Liking cljdoc? Tell your friends :D

dev.zeko.stube.kernel

The pure runtime: step, run-effects, dispatch.

Hosts embedding stube do not call into this namespace directly; the documented embedder surface lives in dev.zeko.stube.embed. This file is the value-language only: every function takes a conversation value (plus the event for dispatch) and returns the next conversation value plus the fragments to emit.

Reading guide

Everything in this namespace operates on plain values. A handler returns [self' effects]; run-effects folds those effects into the conversation, producing the next conversation value and the list of fragments that must be pushed to the browser. A fragment is just a small map describing one Datastar event — see [[fragment-shape]] for the schema.

No I/O, no atoms, no SSE — that all lives one layer up in dev.zeko.stube.runtime / dev.zeko.stube.http / dev.zeko.stube.server. This means the entire interaction loop is testable from a REPL with dispatch and a hand-built conversation value, with no server running.

Effect vocabulary

[:call <embed> :resume <k>]   push a child frame; on `:answer` the
                              parent's `:k` function is invoked
[:call-in-slot <slot> <embed> :resume <k>]
                              temporarily swap one embedded slot;
                              the child answers back to the parent
                              without taking over the page
[:set-keyed-children <slot> <[[key embed]…]>]
                              reconcile an ordered, key-addressed
                              set of children; emits per-child
                              append/remove/outer fragments
                              instead of re-rendering the parent
[:answer <value>]             pop this frame; deliver `value` to
                              the parent under its resume key
[:replace <embed>]            pop this frame and push another in
                              its place (Seaside `become:`)
[:patch <hiccup>]             extra DOM patch (no stack change)
[:patch-signals <map>]        push a Datastar signal patch
[:execute-script <js>]        run literal JS in the browser
[:history :replace|:push url]  sync browser URL (replaceState/pushState)
[:io <fn>]                    ask the bound runtime to run `(fn)`
                              off-thread; pure folds leave it inert
[:after ms event]             schedule a future event for this instance
[:subscribe topic event]      subscribe this instance to published messages
[:unsubscribe topic?]         remove this instance's topic subscription(s)
[:back]                       restore the previous conversation
                              from `:conv/history` (slice 3)
[:end <value>]                terminate the conversation

All effects produce zero or more fragments and an updated conversation.

Component lifecycle keys

Beyond the keys read directly by :render / :handle, a component may include:

:start  (fn [self] [self' effects])
:stop   (fn [self] [self' effects])
:wakeup (fn [self] [self' effects])

:start runs once immediately after instantiation for both stack frames and embedded children, which lets "task" components launch their first :call without a synthetic user event and lets widgets subscribe or schedule timers. :stop runs just before a frame/subtree is removed; :wakeup runs when a persisted or history-restored frame becomes live again.

The pure runtime: `step`, `run-effects`, `dispatch`.

Hosts embedding stube do not call into this namespace directly; the
documented embedder surface lives in [[dev.zeko.stube.embed]].  This
file is the value-language only: every function takes a conversation
value (plus the event for `dispatch`) and returns the next conversation
value plus the fragments to emit.

Reading guide
-------------

Everything in this namespace operates on plain values.  A handler
returns `[self' effects]`; `run-effects` folds those effects into the
conversation, producing the next conversation value and the list of
*fragments* that must be pushed to the browser.  A fragment is just a
small map describing one Datastar event — see [[fragment-shape]] for
the schema.

No I/O, no atoms, no SSE — that all lives one layer up in
[[dev.zeko.stube.runtime]] / [[dev.zeko.stube.http]] / [[dev.zeko.stube.server]].
This means the entire interaction loop is testable from a REPL with
`dispatch` and a hand-built conversation value, with no server running.

Effect vocabulary
-----------------

    [:call <embed> :resume <k>]   push a child frame; on `:answer` the
                                  parent's `:k` function is invoked
    [:call-in-slot <slot> <embed> :resume <k>]
                                  temporarily swap one embedded slot;
                                  the child answers back to the parent
                                  without taking over the page
    [:set-keyed-children <slot> <[[key embed]…]>]
                                  reconcile an ordered, key-addressed
                                  set of children; emits per-child
                                  append/remove/outer fragments
                                  instead of re-rendering the parent
    [:answer <value>]             pop this frame; deliver `value` to
                                  the parent under its resume key
    [:replace <embed>]            pop this frame and push another in
                                  its place (Seaside `become:`)
    [:patch <hiccup>]             extra DOM patch (no stack change)
    [:patch-signals <map>]        push a Datastar signal patch
    [:execute-script <js>]        run literal JS in the browser
    [:history :replace|:push url]  sync browser URL (replaceState/pushState)
    [:io <fn>]                    ask the bound runtime to run `(fn)`
                                  off-thread; pure folds leave it inert
    [:after ms event]             schedule a future event for this instance
    [:subscribe topic event]      subscribe this instance to published messages
    [:unsubscribe topic?]         remove this instance's topic subscription(s)
    [:back]                       restore the previous conversation
                                  from `:conv/history` (slice 3)
    [:end <value>]                terminate the conversation

All effects produce zero or more fragments and an updated conversation.

Component lifecycle keys
------------------------
Beyond the keys read directly by `:render` / `:handle`, a component
may include:

    :start  (fn [self] [self' effects])
    :stop   (fn [self] [self' effects])
    :wakeup (fn [self] [self' effects])

`:start` runs once immediately after instantiation for both stack
frames and embedded children, which lets "task" components launch
their first `:call` without a synthetic user event and lets widgets
subscribe or schedule timers.  `:stop` runs just before a frame/subtree
is removed; `:wakeup` runs when a persisted or history-restored frame
becomes live again.
raw docstring

*current-app*clj

Opaque host value attached to the kernel via the :app option. Bound by the runtime during dispatch and render so component code can read it through dev.zeko.stube.core/app without threading a kernel reference.

Opaque host value attached to the kernel via the `:app` option.  Bound
by the runtime during dispatch and render so component code can read
it through `dev.zeko.stube.core/app` without threading a kernel
reference.
sourceraw docstring

*current-kernel*clj

Runtime kernel currently folding an effect. Standalone helpers use this to route regular functions such as s/publish! to the embedded kernel when called from component code, while preserving the historical default-kernel behaviour outside a runtime dispatch.

Runtime kernel currently folding an effect.  Standalone helpers use
this to route regular functions such as `s/publish!` to the embedded
kernel when called from component code, while preserving the historical
default-kernel behaviour outside a runtime dispatch.
sourceraw docstring

*current-principal*clj

Authenticated principal stamped onto the conversation at mint time via :principal-fn. Bound by the runtime around dispatch and render so component code can read it through dev.zeko.stube.core/principal.

Authenticated principal stamped onto the conversation at mint time
via `:principal-fn`.  Bound by the runtime around dispatch and render
so component code can read it through `dev.zeko.stube.core/principal`.
sourceraw docstring

*run-io!*clj

Optional side-effect hook bound by the runtime for [:io f]. Keeping this as a hook preserves pure run-effects/replay: without a runtime binding, :io is data that produces no fragments and does not execute.

Optional side-effect hook bound by the runtime for `[:io f]`.  Keeping
this as a hook preserves pure `run-effects`/`replay`: without a runtime
binding, `:io` is data that produces no fragments and does not execute.
sourceraw docstring

*schedule-event!*clj

Optional side-effect hook bound by the server while folding effects. The kernel stays ignorant of threads and SSE; it only describes the delayed event that should be sent later.

Optional side-effect hook bound by the server while folding effects.
The kernel stays ignorant of threads and SSE; it only describes the
delayed event that should be sent later.
sourceraw docstring

*subscribe!*clj

Optional side-effect hook bound by the server for [:subscribe …].

Optional side-effect hook bound by the server for `[:subscribe …]`.
sourceraw docstring

*unsubscribe!*clj

Optional side-effect hook bound by the server for [:unsubscribe …].

Optional side-effect hook bound by the server for `[:unsubscribe …]`.
sourceraw docstring

bootclj

(boot flow-id)
(boot flow-id init-args)

Mint the initial set of effects for a freshly minted conversation whose root flow is flow-id. Pulled out so the http layer can ask for them on first SSE connect. flow-id may also be an embed spec, which lets an adapter preserve root init args until the SSE attaches.

Mint the initial set of effects for a freshly minted conversation
whose root flow is `flow-id`.  Pulled out so the http layer can ask
for them on first SSE connect.  `flow-id` may also be an embed spec,
which lets an adapter preserve root init args until the SSE attaches.
sourceraw docstring

dispatchclj

(dispatch conv {:keys [instance-id event payload signals] :as ev})

Apply one client event to a conversation. event is the map

{:instance-id "ix-7e2"
 :event       :submit         ; or any keyword the component knows
 :payload     any-edn-value   ; optional, from (s/on ... :as [:event v])
 :signals     {:answer "42"}}

Returns [conv' fragments]. Pure: no I/O, no globals.

Stale events — those whose instance-id no longer exists in the conversation — are dropped silently. This matters for buttons that are still in the DOM after their owning frame has been popped (e.g. the user double-clicks an OK button: the first click :answers and removes the instance; the second click arrives with an iid that's already gone). Throwing here would surface as a 500 in the http layer for what is, semantically, a no-op.

Apply one client event to a conversation.  `event` is the map

    {:instance-id "ix-7e2"
     :event       :submit         ; or any keyword the component knows
     :payload     any-edn-value   ; optional, from (s/on ... :as [:event v])
     :signals     {:answer "42"}}

Returns `[conv' fragments]`.  Pure: no I/O, no globals.

Stale events — those whose `instance-id` no longer exists in the
conversation — are dropped silently.  This matters for buttons that
are still in the DOM after their owning frame has been popped (e.g.
the user double-clicks an OK button: the first click `:answer`s and
removes the instance; the second click arrives with an iid that's
already gone).  Throwing here would surface as a 500 in the http
layer for what is, semantically, a no-op.
sourceraw docstring

redraw-topclj

(redraw-top conv)

Re-render the current top frame in-place without running :wakeup or snapshotting. Returns [conv' [frag]]. Used by dev-tooling paths (e.g. enabling halos on a live conversation) that want a fresh frame against the current state.

Re-render the current top frame in-place without running `:wakeup`
or snapshotting.  Returns `[conv' [frag]]`.  Used by dev-tooling
paths (e.g. enabling halos on a live conversation) that want a fresh
frame against the *current* state.
sourceraw docstring

resume-topclj

(resume-top conv)

Run :wakeup for the current top frame and render it as a restored frame. Used by the http layer when a persisted conversation reattaches.

Run `:wakeup` for the current top frame and render it as a restored
frame.  Used by the http layer when a persisted conversation reattaches.
sourceraw docstring

run-effectsclj

(run-effects conv effects)

Apply a sequence of effects to conv left to right, collecting fragments. Returns [conv' fragments].

Apply a sequence of effects to `conv` left to right, collecting
fragments.  Returns `[conv' fragments]`.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close