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

synthigy.client.auth

clj

Token providers for the Synthigy client.

A provider is a map {:token-fn f :invalidate-fn g}:

:token-fn — 0-arg returning a default bearer token. Optional 1-arg variant (token-fn audience) returns a token for another service that trusts Synthigy as IdP. :invalidate-fn — 0-arg clearing the provider's cache so the next token-fn call refetches. 1-arg variant clears a specific audience. Optional.

The SDK calls token-fn before every request; on HTTP 401 it calls invalidate-fn (if present) and retries once. How tokens are fetched, cached, or refreshed is entirely the provider's concern — this ns ships two sensible defaults:

(static token) — one fixed token, no refresh (oauth {:client-id ...}) — client-credentials flow, caches per audience, refreshes before expiry

Token providers for the Synthigy client.

A provider is a map `{:token-fn f :invalidate-fn g}`:

  :token-fn     — 0-arg returning a default bearer token.
                  Optional 1-arg variant `(token-fn audience)` returns
                  a token for another service that trusts Synthigy as IdP.
  :invalidate-fn — 0-arg clearing the provider's cache so the next
                   `token-fn` call refetches. 1-arg variant clears
                   a specific audience. Optional.

The SDK calls `token-fn` before every request; on HTTP 401 it calls
`invalidate-fn` (if present) and retries once. How tokens are fetched,
cached, or refreshed is entirely the provider's concern — this ns ships
two sensible defaults:

  (static token)                — one fixed token, no refresh
  (oauth {:client-id ...})      — client-credentials flow, caches per
                                  audience, refreshes before expiry
cljs

Token providers for the Synthigy CLJS client.

A provider is a map {:token-fn f :invalidate-fn g}:

:token-fn — 0-arg returning a bearer token (string or Promise<string>). Optional 1-arg variant (token-fn audience) for IdP federation. :invalidate-fn — 0/1-arg clearing the provider's cache so the next token-fn call refetches.

The SDK calls token-fn before every request; on HTTP 401 it calls invalidate-fn (if present) and retries once. The two defaults shipped here cover 90% of SDK use — teams wanting OIDC / PKCE / silent renew should plug their own :token-fn / :invalidate-fn in.

Token providers for the Synthigy CLJS client.

A provider is a map `{:token-fn f :invalidate-fn g}`:

  :token-fn     — 0-arg returning a bearer token (string or Promise<string>).
                  Optional 1-arg variant `(token-fn audience)` for IdP
                  federation.
  :invalidate-fn — 0/1-arg clearing the provider's cache so the next
                   `token-fn` call refetches.

The SDK calls `token-fn` before every request; on HTTP 401 it calls
`invalidate-fn` (if present) and retries once. The two defaults shipped
here cover 90% of SDK use — teams wanting OIDC / PKCE / silent renew
should plug their own `:token-fn` / `:invalidate-fn` in.
raw docstring

synthigy.client.core

Pure core of the Synthigy client — everything that is genuinely platform-free: the client map (construction + the connected *client*), wire operation builders, result unpacking, tree composition, and the subscription wire shapes. No transport here; synthigy.client (.clj / .cljs) owns the verbs.

Pure core of the Synthigy client — everything that is genuinely
platform-free: the client map (construction + the connected `*client*`),
wire operation builders, result unpacking, tree composition, and the
subscription wire shapes. No transport here; `synthigy.client` (.clj /
.cljs) owns the verbs.
raw docstring

synthigy.client.filter

Filter-condition helpers — mirror the Go (Eq/Neq/…) and JS (eq/neq/…) SDKs for parity. In Clojure these are thin sugar over plain maps; you can always write the literal ({:_eq v}) directly. The combinators and/or/not are where they earn their keep.

Alias as f and place conditions in a where map keyed by field:

(require '[synthigy.client.filter :as f]) (client/search c :user {:-where {:active (f/eq true) :age (f/gt 18)}} [:name]) (client/search c :user {:-where (f/or {:role (f/eq "admin")} {:role (f/eq "owner")})} [:name])

Filter-condition helpers — mirror the Go (Eq/Neq/…) and JS (eq/neq/…)
SDKs for parity. In Clojure these are thin sugar over plain maps; you
can always write the literal (`{:_eq v}`) directly. The combinators
and/or/not are where they earn their keep.

Alias as `f` and place conditions in a where map keyed by field:

  (require '[synthigy.client.filter :as f])
  (client/search c :user {:-where {:active (f/eq true)
                                   :age    (f/gt 18)}} [:name])
  (client/search c :user {:-where (f/or {:role (f/eq "admin")}
                                        {:role (f/eq "owner")})} [:name])
raw docstring

synthigy.client.http

clj

HTTP transport for Synthigy client.

ONE PROCESS, ONE CLIENT: every fn here reads the connected client from synthigy.client.core/*client* — nothing below the public API passes a client around (the Clojure server-restart idiom: connect! destroys the old client and installs the new one, so the root var is always the only live client). Each request resolves the client ONCE and uses that snapshot for token + retry + hooks.

Tokens come from the client's :token-fn (0-arg for default token, 1-arg for audience-scoped). On 401 the client's :invalidate-fn (if any) is called to force a token refresh, then the request is retried once. If that still fails with 401, UNAUTHORIZED is thrown.

HTTP transport for Synthigy client.

ONE PROCESS, ONE CLIENT: every fn here reads the connected client from
`synthigy.client.core/*client*` — nothing below the public API passes a
client around (the Clojure server-restart idiom: `connect!` destroys the
old client and installs the new one, so the root var is always the only
live client). Each request resolves the client ONCE and uses that
snapshot for token + retry + hooks.

Tokens come from the client's `:token-fn` (0-arg for default token,
1-arg for audience-scoped). On 401 the client's `:invalidate-fn` (if
any) is called to force a token refresh, then the request is retried
once. If that still fails with 401, UNAUTHORIZED is thrown.
cljs

HTTP transport for the Synthigy CLJS client.

Uses js/fetch — works in every modern browser and Node 18+. Promise- returning throughout; callers use promesa (p/let) or .then.

Tokens come from the client's :token-fn (0-arg for default token, 1-arg for audience-scoped). On 401 the client's :invalidate-fn (if any) is called to force a token refresh, then the request is retried once. If that still fails with 401, UNAUTHORIZED is thrown.

HTTP transport for the Synthigy CLJS client.

Uses js/fetch — works in every modern browser and Node 18+. Promise-
returning throughout; callers use promesa (`p/let`) or `.then`.

Tokens come from the client's `:token-fn` (0-arg for default token,
1-arg for audience-scoped). On 401 the client's `:invalidate-fn` (if
any) is called to force a token refresh, then the request is retried
once. If that still fails with 401, UNAUTHORIZED is thrown.
raw docstring

synthigy.client.key

Key normalization for the Synthigy client.

Converts kebab-case and camelCase keys to snake_case for the /data endpoint wire format.

Key normalization for the Synthigy client.

Converts kebab-case and camelCase keys to snake_case
for the /data endpoint wire format.
raw docstring

synthigy.client.retry

clj

Opt-in retry helper for transient failures.

Scope: wrap a thunk that calls the SDK, retry on transport errors and 5xx responses, leave 4xx alone. NOT composable with write ops at the caller's discretion — retrying a sync after a timeout could double- apply if the server processed the first attempt. Use on idempotent calls (search / get / count / schema / sql-template).

Retryable: :code TRANSPORT_ERROR — network blip, DNS, timeout :code HTTP_ERROR + :status 502/503/504 — gateway / upstream hiccup

NOT retryable (propagates on first failure): :code UNAUTHORIZED / FORBIDDEN — auth problem; retry won't help :code HTTP_ERROR with 4xx — caller bug; retry won't help :code UNKNOWN_ENTITY / operation errors — app-level failures

Opt-in retry helper for transient failures.

Scope: wrap a thunk that calls the SDK, retry on transport errors and
5xx responses, leave 4xx alone. NOT composable with write ops at the
caller's discretion — retrying a `sync` after a timeout could double-
apply if the server processed the first attempt. Use on idempotent
calls (search / get / count / schema / sql-template).

Retryable:
  :code TRANSPORT_ERROR  — network blip, DNS, timeout
  :code HTTP_ERROR + :status 502/503/504 — gateway / upstream hiccup

NOT retryable (propagates on first failure):
  :code UNAUTHORIZED / FORBIDDEN — auth problem; retry won't help
  :code HTTP_ERROR with 4xx      — caller bug; retry won't help
  :code UNKNOWN_ENTITY / operation errors — app-level failures
cljs

Opt-in retry helper for transient failures in the browser SDK.

Scope matches the CLJ sibling: wrap a promise-returning thunk, retry transport errors and 5xx responses, leave 4xx alone. Use only on idempotent calls.

Retryable: :code TRANSPORT_ERROR — network blip, DNS, timeout :code HTTP_ERROR + :status 502/503/504 — gateway / upstream hiccup

NOT retryable (propagates on first failure): :code UNAUTHORIZED / FORBIDDEN — auth problem :code HTTP_ERROR with 4xx — caller bug app-level failures

Opt-in retry helper for transient failures in the browser SDK.

Scope matches the CLJ sibling: wrap a promise-returning thunk, retry
transport errors and 5xx responses, leave 4xx alone. Use only on
idempotent calls.

Retryable:
  :code TRANSPORT_ERROR  — network blip, DNS, timeout
  :code HTTP_ERROR + :status 502/503/504 — gateway / upstream hiccup

NOT retryable (propagates on first failure):
  :code UNAUTHORIZED / FORBIDDEN — auth problem
  :code HTTP_ERROR with 4xx      — caller bug
  app-level failures
raw docstring

synthigy.client.selection

Selection normalization for the Synthigy client.

Converts user-friendly selection shorthand into the wire format expected by the /data endpoint.

Selection normalization for the Synthigy client.

Converts user-friendly selection shorthand into the wire format
expected by the /data endpoint.
raw docstring

synthigy.client.sse

SSE listener for the Synthigy CLJS client.

Uses fetch streaming (ReadableStream + TextDecoder) — supports Authorization headers, matches sdk/js. Callback-driven: caller provides on-event; listen returns a 0-arg stop function that aborts the connection.

Auto-reconnects with Last-Event-ID + exponential backoff (1s → 30s).

SSE listener for the Synthigy CLJS client.

Uses fetch streaming (ReadableStream + TextDecoder) — supports
Authorization headers, matches sdk/js. Callback-driven: caller
provides `on-event`; `listen` returns a 0-arg `stop` function that
aborts the connection.

Auto-reconnects with Last-Event-ID + exponential backoff (1s → 30s).
raw docstring

synthigy.client.subscriptions

clj

RAW server-side subscription-set management — ADVANCED / low-level.

Prefer synthigy.client/watch and synthigy.client/watch-query: the watch multiplexer manages this same server-side set automatically (union of all watch interests, re-asserted on every SSE reconnect).

WARNING: the server keeps ONE subscription set per client identity and /data/subscription/set is FULL-REPLACE. Calling these fns while any watch/watch-query is active on the same client CLOBBERS the multiplexer's set (and vice versa) — live updates silently stop. Use this namespace only when you consume /data/events yourself via synthigy.client/listen and no watches are open.

RAW server-side subscription-set management — ADVANCED / low-level.

Prefer `synthigy.client/watch` and `synthigy.client/watch-query`: the watch
multiplexer manages this same server-side set automatically (union of all
watch interests, re-asserted on every SSE reconnect).

WARNING: the server keeps ONE subscription set per client identity and
`/data/subscription/set` is FULL-REPLACE. Calling these fns while any
watch/watch-query is active on the same client CLOBBERS the multiplexer's
set (and vice versa) — live updates silently stop. Use this namespace only
when you consume `/data/events` yourself via `synthigy.client/listen` and
no watches are open.
cljs

RAW server-side subscription-set management — ADVANCED / low-level (ClojureScript, promise-returning).

Prefer the watch layer: the server keeps ONE subscription set per client identity and /data/subscription/set is FULL-REPLACE — mixing this with any watch machinery on the same client clobbers its set. Use only when consuming /data/events yourself via synthigy.client/listen.

RAW server-side subscription-set management — ADVANCED / low-level
(ClojureScript, promise-returning).

Prefer the watch layer: the server keeps ONE subscription set per client
identity and `/data/subscription/set` is FULL-REPLACE — mixing this with
any watch machinery on the same client clobbers its set. Use only when
consuming `/data/events` yourself via `synthigy.client/listen`.
raw docstring

synthigy.gen

Code generator: a folder of .xsql → committed Clojure source.

Connects to a running Synthigy backend ONCE (op:describe = the XSQL compiler) and emits one namespace per XSQL @namespace, with a named, documented function per operation. The generated code carries NO parser and needs NO backend at runtime — it embeds each op's compiled XSQL source string and sends it via synthigy.client. Connection is a BUILD-time dependency, like Prisma/sqlc/genqlient; commit the output and it runs offline forever after.

clj -X:gen :dir '"synthigy"' :out '"src"'
:ns-prefix myapp.ops :endpoint '"http://localhost:7887"'

Auth for the pull: THE APP'S OWN client credentials (:client-id/:client-secret or SYNTHIGY_CLIENT_ID/SYNTHIGY_CLIENT_SECRET) — /schema + describe are IAM-filtered per principal, so generating as the app makes the generated contract exactly what the app can do at runtime (a personal/dev identity would generate a surface the app can't honor). Grant the client schema:read (or the broader dataset:load). :token / SYNTHIGY_TOKEN and authless remain for bare dev servers. Regenerate any time you edit an .xsql — the diff shows exactly what changed.

Code generator: a folder of .xsql → committed Clojure source.

Connects to a running Synthigy backend ONCE (op:describe = the XSQL
compiler) and emits one namespace per XSQL @namespace, with a named,
documented function per operation. The generated code carries NO parser and
needs NO backend at runtime — it embeds each op's compiled XSQL source string
and sends it via synthigy.client. Connection is a BUILD-time dependency, like
Prisma/sqlc/genqlient; commit the output and it runs offline forever after.

  clj -X:gen :dir '"synthigy"' :out '"src"' \
             :ns-prefix myapp.ops :endpoint '"http://localhost:7887"'

Auth for the pull: THE APP'S OWN client credentials (:client-id/:client-secret
or SYNTHIGY_CLIENT_ID/SYNTHIGY_CLIENT_SECRET) — /schema + describe are
IAM-filtered per principal, so generating as the app makes the generated
contract exactly what the app can do at runtime (a personal/dev identity
would generate a surface the app can't honor). Grant the client `schema:read`
(or the broader `dataset:load`). :token / SYNTHIGY_TOKEN and authless remain
for bare dev servers. Regenerate any time you edit an .xsql — the diff shows
exactly what changed.
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