Liking cljdoc? Tell your friends :D

supabase.core.client

Client configuration for interacting with Supabase.

Creates and manages immutable client maps containing connection options, service URLs, and configuration for your Supabase project. The client is a plain Clojure map validated with Malli schemas.

Usage

(require '[supabase.core.client :as client])

;; Create a client with defaults
(client/make-client "https://abc.supabase.co" "my-api-key")

;; Create a client with options
(client/make-client "https://abc.supabase.co" "my-api-key"
  :db {:schema "another"}
  :auth {:flow-type "pkce"}
  :global {:headers {"custom-header" "custom-value"}})

;; Update the access token for authenticated requests
(client/update-access-token client "new-token")

Client Map Structure

{:base-url       "https://abc.supabase.co"
 :api-key        "my-api-key"
 :access-token   "my-api-key"
 :auth-url       "https://abc.supabase.co/auth/v1"
 :database-url   "https://abc.supabase.co/rest/v1"
 :storage-url    "https://abc.supabase.co/storage/v1"
 :functions-url  "https://abc.supabase.co/functions/v1"
 :realtime-url   "https://abc.supabase.co/realtime/v1"
 :db             {:schema "public"}
 :client-info    {"supabase-clj" "0.7.0"}
 :global         {:headers {}}
 :auth           {:auto-refresh-token true, :flow-type "implicit", ...}
 :storage        {:use-new-hostname false}}

The :client-info map is rendered into the structured x-client-info header on every request (see format-client-info). Service modules register themselves via with-client-info.

See https://supabase.com/docs/reference/javascript/initializing

Client configuration for interacting with Supabase.

Creates and manages immutable client maps containing connection options,
service URLs, and configuration for your Supabase project. The client is
a plain Clojure map validated with Malli schemas.

## Usage

    (require '[supabase.core.client :as client])

    ;; Create a client with defaults
    (client/make-client "https://abc.supabase.co" "my-api-key")

    ;; Create a client with options
    (client/make-client "https://abc.supabase.co" "my-api-key"
      :db {:schema "another"}
      :auth {:flow-type "pkce"}
      :global {:headers {"custom-header" "custom-value"}})

    ;; Update the access token for authenticated requests
    (client/update-access-token client "new-token")

## Client Map Structure

    {:base-url       "https://abc.supabase.co"
     :api-key        "my-api-key"
     :access-token   "my-api-key"
     :auth-url       "https://abc.supabase.co/auth/v1"
     :database-url   "https://abc.supabase.co/rest/v1"
     :storage-url    "https://abc.supabase.co/storage/v1"
     :functions-url  "https://abc.supabase.co/functions/v1"
     :realtime-url   "https://abc.supabase.co/realtime/v1"
     :db             {:schema "public"}
     :client-info    {"supabase-clj" "0.7.0"}
     :global         {:headers {}}
     :auth           {:auto-refresh-token true, :flow-type "implicit", ...}
     :storage        {:use-new-hostname false}}

The `:client-info` map is rendered into the structured `x-client-info`
header on every request (see [[format-client-info]]). Service modules
register themselves via [[with-client-info]].

See https://supabase.com/docs/reference/javascript/initializing
raw docstring

supabase.core.error

Anomaly-based error handling for the Supabase Clojure SDK.

Errors are represented as plain maps following the cognitect/anomalies convention. This avoids tagged tuples and exceptions by default, matching the data-driven philosophy of libraries like cognitect/aws-api.

Anomaly Categories

The SDK maps HTTP status codes and domain errors to these categories:

  • :cognitect.anomalies/incorrect — bad request, validation failure (4xx client errors)
  • :cognitect.anomalies/forbidden — authentication/authorization failure (401, 403)
  • :cognitect.anomalies/not-found — resource not found (404)
  • :cognitect.anomalies/conflict — resource already exists (409)
  • :cognitect.anomalies/busy — rate limited, resource locked (423, 429)
  • :cognitect.anomalies/unavailable — server error, service unavailable (5xx)
  • :cognitect.anomalies/fault — unexpected server-side failure

Structure

An anomaly map always contains :cognitect.anomalies/category and may include:

  • :cognitect.anomalies/message — human-readable error description
  • :supabase/service — originating service (:auth, :storage, etc.)
  • :supabase/code — semantic error code keyword (e.g. :not-found)
  • :http/status — original HTTP status code
  • :http/body — response body (parsed or raw)
  • :http/headers — response headers

Usage

(require '[supabase.core.error :as error])

;; Check if a result is an error
(error/anomaly? result)

;; Create an anomaly from an HTTP response
(error/from-http-response 404 {:message "Not Found"} :storage)

;; Create a domain-specific anomaly
(error/anomaly :cognitect.anomalies/incorrect
  {:supabase/service :auth
   :cognitect.anomalies/message "Invalid credentials"})
Anomaly-based error handling for the Supabase Clojure SDK.

Errors are represented as plain maps following the cognitect/anomalies convention.
This avoids tagged tuples and exceptions by default, matching the data-driven
philosophy of libraries like cognitect/aws-api.

## Anomaly Categories

The SDK maps HTTP status codes and domain errors to these categories:

  - `:cognitect.anomalies/incorrect`   — bad request, validation failure (4xx client errors)
  - `:cognitect.anomalies/forbidden`   — authentication/authorization failure (401, 403)
  - `:cognitect.anomalies/not-found`   — resource not found (404)
  - `:cognitect.anomalies/conflict`    — resource already exists (409)
  - `:cognitect.anomalies/busy`        — rate limited, resource locked (423, 429)
  - `:cognitect.anomalies/unavailable` — server error, service unavailable (5xx)
  - `:cognitect.anomalies/fault`       — unexpected server-side failure

## Structure

An anomaly map always contains `:cognitect.anomalies/category` and may include:

  - `:cognitect.anomalies/message` — human-readable error description
  - `:supabase/service`            — originating service (`:auth`, `:storage`, etc.)
  - `:supabase/code`               — semantic error code keyword (e.g. `:not-found`)
  - `:http/status`                 — original HTTP status code
  - `:http/body`                   — response body (parsed or raw)
  - `:http/headers`                — response headers

## Usage

    (require '[supabase.core.error :as error])

    ;; Check if a result is an error
    (error/anomaly? result)

    ;; Create an anomaly from an HTTP response
    (error/from-http-response 404 {:message "Not Found"} :storage)

    ;; Create a domain-specific anomaly
    (error/anomaly :cognitect.anomalies/incorrect
      {:supabase/service :auth
       :cognitect.anomalies/message "Invalid credentials"})
raw docstring

supabase.core.http

Composable HTTP request builder and executor for Supabase services.

Requests are built as plain maps using a threading-friendly API, then executed through a supabase.core.transport/Transport. The default transport wraps Hato on the JVM and js/fetch on ClojureScript; tests and integrators can swap it.

Request map

A request map contains:

  • :method — HTTP method keyword (:get :post :put :patch :delete)
  • :url — fully resolved URL string
  • :headers — map of header name to value
  • :query — map of query parameter name to value
  • :body — request body (map, string, bytes, File, InputStream, or nil)
  • :multipart — vector of multipart parts (mutually exclusive with :body)
  • :response-as — :string (default), :byte-array, :stream, :reader (:stream and :reader are JVM-only)
  • :decoder — fn from raw body to parsed body (default JSON for :string)
  • :error-parser — fn [status body headers service] → anomaly map
  • :log? — emit debug/error log lines for this request
  • :timeout — per-request timeout (ms)
  • :transport — explicit transport instance (overrides client transport)
  • :retries — retry policy override (true, integer, or opts map; false disables). Overrides the client :retries.
  • :on-event — telemetry fn for this request (overrides client :on-event)
  • :service — originating service keyword (:auth, :storage, etc.)
  • :client — reference to the client map

Usage

(require '[supabase.core.http :as http])

;; Build and execute a request
(-> (http/request client)
    (http/with-service-url :auth-url "/signup")
    (http/with-method :post)
    (http/with-body {:email "user@example.com" :password "secret"})
    (http/execute))
;; => {:status 200, :body {...}, :headers {...}} on success
;; => anomaly map on HTTP error (status >= 400)

Platforms

execute is synchronous and JVM-only (ClojureScript throws). On ClojureScript use execute-async, which returns a js/Promise instead of a CompletableFuture.

Composable HTTP request builder and executor for Supabase services.

Requests are built as plain maps using a threading-friendly API, then
executed through a [[supabase.core.transport/Transport]]. The default
transport wraps Hato on the JVM and `js/fetch` on ClojureScript; tests
and integrators can swap it.

## Request map

A request map contains:

  - `:method`        — HTTP method keyword (`:get` `:post` `:put` `:patch` `:delete`)
  - `:url`           — fully resolved URL string
  - `:headers`       — map of header name to value
  - `:query`         — map of query parameter name to value
  - `:body`          — request body (map, string, bytes, File, InputStream, or nil)
  - `:multipart`     — vector of multipart parts (mutually exclusive with `:body`)
  - `:response-as`   — `:string` (default), `:byte-array`, `:stream`, `:reader`
                       (`:stream` and `:reader` are JVM-only)
  - `:decoder`       — fn from raw body to parsed body (default JSON for `:string`)
  - `:error-parser`  — fn `[status body headers service]` → anomaly map
  - `:log?`          — emit debug/error log lines for this request
  - `:timeout`       — per-request timeout (ms)
  - `:transport`     — explicit transport instance (overrides client transport)
  - `:retries`       — retry policy override (`true`, integer, or opts map;
                       `false` disables). Overrides the client `:retries`.
  - `:on-event`      — telemetry fn for this request (overrides client
                       `:on-event`)
  - `:service`       — originating service keyword (`:auth`, `:storage`, etc.)
  - `:client`        — reference to the client map

## Usage

    (require '[supabase.core.http :as http])

    ;; Build and execute a request
    (-> (http/request client)
        (http/with-service-url :auth-url "/signup")
        (http/with-method :post)
        (http/with-body {:email "user@example.com" :password "secret"})
        (http/execute))
    ;; => {:status 200, :body {...}, :headers {...}} on success
    ;; => anomaly map on HTTP error (status >= 400)

## Platforms

`execute` is synchronous and JVM-only (ClojureScript throws). On
ClojureScript use [[execute-async]], which returns a `js/Promise`
instead of a `CompletableFuture`.
raw docstring

supabase.core.json

Platform JSON seam for the Supabase SDK.

All JSON encoding/decoding in supabase.core goes through this namespace so the same code runs on both platforms:

  • JVM — jsonista (Jackson), keywordized keys.
  • ClojureScript — js/JSON with js->clj keywordization.

Both sides decode object keys to keywords and throw on malformed input; callers that want lenient parsing should use read-string-safe.

Platform JSON seam for the Supabase SDK.

All JSON encoding/decoding in `supabase.core` goes through this
namespace so the same code runs on both platforms:

  - **JVM** — jsonista (Jackson), keywordized keys.
  - **ClojureScript** — `js/JSON` with `js->clj` keywordization.

Both sides decode object keys to keywords and throw on malformed
input; callers that want lenient parsing should use [[read-string-safe]].
raw docstring

supabase.core.retry

Pure retry policy for transient HTTP failures in the Supabase Clojure SDK.

This namespace decides whether and how long to wait before retrying a failed request. It performs no sleeping and no I/O: supabase.core.http calls these functions from its retry loop and owns the actual waiting.

Transient failures

A failure is worth retrying when it is likely to resolve on its own:

  • HTTP statuses 429, 502, 503, 504 (transient-status?)
  • Transport exceptions: connection refused, connect/read timeouts, no route to host, reset or broken-pipe sockets, and unexpected EOF (transient-exception?, which also walks the cause chain)

Delay computation

Delays combine two sources, with the server always winning:

  1. A Retry-After response header, when present and parseable (retry-after-ms), either as delay-seconds or an RFC 1123 HTTP-date.
  2. Exponential backoff with full jitter (backoff-ms), capped at :max-delay-ms.

next-delay-ms applies that precedence. merge-opts resolves client-level and request-level retry options against default-opts.

Usage

(require '[supabase.core.retry :as retry])

(retry/transient-status? 503)              ;; => true
(retry/retry-after-ms {"retry-after" "3"}) ;; => 3000
(retry/backoff-ms 2)                       ;; => long in [0, 400]
(retry/next-delay-ms 2 {"retry-after" "3"}) ;; => 3000
(retry/merge-opts {:max-attempts 5} true)  ;; => {:max-attempts 5, ...}
Pure retry policy for transient HTTP failures in the Supabase Clojure SDK.

This namespace decides *whether* and *how long* to wait before retrying a
failed request. It performs no sleeping and no I/O: `supabase.core.http`
calls these functions from its retry loop and owns the actual waiting.

## Transient failures

A failure is worth retrying when it is likely to resolve on its own:

  - HTTP statuses 429, 502, 503, 504 (`transient-status?`)
  - Transport exceptions: connection refused, connect/read timeouts, no
    route to host, reset or broken-pipe sockets, and unexpected EOF
    (`transient-exception?`, which also walks the cause chain)

## Delay computation

Delays combine two sources, with the server always winning:

  1. A `Retry-After` response header, when present and parseable
     (`retry-after-ms`), either as delay-seconds or an RFC 1123 HTTP-date.
  2. Exponential backoff with full jitter (`backoff-ms`), capped at
     `:max-delay-ms`.

`next-delay-ms` applies that precedence. `merge-opts` resolves client-level
and request-level retry options against `default-opts`.

## Usage

    (require '[supabase.core.retry :as retry])

    (retry/transient-status? 503)              ;; => true
    (retry/retry-after-ms {"retry-after" "3"}) ;; => 3000
    (retry/backoff-ms 2)                       ;; => long in [0, 400]
    (retry/next-delay-ms 2 {"retry-after" "3"}) ;; => 3000
    (retry/merge-opts {:max-attempts 5} true)  ;; => {:max-attempts 5, ...}
raw docstring

supabase.core.transport

Pluggable HTTP transport for the Supabase Clojure SDK.

All HTTP traffic is executed through an implementation of the Transport protocol. The default implementation wraps hato.client on the JVM and js/fetch on ClojureScript; service modules (auth, storage, postgrest, functions, realtime) never call either directly.

Why a protocol? Three reasons:

  1. Testability — tests inject a fake transport that returns canned responses without touching the network.
  2. Pooling — on the JVM, a per-client transport can own a single HttpClient instance with custom timeouts, pool sizing, and HTTP version selection.
  3. Adapters — callers who need clj-http, http-kit, or a custom HTTP stack can implement Transport and inject it via the client map (:transport) or per request.

Request format

A transport receives a lower-level request map produced by supabase.core.http:

{:method      :post
 :url         "https://abc.supabase.co/auth/v1/token"
 :headers     {"authorization" "Bearer ..." ...}
 :query-params {"grant_type" "password"}
 :body        "{\"email\":\"a@b.com\"}" ;; string | bytes | File | InputStream
 :multipart   [{:name "file" :content #object[File ...]
                :content-type "image/png" :file-name "a.png"}]
 :as          :string ;; :string | :byte-array | :stream | :reader
 :timeout     30000}  ;; optional

On ClojureScript only :string and :byte-array are meaningful for :as (the latter yields a js/Uint8Array), and :body must be a string. Multipart bodies are assembled with js/FormData.

Response format

The transport must return a map with at minimum:

{:status  200
 :headers {"content-type" "application/json" ...}
 :body    "{...}" ;; type depends on :as
 :uri     "..."   ;; optional, but recommended for logging
 :request {...}}    ;; optional echo of the request for debugging

Exceptions are caught by supabase.core.http, not by the transport, and converted to anomalies via supabase.core.error/from-exception.

Async

On the JVM, execute-async returns a java.util.concurrent.CompletionStage that resolves to a response map. On ClojureScript it returns a js/Promise. The same exception handling rules apply. ClojureScript has no synchronous execute (fetch is async-only); calling it throws.

Pluggable HTTP transport for the Supabase Clojure SDK.

All HTTP traffic is executed through an implementation of the
[[Transport]] protocol. The default implementation wraps `hato.client`
on the JVM and `js/fetch` on ClojureScript; service modules (auth,
storage, postgrest, functions, realtime) never call either directly.

Why a protocol? Three reasons:

  1. **Testability** — tests inject a fake transport that returns
     canned responses without touching the network.
  2. **Pooling** — on the JVM, a per-client transport can own a single
     `HttpClient` instance with custom timeouts, pool sizing, and
     HTTP version selection.
  3. **Adapters** — callers who need clj-http, http-kit, or a custom
     HTTP stack can implement [[Transport]] and inject it via the
     client map (`:transport`) or per request.

## Request format

A transport receives a lower-level request map produced by
`supabase.core.http`:

    {:method      :post
     :url         "https://abc.supabase.co/auth/v1/token"
     :headers     {"authorization" "Bearer ..." ...}
     :query-params {"grant_type" "password"}
     :body        "{\"email\":\"a@b.com\"}" ;; string | bytes | File | InputStream
     :multipart   [{:name "file" :content #object[File ...]
                    :content-type "image/png" :file-name "a.png"}]
     :as          :string ;; :string | :byte-array | :stream | :reader
     :timeout     30000}  ;; optional

On ClojureScript only `:string` and `:byte-array` are meaningful for
`:as` (the latter yields a `js/Uint8Array`), and `:body` must be a
string. Multipart bodies are assembled with `js/FormData`.

## Response format

The transport must return a map with at minimum:

    {:status  200
     :headers {"content-type" "application/json" ...}
     :body    "{...}" ;; type depends on :as
     :uri     "..."   ;; optional, but recommended for logging
     :request {...}}    ;; optional echo of the request for debugging

Exceptions are caught by `supabase.core.http`, not by the transport,
and converted to anomalies via `supabase.core.error/from-exception`.

## Async

On the JVM, `execute-async` returns a
`java.util.concurrent.CompletionStage` that resolves to a response map.
On ClojureScript it returns a `js/Promise`. The same exception handling
rules apply. ClojureScript has no synchronous `execute` (fetch is
async-only); calling it throws.
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