Skip to content

Instantly share code, notes, and snippets.

@dustingetz dustingetz/ Secret
Last active Jun 2, 2020

What would you like to do?

Hyperfiddle DSL, 2020 April iteration

This DSL generates client/server UI for Datomic entities. The UI is transactional, secure, reactive, includes data sync, etc.


(ns user.hello-world
    [hyperfiddle.api :as hf]))

(def submissions-master
  '[{`submissions [(:dustingetz/email
                     ; Three hypermedia controls on ::email (which is :db.unique/identity)
                     {:hf/a `submissions-detail}            ; hyperlink
                     {:hf/tx `remove}                       ; transaction

                     {:hf/class :hf/new                     ; classes are semantic, this allocates a tempid
                      :hf/prompt `submissions-detail})      ; prompt for more edits as part of the transaction

                   {:dustingetz/gender [:db/ident
                                        #_`f                ; Hyperfiddle can "pull" through functions, as if keywords
                                        {`shirt-sizes [:db/ident]}]}
                   {:dustingetz/shirt-size [:db/ident]}]}

(defn remove [ctx [e a v] props]
  [[:db/retractEntity v]])

(defn submissions [$ & args]
  (q '[:find [?e ...]                                       ; they must return FindColl for now
       :where [?e :dustingetz/email]] $))

(defn genders [$ & args]
  (q '[:find [(pull ?e [:db/ident]) ...]
       :where [?e :dustingetz/type :dustingetz/gender]]

(defn shirt-sizes [$ & [gender]]
  (q '[:in $ ?gender
       :find [?e ...]
       [?e :dustingetz/type :dustingetz/shirt-size]
       [?e :dustingetz/gender ?gender]]
    $ gender))

(def submissions-detail
   {:dustingetz/gender [:db/ident
                        {`shirt-sizes [:db/ident]}]}
   {:dustingetz/shirt-size [:db/ident]}

(def config {:domain {:databases {"$" {:database/uri #uri "datomic:mem://app-db"}}}})
(def config (hf/get-config config))
(def domain (hf/get-domain config))
(def conn (hf/connect domain "$"))
(def $ (-> (hf/db conn)
         (hf/with [{:db/ident :dustingetz/email :db/valueType :db.type/string :db/cardinality :db.cardinality/one  :db/unique :db.unique/identity}
                   {:db/ident :dustingetz/gender :db/valueType :db.type/ref :db/cardinality :db.cardinality/one}
                   {:db/ident :dustingetz/shirt-size :db/valueType :db.type/ref :db/cardinality :db.cardinality/one}
                   {:db/ident :dustingetz/type :db/valueType :db.type/keyword :db/cardinality :db.cardinality/one}])
         (hf/with [{:dustingetz/type :dustingetz/gender :db/ident :dustingetz/male}
                   {:dustingetz/type :dustingetz/gender :db/ident :dustingetz/female}])
         (hf/with [{:dustingetz/type :dustingetz/shirt-size :db/ident :dustingetz/mens-small :dustingetz/gender :dustingetz/male}
                   {:dustingetz/type :dustingetz/shirt-size :db/ident :dustingetz/mens-medium :dustingetz/gender :dustingetz/male}
                   {:dustingetz/type :dustingetz/shirt-size :db/ident :dustingetz/mens-large :dustingetz/gender :dustingetz/male}
                   {:dustingetz/type :dustingetz/shirt-size :db/ident :dustingetz/womens-small :dustingetz/gender :dustingetz/female}
                   {:dustingetz/type :dustingetz/shirt-size :db/ident :dustingetz/womens-medium :dustingetz/gender :dustingetz/female}
                   {:dustingetz/type :dustingetz/shirt-size :db/ident :dustingetz/womens-large :dustingetz/gender :dustingetz/female}])
         (hf/with [{:dustingetz/email "" :dustingetz/gender :dustingetz/female :dustingetz/shirt-size :dustingetz/womens-large}
                   {:dustingetz/email "" :dustingetz/gender :dustingetz/male :dustingetz/shirt-size :dustingetz/mens-large}
                   {:dustingetz/email "" :dustingetz/gender :dustingetz/male :dustingetz/shirt-size :dustingetz/mens-medium}])))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.