Athena

API Reference

Contract-level reference for Athena.js client creation, results, builders, query AST types, and supporting subpath exports.

This page covers the stable contract surfaces you use when wiring Athena.js into an application. It intentionally stays grouped by runtime domain so it remains readable inside the docs site. Use Method surface reference when you want the broader grouped inventory across auth, React, cookies, and utils.

Exports at a glance

Package entrypoint @xylex-group/athena exports:

  • client/runtime constructors
  • query-builder types and operations
  • error helpers
  • typed schema helpers (defineModel, defineSchema, defineDatabase, defineRegistry)
  • generator configuration and rendering helpers
  • query AST types for findMany(...)
  • auth bindings on client.auth

For a high-level workflow, see:

Core result type

Most runtime operations resolve to:

interface AthenaResult<T> {
  data: T | null
  error: AthenaResultError | null
  statusText?: string | null
  errorDetails?: AthenaGatewayErrorDetails | null
  status: number
  count?: number | null
  raw: unknown
}

data is null on failure. error is a structured object on failure and null on success.

interface AthenaResultError {
  message: string
  code: string | null
  athenaCode: string
  gatewayCode?: string | null
  kind: string
  category: string
  retryable: boolean
  details: unknown | null
  hint: string | null
  status: number
  statusText: string | null
  constraint?: string
  table?: string
  operation?: string
  endpoint?: string
  method?: string
  requestId?: string
  cause?: string
  raw: unknown
}

errorDetails remains for compatibility, but new code should normally read error.message, error.kind, error.code, and related fields directly.

Client construction

createClient

import { createClient } from "@xylex-group/athena";

const athena = createClient(
  url: string,
  apiKey: string,
  options?: {
    client?: string
    headers?: Record<string, string>
    backend?: BackendConfig | BackendType
    auth?: AthenaAuthClientConfig
    experimental?: AthenaClientExperimentalOptions
  },
): AthenaSdkClientWithAuth

AthenaClient

import { AthenaClient } from "@xylex-group/athena";

const athena = AthenaClient.fromEnvironment();
  • fromEnvironment() reads:
    • ATHENA_URL or ATHENA_GATEWAY_URL
    • ATHENA_API_KEY or ATHENA_GATEWAY_API_KEY
  • throws if url/key are missing

Builder API (AthenaClient.builder())

interface AthenaClientBuilder {
  url(url: string): AthenaClientBuilder
  key(apiKey: string): AthenaClientBuilder
  backend(backend: BackendConfig | BackendType): AthenaClientBuilder
  client(clientName: string): AthenaClientBuilder
  headers(headers: Record<string, string>): AthenaClientBuilder
  auth(config: AthenaAuthClientConfig): AthenaClientBuilder
  experimental(options: AthenaClientExperimentalOptions): AthenaClientBuilder
  options(options: AthenaCreateClientOptions): AthenaClientBuilder
  healthTracking(enabled: boolean): AthenaClientBuilder
  build(): AthenaSdkClientWithAuth
}

Useful notes:

  • auth(...) configures the client.auth.* surface
  • experimental(...) is where traceQueries and findManyAst live; on the current Athena server contract, findManyAst is a client-side compatibility option and top-level AST /gateway/fetch bodies are not supported public input
  • options(...) applies the same options object accepted by createClient(...)
  • options(...) merges staged headers, auth, and experimental config
  • healthTracking(...) is a metadata flag kept on the builder surface

Backend constants and type

Backend export:

const Backend = {
  Athena: { type: "athena" },
  Postgrest: { type: "postgrest" },
  PostgreSQL: { type: "postgresql" },
  ScyllaDB: { type: "scylladb" },
} as const

BackendType is "athena" | "postgrest" | "postgresql" | "scylladb".

Query runtime API

AthenaSdkClient

interface AthenaSdkClient {
  from<Row = unknown, Insert = Partial<Row>, Update = Partial<Insert>>(
    table: string,
  ): TableQueryBuilder<Row, Insert, Update>
  db: AthenaDbModule
  rpc<Row = unknown, Args extends Record<string, unknown> = Record<string, unknown>>(
    fn: string,
    args?: Args,
    options?: AthenaRpcCallOptions,
  ): RpcQueryBuilder<Row>
  query<Row = unknown>(query: string, options?: AthenaGatewayCallOptions): Promise<AthenaResult<Row[]>>
}

AthenaSdkClientWithAuth extends this shape with:

interface AthenaSdkClientWithAuth extends AthenaSdkClient {
  auth: AthenaAuthBindings
}

db mirrors the same runtime surface in function form:

  • db.from(...)
  • db.select(...)
  • db.insert(...)
  • db.upsert(...)
  • db.update(...)
  • db.delete(...)
  • db.rpc(...)
  • db.query(...)

Filter and modifier chain methods

FilterChain<T> is implemented by TableQueryBuilder, SelectChain, and UpdateChain:

interface FilterChain<Self> {
  eq(column: string, value: AthenaConditionValue): Self
  eqCast(column: string, value: AthenaConditionValue, cast: string): Self
  eqUuid(column: string, value: string): Self
  match(filters: Record<string, AthenaConditionValue>): Self
  range(from: number, to: number): Self
  limit(count: number): Self
  offset(count: number): Self
  currentPage(value: number): Self
  pageSize(value: number): Self
  totalPages(value: number): Self
  order(column: string, options?: { ascending?: boolean }): Self
  gt(column: string, value: AthenaConditionValue): Self
  gte(column: string, value: AthenaConditionValue): Self
  lt(column: string, value: AthenaConditionValue): Self
  lte(column: string, value: AthenaConditionValue): Self
  neq(column: string, value: AthenaConditionValue): Self
  like(column: string, value: AthenaConditionValue): Self
  ilike(column: string, value: AthenaConditionValue): Self
  is(column: string, value: AthenaConditionValue): Self
  in(column: string, values: AthenaConditionArrayValue): Self
  contains(column: string, values: AthenaConditionArrayValue): Self
  containedBy(column: string, values: AthenaConditionArrayValue): Self
  not(columnOrExpression: string, operator?: AthenaConditionOperator, value?: AthenaConditionValue): Self
  or(expression: string): Self
}

eq() auto-switches to text-aware typed comparison when values look like UUIDs and the column name matches identifier patterns such as id, *_id, or *uuid*.

TableQueryBuilder

interface TableQueryBuilder<Row, Insert = Partial<Row>, Update = Partial<Insert>, TContext = unknown>
  extends FilterChain<TableQueryBuilder<Row, Insert, Update, TContext>> {
  select<T = Row>(columns?: string | string[], options?: AthenaGatewayCallOptions): SelectChain<Row, T>
  findMany<const TSelect extends AthenaSelectShape>(
    options: AthenaFindManyOptions<Row, TSelect>,
  ): Promise<AthenaResult<Array<AthenaFindManyResult<Row, TSelect, TContext>>>>
  insert(values: Insert, options?: AthenaGatewayCallOptions): MutationQuery<Row>
  insert(values: Insert[], options?: AthenaGatewayCallOptions): MutationQuery<Row[]>
  upsert(
    values: Insert,
    options?: AthenaGatewayCallOptions & { updateBody?: Update; onConflict?: string | string[] },
  ): MutationQuery<Row>
  upsert(
    values: Insert[],
    options?: AthenaGatewayCallOptions & { updateBody?: Update; onConflict?: string | string[] },
  ): MutationQuery<Row[]>
  update(values: Update, options?: AthenaGatewayCallOptions): UpdateChain<Row>
  delete(options?: AthenaGatewayCallOptions & { resourceId?: string }): MutationQuery<Row | null>
  single<T = Row>(columns?: string | string[], options?: AthenaGatewayCallOptions): Promise<AthenaResult<T | null>>
  maybeSingle<T = Row>(columns?: string | string[], options?: AthenaGatewayCallOptions): Promise<AthenaResult<T | null>>
  reset(): TableQueryBuilder<Row, Insert, Update, TContext>
}

Notes:

  • .select() returns a SelectChain, not a promise
  • .findMany(...) is eager and promise-based
  • .single() / .maybeSingle() are convenience read terminators
  • .delete() throws if no id/resource_id filter and no resourceId option are present
  • .reset() clears accumulated filters and modifiers only

SelectChain

interface SelectChain<Row, SelectedRow = Row>
  extends FilterChain<SelectChain<Row, SelectedRow>>,
    PromiseLike<AthenaResult<SelectedRow[]>> {
  single<T = SelectedRow>(
    columns?: string | string[],
    options?: AthenaGatewayCallOptions,
  ): Promise<AthenaResult<T | null>>
  maybeSingle<T = SelectedRow>(
    columns?: string | string[],
    options?: AthenaGatewayCallOptions,
  ): Promise<AthenaResult<T | null>>
}

then/await executes the read immediately.

MutationQuery

interface MutationQuery<Result> extends PromiseLike<AthenaResult<Result>> {
  select(columns?: string | string[], options?: AthenaGatewayCallOptions): Promise<AthenaResult<Result>>
  returning(columns?: string | string[], options?: AthenaGatewayCallOptions): Promise<AthenaResult<Result>>
  single(
    columns?: string | string[],
    options?: AthenaGatewayCallOptions,
  ): Promise<AthenaResult<MutationSingleResult<Result>>>
  maybeSingle(
    columns?: string | string[],
    options?: AthenaGatewayCallOptions,
  ): Promise<AthenaResult<MutationSingleResult<Result>>>
}

MutationSingleResult<Result> resolves to Result | null for both scalar and array mutation payloads.

UpdateChain

interface UpdateChain<Row> extends FilterChain<UpdateChain<Row>>, MutationQuery<Row[]> {}

RpcQueryBuilder

interface RpcQueryBuilder<Row> extends PromiseLike<AthenaResult<Row[]>> {
  eq(column: string, value: AthenaConditionValue): RpcQueryBuilder<Row>
  neq(column: string, value: AthenaConditionValue): RpcQueryBuilder<Row>
  gt(column: string, value: AthenaConditionValue): RpcQueryBuilder<Row>
  gte(column: string, value: AthenaConditionValue): RpcQueryBuilder<Row>
  lt(column: string, value: AthenaConditionValue): RpcQueryBuilder<Row>
  lte(column: string, value: AthenaConditionValue): RpcQueryBuilder<Row>
  like(column: string, value: AthenaConditionValue): RpcQueryBuilder<Row>
  ilike(column: string, value: AthenaConditionValue): RpcQueryBuilder<Row>
  is(column: string, value: AthenaConditionValue): RpcQueryBuilder<Row>
  in(column: string, values: AthenaConditionArrayValue): RpcQueryBuilder<Row>
  order(column: string, options?: { ascending?: boolean }): RpcQueryBuilder<Row>
  limit(count: number): RpcQueryBuilder<Row>
  offset(count: number): RpcQueryBuilder<Row>
  range(from: number, to: number): RpcQueryBuilder<Row>
  select(columns?: string | string[], options?: AthenaRpcCallOptions): Promise<AthenaResult<Row[]>>
  single<T = Row>(columns?: string | string[], options?: AthenaRpcCallOptions): Promise<AthenaResult<T | null>>
  maybeSingle<T = Row>(columns?: string | string[], options?: AthenaRpcCallOptions): Promise<AthenaResult<T | null>>
}

athena.rpc(fn, args, options) requires a non-empty function name.

findMany(...) AST types

findMany(...) uses these exported types:

interface AthenaRelationSelectNode<TSelect extends AthenaSelectShape = AthenaSelectShape> {
  select: TSelect
  as?: string
  via?: string
}

type AthenaSelectShape = Record<string, true | AthenaRelationSelectNode<AthenaSelectShape>>

type AthenaOrderBy<Row> =
  | { column: keyof Row & string; ascending?: boolean }
  | Partial<Record<keyof Row & string, "asc" | "desc" | "ascending" | "descending" | boolean | { ascending?: boolean }>>

interface AthenaFindManyOptions<Row, TSelect extends AthenaSelectShape> {
  select: TSelect
  where?: AthenaWhere<Row>
  orderBy?: AthenaOrderBy<Row>
  limit?: number
}

Read findMany AST and server contract for transport details and compatibility notes.

Gateway-level options and payloads

AthenaGatewayCallOptions

Used by builder .select/.insert/.update/.delete payloads and query methods.

interface AthenaGatewayCallOptions {
  baseUrl?: string
  apiKey?: string
  client?: string
  backend?: BackendConfig | BackendType
  publishEvent?: string
  headers?: Record<string, string>
  userId?: string | null
  organizationId?: string | null
  schema?: string
  count?: "exact" | "planned" | "estimated"
  head?: boolean
  defaultToNull?: boolean
  stripNulls?: boolean
  onConflict?: string | string[]
  updateBody?: Record<string, unknown>
}

AthenaRpcCallOptions

interface AthenaRpcCallOptions extends AthenaGatewayCallOptions {
  count?: "exact" | "planned" | "estimated"
  get?: boolean
}

Condition and sort primitives

type AthenaConditionValue = string | number | boolean | null
type AthenaConditionArrayValue = Array<AthenaConditionValue>
type AthenaConditionOperator =
  | "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "like" | "ilike" | "is"
  | "in" | "contains" | "containedBy" | "not" | "or"

React integration (@xylex-group/athena/react)

useAthenaGateway

import { useAthenaGateway } from "@xylex-group/athena/react";
interface AthenaGatewayHookConfig {
  baseUrl?: string
  apiKey?: string
  headers?: Record<string, string>
  backend?: BackendConfig | BackendType
  client?: string
  userId?: string | null
  organizationId?: string | null
  publishEvent?: string
}

interface AthenaGatewayHookResult {
  fetchGateway<T>(payload: AthenaFetchPayload, options?: AthenaGatewayCallOptions): Promise<AthenaGatewayResponse<T>>
  insertGateway<T>(payload: AthenaInsertPayload, options?: AthenaGatewayCallOptions): Promise<AthenaGatewayResponse<T>>
  updateGateway<T>(payload: AthenaUpdatePayload, options?: AthenaGatewayCallOptions): Promise<AthenaGatewayResponse<T>>
  deleteGateway<T>(payload: AthenaDeletePayload, options?: AthenaGatewayCallOptions): Promise<AthenaGatewayResponse<T>>
  rpcGateway<T>(payload: AthenaRpcPayload, options?: AthenaRpcCallOptions): Promise<AthenaGatewayResponse<T>>
  isLoading: boolean
  error: string | null
  lastRequest: AthenaGatewayCallLog | null
  lastResponse: AthenaGatewayResponseLog | null
  baseUrl: string
}

Important difference from builder results: AthenaGatewayHookResult.error is still string | null.

Query runtime

  • createAthenaQueryClient(config?)
  • AthenaQueryClientProvider
  • useAthenaQueryClient
  • useQuery(options)
  • useMutation(options)
  • attachStateAdapter(client, adapter)

Runtime defaults:

  • cache.mode = "none" by default
  • query retry defaults to 0
  • mutation retry defaults to 0
  • identical inflight query keys are deduplicated

Supporting subpath exports

@xylex-group/athena/utils

Use this subpath for small operational helpers:

  • slugify
  • trimTrailingSlashes
  • parseBooleanFlag
  • isLocalHostname
  • clearAuthCookies
  • proxyRequestHeaders

@xylex-group/athena/cookies

Use this subpath when you need auth/session cookie helpers such as:

  • getSessionCookie
  • setSessionCookie
  • deleteSessionCookie
  • createSessionStore
  • getCookieCache

Error and helper exports

Service-layer code usually combines AthenaResult<T> with:

  • isOk
  • unwrap
  • unwrapRows
  • unwrapOne
  • requireSuccess
  • requireAffected
  • normalizeAthenaError
  • coerceInt
  • assertInt
  • withRetry

Validation commands

In the Athena.js package repo:

pnpm typecheck
pnpm check:all

Use these after API-level changes, generated-contract work, or public surface updates.