diff --git a/resources/clj-kondo/clj-kondo.exports/metosin/malli/config.edn b/resources/clj-kondo/clj-kondo.exports/metosin/malli/config.edn index 0f8b25ccf..d322f5243 100644 --- a/resources/clj-kondo/clj-kondo.exports/metosin/malli/config.edn +++ b/resources/clj-kondo/clj-kondo.exports/metosin/malli/config.edn @@ -1,2 +1,3 @@ -{:lint-as {malli.experimental/defn schema.core/defn} +{:lint-as {malli.experimental/defn schema.core/defn + malli.experimental/def schema.core/def} :linters {:unresolved-symbol {:exclude [(malli.core/=>)]}}} diff --git a/src/demo.clj b/src/demo.clj new file mode 100644 index 000000000..618242b15 --- /dev/null +++ b/src/demo.clj @@ -0,0 +1,26 @@ +(ns demo + (:require [malli.experimental :as mx] + [malli.provider :as mp])) + +;; pull schema from example +(def Config + (mp/provide + [{:port 8080 + :host "127.0.0.1" + :db {:adapter "postgresql" + :username "example" + :password "example" + :server-name "localhost" + :port-number 5432 + :database-name "example"}}])) + +;; fail fast +(mx/def config :- Config + {:port "8080" + :host "127.0.0.1" + :db {:adapter "postgresql" + :username "example" + :password "example" + :server-name "localhost" + :port-number "5432" + :database-name :example}}) diff --git a/src/malli/experimental.cljc b/src/malli/experimental.cljc index dbf7f137c..5727eefb9 100644 --- a/src/malli/experimental.cljc +++ b/src/malli/experimental.cljc @@ -3,9 +3,10 @@ #?(:cljs (:require-macros malli.experimental)) (:require [clojure.core :as c] [malli.core :as m] - [malli.destructure :as md])) + [malli.destructure :as md] + [malli.dev.pretty :as pretty])) -(c/defn -schema [inline-schemas] +(c/defn -defn-schema [inline-schemas] (m/schema [:schema {:registry {"Schema" any? @@ -32,8 +33,28 @@ [:meta [:? :map]]]]]]]}} "Params"])) -(def SchematizedParams (-schema true)) -(def Params (-schema false)) +(c/defn -def-schema [inline-schemas] + (m/schema + [:schema + {:registry {"Schema" any? + "Separator" (if inline-schemas [:= :-] md/Never) + "Params" [:catn + [:name symbol?] + [:return [:? [:catn + [:- "Separator"] + [:schema "Schema"]]]] + [:doc [:? string?]] + [:body any?]]}} + "Params"])) + +(def SchematizedDefnParams (-defn-schema true)) +(def DefnParams (-defn-schema false)) + +(def ^:depecated SchematizedParams SchematizedDefnParams) +(def ^:depecated Params DefnParams) + +(def SchematizedDefParams (-def-schema true)) +(def DefParams (-def-schema false)) (c/defn -defn [schema args] (let [{:keys [name return doc arities] body-meta :meta :as parsed} (m/parse schema args) @@ -64,8 +85,20 @@ (m/=> ~name ~schema) defn#))) +(c/defn -def [schema args] + (let [{:keys [name doc body] {:keys [schema]} :return :as parsed} (m/parse schema args)] + (when (= ::m/invalid parsed) (m/-fail! ::parse-error {:schema schema, :args args})) + `(let [def# (def + ~(with-meta name {:schema schema}) + ~@(some-> doc vector))] + (when (and ~schema (not (m/validate ~schema ~body))) + (pretty/explain ~schema ~body) + (m/-fail! ::invalid-data {:def ~name, :schema ~schema, :body ~body})) + def#))) + ;; ;; public api ;; -#?(:clj (defmacro defn [& args] (-defn SchematizedParams args))) +#?(:clj (defmacro defn [& args] (-defn SchematizedDefnParams args))) +#?(:clj (defmacro def [& args] (-def SchematizedDefParams args)))