Files
skills/docs/persistence/database/surrealdb/src/adapter/query-helpers/query-helpers.md
2026-05-29 08:20:56 +01:00

3.2 KiB

query-helpers

(no submodules)

Purpose

query-helpers holds the small, stateless utility functions shared by every public method on SurrealAdapter and its sibling CRUD/transaction modules: positional-parameter conversion, error normalisation, and result-shape flattening.

Centralising these helpers keeps adapter.ts focused on the DatabaseAdapter lifecycle (connect/disconnect/state) and lets the CRUD and transaction modules each consume the same battle-tested implementations without duplication.

Features

  • paramsToRecord(params?) — turn readonly unknown[] into { p0, p1, ... } (or undefined for empty input)
  • wrapQueryError(err, sql) — coerce arbitrary thrown values into structured SurrealError(QUERY_FAILED) with cause preservation
  • flattenRows<T>(results) — flatten the surrealdb.js [[row, ...]] nested shape into T[]
  • All helpers are pure, allocation-free on the empty-input fast paths, and free of any client/IO coupling

Usage: Basic Example

import {
    paramsToRecord,
    wrapQueryError,
    flattenRows,
} from "@suaveplan/surrealdb/adapter/query-helpers";

const vars = paramsToRecord(["alice", 42]);
// vars === { p0: "alice", p1: 42 }

try {
    // ...driver call...
} catch (err) {
    throw wrapQueryError(err, "SELECT * FROM user");
}

Usage: Advanced Example

import {
    flattenRows,
    wrapQueryError,
} from "@suaveplan/surrealdb/adapter/query-helpers";

async function safeQuery<T>(
    client: { query<U>(sql: string): Promise<U[]> },
    sql: string
): Promise<T[]> {
    try {
        const results = await client.query<T>(sql);
        return flattenRows<T>(results);
    } catch (err) {
        throw wrapQueryError(err, sql);
    }
}

API Reference

paramsToRecord(params?: readonly unknown[]): Record<string, unknown> | undefined

Returns undefined when params is missing or empty. Otherwise returns a fresh record keyed p0, p1, ... in order.

wrapQueryError(err: unknown, sql: string): SurrealError

Returns err unchanged when it is already a SurrealError. Otherwise wraps it as SurrealError(SURREAL.QUERY_FAILED, "Query failed [<sql>]: <message>", { cause }) where cause is preserved only for Error instances.

flattenRows<T>(results: unknown): T[]

If results is [[...]] returns the inner array. If results is [T, ...] returns it as-is. For empty or non-array inputs returns [].

Implementation Notes

  • paramsToRecord allocates a fresh object on every call to keep callers safe from accidental mutation; the empty-input branch avoids the allocation entirely.
  • wrapQueryError mirrors the original behaviour from SurrealAdapter._wrapQueryError — it must NOT swallow SurrealError subclasses, since callers rely on the code discriminator surviving the await boundary.
  • flattenRows accepts unknown so call-sites can pass the raw driver return value without an upfront cast; the structural test exhausts both observed shapes (single-statement and multi-statement query responses).
  • These functions are deliberately leaf utilities: they import only ../../errors/index.js, never the driver or adapter. That keeps the dependency graph acyclic when the CRUD and transaction modules depend on them.