We use Break Versioning. The version numbers follow a <major>.<minor>.<patch> scheme with the following intent:
| Bump | Intent |
|---|---|
major | Major breaking changes -- check the changelog for details. |
minor | Minor breaking changes -- check the changelog for details. |
patch | No breaking changes, ever!! |
-SNAPSHOT versions are preview versions for upcoming releases.
Malli is in well matured alpha.
:definitions nil in swagger. #1134:gen/fmap property requires its schema to create a generator.
nil-returning generator, even if the schema doesn't accept nil:gen/return nil property to restore this behavior[:map schemas in json-transformer #1135:not humanizer #1138:seqable generates nil when :min is greater than 0 #1121malli.registry/{mode,type} not respected in Babashka #1124:float accepts doubles but never generates them #1132:float missing humanizer #1122fipp/fipp '0.6.26' to '0.6.27'
:merge over :multi #1086, see documentation:multi with keyword :dispatch accumulates data to generated values #1095m/-proxy-schema child to be a delay #1090json-transformer decodes 123.0 into 123 for schemas like :int, pos-int? etc. #986malli.dev.pretty throws when explaining errors in nested maps #1094(-some-pred []) should return false #1101mu/assoc and mu/dissoc only handle one key at a time #1099map-of-min-max-test less flaky by fixing seed #1098borkdude/edamame '1.4.25' to '1.4.27'
:-> added to default registry, see documentation.:seqable and :every schemas #1041, see docs(malli.dev/start!) #1083.entryAt with .valAt during validation #1079m/-simple-schema #1077:-> for simpler function defintions (not available on default schema registry) #1027[:-> :any] ; [:=> :cat :any]
[:-> :int :any] ; [:=> [:cat :int] :any]
[:-> [:cat :int] :any] ; [:=> [:cat [:cat :int]] :any]
[:-> a b c d :any] ; [:=> [:cat a b c d] :any]
;; guard property
[:-> {:guard (fn [[[arg] ret]] ...)} :string :boolean]
; [:=> [:cat :string] :boolean [:fn (fn [[[arg] ret]] ...)]]
mu/get-in for false-y keys #1065:float #1055:double generates Long if :min is Long #1034:malli.json-schema/definitions-path #1045:body swagger parameters #1044mu/update-entry-properties #1037:min / :max when different #1032:map-of :min and unreachable generator, explain such-that failures #1029:=> takes optional 3rd child, the guard schema validating vector of arguments and return value [args ret]. See Function Guards for more details. Fixes #764 and #764.;; function of arg:int -> ret:int, where arg < ret
[:=>
[:cat :int]
:int
[:fn (fn [[[arg] ret]] (< arg ret))]]
BREAKING: malli.generator/function-checker returns explanations under new keys:
::mg/explain-input -> ::m/explain-input::mg/explain-output -> ::m/explain-output::m/explain-guard to return guard explanation, if anym/explain for :=> returns also errors for args, return and guard if they exist
FIX m/deref-recursive doesn't play nice with :merge schema #997 via #999
FIX nested :repeat sequence schema's doesn't seem to work #761 via #1024
FIX Invalid Swagger JSON with [:or :nil] alternatives #1006 via #1023
FIX (explain :tuple []) #1022
Enforce entry specs in open map destructurings #1021
FIX goog/mixin was deprecated and is now removed #1016
Updated dependencies:
borkdude/edamame 1.3.23 -> 1.4.25
m/deref-recursive to recursive deref all schemas (not :refs)m/coerce and m/coercer throw ::m/coercion instead of ::m/invalid-inputmt/strip-extra-keys-transformer for recursive map encoding #963:type in into-schema opt for :map and :map-of #968mu/path->in works with :orn, :catn and :altn.:or and :orn, #946decode for :double and double? in cljs doesn't allow trailing garbage any more #942:map, #948 & #949:altn can't handle just one child entry when nested in sequence schema #945bound-fn in malli.dev/start! to preserve *out* #954malli.experimental.describe descriptions of :min and :max are backwards #959:catn unparse, fixes #925malli.experimental.timemalli.core/-comp keeps interceptor order with long chains #905malli.dev/start! exception does not contain source #896:gen/return support in malli.generator #933:default/fn prop for default-value-transformer #927borkdude/edamame 1.3.20 -> 1.3.23
mu/from-map-syntax, mu/to-map-syntax. Note that AST syntax and lite syntax remain unchanged.:schema with an id no longer passes [id] instead of children to the walker function #884goog/mixin with Object.assign #890malli.swagger ns, broken test on reitit.(m/validate
[:map
[:x :int]
[:y :int]
[::m/default [:map-of :string :string]]]
{:x 1, :y 2, "kikka" "kukka"})
; => true
mt/strip-extra-keys-transformer works with :map-of.(m/decode
[:map-of :int :int]
{1 1, 2 "2", "3" 3, "4" "4"}
(mt/strip-extra-keys-transformer))
; => {1 1}
mt/strip-extra-keys-transformer strips non-defined keys of implicitely open :map:(m/decode
[:map [:x :int]]
{:x 1, :y 2, :z 3}
(mt/strip-extra-keys-transformer))
; => {:x 1}
m/default-schema to pull the ::m/default schema from entry schemasm/explicit-keys to get a vector of explicit keys from entry schemas (no ::m/default)m/-simple-schema and m/-collection-schema via new 3-arity :compile function of type children properties options -> props. Old 2-arity top-level callback function is m/deprecated! and support for it will be removed in future versions. #866malli.util/assoc-in referencing non-existing maps fail #874borkdude/edamame 1.1.17 -> 1.3.20
Implement malli.experimental.time schemas for clojurescript using js-joda #853
Allow instrumenting external functions #841
Add clj-kondo support for cljs function schemas #833
Turn on instrumentation for mx/defn with :malli/always meta #825
Support type-properties in m/-map-schema, m/-map-of-schema and m/-tuple-schema #856
FIX: properly compose interceptors in :map-of json-transformer #849
FIX: error paths for :multi schemas when value is not a map #845
FIX: Malli generates :nilable/any which is not a valid type in clj-kondo #821
FIX: mi/collect! without args doesn't work properly #834
Updated dependencies:
mvxcvi/mvxcvi 2.0.0 -> 2.1.0
borkdude/edamame 1.0.0 -> 1.1.17
java.time:
:time/duration, :time/instant, :time/local-date, :time/local-date-time, :time/local-time, :time/offset-date-time, :time/offset-time, :time/zone-id, :time/zone-offset, :time/zoned-date-time, see README:enum and := with malli.transform and malli.json-schema - detects homogenous :string, :keyword, :symbol, :int and :double), #782 & #784malli.core/coercer and malli.core/coerce to both decode and validate a value, see Docsmalli.core/-no-op-transformer:map-of inferring via malli.provider/provide:
:malli.provider/map-of-threshold default dropped (was 3)malli.provider/map-of-accept) function of stats -> boolean for identifying :map-of:int over 'int?):pred option to m/-map-schema #767:some schema (like some?)malli.experimental.describe to describe Schemas in english:* (require '[malli.experimental.describe :as med])
(med/describe [:map {:closed true} [:x int?]])
; => "map where {:x -> <integer>} with no other keys"
:min/:max #759malli.dev.pretty/explain #738::m/extra-key error retains the error valuemalli.error/error-value utility for compact error value presentation.me/-push takes extra argumentme/-assoc-in is now called me/-push-inborkdude/dynaload 0.3.4 -> 0.3.5
borkdude/dynaload 0.2.2 -> 0.3.4
malli.dev.pretty/prettier helper, [#672]mall.util/explain-data, malli.util/data-explainer and malli.util/keys #707malli.transform/default-value-transformer accepts mt/add-optional-keys option:(m/decode
[:map
[:name [:string {:default "kikka"}]]
[:description {:optional true} [:string {:default "kikka"}]]]
{}
(mt/default-value-transformer {::mt/add-optional-keys true}))
; => {:name "kikka", :description "kikka"}
fipp/fipp 0.2.5 -> 0.2.6
borkdude/edamame 0.0.18 -> 1.0.0
default-fn option in mt/default-value-transformer #582 & #644malli.experimental.lite, see the docs.(require '[malli.experimental.lite :as l])
{:id string?
:tags [:set keyword?]
:address {:street string?
:city string?
:zip (l/optional int?)
:lonlat [:tuple double? double?]}}
borkdude/edamame 0.0.18 -> 0.0.19
new malli.instrument.cljs and malli.dev.cljs namespaces for instrumentationa and dev-tooling for ClojureScript
malli.dev/start! uses malli.dev.pretty/reporter by default
allow :malli/schema to be defined via arglist meta-data, #615
BREAKING: local registries with schemas in vector syntax are stored as identity, not as form
BREAKING: :malli.provider/tuple-threshold has no default value
FIX: me/-resolve-root-error does not respect :error/path, #554
FIX: m/from-ast does not work with symbols or unamespaced keywords, #626
FIX: :+ parsing returns vector, not sequence
new malli.destructure ns for parsing Clojure & Plumatic destructuring binding syntaxes, see Destructuring.
(require '[malli.destructure :as md])
(-> '[a b & cs] (md/parse) :schema)
; => [:cat :any :any [:* :any]]
(-> '[a :- :string, b & cs :- [:* :int]] (md/parse) :schema)
; => [:cat :string :any [:* :int]]
malli.experimental namespace with schematized defn, automatically registers the functions schemas with m/=>.(require '[malli.experimental :as mx])
(mx/defn kakka :- :int
"inline schemas (plumatic-style)"
[x :- :int] (inc x))
:decode and :encode keys:(m/decode
[:string {:decode {:string (partial str "olipa "}}]
"kerran" mt/string-transformer)
; => "olipa kerran"
malli.dev.pretty/explain for pretty-printing explanations
fipp/fipp 0.6.24 -> 0.6.25
.clj-kondo/metosin/malli-types/config.edn)mvxcvi/arrangement 1.2.0 -> 2.0.0
borkdude/edamame 0.0.11 -> 0.0.18
org.clojure/test.check 1.1.0 -> 1.1.1
(mp/provide
[{:id "caa71a26-5fe1-11ec-bf63-0242ac130002"}
{:id "8aadbf5e-5fe3-11ec-bf63-0242ac130002"}]
{::mp/value-decoders {'string? {:uuid mt/-string->uuid}}})
; => [:map [:id :uuid]]
:map-of inferring can be forced with :malli.provider/hint :map-of meta-data:(require '[malli.provider :as mp])
(mp/provide
[^{::mp/hint :map-of}
{:a {:b 1, :c 2}
:b {:b 2, :c 1}
:c {:b 3}
:d nil}])
;[:map-of
; keyword?
; [:maybe [:map
; [:b int?]
; [:c {:optional true} int?]]]]
:tuple inferring (supports type-hints and threshold options)(mp/provide
[[1 "kikka" true]
[2 "kukka" true]
[3 "kakka" true]]
{::mp/tuple-threshold 3})
; [:tuple int? string? boolean?]
decimal? predicate schema was removed in 0.7.0, #590(def ?schema
[:map
[:x boolean?]
[:y {:optional true} int?]
[:z [:map
[:x boolean?]
[:y {:optional true} int?]]]])
(def schema (m/schema ?schema))
;; 44µs -> 2.5µs (18x)
(bench (m/schema ?schema))
;; 44µs -> 240ns (180x, not realized)
(p/bench (m/schema ?schema {::m/lazy-entries true}))
;; 26µs -> 1.2µs (21x)
(bench (m/walk schema (m/schema-walker identity)))
;; 4.2µs -> 0.54µs (7x)
(bench (mu/assoc schema :w :string))
;; 51µs -> 3.4µs (15x)
(bench (mu/closed-schema schema))
;; 5µs -> 28ns (180x)
(p/bench (m/deref-all ref-schema))
;; 134µs -> 9µs (15x)
(p/bench (mu/merge schema schema))
(def schema (m/schema ?schema))
;; 1.6µs -> 64ns (25x)
(p/bench (m/validate schema {:x true, :z {:x true}}))
;; 1.6µs -> 450ns (3x)
(p/bench (m/explain schema {:x true, :z {:x true}}))
(def samples
[{:id "Lillan"
:tags #{:artesan :coffee :hotel}
:address {:street "Ahlmanintie 29"
:city "Tampere"
:zip 33100
:lonlat [61.4858322, 23.7854658]}}
{:id "Huber",
:description "Beefy place"
:tags #{:beef :wine :beer}
:address {:street "Aleksis Kiven katu 13"
:city "Tampere"
:zip 33200
:lonlat [61.4963599 23.7604916]}}])
;; 126ms -> 2.5ms (50x)
(p/bench (mp/provide samples))
;; 380µs (330x)
(let [provide (mp/provider)]
(p/bench (provide samples)))
New optimized map-syntax to super-fast schema creation, see README.
(def ast (m/ast ?schema))
;{:type :map,
; :keys {:x {:order 0, :value {:type boolean?}},
; :y {:order 1, :value {:type int?}
; :properties {:optional true}},
; :z {:order 2,
; :value {:type :map,
; :keys {:x {:order 0
; :value {:type boolean?}},
; :y {:order 1
; :value {:type int?}
; :properties {:optional true}}}}}}}
;; 150ns (16x)
(p/bench (m/from-ast ast))
(-> ?schema
(m/schema)
(m/ast)
(m/from-ast)
(m/form)
(= ?schema))
; => true
Currently in alpha, will fully replace the old map-syntax at some point.
No need to play with Compiler options or JVM properties to swap the default registry (only if you want to get DCE on CLJS with small set of schemas). Can be disabled with new malli.registry/mode=strict option.
(require '[malli.core :as m]
'[malli.util :as mu]
'[malli.registry :as mr]
'[malli.generator :as mg])
;; look ma, just works
(mr/set-default-registry!
(mr/composite-registry
(m/default-schemas)
(mu/schemas)))
(mg/generate
[:merge
[:map [:x :int]]
[:map [:y :int]]])
; => {:x 0, :y 92}
m/explain :errors are plain maps, not Error records.malli.provider/schema is moved into extender API: malli.provider/-schemamalli.provider supports inferring of :maybe and :map-ofnil is a valid default with mt/default-value-transformer #576:schema explain path, #573:enum explain path, #553:function lensesm/function-schemaempty? Schema does not throw exceptionsm/EntrySchema replaces m/MapSchema with new -entry-parser methodm/-parse-entries is removed, use m/-entry-parser insteadm/-create-form supports 2 & 4 arities (was: 3)m/EntryParser protocolm/-entry-forms helperm/walk-leaf, m/-walk-entries & m/-walk-indexed helpersm/Cached protocol and m/-create-cache for memoization of -validator, -explainer, -parser and -unparser when using m/validator, m/explain, m/parser and m/unparser.mvxcvi/arrangement to make pretty printing work:or, :and, :orn and :map, thanks to Ben Sless:;; 164ns -> 28ns
(let [valid? (m/validator [:and [:> 0] [:> 1] [:> 2] [:> 3] [:> 4]])]
(cc/quick-bench (valid? 5)))
;; 150ns -> 30ns
(let [valid? (m/validator [:map [:a :any] [:b :any] [:c :any] [:d :any] [:e :any]])
value {:a 1, :b 2, :c 3, :d 4, :e 5}]
(cc/quick-bench (valid? value)))
(let [decode (m/decoder
[:map
[:id :string]
[:type :keyword]
[:address
[:map
[:street :string]
[:lonlat [:tuple :double :double]]]]]
(mt/json-transformer))
json {:id "pulla"
:type "food"
:address {:street "hämeenkatu 14"
:lonlat [61 23.7644223]}}]
;; 920ns => 160ns
(cc/quick-bench
(decode json)))
BREAKING: malli.json-schema/unlift-keys is removed in favor of malli.core/-unlift-keys
BREAKING: malli.json-schema/unlift is removed in favor of get
BREAKING: malli.provider/stats is removed (was already deprecated)
BREAKING: malli.util/update doesn't the properties of the key it updates, fixes #412
BREAKING: New rules for humanized errors, see #502, fixes #80, #428 and #499.
new malli.instrument and malli.dev for instrumenting function Vars (e.g. defns), see the guide.
new malli.plantuml namespace for PlantUML generation
new malli.generator/check for generative testing of functions and defns.
new malli.core/parent
:map-of supports :min and :max properties
Collection Schemas emit correct JSON Schema min & max declarations
humanized errors for :boolean & :malli.core/tuple-limit
predicate schema for fn?
malli.util/transform-entries passes in options [#340]/(https://github.com/metosin/malli/pull/340)
BETA: humanized errors can be read from parent schemas (also from map entries), fixes #86:
(-> [:map
[:foo {:error/message "entry-failure"} :int]]
(m/explain {:foo "1"})
(me/humanize {:resolve me/-resolve-root-error}))
; => {:foo ["entry-failure"]}
malli.util.impl/-fail! is now malli.core/-fail!malli.core/-unlift-keysmalli.core/-instrumentmalli.core/-register-function-schema! is now 4-arity, new argument is data mapmalli.core/-fail! has only arity 1 & 2 versionsifn? predicate, #416m/-explain with :function and :=> Schemasm/properties-schema and m/children-schema to resolve Malli Schemas for IntoSchemas. Empty implementations.:gen/schema property for declarative generation, e.g. [:string {:gen/schema :int, :gen/fmap str}]-type is moved from Schema to IntoSchema.-type-properties is moved from Schema to IntoSchema.IntoSchema Protocol
(-properties-schema [this options] "maybe returns :map schema describing schema properties")(-children-schema [this options] "maybe returns sequence schema describing schema children"):nil schema, #401:multi returns branch information, #403:and merges using first child, #405:orn json-schema & generator, #400mt/default-value-transformer, #397nil keys in maps, #392:m/default for :multi, #391:double, #382support for sequence schemas: :cat, catn, alt, altn, :?, :*, :+ and repeat, see Sequence Schemas.
support for parsing and unparsing schemas: m/parse, m/parser, m/unparse, m/unparser, see Parsing values.
support for function schmas: :=> and :function, see Function Schemas.
new schemas: :any (e.g. any?), :not (complement) and :orn (or with named branches)
:qualified-keyword support :namespace property
FIX: Schema vizualization is not working for [:< ...] like schemas, #370
Ensure we use size 30 for generator (for more variety), #364
Set JSON Schema types and formats for numbers properly #354
-memoize actually memoized. easily 100x faster now #350
Fix interceptor composition, #347
malli.util: add a rename-keys utility, similar to clojure.set #338
Let mu/update accept plain data schemas, #329
mu/find, #322
m/Schema has new methods: -parent, -parser and -unparserm/-coder and m/-chain are replaced wih m/-interceptingm/-fail! is now miu/-fail!m/-error is now miu/-error:sequential decoding with empty sequence under mt/json-transformer, fixes #288
mt/-sequential->seqm/deref returns original schema, does not throw, fixes #284.malli.util deref top-level refs recursively: merge, union, transform-entries, optional-keys, required-keys, select-keys and dissoc.m/deref-all derefs all top-level references recursively, e.g.(m/deref-all [:schema [:schema int?]])
; => int?
:ref, :schema, ::m/schema have now generators, JSON Schema and Swagger supportmu/subschemas walks over top-level :ref and all :schemas.m/walk can walk over :ref and :schema reference schemas. Walking can be enabled using options :malli.core/walk-refs and :malli.core/walk-schema-refs.There are also declarative versions of schema transforming utilities in malli.util/schemas. These include :merge, :union and :select-keys:
(def registry (merge (m/default-schemas) (mu/schemas)))
(def Merged
(m/schema
[:merge
[:map [:x :string]]
[:map [:y :int]]]
{:registry registry}))
Merged
;[:merge
; [:map [:x :string]]
; [:map [:y :int]]]
(m/deref Merged)
;[:map
; [:x :string]
; [:y :int]]
(m/validate Merged {:x "kikka", :y 6})
; => true
New options for SCI:
:malli.core/disable-sci for explicitly disabling sci, fixes #276:malli.core/sci-options for configuring scimalli.transform/default-value-transformer accepts options :key and :defaults:
(m/decode
[:map
[:user [:map
[:name :string]
[:description {:ui/default "-"} :string]]]]
nil
(mt/default-value-transformer
{:key :ui/default
:defaults {:map (constantly {})
:string (constantly "")}}))
; => {:user {:name "", :description "-"}}
First stable release.
:list schemamalli.error/SchemaError protocol in favor of using m/type-properties for custom errorsm/-predicate-schema, m/-partial-predicate-schema and m/-leaf-schemam/Schema: -type-propertiesm/children returns 3-tuple (key, properties, schema) for MapSchemasm/map-entries is removed, m/entries returns a MapEntry of key & m/-val-schema:path in explain is re-implemented: map keys by value, others by child indexm/-walk and m/Walker uses :path, not :inm/-outer has new parameter order: walker schema path children optionsmalli.util/path-schemas replaced with malli.util/subschemas & malli.util/distict-byLensSchema has a new -key methodmalli.core & malli.utilmalli.core to malli.utilcom.gfredericks/test.chucksci is not a default dependency. Enabling sci-support:
borkdude/scisci.core (directly or via :preloads)malli.transform internals.malli.mermaid is removed (in favor of malli.dot)[metosin/malli "0.0.1-20200710.075225-19"]m/accept -> m/walkm/schema-visitor -> m/schema-walkerm/map-syntax-visitor -> m/map-syntax-walker-children method in Schema, to return child schemas as instances (instead of just AST)malli.core/*-registry defs into malli.core/*-schemas defns to enable DCE for clojurescriptmalli.core/name & malli.core/-name renamed to malli.core/type & malli.core/-typemalli.generator/-generator is renamed to malli.generator/-schema-generatorCan you improve this documentation? These fine people already did:
Tommi Reiman, Joel Kaasinen, Ambrose Bonnaire-Sergeant, Dmitry Dzhus, Miikka Koskinen, James Conroy-Finn & Lucy WangEdit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |