Unified event system for Clojure/ClojureScript.
Combines:
Design principles:
Usage: (require '[hive.events :as ev])
;; Register effect handlers (ev/reg-fx :http (fn [request] ...)) (ev/reg-fx :db (fn [tx] ...))
;; Register event handlers (ev/reg-event-fx :user/login [ev/debug ev/validate] ; interceptors (fn [{:keys [db]} [_ credentials]] {:db (assoc db :loading? true) :http {:method :post :url "/login" :body credentials}}))
;; Dispatch events (ev/dispatch [:user/login {:email "..." :password "..."}])
Unified event system for Clojure/ClojureScript.
Combines:
- re-frame interceptor chain (portable to JVM)
- re-frame effects/coeffects system
- domino-style declarative models with async support
Design principles:
- Events as data
- Pure handlers returning effect maps
- Interceptors for cross-cutting concerns
- Async-first with core.async
Usage:
(require '[hive.events :as ev])
;; Register effect handlers
(ev/reg-fx :http (fn [request] ...))
(ev/reg-fx :db (fn [tx] ...))
;; Register event handlers
(ev/reg-event-fx :user/login
[ev/debug ev/validate] ; interceptors
(fn [{:keys [db]} [_ credentials]]
{:db (assoc db :loading? true)
:http {:method :post :url "/login" :body credentials}}))
;; Dispatch events
(ev/dispatch [:user/login {:email "..." :password "..."}])Async extensions for hive-events.
Provides advanced async patterns beyond basic dispatch:
JVM-first with core.async, graceful degradation on CLJS.
Async extensions for hive-events. Provides advanced async patterns beyond basic dispatch: - Timeout-wrapped dispatch - Retry with backoff - Debounced dispatch - Event streams (pub/sub) - Saga/process manager patterns JVM-first with core.async, graceful degradation on CLJS.
Coeffects (cofx) system - dependency injection for event handlers.
Ported from re-frame/cofx.cljc with JVM compatibility.
Coeffects are input data that handlers need but shouldn't fetch themselves. They enable pure handlers by injecting all dependencies.
Built-in coeffects:
Usage: ;; Register a coeffect handler (reg-cofx :now (fn [coeffects] (assoc coeffects :now (System/currentTimeMillis))))
;; Inject into event handler (reg-event-fx :log/timestamp [(inject-cofx :now)] (fn [{:keys [db now]} _] {:db (assoc db :last-timestamp now)}))
Coeffects (cofx) system - dependency injection for event handlers.
Ported from re-frame/cofx.cljc with JVM compatibility.
Coeffects are input data that handlers need but shouldn't fetch themselves.
They enable pure handlers by injecting all dependencies.
Built-in coeffects:
- :db - Current application state
- :event - The event being processed
Usage:
;; Register a coeffect handler
(reg-cofx :now
(fn [coeffects]
(assoc coeffects :now (System/currentTimeMillis))))
;; Inject into event handler
(reg-event-fx :log/timestamp
[(inject-cofx :now)]
(fn [{:keys [db now]} _]
{:db (assoc db :last-timestamp now)}))Deterministic FSM workflow engine for hive-events.
Adapted from yogthos/maestro — state machine runner for expressing workflows as data. Integrated with hive-events fx/cofx system.
(require '[hive.events.fsm :as fsm])
;; Define FSM spec
(def my-workflow
{:fsm {::fsm/start {:handler (fn [resources data]
(assoc data :step :ready))
:dispatches [[::process (constantly true)]]}
::process {:handler (fn [resources data]
(assoc data :result ((:compute resources) data)))
:dispatches [[::fsm/end (fn [{:keys [result]}] (some? result))]
[::fsm/error (constantly true)]]}}
:opts {:max-trace 100}})
;; Compile and run
(-> (fsm/compile my-workflow)
(fsm/run {:compute my-fn} {:data {:input 42}}))
::start — initial state::end — terminal success, returns data::halt — pausable, returns FSM state for resume::error — terminal failure(fn [resources data] new-data)(fn [resources data] {:data new-data, :fx [[:effect-id params]]})
Effects are processed through the hive.events.fx pipeline after transition.run-sub-fsm and make-sub-fsm-handlerBased on yogthos/maestro v0.2.1 (MIT License).
Deterministic FSM workflow engine for hive-events.
Adapted from yogthos/maestro — state machine runner for expressing
workflows as data. Integrated with hive-events fx/cofx system.
## Usage
```clojure
(require '[hive.events.fsm :as fsm])
;; Define FSM spec
(def my-workflow
{:fsm {::fsm/start {:handler (fn [resources data]
(assoc data :step :ready))
:dispatches [[::process (constantly true)]]}
::process {:handler (fn [resources data]
(assoc data :result ((:compute resources) data)))
:dispatches [[::fsm/end (fn [{:keys [result]}] (some? result))]
[::fsm/error (constantly true)]]}}
:opts {:max-trace 100}})
;; Compile and run
(-> (fsm/compile my-workflow)
(fsm/run {:compute my-fn} {:data {:input 42}}))
```
## Privileged States
- `::start` — initial state
- `::end` — terminal success, returns data
- `::halt` — pausable, returns FSM state for resume
- `::error` — terminal failure
## Integration with hive-events
- Handlers are pure: `(fn [resources data] new-data)`
- Handlers may return fx-enhanced results:
`(fn [resources data] {:data new-data, :fx [[:effect-id params]]})`
Effects are processed through the hive.events.fx pipeline after transition.
- Subscriptions can dispatch events on state path changes
- Pre/post hooks for interceptor-style concerns
- EDN specs compiled with SCI
- Sub-FSM composition via `run-sub-fsm` and `make-sub-fsm-handler`
Based on yogthos/maestro v0.2.1 (MIT License).Effects (fx) system - side effect handlers.
Ported from re-frame/fx.cljc with JVM compatibility.
Effects are declarative descriptions of side effects. Each effect type has a registered handler that performs the actual work.
Built-in effects:
Usage: ;; Register a custom effect handler (reg-fx :http (fn [{:keys [method url on-success]}] (http-request method url (fn [response] (dispatch [on-success response])))))
;; Event handler returns effects map (reg-event-fx :user/login (fn [{:keys [db]} [_ credentials]] {:db (assoc db :loading? true) :http {:method :post :url "/api/login" :body credentials}}))
Effects (fx) system - side effect handlers.
Ported from re-frame/fx.cljc with JVM compatibility.
Effects are declarative descriptions of side effects.
Each effect type has a registered handler that performs the actual work.
Built-in effects:
- :db - Update application state
- :dispatch - Dispatch another event
- :dispatch-n - Dispatch multiple events
Usage:
;; Register a custom effect handler
(reg-fx :http
(fn [{:keys [method url on-success]}]
(http-request method url
(fn [response]
(dispatch [on-success response])))))
;; Event handler returns effects map
(reg-event-fx :user/login
(fn [{:keys [db]} [_ credentials]]
{:db (assoc db :loading? true)
:http {:method :post :url "/api/login" :body credentials}}))Interceptor chain implementation.
Ported from re-frame/interceptor.cljc with JVM compatibility.
An interceptor is a map with optional keys:
Context is a map containing:
Interceptor chain implementation. Ported from re-frame/interceptor.cljc with JVM compatibility. An interceptor is a map with optional keys: - :id - keyword identifier - :before - fn [context] -> context (pre-processing) - :after - fn [context] -> context (post-processing) Context is a map containing: - :coeffects - input data (including :event and :db) - :effects - output data (side effects to perform) - :queue - interceptors yet to execute - :stack - interceptors already executed (for :after phase)
Minimal pluggable logging for hive-events.
Three levels: :debug, :warn, :error
Default behavior:
Override: (set-log-fn! (fn [level msg & args] ;; your logging here ))
Disable: (set-log-fn! (fn [& _]))
Restore default: (set-log-fn! nil)
Minimal pluggable logging for hive-events.
Three levels: :debug, :warn, :error
Default behavior:
- JVM: prints to *err* (stderr)
- JS: uses console.log/warn/error
Override:
(set-log-fn! (fn [level msg & args]
;; your logging here
))
Disable:
(set-log-fn! (fn [& _]))
Restore default:
(set-log-fn! nil)Multimethod-based event dispatch + pure orchestration for hive-events.
Two complementary subsystems in one namespace:
Registration:
(register-handler! event-id handler-fn) — register handler (no interceptors)(register-handler! event-id interceptors handler-fn) — with interceptors(remove-handler! event-id) — remove a registered handlerDispatch:
(dispatch-sync event) — synchronous dispatch + fx execution(event-id event) — extract event-id (dispatch fn)Query:
(handler-registered? event-id) — check if handler existsHandler signature: (fn [coeffects event] effects-map)
Compile a batch of cross-tool operations into a wave-based execution plan. Pure functions — no side effects, no IO, no requiring-resolve.
Pipeline: normalize → validate → expand-batch → assign-waves → compile-spec
(normalize-op op) — normalize string keys, auto-generate ID(validate-ops ops) — validate IDs, deps, cycles (Kahn's algorithm)(expand-batch-macro ops) — expand 'batch' command into fan-out sub-ops(assign-waves ops) — topological sort into dependency-ordered wave groups(compile-multi-spec ops) — end-to-end: validate → expand → waves → FSM spechive-events (this ns) — pure compilation (validate, sort, waves)
↓
hive-mcp tools/multi — bridge (resolve handlers, execute ops, format)
↓
hive-mcp consolidated — MCP facade (JSON schema, tool def)
SOLID: OCP — Open for extension via defmethod handlers SOLID: SRP — Pure orchestration logic, no side effects CLARITY: L — Layered: pure compilation separate from execution
Multimethod-based event dispatch + pure orchestration for hive-events. Two complementary subsystems in one namespace: ## 1. Handler Dispatch (multimethod-based) Registration: - `(register-handler! event-id handler-fn)` — register handler (no interceptors) - `(register-handler! event-id interceptors handler-fn)` — with interceptors - `(remove-handler! event-id)` — remove a registered handler Dispatch: - `(dispatch-sync event)` — synchronous dispatch + fx execution - `(event-id event)` — extract event-id (dispatch fn) Query: - `(handler-registered? event-id)` — check if handler exists Handler signature: `(fn [coeffects event] effects-map)` ## 2. Pure Orchestration (multi-op compilation) Compile a batch of cross-tool operations into a wave-based execution plan. Pure functions — no side effects, no IO, no requiring-resolve. Pipeline: normalize → validate → expand-batch → assign-waves → compile-spec - `(normalize-op op)` — normalize string keys, auto-generate ID - `(validate-ops ops)` — validate IDs, deps, cycles (Kahn's algorithm) - `(expand-batch-macro ops)` — expand 'batch' command into fan-out sub-ops - `(assign-waves ops)` — topological sort into dependency-ordered wave groups - `(compile-multi-spec ops)` — end-to-end: validate → expand → waves → FSM spec ## Architecture ``` hive-events (this ns) — pure compilation (validate, sort, waves) ↓ hive-mcp tools/multi — bridge (resolve handlers, execute ops, format) ↓ hive-mcp consolidated — MCP facade (JSON schema, tool def) ``` SOLID: OCP — Open for extension via defmethod handlers SOLID: SRP — Pure orchestration logic, no side effects CLARITY: L — Layered: pure compilation separate from execution
Event router - registration and dispatch.
Ported from re-frame with JVM-first async support via core.async.
Supports two types of event handlers:
Dispatch modes:
Usage: ;; Initialize with app state atom (init! (atom {}))
;; Register handlers (reg-event-db :counter/inc (fn [db [_ amount]] (update db :count + amount)))
(reg-event-fx :user/fetch (fn [{:keys [db]} [_ user-id]] {:db (assoc db :loading? true) :http {:url (str "/users/" user-id)}}))
;; Dispatch events (dispatch [:counter/inc 5]) (dispatch-sync [:counter/inc 1])
Event router - registration and dispatch.
Ported from re-frame with JVM-first async support via core.async.
Supports two types of event handlers:
- reg-event-db: Handler receives db, returns new db
- reg-event-fx: Handler receives coeffects, returns effects map
Dispatch modes:
- dispatch: Async dispatch (queued, processed in order)
- dispatch-sync: Synchronous dispatch (immediate processing)
Usage:
;; Initialize with app state atom
(init! (atom {}))
;; Register handlers
(reg-event-db :counter/inc
(fn [db [_ amount]]
(update db :count + amount)))
(reg-event-fx :user/fetch
(fn [{:keys [db]} [_ user-id]]
{:db (assoc db :loading? true)
:http {:url (str "/users/" user-id)}}))
;; Dispatch events
(dispatch [:counter/inc 5])
(dispatch-sync [:counter/inc 1])cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |