turbine-orm 0.81.0 → 0.90.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 +26 -25
- package/dist/checkout.d.ts +27 -2
- package/dist/checkout.js +75 -4
- package/dist/cjs/checkout.d.ts +27 -2
- package/dist/cjs/checkout.js +76 -3
- package/dist/cjs/cli/code-first-tags.d.ts +62 -0
- package/dist/cjs/cli/code-first-tags.js +124 -0
- package/dist/cjs/cli/compile-query.js +9 -0
- package/dist/cjs/cli/config.d.ts +35 -6
- package/dist/cjs/cli/config.js +17 -1
- package/dist/cjs/cli/destructive.d.ts +7 -4
- package/dist/cjs/cli/destructive.js +224 -20
- package/dist/cjs/cli/error-catalog.js +36 -0
- package/dist/cjs/cli/error-text.d.ts +15 -0
- package/dist/cjs/cli/error-text.js +40 -0
- package/dist/cjs/cli/index.d.ts +62 -4
- package/dist/cjs/cli/index.js +568 -108
- package/dist/cjs/cli/local-server-guard.d.ts +53 -0
- package/dist/cjs/cli/local-server-guard.js +119 -0
- package/dist/cjs/cli/local-server-output.d.ts +41 -0
- package/dist/cjs/cli/local-server-output.js +103 -0
- package/dist/cjs/cli/mcp.d.ts +8 -0
- package/dist/cjs/cli/mcp.js +121 -32
- package/dist/cjs/cli/migrate.d.ts +113 -5
- package/dist/cjs/cli/migrate.js +270 -21
- package/dist/cjs/cli/observe.d.ts +6 -1
- package/dist/cjs/cli/observe.js +85 -55
- package/dist/cjs/cli/pii-predicate-guard.d.ts +43 -23
- package/dist/cjs/cli/pii-predicate-guard.js +98 -37
- package/dist/cjs/cli/prisma-resolve.js +17 -13
- package/dist/cjs/cli/prisma-schema.js +12 -4
- package/dist/cjs/cli/studio-ui.generated.js +1 -1
- package/dist/cjs/cli/studio.d.ts +14 -2
- package/dist/cjs/cli/studio.js +244 -69
- package/dist/cjs/cli/ui.d.ts +1 -1
- package/dist/cjs/client.d.ts +558 -85
- package/dist/cjs/client.js +1270 -395
- package/dist/cjs/connection-guard.d.ts +13 -0
- package/dist/cjs/connection-guard.js +28 -0
- package/dist/cjs/connection-url.d.ts +51 -16
- package/dist/cjs/connection-url.js +67 -34
- package/dist/cjs/diagnostics.d.ts +81 -0
- package/dist/cjs/diagnostics.js +147 -0
- package/dist/cjs/dialect.d.ts +449 -20
- package/dist/cjs/dialect.js +117 -76
- package/dist/cjs/engine-config.d.ts +7 -6
- package/dist/cjs/errors.d.ts +126 -6
- package/dist/cjs/errors.js +256 -13
- package/dist/cjs/generate.d.ts +57 -7
- package/dist/cjs/generate.js +635 -279
- package/dist/cjs/global-filters-config.d.ts +59 -0
- package/dist/cjs/global-filters-config.js +367 -0
- package/dist/cjs/index.d.ts +9 -4
- package/dist/cjs/index.js +10 -2
- package/dist/cjs/introspect.d.ts +31 -6
- package/dist/cjs/introspect.js +108 -50
- package/dist/cjs/log-codes.d.ts +12 -0
- package/dist/cjs/log-codes.js +77 -0
- package/dist/cjs/logger.d.ts +87 -0
- package/dist/cjs/logger.js +98 -0
- package/dist/cjs/mssql.d.ts +8 -5
- package/dist/cjs/mssql.js +352 -65
- package/dist/cjs/mysql.d.ts +3 -5
- package/dist/cjs/mysql.js +420 -70
- package/dist/cjs/nested-write.d.ts +3 -0
- package/dist/cjs/nested-write.js +179 -114
- package/dist/cjs/pipeline-submittable.d.ts +12 -0
- package/dist/cjs/pipeline-submittable.js +118 -44
- package/dist/cjs/pipeline.js +21 -26
- package/dist/cjs/powdb-introspect.d.ts +5 -2
- package/dist/cjs/powdb-introspect.js +20 -15
- package/dist/cjs/powdb-shared.d.ts +36 -5
- package/dist/cjs/powdb-shared.js +67 -8
- package/dist/cjs/powdb.d.ts +4 -0
- package/dist/cjs/powdb.js +183 -51
- package/dist/cjs/powql.d.ts +394 -51
- package/dist/cjs/powql.js +1829 -284
- package/dist/cjs/prisma-compat.d.ts +23 -15
- package/dist/cjs/prisma-compat.js +507 -372
- package/dist/cjs/query/aggregates.d.ts +17 -1
- package/dist/cjs/query/aggregates.js +261 -29
- package/dist/cjs/query/batched-loader.d.ts +25 -6
- package/dist/cjs/query/batched-loader.js +103 -20
- package/dist/cjs/query/builder.d.ts +325 -184
- package/dist/cjs/query/builder.js +1452 -490
- package/dist/cjs/query/column-ref.d.ts +61 -0
- package/dist/cjs/query/column-ref.js +73 -0
- package/dist/cjs/query/compound-unique.d.ts +21 -0
- package/dist/cjs/query/compound-unique.js +98 -18
- package/dist/cjs/query/deferred.d.ts +53 -16
- package/dist/cjs/query/expr.d.ts +217 -0
- package/dist/cjs/query/expr.js +859 -0
- package/dist/cjs/query/filters.d.ts +155 -53
- package/dist/cjs/query/filters.js +613 -76
- package/dist/cjs/query/index.d.ts +2 -0
- package/dist/cjs/query/index.js +7 -1
- package/dist/cjs/query/json-value.d.ts +43 -0
- package/dist/cjs/query/json-value.js +59 -0
- package/dist/cjs/query/normalize-args.d.ts +87 -0
- package/dist/cjs/query/normalize-args.js +527 -0
- package/dist/cjs/query/option-surface.d.ts +16 -4
- package/dist/cjs/query/option-surface.js +57 -14
- package/dist/cjs/query/relation-names.d.ts +14 -0
- package/dist/cjs/query/relation-names.js +77 -18
- package/dist/cjs/query/relations.d.ts +30 -3
- package/dist/cjs/query/relations.js +219 -63
- package/dist/cjs/query/row-lock.d.ts +49 -0
- package/dist/cjs/query/row-lock.js +138 -0
- package/dist/cjs/query/sql-comment.d.ts +161 -0
- package/dist/cjs/query/sql-comment.js +381 -0
- package/dist/cjs/query/stream-idle.d.ts +132 -0
- package/dist/cjs/query/stream-idle.js +212 -0
- package/dist/cjs/query/table-client.d.ts +101 -0
- package/dist/cjs/query/table-client.js +74 -0
- package/dist/cjs/query/types.d.ts +677 -298
- package/dist/cjs/query/utils.d.ts +105 -6
- package/dist/cjs/query/utils.js +426 -19
- package/dist/cjs/query/warn-registry.d.ts +18 -0
- package/dist/cjs/query/warn-registry.js +18 -0
- package/dist/cjs/query/where-compile.d.ts +138 -14
- package/dist/cjs/query/where-compile.js +513 -29
- package/dist/cjs/query/where.d.ts +159 -59
- package/dist/cjs/query/where.js +716 -246
- package/dist/cjs/query/writes.d.ts +112 -50
- package/dist/cjs/query/writes.js +1498 -200
- package/dist/cjs/query-events.d.ts +4 -2
- package/dist/cjs/query-events.js +3 -1
- package/dist/cjs/realtime.d.ts +7 -3
- package/dist/cjs/realtime.js +13 -2
- package/dist/cjs/schema-builder.d.ts +55 -4
- package/dist/cjs/schema-builder.js +382 -18
- package/dist/cjs/schema-metadata.d.ts +21 -1
- package/dist/cjs/schema-metadata.js +29 -7
- package/dist/cjs/schema-sql.d.ts +75 -5
- package/dist/cjs/schema-sql.js +497 -45
- package/dist/cjs/schema.d.ts +26 -5
- package/dist/cjs/schema.js +110 -13
- package/dist/cjs/sql-placeholders.d.ts +56 -0
- package/dist/cjs/sql-placeholders.js +204 -0
- package/dist/cjs/sqlite.d.ts +75 -20
- package/dist/cjs/sqlite.js +593 -95
- package/dist/cjs/supplied-pool-types.d.ts +48 -0
- package/dist/cjs/supplied-pool-types.js +256 -0
- package/dist/cjs/transaction-control.d.ts +51 -0
- package/dist/cjs/transaction-control.js +316 -0
- package/dist/cjs/transaction-state.d.ts +342 -0
- package/dist/cjs/transaction-state.js +707 -0
- package/dist/cjs/typed-sql.d.ts +37 -3
- package/dist/cjs/typed-sql.js +102 -8
- package/dist/cli/code-first-tags.d.ts +62 -0
- package/dist/cli/code-first-tags.js +120 -0
- package/dist/cli/compile-query.js +9 -0
- package/dist/cli/config.d.ts +35 -6
- package/dist/cli/config.js +16 -1
- package/dist/cli/destructive.d.ts +7 -4
- package/dist/cli/destructive.js +224 -20
- package/dist/cli/error-catalog.js +36 -0
- package/dist/cli/error-text.d.ts +15 -0
- package/dist/cli/error-text.js +37 -0
- package/dist/cli/index.d.ts +62 -4
- package/dist/cli/index.js +569 -112
- package/dist/cli/local-server-guard.d.ts +53 -0
- package/dist/cli/local-server-guard.js +113 -0
- package/dist/cli/local-server-output.d.ts +41 -0
- package/dist/cli/local-server-output.js +98 -0
- package/dist/cli/mcp.d.ts +8 -0
- package/dist/cli/mcp.js +121 -34
- package/dist/cli/migrate.d.ts +113 -5
- package/dist/cli/migrate.js +261 -21
- package/dist/cli/observe.d.ts +6 -1
- package/dist/cli/observe.js +84 -54
- package/dist/cli/pii-predicate-guard.d.ts +43 -23
- package/dist/cli/pii-predicate-guard.js +100 -35
- package/dist/cli/prisma-resolve.js +15 -11
- package/dist/cli/prisma-schema.js +12 -4
- package/dist/cli/studio-ui.generated.js +1 -1
- package/dist/cli/studio.d.ts +14 -2
- package/dist/cli/studio.js +246 -71
- package/dist/cli/ui.d.ts +1 -1
- package/dist/client.d.ts +558 -85
- package/dist/client.js +1275 -400
- package/dist/connection-guard.d.ts +13 -0
- package/dist/connection-guard.js +27 -0
- package/dist/connection-url.d.ts +51 -16
- package/dist/connection-url.js +63 -34
- package/dist/diagnostics.d.ts +81 -0
- package/dist/diagnostics.js +144 -0
- package/dist/dialect.d.ts +449 -20
- package/dist/dialect.js +115 -43
- package/dist/engine-config.d.ts +7 -6
- package/dist/errors.d.ts +126 -6
- package/dist/errors.js +252 -12
- package/dist/generate.d.ts +57 -7
- package/dist/generate.js +635 -281
- package/dist/global-filters-config.d.ts +59 -0
- package/dist/global-filters-config.js +361 -0
- package/dist/index.d.ts +9 -4
- package/dist/index.js +4 -2
- package/dist/introspect.d.ts +31 -6
- package/dist/introspect.js +106 -50
- package/dist/log-codes.d.ts +12 -0
- package/dist/log-codes.js +74 -0
- package/dist/logger.d.ts +87 -0
- package/dist/logger.js +93 -0
- package/dist/mssql.d.ts +8 -5
- package/dist/mssql.js +354 -67
- package/dist/mysql.d.ts +3 -5
- package/dist/mysql.js +423 -73
- package/dist/nested-write.d.ts +3 -0
- package/dist/nested-write.js +177 -112
- package/dist/pipeline-submittable.d.ts +12 -0
- package/dist/pipeline-submittable.js +117 -44
- package/dist/pipeline.js +21 -26
- package/dist/powdb-introspect.d.ts +5 -2
- package/dist/powdb-introspect.js +21 -16
- package/dist/powdb-shared.d.ts +36 -5
- package/dist/powdb-shared.js +65 -8
- package/dist/powdb.d.ts +4 -0
- package/dist/powdb.js +183 -51
- package/dist/powql.d.ts +394 -51
- package/dist/powql.js +1836 -291
- package/dist/prisma-compat.d.ts +23 -15
- package/dist/prisma-compat.js +508 -373
- package/dist/query/aggregates.d.ts +17 -1
- package/dist/query/aggregates.js +263 -32
- package/dist/query/batched-loader.d.ts +25 -6
- package/dist/query/batched-loader.js +101 -21
- package/dist/query/builder.d.ts +325 -184
- package/dist/query/builder.js +1458 -495
- package/dist/query/column-ref.d.ts +61 -0
- package/dist/query/column-ref.js +66 -0
- package/dist/query/compound-unique.d.ts +21 -0
- package/dist/query/compound-unique.js +97 -19
- package/dist/query/deferred.d.ts +53 -16
- package/dist/query/expr.d.ts +217 -0
- package/dist/query/expr.js +848 -0
- package/dist/query/filters.d.ts +155 -53
- package/dist/query/filters.js +597 -72
- package/dist/query/index.d.ts +2 -0
- package/dist/query/index.js +4 -0
- package/dist/query/json-value.d.ts +43 -0
- package/dist/query/json-value.js +54 -0
- package/dist/query/normalize-args.d.ts +87 -0
- package/dist/query/normalize-args.js +517 -0
- package/dist/query/option-surface.d.ts +16 -4
- package/dist/query/option-surface.js +56 -13
- package/dist/query/relation-names.d.ts +14 -0
- package/dist/query/relation-names.js +77 -19
- package/dist/query/relations.d.ts +30 -3
- package/dist/query/relations.js +220 -67
- package/dist/query/row-lock.d.ts +49 -0
- package/dist/query/row-lock.js +131 -0
- package/dist/query/sql-comment.d.ts +161 -0
- package/dist/query/sql-comment.js +374 -0
- package/dist/query/stream-idle.d.ts +132 -0
- package/dist/query/stream-idle.js +203 -0
- package/dist/query/table-client.d.ts +101 -0
- package/dist/query/table-client.js +70 -0
- package/dist/query/types.d.ts +677 -298
- package/dist/query/utils.d.ts +105 -6
- package/dist/query/utils.js +414 -18
- package/dist/query/warn-registry.d.ts +18 -0
- package/dist/query/warn-registry.js +18 -0
- package/dist/query/where-compile.d.ts +138 -14
- package/dist/query/where-compile.js +508 -31
- package/dist/query/where.d.ts +159 -59
- package/dist/query/where.js +711 -248
- package/dist/query/writes.d.ts +112 -50
- package/dist/query/writes.js +1496 -202
- package/dist/query-events.d.ts +4 -2
- package/dist/query-events.js +3 -1
- package/dist/realtime.d.ts +7 -3
- package/dist/realtime.js +13 -2
- package/dist/schema-builder.d.ts +55 -4
- package/dist/schema-builder.js +381 -18
- package/dist/schema-metadata.d.ts +21 -1
- package/dist/schema-metadata.js +28 -7
- package/dist/schema-sql.d.ts +75 -5
- package/dist/schema-sql.js +494 -44
- package/dist/schema.d.ts +26 -5
- package/dist/schema.js +109 -13
- package/dist/sql-placeholders.d.ts +56 -0
- package/dist/sql-placeholders.js +200 -0
- package/dist/sqlite.d.ts +75 -20
- package/dist/sqlite.js +597 -99
- package/dist/supplied-pool-types.d.ts +48 -0
- package/dist/supplied-pool-types.js +247 -0
- package/dist/transaction-control.d.ts +51 -0
- package/dist/transaction-control.js +311 -0
- package/dist/transaction-state.d.ts +342 -0
- package/dist/transaction-state.js +696 -0
- package/dist/typed-sql.d.ts +37 -3
- package/dist/typed-sql.js +100 -8
- package/package.json +7 -4
- package/skills/turbine-orm/SKILL.md +56 -6
package/dist/powdb-shared.js
CHANGED
|
@@ -220,16 +220,42 @@ function isTsSpace(code) {
|
|
|
220
220
|
code === 0xfeff);
|
|
221
221
|
}
|
|
222
222
|
/**
|
|
223
|
-
*
|
|
223
|
+
* The labels of the enum type this column is declared as, or `undefined` when
|
|
224
|
+
* it is not an enum column of `enums`.
|
|
225
|
+
*
|
|
226
|
+
* An enum column carries its TYPE NAME as `dialectType` / `pgType` and a
|
|
227
|
+
* `tsType` that says nothing useful (`unknown` from `defineSchema`, a union of
|
|
228
|
+
* the labels from introspection), so the column's own metadata cannot answer
|
|
229
|
+
* the question: the schema's `enums` map is the only authority. PowDB has no
|
|
230
|
+
* enum type, so such a column is a `str` holding the label text, which is what
|
|
231
|
+
* PostgreSQL stores and returns. Without this the tsType heuristic in
|
|
232
|
+
* {@link isJsonColumn} declared a `defineSchema` enum column as `json`, and
|
|
233
|
+
* writing a label failed as invalid JSON.
|
|
234
|
+
*/
|
|
235
|
+
export function powdbEnumLabels(col, enums) {
|
|
236
|
+
if (!enums || col.isArray)
|
|
237
|
+
return undefined;
|
|
238
|
+
const type = col.dialectType ?? col.pgType;
|
|
239
|
+
return type !== undefined && Object.hasOwn(enums, type) ? enums[type] : undefined;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Does this column map to PowDB's native `json` document type? An enum column
|
|
243
|
+
* of `enums` never does (see {@link powdbEnumLabels}). A Postgres
|
|
224
244
|
* `json`/`jsonb` type (via `dialectType`/`pgType`) is authoritative; otherwise
|
|
225
245
|
* the tsType heuristic (`Record<…>`, `object`, `unknown`, an object/array
|
|
226
246
|
* literal) that the four scalar branches do not claim. Array columns never map
|
|
227
247
|
* to json, a PowDB array only exists INSIDE a json document, so a Postgres
|
|
228
248
|
* array column has no PowDB shape and still throws in {@link powqlColumnType}.
|
|
249
|
+
*
|
|
250
|
+
* `enums` is optional for callers outside Turbine; every call inside the
|
|
251
|
+
* engine passes the schema's map (a source scan in fx-powdb-r2.test.ts
|
|
252
|
+
* checks it).
|
|
229
253
|
*/
|
|
230
|
-
export function isJsonColumn(col) {
|
|
254
|
+
export function isJsonColumn(col, enums) {
|
|
231
255
|
if (col.isArray)
|
|
232
256
|
return false;
|
|
257
|
+
if (powdbEnumLabels(col, enums))
|
|
258
|
+
return false;
|
|
233
259
|
const dbType = (col.dialectType ?? col.pgType ?? '').toLowerCase();
|
|
234
260
|
if (dbType === 'json' || dbType === 'jsonb')
|
|
235
261
|
return true;
|
|
@@ -247,14 +273,17 @@ export function isJsonColumn(col) {
|
|
|
247
273
|
* - `Date` → `int` (epoch micros) - `boolean` → `bool`
|
|
248
274
|
* - integral `number`/`bigint` → `int` - fractional `number` → `float`
|
|
249
275
|
* - JSON / object columns → `json` (native PowDB document type, ≥ 0.12)
|
|
276
|
+
* - an enum column of `enums` → `str` (the label text)
|
|
250
277
|
* - everything else (incl. UUID/PK strings) → `str`
|
|
251
278
|
* Array (non-json) and bytes columns throw, they have no PowDB equivalent.
|
|
252
279
|
*/
|
|
253
|
-
export function powqlColumnType(col) {
|
|
280
|
+
export function powqlColumnType(col, enums) {
|
|
254
281
|
if (col.isArray) {
|
|
255
282
|
throw new ValidationError(`Column "${col.name}" is an array, PowDB has no array type. Arrays are unsupported on the PowDB backend.`);
|
|
256
283
|
}
|
|
257
|
-
if (
|
|
284
|
+
if (powdbEnumLabels(col, enums))
|
|
285
|
+
return 'str';
|
|
286
|
+
if (isJsonColumn(col, enums))
|
|
258
287
|
return 'json';
|
|
259
288
|
const ts = baseTsType(col.tsType);
|
|
260
289
|
if (ts === 'Date')
|
|
@@ -272,6 +301,23 @@ export function powqlColumnType(col) {
|
|
|
272
301
|
}
|
|
273
302
|
return 'str';
|
|
274
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* Is this a `numeric` / `decimal` / `money` column that PowDB stores as `str`?
|
|
306
|
+
*
|
|
307
|
+
* A Postgres-sourced decimal surfaces as a JS string (so its digits survive),
|
|
308
|
+
* and PowDB has no decimal type, so the column is DDL'd as PowQL `str`. Every
|
|
309
|
+
* comparison, ordering and aggregate the engine runs on it is then a TEXT
|
|
310
|
+
* operation, which is why the query generator refuses those on such a column.
|
|
311
|
+
*/
|
|
312
|
+
export function isPowdbDecimalTextColumn(col, enums) {
|
|
313
|
+
// An enum type's NAME is free text (`money_kind`), so an enum column is
|
|
314
|
+
// answered before the type-name match below can mistake it for a decimal.
|
|
315
|
+
if (powdbEnumLabels(col, enums))
|
|
316
|
+
return false;
|
|
317
|
+
if (col.isArray || isJsonColumn(col, enums) || baseTsType(col.tsType) !== 'string')
|
|
318
|
+
return false;
|
|
319
|
+
return /numeric|decimal|money/.test((col.dialectType ?? col.pgType ?? '').toLowerCase());
|
|
320
|
+
}
|
|
275
321
|
/** Heuristic: does this numeric column hold fractional values (→ PowQL `float`)? */
|
|
276
322
|
function isFloatColumn(col) {
|
|
277
323
|
const t = (col.dialectType ?? col.pgType ?? '').toLowerCase();
|
|
@@ -467,9 +513,12 @@ export function quotePowqlDotted(name) {
|
|
|
467
513
|
* Every PowDB value arrives as a string; NULL arrives as the bareword `"null"`.
|
|
468
514
|
* Metadata resolves the `"null"` ambiguity for nullable non-string columns.
|
|
469
515
|
*/
|
|
470
|
-
export function coerceValue(raw, col) {
|
|
516
|
+
export function coerceValue(raw, col, enums) {
|
|
517
|
+
// An enum column holds its label as text, read as a string column is.
|
|
518
|
+
if (powdbEnumLabels(col, enums))
|
|
519
|
+
return raw === 'null' && col.nullable ? null : raw;
|
|
471
520
|
const ts = baseTsType(col.tsType);
|
|
472
|
-
const json = isJsonColumn(col);
|
|
521
|
+
const json = isJsonColumn(col, enums);
|
|
473
522
|
// NULL bareword: unambiguous for non-string columns; for `str` we cannot tell a
|
|
474
523
|
// literal "null" from SQL NULL, so a nullable str of value "null" reads as null.
|
|
475
524
|
// For a `json` column the bareword `null` (a legacy-wire rendering shared by an
|
|
@@ -552,7 +601,7 @@ export function coerceNativeValue(value, col) {
|
|
|
552
601
|
* cells arrive pre-typed and go through {@link coerceNativeValue} (see F3).
|
|
553
602
|
* Callers on the native transport pass `this.pool.capabilities.nativeRaw`.
|
|
554
603
|
*/
|
|
555
|
-
export function rowToEntity(raw, meta, native = false) {
|
|
604
|
+
export function rowToEntity(raw, meta, native = false, enums) {
|
|
556
605
|
const byName = new Map(meta.columns.map((c) => [c.name, c]));
|
|
557
606
|
const out = {};
|
|
558
607
|
for (const snake of Object.keys(raw)) {
|
|
@@ -565,8 +614,16 @@ export function rowToEntity(raw, meta, native = false) {
|
|
|
565
614
|
else if (native) {
|
|
566
615
|
out[field] = coerceNativeValue(value, col);
|
|
567
616
|
}
|
|
617
|
+
else if (typeof value === 'string') {
|
|
618
|
+
out[field] = coerceValue(value, col, enums);
|
|
619
|
+
}
|
|
620
|
+
else if ((typeof value === 'number' || typeof value === 'bigint') && isDateColumn(col)) {
|
|
621
|
+
// A Date column's micros as a number cell: the Date it stores, as on the
|
|
622
|
+
// other wires, never the raw count (which a filter would then refuse).
|
|
623
|
+
out[field] = new Date(Number(value) / 1000);
|
|
624
|
+
}
|
|
568
625
|
else {
|
|
569
|
-
out[field] =
|
|
626
|
+
out[field] = value;
|
|
570
627
|
}
|
|
571
628
|
}
|
|
572
629
|
return out;
|
package/dist/powdb.d.ts
CHANGED
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
import { type PgCompatPool, type PgCompatPoolClient, TurbineClient, type TurbineConfig } from './client.js';
|
|
56
56
|
import { type Dialect } from './dialect.js';
|
|
57
57
|
import type { EngineClientConfig } from './engine-config.js';
|
|
58
|
+
import { type TurbineLogger } from './logger.js';
|
|
58
59
|
import type { PowdbExec } from './powdb-introspect.js';
|
|
59
60
|
import { type PowdbCapabilities } from './powdb-shared.js';
|
|
60
61
|
import { type SchemaMetadata } from './schema.js';
|
|
@@ -261,6 +262,8 @@ export declare function capabilitiesFromVersion(version: string | undefined | nu
|
|
|
261
262
|
*/
|
|
262
263
|
export interface PowqlSchemaDDLOptions {
|
|
263
264
|
capabilities?: PowdbCapabilities;
|
|
265
|
+
/** Where a skipped-link warning goes. Defaults to the console logger. */
|
|
266
|
+
logger?: TurbineLogger;
|
|
264
267
|
/**
|
|
265
268
|
* Emit `link Owner.name -> Target on local = target` declarations (PowDB entity
|
|
266
269
|
* links, >= 0.19) for every single-column hasMany / hasOne / belongsTo relation
|
|
@@ -340,6 +343,7 @@ export declare function powqlSchemaDDL(schema: SchemaMetadata, opts?: PowqlSchem
|
|
|
340
343
|
*/
|
|
341
344
|
export declare function applyPowdbLinks(exec: PowdbExec, schema: SchemaMetadata, options?: {
|
|
342
345
|
capabilities?: PowdbCapabilities;
|
|
346
|
+
logger?: TurbineLogger;
|
|
343
347
|
}): Promise<string[]>;
|
|
344
348
|
/**
|
|
345
349
|
* Translate a PowDB error into a typed Turbine error. Handles BOTH transports,
|
package/dist/powdb.js
CHANGED
|
@@ -56,6 +56,7 @@ import { AsyncLocalStorage } from 'node:async_hooks';
|
|
|
56
56
|
import { TurbineClient, } from './client.js';
|
|
57
57
|
import { postgresDialect } from './dialect.js';
|
|
58
58
|
import { ConnectionError, malformedConnectionStringMessage, NotNullViolationError, ReadOnlyError, TimeoutError, UniqueConstraintError, UnsupportedFeatureError, ValidationError, } from './errors.js';
|
|
59
|
+
import { consoleLogger, logTo } from './logger.js';
|
|
59
60
|
import importOptionalPeer from './optional-peer-import.cjs';
|
|
60
61
|
import { ALL_POWDB_CAPABILITIES, atLeastVersion, isDateColumn, PowdbFloatParam, PowdbJsonParam, parsePowdbSemver, powqlColumnType, quotePowqlIdent, requireCapability, } from './powdb-shared.js';
|
|
61
62
|
import { shouldWarnOnce, WARN_NS } from './query/warn-registry.js';
|
|
@@ -91,6 +92,48 @@ export { ALL_POWDB_CAPABILITIES, coerceNativeValue, coerceValue, isJsonColumn, i
|
|
|
91
92
|
export const powdbDialect = {
|
|
92
93
|
...postgresDialect,
|
|
93
94
|
name: 'powdb',
|
|
95
|
+
// PowqlInterface compiles PowQL itself and refuses what PowDB lacks; these
|
|
96
|
+
// answer for the client paths a PowDB client shares (transactions, raw
|
|
97
|
+
// queries, `tx.$connection()`) and keep every SQL-only feature off.
|
|
98
|
+
capabilities: Object.freeze({
|
|
99
|
+
distinctOn: false,
|
|
100
|
+
positionalJson: false,
|
|
101
|
+
nullsOrderingClause: false,
|
|
102
|
+
nullsSortHigh: false,
|
|
103
|
+
insensitiveInList: false,
|
|
104
|
+
jsonDocumentEquality: 'text',
|
|
105
|
+
jsonExtractTyped: false,
|
|
106
|
+
jsonExactNumericCast: false,
|
|
107
|
+
numericTextComparison: false,
|
|
108
|
+
// PowDB has no foreign keys: declared relations are not enforced, and its
|
|
109
|
+
// own mass-mutation guard already folds with foreignKeys: false.
|
|
110
|
+
enforcesForeignKeys: false,
|
|
111
|
+
partitionLimitPushdown: false,
|
|
112
|
+
utcTimestampRewrite: false,
|
|
113
|
+
paramTypeCasts: false,
|
|
114
|
+
namedEnumTypes: false,
|
|
115
|
+
structuredValueColumns: 'scalars',
|
|
116
|
+
maxBindParameters: Number.POSITIVE_INFINITY,
|
|
117
|
+
maxInsertRows: Number.POSITIVE_INFINITY,
|
|
118
|
+
upsertConflictTarget: 'explicit',
|
|
119
|
+
setClauseOrder: 'snapshot',
|
|
120
|
+
reselectLocksRows: false,
|
|
121
|
+
integerDivision: '/',
|
|
122
|
+
updateExpressions: false,
|
|
123
|
+
bulkUpsertAppliesRepeatedKeys: false,
|
|
124
|
+
readOnlyTransactions: false,
|
|
125
|
+
connectionParameters: false,
|
|
126
|
+
backendCancel: false,
|
|
127
|
+
idleTransactionTimeout: false,
|
|
128
|
+
abortsTransactionOnError: false,
|
|
129
|
+
connectionDriver: 'none',
|
|
130
|
+
preparesEveryStatement: false,
|
|
131
|
+
statementSyntax: null,
|
|
132
|
+
// No foreign keys to declare, inline or otherwise; PowQL DDL comes from
|
|
133
|
+
// powqlSchemaDDL, which never reads this.
|
|
134
|
+
inlineForeignKeys: false,
|
|
135
|
+
unboundedTextKeys: true,
|
|
136
|
+
}),
|
|
94
137
|
// `resultStrategy` is decorative for PowDB, PowqlInterface owns its own write
|
|
95
138
|
// path and never reads it. Set to 'returning' for honesty: writes use PowDB
|
|
96
139
|
// 0.7.0's trailing `returning` keyword (upsert excepted, see PowqlInterface).
|
|
@@ -108,6 +151,11 @@ export const powdbDialect = {
|
|
|
108
151
|
// earlier, this override keeps the flag truthful if a future path consults it.
|
|
109
152
|
supportsLateralJoin: false,
|
|
110
153
|
supportsPlanCacheMode: false,
|
|
154
|
+
// PowqlInterface reads none of these (it refuses each feature itself); they
|
|
155
|
+
// are set so the flags stay truthful if a shared path consults them.
|
|
156
|
+
rowLockModes: [],
|
|
157
|
+
supportsPercentileAggregates: false,
|
|
158
|
+
supportsBulkUpsert: false,
|
|
111
159
|
beginStatement: () => 'begin',
|
|
112
160
|
commitStatement: () => 'commit',
|
|
113
161
|
rollbackStatement: () => 'rollback',
|
|
@@ -324,7 +372,7 @@ export function powqlSchemaDDL(schema, opts = {}) {
|
|
|
324
372
|
new Set(idx.columns).size === pkSet.size &&
|
|
325
373
|
idx.columns.every((c) => pkSet.has(c));
|
|
326
374
|
const fields = meta.columns.map((col) => {
|
|
327
|
-
const powqlType = powqlColumnType(col);
|
|
375
|
+
const powqlType = powqlColumnType(col, schema.enums);
|
|
328
376
|
// Gate `json` columns behind the engine's jsonDocs capability when a
|
|
329
377
|
// caller supplied one, an old engine has no `json` type and would reject
|
|
330
378
|
// the DDL. Pure-function callers (no opts) emit unconditionally.
|
|
@@ -409,8 +457,8 @@ export function powqlSchemaDDL(schema, opts = {}) {
|
|
|
409
457
|
requireCapability(caps, 'entityLinks', 'entity link DDL (`emitLinks`)');
|
|
410
458
|
const links = deriveDesiredLinks(schema, (owner, name) => {
|
|
411
459
|
if (shouldWarnOnce(WARN_NS.powdbLinks, `collide:${owner}.${name}`)) {
|
|
412
|
-
|
|
413
|
-
'same name; skipping its link declaration (PowDB hard-errors on a link that shadows a column).');
|
|
460
|
+
logTo(opts.logger ?? consoleLogger, 'warn', `powqlSchemaDDL(emitLinks): relation "${name}" on "${owner}" collides with a column of the ` +
|
|
461
|
+
'same name; skipping its link declaration (PowDB hard-errors on a link that shadows a column).', { code: 'powdb-link-collision', table: owner, relation: name, operation: 'powqlSchemaDDL' });
|
|
414
462
|
}
|
|
415
463
|
});
|
|
416
464
|
for (const link of links)
|
|
@@ -438,6 +486,7 @@ export function powqlSchemaDDL(schema, opts = {}) {
|
|
|
438
486
|
*/
|
|
439
487
|
export async function applyPowdbLinks(exec, schema, options = {}) {
|
|
440
488
|
const caps = options.capabilities;
|
|
489
|
+
const logger = options.logger ?? consoleLogger;
|
|
441
490
|
if (caps) {
|
|
442
491
|
requireCapability(caps, 'entityLinks', 'entity link DDL (`applyPowdbLinks`)');
|
|
443
492
|
requireCapability(caps, 'linkIntrospection', 'PowDB `schema links` introspection');
|
|
@@ -446,8 +495,8 @@ export async function applyPowdbLinks(exec, schema, options = {}) {
|
|
|
446
495
|
const byOwnerName = new Map(existing.map((l) => [`${l.owner}\u0000${l.name}`, l]));
|
|
447
496
|
const desired = deriveDesiredLinks(schema, (owner, name) => {
|
|
448
497
|
if (shouldWarnOnce(WARN_NS.powdbLinks, `collide:${owner}.${name}`)) {
|
|
449
|
-
|
|
450
|
-
'skipping its link (PowDB hard-errors on a link that shadows a column).');
|
|
498
|
+
logTo(logger, 'warn', `applyPowdbLinks: relation "${name}" on "${owner}" collides with a column of the same name; ` +
|
|
499
|
+
'skipping its link (PowDB hard-errors on a link that shadows a column).', { code: 'powdb-link-collision', table: owner, relation: name, operation: 'applyPowdbLinks' });
|
|
451
500
|
}
|
|
452
501
|
});
|
|
453
502
|
const executed = [];
|
|
@@ -456,9 +505,9 @@ export async function applyPowdbLinks(exec, schema, options = {}) {
|
|
|
456
505
|
if (found) {
|
|
457
506
|
const same = found.target === link.target && found.localKey === link.localKey && found.targetKey === link.targetKey;
|
|
458
507
|
if (!same && shouldWarnOnce(WARN_NS.powdbLinks, `drift:${link.owner}.${link.name}`)) {
|
|
459
|
-
|
|
508
|
+
logTo(logger, 'warn', `applyPowdbLinks: link "${link.name}" on "${link.owner}" is already declared with different ` +
|
|
460
509
|
`endpoints (have ${found.target} on ${found.localKey} = ${found.targetKey}, want ${link.target} on ` +
|
|
461
|
-
`${link.localKey} = ${link.targetKey}); leaving it untouched (PowDB has no drop-link DDL)
|
|
510
|
+
`${link.localKey} = ${link.targetKey}); leaving it untouched (PowDB has no drop-link DDL).`, { code: 'powdb-link-drift', table: link.owner, relation: link.name, operation: 'applyPowdbLinks' });
|
|
462
511
|
}
|
|
463
512
|
continue; // identical → idempotent skip; drift → warned skip
|
|
464
513
|
}
|
|
@@ -704,7 +753,9 @@ export function wrapPowdbError(err) {
|
|
|
704
753
|
// evaluate true for every row. Runs before the generic `type mismatch` regex
|
|
705
754
|
// below so the column name and the fix survive into the message.
|
|
706
755
|
{
|
|
707
|
-
|
|
756
|
+
// Every group is bounded: `[^,]+` retried from each "expected " in a long
|
|
757
|
+
// message made this quadratic in the message length.
|
|
758
|
+
const m = /type mismatch for column '([^']{1,256})': expected ([^,]{1,64}), got (\w{1,32})/i.exec(msg);
|
|
708
759
|
if (m) {
|
|
709
760
|
return new ValidationError(`PowDB rejected a comparison on column "${m[1]}": the column is ${m[2]} but the bound value is ` +
|
|
710
761
|
`${m[3]}. PowQL never coerces across types in a comparison (before engine 0.20 this silently matched ` +
|
|
@@ -841,6 +892,19 @@ function reentrantTransactionError() {
|
|
|
841
892
|
'on the write lock the open transaction holds. Use the `tx` client the callback receives, or start the ' +
|
|
842
893
|
'second transaction after the first completes. (Independent concurrent transactions queue automatically.)');
|
|
843
894
|
}
|
|
895
|
+
/**
|
|
896
|
+
* The error for a plain statement issued through the CLIENT (not the `tx`
|
|
897
|
+
* client) from inside that client's own open transaction callback, on the
|
|
898
|
+
* embedded engine. Its one handle carries one transaction, so the statement
|
|
899
|
+
* could only run inside the transaction (and be rolled back with it) or wait
|
|
900
|
+
* for the transaction to finish, which is itself waiting on this statement.
|
|
901
|
+
*/
|
|
902
|
+
function statementInsideTransactionError() {
|
|
903
|
+
return new UnsupportedFeatureError('A statement on the client while its own transaction is open', 'powdb', 'This call was made through the client, not the `tx` client, from inside an open $transaction callback. The ' +
|
|
904
|
+
'embedded engine has one handle and one transaction, so the call would either join that transaction (and be ' +
|
|
905
|
+
'rolled back with it) or wait for it forever. Use the `tx` client the callback receives, or make the call ' +
|
|
906
|
+
'after the transaction completes.');
|
|
907
|
+
}
|
|
844
908
|
// ---------------------------------------------------------------------------
|
|
845
909
|
// Single-writer transaction gate, FIFO queueing + re-entrancy detection
|
|
846
910
|
// ---------------------------------------------------------------------------
|
|
@@ -911,9 +975,15 @@ class PowdbTxGate {
|
|
|
911
975
|
queueTimeoutMs;
|
|
912
976
|
/** Tail of the FIFO queue, resolves once every earlier transaction has finished. */
|
|
913
977
|
tail = Promise.resolve();
|
|
978
|
+
/** Holds taken and not yet finished, queued ones included. */
|
|
979
|
+
outstanding = 0;
|
|
914
980
|
constructor(queueTimeoutMs) {
|
|
915
981
|
this.queueTimeoutMs = queueTimeoutMs;
|
|
916
982
|
}
|
|
983
|
+
/** True while any transaction holds the gate or waits for it. */
|
|
984
|
+
get busy() {
|
|
985
|
+
return this.outstanding > 0;
|
|
986
|
+
}
|
|
917
987
|
/**
|
|
918
988
|
* Take a place in the transaction queue. The prologue walks the caller's
|
|
919
989
|
* marker chain (planted around transaction callbacks by the pool's
|
|
@@ -922,7 +992,7 @@ class PowdbTxGate {
|
|
|
922
992
|
* the returned hold carries the fresh marker (`hold.ctx`) for
|
|
923
993
|
* `wrapTransactionCallback` to scope around the user callback.
|
|
924
994
|
*/
|
|
925
|
-
async acquire() {
|
|
995
|
+
async acquire(reentrantError = reentrantTransactionError) {
|
|
926
996
|
// Walk the WHOLE marker chain, not just the innermost marker: with two
|
|
927
997
|
// pools, dbA-tx → dbB-tx → dbA-begin leaves dbB's marker innermost, but
|
|
928
998
|
// the dbA ancestor is still open, queueing the inner dbA begin behind it
|
|
@@ -935,7 +1005,7 @@ class PowdbTxGate {
|
|
|
935
1005
|
parent = parent.parent;
|
|
936
1006
|
for (let c = parent; c !== undefined; c = c.parent) {
|
|
937
1007
|
if (c.gate === this && !c.done) {
|
|
938
|
-
throw
|
|
1008
|
+
throw reentrantError();
|
|
939
1009
|
}
|
|
940
1010
|
}
|
|
941
1011
|
const ctx = { gate: this, done: false, parent };
|
|
@@ -945,12 +1015,14 @@ class PowdbTxGate {
|
|
|
945
1015
|
});
|
|
946
1016
|
const ahead = this.tail;
|
|
947
1017
|
this.tail = ahead.then(() => finished);
|
|
1018
|
+
this.outstanding++;
|
|
948
1019
|
const hold = {
|
|
949
1020
|
ctx,
|
|
950
1021
|
finish: () => {
|
|
951
1022
|
if (ctx.done)
|
|
952
1023
|
return;
|
|
953
1024
|
ctx.done = true;
|
|
1025
|
+
this.outstanding--;
|
|
954
1026
|
handOff();
|
|
955
1027
|
},
|
|
956
1028
|
};
|
|
@@ -1608,6 +1680,30 @@ export class PowdbEmbeddedPool {
|
|
|
1608
1680
|
throw new ConnectionError('The PowDB embedded pool is closed: disconnect() was already called on this client.');
|
|
1609
1681
|
}
|
|
1610
1682
|
}
|
|
1683
|
+
if (ctl === null && holdRef.hold === null && this.txGate.busy) {
|
|
1684
|
+
// A statement from OUTSIDE the open transaction. The engine is one
|
|
1685
|
+
// handle, so running it now would put it inside that transaction: it
|
|
1686
|
+
// would read uncommitted rows, and a write would be rolled back with the
|
|
1687
|
+
// transaction after being reported as done. It takes its FIFO turn on the
|
|
1688
|
+
// gate instead, as a one-statement transaction of its own would. From
|
|
1689
|
+
// inside the transaction's own callback that wait could never end, so the
|
|
1690
|
+
// gate refuses it there.
|
|
1691
|
+
const hold = await this.txGate.acquire(statementInsideTransactionError);
|
|
1692
|
+
try {
|
|
1693
|
+
if (this.closed) {
|
|
1694
|
+
throw new ConnectionError('The PowDB embedded pool is closed: disconnect() was already called on this client.');
|
|
1695
|
+
}
|
|
1696
|
+
try {
|
|
1697
|
+
return this.exec(powql, params);
|
|
1698
|
+
}
|
|
1699
|
+
catch (err) {
|
|
1700
|
+
throw wrapPowdbError(err);
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
finally {
|
|
1704
|
+
hold.finish();
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1611
1707
|
if ((ctl === 'commit' || ctl === 'rollback') && holdRef.hold === null) {
|
|
1612
1708
|
// This context never acquired the gate, its `begin` never ran (the
|
|
1613
1709
|
// gate timed out / threw re-entrant E017, or no begin was issued at
|
|
@@ -1799,25 +1895,52 @@ async function openEmbeddedPool(target, poolOptions = {}, assumeEngineVersion, i
|
|
|
1799
1895
|
throw err;
|
|
1800
1896
|
throw new ConnectionError(`PowDB embedded could not open data dir "${dir}": ${err.message}`);
|
|
1801
1897
|
}
|
|
1802
|
-
|
|
1803
|
-
if (
|
|
1804
|
-
|
|
1898
|
+
try {
|
|
1899
|
+
if (syncMode !== undefined) {
|
|
1900
|
+
if (typeof db.setSyncMode !== 'function') {
|
|
1901
|
+
throw new ConnectionError('embedded `syncMode` requires @zvndev/powdb-embedded ≥ 0.7.1 (the installed addon has no setSyncMode).');
|
|
1902
|
+
}
|
|
1903
|
+
db.setSyncMode(syncMode);
|
|
1904
|
+
}
|
|
1905
|
+
// Native typed wire is feature-detected on the OPENED handle: an addon ≥ 0.14
|
|
1906
|
+
// exposes `queryWithParams`, so nativeRaw turns on (server-gate ≥ 0.13 still
|
|
1907
|
+
// applies via the version); an older addon has no such method → false.
|
|
1908
|
+
const capabilities = capabilitiesFromVersion(assumeEngineVersion ?? resolveEmbeddedVersion(), {
|
|
1909
|
+
hasNativeRaw: typeof db.queryWithParams === 'function',
|
|
1910
|
+
});
|
|
1911
|
+
// A read-only target forces the pool's readonly flag; otherwise honor whatever
|
|
1912
|
+
// `poolOptions` (threaded from `options.readonly`) carried.
|
|
1913
|
+
return new PowdbEmbeddedPool(db, {
|
|
1914
|
+
...poolOptions,
|
|
1915
|
+
capabilities,
|
|
1916
|
+
readonly: Boolean(readonly) || Boolean(poolOptions.readonly),
|
|
1917
|
+
});
|
|
1918
|
+
}
|
|
1919
|
+
catch (err) {
|
|
1920
|
+
// The caller never receives this handle, so nothing else can close it.
|
|
1921
|
+
try {
|
|
1922
|
+
db.close?.();
|
|
1923
|
+
}
|
|
1924
|
+
catch {
|
|
1925
|
+
// The failure being reported is the useful one.
|
|
1805
1926
|
}
|
|
1806
|
-
|
|
1927
|
+
throw err;
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1930
|
+
/**
|
|
1931
|
+
* Probe a networked pool Turbine just built and wrap it. The pool is closed
|
|
1932
|
+
* when the probe or the wrapper refuses, because the caller never sees it
|
|
1933
|
+
* and its idle sockets would otherwise keep the process alive.
|
|
1934
|
+
*/
|
|
1935
|
+
async function wrapOwnedClientPool(clientPool, poolOptions, assumeEngineVersion) {
|
|
1936
|
+
try {
|
|
1937
|
+
const capabilities = await assertNetworkedVersion(clientPool, assumeEngineVersion);
|
|
1938
|
+
return new PowdbPool(clientPool, undefined, { ...poolOptions, capabilities });
|
|
1939
|
+
}
|
|
1940
|
+
catch (err) {
|
|
1941
|
+
await clientPool.close().catch(() => { });
|
|
1942
|
+
throw err;
|
|
1807
1943
|
}
|
|
1808
|
-
// Native typed wire is feature-detected on the OPENED handle: an addon ≥ 0.14
|
|
1809
|
-
// exposes `queryWithParams`, so nativeRaw turns on (server-gate ≥ 0.13 still
|
|
1810
|
-
// applies via the version); an older addon has no such method → false.
|
|
1811
|
-
const capabilities = capabilitiesFromVersion(assumeEngineVersion ?? resolveEmbeddedVersion(), {
|
|
1812
|
-
hasNativeRaw: typeof db.queryWithParams === 'function',
|
|
1813
|
-
});
|
|
1814
|
-
// A read-only target forces the pool's readonly flag; otherwise honor whatever
|
|
1815
|
-
// `poolOptions` (threaded from `options.readonly`) carried.
|
|
1816
|
-
return new PowdbEmbeddedPool(db, {
|
|
1817
|
-
...poolOptions,
|
|
1818
|
-
capabilities,
|
|
1819
|
-
readonly: Boolean(readonly) || Boolean(poolOptions.readonly),
|
|
1820
|
-
});
|
|
1821
1944
|
}
|
|
1822
1945
|
/**
|
|
1823
1946
|
* Bind Turbine to PowDB. `target` is one of:
|
|
@@ -1848,9 +1971,7 @@ export async function turbinePowDB(target, schema, options = {}) {
|
|
|
1848
1971
|
const max = options.connectionLimit ?? 10;
|
|
1849
1972
|
if (typeof target === 'string') {
|
|
1850
1973
|
const mod = options.powdbClientModule ?? (await loadPowdb());
|
|
1851
|
-
|
|
1852
|
-
const capabilities = await assertNetworkedVersion(clientPool, options.assumeEngineVersion);
|
|
1853
|
-
pool = new PowdbPool(clientPool, undefined, { ...poolOptions, capabilities });
|
|
1974
|
+
pool = await wrapOwnedClientPool(new mod.Pool({ ...parsePowdbUrl(target), max }), poolOptions, options.assumeEngineVersion);
|
|
1854
1975
|
owns = true;
|
|
1855
1976
|
}
|
|
1856
1977
|
else if (target instanceof PowdbPool) {
|
|
@@ -1870,26 +1991,36 @@ export async function turbinePowDB(target, schema, options = {}) {
|
|
|
1870
1991
|
}
|
|
1871
1992
|
else {
|
|
1872
1993
|
const mod = options.powdbClientModule ?? (await loadPowdb());
|
|
1873
|
-
|
|
1874
|
-
const capabilities = await assertNetworkedVersion(clientPool, options.assumeEngineVersion);
|
|
1875
|
-
pool = new PowdbPool(clientPool, undefined, { ...poolOptions, capabilities });
|
|
1994
|
+
pool = await wrapOwnedClientPool(new mod.Pool({ ...target, max }), poolOptions, options.assumeEngineVersion);
|
|
1876
1995
|
owns = true;
|
|
1877
1996
|
}
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
...clientConfig
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1997
|
+
let client;
|
|
1998
|
+
try {
|
|
1999
|
+
// The PowQL generator is loaded here to keep client.ts free of any PowDB import.
|
|
2000
|
+
const { PowqlInterface } = await import('./powql.js');
|
|
2001
|
+
const queryInterfaceFactory = (p, table, sch, middlewares, opts) => new PowqlInterface(p, table, sch, middlewares, opts);
|
|
2002
|
+
// Forward every client-level option EXCEPT the ones this factory owns (they
|
|
2003
|
+
// configure the pool / transport above, and TurbineClient warns on a config
|
|
2004
|
+
// key it does not recognize). Destructured rather than hand-listed on the way
|
|
2005
|
+
// IN: an allowlist is how `globalFilters` came to be accepted and ignored.
|
|
2006
|
+
const { connectionLimit: _connectionLimit, transactionQueueTimeoutMs: _transactionQueueTimeoutMs, retryStaleReads: _retryStaleReads, assumeEngineVersion: _assumeEngineVersion, readonly: _readonly, powdbClientModule: _powdbClientModule, powdbEmbeddedModule: _powdbEmbeddedModule, ...clientConfig } = options;
|
|
2007
|
+
client = new TurbineClient({
|
|
2008
|
+
...clientConfig,
|
|
2009
|
+
pool,
|
|
2010
|
+
preparedStatements: false,
|
|
2011
|
+
dialect: powdbDialect,
|
|
2012
|
+
queryInterfaceFactory,
|
|
2013
|
+
}, schema);
|
|
2014
|
+
}
|
|
2015
|
+
catch (err) {
|
|
2016
|
+
// A failed factory hands the caller nothing to close, so a pool or embedded
|
|
2017
|
+
// handle it BUILT is closed here (the client constructor refuses a bad
|
|
2018
|
+
// config, a static global filter naming no table for one). A pool the
|
|
2019
|
+
// caller supplied is the caller's and stays open.
|
|
2020
|
+
if (owns)
|
|
2021
|
+
await pool.end().catch(() => { });
|
|
2022
|
+
throw err;
|
|
2023
|
+
}
|
|
1893
2024
|
if (owns) {
|
|
1894
2025
|
// Turbine built this pool / embedded handle, so disconnect()/end() must
|
|
1895
2026
|
// close it. client.ts sees TurbineConfig.pool as EXTERNAL (ownsPool =
|
|
@@ -1898,9 +2029,10 @@ export async function turbinePowDB(target, schema, options = {}) {
|
|
|
1898
2029
|
// open until powdb-server's idle timeout (~300s) closed them. Consistent
|
|
1899
2030
|
// with turbineMssql's owned-pool patch.
|
|
1900
2031
|
const baseDisconnect = client.disconnect.bind(client);
|
|
1901
|
-
const close = async () => {
|
|
1902
|
-
await baseDisconnect();
|
|
2032
|
+
const close = async (options) => {
|
|
2033
|
+
const result = options === undefined ? await baseDisconnect() : await baseDisconnect(options);
|
|
1903
2034
|
await pool.end();
|
|
2035
|
+
return result ?? undefined;
|
|
1904
2036
|
};
|
|
1905
2037
|
const patch = client;
|
|
1906
2038
|
patch.disconnect = close;
|
|
@@ -1908,7 +2040,7 @@ export async function turbinePowDB(target, schema, options = {}) {
|
|
|
1908
2040
|
}
|
|
1909
2041
|
else {
|
|
1910
2042
|
// Injected pool, the caller owns its lifecycle.
|
|
1911
|
-
client.disconnect = async () => { };
|
|
2043
|
+
client.disconnect = async (options) => (options === undefined ? undefined : { timedOut: false, forcedConnections: 0 });
|
|
1912
2044
|
}
|
|
1913
2045
|
return client;
|
|
1914
2046
|
}
|