Liking cljdoc? Tell your friends :D

license codecov build deploy clojars cljdoc

Warning: This library in designing and prototyping phase

Modelizer

A Clojure (Script) library for describing data and metadata that helps ensure data quality and governance.

The main goals:

  • simple

  • fast

  • extensible

  • serializable

Quick Start Guide

Add the following dependency in your project:

;; project.clj or build.boot
[modelizer "RELEASE"]

;; deps.edn
{:deps {modelizer {:mvn/version "RELEASE"}}}

Example

You can see a full example here.

(ns your.app
  (:require
    [modelizer.core :as m]))

;; 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[clojure.core$some_fn$sp2__8653 0x4811bfa1 "clojure.core$some_fn$sp2__8653@4811bfa1"]}


;; Add 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[clojure.core$some_fn$sp2__8653 0x4811bfa1 "clojure.core$some_fn$sp2__8653@4811bfa1"]}


;; Add additional 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[clojure.core$some_fn$sp2__8653 0x4811bfa1 "clojure.core$some_fn$sp2__8653@4811bfa1"]}


;; Specify schema 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[clojure.core$some_fn$sp2__8653 0x4811bfa1 "clojure.core$some_fn$sp2__8653@4811bfa1"]}


;; Specify schema status

(m/defschema :example "v1" :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   "v1"
;;                      :status    :production
;;                      :validator #object[clojure.core$some_fn$sp2__8653 0x4811bfa1 "clojure.core$some_fn$sp2__8653@4811bfa1"]}


;; Create schema from map

(m/defschema
  {:name    :example
   :doc     "Example schema"
   :version "v1"
   :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   "v1"
;;                      :status    :production
;;                      :validator #object[clojure.core$some_fn$sp2__8653 0x4811bfa1 "clojure.core$some_fn$sp2__8653@4811bfa1"]}


;; If necessary, use the function instead of the macro

(m/register
  {:name    :example
   :doc     "Example schema"
   :version "v1"
   :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   "v1"
;;                      :status    :production
;;                      :validator #object[clojure.core$some_fn$sp2__8653 0x4811bfa1 "clojure.core$some_fn$sp2__8653@4811bfa1"]}


;; Get all registered schemas

(m/get-schemas)
;; => {...}


;; Get all schema versions

(m/get-schemas :example)
;; => {"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[clojure.core$some_fn$sp2__8653 0x3977eef9 "clojure.core$some_fn$sp2__8653@3977eef9"]}
;;
;;     :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[clojure.core$some_fn$sp2__8653 0x31188dcb "clojure.core$some_fn$sp2__8653@31188dcb"]}}


;; 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[clojure.core$some_fn$sp2__8653 0x31188dcb "clojure.core$some_fn$sp2__8653@31188dcb"]}


;; Get specified schema version

(m/get-schema :example "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[clojure.core$some_fn$sp2__8653 0x3977eef9 "clojure.core$some_fn$sp2__8653@3977eef9"]}


;; Save schema into variable

(def example (m/get-schema :example "v1"))

;; Available functions for working with schemas:
;; - (m/get-name example)
;; - (m/get-version example)
;; - (m/get-status example)
;; - (m/get-doc example)
;; - (m/get-meta example)
;; - (m/get-form example)
;; - (m/unwrap example)
;; - (m/get-validator example)
;; - (m/validate example your-data)


;; Save schema validator into variable

(def valid? (m/get-validator example))

(valid? "1")
;;=> true

(valid? 1)
;;=> true

(valid? -1)
;;=> false

(valid? 0)
;;=> false



;; Use aliases and versions

(m/defschema ::example "v2" :production
  "Example schema"
  {:added   "0.0.2"
   :require {:my-example [:example "v1"]}} ;; API in design
  :my-example)
;; => #modelizer/schema{:meta      {:added   "0.0.2"
;;                                  :require {:my-example [:example "v1"]}}
;;                      :name      :your.app/example
;;                      :status    :production
;;                      :form      :my-example
;;                      :version   "v2"
;;                      :doc       "Example schema"
;;                      :validator #object[clojure.core$some_fn$sp2__8653 0x1373f57d "clojure.core$some_fn$sp2__8653@1373f57d"]}

(def valid2? (m/get-validator (m/get-schema ::example "v2")))

(valid2? "1")
;;=> true

(valid2? 1)
;;=> true

(valid2? -1)
;;=> false

(valid2? 0)
;;=> false


;;;;
;; Example with a custom validator
;;;;

;; Create a custom validator function

(defn custom-validator
  "Custom validator fn"
  {:added "2020-04-01"}
  [x]
  (string? x))


;; Create schema from a custom validator function

(m/defschema #'custom-validator)
;; => #modelizer/schema{:name      :custom-validator
;;                      :version   :schema.version/not-specified
;;                      :status    :schema.status/not-specified
;;                      :meta      {:ns your.app :added "2020-04-01"}
;;                      :form      #'your.app/custom-validator
;;                      :validator #object[modelizer.core$fn__GT_validator$fn__3809 0x2972a80a "modelizer.core$fn__GT_validator$fn__3809@2972a80a"]
;;                      :doc       "Custom validator fn"}


;; Add another schema

(m/defschema :custom :custom-validator)


;; Use aliases

(def custom-example
  (m/defschema ::example "v1"
    "Example schema"
    {:require {:string  [:custom]
               :pos-int [:pos-int?]}}
    [:or :string [:and :pos-int [:not :zero?]]]))


;; Use a custom validator function

(def valid3? (m/get-validator custom-example))

(valid3? "1") ;; or (m/validate custom-example "1")
;;=> true

(valid3? 1) ;; or (m/validate custom-example 1)
;;=> true

(valid3? -1) ;; or (m/validate custom-example -1)
;;=> false

(valid3? 0) ;; or (m/validate custom-example 0)
;;=> false

Roadmap

TBD

Development

# Run REPL & connect from your IDE
$ make repl

Testing

# Run all tests
$ make test

# Run Clojure tests
$ make test-clj

# Run ClojureScript tests
$ make test-cljs

Deploy

# 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

Available commands

$ 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 is 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