Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
# query-helpers
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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
```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<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.