;; project.clj or build.boot
[modelizer "RELEASE"]
;; deps.edn
{:deps {modelizer {:mvn/version "RELEASE"}}}
Warning: This library in designing and prototyping phase
A Clojure (Script) library for describing data and metadata that helps ensure data quality and governance.
The main goals:
simple
fast
extensible
serializable
Add the following dependency in your project:
;; project.clj or build.boot
[modelizer "RELEASE"]
;; deps.edn
{:deps {modelizer {:mvn/version "RELEASE"}}}
You can see a full example here.
(ns your.app
(:require
[modelizer.core :as m]
[modelizer.generator :as gen]))
;;;;
;; Registry
;;;;
;; Available functions for working with registry:
;; - (m/get-schemas)
;; - (m/get-schemas name)
;; - (m/get-schema name)
;; - (m/get-schema name version)
;; - (m/register schema)
;; - (m/register-generator validator generator)
;; - (m/defschema [schema])
;; - (m/defschema [name form])
;; - (m/defschema [name doc form])
;; - (m/defschema [name doc meta form])
;; - (m/defschema [name version doc meta form])
;; - (m/defschema [name version status doc meta form])
;; Create schema
(m/defschema :example
[:or :string? [:and :pos-int? [:not :zero?]]])
;; => #modelizer/schema{:name :example
;; :form [:or :string? [:and :pos-int? [:not :zero?]]]
;; :version :schema.version/not-specified
;; :status :schema.status/not-specified
;; :validator #object[...]
;; :generator #clojure.test.check.generators.Generator[...]}
;; Create schema with a docstring
(m/defschema :example
"Example schema"
[:or :string? [:and :pos-int? [:not :zero?]]])
;; => #modelizer/schema{:name :example
;; :form [:or :string? [:and :pos-int? [:not :zero?]]]
;; :doc "Example schema"
;; :version :schema.version/not-specified
;; :status :schema.status/not-specified
;; :validator #object[...]
;; :generator #clojure.test.check.generators.Generator[...]}
;; Create schema with a metadata
(m/defschema :example
"Example schema"
{:added "0.0.2"}
[:or :string? [:and :pos-int? [:not :zero?]]])
;; => #modelizer/schema{:name :example
;; :meta {:added "0.0.2"}
;; :form [:or :string? [:and :pos-int? [:not :zero?]]]
;; :doc "Example schema"
;; :version :schema.version/not-specified
;; :status :schema.status/not-specified
;; :validator #object[...]
;; :generator #clojure.test.check.generators.Generator[...]}
;; Create schema with a specified version
(m/defschema :example "v1"
"Example schema"
{:added "0.0.2"}
[:or :string? [:and :pos-int? [:not :zero?]]])
;; => #modelizer/schema{:name :example
;; :meta {:added "0.0.2"}
;; :form [:or :string? [:and :pos-int? [:not :zero?]]]
;; :doc "Example schema"
;; :version "v1"
;; :status :schema.status/not-specified
;; :validator #object[...]
;; :generator #clojure.test.check.generators.Generator[...]}
;; Create schema with a specified status
(m/defschema :example "v2" :production
"Example schema"
{:added "0.0.2"}
[:or :string? [:and :pos-int? [:not :zero?]]])
;; => #modelizer/schema{:name :example
;; :meta {:added "0.0.2"}
;; :form [:or :string? [:and :pos-int? [:not :zero?]]]
;; :doc "Example schema"
;; :version "v2"
;; :status :production
;; :validator #object[...]
;; :generator #clojure.test.check.generators.Generator[...]}
;; Create schema from a map
(m/defschema
{:name :example
:doc "Example schema"
:version "v3"
:status :production
:meta {:added "0.0.2"}
:form [:or :string? [:and :pos-int? [:not :zero?]]]})
;; => #modelizer/schema{:name :example
;; :meta {:added "0.0.2"}
;; :form [:or :string? [:and :pos-int? [:not :zero?]]]
;; :doc "Example schema"
;; :version "v3"
;; :status :production
;; :validator #object[...]
;; :generator #clojure.test.check.generators.Generator[...]}
;; If necessary, use the function instead of the macro
(m/register
{:name :example
:doc "Example schema"
:version "v4"
:status :production
:meta {:added "0.0.2"}
:form [:or :string? [:and :pos-int? [:not :zero?]]]})
;; => #modelizer/schema{:name :example
;; :meta {:added "0.0.2"}
;; :form [:or :string? [:and :pos-int? [:not :zero?]]]
;; :doc "Example schema"
;; :version "v4"
;; :status :production
;; :validator #object[...]
;; :generator #clojure.test.check.generators.Generator[...]}
;; Get all registered schemas
(m/get-schemas)
;; => {...}
;; Get all schema versions
(m/get-schemas :example)
;; => {"v4" #modelizer/schema{...}
;; ...
;; "v1" #modelizer/schema{:name :example
;; :doc "Example schema"
;; :version "v1"
;; :status :production
;; :meta {:added "0.0.2"}
;; :form [:or :string? [:and :pos-int? [:not :zero?]]]
;; :validator #object[...]
;; :generator #clojure.test.check.generators.Generator[...]}
;;
;; :schema.version/not-specified #modelizer/schema{:meta {:added "0.0.2"}
;; :name :example
;; :form [:or :string? [:and :pos-int? [:not :zero?]]]
;; :doc "Example schema"
;; :version :schema.version/not-specified
;; :status :schema.status/not-specified
;; :validator #object[...]
;; :generator #clojure.test.check.generators.Generator[...]}}
;; Get schema default version
;; NOTE: You will soon be able to specify a strategy to get the required schema version
(m/get-schema :example)
;; => #modelizer/schema{:meta {:added "0.0.2"}
;; :name :example
;; :form [:or :string? [:and :pos-int? [:not :zero?]]]
;; :doc "Example schema"
;; :version :schema.version/not-specified
;; :status :schema.status/not-specified
;; :validator #object[...]
;; :generator #clojure.test.check.generators.Generator[...]}
;; Get specified schema version
(m/get-schema :example "v4")
;; => #modelizer/schema{:name :example
;; :doc "Example schema"
;; :version "v4"
;; :status :production
;; :meta {:added "0.0.2"}
;; :form [:or :string? [:and :pos-int? [:not :zero?]]]
;; :validator #object[...]
;; :generator #clojure.test.check.generators.Generator[...]}
;;;;
;; Schema
;;;;
;; Available functions for working with schemas:
;; - (m/get-name schema)
;; - (m/get-version schema)
;; - (m/get-status schema)
;; - (m/get-doc schema)
;; - (m/get-meta schema)
;; - (m/get-form schema)
;; - (m/unwrap schema)
;; - (m/get-validator schema)
;; - (m/validate schema data)
;; - (m/validate schema data meta)
;; - (m/get-generator schema)
;; - (m/generate schema)
;; - (m/generate schema opts)
;; - (m/sample schema)
;; - (m/sample schema opts)
;;;;
;; Schema validators
;;;;
;; Save schema into variable
(def example1 (m/get-schema :example "v4"))
(m/validate example1 "1") ;; => true
(m/validate example1 1) ;; => true
(m/validate example1 -1) ;; => false
(m/validate example1 0) ;; => false
;; Save schema validator into variable
(def valid1? (m/get-validator example1))
(valid1? "1") ;; => true
(valid1? 1) ;; => true
(valid1? -1) ;; => false
(valid1? 0) ;; => false
;; Use aliases and versions
(m/defschema :example "v5" :production
"Example schema"
{:added "0.0.2"
:require {:my-example [:example "v4"]}}
:my-example)
;; => #modelizer/schema{:meta {:added "0.0.2"
;; :require {:my-example [:example "v4"]}}
;; :name :example
;; :status :production
;; :form :my-example
;; :version "v5"
;; :doc "Example schema"
;; :validator #object[...]
;; :generator #clojure.test.check.generators.Generator[...]}
(def example2 (m/get-schema :example "v5"))
(m/validate example2 "1") ;; => true
(m/validate example2 1) ;; => true
(m/validate example2 -1) ;; => false
(m/validate example2 0) ;; => false
(def valid2? (m/get-validator example2))
(valid2? "1") ;; => true
(valid2? 1) ;; => true
(valid2? -1) ;; => false
(valid2? 0) ;; => false
;;;;
;; Schema generators
;;;;
;; simple
(m/defschema :example "v6"
"Example schema"
{}
:string?)
(def example3 (m/get-schema :example "v6"))
(m/generate example3) ;; => "W"
(m/generate example3 {:size 10}) ;; => "MIt"
(m/sample example3) ;; => ("" "g" "HK" "5" "y" "Q" "48L3" "wAk5Fz9" "W1l" "")
(m/sample example3 {:size 5}) ;; => ("" "9" "lE" "979" "UOi5")
;; or
(m/defschema :example "v7"
"Example schema"
{}
[:or :string? :pos-int?])
(def example4 (m/get-schema :example "v7"))
(m/generate example4) ;; => 2
(m/generate example4 {:size 10}) ;; => "hjE5W"
(m/sample example4) ;; => (1 1 2 2 3 3 4 "7PuTp" 1 "66Gb")
(m/sample example4 {:size 5}) ;; => (1 2 1 "16" "Av")
;; and
(m/defschema :example "v8"
"Example schema"
{}
[:and :pos-int? :even?])
(def example5 (m/get-schema :example "v8"))
(m/generate example5) ;; => 6
(m/generate example5 {:size 10}) ;; => 240
(m/sample example5) ;; => (4 2 2 52 2 10 58 4 14 8)
(m/sample example5 {:size 5}) ;; => (2 4 2 64 8)
;; not
(m/defschema :example "v8"
"Example schema"
{}
[:not :string?])
(def example6 (m/get-schema :example "v8"))
(m/generate example6) ;; => (:*D/w)
(m/generate example6 {:size 10}) ;; => (0.5 (\a 0.2568359375))
(m/sample example6) ;; => ({} [false] nil nil nil [] nil nil nil nil)
(m/sample example6 {:size 5}) ;; => (() nil nil #{false} [zS8/o8])
;; Use aliases and versions
(m/defschema :example "v9"
"Example schema"
{:require {:pos-int [:pos-int?]}}
[:and :pos-int [:not :even?]])
(def example7 (m/get-schema :example "v9"))
(m/generate example7) ;; => 9
(m/generate example7 {:size 10}) ;; => 20453
(m/sample example7) ;; => (5 31 7 5 1 7 1 1 5 243)
(m/sample example7 {:size 5}) ;; => (5 23 1 3 15)
;;;;
;; Example with a custom validator and generator
;;;
;; Create a custom validator
(defn custom-validator
;; Default validator
([x]
(custom-validator x false))
;; 2-arity validator uses for specified cases when the result depends on external metadata.
;; E.g. you can add strict mode or whatever you want
([x randomize?]
(if-not randomize?
(uuid? x)
(rand-nth [false true]))))
;; Create a custom generator
(def custom-generator gen/gen-uuid?)
;; Create a schema with a specified generator (explicitly)
(m/defschema :custom "v1"
"Example schema"
{:generator custom-generator}
#'custom-validator)
(def custom-example1 (m/get-schema :custom "v1"))
(m/validate custom-example1 (m/generate custom-example1)) ;; => true
(m/validate custom-example1 (m/generate custom-example1) true) ;; => random result true/false
;; Register global validator and generator
(m/register-generator custom-validator custom-generator)
;; Create a schema without a specified generator (implicitly)
(m/defschema :custom "v2"
"Example schema"
{}
#'custom-validator)
(def custom-example2 (m/get-schema :custom "v2"))
(m/validate custom-example2 (m/generate custom-example2)) ;; => true
(m/validate custom-example2 (m/generate custom-example2) true) ;; => random result true/false
;; enum
(m/defschema :example "v10"
"Example schema"
{}
[:enum "Steve Jobs" "Bill Gates"])
(def example8 (m/get-schema :example "v10"))
(m/generate example8) ;; => => "Steve Jobs"
(m/sample example8 {:size 2}) ;; => ("Steve Jobs" "Bill Gates")
(m/validate example8 "Steve Jobs") ;; => true
(m/validate example8 "Elon Musk") ;; => false
TBD
# Run REPL & connect from your IDE
$ make repl
# Run all tests
$ make test
# Run Clojure tests
$ make test-clj
# Run ClojureScript tests
$ make test-cljs
# create a new git tag
# available types `patch`, `minor`, `major`, `minor-rc`, `major-rc`, `minor-release`, `major-release`
$ make patch
# push a new git tag
$ make release
$ make help
help Show help
clean Clean
repl Run REPL
lint Run linter
test-cljs Run ClojureScript tests
test-clj Run Clojure tests
test Run tests
jar Build jar
install Install locally
deploy Deploy to repository
init Init first version
patch Increment patch version
minor Increment minor version
major Increment major version
minor-rc Increment minor-rc version
major-rc Increment major-rc version
minor-release Increment minor-release version
major-release Increment major-release version
release Release a new version
This library inspired by the following excellent libraries:
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close