turbine-orm 0.21.0 → 0.23.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 +19 -2
- package/dist/cjs/client.js +11 -2
- package/dist/cjs/generate.js +4 -0
- package/dist/cjs/introspect.js +6 -0
- package/dist/cjs/powdb.js +865 -0
- package/dist/cjs/powql.js +1262 -0
- package/dist/cli/ui.d.ts +1 -1
- package/dist/client.js +11 -2
- package/dist/generate.js +4 -0
- package/dist/introspect.js +6 -0
- package/dist/powdb.d.ts +341 -0
- package/dist/powdb.js +816 -0
- package/dist/powql.d.ts +205 -0
- package/dist/powql.js +1226 -0
- package/dist/query/builder.d.ts +8 -0
- package/dist/schema.d.ts +10 -0
- package/package.json +16 -1
package/dist/cli/ui.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ export declare const symbols: {
|
|
|
40
40
|
readonly bottomLeft: "+" | "╰";
|
|
41
41
|
readonly bottomRight: "+" | "╯";
|
|
42
42
|
readonly tee: "|" | "├";
|
|
43
|
-
readonly teeEnd: "
|
|
43
|
+
readonly teeEnd: "\\" | "└";
|
|
44
44
|
};
|
|
45
45
|
export declare function box(content: string, options?: {
|
|
46
46
|
title?: string;
|
package/dist/client.js
CHANGED
|
@@ -113,7 +113,9 @@ export class TransactionClient {
|
|
|
113
113
|
// We use a proxy pool that routes queries through the transaction client
|
|
114
114
|
const txPool = this.createTxPool();
|
|
115
115
|
const txOpts = { ...this.queryOptions, _txScoped: true };
|
|
116
|
-
qi =
|
|
116
|
+
qi = txOpts.queryInterfaceFactory
|
|
117
|
+
? txOpts.queryInterfaceFactory(txPool, name, this.schema, this.middlewares, txOpts)
|
|
118
|
+
: new QueryInterface(txPool, name, this.schema, this.middlewares, txOpts);
|
|
117
119
|
this.tableCache.set(name, qi);
|
|
118
120
|
}
|
|
119
121
|
return qi;
|
|
@@ -254,6 +256,11 @@ export class TurbineClient {
|
|
|
254
256
|
preparedStatements: envDisablePrepared ? false : (config.preparedStatements ?? !config.pool),
|
|
255
257
|
sqlCache: config.sqlCache ?? true,
|
|
256
258
|
dialect: config.dialect,
|
|
259
|
+
// Non-SQL backends (PowDB) inject a factory that builds their own query
|
|
260
|
+
// interface (PowqlInterface) instead of the SQL QueryInterface. SQL engines
|
|
261
|
+
// never set this, so `table()` keeps constructing `new QueryInterface`.
|
|
262
|
+
queryInterfaceFactory: config
|
|
263
|
+
.queryInterfaceFactory,
|
|
257
264
|
_onQuery: (event) => {
|
|
258
265
|
if (this.queryListeners.size === 0)
|
|
259
266
|
return;
|
|
@@ -405,7 +412,9 @@ export class TurbineClient {
|
|
|
405
412
|
table(name) {
|
|
406
413
|
let qi = this.tableCache.get(name);
|
|
407
414
|
if (!qi) {
|
|
408
|
-
qi =
|
|
415
|
+
qi = this.queryOptions?.queryInterfaceFactory
|
|
416
|
+
? this.queryOptions.queryInterfaceFactory(this.pool, name, this.schema, this.middlewares, this.queryOptions)
|
|
417
|
+
: new QueryInterface(this.pool, name, this.schema, this.middlewares, this.queryOptions);
|
|
409
418
|
this.tableCache.set(name, qi);
|
|
410
419
|
}
|
|
411
420
|
return qi;
|
package/dist/generate.js
CHANGED
|
@@ -504,6 +504,10 @@ function serializeColumn(col) {
|
|
|
504
504
|
`arrayType: '${escSQ(col.arrayType ?? col.pgArrayType)}'`,
|
|
505
505
|
`pgArrayType: '${escSQ(col.pgArrayType)}'`,
|
|
506
506
|
];
|
|
507
|
+
// Emit isGenerated only when set (server-generated serial/identity), so the
|
|
508
|
+
// output stays byte-identical for the common client-default columns.
|
|
509
|
+
if (col.isGenerated)
|
|
510
|
+
parts.push(`isGenerated: true`);
|
|
507
511
|
if (col.maxLength !== undefined)
|
|
508
512
|
parts.push(`maxLength: ${col.maxLength}`);
|
|
509
513
|
return `{ ${parts.join(', ')} }`;
|
package/dist/introspect.js
CHANGED
|
@@ -28,6 +28,7 @@ const SQL_COLUMNS = `
|
|
|
28
28
|
data_type,
|
|
29
29
|
is_nullable,
|
|
30
30
|
column_default,
|
|
31
|
+
is_identity,
|
|
31
32
|
ordinal_position,
|
|
32
33
|
character_maximum_length
|
|
33
34
|
FROM information_schema.columns
|
|
@@ -163,6 +164,11 @@ export async function introspectPostgresCatalog(options) {
|
|
|
163
164
|
pgTypeToTs(isArray ? dialectType : baseType, isNullable),
|
|
164
165
|
nullable: isNullable,
|
|
165
166
|
hasDefault: row.column_default !== null,
|
|
167
|
+
// Server-generated = a sequence default (serial/BIGSERIAL → nextval(…))
|
|
168
|
+
// or an IDENTITY column. Distinct from a client-side default expression
|
|
169
|
+
// (gen_random_uuid(), now()), which Turbine must still synthesize.
|
|
170
|
+
isGenerated: (typeof row.column_default === 'string' && row.column_default.includes('nextval(')) ||
|
|
171
|
+
row.is_identity === 'YES',
|
|
166
172
|
isArray,
|
|
167
173
|
arrayType,
|
|
168
174
|
pgArrayType: arrayType,
|
package/dist/powdb.d.ts
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
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/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/pipelining** — nested
|
|
26
|
+
* transactions / isolation / vector / LISTEN-NOTIFY / RLS throw.
|
|
27
|
+
*
|
|
28
|
+
* `@zvndev/powdb-client` is an **optional peer dependency** loaded by dynamic
|
|
29
|
+
* import; `npm i turbine-orm` still pulls only `pg`.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { turbinePowDB } from 'turbine-orm/powdb';
|
|
34
|
+
* import { SCHEMA } from './generated/turbine/metadata.js';
|
|
35
|
+
*
|
|
36
|
+
* const db = await turbinePowDB({ host: '127.0.0.1', port: 5433 }, SCHEMA);
|
|
37
|
+
* const user = await db.table('users').create({ data: { name: 'Ada' } }); // UUID id auto-generated
|
|
38
|
+
* const found = await db.table('users').findMany({ where: { name: 'Ada' }, limit: 10 });
|
|
39
|
+
* await db.disconnect();
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @module
|
|
43
|
+
*/
|
|
44
|
+
import { type PgCompatPool, type PgCompatPoolClient, TurbineClient, type TurbineConfig } from './client.js';
|
|
45
|
+
import { type Dialect } from './dialect.js';
|
|
46
|
+
import type { ColumnMetadata, SchemaMetadata, TableMetadata } from './schema.js';
|
|
47
|
+
/**
|
|
48
|
+
* Capability descriptor for PowDB. PowQL generation is owned by
|
|
49
|
+
* {@link PowqlInterface} (not the SQL `Dialect`), so this dialect exists only to
|
|
50
|
+
* drive `TurbineClient`'s capability gating and transaction keywords:
|
|
51
|
+
* - `supports*` flags are all `false` for the Postgres-only features, so
|
|
52
|
+
* `$listen`/`$notify`, RLS `sessionContext`/`$withSession`, and pgvector
|
|
53
|
+
* throw a clear {@link UnsupportedFeatureError} (E017) at the client surface
|
|
54
|
+
* instead of emitting SQL that PowDB cannot parse.
|
|
55
|
+
* - `begin`/`commit`/`rollback` are lowercase PowQL keywords (verified on the
|
|
56
|
+
* wire) so a single-level `$transaction` works.
|
|
57
|
+
* - PowDB has a single global write lock and supports neither savepoints nor
|
|
58
|
+
* nested/concurrent transactions. The `savepoint*` keywords therefore throw
|
|
59
|
+
* {@link UnsupportedFeatureError} (E017): a nested `tx.$transaction` emits a
|
|
60
|
+
* savepoint synchronously (before any DB call) and so fails fast with a
|
|
61
|
+
* clear typed error instead of leaking PowDB's cryptic `Parse(... 'sp_1')`.
|
|
62
|
+
* The pool-level begin-while-active guard (see {@link PowdbPool}) catches the
|
|
63
|
+
* other re-entrant shape — a fresh top-level `db.$transaction` opened inside
|
|
64
|
+
* an already-open one — before it can deadlock on the write lock.
|
|
65
|
+
* Isolation levels remain Phase B.
|
|
66
|
+
*/
|
|
67
|
+
export declare const powdbDialect: Dialect;
|
|
68
|
+
/** A single value PowDB accepts as a positional `$N` parameter. */
|
|
69
|
+
type PowdbParam = string | number | bigint | boolean | null;
|
|
70
|
+
/**
|
|
71
|
+
* Marker wrapper for a value bound to a `float` column. The networked driver
|
|
72
|
+
* unwraps it to the plain number (the wire param is unchanged), but the
|
|
73
|
+
* *embedded* literal encoder reads it to emit a float-form PowQL literal (`42`
|
|
74
|
+
* → `42.0`) so an integer-valued float column stays unambiguously a float.
|
|
75
|
+
* Constructed in {@link PowqlInterface.param}.
|
|
76
|
+
*/
|
|
77
|
+
export declare class PowdbFloatParam {
|
|
78
|
+
readonly value: number;
|
|
79
|
+
constructor(value: number);
|
|
80
|
+
}
|
|
81
|
+
/** The four shapes a PowQL result takes over the wire. */
|
|
82
|
+
type PowdbResult = {
|
|
83
|
+
kind: 'rows';
|
|
84
|
+
columns: string[];
|
|
85
|
+
rows: string[][];
|
|
86
|
+
} | {
|
|
87
|
+
kind: 'scalar';
|
|
88
|
+
value: string;
|
|
89
|
+
} | {
|
|
90
|
+
kind: 'ok';
|
|
91
|
+
affected: bigint;
|
|
92
|
+
} | {
|
|
93
|
+
kind: 'message';
|
|
94
|
+
message: string;
|
|
95
|
+
};
|
|
96
|
+
interface PowdbClient {
|
|
97
|
+
readonly serverVersion: string;
|
|
98
|
+
query(query: string, params?: PowdbParam[], opts?: {
|
|
99
|
+
signal?: AbortSignal;
|
|
100
|
+
}): Promise<PowdbResult>;
|
|
101
|
+
close(): Promise<void>;
|
|
102
|
+
}
|
|
103
|
+
interface PowdbClientPool {
|
|
104
|
+
acquire(): Promise<PowdbClient>;
|
|
105
|
+
release(c: PowdbClient): void;
|
|
106
|
+
destroy(c: PowdbClient): void;
|
|
107
|
+
withClient<T>(fn: (c: PowdbClient) => Promise<T>): Promise<T>;
|
|
108
|
+
close(): Promise<void>;
|
|
109
|
+
}
|
|
110
|
+
/** Connection options for {@link turbinePowDB} — host/port, not a connection string. */
|
|
111
|
+
export interface PowdbConnOptions {
|
|
112
|
+
host: string;
|
|
113
|
+
port: number;
|
|
114
|
+
dbName?: string;
|
|
115
|
+
user?: string;
|
|
116
|
+
password?: string | null;
|
|
117
|
+
connectTimeoutMs?: number;
|
|
118
|
+
tls?: boolean;
|
|
119
|
+
}
|
|
120
|
+
/** Minimum PowDB server version the networked transport requires. */
|
|
121
|
+
export declare const MIN_POWDB_VERSION = "0.7.0";
|
|
122
|
+
/**
|
|
123
|
+
* Parse a `powdb://[user[:pass]@]host[:port][/db]` connection string into
|
|
124
|
+
* {@link PowdbConnOptions} (consistency with `turbineMysql`/`turbineMssql`,
|
|
125
|
+
* which accept a URL). Defaults: host `127.0.0.1`, port `5433`.
|
|
126
|
+
*/
|
|
127
|
+
export declare function parsePowdbUrl(connectionString: string): PowdbConnOptions;
|
|
128
|
+
/**
|
|
129
|
+
* Fail fast if a networked PowDB server is older than {@link MIN_POWDB_VERSION}.
|
|
130
|
+
* Turbine's write path relies on the trailing `returning` keyword and the
|
|
131
|
+
* int→float coercion fix, both of which landed in 0.7.0. Embedded exposes no
|
|
132
|
+
* version method, so this is networked-only (the embedded peer is pinned ^0.7.0
|
|
133
|
+
* at install time). A non-semver / empty version string is tolerated (we cannot
|
|
134
|
+
* prove it is too old).
|
|
135
|
+
*/
|
|
136
|
+
export declare function assertSupportedPowdbVersion(version: string | undefined): void;
|
|
137
|
+
/** PowQL column types Turbine is willing to emit (the four writable scalars). */
|
|
138
|
+
export type PowqlType = 'str' | 'int' | 'float' | 'bool';
|
|
139
|
+
/**
|
|
140
|
+
* Map a Turbine column to the PowQL DDL type used in `defineSchema` →
|
|
141
|
+
* `type T { … }`. Turbine never emits PowDB's `uuid`/`datetime`/`bytes` types,
|
|
142
|
+
* which cannot hold client-supplied values on the wire (no literal, no cast):
|
|
143
|
+
* - `Date` → `int` (epoch micros) - `boolean` → `bool`
|
|
144
|
+
* - integral `number`/`bigint` → `int` - fractional `number` → `float`
|
|
145
|
+
* - everything else (incl. UUID/PK strings) → `str`
|
|
146
|
+
* Array / JSON / bytes columns throw — they have no PowDB equivalent.
|
|
147
|
+
*/
|
|
148
|
+
export declare function powqlColumnType(col: ColumnMetadata): PowqlType;
|
|
149
|
+
/**
|
|
150
|
+
* Generate PowQL DDL (`type T { … }`) for every table in a schema. Used to
|
|
151
|
+
* provision a PowDB database from a code-first `defineSchema`/`SchemaMetadata`
|
|
152
|
+
* (PowDB has no migration runner yet). The primary key column is declared
|
|
153
|
+
* `required unique`; non-nullable columns are `required`. A server-generated
|
|
154
|
+
* column ({@link ColumnMetadata.isGenerated}) that maps to PowQL `int` gets the
|
|
155
|
+
* `auto` modifier, so PowDB assigns a monotonic id on insert and Turbine stops
|
|
156
|
+
* synthesizing a client-side value for it.
|
|
157
|
+
*/
|
|
158
|
+
export declare function powqlSchemaDDL(schema: SchemaMetadata): string[];
|
|
159
|
+
/**
|
|
160
|
+
* Coerce a single PowDB wire string into the JS value its column type implies.
|
|
161
|
+
* Every PowDB value arrives as a string; NULL arrives as the bareword `"null"`.
|
|
162
|
+
* Metadata resolves the `"null"` ambiguity for nullable non-string columns.
|
|
163
|
+
*/
|
|
164
|
+
export declare function coerceValue(raw: string, col: ColumnMetadata): unknown;
|
|
165
|
+
/**
|
|
166
|
+
* Map one raw PowDB row (snake-cased columns → raw wire strings, as produced by
|
|
167
|
+
* {@link PowdbPool}) into a typed entity (camelCase fields, coerced values).
|
|
168
|
+
* Only the columns present in `raw` are emitted, so partial `select` projections
|
|
169
|
+
* round-trip unchanged.
|
|
170
|
+
*/
|
|
171
|
+
export declare function rowToEntity(raw: Record<string, unknown>, meta: TableMetadata): Record<string, unknown>;
|
|
172
|
+
/**
|
|
173
|
+
* Translate a PowDB error into a typed Turbine error. Handles BOTH transports,
|
|
174
|
+
* whose error shapes differ:
|
|
175
|
+
* - **networked** (`@zvndev/powdb-client`) tags errors with a *semantic*
|
|
176
|
+
* `.code` (`connect_failed`, `timeout`, `query_failed`, …);
|
|
177
|
+
* - **embedded** (`@zvndev/powdb-embedded` napi addon) tags EVERY error
|
|
178
|
+
* `code:'GenericFailure'`, so the class can only be recovered from the
|
|
179
|
+
* message text (`Execution("column 'email' is required …")`,
|
|
180
|
+
* `Execution("type mismatch …")`, `Parse(…)`, `StorageError(…)`).
|
|
181
|
+
*
|
|
182
|
+
* So we always run the unique-constraint and message-shape checks first (they
|
|
183
|
+
* fire for both transports), then fall through to the networked `.code` switch.
|
|
184
|
+
*/
|
|
185
|
+
export declare function wrapPowdbError(err: unknown): Error;
|
|
186
|
+
type QueryArg = string | {
|
|
187
|
+
name?: string;
|
|
188
|
+
text: string;
|
|
189
|
+
values?: unknown[];
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
* A {@link PgCompatPool} backed by a `@zvndev/powdb-client` `Pool`. The query
|
|
193
|
+
* `text` is **PowQL**, not SQL — {@link PowqlInterface} generates it. Rows come
|
|
194
|
+
* back as raw strings here; per-column JS coercion happens in `PowqlInterface`
|
|
195
|
+
* (it owns the schema metadata).
|
|
196
|
+
*/
|
|
197
|
+
export declare class PowdbPool implements PgCompatPool {
|
|
198
|
+
readonly pool: PowdbClientPool;
|
|
199
|
+
private readonly toParam;
|
|
200
|
+
private closed;
|
|
201
|
+
/**
|
|
202
|
+
* Pool-level single-writer guard. PowDB holds one global write lock, so at
|
|
203
|
+
* most one transaction may be open across the whole pool. A `begin` issued
|
|
204
|
+
* while this is `true` is rejected (it would otherwise check out a second
|
|
205
|
+
* connection and block on the lock forever — the networked re-entrant hang).
|
|
206
|
+
*/
|
|
207
|
+
private activeTransaction;
|
|
208
|
+
constructor(pool: PowdbClientPool, toParam?: (v: unknown, i: number) => PowdbParam);
|
|
209
|
+
/**
|
|
210
|
+
* Enforce the single-writer model on a transaction-control statement. Throws
|
|
211
|
+
* (before any query runs) if a `begin` arrives while a transaction is open;
|
|
212
|
+
* otherwise flips the pool-level flag. Returns the control kind so the caller
|
|
213
|
+
* can decide whether it even needs to hit the engine.
|
|
214
|
+
*/
|
|
215
|
+
private guardTxControl;
|
|
216
|
+
query(text: QueryArg, values?: unknown[]): Promise<any>;
|
|
217
|
+
connect(): Promise<PgCompatPoolClient>;
|
|
218
|
+
end(): Promise<void>;
|
|
219
|
+
}
|
|
220
|
+
/** The embedded addon's result shape (matches {@link PowdbResult} but with optional fields). */
|
|
221
|
+
interface EmbeddedQueryResult {
|
|
222
|
+
kind: string;
|
|
223
|
+
columns?: string[];
|
|
224
|
+
rows?: string[][];
|
|
225
|
+
value?: string;
|
|
226
|
+
affected?: bigint;
|
|
227
|
+
message?: string;
|
|
228
|
+
}
|
|
229
|
+
/** A single in-process embedded database handle (`@zvndev/powdb-embedded`). */
|
|
230
|
+
interface EmbeddedDatabase {
|
|
231
|
+
query(powql: string): EmbeddedQueryResult;
|
|
232
|
+
querySql(sql: string): EmbeddedQueryResult;
|
|
233
|
+
queryReadonly(powql: string): EmbeddedQueryResult;
|
|
234
|
+
isPoisoned(): boolean;
|
|
235
|
+
/** WAL durability selector — `@zvndev/powdb-embedded` ≥ 0.7.1. */
|
|
236
|
+
setSyncMode?(mode: string): void;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Encode a JS value as a **PowQL literal** for the embedded driver, which takes
|
|
240
|
+
* no params array — `$N` placeholders must be materialized into the query text.
|
|
241
|
+
*
|
|
242
|
+
* This is the single place Turbine builds PowQL text from a value, so it is the
|
|
243
|
+
* security-critical surface. String encoding matches PowDB's lexer
|
|
244
|
+
* (`crates/query/src/lexer.rs`) exactly: a string literal is `"…"`, and inside
|
|
245
|
+
* it the lexer recognizes only the escapes `\"`, `\\`, `\n`, `\t` (any other
|
|
246
|
+
* `\x` drops the backslash and keeps `x`; every non-`\`/non-`"` char — raw
|
|
247
|
+
* newlines, CR, unicode — is taken literally). So we escape `\` → `\\` and
|
|
248
|
+
* `"` → `\"` (the only breakout vectors), render `\n`/`\t` as their recognized
|
|
249
|
+
* escapes, and leave everything else raw. Verified against the real engine:
|
|
250
|
+
* quotes, backslashes, `$N`, `"); drop … --`, raw CR, and emoji all round-trip
|
|
251
|
+
* as data and cannot break out of the literal or inject a second statement.
|
|
252
|
+
*/
|
|
253
|
+
export declare function encodePowqlLiteral(value: unknown): string;
|
|
254
|
+
/**
|
|
255
|
+
* Substitute every `$N` placeholder in a generator-produced PowQL template with
|
|
256
|
+
* the encoded literal of `params[N-1]`. Safe because the template is produced by
|
|
257
|
+
* {@link PowqlInterface} and contains **no** user string literals — the only
|
|
258
|
+
* `$<digits>` tokens are genuine positional placeholders, so a single scan
|
|
259
|
+
* cannot accidentally rewrite a `$N` that is itself part of a value (values are
|
|
260
|
+
* params, never inlined into the template by the generator).
|
|
261
|
+
*/
|
|
262
|
+
export declare function materializePowql(powql: string, params: unknown[]): string;
|
|
263
|
+
/**
|
|
264
|
+
* A {@link PgCompatPool} backed by an in-process `@zvndev/powdb-embedded`
|
|
265
|
+
* `Database`. The embedded addon takes **no params array** — its `query(powql)`
|
|
266
|
+
* accepts only a string — so this pool materializes each positional `$N` into a
|
|
267
|
+
* PowQL literal via {@link materializePowql} before handing the text to the
|
|
268
|
+
* engine. One handle, single connection: transaction keywords (`begin`/`commit`/
|
|
269
|
+
* `rollback`) are issued serially as ordinary queries.
|
|
270
|
+
*/
|
|
271
|
+
export declare class PowdbEmbeddedPool implements PgCompatPool {
|
|
272
|
+
private readonly db;
|
|
273
|
+
private closed;
|
|
274
|
+
/**
|
|
275
|
+
* Single-writer guard. The embedded engine is one handle with one global
|
|
276
|
+
* write lock — only one transaction may be open at a time. A re-entrant
|
|
277
|
+
* `begin` (a fresh top-level `db.$transaction` opened inside an open one)
|
|
278
|
+
* would otherwise hit PowDB's raw "already in a transaction" parse error;
|
|
279
|
+
* this surfaces a typed error instead. (Nested `tx.$transaction` is caught
|
|
280
|
+
* earlier still, by the savepoint override in {@link powdbDialect}.)
|
|
281
|
+
*/
|
|
282
|
+
private activeTransaction;
|
|
283
|
+
constructor(db: EmbeddedDatabase);
|
|
284
|
+
/** Enforce the single-writer model on a transaction-control statement. */
|
|
285
|
+
private guardTxControl;
|
|
286
|
+
private run;
|
|
287
|
+
query(text: QueryArg, values?: unknown[]): Promise<any>;
|
|
288
|
+
connect(): Promise<PgCompatPoolClient>;
|
|
289
|
+
end(): Promise<void>;
|
|
290
|
+
}
|
|
291
|
+
export { PowqlInterface } from './powql.js';
|
|
292
|
+
/** Options for {@link turbinePowDB}. */
|
|
293
|
+
export interface TurbinePowdbOptions extends Pick<TurbineConfig, 'logging' | 'defaultLimit' | 'warnOnUnlimited'> {
|
|
294
|
+
/** Max pooled connections (default 10). Networked transport only. */
|
|
295
|
+
connectionLimit?: number;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Selects the **embedded** transport — an in-process `@zvndev/powdb-embedded`
|
|
299
|
+
* database at the given data directory (no server, no socket). The value is the
|
|
300
|
+
* data dir path. Preview: Full-durability checkpoint-bound; built binaries ship
|
|
301
|
+
* for macOS (arm64/x64) and Unix-glibc only (Intel-mac/musl/Windows fall back to
|
|
302
|
+
* a from-source `npm run build`).
|
|
303
|
+
*
|
|
304
|
+
* @example
|
|
305
|
+
* ```ts
|
|
306
|
+
* const db = await turbinePowDB({ embedded: '/var/data/app.powdb' }, SCHEMA);
|
|
307
|
+
* // Faster writes (fsync off the commit path, bounded-loss) — requires addon >= 0.7.1:
|
|
308
|
+
* const fast = await turbinePowDB({ embedded: '/var/data/app.powdb', syncMode: 'normal' }, SCHEMA);
|
|
309
|
+
* ```
|
|
310
|
+
*/
|
|
311
|
+
export interface TurbinePowdbEmbeddedTarget {
|
|
312
|
+
embedded: string;
|
|
313
|
+
/**
|
|
314
|
+
* WAL durability for the embedded engine (requires `@zvndev/powdb-embedded` ≥ 0.7.1):
|
|
315
|
+
* `'full'` (default — fsync per commit), `'normal'` (fsync off the commit path,
|
|
316
|
+
* ~15–40× faster writes, bounded loss on OS crash/power loss), `'off'` (bench-only).
|
|
317
|
+
*/
|
|
318
|
+
syncMode?: 'full' | 'normal' | 'off';
|
|
319
|
+
/** Per-query memory budget in bytes (requires `@zvndev/powdb-embedded` ≥ 0.7.1). */
|
|
320
|
+
memoryLimit?: number;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Bind Turbine to PowDB. `target` is one of:
|
|
324
|
+
* - a `powdb://[user[:pass]@]host[:port][/db]` connection string → a
|
|
325
|
+
* **networked** `@zvndev/powdb-client` pool (consistency with
|
|
326
|
+
* `turbineMysql`/`turbineMssql`);
|
|
327
|
+
* - a host/port options object → a **networked** `@zvndev/powdb-client` pool;
|
|
328
|
+
* - an `{ embedded: <data-dir> }` object → an in-process
|
|
329
|
+
* `@zvndev/powdb-embedded` database (no server);
|
|
330
|
+
* - an already-constructed `@zvndev/powdb-client` `Pool` or {@link PowdbPool}
|
|
331
|
+
* (injection — you own its lifecycle and `disconnect()` is a no-op).
|
|
332
|
+
*
|
|
333
|
+
* On the networked transport the server version is probed and a clear
|
|
334
|
+
* {@link ConnectionError} is thrown if it is older than {@link MIN_POWDB_VERSION}
|
|
335
|
+
* (the `returning` keyword / int->float coercion fix Turbine relies on).
|
|
336
|
+
*
|
|
337
|
+
* Resolves to a `TurbineClient` whose `table()` accessors generate **PowQL** via
|
|
338
|
+
* {@link PowqlInterface}. The SQL `Dialect` is not involved.
|
|
339
|
+
*/
|
|
340
|
+
export declare function turbinePowDB(target: string | PowdbConnOptions | PowdbClientPool | PowdbPool | TurbinePowdbEmbeddedTarget, schema: SchemaMetadata, options?: TurbinePowdbOptions): Promise<TurbineClient>;
|
|
341
|
+
//# sourceMappingURL=powdb.d.ts.map
|