# 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(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 ```ts 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 ```ts import { flattenRows, wrapQueryError, } from "@suaveplan/surrealdb/adapter/query-helpers"; async function safeQuery( client: { query(sql: string): Promise }, sql: string ): Promise { try { const results = await client.query(sql); return flattenRows(results); } catch (err) { throw wrapQueryError(err, sql); } } ``` ## API Reference ### `paramsToRecord(params?: readonly unknown[]): Record | 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 []: ", { cause })` where `cause` is preserved only for `Error` instances. ### `flattenRows(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.