Skip to content

Instantly share code, notes, and snippets.

@olivergeorge
Last active March 29, 2019 12:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save olivergeorge/8368ab3637d0ade128166de78bac7903 to your computer and use it in GitHub Desktop.
Save olivergeorge/8368ab3637d0ade128166de78bac7903 to your computer and use it in GitHub Desktop.
generate simple api pull spec from clojure.spec forms
(ns serverless.pmr-spec
(:require [clojure.spec :as s]))
(s/def ::spec
(s/or ::table (s/cat :s #{`s/keys 's/keys} :pairs (s/* any?))
::many-rel (s/cat :s #{`s/every} :pred any? :opts (s/* any?))
::and (s/cat :s #{`s/and} :pred-forms (s/* any?))
::other any?))
(defn spec-type [spec]
(first (s/conform ::spec (s/form spec))))
(defn spec->pull
"Translate a clojure spec into the pull format"
[acc form]
(let [[k v :as x] (s/conform ::spec form)]
(case k
::table (into acc (for [field-spec (mapcat second (partition 2 (:pairs v)))]
(case (spec-type field-spec)
::other (name field-spec)
::many-rel {(name field-spec)
(spec->pull nil (s/form field-spec))}
::table {(name field-spec)
(spec->pull acc (s/form field-spec))})))
::many-rel (spec->pull acc (:pred v))
::and (reduce spec->pull acc (map s/form (:pred-forms v)))
::other nil)))
(s/def :PROJ_COMPANY/COMPANY_NAME string?)
(s/def :PROJ_CONTACT/NAME string?)
(s/def :PROJ_COMPANY/STAFF (s/coll-of (s/keys :req-un [:PROJ_CONTACT/NAME])))
(s/def :example/company (s/keys :req-un [:PROJ_COMPANY/COMPANY_NAME :PROJ_COMPANY/STAFF]))
(comment
(= (spec->pull nil (s/form :example/company))
[{"STAFF" ["NAME"]} "COMPANY_NAME"]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment