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.
Files changed (186) hide show
  1. package/README.md +66 -66
  2. package/dist/adapters/cockroachdb.d.ts +5 -5
  3. package/dist/adapters/cockroachdb.js +10 -10
  4. package/dist/adapters/index.d.ts +5 -5
  5. package/dist/adapters/index.js +7 -7
  6. package/dist/adapters/yugabytedb.d.ts +7 -7
  7. package/dist/adapters/yugabytedb.js +10 -10
  8. package/dist/cjs/adapters/cockroachdb.d.ts +5 -5
  9. package/dist/cjs/adapters/cockroachdb.js +10 -10
  10. package/dist/cjs/adapters/index.d.ts +5 -5
  11. package/dist/cjs/adapters/index.js +7 -7
  12. package/dist/cjs/adapters/yugabytedb.d.ts +7 -7
  13. package/dist/cjs/adapters/yugabytedb.js +10 -10
  14. package/dist/cjs/cli/config.d.ts +13 -2
  15. package/dist/cjs/cli/config.js +3 -2
  16. package/dist/cjs/cli/destructive.d.ts +1 -1
  17. package/dist/cjs/cli/destructive.js +1 -1
  18. package/dist/cjs/cli/index.d.ts +10 -10
  19. package/dist/cjs/cli/index.js +49 -45
  20. package/dist/cjs/cli/loader.d.ts +7 -7
  21. package/dist/cjs/cli/loader.js +9 -9
  22. package/dist/cjs/cli/mcp.js +4 -4
  23. package/dist/cjs/cli/migrate.d.ts +5 -5
  24. package/dist/cjs/cli/migrate.js +11 -11
  25. package/dist/cjs/cli/studio-ui.generated.js +1 -1
  26. package/dist/cjs/cli/ui.d.ts +2 -2
  27. package/dist/cjs/cli/ui.js +2 -2
  28. package/dist/cjs/client.d.ts +49 -38
  29. package/dist/cjs/client.js +57 -56
  30. package/dist/cjs/dialect.d.ts +62 -18
  31. package/dist/cjs/dialect.js +40 -2
  32. package/dist/cjs/errors.d.ts +5 -5
  33. package/dist/cjs/errors.js +11 -11
  34. package/dist/cjs/generate.d.ts +6 -6
  35. package/dist/cjs/generate.js +31 -29
  36. package/dist/cjs/index-advisor.d.ts +5 -5
  37. package/dist/cjs/index-advisor.js +0 -0
  38. package/dist/cjs/index.d.ts +1 -1
  39. package/dist/cjs/index.js +7 -7
  40. package/dist/cjs/introspect.d.ts +35 -9
  41. package/dist/cjs/introspect.js +83 -32
  42. package/dist/cjs/mssql.d.ts +11 -11
  43. package/dist/cjs/mssql.js +64 -29
  44. package/dist/cjs/mysql.d.ts +8 -8
  45. package/dist/cjs/mysql.js +61 -23
  46. package/dist/cjs/nested-write.d.ts +21 -2
  47. package/dist/cjs/nested-write.js +51 -14
  48. package/dist/cjs/optional-peer-import.cjs +7 -7
  49. package/dist/cjs/optional-peer-import.d.cts +7 -7
  50. package/dist/cjs/pipeline-submittable.d.ts +2 -2
  51. package/dist/cjs/pipeline-submittable.js +6 -6
  52. package/dist/cjs/pipeline.d.ts +1 -1
  53. package/dist/cjs/pipeline.js +4 -4
  54. package/dist/cjs/powdb-introspect.d.ts +1 -1
  55. package/dist/cjs/powdb-introspect.js +1 -1
  56. package/dist/cjs/powdb.d.ts +28 -28
  57. package/dist/cjs/powdb.js +66 -66
  58. package/dist/cjs/powql.d.ts +27 -27
  59. package/dist/cjs/powql.js +73 -52
  60. package/dist/cjs/query/aggregates.d.ts +1 -1
  61. package/dist/cjs/query/aggregates.js +5 -5
  62. package/dist/cjs/query/batched-loader.d.ts +11 -11
  63. package/dist/cjs/query/batched-loader.js +24 -24
  64. package/dist/cjs/query/builder.d.ts +39 -21
  65. package/dist/cjs/query/builder.js +99 -57
  66. package/dist/cjs/query/compound-unique.d.ts +1 -1
  67. package/dist/cjs/query/compound-unique.js +0 -0
  68. package/dist/cjs/query/deferred.d.ts +12 -6
  69. package/dist/cjs/query/deferred.js +1 -1
  70. package/dist/cjs/query/filters.d.ts +31 -11
  71. package/dist/cjs/query/filters.js +67 -14
  72. package/dist/cjs/query/index.d.ts +1 -1
  73. package/dist/cjs/query/index.js +1 -1
  74. package/dist/cjs/query/relations.d.ts +9 -9
  75. package/dist/cjs/query/relations.js +164 -57
  76. package/dist/cjs/query/types.d.ts +86 -35
  77. package/dist/cjs/query/types.js +1 -1
  78. package/dist/cjs/query/utils.d.ts +27 -10
  79. package/dist/cjs/query/utils.js +86 -14
  80. package/dist/cjs/query/where.d.ts +47 -28
  81. package/dist/cjs/query/where.js +130 -31
  82. package/dist/cjs/query/writes.d.ts +24 -5
  83. package/dist/cjs/query/writes.js +102 -13
  84. package/dist/cjs/realtime.d.ts +7 -7
  85. package/dist/cjs/realtime.js +9 -9
  86. package/dist/cjs/schema-builder.d.ts +18 -7
  87. package/dist/cjs/schema-builder.js +17 -10
  88. package/dist/cjs/schema-metadata.d.ts +3 -3
  89. package/dist/cjs/schema-metadata.js +9 -9
  90. package/dist/cjs/schema-sql.d.ts +9 -9
  91. package/dist/cjs/schema-sql.js +20 -20
  92. package/dist/cjs/schema.d.ts +19 -9
  93. package/dist/cjs/schema.js +6 -6
  94. package/dist/cjs/serverless.d.ts +15 -15
  95. package/dist/cjs/serverless.js +16 -16
  96. package/dist/cjs/sqlite.d.ts +8 -8
  97. package/dist/cjs/sqlite.js +53 -22
  98. package/dist/cjs/typed-sql.d.ts +4 -4
  99. package/dist/cjs/typed-sql.js +5 -5
  100. package/dist/cli/config.d.ts +13 -2
  101. package/dist/cli/config.js +3 -2
  102. package/dist/cli/destructive.d.ts +1 -1
  103. package/dist/cli/destructive.js +1 -1
  104. package/dist/cli/index.d.ts +10 -10
  105. package/dist/cli/index.js +49 -45
  106. package/dist/cli/loader.d.ts +7 -7
  107. package/dist/cli/loader.js +9 -9
  108. package/dist/cli/mcp.js +4 -4
  109. package/dist/cli/migrate.d.ts +5 -5
  110. package/dist/cli/migrate.js +11 -11
  111. package/dist/cli/studio-ui.generated.js +1 -1
  112. package/dist/cli/ui.d.ts +2 -2
  113. package/dist/cli/ui.js +2 -2
  114. package/dist/client.d.ts +49 -38
  115. package/dist/client.js +57 -56
  116. package/dist/dialect.d.ts +62 -18
  117. package/dist/dialect.js +40 -2
  118. package/dist/errors.d.ts +5 -5
  119. package/dist/errors.js +11 -11
  120. package/dist/generate.d.ts +6 -6
  121. package/dist/generate.js +31 -29
  122. package/dist/index-advisor.d.ts +5 -5
  123. package/dist/index-advisor.js +0 -0
  124. package/dist/index.d.ts +1 -1
  125. package/dist/index.js +7 -7
  126. package/dist/introspect.d.ts +35 -9
  127. package/dist/introspect.js +82 -32
  128. package/dist/mssql.d.ts +11 -11
  129. package/dist/mssql.js +64 -29
  130. package/dist/mysql.d.ts +8 -8
  131. package/dist/mysql.js +61 -23
  132. package/dist/nested-write.d.ts +21 -2
  133. package/dist/nested-write.js +51 -14
  134. package/dist/optional-peer-import.cjs +7 -7
  135. package/dist/optional-peer-import.d.cts +7 -7
  136. package/dist/pipeline-submittable.d.ts +2 -2
  137. package/dist/pipeline-submittable.js +6 -6
  138. package/dist/pipeline.d.ts +1 -1
  139. package/dist/pipeline.js +4 -4
  140. package/dist/powdb-introspect.d.ts +1 -1
  141. package/dist/powdb-introspect.js +1 -1
  142. package/dist/powdb.d.ts +28 -28
  143. package/dist/powdb.js +66 -66
  144. package/dist/powql.d.ts +27 -27
  145. package/dist/powql.js +73 -52
  146. package/dist/query/aggregates.d.ts +1 -1
  147. package/dist/query/aggregates.js +5 -5
  148. package/dist/query/batched-loader.d.ts +11 -11
  149. package/dist/query/batched-loader.js +24 -24
  150. package/dist/query/builder.d.ts +39 -21
  151. package/dist/query/builder.js +100 -58
  152. package/dist/query/compound-unique.d.ts +1 -1
  153. package/dist/query/compound-unique.js +0 -0
  154. package/dist/query/deferred.d.ts +12 -6
  155. package/dist/query/deferred.js +1 -1
  156. package/dist/query/filters.d.ts +31 -11
  157. package/dist/query/filters.js +66 -13
  158. package/dist/query/index.d.ts +1 -1
  159. package/dist/query/index.js +1 -1
  160. package/dist/query/relations.d.ts +9 -9
  161. package/dist/query/relations.js +165 -58
  162. package/dist/query/types.d.ts +86 -35
  163. package/dist/query/types.js +1 -1
  164. package/dist/query/utils.d.ts +27 -10
  165. package/dist/query/utils.js +84 -14
  166. package/dist/query/where.d.ts +47 -28
  167. package/dist/query/where.js +129 -32
  168. package/dist/query/writes.d.ts +24 -5
  169. package/dist/query/writes.js +101 -13
  170. package/dist/realtime.d.ts +7 -7
  171. package/dist/realtime.js +9 -9
  172. package/dist/schema-builder.d.ts +18 -7
  173. package/dist/schema-builder.js +17 -10
  174. package/dist/schema-metadata.d.ts +3 -3
  175. package/dist/schema-metadata.js +9 -9
  176. package/dist/schema-sql.d.ts +9 -9
  177. package/dist/schema-sql.js +20 -20
  178. package/dist/schema.d.ts +19 -9
  179. package/dist/schema.js +6 -6
  180. package/dist/serverless.d.ts +15 -15
  181. package/dist/serverless.js +16 -16
  182. package/dist/sqlite.d.ts +8 -8
  183. package/dist/sqlite.js +53 -22
  184. package/dist/typed-sql.d.ts +4 -4
  185. package/dist/typed-sql.js +5 -5
  186. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /**
3
- * turbine-orm — Nested write engine
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 — the transaction handle is passed in via
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
- * — which is every junction `turbine pull` produces over a hand-written join
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 — the `Dialect` is private
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 — so it is read from the engine's OWN structured
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`) — one INSERT, no read. The engine resolves the
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 — read this parent's existing link rows for exactly these targets
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 — otherwise a NOT NULL FK column
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 — their FK lives on the CHILD, so they
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 — same as nested create
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 — derive where from parent FK)
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) — fast path
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 — insert the related row, then update parent's FK
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 — validate existence, update parent's FK
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`) — safe in BOTH
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(...))` — and `require()` of an
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` — a CommonJS
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) — real `import()`
27
- * - `dist/cjs/optional-peer-import.cjs` (CJS pass, CommonJS) — lowered to `require()`
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 — the delegated call passes
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`) — safe in BOTH
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(...))` — and `require()` of an
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` — a CommonJS
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) — real `import()`
26
- * - `dist/cjs/optional-peer-import.cjs` (CJS pass, CommonJS) — lowered to `require()`
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 — the delegated call passes
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 — Real Postgres pipeline protocol implementation
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 — an EventEmitter with wire-protocol methods */
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 — Real Postgres pipeline protocol implementation
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 — tracks position across all commands
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 — transform results
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 — anonymous prepared statements
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 — no RowDescription follows. Fine.
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 — all in one TCP flush
316
+ // Send protocol messages, all in one TCP flush
317
317
  // -----------------------------------------------------------------------
318
318
  try {
319
319
  if (connection.stream.cork) {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * turbine-orm — Pipeline execution
2
+ * turbine-orm, Pipeline execution
3
3
  *
4
4
  * Pipelines batch multiple independent queries into a single database round-trip.
5
5
  * Instead of N sequential awaits (N round-trips), you get 1 round-trip for all N queries.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /**
3
- * turbine-orm — Pipeline execution
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 — reused for both capability check and execution
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 — uses extended-query protocol wire methods
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 — reuses the same client
105
+ // Sequential fallback, reuses the same client
106
106
  return await runSequential(client, queries, options);
107
107
  }
108
108
  finally {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * turbine-orm/powdb — `describe`-based introspection.
2
+ * turbine-orm/powdb, `describe`-based introspection.
3
3
  *
4
4
  * PowDB exposes its catalog through two ordinary rows-returning statements
5
5
  * (keywords since engine 0.10):
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /**
3
- * turbine-orm/powdb — `describe`-based introspection.
3
+ * turbine-orm/powdb, `describe`-based introspection.
4
4
  *
5
5
  * PowDB exposes its catalog through two ordinary rows-returning statements
6
6
  * (keywords since engine 0.10):
@@ -1,5 +1,5 @@
1
1
  /**
2
- * turbine-orm/powdb — Turbine's PowDB / PowQL backend.
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)** — `create/createMany/update/delete` append the
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** — the app must supply every value → Turbine generates a
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** — single-query nested `with` is
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** — nested
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 — a `db.$transaction` opened from inside
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 — fails fast with E017.
32
- * - **The wire protocol pipelines** — `@zvndev/powdb-client` writes each
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} — host/port, not a connection string. */
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) — a projection field may be a
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 — the v0.10 lexer keyword table from POWQL.md's
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 — DDL type/field names, index DDL,
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 — accurate even when the server sanitized the message text),
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 — the networked hang);
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 — surface the same ConnectionError on both transports.
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 — `@zvndev/powdb-embedded` ≥ 0.7.1. */
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 — `@zvndev/powdb-embedded` ≥ 0.7.1. */
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 — `$N` placeholders must be materialized into the query text.
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 — raw
694
- * newlines, CR, unicode — is taken literally). So we escape `\` → `\\` and
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 — no bump is needed for 0.19.1.
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 — the only
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 — only one transaction may be open at a time. A re-entrant
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 — queueing that shape would deadlock.
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 — an in-process `@zvndev/powdb-embedded`
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) — requires addon >= 0.7.1:
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 — fsync per commit), `'normal'` (fsync off the commit path,
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 — you own its lifecycle and `disconnect()` is a no-op).
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}