turbine-orm 0.50.0 → 0.51.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 +66 -66
- package/dist/adapters/cockroachdb.d.ts +5 -5
- package/dist/adapters/cockroachdb.js +10 -10
- package/dist/adapters/index.d.ts +5 -5
- package/dist/adapters/index.js +7 -7
- package/dist/adapters/yugabytedb.d.ts +7 -7
- package/dist/adapters/yugabytedb.js +10 -10
- package/dist/cjs/adapters/cockroachdb.d.ts +5 -5
- package/dist/cjs/adapters/cockroachdb.js +10 -10
- package/dist/cjs/adapters/index.d.ts +5 -5
- package/dist/cjs/adapters/index.js +7 -7
- package/dist/cjs/adapters/yugabytedb.d.ts +7 -7
- package/dist/cjs/adapters/yugabytedb.js +10 -10
- package/dist/cjs/cli/config.d.ts +13 -2
- package/dist/cjs/cli/config.js +3 -2
- package/dist/cjs/cli/destructive.d.ts +1 -1
- package/dist/cjs/cli/destructive.js +1 -1
- package/dist/cjs/cli/index.d.ts +10 -10
- package/dist/cjs/cli/index.js +49 -45
- package/dist/cjs/cli/loader.d.ts +7 -7
- package/dist/cjs/cli/loader.js +9 -9
- package/dist/cjs/cli/mcp.js +4 -4
- package/dist/cjs/cli/migrate.d.ts +5 -5
- package/dist/cjs/cli/migrate.js +11 -11
- package/dist/cjs/cli/studio-ui.generated.js +1 -1
- package/dist/cjs/cli/ui.d.ts +2 -2
- package/dist/cjs/cli/ui.js +2 -2
- package/dist/cjs/client.d.ts +49 -38
- package/dist/cjs/client.js +57 -56
- package/dist/cjs/dialect.d.ts +62 -18
- package/dist/cjs/dialect.js +40 -2
- package/dist/cjs/errors.d.ts +5 -5
- package/dist/cjs/errors.js +11 -11
- package/dist/cjs/generate.d.ts +6 -6
- package/dist/cjs/generate.js +31 -29
- package/dist/cjs/index-advisor.d.ts +5 -5
- package/dist/cjs/index-advisor.js +0 -0
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +7 -7
- package/dist/cjs/introspect.d.ts +35 -9
- package/dist/cjs/introspect.js +83 -32
- package/dist/cjs/mssql.d.ts +11 -11
- package/dist/cjs/mssql.js +64 -29
- package/dist/cjs/mysql.d.ts +8 -8
- package/dist/cjs/mysql.js +61 -23
- package/dist/cjs/nested-write.d.ts +21 -2
- package/dist/cjs/nested-write.js +51 -14
- package/dist/cjs/optional-peer-import.cjs +7 -7
- package/dist/cjs/optional-peer-import.d.cts +7 -7
- package/dist/cjs/pipeline-submittable.d.ts +2 -2
- package/dist/cjs/pipeline-submittable.js +6 -6
- package/dist/cjs/pipeline.d.ts +1 -1
- package/dist/cjs/pipeline.js +4 -4
- package/dist/cjs/powdb-introspect.d.ts +1 -1
- package/dist/cjs/powdb-introspect.js +1 -1
- package/dist/cjs/powdb.d.ts +28 -28
- package/dist/cjs/powdb.js +66 -66
- package/dist/cjs/powql.d.ts +27 -27
- package/dist/cjs/powql.js +73 -52
- package/dist/cjs/query/aggregates.d.ts +1 -1
- package/dist/cjs/query/aggregates.js +5 -5
- package/dist/cjs/query/batched-loader.d.ts +11 -11
- package/dist/cjs/query/batched-loader.js +24 -24
- package/dist/cjs/query/builder.d.ts +39 -21
- package/dist/cjs/query/builder.js +99 -57
- package/dist/cjs/query/compound-unique.d.ts +1 -1
- package/dist/cjs/query/compound-unique.js +0 -0
- package/dist/cjs/query/deferred.d.ts +12 -6
- package/dist/cjs/query/deferred.js +1 -1
- package/dist/cjs/query/filters.d.ts +31 -11
- package/dist/cjs/query/filters.js +67 -14
- package/dist/cjs/query/index.d.ts +1 -1
- package/dist/cjs/query/index.js +1 -1
- package/dist/cjs/query/relations.d.ts +9 -9
- package/dist/cjs/query/relations.js +164 -57
- package/dist/cjs/query/types.d.ts +86 -35
- package/dist/cjs/query/types.js +1 -1
- package/dist/cjs/query/utils.d.ts +27 -10
- package/dist/cjs/query/utils.js +86 -14
- package/dist/cjs/query/where.d.ts +47 -28
- package/dist/cjs/query/where.js +130 -31
- package/dist/cjs/query/writes.d.ts +24 -5
- package/dist/cjs/query/writes.js +102 -13
- package/dist/cjs/realtime.d.ts +7 -7
- package/dist/cjs/realtime.js +9 -9
- package/dist/cjs/schema-builder.d.ts +18 -7
- package/dist/cjs/schema-builder.js +17 -10
- package/dist/cjs/schema-metadata.d.ts +3 -3
- package/dist/cjs/schema-metadata.js +9 -9
- package/dist/cjs/schema-sql.d.ts +9 -9
- package/dist/cjs/schema-sql.js +20 -20
- package/dist/cjs/schema.d.ts +19 -9
- package/dist/cjs/schema.js +6 -6
- package/dist/cjs/serverless.d.ts +15 -15
- package/dist/cjs/serverless.js +16 -16
- package/dist/cjs/sqlite.d.ts +8 -8
- package/dist/cjs/sqlite.js +53 -22
- package/dist/cjs/typed-sql.d.ts +4 -4
- package/dist/cjs/typed-sql.js +5 -5
- package/dist/cli/config.d.ts +13 -2
- package/dist/cli/config.js +3 -2
- package/dist/cli/destructive.d.ts +1 -1
- package/dist/cli/destructive.js +1 -1
- package/dist/cli/index.d.ts +10 -10
- package/dist/cli/index.js +49 -45
- package/dist/cli/loader.d.ts +7 -7
- package/dist/cli/loader.js +9 -9
- package/dist/cli/mcp.js +4 -4
- package/dist/cli/migrate.d.ts +5 -5
- package/dist/cli/migrate.js +11 -11
- package/dist/cli/studio-ui.generated.js +1 -1
- package/dist/cli/ui.d.ts +2 -2
- package/dist/cli/ui.js +2 -2
- package/dist/client.d.ts +49 -38
- package/dist/client.js +57 -56
- package/dist/dialect.d.ts +62 -18
- package/dist/dialect.js +40 -2
- package/dist/errors.d.ts +5 -5
- package/dist/errors.js +11 -11
- package/dist/generate.d.ts +6 -6
- package/dist/generate.js +31 -29
- package/dist/index-advisor.d.ts +5 -5
- package/dist/index-advisor.js +0 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -7
- package/dist/introspect.d.ts +35 -9
- package/dist/introspect.js +82 -32
- package/dist/mssql.d.ts +11 -11
- package/dist/mssql.js +64 -29
- package/dist/mysql.d.ts +8 -8
- package/dist/mysql.js +61 -23
- package/dist/nested-write.d.ts +21 -2
- package/dist/nested-write.js +51 -14
- package/dist/optional-peer-import.cjs +7 -7
- package/dist/optional-peer-import.d.cts +7 -7
- package/dist/pipeline-submittable.d.ts +2 -2
- package/dist/pipeline-submittable.js +6 -6
- package/dist/pipeline.d.ts +1 -1
- package/dist/pipeline.js +4 -4
- package/dist/powdb-introspect.d.ts +1 -1
- package/dist/powdb-introspect.js +1 -1
- package/dist/powdb.d.ts +28 -28
- package/dist/powdb.js +66 -66
- package/dist/powql.d.ts +27 -27
- package/dist/powql.js +73 -52
- package/dist/query/aggregates.d.ts +1 -1
- package/dist/query/aggregates.js +5 -5
- package/dist/query/batched-loader.d.ts +11 -11
- package/dist/query/batched-loader.js +24 -24
- package/dist/query/builder.d.ts +39 -21
- package/dist/query/builder.js +100 -58
- package/dist/query/compound-unique.d.ts +1 -1
- package/dist/query/compound-unique.js +0 -0
- package/dist/query/deferred.d.ts +12 -6
- package/dist/query/deferred.js +1 -1
- package/dist/query/filters.d.ts +31 -11
- package/dist/query/filters.js +66 -13
- package/dist/query/index.d.ts +1 -1
- package/dist/query/index.js +1 -1
- package/dist/query/relations.d.ts +9 -9
- package/dist/query/relations.js +165 -58
- package/dist/query/types.d.ts +86 -35
- package/dist/query/types.js +1 -1
- package/dist/query/utils.d.ts +27 -10
- package/dist/query/utils.js +84 -14
- package/dist/query/where.d.ts +47 -28
- package/dist/query/where.js +129 -32
- package/dist/query/writes.d.ts +24 -5
- package/dist/query/writes.js +101 -13
- package/dist/realtime.d.ts +7 -7
- package/dist/realtime.js +9 -9
- package/dist/schema-builder.d.ts +18 -7
- package/dist/schema-builder.js +17 -10
- package/dist/schema-metadata.d.ts +3 -3
- package/dist/schema-metadata.js +9 -9
- package/dist/schema-sql.d.ts +9 -9
- package/dist/schema-sql.js +20 -20
- package/dist/schema.d.ts +19 -9
- package/dist/schema.js +6 -6
- package/dist/serverless.d.ts +15 -15
- package/dist/serverless.js +16 -16
- package/dist/sqlite.d.ts +8 -8
- package/dist/sqlite.js +53 -22
- package/dist/typed-sql.d.ts +4 -4
- package/dist/typed-sql.js +5 -5
- package/package.json +2 -2
package/dist/cjs/nested-write.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* turbine-orm
|
|
3
|
+
* turbine-orm, Nested write engine
|
|
4
4
|
*
|
|
5
5
|
* Tree-walking create/update that resolves relation fields in `data` into
|
|
6
6
|
* batched SQL operations within a transaction. Supports create, connect,
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* This module is imported by `query/builder.ts` when the `data` argument
|
|
11
11
|
* of `create()` or `update()` contains relation fields. It never imports
|
|
12
|
-
* `client.ts` directly
|
|
12
|
+
* `client.ts` directly, the transaction handle is passed in via
|
|
13
13
|
* `NestedWriteContext`.
|
|
14
14
|
*/
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -249,7 +249,7 @@ const M2M_SUPPORTED_OPS = new Set(['connect', 'disconnect', 'set']);
|
|
|
249
249
|
* On the core client the auto-created property accessors are CAMELCASED
|
|
250
250
|
* (`db.userTags` for `user_tags`, see the `Object.defineProperty` loops in
|
|
251
251
|
* client.ts), so `db["user_tags"]` is `undefined` for every snake_case junction
|
|
252
|
-
*
|
|
252
|
+
* - which is every junction `turbine pull` produces over a hand-written join
|
|
253
253
|
* table. `db.table("user_tags")` takes the raw table name and exists on both
|
|
254
254
|
* TurbineClient and the TransactionClient handed to `$transaction`, so that is
|
|
255
255
|
* the form to recommend.
|
|
@@ -476,9 +476,9 @@ const SKIP_DUPLICATES_FEATURE = 'createMany({ skipDuplicates: true })';
|
|
|
476
476
|
* `createMany({ skipDuplicates })`, so the engines that refuse it pay for the
|
|
477
477
|
* refusal once instead of on every connect.
|
|
478
478
|
*
|
|
479
|
-
* The capability is not reachable from here as a flag
|
|
479
|
+
* The capability is not reachable from here as a flag, the `Dialect` is private
|
|
480
480
|
* to QueryInterface / TurbineClient and `NestedWriteContext` carries only the
|
|
481
|
-
* schema and the transaction
|
|
481
|
+
* schema and the transaction, so it is read from the engine's OWN structured
|
|
482
482
|
* refusal (`UnsupportedFeatureError.feature`) rather than from a hardcoded
|
|
483
483
|
* engine list that would drift. Both refusing engines throw while BUILDING the
|
|
484
484
|
* statement, before anything is written, so the attempt is side-effect-free.
|
|
@@ -516,11 +516,11 @@ async function insertJunctionRowsSkippingDuplicates(ctx, plan, values) {
|
|
|
516
516
|
*
|
|
517
517
|
* 1. Junction constrains the pair AND the engine supports `skipDuplicates`
|
|
518
518
|
* (PostgreSQL, SQLite and MySQL: `ON CONFLICT DO NOTHING` / a no-op
|
|
519
|
-
* `ON DUPLICATE KEY UPDATE`)
|
|
519
|
+
* `ON DUPLICATE KEY UPDATE`), one INSERT, no read. The engine resolves the
|
|
520
520
|
* conflict, so two transactions connecting the same pair at the same time
|
|
521
521
|
* both succeed and one link row exists. This is the introspected path:
|
|
522
522
|
* every junction introspection can detect declares the pair unique.
|
|
523
|
-
* 2. Otherwise
|
|
523
|
+
* 2. Otherwise, read this parent's existing link rows for exactly these targets
|
|
524
524
|
* and insert only the missing ones. Used when the engine refuses the option
|
|
525
525
|
* (SQL Server and PowDB have no single-statement skip-duplicates form and
|
|
526
526
|
* throw E017), and when the junction does NOT constrain the pair, where
|
|
@@ -665,7 +665,7 @@ async function executeNestedCreate(ctx, tableName, data, depth = 0, path = []) {
|
|
|
665
665
|
validateOps(relName, ops, false);
|
|
666
666
|
}
|
|
667
667
|
// belongsTo relations put the foreign key on the PARENT row, so they must be
|
|
668
|
-
// resolved BEFORE the parent is inserted
|
|
668
|
+
// resolved BEFORE the parent is inserted, otherwise a NOT NULL FK column
|
|
669
669
|
// fails on the initial INSERT. We resolve each belongsTo op (create/connect/
|
|
670
670
|
// connectOrCreate) to its referenced row and fold the FK values into the
|
|
671
671
|
// parent's own INSERT.
|
|
@@ -686,7 +686,7 @@ async function executeNestedCreate(ctx, tableName, data, depth = 0, path = []) {
|
|
|
686
686
|
const parentRow = (await ctx.tx.table(tableName).create({
|
|
687
687
|
data: { ...scalars, ...belongsToFks },
|
|
688
688
|
}));
|
|
689
|
-
// Process hasMany / hasOne relations
|
|
689
|
+
// Process hasMany / hasOne relations, their FK lives on the CHILD, so they
|
|
690
690
|
// need the parent row to exist first.
|
|
691
691
|
for (const [relName, ops] of Object.entries(relations)) {
|
|
692
692
|
const rel = tableMeta.relations[relName];
|
|
@@ -753,7 +753,7 @@ async function executeNestedUpdate(ctx, tableName, where, data, depth = 0, path
|
|
|
753
753
|
for (const [relName, ops] of Object.entries(relations)) {
|
|
754
754
|
const rel = tableMeta.relations[relName];
|
|
755
755
|
if (rel.type === 'hasMany' || rel.type === 'hasOne') {
|
|
756
|
-
// create, connect, connectOrCreate
|
|
756
|
+
// create, connect, connectOrCreate, same as nested create
|
|
757
757
|
await processHasManyCreate(ctx, rel, ops, parentRow, depth, path, relName);
|
|
758
758
|
// disconnect
|
|
759
759
|
if (ops.disconnect !== undefined) {
|
|
@@ -778,7 +778,7 @@ async function executeNestedUpdate(ctx, tableName, where, data, depth = 0, path
|
|
|
778
778
|
}
|
|
779
779
|
else if (rel.type === 'belongsTo') {
|
|
780
780
|
await processBelongsToCreate(ctx, rel, ops, parentRow, tableName, depth, path, relName);
|
|
781
|
-
// update (belongsTo
|
|
781
|
+
// update (belongsTo, derive where from parent FK)
|
|
782
782
|
if (ops.update !== undefined) {
|
|
783
783
|
await processBelongsToUpdate(ctx, rel, ops.update, parentRow, tableName);
|
|
784
784
|
}
|
|
@@ -841,7 +841,7 @@ async function processHasManyCreate(ctx, rel, ops, parentRow, depth, path, relNa
|
|
|
841
841
|
}
|
|
842
842
|
}
|
|
843
843
|
else {
|
|
844
|
-
// Batch via createMany (UNNEST)
|
|
844
|
+
// Batch via createMany (UNNEST), fast path
|
|
845
845
|
const injected = items.map((item) => injectForeignKey(item, rel, parentRow, ctx.schema));
|
|
846
846
|
await ctx.tx.table(rel.to).createMany({ data: injected });
|
|
847
847
|
}
|
|
@@ -921,7 +921,7 @@ async function resolveBelongsToForCreate(ctx, rel, ops, parentTable, depth, path
|
|
|
921
921
|
async function processBelongsToCreate(ctx, rel, ops, parentRow, parentTable, depth, path, relName) {
|
|
922
922
|
const fks = (0, schema_js_1.normalizeKeyColumns)(rel.foreignKey);
|
|
923
923
|
const refs = (0, schema_js_1.normalizeKeyColumns)(rel.referenceKey);
|
|
924
|
-
// create
|
|
924
|
+
// create, insert the related row, then update parent's FK
|
|
925
925
|
if (ops.create !== undefined) {
|
|
926
926
|
const items = toArray(ops.create);
|
|
927
927
|
if (items.length > 0) {
|
|
@@ -940,7 +940,7 @@ async function processBelongsToCreate(ctx, rel, ops, parentRow, parentTable, dep
|
|
|
940
940
|
});
|
|
941
941
|
}
|
|
942
942
|
}
|
|
943
|
-
// connect
|
|
943
|
+
// connect, validate existence, update parent's FK
|
|
944
944
|
if (ops.connect !== undefined) {
|
|
945
945
|
const items = toArray(ops.connect);
|
|
946
946
|
if (items.length > 0) {
|
|
@@ -967,6 +967,41 @@ async function processBelongsToCreate(ctx, rel, ops, parentRow, parentTable, dep
|
|
|
967
967
|
// ---------------------------------------------------------------------------
|
|
968
968
|
// connect, connectOrCreate, disconnect, set, delete helpers
|
|
969
969
|
// ---------------------------------------------------------------------------
|
|
970
|
+
/**
|
|
971
|
+
* Refuse a connect that would take a to-many child away from another parent,
|
|
972
|
+
* when {@link NestedWriteContext.scopedConnect} is on. See that field for why.
|
|
973
|
+
*
|
|
974
|
+
* Compares the child's CURRENT foreign key against the parent's reference
|
|
975
|
+
* value. Null (unowned) passes, an exact match passes (idempotent re-connect),
|
|
976
|
+
* anything else is refused. Values are compared after normalizing to a
|
|
977
|
+
* primitive, so a bigint FK read back as a string cannot look like a mismatch
|
|
978
|
+
* against the number the parent write returned.
|
|
979
|
+
*/
|
|
980
|
+
function assertConnectInScope(ctx, rel, child, parentRow, target) {
|
|
981
|
+
if (!ctx.scopedConnect)
|
|
982
|
+
return;
|
|
983
|
+
if (rel.type !== 'hasMany' && rel.type !== 'hasOne')
|
|
984
|
+
return;
|
|
985
|
+
const childTable = ctx.schema.tables[rel.to];
|
|
986
|
+
const parentTable = ctx.schema.tables[rel.from];
|
|
987
|
+
if (!childTable)
|
|
988
|
+
return;
|
|
989
|
+
const fks = (0, schema_js_1.normalizeKeyColumns)(rel.foreignKey);
|
|
990
|
+
const refs = (0, schema_js_1.normalizeKeyColumns)(rel.referenceKey);
|
|
991
|
+
const key = (v) => (v === null || v === undefined ? null : String(v));
|
|
992
|
+
for (let i = 0; i < fks.length; i++) {
|
|
993
|
+
const fkField = childTable.reverseColumnMap[fks[i]] ?? fks[i];
|
|
994
|
+
const refField = parentTable?.reverseColumnMap[refs[i]] ?? refs[i];
|
|
995
|
+
const current = key(child[fkField]);
|
|
996
|
+
if (current === null)
|
|
997
|
+
continue;
|
|
998
|
+
if (current === key(parentRow[refField]))
|
|
999
|
+
continue;
|
|
1000
|
+
throw new errors_js_1.ValidationError(`[turbine] connect refused: ${rel.to} row ${(0, errors_js_1.describeTargetForMessage)(target)} is already owned by ` +
|
|
1001
|
+
`another "${rel.from}" (its ${fks[i]} is ${current}). \`scopedConnect\` only allows connecting a row ` +
|
|
1002
|
+
`that is unowned or already owned by this parent; re-parenting must be an explicit update.`);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
970
1005
|
async function batchConnect(ctx, rel, items, parentRow) {
|
|
971
1006
|
const fks = (0, schema_js_1.normalizeKeyColumns)(rel.foreignKey);
|
|
972
1007
|
const refs = (0, schema_js_1.normalizeKeyColumns)(rel.referenceKey);
|
|
@@ -979,6 +1014,7 @@ async function batchConnect(ctx, rel, items, parentRow) {
|
|
|
979
1014
|
if (!existing) {
|
|
980
1015
|
throw new errors_js_1.ValidationError(`[turbine] connect: no ${rel.to} row found matching ${(0, errors_js_1.describeTargetForMessage)(target)}.`);
|
|
981
1016
|
}
|
|
1017
|
+
assertConnectInScope(ctx, rel, existing, parentRow, target);
|
|
982
1018
|
}
|
|
983
1019
|
// Build FK update data to point children at parent
|
|
984
1020
|
const updateData = {};
|
|
@@ -1006,6 +1042,7 @@ async function connectOrCreate(ctx, rel, op, parentRow) {
|
|
|
1006
1042
|
row = (await ctx.tx.table(rel.to).create({ data: injected }));
|
|
1007
1043
|
}
|
|
1008
1044
|
else {
|
|
1045
|
+
assertConnectInScope(ctx, rel, row, parentRow, op.where);
|
|
1009
1046
|
// Update FK to point to parent
|
|
1010
1047
|
const updateData = {};
|
|
1011
1048
|
for (let i = 0; i < fks.length; i++) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
3
|
* True dynamic `import()` for the optional peer dependencies (`mysql2`,
|
|
4
|
-
* `mssql`, `@zvndev/powdb-client`, `@zvndev/powdb-embedded`)
|
|
4
|
+
* `mssql`, `@zvndev/powdb-client`, `@zvndev/powdb-embedded`), safe in BOTH
|
|
5
5
|
* build outputs, including for peers that are ESM-only.
|
|
6
6
|
*
|
|
7
7
|
* THE PROBLEM THIS FILE SOLVES (the `@zvndev/powdb-client` ≥ 0.9 CJS break):
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* peers stay out of the static graph. The ESM build (`tsconfig.json`, module
|
|
10
10
|
* NodeNext) emits that `import()` verbatim. The CJS build (`tsconfig.cjs.json`,
|
|
11
11
|
* module CommonJS) however TRANSPILES `import()` into
|
|
12
|
-
* `Promise.resolve().then(() => require(...))
|
|
12
|
+
* `Promise.resolve().then(() => require(...))`, and `require()` of an
|
|
13
13
|
* ESM-only package (no `require` export condition, e.g. powdb-client ≥ 0.9)
|
|
14
14
|
* throws `ERR_PACKAGE_PATH_NOT_EXPORTED`, breaking every CJS consumer.
|
|
15
15
|
*
|
|
@@ -18,18 +18,18 @@
|
|
|
18
18
|
* says `"type": "module"`, so NodeNext would classify every `.ts` source as
|
|
19
19
|
* ESM and emit ESM into dist/cjs). A `.cts` file is the escape hatch: it is
|
|
20
20
|
* CommonJS-format by extension regardless of package `type`, so under the ESM
|
|
21
|
-
* pass (NodeNext) it compiles to `dist/optional-peer-import.cjs
|
|
21
|
+
* pass (NodeNext) it compiles to `dist/optional-peer-import.cjs`, a CommonJS
|
|
22
22
|
* file whose `import()` SURVIVES transpilation (NodeNext preserves dynamic
|
|
23
23
|
* import in CJS files precisely because it is the only way CJS can load ESM).
|
|
24
24
|
*
|
|
25
25
|
* That gives the published package two copies of this module:
|
|
26
|
-
* - `dist/optional-peer-import.cjs` (ESM pass, NodeNext)
|
|
27
|
-
* - `dist/cjs/optional-peer-import.cjs` (CJS pass, CommonJS)
|
|
26
|
+
* - `dist/optional-peer-import.cjs` (ESM pass, NodeNext) , real `import()`
|
|
27
|
+
* - `dist/cjs/optional-peer-import.cjs` (CJS pass, CommonJS) , lowered to `require()`
|
|
28
28
|
*
|
|
29
29
|
* The lowered copy works fine for CJS-loadable peers (`mysql2`, `mssql`, older
|
|
30
30
|
* powdb peers). When it hits an ESM-only peer, the `require()` fails with a
|
|
31
31
|
* recognizable code and this function falls back to delegating the load to the
|
|
32
|
-
* sibling NodeNext copy one directory up (`../optional-peer-import.cjs`)
|
|
32
|
+
* sibling NodeNext copy one directory up (`../optional-peer-import.cjs`) -
|
|
33
33
|
* which is a plain CommonJS file (loadable by `require()` on every supported
|
|
34
34
|
* Node) whose real `import()` then loads the ESM peer. The ESM-pass copy has
|
|
35
35
|
* no such sibling; its lazy `require` throws and the original error surfaces,
|
|
@@ -93,7 +93,7 @@ function isEsmOnlyLoadError(err) {
|
|
|
93
93
|
* transpilation (see the module doc comment).
|
|
94
94
|
*
|
|
95
95
|
* @param specifier bare package specifier (e.g. `'@zvndev/powdb-client'`).
|
|
96
|
-
* @param allowEsmFallback internal recursion guard
|
|
96
|
+
* @param allowEsmFallback internal recursion guard, the delegated call passes
|
|
97
97
|
* `false` so a failure in the sibling copy can never bounce back.
|
|
98
98
|
*/
|
|
99
99
|
async function importOptionalPeer(specifier, allowEsmFallback = true) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* True dynamic `import()` for the optional peer dependencies (`mysql2`,
|
|
3
|
-
* `mssql`, `@zvndev/powdb-client`, `@zvndev/powdb-embedded`)
|
|
3
|
+
* `mssql`, `@zvndev/powdb-client`, `@zvndev/powdb-embedded`), safe in BOTH
|
|
4
4
|
* build outputs, including for peers that are ESM-only.
|
|
5
5
|
*
|
|
6
6
|
* THE PROBLEM THIS FILE SOLVES (the `@zvndev/powdb-client` ≥ 0.9 CJS break):
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* peers stay out of the static graph. The ESM build (`tsconfig.json`, module
|
|
9
9
|
* NodeNext) emits that `import()` verbatim. The CJS build (`tsconfig.cjs.json`,
|
|
10
10
|
* module CommonJS) however TRANSPILES `import()` into
|
|
11
|
-
* `Promise.resolve().then(() => require(...))
|
|
11
|
+
* `Promise.resolve().then(() => require(...))`, and `require()` of an
|
|
12
12
|
* ESM-only package (no `require` export condition, e.g. powdb-client ≥ 0.9)
|
|
13
13
|
* throws `ERR_PACKAGE_PATH_NOT_EXPORTED`, breaking every CJS consumer.
|
|
14
14
|
*
|
|
@@ -17,18 +17,18 @@
|
|
|
17
17
|
* says `"type": "module"`, so NodeNext would classify every `.ts` source as
|
|
18
18
|
* ESM and emit ESM into dist/cjs). A `.cts` file is the escape hatch: it is
|
|
19
19
|
* CommonJS-format by extension regardless of package `type`, so under the ESM
|
|
20
|
-
* pass (NodeNext) it compiles to `dist/optional-peer-import.cjs
|
|
20
|
+
* pass (NodeNext) it compiles to `dist/optional-peer-import.cjs`, a CommonJS
|
|
21
21
|
* file whose `import()` SURVIVES transpilation (NodeNext preserves dynamic
|
|
22
22
|
* import in CJS files precisely because it is the only way CJS can load ESM).
|
|
23
23
|
*
|
|
24
24
|
* That gives the published package two copies of this module:
|
|
25
|
-
* - `dist/optional-peer-import.cjs` (ESM pass, NodeNext)
|
|
26
|
-
* - `dist/cjs/optional-peer-import.cjs` (CJS pass, CommonJS)
|
|
25
|
+
* - `dist/optional-peer-import.cjs` (ESM pass, NodeNext) , real `import()`
|
|
26
|
+
* - `dist/cjs/optional-peer-import.cjs` (CJS pass, CommonJS) , lowered to `require()`
|
|
27
27
|
*
|
|
28
28
|
* The lowered copy works fine for CJS-loadable peers (`mysql2`, `mssql`, older
|
|
29
29
|
* powdb peers). When it hits an ESM-only peer, the `require()` fails with a
|
|
30
30
|
* recognizable code and this function falls back to delegating the load to the
|
|
31
|
-
* sibling NodeNext copy one directory up (`../optional-peer-import.cjs`)
|
|
31
|
+
* sibling NodeNext copy one directory up (`../optional-peer-import.cjs`) -
|
|
32
32
|
* which is a plain CommonJS file (loadable by `require()` on every supported
|
|
33
33
|
* Node) whose real `import()` then loads the ESM peer. The ESM-pass copy has
|
|
34
34
|
* no such sibling; its lazy `require` throws and the original error surfaces,
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
* transpilation (see the module doc comment).
|
|
47
47
|
*
|
|
48
48
|
* @param specifier bare package specifier (e.g. `'@zvndev/powdb-client'`).
|
|
49
|
-
* @param allowEsmFallback internal recursion guard
|
|
49
|
+
* @param allowEsmFallback internal recursion guard, the delegated call passes
|
|
50
50
|
* `false` so a failure in the sibling copy can never bounce back.
|
|
51
51
|
*/
|
|
52
52
|
declare function importOptionalPeer(specifier: string, allowEsmFallback?: boolean): Promise<unknown>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* turbine-orm
|
|
2
|
+
* turbine-orm, Real Postgres pipeline protocol implementation
|
|
3
3
|
*
|
|
4
4
|
* Uses the pg extended-query protocol wire methods (parse/bind/describe/execute/sync)
|
|
5
5
|
* exposed on pg.Client's Connection object to send multiple queries in a single
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import type { EventEmitter } from 'node:events';
|
|
20
20
|
import type { DeferredQuery } from './query/index.js';
|
|
21
|
-
/** The pg Connection object
|
|
21
|
+
/** The pg Connection object, an EventEmitter with wire-protocol methods */
|
|
22
22
|
export interface PgConnection extends EventEmitter {
|
|
23
23
|
stream: {
|
|
24
24
|
cork?: () => void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* turbine-orm
|
|
3
|
+
* turbine-orm, Real Postgres pipeline protocol implementation
|
|
4
4
|
*
|
|
5
5
|
* Uses the pg extended-query protocol wire methods (parse/bind/describe/execute/sync)
|
|
6
6
|
* exposed on pg.Client's Connection object to send multiple queries in a single
|
|
@@ -115,7 +115,7 @@ async function runPipelined(client, queries, options = {}) {
|
|
|
115
115
|
for (let i = 0; i < queries.length; i++) {
|
|
116
116
|
results.push(new result_1.default(undefined, client._types));
|
|
117
117
|
}
|
|
118
|
-
// commandComplete counter
|
|
118
|
+
// commandComplete counter, tracks position across all commands
|
|
119
119
|
let commandIndex = 0;
|
|
120
120
|
// readyForQuery counter
|
|
121
121
|
let rfqCount = 0;
|
|
@@ -193,7 +193,7 @@ async function runPipelined(client, queries, options = {}) {
|
|
|
193
193
|
reject(pipelineError);
|
|
194
194
|
return;
|
|
195
195
|
}
|
|
196
|
-
// All succeeded
|
|
196
|
+
// All succeeded, transform results
|
|
197
197
|
try {
|
|
198
198
|
const transformed = [];
|
|
199
199
|
for (let i = 0; i < queries.length; i++) {
|
|
@@ -210,13 +210,13 @@ async function runPipelined(client, queries, options = {}) {
|
|
|
210
210
|
// Event handlers
|
|
211
211
|
// -----------------------------------------------------------------------
|
|
212
212
|
function onParseComplete() {
|
|
213
|
-
// No action needed
|
|
213
|
+
// No action needed, anonymous prepared statements
|
|
214
214
|
}
|
|
215
215
|
function onBindComplete() {
|
|
216
216
|
// No action needed
|
|
217
217
|
}
|
|
218
218
|
function onNoData() {
|
|
219
|
-
// DML without RETURNING
|
|
219
|
+
// DML without RETURNING, no RowDescription follows. Fine.
|
|
220
220
|
}
|
|
221
221
|
function onRowDescription(msg) {
|
|
222
222
|
const qIdx = currentQueryIndex();
|
|
@@ -313,7 +313,7 @@ async function runPipelined(client, queries, options = {}) {
|
|
|
313
313
|
}, timeout);
|
|
314
314
|
}
|
|
315
315
|
// -----------------------------------------------------------------------
|
|
316
|
-
// Send protocol messages
|
|
316
|
+
// Send protocol messages, all in one TCP flush
|
|
317
317
|
// -----------------------------------------------------------------------
|
|
318
318
|
try {
|
|
319
319
|
if (connection.stream.cork) {
|
package/dist/cjs/pipeline.d.ts
CHANGED
package/dist/cjs/pipeline.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* turbine-orm
|
|
3
|
+
* turbine-orm, Pipeline execution
|
|
4
4
|
*
|
|
5
5
|
* Pipelines batch multiple independent queries into a single database round-trip.
|
|
6
6
|
* Instead of N sequential awaits (N round-trips), you get 1 round-trip for all N queries.
|
|
@@ -90,11 +90,11 @@ async function executePipeline(pool, queries, options) {
|
|
|
90
90
|
if (queries.length === 0) {
|
|
91
91
|
return [];
|
|
92
92
|
}
|
|
93
|
-
// Acquire a single client
|
|
93
|
+
// Acquire a single client, reused for both capability check and execution
|
|
94
94
|
const client = await pool.connect();
|
|
95
95
|
try {
|
|
96
96
|
if ((0, pipeline_submittable_js_1.supportsExtendedPipeline)(client)) {
|
|
97
|
-
// Real pipeline path
|
|
97
|
+
// Real pipeline path, uses extended-query protocol wire methods
|
|
98
98
|
const pipelineOptions = {
|
|
99
99
|
transactional: options?.transactional ?? true,
|
|
100
100
|
timeout: options?.timeout,
|
|
@@ -102,7 +102,7 @@ async function executePipeline(pool, queries, options) {
|
|
|
102
102
|
const results = await (0, pipeline_submittable_js_1.runPipelined)(client, queries, pipelineOptions);
|
|
103
103
|
return results;
|
|
104
104
|
}
|
|
105
|
-
// Sequential fallback
|
|
105
|
+
// Sequential fallback, reuses the same client
|
|
106
106
|
return await runSequential(client, queries, options);
|
|
107
107
|
}
|
|
108
108
|
finally {
|
package/dist/cjs/powdb.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* turbine-orm/powdb
|
|
2
|
+
* turbine-orm/powdb, Turbine's PowDB / PowQL backend.
|
|
3
3
|
*
|
|
4
4
|
* PowDB is a single-node embedded database with its own query language, **PowQL**
|
|
5
5
|
* (not SQL), reached over `@zvndev/powdb-client`'s binary TCP protocol. PowDB is a
|
|
@@ -10,26 +10,26 @@
|
|
|
10
10
|
*
|
|
11
11
|
* PowDB realities shape the design (all verified firsthand against a live
|
|
12
12
|
* `powdb-server` / the embedded addon, see `docs/internal/strategy/powdb-parity-matrix.md`):
|
|
13
|
-
* - **`RETURNING` (since 0.7.0)
|
|
13
|
+
* - **`RETURNING` (since 0.7.0)**, `create/createMany/update/delete` append the
|
|
14
14
|
* trailing `returning` keyword (`RETURNING *`, all columns) and read the
|
|
15
15
|
* affected rows back in one round-trip. `upsert` is the lone exception (its
|
|
16
16
|
* statement rejects `returning`) and reselects by primary key.
|
|
17
|
-
* - **No generated IDs
|
|
17
|
+
* - **No generated IDs**, the app must supply every value → Turbine generates a
|
|
18
18
|
* client-side UUID for the primary key when it has a default.
|
|
19
19
|
* - **`uuid`/`datetime`/`bytes` columns can't hold client-supplied values** (no
|
|
20
20
|
* literal, no working cast on the wire) → Turbine maps everything onto the four
|
|
21
21
|
* writable types (`str`/`int`/`float`/`bool`); `Date` → `int` epoch micros;
|
|
22
22
|
* `string` PKs hold UUID strings.
|
|
23
|
-
* - **No JSON aggregation / link navigation
|
|
23
|
+
* - **No JSON aggregation / link navigation**, single-query nested `with` is
|
|
24
24
|
* impossible → it degrades to batched N+1 loaders (Phase B).
|
|
25
|
-
* - **Single global write lock; no savepoints/isolation
|
|
25
|
+
* - **Single global write lock; no savepoints/isolation**, nested
|
|
26
26
|
* transactions / isolation / vector / LISTEN-NOTIFY / RLS throw.
|
|
27
27
|
* Independent concurrent `db.$transaction` calls do NOT throw: they queue
|
|
28
28
|
* FIFO on a pool-level gate and run one at a time (see {@link PowdbTxGate}).
|
|
29
|
-
* Only a *re-entrant* transaction
|
|
29
|
+
* Only a *re-entrant* transaction, a `db.$transaction` opened from inside
|
|
30
30
|
* an active transaction callback's async context, which queueing would
|
|
31
|
-
* deadlock
|
|
32
|
-
* - **The wire protocol pipelines
|
|
31
|
+
* deadlock, fails fast with E017.
|
|
32
|
+
* - **The wire protocol pipelines**, `@zvndev/powdb-client` writes each
|
|
33
33
|
* request frame immediately and matches replies FIFO, so multiple queries
|
|
34
34
|
* may be in flight on one connection. {@link PowdbPool}'s checked-out
|
|
35
35
|
* clients advertise `supportsPipelining`, which lets the batch
|
|
@@ -211,7 +211,7 @@ interface PowdbModule {
|
|
|
211
211
|
message: string;
|
|
212
212
|
};
|
|
213
213
|
}
|
|
214
|
-
/** Connection options for {@link turbinePowDB}
|
|
214
|
+
/** Connection options for {@link turbinePowDB}, host/port, not a connection string. */
|
|
215
215
|
export interface PowdbConnOptions {
|
|
216
216
|
host: string;
|
|
217
217
|
port: number;
|
|
@@ -258,7 +258,7 @@ export interface PowdbCapabilities {
|
|
|
258
258
|
/** ≥ 0.13: server-side joins, hash-accelerated and bounded. */
|
|
259
259
|
serverJoins: boolean;
|
|
260
260
|
/**
|
|
261
|
-
* ≥ 0.18: nested projections (shaped results)
|
|
261
|
+
* ≥ 0.18: nested projections (shaped results), a projection field may be a
|
|
262
262
|
* whole correlated child query returning a per-parent JSON array. When set,
|
|
263
263
|
* eligible `with` clauses compile into the parent statement instead of the
|
|
264
264
|
* batched loaders.
|
|
@@ -367,7 +367,7 @@ export declare function powqlColumnType(col: ColumnMetadata): PowqlType;
|
|
|
367
367
|
* synthesizing a client-side value for it.
|
|
368
368
|
*/
|
|
369
369
|
/**
|
|
370
|
-
* PowQL reserved words
|
|
370
|
+
* PowQL reserved words, the v0.10 lexer keyword table from POWQL.md's
|
|
371
371
|
* "Reserved Words and Quoting" section, including the v0.10 additions
|
|
372
372
|
* `schema` and `describe`. Keyword matching is case-sensitive in the lexer,
|
|
373
373
|
* so only the exact lowercase form collides.
|
|
@@ -376,7 +376,7 @@ export declare const POWQL_KEYWORDS: ReadonlySet<string>;
|
|
|
376
376
|
/**
|
|
377
377
|
* Backtick-quote an identifier when PowQL would otherwise lex it as a keyword
|
|
378
378
|
* (or when it contains characters outside the bare-identifier grammar).
|
|
379
|
-
* Applied only in bare-identifier positions
|
|
379
|
+
* Applied only in bare-identifier positions, DDL type/field names, index DDL,
|
|
380
380
|
* and `insert`/`update`/`upsert` assignment targets. Dotted references
|
|
381
381
|
* (`.col` in filters/projections/ordering) bypass keyword lookup on every
|
|
382
382
|
* engine version and deliberately stay bare for ≤0.9 compatibility. Backticks
|
|
@@ -505,7 +505,7 @@ export declare function rowToEntity(raw: Record<string, unknown>, meta: TableMet
|
|
|
505
505
|
* So we always run the unique-constraint and message-shape checks first (they
|
|
506
506
|
* fire for both transports and extract detail like constraint / column names),
|
|
507
507
|
* then classify by the typed wire error class (`.wireErrorClass`, networked
|
|
508
|
-
* server >= 0.17
|
|
508
|
+
* server >= 0.17, accurate even when the server sanitized the message text),
|
|
509
509
|
* then fall through to the networked `.code` switch.
|
|
510
510
|
*/
|
|
511
511
|
export declare function wrapPowdbError(err: unknown): Error;
|
|
@@ -587,7 +587,7 @@ export declare class PowdbPool implements PgCompatPool {
|
|
|
587
587
|
* Pool-level single-writer gate. PowDB holds one global write lock, so at
|
|
588
588
|
* most one transaction may be open across the whole pool. Concurrent
|
|
589
589
|
* `begin`s queue FIFO on the gate (instead of checking out a second
|
|
590
|
-
* connection and blocking on the lock forever
|
|
590
|
+
* connection and blocking on the lock forever, the networked hang);
|
|
591
591
|
* re-entrant `begin`s throw E017 (see {@link PowdbTxGate}).
|
|
592
592
|
*/
|
|
593
593
|
private readonly txGate;
|
|
@@ -624,7 +624,7 @@ export declare class PowdbPool implements PgCompatPool {
|
|
|
624
624
|
/**
|
|
625
625
|
* Typed guard mirroring {@link PowdbEmbeddedPool}: after `end()` the driver
|
|
626
626
|
* pool throws a raw `Error('pool closed')` that {@link wrapPowdbError}
|
|
627
|
-
* cannot classify
|
|
627
|
+
* cannot classify, surface the same ConnectionError on both transports.
|
|
628
628
|
*/
|
|
629
629
|
private assertOpen;
|
|
630
630
|
connect(): Promise<PgCompatPoolClient>;
|
|
@@ -653,7 +653,7 @@ interface EmbeddedDatabase {
|
|
|
653
653
|
querySql(sql: string): EmbeddedQueryResult;
|
|
654
654
|
queryReadonly(powql: string): EmbeddedQueryResult;
|
|
655
655
|
isPoisoned(): boolean;
|
|
656
|
-
/** WAL durability selector
|
|
656
|
+
/** WAL durability selector, `@zvndev/powdb-embedded` ≥ 0.7.1. */
|
|
657
657
|
setSyncMode?(mode: string): void;
|
|
658
658
|
/**
|
|
659
659
|
* Lossless typed native wire (`@zvndev/powdb-embedded` ≥ 0.14). All optional
|
|
@@ -671,7 +671,7 @@ interface EmbeddedDatabase {
|
|
|
671
671
|
interface EmbeddedModule {
|
|
672
672
|
Database: {
|
|
673
673
|
open(dir: string): EmbeddedDatabase;
|
|
674
|
-
/** Open with a per-query memory budget
|
|
674
|
+
/** Open with a per-query memory budget, `@zvndev/powdb-embedded` ≥ 0.7.1. */
|
|
675
675
|
openWithMemoryLimit?(dir: string, limitBytes: number): EmbeddedDatabase;
|
|
676
676
|
/**
|
|
677
677
|
* Open a read-only handle for snapshot serving (`@zvndev/powdb-embedded` ≥
|
|
@@ -684,14 +684,14 @@ interface EmbeddedModule {
|
|
|
684
684
|
}
|
|
685
685
|
/**
|
|
686
686
|
* Encode a JS value as a **PowQL literal** for the embedded driver, which takes
|
|
687
|
-
* no params array
|
|
687
|
+
* no params array, `$N` placeholders must be materialized into the query text.
|
|
688
688
|
*
|
|
689
689
|
* This is the single place Turbine builds PowQL text from a value, so it is the
|
|
690
690
|
* security-critical surface. String encoding matches PowDB's lexer
|
|
691
691
|
* (`crates/query/src/lexer.rs`) exactly: a string literal is `"…"`, and inside
|
|
692
692
|
* it the lexer recognizes only the escapes `\"`, `\\`, `\n`, `\t` (any other
|
|
693
|
-
* `\x` drops the backslash and keeps `x`; every non-`\`/non-`"` char
|
|
694
|
-
* newlines, CR, unicode
|
|
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
695
|
* `"` → `\"` (the only breakout vectors), render `\n`/`\t` as their recognized
|
|
696
696
|
* escapes, and leave everything else raw. Verified against the real engine:
|
|
697
697
|
* quotes, backslashes, `$N`, `"); drop … --`, raw CR, and emoji all round-trip
|
|
@@ -725,13 +725,13 @@ export declare function encodePowqlLiteral(value: unknown, position?: string): s
|
|
|
725
725
|
* `git diff v0.19.0 v0.19.1 -- crates/query/src/lexer.rs` is empty (the bare-dotted-path
|
|
726
726
|
* hard error is parser-level, not tokenization), so this ceiling stays `'0.19'`. The
|
|
727
727
|
* guard in {@link PowdbEmbeddedPool.exec} compares major.minor only, so `'0.19'`
|
|
728
|
-
* already covers every 0.19.x patch
|
|
728
|
+
* already covers every 0.19.x patch, no bump is needed for 0.19.1.
|
|
729
729
|
*/
|
|
730
730
|
export declare const POWQL_LEXER_TESTED_CEILING = "0.19";
|
|
731
731
|
/**
|
|
732
732
|
* Substitute every `$N` placeholder in a generator-produced PowQL template with
|
|
733
733
|
* the encoded literal of `params[N-1]`. Safe because the template is produced by
|
|
734
|
-
* {@link PowqlInterface} and contains **no** user string literals
|
|
734
|
+
* {@link PowqlInterface} and contains **no** user string literals, the only
|
|
735
735
|
* `$<digits>` tokens are genuine positional placeholders, so a single scan
|
|
736
736
|
* cannot accidentally rewrite a `$N` that is itself part of a value (values are
|
|
737
737
|
* params, never inlined into the template by the generator).
|
|
@@ -754,7 +754,7 @@ export declare class PowdbEmbeddedPool implements PgCompatPool {
|
|
|
754
754
|
private closed;
|
|
755
755
|
/**
|
|
756
756
|
* Single-writer gate. The embedded engine is one handle with one global
|
|
757
|
-
* write lock
|
|
757
|
+
* write lock, only one transaction may be open at a time. A re-entrant
|
|
758
758
|
* `begin` (a fresh top-level `db.$transaction` opened inside an open one's
|
|
759
759
|
* callback) would otherwise hit PowDB's raw "already in a transaction"
|
|
760
760
|
* parse error; the gate surfaces a typed E017 instead, while INDEPENDENT
|
|
@@ -820,7 +820,7 @@ export interface TurbinePowdbOptions extends Pick<TurbineConfig, 'logging' | 'de
|
|
|
820
820
|
* `0` / `Infinity` = wait without limit). Independent concurrent
|
|
821
821
|
* transactions queue and run one at a time; only a re-entrant
|
|
822
822
|
* `db.$transaction` (opened inside an active transaction callback) throws
|
|
823
|
-
* E017
|
|
823
|
+
* E017, queueing that shape would deadlock.
|
|
824
824
|
*
|
|
825
825
|
* Ignored when you inject an already-constructed {@link PowdbPool} (it carries
|
|
826
826
|
* its own {@link PowdbPoolOptions}); set it on that pool's constructor instead.
|
|
@@ -876,7 +876,7 @@ export interface TurbinePowdbOptions extends Pick<TurbineConfig, 'logging' | 'de
|
|
|
876
876
|
powdbEmbeddedModule?: EmbeddedModule;
|
|
877
877
|
}
|
|
878
878
|
/**
|
|
879
|
-
* Selects the **embedded** transport
|
|
879
|
+
* Selects the **embedded** transport, an in-process `@zvndev/powdb-embedded`
|
|
880
880
|
* database at the given data directory (no server, no socket). The value is the
|
|
881
881
|
* data dir path. Preview: Full-durability checkpoint-bound; built binaries ship
|
|
882
882
|
* for macOS (arm64/x64) and Unix-glibc only (Intel-mac/musl/Windows fall back to
|
|
@@ -885,7 +885,7 @@ export interface TurbinePowdbOptions extends Pick<TurbineConfig, 'logging' | 'de
|
|
|
885
885
|
* @example
|
|
886
886
|
* ```ts
|
|
887
887
|
* const db = await turbinePowDB({ embedded: '/var/data/app.powdb' }, SCHEMA);
|
|
888
|
-
* // Faster writes (fsync off the commit path, bounded-loss)
|
|
888
|
+
* // Faster writes (fsync off the commit path, bounded-loss), requires addon >= 0.7.1:
|
|
889
889
|
* const fast = await turbinePowDB({ embedded: '/var/data/app.powdb', syncMode: 'normal' }, SCHEMA);
|
|
890
890
|
* ```
|
|
891
891
|
*/
|
|
@@ -893,7 +893,7 @@ export interface TurbinePowdbEmbeddedTarget {
|
|
|
893
893
|
embedded: string;
|
|
894
894
|
/**
|
|
895
895
|
* WAL durability for the embedded engine (requires `@zvndev/powdb-embedded` ≥ 0.7.1):
|
|
896
|
-
* `'full'` (default
|
|
896
|
+
* `'full'` (default, fsync per commit), `'normal'` (fsync off the commit path,
|
|
897
897
|
* ~15–40× faster writes, bounded loss on OS crash/power loss), `'off'` (bench-only).
|
|
898
898
|
*/
|
|
899
899
|
syncMode?: 'full' | 'normal' | 'off';
|
|
@@ -919,7 +919,7 @@ export interface TurbinePowdbEmbeddedTarget {
|
|
|
919
919
|
* - an `{ embedded: <data-dir> }` object → an in-process
|
|
920
920
|
* `@zvndev/powdb-embedded` database (no server);
|
|
921
921
|
* - an already-constructed `@zvndev/powdb-client` `Pool` or {@link PowdbPool}
|
|
922
|
-
* (injection
|
|
922
|
+
* (injection, you own its lifecycle and `disconnect()` is a no-op).
|
|
923
923
|
*
|
|
924
924
|
* On the networked transport the server version is probed and a clear
|
|
925
925
|
* {@link ConnectionError} is thrown if it is older than {@link MIN_POWDB_VERSION}
|