ClojureScript map factory with shape validation using prost and cljs.spec
Clojure
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
src/strukt Update README Apr 13, 2017
test/strukt
.gitignore
CHANGELOG.md Update to ClojureScript 1.9.542 + prost v1.1.0 May 22, 2017
LICENSE Port defstruct from trngl -> defstrukt Apr 10, 2017
README.md Update README.md May 22, 2017
boot.properties
build.boot Update to ClojureScript 1.9.542 + prost v1.1.0 May 22, 2017
circle.yml Port defstruct from trngl -> defstrukt Apr 10, 2017

README.md

strukt

ClojureScript map factory with shape validation using prost and cljs.spec

CircleCI

[adamrenklint/strukt "1.1.0"] ;; latest release

Usage

(ns strukt.example
  (:require [strukt.core :refer-macros [defstrukt] :refer [valid? valid!]]))

; Create a spec to validate the shape
(s/def ::color keyword?)
(s/def ::size (s/and number? pos?))
(s/def ::hat (s/keys :req-un [::color ::radius]))

; Define the strukt factory
(defstrukt hat ::hat ::size {:color :red :size 5})

; Create a strukt with valid values
(hat) ; => {:type :hat :size 5 :color :red}

; The factory function takes many different forms of arguments to create a new strukt map
(hat 12) ; => {:type :hat :size 12 :color :red}
(hat :color :blue) ; => {:type :hat :size 5 :color :blue}
(hat {:color :blue}) ; => {:type :hat :size 5 :color :blue}

; Try creating a strukt with invalid values
(hat :size :big) ; => invalid shape 'hat :size', expected :big to be number? via :strukt.example/hat > :strukt.example/size

; A strukt is just a map with its name and spec attached as meta data
(def my-hat (hat))
(-> my-hat meta :name) ; => "hat"
(-> my-hat meta :spec) ; => ::hat

; Having the spec attached means that we can easily call validation methods, without having to pass the spec all the time
(valid? my-hat) ; => true
(valid? (assoc my-hat :size :big)) ; => false
(valid! my-hat) ; => {:type :hat :size 5 :color :red}
(valid! (assoc my-hat :size :big)) ; => invalid shape 'hat :size', expected :big to be number? via :strukt.example/hat > :strukt.example/size

API

Macros

defstrukt [name spec primary-key defaults] => defn => m

defstrukt [name type spec primary-key defaults] => defn => m

Define a strukt map factory as fn name in current namespace. type is optionally a keyword, or the name will be keywordized and used. spec is a keyword pointing to a spec definiton in the spec registry. primary-key is a keyword that represents the main field on the strukt, and will be used for the shorthand primary-key value factory. defaults is a map of default values.

strukt* [name type spec primary-key defaults] => fn => m

Create a strukt map factory with name. type is a keyword and will be used to identify the type of strukt. spec is a keyword pointing to a spec definiton in the spec registry. primary-key is a keyword that represents the main field on the strukt, and will be used for the shorthand primary-key value factory. defaults is a map of default values.

Returns a strukt map factory fn that can be called with no arguments, a single value to associated with primary-key, a map of keys and values, or variadic keyword arguments.

Functions

valid? [m] => bool

Check if map m conforms to its spec, which is attached as meta data. Returns true or false.

valid! [m] => m | nil

Check if map m conforms to its spec, which is attached as meta data. Returns the map if true, and throws an error if false.

->strukt [name spec m] => m

Attach name and spec to map strukt m as meta data.

Develop

  • boot test - run tests
  • boot watch-test - watch and run tests
  • boot fmt - format source with cljfmt
  • boot release - build and push release to Clojars

License

Copyright (c) 2017 Adam Renklint

Distributed under the MIT license