Liking cljdoc? Tell your friends :D

synthigy.client

clj

Synthigy client for the /data endpoint — JVM / babashka.

Connect once, then call; no client threading:

(connect! {:endpoint "http://localhost:7887" :client-id "my-service" :client-secret "secret"})

(search :user {:-where {:active {:-eq true}}} {:name nil :roles [:name :active]})

(sync :user {:name "alice" :active true})

THE INVARIANT: one process, one client, one backend. A process (BFF, service, script) connects to Synthigy as exactly ONE OAuth client — identity is multiplexed per-call with :acting-as, never with a second client. binding synthigy.client.core/*client* exists for TESTS, nothing else. Internals that pass the client VALUE do so for lifecycle correctness (a watch must tear down against the client it registered in, even after a REPL re-connect!) — not for multi-endpoint support, which is a non-goal.

Keys are kebab-case in both directions by default (:key-format nil for raw snake_case wire keys).

Pure data helpers — op builders for batch, results->data/ok?, compose-tree/compose-forest — live in synthigy.client.core.

Synthigy client for the /data endpoint — JVM / babashka.

Connect once, then call; no client threading:

  (connect! {:endpoint "http://localhost:7887"
             :client-id "my-service"
             :client-secret "secret"})

  (search :user
    {:-where {:active {:-eq true}}}
    {:name nil :roles [:name :active]})

  (sync :user {:name "alice" :active true})

THE INVARIANT: one process, one client, one backend. A process (BFF,
service, script) connects to Synthigy as exactly ONE OAuth client —
identity is multiplexed per-call with `:acting-as`, never with a second
client. `binding synthigy.client.core/*client*` exists for TESTS, nothing
else. Internals that pass the client VALUE do so for lifecycle correctness
(a watch must tear down against the client it registered in, even after a
REPL re-`connect!`) — not for multi-endpoint support, which is a non-goal.

Keys are kebab-case in both directions by default (`:key-format nil`
for raw snake_case wire keys).

Pure data helpers — op builders for `batch`, `results->data`/`ok?`,
`compose-tree`/`compose-forest` — live in `synthigy.client.core`.
cljs

Synthigy client for the /data endpoint — ClojureScript (promise-returning).

Same surface as the CLJ client; every network fn returns a Promise. Connect once via connect!; pure data helpers live in synthigy.client.core.

THE INVARIANT: one process, one client, one backend — identity is multiplexed per-call with :acting-as, never with a second client.

Synthigy client for the /data endpoint — ClojureScript (promise-returning).

Same surface as the CLJ client; every network fn returns a Promise.
Connect once via `connect!`; pure data helpers live in
`synthigy.client.core`.

THE INVARIANT: one process, one client, one backend — identity is
multiplexed per-call with `:acting-as`, never with a second client.
raw docstring

batchclj/s≠

(batch operations & {:as opts})
clj

Execute multiple operations in a single request.

Returns vector of raw results in request order. Each result is {:ok true :data ...} or {:ok false :error {:message ... :code ...}}.

Use op-* builders to construct operations:

(let [ops [(core/op-sync :user {:name "alice"}) (core/op-search :user nil [:name]) (core/op-search :user_role nil [:name])] [synced users roles] (results->data (batch ops) ops)] (when (all-ok? [synced users roles]) (println synced users roles)))

Execute multiple operations in a single request.

Returns vector of raw results in request order. Each result is
{:ok true :data ...} or {:ok false :error {:message ... :code ...}}.

Use op-* builders to construct operations:

  (let [ops [(core/op-sync :user {:name "alice"})
             (core/op-search :user nil [:name])
             (core/op-search :user_role nil [:name])]
        [synced users roles] (results->data (batch ops) ops)]
    (when (all-ok? [synced users roles])
      (println synced users roles)))
cljs

Execute multiple operations in a single request. Returns a Promise of raw results vector; use results->data to extract.

Execute multiple operations in a single request. Returns a Promise
of raw results vector; use `results->data` to extract.
source (clj)source (cljs)raw docstring

close-watch!clj/s≠

(close-watch! h)
clj

Stop a handle from watch/watch-schema (a map with :close) or from watch-query (an atom carrying :close in its metadata).

Stop a handle from `watch`/`watch-schema` (a map with :close) or from
`watch-query` (an atom carrying :close in its metadata).
cljs

Stop a handle from watch/watch-schema (a map with :close) or from watch-query/watch-xsql (an atom carrying :close in its metadata).

Stop a handle from `watch`/`watch-schema` (a map with :close) or from
`watch-query`/`watch-xsql` (an atom carrying :close in its metadata).
source (clj)source (cljs)raw docstring

connect!clj/s≠

(connect! opts)
clj

Create a client from opts (see synthigy.client.core/create-client) and install it as the process-wide default — the Clojure server-restart idiom: the PREVIOUS client (if any) is destroyed first (disconnect! — its SSE listener stops, its watches close), then the new one replaces it. Call at startup; call again to reconnect.

Create a client from `opts` (see `synthigy.client.core/create-client`) and
install it as the process-wide default — the Clojure server-restart idiom:
the PREVIOUS client (if any) is destroyed first (`disconnect!` — its SSE
listener stops, its watches close), then the new one replaces it. Call at
startup; call again to reconnect.
cljs

Create a client from opts and install it as the process-wide default — the same server-restart idiom as the CLJ client: the PREVIOUS client (if any) is destroyed first (disconnect! — its SSE listener stops, its watches close), then the new one replaces it. Call again to reconnect (e.g. after a silent-renew login/logout swap).

Create a client from `opts` and install it as the process-wide default —
the same server-restart idiom as the CLJ client: the PREVIOUS client (if
any) is destroyed first (`disconnect!` — its SSE listener stops, its
watches close), then the new one replaces it. Call again to reconnect
(e.g. after a silent-renew login/logout swap).
source (clj)source (cljs)raw docstring

deleteclj/s≠

(delete entity data & {:as opts})
clj

Delete entity records.

Data keys accept kebab-case (normalized to snake_case).

Delete entity records.

Data keys accept kebab-case (normalized to snake_case).
cljs

Delete entity records. Returns a Promise.

Delete entity records. Returns a Promise.
source (clj)source (cljs)raw docstring

deployed-modelclj/s≠

(deployed-model & {:as opts})
clj

Fetch the raw ERD model as deployed. Requires dataset:load scope.

Fetch the raw ERD model as deployed. Requires dataset:load scope.
cljs

Fetch the raw ERD model as deployed. Requires dataset:load scope. Returns a Promise.

Fetch the raw ERD model as deployed. Requires dataset:load scope.
Returns a Promise.
source (clj)source (cljs)raw docstring

disconnect!clj/s≠

(disconnect!)
clj

Destroy the connected client, server-restart style: stop the watch multiplexer's SSE listener, drop all watches, best-effort clear the server-side subscription set, and uninstall the client. No-op when not connected. connect! calls this on the previous client automatically.

Destroy the connected client, server-restart style: stop the watch
multiplexer's SSE listener, drop all watches, best-effort clear the
server-side subscription set, and uninstall the client. No-op when not
connected. `connect!` calls this on the previous client automatically.
cljs

Destroy the connected client, server-restart style: stop the watch multiplexer's SSE listener, drop all watches, best-effort clear the server-side subscription set, and uninstall the client. No-op when not connected. connect! calls this on the previous client automatically. Returns a Promise.

Destroy the connected client, server-restart style: stop the watch
multiplexer's SSE listener, drop all watches, best-effort clear the
server-side subscription set, and uninstall the client. No-op when not
connected. `connect!` calls this on the previous client automatically.
Returns a Promise.
source (clj)source (cljs)raw docstring

getclj/s≠

(get entity args selection & {:as opts})
clj

Get a single entity by unique constraint.

Args and selection accept kebab-case (normalized to snake_case). Selection supports shorthand syntax.

Get a single entity by unique constraint.

Args and selection accept kebab-case (normalized to snake_case).
Selection supports shorthand syntax.
cljs

Get a single entity by unique constraint. Returns a Promise.

Get a single entity by unique constraint. Returns a Promise.
source (clj)source (cljs)raw docstring

get-treeclj/s≠

(get-tree entity root on selection & {:as opts})
clj

From root entity id, return root + descendants reachable via :on.

From `root` entity id, return root + descendants reachable via :on.
cljs

Get root + descendants via :on relation. Returns a Promise.

Get root + descendants via :on relation. Returns a Promise.
source (clj)source (cljs)raw docstring

history-diffclj

(history-diff record-xid from-ts to-ts & {:keys [tenant]})

Difference in a record's state between two timestamps. Option: :tenant

Difference in a record's state between two timestamps. Option: :tenant
sourceraw docstring

history-eventsclj

(history-events record-xid & {:keys [between tenant limit track]})

Events for record-xid (nil = any record) over a time range. Options: :between [from to] (defaults [nil now]) :tenant :limit :track

Events for `record-xid` (nil = any record) over a time range. Options:
:between [from to] (defaults [nil now]) :tenant :limit :track
sourceraw docstring

history-get-atclj

(history-get-at record-xid at & {:keys [tenant include-deleted?]})

State of record-xid at timestamp at. Options: :tenant :include-deleted?

State of `record-xid` at timestamp `at`. Options: :tenant :include-deleted?
sourceraw docstring

history-sinceclj

(history-since & {:keys [cursor tenant limit track]})

Events strictly after the :cursor timestamp, oldest-first. Options: :cursor :tenant :limit :track

Events strictly after the :cursor timestamp, oldest-first.
Options: :cursor :tenant :limit :track
sourceraw docstring

history-timelineclj

(history-timeline & {:keys [between group-by tenant limit]})

Events grouped by :group-by (":request"/":actor"/":scope"). Options: :between [from to] :group-by :tenant :limit

Events grouped by :group-by (":request"/":actor"/":scope").
Options: :between [from to] :group-by :tenant :limit
sourceraw docstring

lintclj/s≠

(lint source & {:keys [entity op]})
clj

Check an XSQL source string against the IAM-projected schema and return a seq of diagnostics. :entity enables schema-aware checks, :op sets the wire op.

Check an XSQL `source` string against the IAM-projected schema and
return a seq of diagnostics. :entity enables schema-aware checks,
:op sets the wire op.
cljs

Check an XSQL source string against the IAM-projected schema. Returns a Promise of the diagnostics seq. :entity enables schema-aware checks, :op sets the wire op.

Check an XSQL `source` string against the IAM-projected schema.
Returns a Promise of the diagnostics seq. :entity enables
schema-aware checks, :op sets the wire op.
source (clj)source (cljs)raw docstring

listenclj/s≠

(listen on-event)
(listen on-event opts)
clj

Stream SSE change events from /data/events, calling on-event with each delta envelope. :type is the delta kind — record/insert|update|delete (with :record-xid + :before/:after), relation/link|unlink (with :data [subscribed other]), or the coalesced pokes entity/touched (:entity) / relation/touched (:relation).

BLOCKS the calling thread — wrap in (future ...) for background use. Auto-reconnects with Last-Event-ID + exponential backoff (1s → 30s).

Events are notification-only — fetch the updated records via search/get/batch after receiving one.

Options: :stop? — 0-arg predicate; truthy stops the loop between frames :max-delay — cap for reconnect backoff in ms (default 30000)

UNAUTHORIZED/FORBIDDEN propagate; other transport errors reconnect.

(subscribe c :user) (future (listen c prn))

Stream SSE change events from /data/events, calling `on-event` with each
delta envelope. `:type` is the delta kind — record/insert|update|delete
(with `:record-xid` + `:before`/`:after`), relation/link|unlink (with
`:data` [subscribed other]), or the coalesced pokes entity/touched
(`:entity`) / relation/touched (`:relation`).

BLOCKS the calling thread — wrap in (future ...) for background use.
Auto-reconnects with Last-Event-ID + exponential backoff (1s → 30s).

Events are notification-only — fetch the updated records via
`search`/`get`/`batch` after receiving one.

Options:
  :stop?     — 0-arg predicate; truthy stops the loop between frames
  :max-delay — cap for reconnect backoff in ms (default 30000)

UNAUTHORIZED/FORBIDDEN propagate; other transport errors reconnect.

  (subscribe c :user)
  (future (listen c prn))
cljs

Stream SSE notifications from /data/events. Calls on-event with each {:type :entity :relations :xids} notification. Returns a 0-arg stop function that aborts the listener.

Auto-reconnects with Last-Event-ID + exponential backoff. Does NOT block — runs on the microtask queue via fetch streaming.

Options: :max-delay — reconnect backoff cap ms (default 30000) :on-parse-error — (fn [error raw]) for malformed frames

Stream SSE notifications from /data/events. Calls `on-event` with
each `{:type :entity :relations :xids}` notification. Returns a
0-arg `stop` function that aborts the listener.

Auto-reconnects with Last-Event-ID + exponential backoff. Does
NOT block — runs on the microtask queue via fetch streaming.

Options:
  :max-delay       — reconnect backoff cap ms (default 30000)
  :on-parse-error  — (fn [error raw]) for malformed frames
source (clj)source (cljs)raw docstring

onboardclj/s≠

(onboard xid & {:keys [reset methods ttl-seconds return-url]})
clj

Mint a one-time account-claim link (POST /oauth/onboard). Confidential client whose principal administers the account — RBAC update on User plus the row inside its owner-group write scope, which the shipped User Provisioner role grants — else :code "PROVISION_FORBIDDEN". The connected client's own client_credentials identity IS that principal, so no separate credential is needed here.

xid : an EXISTING account's xid. Onboarding no longer creates accounts — create it first over /data (with person_info, roles, groups in one tree), then mint a ticket for it. A blank xid throws :code "XID_REQUIRED"; one that doesn't resolve throws :code "USER_NOT_FOUND". :reset : soft-recycle this account first — strip its federated identities, null its password, revoke live sessions/tokens — before minting. Does NOT touch active; that flag is your data, write it yourself. :methods : restrict the claim page, e.g. ["password"] or ["google"]; omitted = every active federation provider plus password :ttl-seconds : claim-link lifetime; server default 24h :return-url : where a successful DIRECT (browser) claim redirects instead of Synthigy's generic status page. Must match one of THIS client's registered redirections (or be a loopback URI); an unregistered value throws :code "RETURN_URL_NOT_REGISTERED".

-> {:onboard_url ... :expires_at ... :user {:xid ...}} (wire keys as-is, like schema/lint). Throws ex-info with :code (e.g. "PROVISION_FORBIDDEN", "XID_REQUIRED", "USER_NOT_FOUND") and :status on failure.

Mint a one-time account-claim link (POST /oauth/onboard). Confidential
client whose principal administers the account — RBAC update on User plus
the row inside its owner-group write scope, which the shipped User
Provisioner role grants — else :code "PROVISION_FORBIDDEN". The
connected client's own client_credentials identity IS that principal, so
no separate credential is needed here.

xid          : an EXISTING account's xid. Onboarding no longer creates
               accounts — create it first over `/data` (with person_info,
               roles, groups in one tree), then mint a ticket for it.
               A blank xid throws :code "XID_REQUIRED"; one that doesn't
               resolve throws :code "USER_NOT_FOUND".
:reset       : soft-recycle this account first — strip its federated
               identities, null its password, revoke live sessions/tokens
               — before minting. Does NOT touch `active`; that flag is
               your data, write it yourself.
:methods     : restrict the claim page, e.g. ["password"] or ["google"];
               omitted = every active federation provider plus password
:ttl-seconds : claim-link lifetime; server default 24h
:return-url  : where a successful DIRECT (browser) claim redirects instead
               of Synthigy's generic status page. Must match one of THIS
               client's registered redirections (or be a loopback URI);
               an unregistered value throws :code "RETURN_URL_NOT_REGISTERED".

-> {:onboard_url ... :expires_at ... :user {:xid ...}} (wire keys as-is,
like schema/lint).
Throws ex-info with :code (e.g. "PROVISION_FORBIDDEN", "XID_REQUIRED",
"USER_NOT_FOUND") and :status on failure.
cljs

Mint a one-time account-claim link (POST /oauth/onboard). Confidential client whose principal administers the account — RBAC update on User plus the row inside its owner-group write scope, which the shipped User Provisioner role grants — else :code "PROVISION_FORBIDDEN". The connected client's own client_credentials identity IS that principal, so no separate credential is needed here.

xid : an EXISTING account's xid. Onboarding no longer creates accounts — create it first over /data (with person_info, roles, groups in one tree), then mint a ticket for it. A blank xid rejects with :code "XID_REQUIRED"; one that doesn't resolve rejects with :code "USER_NOT_FOUND". :reset : soft-recycle this account first — strip its federated identities, null its password, revoke live sessions/tokens — before minting. Does NOT touch active; that flag is your data, write it yourself. :methods : restrict the claim page, e.g. ["password"] or ["google"]; omitted = every active federation provider plus password :ttl-seconds : claim-link lifetime; server default 24h :return-url : where a successful DIRECT (browser) claim redirects instead of Synthigy's generic status page. Must match one of THIS client's registered redirections (or be a loopback URI); an unregistered value rejects with :code "RETURN_URL_NOT_REGISTERED".

Returns a Promise of {:onboard_url ... :expires_at ... :user {:xid ...}} (wire keys as-is, like schema/lint). Rejects with ex-info carrying :code (e.g. "PROVISION_FORBIDDEN", "XID_REQUIRED", "USER_NOT_FOUND") and :status on failure.

Mint a one-time account-claim link (POST /oauth/onboard). Confidential
client whose principal administers the account — RBAC update on User plus
the row inside its owner-group write scope, which the shipped User
Provisioner role grants — else :code "PROVISION_FORBIDDEN". The
connected client's own client_credentials identity IS that principal, so
no separate credential is needed here.

xid          : an EXISTING account's xid. Onboarding no longer creates
               accounts — create it first over `/data` (with person_info,
               roles, groups in one tree), then mint a ticket for it.
               A blank xid rejects with :code "XID_REQUIRED"; one that
               doesn't resolve rejects with :code "USER_NOT_FOUND".
:reset       : soft-recycle this account first — strip its federated
               identities, null its password, revoke live sessions/tokens
               — before minting. Does NOT touch `active`; that flag is
               your data, write it yourself.
:methods     : restrict the claim page, e.g. ["password"] or ["google"];
               omitted = every active federation provider plus password
:ttl-seconds : claim-link lifetime; server default 24h
:return-url  : where a successful DIRECT (browser) claim redirects instead
               of Synthigy's generic status page. Must match one of THIS
               client's registered redirections (or be a loopback URI);
               an unregistered value rejects with :code
               "RETURN_URL_NOT_REGISTERED".

Returns a Promise of {:onboard_url ... :expires_at ... :user {:xid ...}}
(wire keys as-is, like schema/lint).
Rejects with ex-info carrying :code (e.g.
"PROVISION_FORBIDDEN", "XID_REQUIRED", "USER_NOT_FOUND") and :status
on failure.
source (clj)source (cljs)raw docstring

onboard-completeclj/s≠

(onboard-complete ticket)
clj

Redeem an onboarding ticket without a browser (POST /oauth/onboard/complete) — the indirect face of the SAME ticket onboard mints. Must be called by the SAME client that minted the ticket; any other client's bearer is rejected with :code "CLAIM_INVALID", and the client must still administer the account (:code "PROVISION_FORBIDDEN").

The caller runs its own out-of-band proofing (email link, SMS OTP, push approval, KYC, a phone call — Synthigy never learns which) and, once satisfied, redeems the ticket itself instead of bouncing the user's browser through /oauth/claim. This never sets a credential — credentials are subject-only. The account activates with none; give it one via the claim page (password or a federated identity) or a later ticket.

ticket : the token minted by onboard (parse it out of :onboard_url)

-> {:user {:xid ...} :active true} Throws ex-info with :code (e.g. "CLAIM_INVALID") and :status on failure.

Redeem an onboarding ticket without a browser (POST
/oauth/onboard/complete) — the indirect face of the SAME ticket `onboard`
mints. Must be called by the SAME client that minted the ticket; any
other client's bearer is rejected with :code "CLAIM_INVALID", and the
client must still administer the account (:code "PROVISION_FORBIDDEN").

The caller runs its own out-of-band proofing (email link, SMS OTP, push
approval, KYC, a phone call — Synthigy never learns which) and, once
satisfied, redeems the ticket itself instead of bouncing the user's
browser through /oauth/claim. This never sets a credential — credentials
are subject-only. The account activates with none; give it one via the
claim page (password or a federated identity) or a later ticket.

ticket : the token minted by `onboard` (parse it out of :onboard_url)

-> {:user {:xid ...} :active true}
Throws ex-info with :code (e.g. "CLAIM_INVALID") and :status on failure.
cljs

Redeem an onboarding ticket without a browser (POST /oauth/onboard/complete) — the indirect face of the SAME ticket onboard mints. Must be called by the SAME client that minted the ticket; any other client's bearer is rejected with :code "CLAIM_INVALID", and the client must still administer the account (:code "PROVISION_FORBIDDEN").

The caller runs its own out-of-band proofing (email link, SMS OTP, push approval, KYC, a phone call — Synthigy never learns which) and, once satisfied, redeems the ticket itself instead of bouncing the user's browser through /oauth/claim. This never sets a credential — credentials are subject-only. The account activates with none; give it one via the claim page (password or a federated identity) or a later ticket.

ticket : the token minted by onboard (parse it out of :onboard_url)

Returns a Promise of {:user {:xid ...} :active true}. Rejects with ex-info carrying :code (e.g. "CLAIM_INVALID") and :status on failure.

Redeem an onboarding ticket without a browser (POST
/oauth/onboard/complete) — the indirect face of the SAME ticket `onboard`
mints. Must be called by the SAME client that minted the ticket; any
other client's bearer is rejected with :code "CLAIM_INVALID", and the
client must still administer the account (:code "PROVISION_FORBIDDEN").

The caller runs its own out-of-band proofing (email link, SMS OTP, push
approval, KYC, a phone call — Synthigy never learns which) and, once
satisfied, redeems the ticket itself instead of bouncing the user's
browser through /oauth/claim. This never sets a credential — credentials
are subject-only. The account activates with none; give it one via the
claim page (password or a federated identity) or a later ticket.

ticket : the token minted by `onboard` (parse it out of :onboard_url)

Returns a Promise of {:user {:xid ...} :active true}. Rejects with
ex-info carrying :code (e.g. "CLAIM_INVALID") and :status on failure.
source (clj)source (cljs)raw docstring

purgeclj/s≠

(purge entity args selection & {:as opts})
clj

Find and delete matching records, return deleted data.

Args and selection accept kebab-case (normalized to snake_case). Selection supports shorthand syntax.

Find and delete matching records, return deleted data.

Args and selection accept kebab-case (normalized to snake_case).
Selection supports shorthand syntax.
cljs

Find and delete matching records. Returns a Promise of deleted data.

Find and delete matching records. Returns a Promise of deleted data.
source (clj)source (cljs)raw docstring

queryclj/s≠

(query xsql params & {:keys [op] :or {op "search"} :as opts})
clj

Run an XSQL query with optional ?name:type[] params. STRICT wire: sends the xsql DOCUMENT op ({:op "xsql" :xsql <document> :params …}) — a bare rooted body gets a synthetic @<op> _q header client-side; the server derives verb/entity/selections/args from the document. :op defaults to "search" — pass :op :get for a unique-key read.

Run an XSQL query with optional ?name:type[] params. STRICT wire: sends
the `xsql` DOCUMENT op ({:op "xsql" :xsql <document> :params …}) — a
bare rooted body gets a synthetic `@<op> _q` header client-side; the
server derives verb/entity/selections/args from the document. `:op`
defaults to "search" — pass :op :get for a unique-key read.
cljs

Run an XSQL query with optional ?name:type[] params. STRICT wire: sends the xsql DOCUMENT op ({:op "xsql" :xsql <document> :params …}) — a bare rooted body gets a synthetic @<op> _q header client-side; the server derives verb/entity/selections/args from the document. :op defaults to "search" — pass :op :get for a unique-key read. Returns a Promise.

Run an XSQL query with optional ?name:type[] params. STRICT wire: sends
the `xsql` DOCUMENT op ({:op "xsql" :xsql <document> :params …}) — a
bare rooted body gets a synthetic `@<op> _q` header client-side; the
server derives verb/entity/selections/args from the document. `:op`
defaults to "search" — pass :op :get for a unique-key read. Returns a Promise.
source (clj)source (cljs)raw docstring

runtime-modelclj/s≠

(runtime-model & {:as opts})
clj

Fetch the runtime ERD model (deployed + identity/audit/ref expansion). Requires dataset:load scope.

Fetch the runtime ERD model (deployed + identity/audit/ref expansion).
Requires dataset:load scope.
cljs

Fetch the runtime ERD model (deployed + identity/audit/ref expansion). Requires dataset:load scope. Returns a Promise.

Fetch the runtime ERD model (deployed + identity/audit/ref expansion).
Requires dataset:load scope. Returns a Promise.
source (clj)source (cljs)raw docstring

schemaclj/s≠

(schema)
(schema entities)
clj

Fetch the IAM-filtered deployed model via GET /schema.

Without entities: full schema. With a seq of entity names (kebab-case strings or keywords): narrow the response to those entities. Returns {:id-key :entities}.

Fetch the IAM-filtered deployed model via GET /schema.

Without `entities`: full schema.
With a seq of entity names (kebab-case strings or keywords): narrow
the response to those entities. Returns {:id-key :entities}.
cljs

Fetch the IAM-filtered deployed model via GET /schema. Returns a Promise.

Fetch the IAM-filtered deployed model via GET /schema. Returns a Promise.
source (clj)source (cljs)raw docstring

(search entity args selection & {:as opts})
clj

Search for entities matching args.

Args and selection accept kebab-case (normalized to snake_case). Selection supports shorthand syntax.

Search for entities matching args.

Args and selection accept kebab-case (normalized to snake_case).
Selection supports shorthand syntax.
cljs

Search for entities. Returns a Promise of the result data.

Search for entities. Returns a Promise of the result data.
source (clj)source (cljs)raw docstring

search-treeclj/s≠

(search-tree entity on args selection & {:as opts})
clj

Search matching entities + walk :on relation UP to their ancestors. on is a keyword/string naming the tree (self-FK) relation.

Search matching entities + walk :on relation UP to their ancestors.
`on` is a keyword/string naming the tree (self-FK) relation.
cljs

Search matching entities + walk :on relation UP to ancestors. Returns a Promise.

Search matching entities + walk :on relation UP to ancestors. Returns a Promise.
source (clj)source (cljs)raw docstring

sliceclj/s≠

(slice entity args selection & {:as opts})
clj

Slice relations from entity.

Args and selection accept kebab-case (normalized to snake_case). Selection supports shorthand syntax.

Slice relations from entity.

Args and selection accept kebab-case (normalized to snake_case).
Selection supports shorthand syntax.
cljs

Slice relations from entity. Returns a Promise.

Slice relations from entity. Returns a Promise.
source (clj)source (cljs)raw docstring

sql-templateclj/s≠

(sql-template template params & {:keys [cached] :or {cached true} :as opts})
clj

Execute an ERD-aware SQL template. Auto-generates FROM and JOINs from {entity.field} / {entity->rel.field} placeholders; supports junction, self-FK (tree), and field-ref traversal.

Execute an ERD-aware SQL template.
Auto-generates FROM and JOINs from {entity.field} / {entity->rel.field}
placeholders; supports junction, self-FK (tree), and field-ref traversal.
cljs

Execute an ERD-aware SQL template. Returns a Promise.

Execute an ERD-aware SQL template. Returns a Promise.
source (clj)source (cljs)raw docstring

stackclj/s≠

(stack entity data & {:keys [returning] :as opts})
clj

Stack data on top of current state — returns {:count n}.

Data keys accept kebab-case (normalized to snake_case). Same :returning contract as sync.

Stack data on top of current state — returns {:count n}.

Data keys accept kebab-case (normalized to snake_case). Same `:returning`
contract as sync.
cljs

Stack data on top of current state — resolves to {:count n}. Same :returning contract as sync.

Stack data on top of current state — resolves to {:count n}. Same
`:returning` contract as sync.
source (clj)source (cljs)raw docstring

syncclj/s≠

(sync entity data & {:keys [returning] :as opts})
clj

Sync (upsert) entity data — returns {:count n}.

Data keys accept kebab-case (normalized to snake_case). Pass :returning true for the written records; mint ids with synthigy.client.core/new-xid when you need them up front.

Sync (upsert) entity data — returns {:count n}.

Data keys accept kebab-case (normalized to snake_case). Pass
`:returning true` for the written records; mint ids with
`synthigy.client.core/new-xid` when you need them up front.
cljs

Sync (upsert) entity data — resolves to {:count n}. Pass :returning true for the written records.

Sync (upsert) entity data — resolves to {:count n}. Pass `:returning true`
for the written records.
source (clj)source (cljs)raw docstring

tokenclj/s≠

(token)
(token {:keys [audience]})
clj

Resolve a bearer access token via the client's provider.

Without opts: default token (for /data — Synthigy itself). With :audience "svc": a token for another service that trusts Synthigy as IdP.

Resolve a bearer access token via the client's provider.

Without opts: default token (for /data — Synthigy itself).
With `:audience "svc"`: a token for another service that trusts
Synthigy as IdP.
cljs

Resolve a bearer access token via the client's provider. Returns a promise — the CLJS transport is async throughout.

Resolve a bearer access token via the client's provider.
Returns a promise — the CLJS transport is async throughout.
source (clj)source (cljs)raw docstring

watchclj/s≠

(watch interest on-event & {:as _opts})
clj

Open a live SSE subscription for interest and stream change events to on-event. Mirrors the TypeScript SDK's client.watch(interest).

Registers with the client's shared multiplexer: ALL watch / watch-query on a client share ONE /data/events stream and ONE consolidated subscription (their interests are unioned). No clobber, one connection.

interest is a map with any of: :records — record xids (data-track) :entities — entity names (entity-track: any change to the entity) :relations — relation labels (relation-track) :operations — optional op filter for the record track

Non-blocking. Returns a handle map: :interest (fn []) → current interest :set-interest (fn [interest]) → replace interest (re-unions + re-POSTs) :add (fn [xids]) → add record xids :remove (fn [xids]) → remove record xids :close (fn []) → deregister (stream stops when last closes)

Events are notification-only — refetch via search/get/batch on receipt (RLS-correct notify-then-refetch).

on-event runs on its OWN dedicated thread, decoupled via a sliding-buffered core.async channel — a slow or blocking callback (I/O, a lock, a slow UI redraw) delays only ITS OWN delivery, never another watcher's, and never the shared SSE stream. Overflow (100 pending events) drops the oldest for that watcher only.

(def w (watch {:entities ["user"]} (fn [ev] (prn ev)))) ((:add w) ["some-xid"]) ((:close w))

Open a live SSE subscription for `interest` and stream change events to
`on-event`. Mirrors the TypeScript SDK's `client.watch(interest)`.

Registers with the client's shared multiplexer: ALL watch / watch-query
on a client share ONE /data/events stream and ONE consolidated
subscription (their interests are unioned). No clobber, one connection.

`interest` is a map with any of:
  :records    — record xids (data-track)
  :entities   — entity names (entity-track: any change to the entity)
  :relations  — relation labels (relation-track)
  :operations — optional op filter for the record track

Non-blocking. Returns a handle map:
  :interest     (fn [])         → current interest
  :set-interest (fn [interest]) → replace interest (re-unions + re-POSTs)
  :add          (fn [xids])     → add record xids
  :remove       (fn [xids])     → remove record xids
  :close        (fn [])         → deregister (stream stops when last closes)

Events are notification-only — refetch via search/get/batch on receipt
(RLS-correct notify-then-refetch).

`on-event` runs on its OWN dedicated thread, decoupled via a
sliding-buffered core.async channel — a slow or blocking callback
(I/O, a lock, a slow UI redraw) delays only ITS OWN delivery, never
another watcher's, and never the shared SSE stream. Overflow (100
pending events) drops the oldest for that watcher only.

  (def w (watch {:entities ["user"]} (fn [ev] (prn ev))))
  ((:add w) ["some-xid"])
  ((:close w))
cljs

Open a live SSE subscription for interest and stream change events to on-event. Mirrors the TypeScript SDK's client.watch(interest) and the CLJ SDK's watch — same interest shape, same shared multiplexer.

interest is a map with any of: :records — record xids (data-track) :entities — entity names (entity-track: any change to the entity) :relations — relation labels (relation-track) :operations — optional op filter for the record track

Non-blocking. Returns a handle map: :interest (fn []) → current interest :set-interest (fn [interest]) → replace interest (re-unions + re-POSTs) :add (fn [xids]) → add record xids :remove (fn [xids]) → remove record xids :close (fn []) → deregister (stream stops when last closes)

Events are notification-only — refetch via search/get/batch on receipt (RLS-correct notify-then-refetch).

(def w (watch {:entities ["user"]} (fn [ev] (js/console.log ev)))) ((:add w) ["some-xid"]) ((:close w))

Open a live SSE subscription for `interest` and stream change events to
`on-event`. Mirrors the TypeScript SDK's `client.watch(interest)` and
the CLJ SDK's `watch` — same interest shape, same shared multiplexer.

`interest` is a map with any of:
  :records    — record xids (data-track)
  :entities   — entity names (entity-track: any change to the entity)
  :relations  — relation labels (relation-track)
  :operations — optional op filter for the record track

Non-blocking. Returns a handle map:
  :interest     (fn [])         → current interest
  :set-interest (fn [interest]) → replace interest (re-unions + re-POSTs)
  :add          (fn [xids])     → add record xids
  :remove       (fn [xids])     → remove record xids
  :close        (fn [])         → deregister (stream stops when last closes)

Events are notification-only — refetch via search/get/batch on receipt
(RLS-correct notify-then-refetch).

  (def w (watch {:entities ["user"]} (fn [ev] (js/console.log ev))))
  ((:add w) ["some-xid"])
  ((:close w))
source (clj)source (cljs)raw docstring

watch-queryclj/s≠

(watch-query entity args selection & {:as opts})
clj

Live, RLS-scoped result-set for a search. Clojure-flavored: returns an ATOM holding the current result vector, kept fresh in the background — deref it, add-watch it, close-watch! it.

(def msgs (watch-query "Chat Message" {:-where {...}} [:content] :acting-as user-xid)) @msgs ; current results (add-watch msgs :ui (fn [_ _ old new] ...)) ; react to changes (close-watch! msgs) ; stop

Mirrors the TS SDK's watchQuery: snapshot via search, register the entity interest with the shared multiplexer, and on each matching event do a coalesced re-run + reset! the atom (notify-then-refetch — RLS stays correct because the refetch carries the same :acting-as). Many watch-queries with different :acting-as / interests now coexist on ONE client and ONE stream — the multiplexer unions their interests.

Options: :acting-as / :key-format — forwarded to the snapshot + every refetch :relations / :records — widen the watch interest beyond the entity :entity-track — false to DROP the entity-wide interest and watch only :records/:relations (default true). Use with :records to scope a live view to a "room" — e.g. a group record whose link events fire when children attach to it. :track-rows — also keep the CURRENT result rows' xids in the interest, re-registered after every refetch. With :entity-track false this makes edits/deletes of already-visible rows fire (their events carry only the row's own xid). :debounce-ms — coalesce window for bursts (default 80)

Live, RLS-scoped result-set for a `search`. Clojure-flavored: returns an
ATOM holding the current result vector, kept fresh in the background —
deref it, `add-watch` it, `close-watch!` it.

  (def msgs (watch-query "Chat Message" {:-where {...}} [:content]
                         :acting-as user-xid))
  @msgs                                          ; current results
  (add-watch msgs :ui (fn [_ _ old new] ...))    ; react to changes
  (close-watch! msgs)                            ; stop

Mirrors the TS SDK's watchQuery: snapshot via `search`, register the
entity interest with the shared multiplexer, and on each matching event
do a coalesced re-run + reset! the atom (notify-then-refetch — RLS stays
correct because the refetch carries the same :acting-as). Many
watch-queries with different :acting-as / interests now coexist on ONE
client and ONE stream — the multiplexer unions their interests.

Options:
  :acting-as / :key-format — forwarded to the snapshot + every refetch
  :relations / :records    — widen the watch interest beyond the entity
  :entity-track            — false to DROP the entity-wide interest and
                             watch only :records/:relations (default true).
                             Use with :records to scope a live view to a
                             "room" — e.g. a group record whose link
                             events fire when children attach to it.
  :track-rows              — also keep the CURRENT result rows' xids in
                             the interest, re-registered after every
                             refetch. With :entity-track false this makes
                             edits/deletes of already-visible rows fire
                             (their events carry only the row's own xid).
  :debounce-ms             — coalesce window for bursts (default 80)
cljs

Live, RLS-scoped result-set for a search. Returns a Promise of an ATOM holding the current result vector, kept fresh in the background — await it once, then deref/add-watch/close-watch! it like any atom.

(p/let [msgs (watch-query "Chat Message" {:-where {...}} [:content])] (add-watch msgs :ui (fn [_ _ old new] ...)) (js/console.log @msgs))

Mirrors the TS SDK's watchQuery / the CLJ SDK's watch-query: snapshot via search, register the entity interest with the shared multiplexer, and on each matching event do a coalesced re-run + reset! the atom (notify-then-refetch — RLS stays correct because the refetch carries the same :acting-as). Many watch-queries now coexist on ONE client and ONE stream — the multiplexer unions their interests.

Options: same as the CLJ SDK's watch-query (:acting-as/:key-format, :relations/:records, :entity-track, :track-rows, :debounce-ms).

Live, RLS-scoped result-set for a `search`. Returns a Promise of an
ATOM holding the current result vector, kept fresh in the background —
await it once, then deref/add-watch/close-watch! it like any atom.

  (p/let [msgs (watch-query "Chat Message" {:-where {...}} [:content])]
    (add-watch msgs :ui (fn [_ _ old new] ...))
    (js/console.log @msgs))

Mirrors the TS SDK's watchQuery / the CLJ SDK's watch-query: snapshot
via `search`, register the entity interest with the shared multiplexer,
and on each matching event do a coalesced re-run + reset! the atom
(notify-then-refetch — RLS stays correct because the refetch carries the
same :acting-as). Many watch-queries now coexist on ONE client and ONE
stream — the multiplexer unions their interests.

Options: same as the CLJ SDK's watch-query (:acting-as/:key-format,
:relations/:records, :entity-track, :track-rows, :debounce-ms).
source (clj)source (cljs)raw docstring

watch-schemaclj/s

(watch-schema on-event & {:keys [raw]})

Stream model-deploy events over the shared multiplexer. Mirrors the TS SDK's client.watchSchema(). :raw true watches the raw deployed model; default the runtime model. Returns a handle with :close.

Stream model-deploy events over the shared multiplexer. Mirrors the TS
SDK's client.watchSchema(). `:raw true` watches the raw deployed model;
default the runtime model. Returns a handle with :close.
source (clj)source (cljs)raw docstring

watch-sql-templateclj/s≠

(watch-sql-template template params & {:keys [entities] :as opts})
clj

Live, RLS-scoped result for a SQL template — the ad-hoc twin of the watch-<name> a codegen'd @watch sql-template emits. Returns the same closeable atom as watch-query.

(def stats (watch-sql-template "SELECT count(*) AS n FROM {movie}" nil :entities ["Movie"])) @stats ; current rows (close-watch! stats) ; stop

:entities is required: a template has no root entity, so there is nothing to infer the multiplexer interest from. Otherwise takes watch-query's options.

Live, RLS-scoped result for a SQL template — the ad-hoc twin of the
`watch-<name>` a codegen'd `@watch` sql-template emits. Returns the same
closeable atom as `watch-query`.

  (def stats (watch-sql-template "SELECT count(*) AS n FROM {movie}" nil
                                 :entities ["Movie"]))
  @stats                                         ; current rows
  (close-watch! stats)                           ; stop

`:entities` is required: a template has no root entity, so there is nothing
to infer the multiplexer interest from. Otherwise takes `watch-query`'s
options.
cljs

Live, RLS-scoped result for a SQL template — the ad-hoc twin of the watch-<name> a codegen'd @watch sql-template emits. Returns the same Promise<atom> as watch-query; close-watch! stops it.

:entities is required: a template has no root entity, so there is nothing to infer the multiplexer interest from. Otherwise takes watch-query's options.

Live, RLS-scoped result for a SQL template — the ad-hoc twin of the
`watch-<name>` a codegen'd `@watch` sql-template emits. Returns the same
Promise<atom> as `watch-query`; `close-watch!` stops it.

`:entities` is required: a template has no root entity, so there is nothing
to infer the multiplexer interest from. Otherwise takes `watch-query`'s
options.
source (clj)source (cljs)raw 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