Validation
Wagoe uses Malli for validation. Schemas live in schema.clj at the root of each module.
Validation always happens in the shell, never in core.
Defining schemas
;; schema.clj
(def UserInput
[:map
[:email [:string {:min 1 :max 255}]]
[:password [:string {:min 8 :max 128}]]
[:name {:optional true} :string]])
(def User
[:map
[:id :uuid]
[:email :string]
[:name {:optional true} :string]
[:created-at inst?]
[:updated-at inst?]])
Validating in the shell
(require '[wagoe.core.validation :as validation]
'[malli.transform :as mt])
(defn create-user [this input]
;; The decoder and the validator are cached on the schema, so this compiles
;; once per schema rather than once per call.
(let [data ((validation/decoder UserInput mt/string-transformer) input)]
(if (validation/valid? UserInput data)
(do-create (:db this) data)
(throw (ex-info "Validation failed"
{:type :validation-error
:errors (validation/explain UserInput data)})))))
CLI argument validation
(require '[wagoe.core.validation :as v]
'[malli.transform :as mt])
(def CLIArgs
[:map
[:module-name [:string {:min 1}]]
[:entity [:string {:min 1}]]])
(let [parsed ((v/decoder CLIArgs mt/string-transformer) args)]
(when-not (v/valid? CLIArgs parsed)
(v/explain CLIArgs parsed)))
Validation coverage reporting
(require '[wagoe.core.validation.coverage :as coverage])
;; Report which fields are validated vs. unvalidated
(coverage/report UserInput)
Snapshot testing for validation
For complex schemas, lock in the expected error messages:
# Run snapshot tests
clojure -M:test --focus user-validation-snapshot-test
# Update snapshots when messages change intentionally
UPDATE_SNAPSHOTS=true clojure -M:test --focus user-validation-snapshot-test
Common schema types
| Type | Usage |
|---|---|
|
|
|
|
|
|
|
|
|
|
Optional field |
|
Nullable field |
|
Enum |
|
See core library for the full validation framework reference.