hyperfiddle-2020 icon indicating copy to clipboard operation
hyperfiddle-2020 copied to clipboard

CRUD apps as a function

Project status, 2021 June: closed beta, repo not available, public release eta 2021

Hyperfiddle: CRUD apps as a function

Hyperfiddle is a Clojure/Script library for building rich CRUD apps out of nothing but functions. Hyperfiddle expresses sophisticated CRUD systems as simply functions that compose, produce values, and run at the REPL. This is made possible by our network-aware Clojure dialect that fully abstracts I/O effects at the programming language layer, uniting frontend and backend into one holistic asynchronous program. There is no divide between queries and views, query and view compose directly. The hyperfiddle macro will partition your AST across the client/server distributed system. There is no client/server dichotomy from the programmer's perspective. All IO and effects are managed.

Figure: Today, Hyperfiddle is about transactional CRUD apps like this

  • High level: Hyperfiddle makes it painless and easy to create sophisticated CRUD UIs with deep and dynamic data dependencies, without needing to think about data loading.
  • Managed I/O: Hyperfiddle leverages a functional effect system to efficiently supervise queries, network, rendering, dom, and any other physical effects.
  • Wicked fast: We believe it to be possible to achieve IO that is perfect and physically ideal. Real-time, streaming, incremental, differental, no over-rendering. #functionalprogramming
  • Spec-driven UI: We interpret clojure.spec annotations on your functions to drive semantic user interface widgets, out of the box with zero coding or configuration.
  • 5k LOC: Tight enough that you can dig in, see how it works, and contribute.

Our mission is to incubate our I/O technology and then abstract a layer further, into a future-of-coding programming experience that is ultimately accessible to regular people.

Dependencies

  • Datomic peer API or other Datomic-like immutable database supporting entity semantics and speculative transactions
  • NO React.js dependency, no need for it (easily integrated if you need the ecosystem)

Hyperfiddle is a reactive pure function

Copy paste this into your Clojure REPL and see the test pass:

git clone
git submodule update --init --recursive
clj
(require '[clojure.spec.alpha :as s]
         '[datascript.core :as d]
         '[hyperfiddle.api :as hf :refer [hfql]]
         '[hyperfiddle.photon :as p]
         '[hyperfiddle.photon-dom :as dom]
         '[missionary.core :as m])

; database effects
#?(:clj (defn submissions [needle] (d/q ... hf/*$* needle)))
#?(:clj (defn shirt-sizes [gender needle] (d/q ... hf/*$* gender needle)))
#?(:clj (defn unique-email [email] true))

; specs are used to reflect a free UI that prompts for function parameters
(s/fdef submissions :args (s/cat :needle string?) :ret sequential?)
(s/fdef genders :args (s/cat) :ret sequential?)
(s/fdef shirt-sizes :args (s/cat :gender keyword?
                                 :needle string?) :ret sequential?)

(p/defn page [needle]      ; signal function
  (hfql
    [{(submissions needle)
      [:db/id
       (:user/email ::hf/render render-email)
       {:user/gender 
        [:db/ident]}
       {(:user/shirt-size
          ::hf/render hf/picklist
          ::hf/options (shirt-sizes user/gender .))
        [:db/ident]}]}]))

(p/defn render-email [email]
  ; query and view compose directly
  (client [:div {:class (if (server (unique-email email)) "valid" "invalid")} email]))
(require '[hyperfiddle.rcf :refer [tests ! %]])
(tests
  (def !needle (atom "alice"))
  (hf/run (! (page ~(m/watch !needle)))) ; test signal exprs at the repl
  % := '{(user/submissions needle)
            [{:db/id           9
              :user/email      [:div {:class "valid"} "[email protected]"]
              :user/gender     {:db/ident :user/female}
              :user/shirt-size [:select {:selected :user/womens-large}
                                [:option 3] [:option 4] [:option 5]]}]}
  (reset! !needle "bob")
  % := '{(user/submissions needle)
            [{:db/id           10
              :user/email      [:div {:class "valid"} "[email protected]"]
              :user/gender     {:db/ident :user/male}
              :user/shirt-size [:select {:selected :user/mens-large}
                                [:option 3] [:option 4] [:option 5]]}]})

Here you can see Hyperfiddle's layers:

  1. hfql, a declarative notation for CRUD app structure and effect orchestration;
  2. defnode, a network-aware Clojure dialect* (embedded in host Clojure, like core.async) that compiles to dataflow netcode, uniting frontend and backend into one program/AST;
  3. missionary, a clojure/script functional effect system with primitives for referentially transparent IO actions, continuous signals and discrete streams, all with backpressure, cancellation, monadic structure and full dynamic control flow. Missionary also is a Clojure dialect and is inspired by core.async.

The key idea here is this that Hyperfiddle ASTs compile into a DAG which the macro will slice and partition over client/server system, shaking out dependencies to produce optimal network effects.

References