Validation
Boundary 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 '[boundary.core.utils.validation :as validation])
(defn create-user [this input]
(let [{:keys [valid? data errors]}
(validation/validate-with-transform UserInput input mt/string-transformer)]
(if valid?
(do-create (:db this) data)
(throw (ex-info "Validation failed"
{:type :validation-error :errors errors})))))
CLI argument validation
(require '[boundary.core.utils.validation :as v])
(def CLIArgs
[:map
[:module-name [:string {:min 1}]]
[:entity [:string {:min 1}]]])
(v/validate-cli-args CLIArgs args cli-transformer)
Validation coverage reporting
(require '[boundary.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:db/h2 --focus user-validation-snapshot-test
# Update snapshots when messages change intentionally
UPDATE_SNAPSHOTS=true clojure -M:test:db/h2 --focus user-validation-snapshot-test
Common schema types
| Type | Usage |
|---|---|
|
|
|
|
|
|
|
|
|
|
Optional field |
|
Nullable field |
|
Enum |
|
See core library for the full validation framework reference.