Core Systems Libraries for Google Workspace API wrappers.
Provides shared credential management, data converters, and request execution helpers used by all clj-goog-workspace-* sub-libraries.
Converters:
Client construction:
Request execution:
All three executors accept an optional opts map with :read-timeout-ms and/or :connect-timeout-ms to apply per-request HTTP timeouts (overriding the client-level defaults set by http-request-initializer).
Core Systems Libraries for Google Workspace API wrappers.
Provides shared credential management, data converters, and request
execution helpers used by all clj-goog-workspace-* sub-libraries.
Converters:
- ->clj — Google API model object (GenericJson / Map / List) -> Clojure
data with kebab-case keyword keys.
- ->camel-str — keyword/string -> camelCase string (API field/option names).
- clj->json — Clojure map (kebab-case keywords) -> java.util.HashMap
(camelCase string keys) for use with GenericJson.putAll.
Client construction:
- http-request-initializer — build an HttpRequestInitializer that wraps
GoogleCredentials with HTTP timeout
configuration. Used by every <service>-client
builder in the workspace.
Request execution:
- json-factory — shared GsonFactory used for typed-model JSON round-trip.
- execute-get — issue a get/patch/create request; returns {:data ...} or
{:error ...}.
- execute-list — issue a list request; returns {:data [...] :next-page-token
"..."} or {:error ...}.
- execute-delete — issue a delete/clear (void) request; returns {:data
:deleted} or {:error ...}.
All three executors accept an optional opts map with :read-timeout-ms and/or
:connect-timeout-ms to apply per-request HTTP timeouts (overriding the
client-level defaults set by http-request-initializer).(->camel-str k)Convert a keyword or string to a camelCase string. Used for translating Clojure-side kebab-case keywords to Google API field and option names.
Convert a keyword or string to a camelCase string. Used for translating Clojure-side kebab-case keywords to Google API field and option names.
(->clj v)Recursively convert a Google API model object (GenericJson / java.util.Map / java.util.List) to a Clojure data structure with kebab-case keyword keys.
Recursively convert a Google API model object (GenericJson / java.util.Map / java.util.List) to a Clojure data structure with kebab-case keyword keys.
(->enum-str v)Coerce a keyword or string to an uppercase SCREAMING_SNAKE_CASE enum string suitable for Google API enum parameters. Hyphens become underscores and the entire string is uppercased — :user-entered -> "USER_ENTERED", "user-entered" -> "USER_ENTERED", "USER_ENTERED" -> "USER_ENTERED".
Coerce a keyword or string to an uppercase SCREAMING_SNAKE_CASE enum string suitable for Google API enum parameters. Hyphens become underscores and the entire string is uppercased — :user-entered -> "USER_ENTERED", "user-entered" -> "USER_ENTERED", "USER_ENTERED" -> "USER_ENTERED".
(application-default-credentials)Return Application Default Credentials (ADC). Delegates to GoogleCredentials.getApplicationDefault().
Return Application Default Credentials (ADC). Delegates to GoogleCredentials.getApplicationDefault().
(clj->json m)Recursively convert a Clojure map (kebab-case keyword keys) to a java.util.HashMap (camelCase string keys) for use with GenericJson.putAll.
Keyword keys are camelCased via ->camel-str; string keys are preserved verbatim. This lets callers pass arbitrary string keys for Map<String,String> body fields (e.g. Cloud Identity's :labels, whose keys are dotted/slashed strings like "cloudidentity.googleapis.com/groups.discussion_forum").
Recursively convert a Clojure map (kebab-case keyword keys) to a java.util.HashMap (camelCase string keys) for use with GenericJson.putAll. Keyword keys are camelCased via ->camel-str; string keys are preserved verbatim. This lets callers pass arbitrary string keys for Map<String,String> body fields (e.g. Cloud Identity's :labels, whose keys are dotted/slashed strings like "cloudidentity.googleapis.com/groups.discussion_forum").
Default per-client HTTP connect timeout (30s). 3× OkHttp's industry default — tight enough for dead hosts, generous enough for legitimate network variance.
Default per-client HTTP connect timeout (30s). 3× OkHttp's industry default — tight enough for dead hosts, generous enough for legitimate network variance.
Default per-client HTTP read timeout (120s). Bounds dead-socket pathology to two minutes while leaving headroom for legitimately slow Workspace API calls (large batchUpdate, full list pages, export creation).
Default per-client HTTP read timeout (120s). Bounds dead-socket pathology to two minutes while leaving headroom for legitimately slow Workspace API calls (large batchUpdate, full list pages, export creation).
(execute-delete request)(execute-delete request {:keys [read-timeout-ms connect-timeout-ms] :as opts})Execute a delete/clear request (void return) and return {:data :deleted} or {:error ...}. With :read-timeout-ms or :connect-timeout-ms, routes through buildHttpRequest so the per-request timeout overrides the client-level default.
Execute a delete/clear request (void return) and return {:data :deleted}
or {:error ...}. With :read-timeout-ms or :connect-timeout-ms, routes
through buildHttpRequest so the per-request timeout overrides the
client-level default.(execute-get request)(execute-get request {:keys [read-timeout-ms connect-timeout-ms] :as opts})Execute a get/patch/create request and return {:data {...}} or {:error ...}.
When opts contains :read-timeout-ms or :connect-timeout-ms, route through the manual buildHttpRequest path so the per-request timeout can be applied (overriding any client-level default). Otherwise fall through to the convenience .execute().
Execute a get/patch/create request and return {:data {...}} or {:error ...}.
When opts contains :read-timeout-ms or :connect-timeout-ms, route through
the manual buildHttpRequest path so the per-request timeout can be applied
(overriding any client-level default). Otherwise fall through to the
convenience .execute().(execute-list request items-key)(execute-list request
items-key
{:keys [read-timeout-ms connect-timeout-ms] :as opts})Execute a list request and return {:data [...] :next-page-token "..."} or {:error ...}. :next-page-token is absent when there are no further pages.
items-key — the kebab-case keyword of the collection field in the response (e.g. :items, :files, :messages).
Execute a list request and return {:data [...] :next-page-token "..."} or
{:error ...}. :next-page-token is absent when there are no further pages.
items-key — the kebab-case keyword of the collection field in the response
(e.g. :items, :files, :messages).(execute-list-all wrapper-fn base-opts)Exhaust pagination on a wrapper function. wrapper-fn takes an opts map
and returns the execute-list-shape result
({:data [...] :next-page-token ...?} or {:error ...}).
base-opts is threaded through every call; this helper overlays
:page-token on each iteration.
Returns {:data [...all items concatenated...]} on full success. On the first failed page, returns the page's :error map merged with :pages-completed n and :items-collected-so-far m for diagnostics — partial results are NOT exposed in :data on error. Callers needing resumable pagination or best-effort partial results should use the lower-level execute-list directly.
Example: (csl/execute-list-all (fn [opts] (licensing/list-license-assignments-for-product client product-id customer-id opts)) {:max-results 1000})
Setting :max-results (or :page-size, per API) to the API maximum in base-opts minimizes round-trips; this helper does not auto-size pages.
Exhaust pagination on a wrapper function. `wrapper-fn` takes an opts map
and returns the `execute-list`-shape result
({:data [...] :next-page-token ...?} or {:error ...}).
`base-opts` is threaded through every call; this helper overlays
`:page-token` on each iteration.
Returns {:data [...all items concatenated...]} on full success. On the
first failed page, returns the page's :error map merged with
:pages-completed n and :items-collected-so-far m for diagnostics —
partial results are NOT exposed in :data on error. Callers needing
resumable pagination or best-effort partial results should use the
lower-level execute-list directly.
Example:
(csl/execute-list-all
(fn [opts] (licensing/list-license-assignments-for-product
client product-id customer-id opts))
{:max-results 1000})
Setting :max-results (or :page-size, per API) to the API maximum in
base-opts minimizes round-trips; this helper does not auto-size pages.(http-request-initializer credentials)(http-request-initializer credentials
{:keys [read-timeout-ms connect-timeout-ms]
:or {read-timeout-ms default-read-timeout-ms
connect-timeout-ms default-connect-timeout-ms}})Returns an HttpRequestInitializer that wraps GoogleCredentials with HTTP timeout configuration. Used internally by every <service>-client builder; consumers do not normally call this directly.
Opts: :read-timeout-ms default 120000 (120s); time to wait for data after the connection is established :connect-timeout-ms default 30000 (30s); time to wait for TCP handshake completion
Caveat — setReadTimeout does not catch every hang. The JDK applies SO_TIMEOUT to socket reads after the connection is established, but TLS-handshake reads (initial handshake, renegotiation) may park without honoring it (jstack confirms parking on SSLSocketInputRecord.readHeader until the OS TCP keepalive timer fires, ~2 hours on macOS). :connect-timeout-ms catches dead-handshake; :read-timeout-ms catches dead-data-flow once the handshake completed. Both are required for full coverage.
Returns an HttpRequestInitializer that wraps GoogleCredentials with HTTP
timeout configuration. Used internally by every <service>-client builder;
consumers do not normally call this directly.
Opts:
:read-timeout-ms default 120000 (120s); time to wait for data after
the connection is established
:connect-timeout-ms default 30000 (30s); time to wait for TCP handshake
completion
Caveat — setReadTimeout does not catch every hang. The JDK applies SO_TIMEOUT
to socket reads after the connection is established, but TLS-handshake reads
(initial handshake, renegotiation) may park without honoring it (jstack
confirms parking on SSLSocketInputRecord.readHeader until the OS TCP
keepalive timer fires, ~2 hours on macOS). :connect-timeout-ms catches
dead-handshake; :read-timeout-ms catches dead-data-flow once the handshake
completed. Both are required for full coverage.Shared GsonFactory instance. Used by every app library for typed-model JSON round-trip — (.fromString json-factory (.toString json-factory ...) Class).
Shared GsonFactory instance. Used by every app library for typed-model JSON round-trip — (.fromString json-factory (.toString json-factory ...) Class).
(scoped-delegated-credentials scopes subject)Returns ADC credentials scoped and delegated for domain-wide delegation (DWD). The underlying credential must be a service account with DWD enabled in Google Admin console.
Returns ADC credentials scoped and delegated for domain-wide delegation (DWD). The underlying credential must be a service account with DWD enabled in Google Admin console. - scopes: collection of OAuth 2.0 scope strings - subject: email address of the Google Workspace user to impersonate
(user-credentials client-id client-secret refresh-token)Build OAuth 2.0 user credentials from a client ID, client secret, and refresh token. Returns {:data UserCredentials} or {:error ...}.
Obtain the refresh token via the REPL bootstrap recipe in goog.workspace.csl.oauth-bootstrap (dev/ source path).
Build OAuth 2.0 user credentials from a client ID, client secret, and refresh token.
Returns {:data UserCredentials} or {:error ...}.
Obtain the refresh token via the REPL bootstrap recipe in
goog.workspace.csl.oauth-bootstrap (dev/ source path).(wait-for-operation poll-fn)(wait-for-operation poll-fn
{:keys [poll-interval-ms timeout-ms operation-name]
:or {poll-interval-ms 5000 timeout-ms 600000}})Poll a long-running Operation until it reports :done true, or until :timeout-ms elapses.
poll-fn — a zero-arg function returning {:data <operation-map>} or {:error ...}. Typical use: a closure over a library-specific get-operation, e.g. #(get-operation client op-name (select-keys opts [:read-timeout-ms]))
opts:
Returns {:data <operation-map>} when the operation reports done=true, or {:error ...} on timeout or on the first polling failure. Note the returned operation map may itself contain :error — that's the operation's own failure result, distinct from a polling failure.
Poll a long-running Operation until it reports :done true, or until
:timeout-ms elapses.
poll-fn — a zero-arg function returning {:data <operation-map>} or
{:error ...}. Typical use: a closure over a library-specific
get-operation, e.g.
#(get-operation client op-name (select-keys opts [:read-timeout-ms]))
opts:
- :poll-interval-ms — int, milliseconds between polls (default 5000)
- :timeout-ms — int, overall deadline in ms (default 600000 = 10 min)
- :operation-name — descriptive; surfaces in the timeout :error map
Returns {:data <operation-map>} when the operation reports done=true, or
{:error ...} on timeout or on the first polling failure. Note the returned
operation map may itself contain :error — that's the operation's own
failure result, distinct from a polling failure.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 |