turbine-orm 0.49.0 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -39
- package/dist/cjs/adapters/cockroachdb.d.ts +39 -0
- package/dist/cjs/adapters/index.d.ts +110 -0
- package/dist/cjs/adapters/yugabytedb.d.ts +51 -0
- package/dist/cjs/cli/config.d.ts +181 -0
- package/dist/cjs/cli/config.js +32 -6
- package/dist/cjs/cli/destructive.d.ts +38 -0
- package/dist/cjs/cli/index.d.ts +359 -0
- package/dist/cjs/cli/index.js +228 -56
- package/dist/cjs/cli/loader.d.ts +61 -0
- package/dist/cjs/cli/mcp.d.ts +42 -0
- package/dist/cjs/cli/migrate.d.ts +356 -0
- package/dist/cjs/cli/migrate.js +131 -40
- package/dist/cjs/cli/observe-ui.d.ts +1 -0
- package/dist/cjs/cli/observe-ui.js +14 -5
- package/dist/cjs/cli/observe.d.ts +25 -0
- package/dist/cjs/cli/observe.js +49 -12
- package/dist/cjs/cli/pii-tags.d.ts +53 -0
- package/dist/cjs/cli/prisma-report.d.ts +33 -0
- package/dist/cjs/cli/prisma-report.js +73 -0
- package/dist/cjs/cli/prisma-resolve.d.ts +106 -0
- package/dist/cjs/cli/prisma-resolve.js +1 -0
- package/dist/cjs/cli/prisma-schema.d.ts +176 -0
- package/dist/cjs/cli/prisma-schema.js +82 -4
- package/dist/cjs/cli/rate-limit.d.ts +32 -0
- package/dist/cjs/cli/rate-limit.js +45 -0
- package/dist/cjs/cli/studio-demo.d.ts +43 -0
- package/dist/cjs/cli/studio-ui.generated.d.ts +1 -0
- package/dist/cjs/cli/studio.d.ts +207 -0
- package/dist/cjs/cli/studio.js +136 -71
- package/dist/cjs/cli/ui.d.ts +73 -0
- package/dist/cjs/cli/ui.js +51 -9
- package/dist/cjs/client.d.ts +837 -0
- package/dist/cjs/client.js +3 -0
- package/dist/cjs/dialect.d.ts +516 -0
- package/dist/cjs/dialect.js +37 -12
- package/dist/cjs/errors.d.ts +370 -0
- package/dist/cjs/generate.d.ts +137 -0
- package/dist/cjs/generate.js +39 -6
- package/dist/cjs/index-advisor.d.ts +153 -0
- package/dist/cjs/index-stats.d.ts +384 -0
- package/dist/cjs/index.d.ts +55 -0
- package/dist/cjs/index.js +7 -2
- package/dist/cjs/introspect.d.ts +269 -0
- package/dist/cjs/mssql.d.ts +232 -0
- package/dist/cjs/mssql.js +6 -0
- package/dist/cjs/mysql.d.ts +173 -0
- package/dist/cjs/mysql.js +16 -0
- package/dist/cjs/nested-write.d.ts +96 -0
- package/dist/cjs/nested-write.js +414 -24
- package/dist/cjs/observe.d.ts +115 -0
- package/dist/cjs/optional-peer-import.d.cts +72 -0
- package/dist/cjs/pipeline-submittable.d.ts +93 -0
- package/dist/cjs/pipeline.d.ts +71 -0
- package/dist/cjs/powdb-introspect.d.ts +84 -0
- package/dist/cjs/powdb.d.ts +931 -0
- package/dist/cjs/powdb.js +106 -21
- package/dist/cjs/powql.d.ts +592 -0
- package/dist/cjs/powql.js +42 -6
- package/dist/cjs/prisma-compat.d.ts +283 -0
- package/dist/cjs/prisma-compat.js +167 -9
- package/dist/cjs/query/aggregates.d.ts +92 -0
- package/dist/cjs/query/aggregates.js +7 -3
- package/dist/cjs/query/batched-loader.d.ts +193 -0
- package/dist/cjs/query/builder.d.ts +849 -0
- package/dist/cjs/query/builder.js +571 -65
- package/dist/cjs/query/compound-unique.d.ts +51 -0
- package/dist/cjs/query/deferred.d.ts +223 -0
- package/dist/cjs/query/filters.d.ts +201 -0
- package/dist/cjs/query/index.d.ts +14 -0
- package/dist/cjs/query/index.js +6 -1
- package/dist/cjs/query/relations.d.ts +609 -0
- package/dist/cjs/query/relations.js +693 -46
- package/dist/cjs/query/types.d.ts +1300 -0
- package/dist/cjs/query/utils.d.ts +209 -0
- package/dist/cjs/query/utils.js +208 -1
- package/dist/cjs/query/warn-registry.d.ts +68 -0
- package/dist/cjs/query/warn-registry.js +9 -0
- package/dist/cjs/query/where-compile.d.ts +139 -0
- package/dist/cjs/query/where.d.ts +548 -0
- package/dist/cjs/query/where.js +58 -22
- package/dist/cjs/query/writes.d.ts +172 -0
- package/dist/cjs/query/writes.js +105 -12
- package/dist/cjs/realtime.d.ts +70 -0
- package/dist/cjs/schema-builder.d.ts +354 -0
- package/dist/cjs/schema-metadata.d.ts +83 -0
- package/dist/cjs/schema-sql.d.ts +217 -0
- package/dist/cjs/schema-sql.js +23 -5
- package/dist/cjs/schema.d.ts +356 -0
- package/dist/cjs/schema.js +125 -0
- package/dist/cjs/seed.d.ts +15 -0
- package/dist/cjs/serverless.d.ts +142 -0
- package/dist/cjs/sqlite.d.ts +143 -0
- package/dist/cjs/sqlite.js +4 -0
- package/dist/cjs/typed-sql.d.ts +102 -0
- package/dist/cli/config.d.ts +18 -4
- package/dist/cli/config.js +31 -6
- package/dist/cli/index.d.ts +123 -0
- package/dist/cli/index.js +223 -58
- package/dist/cli/migrate.d.ts +59 -10
- package/dist/cli/migrate.js +128 -41
- package/dist/cli/observe-ui.d.ts +1 -1
- package/dist/cli/observe-ui.js +14 -5
- package/dist/cli/observe.d.ts +7 -1
- package/dist/cli/observe.js +48 -12
- package/dist/cli/prisma-report.d.ts +14 -0
- package/dist/cli/prisma-report.js +72 -0
- package/dist/cli/prisma-resolve.d.ts +6 -0
- package/dist/cli/prisma-resolve.js +1 -0
- package/dist/cli/prisma-schema.d.ts +62 -2
- package/dist/cli/prisma-schema.js +81 -4
- package/dist/cli/rate-limit.d.ts +32 -0
- package/dist/cli/rate-limit.js +40 -0
- package/dist/cli/studio.d.ts +5 -5
- package/dist/cli/studio.js +135 -70
- package/dist/cli/ui.d.ts +1 -1
- package/dist/cli/ui.js +51 -9
- package/dist/client.d.ts +40 -0
- package/dist/client.js +3 -0
- package/dist/dialect.d.ts +17 -1
- package/dist/dialect.js +37 -12
- package/dist/generate.js +40 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mssql.js +6 -0
- package/dist/mysql.js +16 -0
- package/dist/nested-write.d.ts +2 -0
- package/dist/nested-write.js +415 -25
- package/dist/powdb.d.ts +4 -2
- package/dist/powdb.js +106 -21
- package/dist/powql.d.ts +5 -0
- package/dist/powql.js +42 -6
- package/dist/prisma-compat.d.ts +2 -0
- package/dist/prisma-compat.js +166 -8
- package/dist/query/aggregates.js +7 -3
- package/dist/query/builder.d.ts +292 -21
- package/dist/query/builder.js +570 -64
- package/dist/query/deferred.d.ts +39 -0
- package/dist/query/index.d.ts +1 -1
- package/dist/query/index.js +1 -1
- package/dist/query/relations.d.ts +173 -5
- package/dist/query/relations.js +688 -47
- package/dist/query/types.d.ts +123 -39
- package/dist/query/utils.d.ts +116 -0
- package/dist/query/utils.js +198 -0
- package/dist/query/warn-registry.d.ts +9 -0
- package/dist/query/warn-registry.js +9 -0
- package/dist/query/where.d.ts +38 -1
- package/dist/query/where.js +58 -23
- package/dist/query/writes.d.ts +42 -1
- package/dist/query/writes.js +104 -13
- package/dist/schema-sql.d.ts +14 -0
- package/dist/schema-sql.js +23 -5
- package/dist/schema.d.ts +38 -0
- package/dist/schema.js +123 -0
- package/dist/sqlite.js +4 -0
- package/package.json +77 -28
|
@@ -0,0 +1,931 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* turbine-orm/powdb — Turbine's PowDB / PowQL backend.
|
|
3
|
+
*
|
|
4
|
+
* PowDB is a single-node embedded database with its own query language, **PowQL**
|
|
5
|
+
* (not SQL), reached over `@zvndev/powdb-client`'s binary TCP protocol. PowDB is a
|
|
6
|
+
* different shape than the SQL engines, so this module does NOT route through the
|
|
7
|
+
* SQL `Dialect` / `QueryInterface`: it ships a parallel {@link PowqlInterface} that
|
|
8
|
+
* generates PowQL, plugged into `TurbineClient` via the `queryInterfaceFactory`
|
|
9
|
+
* seam. The four SQL engines are untouched.
|
|
10
|
+
*
|
|
11
|
+
* PowDB realities shape the design (all verified firsthand against a live
|
|
12
|
+
* `powdb-server` / the embedded addon, see `docs/internal/strategy/powdb-parity-matrix.md`):
|
|
13
|
+
* - **`RETURNING` (since 0.7.0)** — `create/createMany/update/delete` append the
|
|
14
|
+
* trailing `returning` keyword (`RETURNING *`, all columns) and read the
|
|
15
|
+
* affected rows back in one round-trip. `upsert` is the lone exception (its
|
|
16
|
+
* statement rejects `returning`) and reselects by primary key.
|
|
17
|
+
* - **No generated IDs** — the app must supply every value → Turbine generates a
|
|
18
|
+
* client-side UUID for the primary key when it has a default.
|
|
19
|
+
* - **`uuid`/`datetime`/`bytes` columns can't hold client-supplied values** (no
|
|
20
|
+
* literal, no working cast on the wire) → Turbine maps everything onto the four
|
|
21
|
+
* writable types (`str`/`int`/`float`/`bool`); `Date` → `int` epoch micros;
|
|
22
|
+
* `string` PKs hold UUID strings.
|
|
23
|
+
* - **No JSON aggregation / link navigation** — single-query nested `with` is
|
|
24
|
+
* impossible → it degrades to batched N+1 loaders (Phase B).
|
|
25
|
+
* - **Single global write lock; no savepoints/isolation** — nested
|
|
26
|
+
* transactions / isolation / vector / LISTEN-NOTIFY / RLS throw.
|
|
27
|
+
* Independent concurrent `db.$transaction` calls do NOT throw: they queue
|
|
28
|
+
* FIFO on a pool-level gate and run one at a time (see {@link PowdbTxGate}).
|
|
29
|
+
* Only a *re-entrant* transaction — a `db.$transaction` opened from inside
|
|
30
|
+
* an active transaction callback's async context, which queueing would
|
|
31
|
+
* deadlock — fails fast with E017.
|
|
32
|
+
* - **The wire protocol pipelines** — `@zvndev/powdb-client` writes each
|
|
33
|
+
* request frame immediately and matches replies FIFO, so multiple queries
|
|
34
|
+
* may be in flight on one connection. {@link PowdbPool}'s checked-out
|
|
35
|
+
* clients advertise `supportsPipelining`, which lets the batch
|
|
36
|
+
* `$transaction([...])` overload dispatch all statements in one write
|
|
37
|
+
* burst (~1 round trip) instead of one round trip per statement.
|
|
38
|
+
*
|
|
39
|
+
* `@zvndev/powdb-client` is an **optional peer dependency** loaded by dynamic
|
|
40
|
+
* import; `npm i turbine-orm` still pulls only `pg`.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* import { turbinePowDB } from 'turbine-orm/powdb';
|
|
45
|
+
* import { SCHEMA } from './generated/turbine/metadata.js';
|
|
46
|
+
*
|
|
47
|
+
* const db = await turbinePowDB({ host: '127.0.0.1', port: 5433 }, SCHEMA);
|
|
48
|
+
* const user = await db.table('users').create({ data: { name: 'Ada' } }); // UUID id auto-generated
|
|
49
|
+
* const found = await db.table('users').findMany({ where: { name: 'Ada' }, limit: 10 });
|
|
50
|
+
* await db.disconnect();
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @module
|
|
54
|
+
*/
|
|
55
|
+
import { type PgCompatPool, type PgCompatPoolClient, TurbineClient, type TurbineConfig } from './client.js';
|
|
56
|
+
import { type Dialect } from './dialect.js';
|
|
57
|
+
import type { PowdbExec } from './powdb-introspect.js';
|
|
58
|
+
import { type ColumnMetadata, type SchemaMetadata, type TableMetadata } from './schema.js';
|
|
59
|
+
/**
|
|
60
|
+
* Capability descriptor for PowDB. PowQL generation is owned by
|
|
61
|
+
* {@link PowqlInterface} (not the SQL `Dialect`), so this dialect exists only to
|
|
62
|
+
* drive `TurbineClient`'s capability gating and transaction keywords:
|
|
63
|
+
* - `supports*` flags are all `false` for the Postgres-only features, so
|
|
64
|
+
* `$listen`/`$notify`, RLS `sessionContext`/`$withSession`, and pgvector
|
|
65
|
+
* throw a clear {@link UnsupportedFeatureError} (E017) at the client surface
|
|
66
|
+
* instead of emitting SQL that PowDB cannot parse.
|
|
67
|
+
* - `begin`/`commit`/`rollback` are lowercase PowQL keywords (verified on the
|
|
68
|
+
* wire) so a single-level `$transaction` works.
|
|
69
|
+
* - PowDB has a single global write lock and supports neither savepoints nor
|
|
70
|
+
* nested/concurrent transactions. The `savepoint*` keywords therefore throw
|
|
71
|
+
* {@link UnsupportedFeatureError} (E017): a nested `tx.$transaction` emits a
|
|
72
|
+
* savepoint synchronously (before any DB call) and so fails fast with a
|
|
73
|
+
* clear typed error instead of leaking PowDB's cryptic `Parse(... 'sp_1')`.
|
|
74
|
+
* The pool-level transaction gate (see {@link PowdbTxGate}) handles the
|
|
75
|
+
* other shapes: a fresh top-level `db.$transaction` opened inside an
|
|
76
|
+
* already-open one throws E017 before it can deadlock on the write lock,
|
|
77
|
+
* while INDEPENDENT concurrent `db.$transaction` calls queue FIFO and run
|
|
78
|
+
* one at a time instead of failing.
|
|
79
|
+
* Isolation levels remain Phase B.
|
|
80
|
+
*/
|
|
81
|
+
export declare const powdbDialect: Dialect;
|
|
82
|
+
/** A single value PowDB accepts as a positional `$N` parameter. */
|
|
83
|
+
type PowdbParam = string | number | bigint | boolean | null;
|
|
84
|
+
/**
|
|
85
|
+
* Marker wrapper for a value bound to a `float` column. The networked driver
|
|
86
|
+
* unwraps it to the plain number (the wire param is unchanged), but the
|
|
87
|
+
* *embedded* literal encoder reads it to emit a float-form PowQL literal (`42`
|
|
88
|
+
* → `42.0`) so an integer-valued float column stays unambiguously a float.
|
|
89
|
+
* Constructed in {@link PowqlInterface.param}.
|
|
90
|
+
*/
|
|
91
|
+
export declare class PowdbFloatParam {
|
|
92
|
+
readonly value: number;
|
|
93
|
+
constructor(value: number);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Marker wrapper for a JS object/array bound to a `json` document column. Both
|
|
97
|
+
* transports serialize `value` with `JSON.stringify` and send the text as a
|
|
98
|
+
* `str` param / string literal, exactly how the PowDB docs insert a json
|
|
99
|
+
* document (the engine validates it as JSON text and stores the canonical
|
|
100
|
+
* binary form). Constructed in {@link PowqlInterface.param} when the target
|
|
101
|
+
* column is `json` and the value is a non-null object/array; a JS string
|
|
102
|
+
* written to a json column passes through RAW (same contract as pg jsonb,
|
|
103
|
+
* pass `'"x"'` to store the JSON string `"x"`), and `null` stays `null`.
|
|
104
|
+
*/
|
|
105
|
+
export declare class PowdbJsonParam {
|
|
106
|
+
readonly value: unknown;
|
|
107
|
+
readonly column?: string | undefined;
|
|
108
|
+
/** `column` is diagnostic only: it names the target column when serialization fails. */
|
|
109
|
+
constructor(value: unknown, column?: string | undefined);
|
|
110
|
+
}
|
|
111
|
+
/** The four shapes a PowQL result takes over the legacy string wire. */
|
|
112
|
+
type PowdbResult = {
|
|
113
|
+
kind: 'rows';
|
|
114
|
+
columns: string[];
|
|
115
|
+
rows: string[][];
|
|
116
|
+
} | {
|
|
117
|
+
kind: 'scalar';
|
|
118
|
+
value: string;
|
|
119
|
+
} | {
|
|
120
|
+
kind: 'ok';
|
|
121
|
+
affected: bigint;
|
|
122
|
+
} | {
|
|
123
|
+
kind: 'message';
|
|
124
|
+
message: string;
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Local structural mirror of `@zvndev/powdb-client`'s `WireValue` (the lossless
|
|
128
|
+
* typed cell of the native wire surface). Defined here rather than imported so
|
|
129
|
+
* the optional peer's types never leak into Turbine's published `.d.ts` (a
|
|
130
|
+
* consumer without the peer installed must still `tsc` cleanly, same rule as
|
|
131
|
+
* every other optional-peer type in this module). `empty` = an unset value
|
|
132
|
+
* (distinct, for a json column, from a JSON-null document, which is
|
|
133
|
+
* `{ type: 'json', value: null }`).
|
|
134
|
+
*/
|
|
135
|
+
type PowdbWireValue = {
|
|
136
|
+
type: 'empty';
|
|
137
|
+
} | {
|
|
138
|
+
type: 'int';
|
|
139
|
+
value: bigint;
|
|
140
|
+
} | {
|
|
141
|
+
type: 'float';
|
|
142
|
+
value: number;
|
|
143
|
+
} | {
|
|
144
|
+
type: 'bool';
|
|
145
|
+
value: boolean;
|
|
146
|
+
} | {
|
|
147
|
+
type: 'str';
|
|
148
|
+
value: string;
|
|
149
|
+
} | {
|
|
150
|
+
type: 'datetime';
|
|
151
|
+
value: bigint;
|
|
152
|
+
} | {
|
|
153
|
+
type: 'uuid';
|
|
154
|
+
value: Uint8Array;
|
|
155
|
+
} | {
|
|
156
|
+
type: 'bytes';
|
|
157
|
+
value: Uint8Array;
|
|
158
|
+
} | {
|
|
159
|
+
type: 'json';
|
|
160
|
+
value: unknown;
|
|
161
|
+
pj1?: Uint8Array;
|
|
162
|
+
};
|
|
163
|
+
/** The native (lossless typed) result shape, mirroring `RawNativeQueryResult`. */
|
|
164
|
+
type PowdbRawNativeResult = {
|
|
165
|
+
kind: 'rows';
|
|
166
|
+
columns: string[];
|
|
167
|
+
rows: PowdbWireValue[][];
|
|
168
|
+
} | {
|
|
169
|
+
kind: 'scalar';
|
|
170
|
+
value: PowdbWireValue;
|
|
171
|
+
} | {
|
|
172
|
+
kind: 'ok';
|
|
173
|
+
affected: bigint;
|
|
174
|
+
} | {
|
|
175
|
+
kind: 'message';
|
|
176
|
+
message: string;
|
|
177
|
+
};
|
|
178
|
+
interface PowdbClient {
|
|
179
|
+
readonly serverVersion: string;
|
|
180
|
+
query(query: string, params?: PowdbParam[], opts?: {
|
|
181
|
+
signal?: AbortSignal;
|
|
182
|
+
}): Promise<PowdbResult>;
|
|
183
|
+
/**
|
|
184
|
+
* Lossless typed wire surface (client ≥ 0.13, server ≥ 0.13). Optional: an
|
|
185
|
+
* older client omits it, so every call site feature-detects
|
|
186
|
+
* `typeof c.queryNativeRaw === 'function'` before using it and falls back to
|
|
187
|
+
* {@link query}. It NEVER retries as a legacy query, replaying an ambiguous
|
|
188
|
+
* mutation is unsafe, so its use is additionally version-gated server-side.
|
|
189
|
+
*/
|
|
190
|
+
queryNativeRaw?(query: string, params?: PowdbParam[], opts?: {
|
|
191
|
+
signal?: AbortSignal;
|
|
192
|
+
}): Promise<PowdbRawNativeResult>;
|
|
193
|
+
close(): Promise<void>;
|
|
194
|
+
}
|
|
195
|
+
interface PowdbClientPool {
|
|
196
|
+
acquire(): Promise<PowdbClient>;
|
|
197
|
+
release(c: PowdbClient): void;
|
|
198
|
+
destroy(c: PowdbClient): void;
|
|
199
|
+
withClient<T>(fn: (c: PowdbClient) => Promise<T>): Promise<T>;
|
|
200
|
+
close(): Promise<void>;
|
|
201
|
+
}
|
|
202
|
+
interface PowdbModule {
|
|
203
|
+
Client: {
|
|
204
|
+
connect(opts: PowdbConnOptions): Promise<PowdbClient>;
|
|
205
|
+
};
|
|
206
|
+
Pool: new (opts: PowdbConnOptions & {
|
|
207
|
+
max?: number;
|
|
208
|
+
}) => PowdbClientPool;
|
|
209
|
+
isPowDBError?(err: unknown): err is {
|
|
210
|
+
code: string;
|
|
211
|
+
message: string;
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
/** Connection options for {@link turbinePowDB} — host/port, not a connection string. */
|
|
215
|
+
export interface PowdbConnOptions {
|
|
216
|
+
host: string;
|
|
217
|
+
port: number;
|
|
218
|
+
dbName?: string;
|
|
219
|
+
user?: string;
|
|
220
|
+
password?: string | null;
|
|
221
|
+
connectTimeoutMs?: number;
|
|
222
|
+
tls?: boolean;
|
|
223
|
+
}
|
|
224
|
+
/** Minimum PowDB server version the networked transport requires. */
|
|
225
|
+
export declare const MIN_POWDB_VERSION = "0.7.0";
|
|
226
|
+
/**
|
|
227
|
+
* Parse a `powdb://[user[:pass]@]host[:port][/db]` connection string into
|
|
228
|
+
* {@link PowdbConnOptions} (consistency with `turbineMysql`/`turbineMssql`,
|
|
229
|
+
* which accept a URL). Defaults: host `127.0.0.1`, port `5433`.
|
|
230
|
+
*/
|
|
231
|
+
export declare function parsePowdbUrl(connectionString: string): PowdbConnOptions;
|
|
232
|
+
/**
|
|
233
|
+
* Fail fast if a networked PowDB server is older than {@link MIN_POWDB_VERSION}.
|
|
234
|
+
* Turbine's write path relies on the trailing `returning` keyword and the
|
|
235
|
+
* int→float coercion fix, both of which landed in 0.7.0. Embedded exposes no
|
|
236
|
+
* version method, so this is networked-only (the embedded peer is pinned ^0.7.0
|
|
237
|
+
* at install time). A non-semver / empty version string is tolerated (we cannot
|
|
238
|
+
* prove it is too old).
|
|
239
|
+
*/
|
|
240
|
+
export declare function assertSupportedPowdbVersion(version: string | undefined): void;
|
|
241
|
+
/**
|
|
242
|
+
* Feature capabilities of a bound PowDB connection. Resolved once (from the
|
|
243
|
+
* probed server version on the networked transport, or the addon package
|
|
244
|
+
* version on embedded) and carried on the pool so {@link PowqlInterface} can
|
|
245
|
+
* gate PowQL features that only exist on newer engines, an old engine gets a
|
|
246
|
+
* typed {@link UnsupportedFeatureError} (E017) with a version hint instead of a
|
|
247
|
+
* raw PowQL parse error.
|
|
248
|
+
*/
|
|
249
|
+
export interface PowdbCapabilities {
|
|
250
|
+
/** Best-known engine version (e.g. `'0.13.0'`), or `null` when unknowable. */
|
|
251
|
+
engineVersion: string | null;
|
|
252
|
+
/** ≥ 0.12: `json` column type, `->` path filters / ordering / grouping. */
|
|
253
|
+
jsonDocs: boolean;
|
|
254
|
+
/** ≥ 0.13: `alter T add index (.col->seg)` expression indexes. */
|
|
255
|
+
docFieldIndexes: boolean;
|
|
256
|
+
/** ≥ 0.10: `schema` / `describe` introspection statements. */
|
|
257
|
+
introspection: boolean;
|
|
258
|
+
/** ≥ 0.13: server-side joins, hash-accelerated and bounded. */
|
|
259
|
+
serverJoins: boolean;
|
|
260
|
+
/**
|
|
261
|
+
* ≥ 0.18: nested projections (shaped results) — a projection field may be a
|
|
262
|
+
* whole correlated child query returning a per-parent JSON array. When set,
|
|
263
|
+
* eligible `with` clauses compile into the parent statement instead of the
|
|
264
|
+
* batched loaders.
|
|
265
|
+
*/
|
|
266
|
+
nestedProjections: boolean;
|
|
267
|
+
/**
|
|
268
|
+
* ≥ 0.19: entity links (`link` DDL, scalar/block traversal). Capability is
|
|
269
|
+
* recognized (probe-only), but query generation deliberately does NOT consume
|
|
270
|
+
* links yet: turbine keeps composing its own nested projections (see the
|
|
271
|
+
* PowDB engine page for the rationale). Declaring a link permanently upgrades
|
|
272
|
+
* the on-disk catalog to v7, so this stays FALSE in ALL_POWDB_CAPABILITIES.
|
|
273
|
+
*/
|
|
274
|
+
entityLinks: boolean;
|
|
275
|
+
/**
|
|
276
|
+
* ≥ 0.19.1: link INTROSPECTION, the `schema links` listing statement and the
|
|
277
|
+
* appended link rows in `describe <T>`. Only meaningful when probed (there is
|
|
278
|
+
* no query-generation flip behind it), so it stays FALSE in
|
|
279
|
+
* ALL_POWDB_CAPABILITIES like the other probe-only gates. Floored at the PATCH
|
|
280
|
+
* 0.19.1: the listing statement shipped there, not in 0.19.0.
|
|
281
|
+
*/
|
|
282
|
+
linkIntrospection: boolean;
|
|
283
|
+
/**
|
|
284
|
+
* ≥ 0.19.1: scalar to-one link PATHS in query generation. Floored at the PATCH
|
|
285
|
+
* 0.19.1 (never 0.19.0) because 0.19.0 had silent-wrong-results link bugs
|
|
286
|
+
* (bare-dotted-path split, wrong aggregates over links) that make traversal
|
|
287
|
+
* unsafe; 0.19.1 turned those into hard errors. This flag flips real query
|
|
288
|
+
* generation (a to-one `with` whose child carries bigint/bytes compiles to
|
|
289
|
+
* link-path projections instead of a loader), so it stays FALSE in
|
|
290
|
+
* ALL_POWDB_CAPABILITIES: it must only light up behind a real version probe.
|
|
291
|
+
*/
|
|
292
|
+
linkPaths: boolean;
|
|
293
|
+
/** Networked only: server ≥ 0.13 AND the client exposes `queryNativeRaw`. */
|
|
294
|
+
nativeRaw: boolean;
|
|
295
|
+
}
|
|
296
|
+
/** The feature-gate capability keys (everything except the version/nativeRaw metadata). */
|
|
297
|
+
type PowdbFeatureKey = 'jsonDocs' | 'docFieldIndexes' | 'introspection' | 'serverJoins' | 'nestedProjections' | 'entityLinks' | 'linkIntrospection' | 'linkPaths';
|
|
298
|
+
/**
|
|
299
|
+
* Trusted-caller default: every FEATURE gate on, engine version unknown. Used
|
|
300
|
+
* for a directly-constructed {@link PowdbPool} / {@link PowdbEmbeddedPool} that
|
|
301
|
+
* did not go through {@link turbinePowDB}'s version probe (e.g. an injected
|
|
302
|
+
* pool, or a unit-test pool). `nativeRaw` stays OFF here because it flips the
|
|
303
|
+
* actual wire path and must only be enabled after a real server-version probe,
|
|
304
|
+
* never inferred from a bare construction. `nestedProjections` stays OFF for
|
|
305
|
+
* the same reason: it changes the generated PowQL for every `with` query, and
|
|
306
|
+
* an unprobed engine below 0.18 would reject the syntax outright.
|
|
307
|
+
* `entityLinks` stays OFF for a stronger reason still: declaring a link
|
|
308
|
+
* one-way-upgrades the on-disk catalog to v7 and locks out pre-0.19 binaries,
|
|
309
|
+
* so it must only ever light up behind a real version probe.
|
|
310
|
+
* `linkIntrospection` / `linkPaths` stay OFF for the same probe-only discipline:
|
|
311
|
+
* `linkPaths` flips real query generation (a to-one `with` compiling to link
|
|
312
|
+
* projections), and `linkIntrospection` is only meaningful once genuinely
|
|
313
|
+
* probed, so both must come from a real version resolution, never a bare
|
|
314
|
+
* construction.
|
|
315
|
+
*/
|
|
316
|
+
export declare const ALL_POWDB_CAPABILITIES: PowdbCapabilities;
|
|
317
|
+
/**
|
|
318
|
+
* Derive {@link PowdbCapabilities} from an engine version string. A non-semver /
|
|
319
|
+
* unknown version turns every gate OFF (the E017 hint then tells the caller to
|
|
320
|
+
* upgrade or pass `assumeEngineVersion`). `nativeRaw` requires BOTH the client
|
|
321
|
+
* to expose `queryNativeRaw` (passed in) AND server ≥ 0.13.
|
|
322
|
+
*/
|
|
323
|
+
export declare function capabilitiesFromVersion(version: string | undefined | null, opts?: {
|
|
324
|
+
hasNativeRaw?: boolean;
|
|
325
|
+
}): PowdbCapabilities;
|
|
326
|
+
/**
|
|
327
|
+
* Throw a version-hinting {@link UnsupportedFeatureError} (E017) when a gated
|
|
328
|
+
* PowQL feature is used on an engine that does not support it. Keeps old engines
|
|
329
|
+
* getting clean typed errors instead of raw PowQL parse failures.
|
|
330
|
+
*/
|
|
331
|
+
export declare function requireCapability(caps: PowdbCapabilities, key: PowdbFeatureKey, feature: string): void;
|
|
332
|
+
/**
|
|
333
|
+
* PowQL column types Turbine emits: the four writable scalars plus PowDB's
|
|
334
|
+
* native `json` document type (added to the map in the 0.12/0.13 parity round,
|
|
335
|
+
* see {@link isJsonColumn}). A `json` column stores a canonical binary document
|
|
336
|
+
* (sorted keys, int/float distinction preserved) that Turbine writes as a JSON
|
|
337
|
+
* string literal and reads back by parsing the canonical JSON text.
|
|
338
|
+
*/
|
|
339
|
+
export type PowqlType = 'str' | 'int' | 'float' | 'bool' | 'json';
|
|
340
|
+
/**
|
|
341
|
+
* Does this column map to PowDB's native `json` document type? A Postgres
|
|
342
|
+
* `json`/`jsonb` type (via `dialectType`/`pgType`) is authoritative; otherwise
|
|
343
|
+
* the tsType heuristic (`Record<…>`, `object`, `unknown`, an object/array
|
|
344
|
+
* literal) that the four scalar branches do not claim. Array columns never map
|
|
345
|
+
* to json, a PowDB array only exists INSIDE a json document, so a Postgres
|
|
346
|
+
* array column has no PowDB shape and still throws in {@link powqlColumnType}.
|
|
347
|
+
*/
|
|
348
|
+
export declare function isJsonColumn(col: ColumnMetadata): boolean;
|
|
349
|
+
/**
|
|
350
|
+
* Map a Turbine column to the PowQL DDL type used in `defineSchema` →
|
|
351
|
+
* `type T { … }`. Turbine never emits PowDB's `uuid`/`datetime`/`bytes` types,
|
|
352
|
+
* which cannot hold client-supplied values on the wire (no literal, no cast):
|
|
353
|
+
* - `Date` → `int` (epoch micros) - `boolean` → `bool`
|
|
354
|
+
* - integral `number`/`bigint` → `int` - fractional `number` → `float`
|
|
355
|
+
* - JSON / object columns → `json` (native PowDB document type, ≥ 0.12)
|
|
356
|
+
* - everything else (incl. UUID/PK strings) → `str`
|
|
357
|
+
* Array (non-json) and bytes columns throw, they have no PowDB equivalent.
|
|
358
|
+
*/
|
|
359
|
+
export declare function powqlColumnType(col: ColumnMetadata): PowqlType;
|
|
360
|
+
/**
|
|
361
|
+
* Generate PowQL DDL (`type T { … }`) for every table in a schema. Used to
|
|
362
|
+
* provision a PowDB database from a code-first `defineSchema`/`SchemaMetadata`
|
|
363
|
+
* (PowDB has no migration runner yet). The primary key column is declared
|
|
364
|
+
* `required unique`; non-nullable columns are `required`. A server-generated
|
|
365
|
+
* column ({@link ColumnMetadata.isGenerated}) that maps to PowQL `int` gets the
|
|
366
|
+
* `auto` modifier, so PowDB assigns a monotonic id on insert and Turbine stops
|
|
367
|
+
* synthesizing a client-side value for it.
|
|
368
|
+
*/
|
|
369
|
+
/**
|
|
370
|
+
* PowQL reserved words — the v0.10 lexer keyword table from POWQL.md's
|
|
371
|
+
* "Reserved Words and Quoting" section, including the v0.10 additions
|
|
372
|
+
* `schema` and `describe`. Keyword matching is case-sensitive in the lexer,
|
|
373
|
+
* so only the exact lowercase form collides.
|
|
374
|
+
*/
|
|
375
|
+
export declare const POWQL_KEYWORDS: ReadonlySet<string>;
|
|
376
|
+
/**
|
|
377
|
+
* Backtick-quote an identifier when PowQL would otherwise lex it as a keyword
|
|
378
|
+
* (or when it contains characters outside the bare-identifier grammar).
|
|
379
|
+
* Applied only in bare-identifier positions — DDL type/field names, index DDL,
|
|
380
|
+
* and `insert`/`update`/`upsert` assignment targets. Dotted references
|
|
381
|
+
* (`.col` in filters/projections/ordering) bypass keyword lookup on every
|
|
382
|
+
* engine version and deliberately stay bare for ≤0.9 compatibility. Backticks
|
|
383
|
+
* parse on PowDB ≥ 0.10; on older engines these names were already parse
|
|
384
|
+
* errors when emitted bare, so quoting is strictly an improvement.
|
|
385
|
+
*/
|
|
386
|
+
export declare function quotePowqlIdent(name: string): string;
|
|
387
|
+
/**
|
|
388
|
+
* Options for {@link powqlSchemaDDL}. Additive: with no options the DDL is
|
|
389
|
+
* emitted unconditionally (pure-function callers / tests); pass `capabilities`
|
|
390
|
+
* to gate engine-version-specific features (json columns, and, since the
|
|
391
|
+
* 0.13 parity round, doc-field expression indexes) behind the connection's
|
|
392
|
+
* real capabilities. Doc-field expression index declarations plug into the
|
|
393
|
+
* per-table `indexes` surface consumed here without further signature churn.
|
|
394
|
+
*/
|
|
395
|
+
export interface PowqlSchemaDDLOptions {
|
|
396
|
+
capabilities?: PowdbCapabilities;
|
|
397
|
+
/**
|
|
398
|
+
* Emit `link Owner.name -> Target on local = target` declarations (PowDB entity
|
|
399
|
+
* links, >= 0.19) for every single-column hasMany / hasOne / belongsTo relation
|
|
400
|
+
* in the metadata, appended after the `type` / index statements. Default
|
|
401
|
+
* `false`: links are opt-in. Composite-key relations and m2m junctions are
|
|
402
|
+
* skipped (a link is single-column only); a relation whose name collides with a
|
|
403
|
+
* column on the owner is skipped with a one-time warning (the engine hard-errors
|
|
404
|
+
* on such a collision). When `capabilities` is also supplied it must pass the
|
|
405
|
+
* `entityLinks` gate, else this throws a typed E017.
|
|
406
|
+
*
|
|
407
|
+
* ONE-WAY DOOR: the FIRST `link` a database ever executes permanently upgrades
|
|
408
|
+
* its on-disk catalog to format v7; pre-0.19 PowDB binaries / addons can then no
|
|
409
|
+
* longer open that data directory. A database that never declares a link stays
|
|
410
|
+
* on its current catalog format. The DDL is create-only (no `if not exists`, no
|
|
411
|
+
* drop spelling), so an apply layer must existence-check first (see
|
|
412
|
+
* {@link applyPowdbLinks}).
|
|
413
|
+
*/
|
|
414
|
+
emitLinks?: boolean;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* One entity link Turbine wants declared for a relation: `link owner.name ->
|
|
418
|
+
* target on localKey = targetKey`. Cardinality is NOT part of the DDL (PowDB
|
|
419
|
+
* derives to-one vs to-many from whether `targetKey` is unique on `target` at
|
|
420
|
+
* declare time), so a belongsTo and its reverse hasMany both round-trip to the
|
|
421
|
+
* same shape from opposite owners.
|
|
422
|
+
*/
|
|
423
|
+
export interface PowdbDesiredLink {
|
|
424
|
+
owner: string;
|
|
425
|
+
name: string;
|
|
426
|
+
target: string;
|
|
427
|
+
localKey: string;
|
|
428
|
+
targetKey: string;
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Derive the entity links Turbine would declare from a schema's relations. One
|
|
432
|
+
* link per single-column hasMany / hasOne / belongsTo relation, owned by the
|
|
433
|
+
* relation's `from` table:
|
|
434
|
+
* - belongsTo Order->User: `Order.user -> User on user_id = id`
|
|
435
|
+
* (localKey = the FK on the owner, targetKey = the referenced key on target).
|
|
436
|
+
* - hasMany User->Order: `User.orders -> Order on id = user_id`
|
|
437
|
+
* (localKey = the referenced key on the owner, targetKey = the FK on the child).
|
|
438
|
+
* Composite-key relations and m2m junctions are skipped (links are single-column;
|
|
439
|
+
* a junction cannot be inferred from links). A relation whose name collides with
|
|
440
|
+
* a column on the owner is skipped and reported through `onCollision` (the caller
|
|
441
|
+
* decides whether to warn). Pure: no capability gate, no side effects.
|
|
442
|
+
*/
|
|
443
|
+
export declare function deriveDesiredLinks(schema: SchemaMetadata, onCollision?: (owner: string, name: string) => void): PowdbDesiredLink[];
|
|
444
|
+
/** Render one {@link PowdbDesiredLink} as its create-only `link ...` DDL statement. */
|
|
445
|
+
export declare function powdbLinkStatement(link: PowdbDesiredLink): string;
|
|
446
|
+
export declare function powqlSchemaDDL(schema: SchemaMetadata, opts?: PowqlSchemaDDLOptions): string[];
|
|
447
|
+
/**
|
|
448
|
+
* Existence-checked apply of entity-link DDL against a LIVE PowDB database.
|
|
449
|
+
* Because link DDL is create-only (no `if not exists`, redeclaring is an error,
|
|
450
|
+
* and there is no drop spelling), an apply layer must diff against the live
|
|
451
|
+
* catalog first: this reads the `schema links` listing, then executes only the
|
|
452
|
+
* links that are genuinely missing.
|
|
453
|
+
*
|
|
454
|
+
* - a desired link already declared with the SAME endpoints → skipped (idempotent);
|
|
455
|
+
* - a link declared with the same owner + name but DIFFERENT endpoints → skipped
|
|
456
|
+
* with a one-time warning (never dropped/replaced: there is no drop DDL, and a
|
|
457
|
+
* silent replace would be a destructive schema change);
|
|
458
|
+
* - a name/column collision on the owner → skipped (deriveDesiredLinks warns).
|
|
459
|
+
*
|
|
460
|
+
* Requires the `entityLinks` + `linkIntrospection` capabilities when `capabilities`
|
|
461
|
+
* is supplied (the listing statement is 0.19.1+). Returns the statements executed.
|
|
462
|
+
* `exec` runs one PowQL statement (embedded `db.raw` / a networked query shim); it
|
|
463
|
+
* must return rows keyed by column name for the `schema links` read.
|
|
464
|
+
*/
|
|
465
|
+
export declare function applyPowdbLinks(exec: PowdbExec, schema: SchemaMetadata, options?: {
|
|
466
|
+
capabilities?: PowdbCapabilities;
|
|
467
|
+
}): Promise<string[]>;
|
|
468
|
+
/**
|
|
469
|
+
* Coerce a single PowDB wire string into the JS value its column type implies.
|
|
470
|
+
* Every PowDB value arrives as a string; NULL arrives as the bareword `"null"`.
|
|
471
|
+
* Metadata resolves the `"null"` ambiguity for nullable non-string columns.
|
|
472
|
+
*/
|
|
473
|
+
export declare function coerceValue(raw: string, col: ColumnMetadata): unknown;
|
|
474
|
+
/**
|
|
475
|
+
* Coerce a single cell that arrived over the NATIVE typed wire (decoded from a
|
|
476
|
+
* {@link PowdbWireValue}, so already a JS `bigint`/`number`/`boolean`/`string`/
|
|
477
|
+
* `NativeJson`/`Uint8Array`/`null`, never a bare `"null"` string). Unlike
|
|
478
|
+
* {@link coerceValue} this NEVER collapses the string `"null"` to `null`: an
|
|
479
|
+
* absent value already decoded to `null` (from the `empty` cell), so a genuine
|
|
480
|
+
* str `"null"` stays the string `"null"` (fixes the legacy-wire wart on the
|
|
481
|
+
* native transport). `datetime`-shaped cells (int micros) become `Date`; a
|
|
482
|
+
* bigint on a `number` column follows the int8 safe-integer policy.
|
|
483
|
+
*/
|
|
484
|
+
export declare function coerceNativeValue(value: unknown, col: ColumnMetadata): unknown;
|
|
485
|
+
/**
|
|
486
|
+
* Map one raw PowDB row into a typed entity (camelCase fields, coerced values).
|
|
487
|
+
* Only the columns present in `raw` are emitted, so partial `select`
|
|
488
|
+
* projections round-trip unchanged. `native` selects the coercion policy: the
|
|
489
|
+
* default `false` handles the legacy string wire (every cell is a string, via
|
|
490
|
+
* {@link coerceValue}); `true` handles the native typed wire, where non-string
|
|
491
|
+
* cells arrive pre-typed and go through {@link coerceNativeValue} (see F3).
|
|
492
|
+
* Callers on the native transport pass `this.pool.capabilities.nativeRaw`.
|
|
493
|
+
*/
|
|
494
|
+
export declare function rowToEntity(raw: Record<string, unknown>, meta: TableMetadata, native?: boolean): Record<string, unknown>;
|
|
495
|
+
/**
|
|
496
|
+
* Translate a PowDB error into a typed Turbine error. Handles BOTH transports,
|
|
497
|
+
* whose error shapes differ:
|
|
498
|
+
* - **networked** (`@zvndev/powdb-client`) tags errors with a *semantic*
|
|
499
|
+
* `.code` (`connect_failed`, `timeout`, `query_failed`, …);
|
|
500
|
+
* - **embedded** (`@zvndev/powdb-embedded` napi addon) tags EVERY error
|
|
501
|
+
* `code:'GenericFailure'`, so the class can only be recovered from the
|
|
502
|
+
* message text (`Execution("column 'email' is required …")`,
|
|
503
|
+
* `Execution("type mismatch …")`, `Parse(…)`, `StorageError(…)`).
|
|
504
|
+
*
|
|
505
|
+
* So we always run the unique-constraint and message-shape checks first (they
|
|
506
|
+
* fire for both transports and extract detail like constraint / column names),
|
|
507
|
+
* then classify by the typed wire error class (`.wireErrorClass`, networked
|
|
508
|
+
* server >= 0.17 — accurate even when the server sanitized the message text),
|
|
509
|
+
* then fall through to the networked `.code` switch.
|
|
510
|
+
*/
|
|
511
|
+
export declare function wrapPowdbError(err: unknown): Error;
|
|
512
|
+
/**
|
|
513
|
+
* True when `err` is the stale-wire-frame {@link ConnectionError} produced by
|
|
514
|
+
* {@link wrapPowdbError} (its `.cause` is a `protocol_error` PowDBError, or the
|
|
515
|
+
* message carries the invalid-state signature). The opt-in read retry
|
|
516
|
+
* (`retryStaleReads`, evaluated in {@link PowqlInterface}'s exec seam) uses this
|
|
517
|
+
* to decide whether a first-statement READ may be replayed once on a fresh
|
|
518
|
+
* connection; writes are NEVER retried (an ambiguous mutation reply is unsafe
|
|
519
|
+
* to replay, matching the client's own native-path policy).
|
|
520
|
+
*/
|
|
521
|
+
export declare function isStaleFramePowdbError(err: unknown): boolean;
|
|
522
|
+
type QueryArg = string | {
|
|
523
|
+
name?: string;
|
|
524
|
+
text: string;
|
|
525
|
+
values?: unknown[];
|
|
526
|
+
};
|
|
527
|
+
/**
|
|
528
|
+
* Default cap (ms) on how long a `begin` may wait in the FIFO queue for
|
|
529
|
+
* PowDB's single global write lock before failing with a typed
|
|
530
|
+
* {@link TimeoutError} (E002). Prevents silent starvation behind a wedged
|
|
531
|
+
* transaction. Override via `transactionQueueTimeoutMs`
|
|
532
|
+
* ({@link TurbinePowdbOptions} / {@link PowdbPoolOptions}); `0` or `Infinity`
|
|
533
|
+
* waits without limit.
|
|
534
|
+
*/
|
|
535
|
+
export declare const DEFAULT_TX_QUEUE_TIMEOUT_MS = 30000;
|
|
536
|
+
/** Tuning options shared by {@link PowdbPool} and {@link PowdbEmbeddedPool}. */
|
|
537
|
+
export interface PowdbPoolOptions {
|
|
538
|
+
/**
|
|
539
|
+
* Max time (ms) a concurrent transaction's `begin` may wait in the FIFO
|
|
540
|
+
* queue for the single-writer lock before failing with a
|
|
541
|
+
* {@link TimeoutError}. Default {@link DEFAULT_TX_QUEUE_TIMEOUT_MS};
|
|
542
|
+
* `0` / `Infinity` = wait without limit. Note this is a separate surface
|
|
543
|
+
* from `$transaction`'s `timeout` option, which only covers the callback
|
|
544
|
+
* *after* the transaction has begun.
|
|
545
|
+
*/
|
|
546
|
+
transactionQueueTimeoutMs?: number;
|
|
547
|
+
/**
|
|
548
|
+
* Feature capabilities of the bound connection. Set by {@link turbinePowDB}
|
|
549
|
+
* from the probed engine version; defaults to {@link ALL_POWDB_CAPABILITIES}
|
|
550
|
+
* (feature gates on, `nativeRaw` off, engine version unknown) for a
|
|
551
|
+
* directly-constructed pool: a "trusted caller".
|
|
552
|
+
*/
|
|
553
|
+
capabilities?: PowdbCapabilities;
|
|
554
|
+
/**
|
|
555
|
+
* Opt in to replaying a first-statement READ once, on a fresh connection,
|
|
556
|
+
* when it fails with the stale-wire-frame {@link ConnectionError} (see
|
|
557
|
+
* {@link isStaleFramePowdbError}). Networked only; writes and mid-transaction
|
|
558
|
+
* statements are NEVER retried. Read by {@link PowqlInterface}'s exec seam.
|
|
559
|
+
* Default `false` (typed-error-only).
|
|
560
|
+
*/
|
|
561
|
+
retryStaleReads?: boolean;
|
|
562
|
+
/**
|
|
563
|
+
* Mark this pool read-only: {@link PowqlInterface}'s exec seam then fails a
|
|
564
|
+
* write (or a tx-control `begin`) fast with a {@link ReadOnlyError} (E018)
|
|
565
|
+
* before it reaches the wire. An `{ embedded, readonly: true }` target forces
|
|
566
|
+
* this true; a networked pool bound to a read-only role can also set it so
|
|
567
|
+
* writes are rejected locally instead of round-tripping to the engine's
|
|
568
|
+
* refusal. Default `false`.
|
|
569
|
+
*/
|
|
570
|
+
readonly?: boolean;
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* A {@link PgCompatPool} backed by a `@zvndev/powdb-client` `Pool`. The query
|
|
574
|
+
* `text` is **PowQL**, not SQL ({@link PowqlInterface} generates it). On the
|
|
575
|
+
* legacy string wire cells come back as strings; when `capabilities.nativeRaw`
|
|
576
|
+
* is set (server ≥ 0.13 + a client exposing `queryNativeRaw`) this pool routes
|
|
577
|
+
* through the typed native wire instead, so cells arrive pre-typed (a json int
|
|
578
|
+
* as `bigint`, etc.) and each result is tagged with the wire that served it
|
|
579
|
+
* ({@link PowdbTaggedResult}). Per-column JS coercion still happens in
|
|
580
|
+
* `PowqlInterface` (it owns the schema metadata), keyed on that per-result tag.
|
|
581
|
+
*/
|
|
582
|
+
export declare class PowdbPool implements PgCompatPool {
|
|
583
|
+
readonly pool: PowdbClientPool;
|
|
584
|
+
private readonly toParam;
|
|
585
|
+
private closed;
|
|
586
|
+
/**
|
|
587
|
+
* Pool-level single-writer gate. PowDB holds one global write lock, so at
|
|
588
|
+
* most one transaction may be open across the whole pool. Concurrent
|
|
589
|
+
* `begin`s queue FIFO on the gate (instead of checking out a second
|
|
590
|
+
* connection and blocking on the lock forever — the networked hang);
|
|
591
|
+
* re-entrant `begin`s throw E017 (see {@link PowdbTxGate}).
|
|
592
|
+
*/
|
|
593
|
+
private readonly txGate;
|
|
594
|
+
/** Hold taken by a `begin` issued via `query()` directly (no checked-out client). */
|
|
595
|
+
private poolHold;
|
|
596
|
+
/**
|
|
597
|
+
* Clients currently checked out via {@link connect}. The driver pool's
|
|
598
|
+
* `close()` only closes IDLE clients (checked-out ones are documented as the
|
|
599
|
+
* caller's responsibility), so {@link end} destroys these explicitly;
|
|
600
|
+
* otherwise a `disconnect()` racing an unreleased connection would leave a
|
|
601
|
+
* live socket holding the process open until the server's idle timeout.
|
|
602
|
+
*/
|
|
603
|
+
private readonly checkedOut;
|
|
604
|
+
/** Feature capabilities of the bound server (probed version + native-wire feature-detect). */
|
|
605
|
+
readonly capabilities: PowdbCapabilities;
|
|
606
|
+
/** Opt-in first-statement-read replay on a stale wire frame (read by {@link PowqlInterface}). */
|
|
607
|
+
readonly retryStaleReads: boolean;
|
|
608
|
+
/**
|
|
609
|
+
* True when the caller marked this pool read-only (`readonly: true`). Read by
|
|
610
|
+
* {@link PowqlInterface}'s exec seam to fail writes fast with E018 before the
|
|
611
|
+
* wire; the engine's own read-only-role refusal (mapped by
|
|
612
|
+
* {@link wrapPowdbError}) is the backstop for raw / injected paths.
|
|
613
|
+
*/
|
|
614
|
+
readonly readonly: boolean;
|
|
615
|
+
constructor(pool: PowdbClientPool, toParam?: (v: unknown, i: number) => PowdbParam, options?: PowdbPoolOptions);
|
|
616
|
+
/**
|
|
617
|
+
* Run one statement on `c`, choosing the lossless native typed wire when the
|
|
618
|
+
* server supports it (`capabilities.nativeRaw`) AND this client exposes
|
|
619
|
+
* `queryNativeRaw` (a defensive per-call feature-detect, so a heterogeneous
|
|
620
|
+
* injected pool cannot crash). Otherwise the legacy string wire, unchanged.
|
|
621
|
+
*/
|
|
622
|
+
private runOnClient;
|
|
623
|
+
query(text: QueryArg, values?: unknown[]): Promise<any>;
|
|
624
|
+
/**
|
|
625
|
+
* Typed guard mirroring {@link PowdbEmbeddedPool}: after `end()` the driver
|
|
626
|
+
* pool throws a raw `Error('pool closed')` that {@link wrapPowdbError}
|
|
627
|
+
* cannot classify — surface the same ConnectionError on both transports.
|
|
628
|
+
*/
|
|
629
|
+
private assertOpen;
|
|
630
|
+
connect(): Promise<PgCompatPoolClient>;
|
|
631
|
+
end(): Promise<void>;
|
|
632
|
+
}
|
|
633
|
+
/** The embedded addon's result shape (matches {@link PowdbResult} but with optional fields). */
|
|
634
|
+
interface EmbeddedQueryResult {
|
|
635
|
+
kind: string;
|
|
636
|
+
columns?: string[];
|
|
637
|
+
rows?: string[][];
|
|
638
|
+
value?: string;
|
|
639
|
+
affected?: bigint;
|
|
640
|
+
message?: string;
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* The embedded addon's native typed result (`@zvndev/powdb-embedded` ≥ 0.14).
|
|
644
|
+
* Mirrors {@link PowdbRawNativeResult}, the same tagged {@link PowdbWireValue}
|
|
645
|
+
* cells (embedded `bytes` arrive as a `Buffer`, which IS a `Uint8Array`, so the
|
|
646
|
+
* decode path is unchanged), including the `message` kind for DDL / status
|
|
647
|
+
* replies, which {@link adaptNativeResult}'s default branch handles at runtime.
|
|
648
|
+
*/
|
|
649
|
+
type EmbeddedNativeResult = PowdbRawNativeResult;
|
|
650
|
+
/** A single in-process embedded database handle (`@zvndev/powdb-embedded`). */
|
|
651
|
+
interface EmbeddedDatabase {
|
|
652
|
+
query(powql: string): EmbeddedQueryResult;
|
|
653
|
+
querySql(sql: string): EmbeddedQueryResult;
|
|
654
|
+
queryReadonly(powql: string): EmbeddedQueryResult;
|
|
655
|
+
isPoisoned(): boolean;
|
|
656
|
+
/** WAL durability selector — `@zvndev/powdb-embedded` ≥ 0.7.1. */
|
|
657
|
+
setSyncMode?(mode: string): void;
|
|
658
|
+
/**
|
|
659
|
+
* Lossless typed native wire (`@zvndev/powdb-embedded` ≥ 0.14). All optional
|
|
660
|
+
* and feature-detected: an older addon omits them, so {@link PowdbEmbeddedPool}
|
|
661
|
+
* falls back to {@link materializePowql} + {@link query}. `queryWithParams`
|
|
662
|
+
* binds positional `$N` params as {@link PowdbParam} values (the NativeParam
|
|
663
|
+
* union) instead of materializing literals.
|
|
664
|
+
*/
|
|
665
|
+
queryNative?(powql: string): EmbeddedNativeResult;
|
|
666
|
+
queryReadonlyNative?(powql: string): EmbeddedNativeResult;
|
|
667
|
+
queryWithParams?(powql: string, params: PowdbParam[]): EmbeddedNativeResult;
|
|
668
|
+
/** Checkpoint-flushing close (`@zvndev/powdb-embedded` ≥ 0.14). Optional (feature-detected). */
|
|
669
|
+
close?(): void;
|
|
670
|
+
}
|
|
671
|
+
interface EmbeddedModule {
|
|
672
|
+
Database: {
|
|
673
|
+
open(dir: string): EmbeddedDatabase;
|
|
674
|
+
/** Open with a per-query memory budget — `@zvndev/powdb-embedded` ≥ 0.7.1. */
|
|
675
|
+
openWithMemoryLimit?(dir: string, limitBytes: number): EmbeddedDatabase;
|
|
676
|
+
/**
|
|
677
|
+
* Open a read-only handle for snapshot serving (`@zvndev/powdb-embedded` ≥
|
|
678
|
+
* 0.14). Optional (feature-detected); a write through such a handle is
|
|
679
|
+
* refused with `readonly mode: statement requires a writer …` (→ E018).
|
|
680
|
+
*/
|
|
681
|
+
openReadOnly?(dir: string): EmbeddedDatabase;
|
|
682
|
+
openReadOnlyWithMemoryLimit?(dir: string, limitBytes: number): EmbeddedDatabase;
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Encode a JS value as a **PowQL literal** for the embedded driver, which takes
|
|
687
|
+
* no params array — `$N` placeholders must be materialized into the query text.
|
|
688
|
+
*
|
|
689
|
+
* This is the single place Turbine builds PowQL text from a value, so it is the
|
|
690
|
+
* security-critical surface. String encoding matches PowDB's lexer
|
|
691
|
+
* (`crates/query/src/lexer.rs`) exactly: a string literal is `"…"`, and inside
|
|
692
|
+
* it the lexer recognizes only the escapes `\"`, `\\`, `\n`, `\t` (any other
|
|
693
|
+
* `\x` drops the backslash and keeps `x`; every non-`\`/non-`"` char — raw
|
|
694
|
+
* newlines, CR, unicode — is taken literally). So we escape `\` → `\\` and
|
|
695
|
+
* `"` → `\"` (the only breakout vectors), render `\n`/`\t` as their recognized
|
|
696
|
+
* escapes, and leave everything else raw. Verified against the real engine:
|
|
697
|
+
* quotes, backslashes, `$N`, `"); drop … --`, raw CR, and emoji all round-trip
|
|
698
|
+
* as data and cannot break out of the literal or inject a second statement.
|
|
699
|
+
*/
|
|
700
|
+
export declare function encodePowqlLiteral(value: unknown, position?: string): string;
|
|
701
|
+
/**
|
|
702
|
+
* The newest PowDB engine LINE (major.minor) whose lexer escape handling
|
|
703
|
+
* {@link encodePowqlString} is VERIFIED against by reading
|
|
704
|
+
* `crates/query/src/lexer.rs`. The legacy materialize path
|
|
705
|
+
* ({@link materializePowql}) inlines encoded string literals directly into query
|
|
706
|
+
* text, so it is only injection-safe while the lexer recognizes exactly the
|
|
707
|
+
* escape set the escaper emits (`\"`, `\\`, `\n`, `\t`, everything else raw). If
|
|
708
|
+
* a future engine line teaches the lexer new escapes (e.g. `\u`, `\x`), a string
|
|
709
|
+
* that the escaper leaves raw could be re-interpreted by the lexer and break out
|
|
710
|
+
* of the literal, turning the fallback into an injection primitive.
|
|
711
|
+
*
|
|
712
|
+
* CONTRACT: bump this ceiling ONLY after re-verifying the escape handling in
|
|
713
|
+
* `crates/query/src/lexer.rs` for the newer line AND confirming
|
|
714
|
+
* {@link encodePowqlString} still escapes every breakout vector the lexer
|
|
715
|
+
* recognizes. The legacy path guards on this value (see
|
|
716
|
+
* {@link PowdbEmbeddedPool.exec}): an embedded addon whose engine line exceeds
|
|
717
|
+
* the ceiling yet still routes through the string wire is refused rather than
|
|
718
|
+
* materialized.
|
|
719
|
+
*
|
|
720
|
+
* Verification for the 0.19 line: `crates/query/src/lexer.rs` is byte-identical
|
|
721
|
+
* between v0.18.0 and v0.19.0 (empty git diff), and `link` was already a lexer
|
|
722
|
+
* keyword at 0.18.0. The 0.19 entity-links surface adds new STATEMENTS built from
|
|
723
|
+
* pre-existing tokens, so the tokenization / escape surface this ceiling guards is
|
|
724
|
+
* unmoved. The 0.19.1 link-introspection / link-path round is likewise lexer-neutral:
|
|
725
|
+
* `git diff v0.19.0 v0.19.1 -- crates/query/src/lexer.rs` is empty (the bare-dotted-path
|
|
726
|
+
* hard error is parser-level, not tokenization), so this ceiling stays `'0.19'`. The
|
|
727
|
+
* guard in {@link PowdbEmbeddedPool.exec} compares major.minor only, so `'0.19'`
|
|
728
|
+
* already covers every 0.19.x patch — no bump is needed for 0.19.1.
|
|
729
|
+
*/
|
|
730
|
+
export declare const POWQL_LEXER_TESTED_CEILING = "0.19";
|
|
731
|
+
/**
|
|
732
|
+
* Substitute every `$N` placeholder in a generator-produced PowQL template with
|
|
733
|
+
* the encoded literal of `params[N-1]`. Safe because the template is produced by
|
|
734
|
+
* {@link PowqlInterface} and contains **no** user string literals — the only
|
|
735
|
+
* `$<digits>` tokens are genuine positional placeholders, so a single scan
|
|
736
|
+
* cannot accidentally rewrite a `$N` that is itself part of a value (values are
|
|
737
|
+
* params, never inlined into the template by the generator).
|
|
738
|
+
*/
|
|
739
|
+
export declare function materializePowql(powql: string, params: unknown[]): string;
|
|
740
|
+
/**
|
|
741
|
+
* A {@link PgCompatPool} backed by an in-process `@zvndev/powdb-embedded`
|
|
742
|
+
* `Database`. On the addon's typed native wire (≥ 0.14, when
|
|
743
|
+
* `capabilities.nativeRaw` is set) this pool binds positional `$N` params via
|
|
744
|
+
* `queryWithParams` and decodes the typed cells, exactly like the networked
|
|
745
|
+
* transport. On an older addon (no `queryWithParams`) it falls back to the
|
|
746
|
+
* legacy string wire, which takes **no params array** (its `query(powql)`
|
|
747
|
+
* accepts only a string), so each positional `$N` is materialized into a PowQL
|
|
748
|
+
* literal via {@link materializePowql} before the text is handed to the engine.
|
|
749
|
+
* One handle, single connection: transaction keywords (`begin`/`commit`/
|
|
750
|
+
* `rollback`) are issued serially as ordinary queries.
|
|
751
|
+
*/
|
|
752
|
+
export declare class PowdbEmbeddedPool implements PgCompatPool {
|
|
753
|
+
private readonly db;
|
|
754
|
+
private closed;
|
|
755
|
+
/**
|
|
756
|
+
* Single-writer gate. The embedded engine is one handle with one global
|
|
757
|
+
* write lock — only one transaction may be open at a time. A re-entrant
|
|
758
|
+
* `begin` (a fresh top-level `db.$transaction` opened inside an open one's
|
|
759
|
+
* callback) would otherwise hit PowDB's raw "already in a transaction"
|
|
760
|
+
* parse error; the gate surfaces a typed E017 instead, while INDEPENDENT
|
|
761
|
+
* concurrent transactions queue FIFO and run one at a time. (Nested
|
|
762
|
+
* `tx.$transaction` is caught earlier still, by the savepoint override in
|
|
763
|
+
* {@link powdbDialect}.)
|
|
764
|
+
*/
|
|
765
|
+
private readonly txGate;
|
|
766
|
+
/** Hold taken by a `begin` issued via `query()` directly (no checked-out client). */
|
|
767
|
+
private readonly poolHoldRef;
|
|
768
|
+
/**
|
|
769
|
+
* Feature capabilities of the embedded engine (resolved from the addon
|
|
770
|
+
* package version). `nativeRaw` is true when the addon is ≥ 0.14 and the
|
|
771
|
+
* opened handle exposes `queryWithParams` (the typed native wire); an older
|
|
772
|
+
* addon has no such method, so it stays false and the legacy string wire is
|
|
773
|
+
* used.
|
|
774
|
+
*/
|
|
775
|
+
readonly capabilities: PowdbCapabilities;
|
|
776
|
+
/** Carried for surface uniformity with {@link PowdbPool}; inert on embedded (no protocol_error frames). */
|
|
777
|
+
readonly retryStaleReads: boolean;
|
|
778
|
+
/**
|
|
779
|
+
* True when this pool was opened read-only (an `{ embedded, readonly: true }`
|
|
780
|
+
* target, or a directly-constructed pool passed `readonly: true`). Read by
|
|
781
|
+
* {@link PowqlInterface}'s exec seam to fail writes fast with E018 before the
|
|
782
|
+
* wire; the engine's own refusal (mapped by {@link wrapPowdbError}) is the
|
|
783
|
+
* backstop for raw / injected paths.
|
|
784
|
+
*/
|
|
785
|
+
readonly readonly: boolean;
|
|
786
|
+
constructor(db: EmbeddedDatabase, options?: PowdbPoolOptions);
|
|
787
|
+
/** Run the PowQL on the in-process engine, choosing the native or legacy wire. */
|
|
788
|
+
private exec;
|
|
789
|
+
/**
|
|
790
|
+
* Run one statement, gating transaction control. `holdRef` scopes the gate
|
|
791
|
+
* hold to whoever issued the `begin` (the pool itself or one checked-out
|
|
792
|
+
* client), so finishing a transaction can never release a slot a different
|
|
793
|
+
* transaction is holding.
|
|
794
|
+
*/
|
|
795
|
+
private run;
|
|
796
|
+
query(text: QueryArg, values?: unknown[]): Promise<any>;
|
|
797
|
+
connect(): Promise<PgCompatPoolClient>;
|
|
798
|
+
end(): Promise<void>;
|
|
799
|
+
}
|
|
800
|
+
export { introspectPowdbDatabase, type PowdbExec, type PowdbIntrospectOptions, } from './powdb-introspect.js';
|
|
801
|
+
export { PowqlInterface } from './powql.js';
|
|
802
|
+
/** Options for {@link turbinePowDB}. */
|
|
803
|
+
export interface TurbinePowdbOptions extends Pick<TurbineConfig, 'logging' | 'defaultLimit' | 'warnOnUnlimited' | 'relationLoadStrategy'> {
|
|
804
|
+
/**
|
|
805
|
+
* Client-level default `with`-relation load strategy. On PowDB the default is
|
|
806
|
+
* the batched N+1 loaders; setting `'join'` opts INTO native PowQL server-side
|
|
807
|
+
* joins for eligible top-level relations (ineligible ones, e.g. a paged parent
|
|
808
|
+
* or a nested `with`, fall back to the loaders per-relation and silently). A
|
|
809
|
+
* per-query `relationLoadStrategy` arg still overrides this. Requires an engine
|
|
810
|
+
* that advertises `serverJoins` (PowDB ≥ 0.13); a per-query `'join'` on an
|
|
811
|
+
* older engine throws E017, a client-level default silently falls back.
|
|
812
|
+
*/
|
|
813
|
+
relationLoadStrategy?: TurbineConfig['relationLoadStrategy'];
|
|
814
|
+
/** Max pooled connections (default 10). Networked transport only. */
|
|
815
|
+
connectionLimit?: number;
|
|
816
|
+
/**
|
|
817
|
+
* Max time (ms) a concurrent `$transaction` waits in the FIFO queue for
|
|
818
|
+
* PowDB's single global write lock before failing with a typed
|
|
819
|
+
* `TimeoutError` (default {@link DEFAULT_TX_QUEUE_TIMEOUT_MS} = 30 000;
|
|
820
|
+
* `0` / `Infinity` = wait without limit). Independent concurrent
|
|
821
|
+
* transactions queue and run one at a time; only a re-entrant
|
|
822
|
+
* `db.$transaction` (opened inside an active transaction callback) throws
|
|
823
|
+
* E017 — queueing that shape would deadlock.
|
|
824
|
+
*
|
|
825
|
+
* Ignored when you inject an already-constructed {@link PowdbPool} (it carries
|
|
826
|
+
* its own {@link PowdbPoolOptions}); set it on that pool's constructor instead.
|
|
827
|
+
*/
|
|
828
|
+
transactionQueueTimeoutMs?: number;
|
|
829
|
+
/**
|
|
830
|
+
* Opt in to replaying a first-statement READ once (on a fresh connection)
|
|
831
|
+
* when it fails with the stale-wire-frame {@link ConnectionError} that a
|
|
832
|
+
* request can hit after a long idle gap. Networked only; WRITES and any
|
|
833
|
+
* statement inside a transaction are NEVER retried (an ambiguous mutation
|
|
834
|
+
* reply is unsafe to replay). Default `false`: the error is surfaced typed
|
|
835
|
+
* so the caller can decide. See the retry recipe in the docs.
|
|
836
|
+
*
|
|
837
|
+
* Ignored when you inject an already-constructed {@link PowdbPool} (it carries
|
|
838
|
+
* its own {@link PowdbPoolOptions}); set it on that pool's constructor instead.
|
|
839
|
+
*/
|
|
840
|
+
retryStaleReads?: boolean;
|
|
841
|
+
/**
|
|
842
|
+
* Override the detected engine version used for capability gating. For exotic
|
|
843
|
+
* deployments and injected pools whose version cannot be probed (a non-semver
|
|
844
|
+
* server string, or an addon whose package.json cannot be resolved): pass
|
|
845
|
+
* e.g. `'0.13.0'` to unlock the features that version supports. Without it, an
|
|
846
|
+
* undetectable version turns every version-gated feature OFF (with a hinting
|
|
847
|
+
* E017).
|
|
848
|
+
*/
|
|
849
|
+
assumeEngineVersion?: string;
|
|
850
|
+
/**
|
|
851
|
+
* Mark the client read-only: a write (or a transaction `begin`) fails fast
|
|
852
|
+
* locally with a {@link ReadOnlyError} (E018) before it reaches the wire,
|
|
853
|
+
* rather than round-tripping to the engine's refusal. Works on both
|
|
854
|
+
* transports (a networked pool bound to a read-only role, or an embedded
|
|
855
|
+
* handle). An `{ embedded, readonly: true }` target implies this. Default
|
|
856
|
+
* `false`.
|
|
857
|
+
*
|
|
858
|
+
* Ignored when you inject an already-constructed {@link PowdbPool} (it carries
|
|
859
|
+
* its own {@link PowdbPoolOptions}); set it on that pool's constructor instead.
|
|
860
|
+
*/
|
|
861
|
+
readonly?: boolean;
|
|
862
|
+
/**
|
|
863
|
+
* Driver-module injection for the networked target forms (URL / host+port):
|
|
864
|
+
* bypasses the dynamic `import('@zvndev/powdb-client')` and uses this object
|
|
865
|
+
* as the driver module instead. Intended for tests (a fake pool that counts
|
|
866
|
+
* connections) and advanced embedding; everyday callers never set it.
|
|
867
|
+
*/
|
|
868
|
+
powdbClientModule?: PowdbModule;
|
|
869
|
+
/**
|
|
870
|
+
* Driver-module injection for the **embedded** target form (`{ embedded }`):
|
|
871
|
+
* bypasses the dynamic `import('@zvndev/powdb-embedded')` and uses this object
|
|
872
|
+
* as the addon module instead. Intended for tests (a fake `Database` factory
|
|
873
|
+
* that records how the handle was opened) and advanced embedding; everyday
|
|
874
|
+
* callers never set it. The symmetric counterpart to {@link powdbClientModule}.
|
|
875
|
+
*/
|
|
876
|
+
powdbEmbeddedModule?: EmbeddedModule;
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Selects the **embedded** transport — an in-process `@zvndev/powdb-embedded`
|
|
880
|
+
* database at the given data directory (no server, no socket). The value is the
|
|
881
|
+
* data dir path. Preview: Full-durability checkpoint-bound; built binaries ship
|
|
882
|
+
* for macOS (arm64/x64) and Unix-glibc only (Intel-mac/musl/Windows fall back to
|
|
883
|
+
* a from-source `npm run build`).
|
|
884
|
+
*
|
|
885
|
+
* @example
|
|
886
|
+
* ```ts
|
|
887
|
+
* const db = await turbinePowDB({ embedded: '/var/data/app.powdb' }, SCHEMA);
|
|
888
|
+
* // Faster writes (fsync off the commit path, bounded-loss) — requires addon >= 0.7.1:
|
|
889
|
+
* const fast = await turbinePowDB({ embedded: '/var/data/app.powdb', syncMode: 'normal' }, SCHEMA);
|
|
890
|
+
* ```
|
|
891
|
+
*/
|
|
892
|
+
export interface TurbinePowdbEmbeddedTarget {
|
|
893
|
+
embedded: string;
|
|
894
|
+
/**
|
|
895
|
+
* WAL durability for the embedded engine (requires `@zvndev/powdb-embedded` ≥ 0.7.1):
|
|
896
|
+
* `'full'` (default — fsync per commit), `'normal'` (fsync off the commit path,
|
|
897
|
+
* ~15–40× faster writes, bounded loss on OS crash/power loss), `'off'` (bench-only).
|
|
898
|
+
*/
|
|
899
|
+
syncMode?: 'full' | 'normal' | 'off';
|
|
900
|
+
/** Per-query memory budget in bytes (requires `@zvndev/powdb-embedded` ≥ 0.7.1). */
|
|
901
|
+
memoryLimit?: number;
|
|
902
|
+
/**
|
|
903
|
+
* Open the data directory read-only for snapshot serving (requires
|
|
904
|
+
* `@zvndev/powdb-embedded` ≥ 0.14: `openReadOnly` / `openReadOnlyWithMemoryLimit`).
|
|
905
|
+
* A write through a read-only handle is refused by the engine with
|
|
906
|
+
* `readonly mode: statement requires a writer …` (→ {@link ReadOnlyError}, E018),
|
|
907
|
+
* and Turbine additionally fails writes fast locally (this implies the pool's
|
|
908
|
+
* `readonly` flag). Meaningless together with `syncMode` (a read-only engine
|
|
909
|
+
* never writes), setting both throws a {@link ValidationError}.
|
|
910
|
+
*/
|
|
911
|
+
readonly?: boolean;
|
|
912
|
+
}
|
|
913
|
+
/**
|
|
914
|
+
* Bind Turbine to PowDB. `target` is one of:
|
|
915
|
+
* - a `powdb://[user[:pass]@]host[:port][/db]` connection string → a
|
|
916
|
+
* **networked** `@zvndev/powdb-client` pool (consistency with
|
|
917
|
+
* `turbineMysql`/`turbineMssql`);
|
|
918
|
+
* - a host/port options object → a **networked** `@zvndev/powdb-client` pool;
|
|
919
|
+
* - an `{ embedded: <data-dir> }` object → an in-process
|
|
920
|
+
* `@zvndev/powdb-embedded` database (no server);
|
|
921
|
+
* - an already-constructed `@zvndev/powdb-client` `Pool` or {@link PowdbPool}
|
|
922
|
+
* (injection — you own its lifecycle and `disconnect()` is a no-op).
|
|
923
|
+
*
|
|
924
|
+
* On the networked transport the server version is probed and a clear
|
|
925
|
+
* {@link ConnectionError} is thrown if it is older than {@link MIN_POWDB_VERSION}
|
|
926
|
+
* (the `returning` keyword / int->float coercion fix Turbine relies on).
|
|
927
|
+
*
|
|
928
|
+
* Resolves to a `TurbineClient` whose `table()` accessors generate **PowQL** via
|
|
929
|
+
* {@link PowqlInterface}. The SQL `Dialect` is not involved.
|
|
930
|
+
*/
|
|
931
|
+
export declare function turbinePowDB(target: string | PowdbConnOptions | PowdbClientPool | PowdbPool | TurbinePowdbEmbeddedTarget, schema: SchemaMetadata, options?: TurbinePowdbOptions): Promise<TurbineClient>;
|