@orkestrel/database 0.0.12 → 0.0.13

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.
@@ -1,11 +1,11 @@
1
- import { DatabaseError, MemoryDriver, applyQuery, bindRowKey, checkAbort, cloneDriverMetadata, cloneMigrationInput, computeAggregate, equalsValue, extractKey, filterRows, isDatabaseError, isKey, matchesQuery, migrateRows, normalizeDriverSchema, planMigration, projectMigrationSchema, validatePage } from "../core/index.js";
1
+ import { DatabaseError, DriverIterator, MemoryDriver, applyQuery, bindRowKey, checkAbort, cloneDriverMetadata, cloneMigrationInput, computeAggregate, equalsValue, extractKey, filterRows, findColumn, isDatabaseError, isKey, matchesQuery, migrateRows, normalizeDriverSchema, planMigration, projectMigrationSchema, validatePage } from "../core/index.js";
2
2
  import { cloneJSONValue, isBoolean, isFiniteNumber, isRecord, isString } from "@orkestrel/contract";
3
3
  import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
4
4
  import { dirname } from "node:path";
5
5
  import { createSQLiteDatabase, isSQLiteError } from "@orkestrel/sqlite";
6
6
  //#region src/server/constants.ts
7
7
  /**
8
- * The declared {@link ColumnStorage}s whose SQL EQUALITY comparisons (`equals` /
8
+ * Lists the declared {@link ColumnStorage}s whose SQL EQUALITY comparisons (`equals` /
9
9
  * `not` / `any` / `none`) and `starts` / `ends` compiles are provably
10
10
  * engine-exact under declared-type trust — `text` / `integer` / `real` /
11
11
  * `boolean`; a `json` or `blob` column always refines instead.
@@ -18,7 +18,7 @@ import { createSQLiteDatabase, isSQLiteError } from "@orkestrel/sqlite";
18
18
  * TEXT byte-for-byte as UTF-8 — equivalent to Unicode CODE-POINT order —
19
19
  * while the core engine's `compareValues` orders JS strings with `<`, which
20
20
  * compares UTF-16 CODE-UNIT order. The two orders diverge for supplementary-
21
- * plane characters (code points ≥ U+10000, e.g. many emoji): a lead surrogate
21
+ * plane characters (code points ≥ U+10000, for example many emoji): a lead surrogate
22
22
  * (`\uD800`–`\uDBFF`) sorts BELOW ``–`￿` in code-unit order, while
23
23
  * its code point sorts ABOVE them. So `matchesConditionExactly`'s range family and
24
24
  * `matchesOrderExactly` exclude `text`, refining through the core engine instead.
@@ -30,7 +30,7 @@ var EXACT_COLUMN_STORAGE = Object.freeze([
30
30
  "boolean"
31
31
  ]);
32
32
  /**
33
- * The declared {@link ColumnStorage}s whose SQL RANGE comparisons
33
+ * Lists the declared {@link ColumnStorage}s whose SQL RANGE comparisons
34
34
  * (`above` / `below` / `from` / `to` / `between`) and `ORDER BY` compiles are
35
35
  * provably engine-exact — `integer` / `real` / `boolean` only. `text` is
36
36
  * excluded: see {@link EXACT_COLUMN_STORAGE}'s remarks for the BINARY-collation
@@ -43,7 +43,7 @@ var EXACT_RANGE_COLUMN_STORAGE = Object.freeze([
43
43
  "boolean"
44
44
  ]);
45
45
  /**
46
- * The reserved metadata table the {@link SQLiteDriver} creates on `open` to
46
+ * Names the reserved metadata table the {@link SQLiteDriver} creates on `open` to
47
47
  * persist its stamped `DriverMetadata` (`version` + declared schema JSON) — the
48
48
  * SQLite realization of the `metadata` / `stamp` driver hooks.
49
49
  *
@@ -55,7 +55,7 @@ var METADATA_TABLE = "_metadata";
55
55
  //#endregion
56
56
  //#region src/server/helpers.ts
57
57
  /**
58
- * Whether a caught filesystem error reports that nothing is there to read.
58
+ * Reports whether a caught filesystem error says that nothing is there to read.
59
59
  *
60
60
  * @remarks
61
61
  * Two codes carry that meaning: `ENOENT` is a plain absence, and `ENOTDIR` is a
@@ -72,7 +72,7 @@ var METADATA_TABLE = "_metadata";
72
72
  * answers `false` rather than being read for a `code` any object could carry.
73
73
  *
74
74
  * @param error - The caught value to classify; any runtime is accepted
75
- * @returns `true` when the error reports that the path holds nothing
75
+ * @returns True if the error reports that the path holds nothing; false otherwise
76
76
  *
77
77
  * @example
78
78
  * ```ts
@@ -86,21 +86,21 @@ function matchesAbsentPath(error) {
86
86
  return error.code === "ENOENT" || error.code === "ENOTDIR";
87
87
  }
88
88
  /**
89
- * Whether a value's runtime type matches a column's declared exact type
90
- * the operand side of the declared-type-trust proof.
89
+ * Reports whether a value's runtime type matches a column's declared exact type
90
+ * the operand side of the declared-type-trust proof.
91
91
  *
92
92
  * @remarks
93
93
  * `text` ↔ string, `integer` / `real` ↔ FINITE number (`NaN` / `±Infinity`
94
94
  * fail), `boolean` ↔ boolean. Backs {@link matchesConditionExactly}'s operand checks.
95
95
  *
96
96
  * @param value - The condition operand to test
97
- * @param type - The column's declared portable type
98
- * @returns `true` when the operand's runtime type matches the declared type
97
+ * @param storage - The column's declared portable storage type
98
+ * @returns True if the operand's runtime type matches the declared type; false otherwise
99
99
  *
100
100
  * @example
101
101
  * ```ts
102
- * matchesDeclaredType('Ada', 'text') // true
103
- * matchesDeclaredType(Number.NaN, 'integer') // false — only finite numbers
102
+ * matchesDeclaredStorage('Ada', 'text') // true
103
+ * matchesDeclaredStorage(Number.NaN, 'integer') // false — only finite numbers
104
104
  * ```
105
105
  */
106
106
  function matchesDeclaredStorage(value, storage) {
@@ -109,9 +109,9 @@ function matchesDeclaredStorage(value, storage) {
109
109
  return isFiniteNumber(value);
110
110
  }
111
111
  /**
112
- * Whether one {@link Condition} compiles to SQL that is PROVABLY identical to
113
- * the core engine's `matchesCondition` for every value its column's declared
114
- * type can store.
112
+ * Reports whether one {@link Condition} compiles to SQL that is PROVABLY
113
+ * identical to the core engine's `matchesCondition` for every value its
114
+ * column's declared type can store.
115
115
  *
116
116
  * @remarks
117
117
  * `false` for a nested `FieldPath` (an array) or a column absent from `schema`.
@@ -140,15 +140,15 @@ function matchesDeclaredStorage(value, storage) {
140
140
  *
141
141
  * @param condition - The condition to test
142
142
  * @param schema - The table's schema
143
- * @returns Whether `condition` is exact
143
+ * @returns True if `condition` is exact; false otherwise
144
144
  */
145
145
  function matchesConditionExactly(condition, schema) {
146
146
  if (!isString(condition.column)) return false;
147
- const column = schema.columns.find((candidate) => candidate.name === condition.column);
147
+ const column = findColumn(condition.column, schema);
148
148
  if (column === void 0) return false;
149
149
  if (condition.operator === "absent" || condition.operator === "present") return !(column.optional && column.nullable);
150
150
  if (column.optional || column.nullable) return false;
151
- if (!EXACT_COLUMN_STORAGE.some((storage) => storage === column.storage)) return false;
151
+ if (!EXACT_COLUMN_STORAGE.includes(column.storage)) return false;
152
152
  const first = condition.values[0];
153
153
  const second = condition.values[1];
154
154
  switch (condition.operator) {
@@ -157,8 +157,8 @@ function matchesConditionExactly(condition, schema) {
157
157
  case "above":
158
158
  case "below":
159
159
  case "from":
160
- case "to": return EXACT_RANGE_COLUMN_STORAGE.some((storage) => storage === column.storage) && matchesDeclaredStorage(first, column.storage);
161
- case "between": return EXACT_RANGE_COLUMN_STORAGE.some((storage) => storage === column.storage) && matchesDeclaredStorage(first, column.storage) && matchesDeclaredStorage(second, column.storage);
160
+ case "to": return EXACT_RANGE_COLUMN_STORAGE.includes(column.storage) && matchesDeclaredStorage(first, column.storage);
161
+ case "between": return EXACT_RANGE_COLUMN_STORAGE.includes(column.storage) && matchesDeclaredStorage(first, column.storage) && matchesDeclaredStorage(second, column.storage);
162
162
  case "any":
163
163
  case "none": return condition.values.length > 0 && condition.values.every((value) => matchesDeclaredStorage(value, column.storage));
164
164
  case "starts":
@@ -168,8 +168,8 @@ function matchesConditionExactly(condition, schema) {
168
168
  }
169
169
  }
170
170
  /**
171
- * Whether one {@link Order} term's column compiles to an `ORDER BY` that
172
- * matches the engine's {@link import('@src/core').sortRows} exactly.
171
+ * Reports whether one {@link Order} term's column compiles to an `ORDER BY`
172
+ * that matches the engine's {@link import('@src/core').sortRows} exactly.
173
173
  *
174
174
  * @remarks
175
175
  * `false` for a nested `FieldPath`, a column absent from `schema`, or a
@@ -182,22 +182,22 @@ function matchesConditionExactly(condition, schema) {
182
182
  *
183
183
  * @param order - The order term to test
184
184
  * @param schema - The table's schema
185
- * @returns Whether `order` is exact
185
+ * @returns True if `order` is exact; false otherwise
186
186
  */
187
187
  function matchesOrderExactly(order, schema) {
188
188
  if (!isString(order.column)) return false;
189
- const column = schema.columns.find((candidate) => candidate.name === order.column);
189
+ const column = findColumn(order.column, schema);
190
190
  if (column === void 0) return false;
191
- return !column.optional && !column.nullable && EXACT_RANGE_COLUMN_STORAGE.some((storage) => storage === column.storage);
191
+ return !column.optional && !column.nullable && EXACT_RANGE_COLUMN_STORAGE.includes(column.storage);
192
192
  }
193
193
  /**
194
- * Whether a whole {@link QueryInput} is exact — every condition and every order
195
- * term is exact. `limit` / `offset` never affect exactness (SQL `LIMIT` /
196
- * `OFFSET` are always engine-identical).
194
+ * Reports whether a whole {@link QueryInput} is exact — every condition and
195
+ * every order term is exact. `limit` / `offset` never affect exactness (SQL
196
+ * `LIMIT` / `OFFSET` are always engine-identical).
197
197
  *
198
198
  * @param input - The query input to test
199
199
  * @param schema - The table's schema
200
- * @returns Whether every part of `input` is exact
200
+ * @returns True if every part of `input` is exact; false otherwise
201
201
  */
202
202
  function matchesQueryExactly(input, schema) {
203
203
  const conditions = input.conditions ?? [];
@@ -205,25 +205,25 @@ function matchesQueryExactly(input, schema) {
205
205
  return conditions.every((condition) => matchesConditionExactly(condition, schema)) && order.every((term) => matchesOrderExactly(term, schema));
206
206
  }
207
207
  /**
208
- * Determine whether SQLite can execute an aggregate exactly like the core engine.
208
+ * Reports whether SQLite can execute an aggregate exactly like the core engine.
209
209
  *
210
210
  * @param operation - Aggregate operation
211
211
  * @param column - Aggregate field
212
212
  * @param schema - Current table schema
213
- * @returns Whether native aggregation is exact
213
+ * @returns True if native aggregation is exact; false otherwise
214
214
  */
215
215
  function matchesAggregateExactly(operation, column, schema) {
216
216
  if (operation === "count") return true;
217
217
  if (operation === "sum" || operation === "average" || !isString(column)) return false;
218
- const declared = schema.columns.find((candidate) => candidate.name === column);
218
+ const declared = findColumn(column, schema);
219
219
  return declared !== void 0 && (declared.storage === "integer" || declared.storage === "real") && !(declared.optional && declared.nullable);
220
220
  }
221
221
  /**
222
- * Test a declared SQLite type against a portable storage affinity.
222
+ * Checks a declared SQLite type against a portable storage affinity.
223
223
  *
224
224
  * @param declared - Native declared type
225
225
  * @param storage - Portable column storage
226
- * @returns Whether SQLite's official affinity rules yield the expected affinity
226
+ * @returns True if SQLite's official affinity rules yield the expected affinity; false otherwise
227
227
  */
228
228
  function matchesSQLiteAffinity(declared, storage) {
229
229
  if (!isString(declared)) return false;
@@ -240,7 +240,7 @@ function matchesSQLiteAffinity(declared, storage) {
240
240
  return affinity === "REAL";
241
241
  }
242
242
  /**
243
- * Quote a SQL identifier (a table or column name) so any characters are literal.
243
+ * Quotes a SQL identifier (a table or column name) so any characters are literal.
244
244
  *
245
245
  * @remarks
246
246
  * Wraps the name in double quotes and doubles any embedded quote — the standard
@@ -259,7 +259,7 @@ function quoteIdentifier(identifier) {
259
259
  return "\"" + identifier.replaceAll("\"", "\"\"") + "\"";
260
260
  }
261
261
  /**
262
- * Encode a JS value to its stored {@link SQLiteValue} for a declared column.
262
+ * Encodes a JS value to its stored {@link SQLiteValue} for a declared column.
263
263
  *
264
264
  * @remarks
265
265
  * The codec is total: a malformed value encodes to SQL `NULL`. Absence always
@@ -298,7 +298,7 @@ function encodeValue(value, column) {
298
298
  }
299
299
  }
300
300
  /**
301
- * Decode a stored {@link SQLiteValue} back to its JS value for a declared column —
301
+ * Decodes a stored {@link SQLiteValue} back to its JS value for a declared column —
302
302
  * the exact inverse of {@link encodeValue}.
303
303
  *
304
304
  * @remarks
@@ -339,7 +339,7 @@ function decodeValue(value, column) {
339
339
  }
340
340
  }
341
341
  /**
342
- * Encode a whole {@link Row} to a {@link SQLiteRow} by its table's schema.
342
+ * Encodes a whole {@link Row} to a {@link SQLiteRow} by its table's schema.
343
343
  *
344
344
  * @remarks
345
345
  * Encodes each declared column's value with {@link encodeValue}; columns the row
@@ -361,7 +361,7 @@ function encodeRow(row, schema) {
361
361
  return result;
362
362
  }
363
363
  /**
364
- * Extract a stored row's values in a declared positional order.
364
+ * Extracts a stored row's values in a declared positional order.
365
365
  *
366
366
  * @remarks
367
367
  * SQLite statements bind arrays positionally. Every requested column must be
@@ -392,7 +392,7 @@ function extractValues(row, names, table) {
392
392
  return values;
393
393
  }
394
394
  /**
395
- * Decode a stored {@link SQLiteRow} back to a {@link Row} by its table's schema.
395
+ * Decodes a stored {@link SQLiteRow} back to a {@link Row} by its table's schema.
396
396
  *
397
397
  * @remarks
398
398
  * Decodes each declared column with {@link decodeValue} and **omits** any column
@@ -421,7 +421,7 @@ function decodeRow(row, schema) {
421
421
  return result;
422
422
  }
423
423
  /**
424
- * Build a collision-free SQL index name for a table + column-group index —
424
+ * Builds a collision-free SQL index name for a table + column-group index —
425
425
  * shared by the compiler module's `schemaToIndexes` and `stepToSQL`,
426
426
  * so a plan-built index name always matches one `open` would have created.
427
427
  *
@@ -447,9 +447,39 @@ function deriveSQLiteIndexName(table, columns) {
447
447
  return "idx_" + [table, ...columns].map((part) => String(part.length) + "_" + part).join("_");
448
448
  }
449
449
  //#endregion
450
+ //#region src/server/inferers.ts
451
+ /**
452
+ * Reads the storage type a nested (`json_extract`) operand encodes as from its
453
+ * RUNTIME value — NOT `json`.
454
+ *
455
+ * @remarks
456
+ * `json_extract` returns the unquoted, natively-typed scalar (a JSON boolean as
457
+ * `1` / `0`, a number as-is, a string as-is), so the operand must encode to that
458
+ * same scalar to compare. A boolean → `'boolean'` (→ `1` / `0`); a number →
459
+ * `'integer'` / `'real'`; a bigint → `'integer'`; a string → `'text'`; `null` /
460
+ * `undefined` → `'text'` (encodes to `null`); an object / array → `'json'` (the
461
+ * edge of comparing against a json subtree).
462
+ *
463
+ * @param value - The runtime operand value
464
+ * @returns The {@link ColumnStorage} to encode it as
465
+ *
466
+ * @example
467
+ * ```ts
468
+ * inferValueStorage(true) // 'boolean'
469
+ * inferValueStorage(9) // 'integer'
470
+ * ```
471
+ */
472
+ function inferValueStorage(value) {
473
+ if (typeof value === "boolean") return "boolean";
474
+ if (typeof value === "number") return Number.isInteger(value) ? "integer" : "real";
475
+ if (typeof value === "bigint") return "integer";
476
+ if (typeof value === "object" && value !== null) return "json";
477
+ return "text";
478
+ }
479
+ //#endregion
450
480
  //#region src/server/compilers.ts
451
481
  /**
452
- * Map a portable {@link ColumnStorage} to its SQLite column type.
482
+ * Maps a portable {@link ColumnStorage} to its SQLite column type.
453
483
  *
454
484
  * @param storage - The portable column type
455
485
  * @returns The SQLite column type keyword
@@ -465,7 +495,7 @@ function compileColumnSQL(storage) {
465
495
  }
466
496
  }
467
497
  /**
468
- * Compile a {@link FieldPath} to the SQL expression that reads it.
498
+ * Compiles a {@link FieldPath} to the SQL expression that reads it.
469
499
  *
470
500
  * @param path - The field path
471
501
  * @returns The SQL expression selecting the value
@@ -478,7 +508,7 @@ function compileFieldSQL(path) {
478
508
  return "json_extract(" + quoteIdentifier(column) + ", '$" + rest + "')";
479
509
  }
480
510
  /**
481
- * Compile an {@link AggregateOperation} over a {@link FieldPath}.
511
+ * Compiles an {@link AggregateOperation} over a {@link FieldPath}.
482
512
  *
483
513
  * @param operation - The aggregate to compute
484
514
  * @param column - The column or nested path to aggregate
@@ -494,7 +524,7 @@ function compileAggregateSQL(operation, column) {
494
524
  }
495
525
  }
496
526
  /**
497
- * Compile a NESTED {@link FieldPath} to the `json_type(<col>, <path>)` SQL
527
+ * Compiles a NESTED {@link FieldPath} to the `json_type(<col>, <path>)` SQL
498
528
  * expression — the {@link compileFieldSQL} `json_extract` sibling used to tell a
499
529
  * PRESENT JSON `null` apart from an ABSENT path (both read back as SQL `NULL`
500
530
  * through `json_extract`, but `json_type` reports `'null'` for the former and
@@ -515,65 +545,7 @@ function compileJSONTypeSQL(path) {
515
545
  return "json_type(" + quoteIdentifier(column) + ", '$" + rest + "')";
516
546
  }
517
547
  /**
518
- * Escape `\`, `%`, and `_` (each with a leading `\`) so a `starts` / `ends`
519
- * operand is matched literally under the `LIKE … ESCAPE '\'` clause.
520
- *
521
- * @param text - The raw operand text
522
- * @returns The text with LIKE metacharacters escaped
523
- *
524
- * @example
525
- * ```ts
526
- * escapeLike('50%_off') // '50\\%\\_off'
527
- * ```
528
- */
529
- function escapeLike(text) {
530
- return text.replaceAll("\\", "\\\\").replaceAll("%", "\\%").replaceAll("_", "\\_");
531
- }
532
- /**
533
- * The declared storage type of a flat (string) column, read from the schema.
534
- *
535
- * @param column - The column name
536
- * @param schema - The table's schema
537
- * @returns The column's {@link ColumnStorage}, or `undefined` if the schema does not carry it
538
- *
539
- * @example
540
- * ```ts
541
- * findColumnStorage('age', schema) // 'integer'
542
- * ```
543
- */
544
- function findColumnStorage(column, schema) {
545
- return schema.columns.find((candidate) => candidate.name === column)?.storage;
546
- }
547
- /**
548
- * The storage type a nested (`json_extract`) operand encodes as, derived from its
549
- * RUNTIME value — NOT `json`.
550
- *
551
- * @remarks
552
- * `json_extract` returns the unquoted, natively-typed scalar (a JSON boolean as
553
- * `1` / `0`, a number as-is, a string as-is), so the operand must encode to that
554
- * same scalar to compare. A boolean → `'boolean'` (→ `1` / `0`); a number →
555
- * `'integer'` / `'real'`; a bigint → `'integer'`; a string → `'text'`; `null` /
556
- * `undefined` → `'text'` (encodes to `null`); an object / array → `'json'` (the
557
- * edge of comparing against a json subtree).
558
- *
559
- * @param value - The runtime operand value
560
- * @returns The {@link ColumnStorage} to encode it as
561
- *
562
- * @example
563
- * ```ts
564
- * inferValueStorage(true) // 'boolean'
565
- * inferValueStorage(9) // 'integer'
566
- * ```
567
- */
568
- function inferValueStorage(value) {
569
- if (typeof value === "boolean") return "boolean";
570
- if (typeof value === "number") return Number.isInteger(value) ? "integer" : "real";
571
- if (typeof value === "bigint") return "integer";
572
- if (typeof value === "object" && value !== null) return "json";
573
- return "text";
574
- }
575
- /**
576
- * Compile one condition to its `<column> <operator>` SQL fragment and the parameters
548
+ * Compiles one condition to its `<column> <operator>` SQL fragment and the parameters
577
549
  * it binds — engine-exact under SQL's three-valued NULL logic.
578
550
  *
579
551
  * @remarks
@@ -644,7 +616,7 @@ function inferValueStorage(value) {
644
616
  function compileConditionSQL(condition, schema) {
645
617
  const column = compileFieldSQL(condition.column);
646
618
  const nested = !isString(condition.column);
647
- const declared = isString(condition.column) ? schema.columns.find((candidate) => candidate.name === condition.column) : void 0;
619
+ const declared = isString(condition.column) ? findColumn(condition.column, schema) : void 0;
648
620
  const first = condition.values[0];
649
621
  const second = condition.values[1];
650
622
  const nullOperand = first === null || first === void 0;
@@ -763,7 +735,7 @@ function compileConditionSQL(condition, schema) {
763
735
  };
764
736
  }
765
737
  /**
766
- * Fold the conditions into one WHERE clause, parenthesizing progressively
738
+ * Folds the conditions into one WHERE clause, parenthesizing progressively
767
739
  * left-to-right so the grouping matches the engine's `matchesQuery` fold.
768
740
  *
769
741
  * @remarks
@@ -779,11 +751,11 @@ function compileConditionSQL(condition, schema) {
779
751
  *
780
752
  * @example
781
753
  * ```ts
782
- * compileWhere([{ column: 'age', operator: 'from', values: [18], connector: 'and' }], schema)
754
+ * compileWhereSQL([{ column: 'age', operator: 'from', values: [18], connector: 'and' }], schema)
783
755
  * // { sql: 'WHERE "age" >= ?', parameters: [18] }
784
756
  * ```
785
757
  */
786
- function compileWhere(conditions, schema) {
758
+ function compileWhereSQL(conditions, schema) {
787
759
  const [first, ...remaining] = conditions;
788
760
  if (first === void 0) return {
789
761
  sql: "",
@@ -804,14 +776,14 @@ function compileWhere(conditions, schema) {
804
776
  };
805
777
  }
806
778
  /**
807
- * Compile the ORDER BY clause from the order terms, always ending with the
779
+ * Compiles the ORDER BY clause from the order terms, always ending with the
808
780
  * primary key as the final determinant.
809
781
  *
810
782
  * @remarks
811
783
  * The native `records` read then resolves ties in key order, matching a
812
784
  * primary-key-ordered `scan` and the core engine's stable `sortRows` over a
813
785
  * key-ordered scan (and IndexedDB's key-ordered reads), so a native read equals
814
- * the scan path (AGENTS §21 / §22 native ↔ engine parity). SQLite without an
786
+ * the scan path native ↔ engine parity. SQLite without an
815
787
  * `ORDER BY` returns rowid (insertion) order, and an explicit order alone breaks
816
788
  * ties by rowid too — both diverge from every key-ordered backend. The
817
789
  * tie-breaker is ASCENDING regardless of the explicit directions: the engine's
@@ -825,17 +797,17 @@ function compileWhere(conditions, schema) {
825
797
  *
826
798
  * @example
827
799
  * ```ts
828
- * compileOrder([{ column: 'age', direction: 'descending' }], schema)
800
+ * compileOrderSQL([{ column: 'age', direction: 'descending' }], schema)
829
801
  * // 'ORDER BY "age" DESC, "id"'
830
802
  * ```
831
803
  */
832
- function compileOrder(order, schema) {
804
+ function compileOrderSQL(order, schema) {
833
805
  const terms = (order ?? []).map((term) => compileFieldSQL(term.column) + (term.direction === "descending" ? " DESC" : " ASC"));
834
806
  if (!(order ?? []).some((term) => isString(term.column) && term.column === schema.primary)) terms.push(quoteIdentifier(schema.primary));
835
807
  return terms.length === 0 ? "" : "ORDER BY " + terms.join(", ");
836
808
  }
837
809
  /**
838
- * Compile the LIMIT / OFFSET clause.
810
+ * Compiles the LIMIT / OFFSET clause.
839
811
  *
840
812
  * @remarks
841
813
  * An offset without a limit uses `LIMIT -1` (SQLite's "no limit") so OFFSET is
@@ -847,10 +819,10 @@ function compileOrder(order, schema) {
847
819
  *
848
820
  * @example
849
821
  * ```ts
850
- * compilePage(undefined, 5) // { sql: 'LIMIT -1 OFFSET ?', parameters: [5] }
822
+ * compilePageSQL(undefined, 5) // { sql: 'LIMIT -1 OFFSET ?', parameters: [5] }
851
823
  * ```
852
824
  */
853
- function compilePage(limit, offset) {
825
+ function compilePageSQL(limit, offset) {
854
826
  validatePage({
855
827
  ...limit === void 0 ? {} : { limit },
856
828
  ...offset === void 0 ? {} : { offset }
@@ -873,7 +845,7 @@ function compilePage(limit, offset) {
873
845
  };
874
846
  }
875
847
  /**
876
- * Compile a {@link QueryInput} into the SQL clause that follows a table name, with
848
+ * Compiles a {@link QueryInput} into the SQL clause that follows a table name, with
877
849
  * its bound parameters in clause order.
878
850
  *
879
851
  * @remarks
@@ -883,11 +855,13 @@ function compilePage(limit, offset) {
883
855
  * over a JS `scan`. The WHERE fold is parenthesized **left-to-right** to mirror
884
856
  * the core engine's `matchesQuery` (not SQL's native AND-over-OR precedence),
885
857
  * so a native and an engine read return identical rows. Each operand is encoded
886
- * via `encodeValue`: a flat column uses its declared schema type, while a nested
858
+ * through `encodeValue`: a flat column uses its declared schema type, while a nested
887
859
  * `FieldPath` (a `json_extract` read) encodes each operand as the native scalar
888
860
  * the extract returns — derived from the operand's runtime type — so it compares.
889
- * The 15 operators map per the databases guide's operator table, with
890
- * `starts` / `ends` using `LIKE ESCAPE '\'` and an empty `any` / `none` list
861
+ * Every operator maps per the databases guide's operator table, with
862
+ * `starts` / `ends` compiling to a CODE-POINT `substr` slice guarded by
863
+ * `typeof(<column>) = 'text'` (case-sensitive, matching the engine's
864
+ * `String.prototype.startsWith` / `endsWith`) and an empty `any` / `none` list
891
865
  * collapsing to a constant. An `undefined` input (or one with no parts)
892
866
  * compiles to an empty clause.
893
867
  *
@@ -903,9 +877,9 @@ function compilePage(limit, offset) {
903
877
  */
904
878
  function compileQuerySQL(input, schema) {
905
879
  validatePage(input);
906
- const where = compileWhere(input?.conditions ?? [], schema);
907
- const orderBy = compileOrder(input?.order, schema);
908
- const page = compilePage(input?.limit, input?.offset);
880
+ const where = compileWhereSQL(input?.conditions ?? [], schema);
881
+ const orderBy = compileOrderSQL(input?.order, schema);
882
+ const page = compilePageSQL(input?.limit, input?.offset);
909
883
  return {
910
884
  sql: [
911
885
  where.sql,
@@ -916,7 +890,7 @@ function compileQuerySQL(input, schema) {
916
890
  };
917
891
  }
918
892
  /**
919
- * Project a {@link TableSchema} to its `CREATE TABLE IF NOT EXISTS` statement.
893
+ * Projects a {@link TableSchema} to its `CREATE TABLE IF NOT EXISTS` statement.
920
894
  *
921
895
  * @param schema - The table schema
922
896
  * @returns The complete table declaration
@@ -926,7 +900,7 @@ function schemaToTable(schema) {
926
900
  return "CREATE TABLE IF NOT EXISTS " + quoteIdentifier(schema.name) + " (" + columns.join(", ") + ", PRIMARY KEY (" + quoteIdentifier(schema.primary) + "))";
927
901
  }
928
902
  /**
929
- * Project a {@link TableSchema} to its declared SQLite indexes.
903
+ * Projects a {@link TableSchema} to its declared SQLite indexes.
930
904
  *
931
905
  * @param schema - The table schema
932
906
  * @returns One statement per declared index
@@ -935,7 +909,7 @@ function schemaToIndexes(schema) {
935
909
  return schema.indexes.map((group) => "CREATE INDEX IF NOT EXISTS " + quoteIdentifier(deriveSQLiteIndexName(schema.name, group)) + " ON " + quoteIdentifier(schema.name) + " (" + group.map(quoteIdentifier).join(", ") + ")");
936
910
  }
937
911
  /**
938
- * Project one {@link MigrationStep} to SQLite DDL.
912
+ * Projects one {@link MigrationStep} to SQLite DDL.
939
913
  *
940
914
  * @param step - The migration step
941
915
  * @returns The statements that apply the step
@@ -951,97 +925,9 @@ function stepToSQL(step) {
951
925
  }
952
926
  }
953
927
  //#endregion
954
- //#region src/core/DriverIterator.ts
955
- /**
956
- * The internal continuation boundary for a root driver async iterator.
957
- *
958
- * @remarks
959
- * A driver transaction can begin while a caller holds an idle root iterator.
960
- * Every `next` therefore checks the driver's root-state guard immediately
961
- * before and after advancing the source. A failed continuation terminalizes the
962
- * iterator, discards any row produced before the post-advance guard failed, and
963
- * attempts source cleanup exactly once.
964
- */
965
- var DriverIterator = class {
966
- #source;
967
- #guard;
968
- #terminal = false;
969
- #cleaned = false;
970
- constructor(source, guard) {
971
- this.#source = source;
972
- this.#guard = guard;
973
- }
974
- [Symbol.asyncIterator]() {
975
- return this;
976
- }
977
- async next() {
978
- if (this.#terminal) return {
979
- done: true,
980
- value: void 0
981
- };
982
- try {
983
- this.#guard();
984
- const result = await this.#source.next();
985
- this.#guard();
986
- if (result.done === true) {
987
- this.#terminal = true;
988
- this.#cleaned = true;
989
- }
990
- return result;
991
- } catch (error) {
992
- this.#terminal = true;
993
- await this.#discard();
994
- throw error;
995
- }
996
- }
997
- async return() {
998
- if (this.#terminal) return {
999
- done: true,
1000
- value: void 0
1001
- };
1002
- this.#terminal = true;
1003
- if (this.#cleaned || this.#source.return === void 0) {
1004
- this.#cleaned = true;
1005
- return {
1006
- done: true,
1007
- value: void 0
1008
- };
1009
- }
1010
- this.#cleaned = true;
1011
- return this.#source.return();
1012
- }
1013
- async throw(error) {
1014
- if (this.#terminal) throw error;
1015
- if (this.#source.throw === void 0) {
1016
- this.#terminal = true;
1017
- await this.#discard();
1018
- throw error;
1019
- }
1020
- try {
1021
- const result = await this.#source.throw(error);
1022
- if (result.done === true) {
1023
- this.#terminal = true;
1024
- this.#cleaned = true;
1025
- }
1026
- return result;
1027
- } catch (cause) {
1028
- this.#terminal = true;
1029
- await this.#discard();
1030
- throw cause;
1031
- }
1032
- }
1033
- async #discard() {
1034
- if (this.#cleaned) return;
1035
- this.#cleaned = true;
1036
- try {
1037
- await this.#source.return?.();
1038
- } catch {}
1039
- }
1040
- };
1041
- //#endregion
1042
928
  //#region src/server/drivers/JSONDriver.ts
1043
929
  /**
1044
- * A persistent {@link DriverInterface} backed by a single JSON file — the
930
+ * Implements a persistent {@link DriverInterface} backed by a single JSON file — the
1045
931
  * reference {@link MemoryDriver} plus file load / flush.
1046
932
  *
1047
933
  * @remarks
@@ -1055,15 +941,15 @@ var DriverIterator = class {
1055
941
  * primary (the table contract), so the key is recovered on load with
1056
942
  * {@link extractKey} and the file need not store it. The parsed JSON crosses the
1057
943
  * boundary as `unknown` and is narrowed with {@link isRecord} / {@link extractKey},
1058
- * never asserted (AGENTS §14). A read that reports no document there starts empty —
944
+ * never asserted. A read that reports no document there starts empty —
1059
945
  * `ENOENT` for a plain absence, and `ENOTDIR` for a path whose parent is not a
1060
946
  * directory, which no later write could find either; every other read failure or
1061
947
  * invalid existing document fails closed without publication, mutation, or
1062
- * automatic repair. It is scan-only it implements none of
1063
- * the optional native `records` / `aggregate` hooks, so the core engine
1064
- * over `scan` answers every query. For development, small datasets, and portable /
1065
- * inspectable data; for large or concurrent workloads reach for a SQLite-backed
1066
- * driver.
948
+ * automatic repair. It implements the optional native `stream` hook that
949
+ * `TableInterface.scan` prefers over `scan`, and neither `records` nor
950
+ * `aggregate`, so the core engine's `matchesQuery` answers every query on
951
+ * either path. For development, small datasets, and portable / inspectable
952
+ * data; for large or concurrent workloads reach for a SQLite-backed driver.
1067
953
  *
1068
954
  * Metadata crosses {@link cloneDriverMetadata} at parsed-file ingress, public and
1069
955
  * scoped write ingress, candidate/root publication, serialization, and copy-out.
@@ -1127,7 +1013,7 @@ var JSONDriver = class {
1127
1013
  return new DriverIterator(this.#scan(table)[Symbol.asyncIterator](), () => this.#root());
1128
1014
  }
1129
1015
  /**
1130
- * Natively filtered lazy iteration — delegates to the inner {@link MemoryDriver}.
1016
+ * Iterates rows lazily with native filtering — delegates to the inner {@link MemoryDriver}.
1131
1017
  *
1132
1018
  * @remarks
1133
1019
  * Semantics are the memory driver's own: `input.conditions` filters, `offset`
@@ -1146,7 +1032,7 @@ var JSONDriver = class {
1146
1032
  await this.#enqueue(() => this.#clear(table));
1147
1033
  }
1148
1034
  /**
1149
- * Run an isolated native transaction callback over a candidate memory store.
1035
+ * Runs an isolated native transaction callback over a candidate memory store.
1150
1036
  *
1151
1037
  * @remarks
1152
1038
  * Single-writer: nesting and root operations while active throw `CONFLICT`.
@@ -1163,7 +1049,7 @@ var JSONDriver = class {
1163
1049
  return this.#enqueue(() => this.#transact(scope));
1164
1050
  }
1165
1051
  /**
1166
- * Capture an owned row snapshot at an exact writer-queue position.
1052
+ * Captures an owned row snapshot at an exact writer-queue position.
1167
1053
  *
1168
1054
  * @remarks
1169
1055
  * Capture owns table names, schemas, rows, and one session-local identity per
@@ -1191,7 +1077,7 @@ var JSONDriver = class {
1191
1077
  return this.#metadata === void 0 ? void 0 : cloneDriverMetadata(this.#metadata);
1192
1078
  }
1193
1079
  /**
1194
- * Persist an owned metadata snapshot for a later `metadata()` to copy out.
1080
+ * Persists an owned metadata snapshot for a later `metadata()` to copy out.
1195
1081
  *
1196
1082
  * @remarks
1197
1083
  * Root stamping conflicts while a transaction is active. The scoped
@@ -1206,7 +1092,7 @@ var JSONDriver = class {
1206
1092
  await this.#enqueue(() => this.#stamp(owned));
1207
1093
  }
1208
1094
  /**
1209
- * Apply one atomic {@link MigrationInput} through an isolated candidate.
1095
+ * Applies one atomic {@link MigrationInput} through an isolated candidate.
1210
1096
  *
1211
1097
  * @remarks
1212
1098
  * The candidate receives every plan step plus optional metadata. Its complete
@@ -1420,7 +1306,8 @@ var JSONDriver = class {
1420
1306
  return this.#requireCandidate(token).keys(table);
1421
1307
  }
1422
1308
  #scanCandidate(token, table) {
1423
- return new DriverIterator(this.#requireCandidate(token).scan(table)[Symbol.asyncIterator](), () => {
1309
+ const source = this.#requireCandidate(token).scan(table);
1310
+ return new DriverIterator(source[Symbol.asyncIterator](), () => {
1424
1311
  this.#requireCandidate(token);
1425
1312
  });
1426
1313
  }
@@ -1667,8 +1554,8 @@ var JSONDriver = class {
1667
1554
  //#endregion
1668
1555
  //#region src/server/drivers/SQLiteDriver.ts
1669
1556
  /**
1670
- * The SQLite {@link DriverInterface} — the server-native, trusted-mode backend
1671
- * built on the published `@orkestrel/sqlite` synchronous wrapper.
1557
+ * Implements the {@link DriverInterface} over SQLite — the server-native, trusted-mode
1558
+ * backend built on the published `@orkestrel/sqlite` synchronous wrapper.
1672
1559
  *
1673
1560
  * @remarks
1674
1561
  * A thin adapter: it implements the storage primitives the core database layer
@@ -1679,41 +1566,40 @@ var JSONDriver = class {
1679
1566
  * reopen-safe), and readies a reserved `_metadata` single-row table `metadata()` /
1680
1567
  * `stamp()` read and write — **a user table named `_metadata` collides with it**;
1681
1568
  * avoid the name. Rows cross the boundary through the codecs in `helpers.ts`
1682
- * (`json` columns store / parse JSON text, a `boolean` stores `1` / `0`), so the
1683
- * typed layer above imposes the exact shape (AGENTS §14). `write` is an
1569
+ * (`json` columns store / parse JSON text, a `boolean` stores `1` / `0`), so
1570
+ * the typed layer above imposes the exact shape. `write` is an
1684
1571
  * `INSERT OR REPLACE` upsert, while `insert` uses a plain `INSERT` and maps its
1685
1572
  * atomic primary-key constraint failure to `CONFLICT`; every other backend
1686
1573
  * `SQLiteError` is contained by the same `DatabaseError` boundary described
1687
- * below. Querying, ordering, paging, and
1688
- * aggregation is native: `records` / `stream` compile a `QueryInput`
1689
- * to SQL with `compileQuerySQL`, and `aggregate` runs a SQL
1690
- * `COUNT`/`SUM`/`AVG`/`MIN`/`MAX` (via `compileAggregateSQL`) over the same compiled
1691
- * WHERE. `transaction` runs a callback inside native `BEGIN` / `COMMIT` /
1692
- * `ROLLBACK`, passing a scoped storage capability that becomes invalid after
1693
- * settlement. `migrate` runs the plan's projected DDL
1694
- * ({@link import('../compilers.js').stepToSQL}) inside whichever native
1695
- * transaction is active: joined into the active transaction callback
1696
- * when one exists (the core's versioned reconcile path wraps migrate + stamp
1697
- * in one native `BEGIN`, and node:sqlite rejects a nested `BEGIN`), or inside
1698
- * its own `database.transaction` otherwise a mid-plan failure rolls back
1699
- * atomically either way, an improvement over the non-atomic `MemoryDriver` /
1700
- * `JSONDriver` migrate; a step referencing an undeclared table throws
1574
+ * below. Querying, ordering, paging, and aggregation is native: `records` /
1575
+ * `stream` compile a `QueryInput` to SQL with `compileQuerySQL`, and
1576
+ * `aggregate` runs a SQL `COUNT`/`SUM`/`AVG`/`MIN`/`MAX` (through
1577
+ * `compileAggregateSQL`) over the same compiled WHERE. `transaction` runs a
1578
+ * callback inside native `BEGIN` / `COMMIT` / `ROLLBACK`, passing a scoped
1579
+ * storage capability that becomes invalid after settlement. `migrate` runs the
1580
+ * plan's projected DDL ({@link import('../compilers.js').stepToSQL}) inside
1581
+ * whichever native transaction is active: joined into the active transaction
1582
+ * callback when one exists (the core's versioned reconcile path wraps migrate +
1583
+ * stamp in one native `BEGIN`, and node:sqlite rejects a nested `BEGIN`), or
1584
+ * inside its own `database.transact` otherwise a mid-plan failure rolls
1585
+ * back atomically either way, an improvement over the non-atomic `MemoryDriver`
1586
+ * / `JSONDriver` migrate; a step referencing an undeclared table throws
1701
1587
  * `DatabaseError` `MIGRATION` before any DDL for that step runs. `snapshot` is
1702
- * capture-replay (SELECT the
1703
- * named tables' rows, replay via DELETE + INSERT OR REPLACE inside a native
1704
- * transaction on rollback) rather than a SQL `SAVEPOINT`, since the core
1705
- * `transaction` calls the rollback thunk only on failure with no commit-on-
1706
- * success signal a long-lived `SAVEPOINT` would leave the connection
1707
- * uncommitted (lost on close). Every backend interaction runs through `#guard`,
1708
- * which maps a thrown backend `SQLiteError` (or any unexpected non-`SQLiteError`
1709
- * throw) to a typed {@link DatabaseError} never a raw backend error escapes
1710
- * `DriverInterface`: `CONSTRAINT` → `CONFLICT`, the wrapper's own `CLOSED`
1711
- * `CLOSED`, `BUSY` (a locked database that outlasted the configured `timeout`)
1712
- * → a retryable `DRIVER` (`context.retryable` is `true`), and `UNKNOWN` / any
1713
- * other throw `DRIVER`. The original error is preserved as `context.cause`.
1714
- * A `DatabaseError` this driver throws directly (`CLOSED` from the `#require`
1715
- * gate, `NOT_FOUND` from `#table`, `MIGRATION` from a migration-plan fault)
1716
- * passes through `#guard` unchanged, never re-wrapped.
1588
+ * capture-replay (SELECT the named tables' rows, replay through DELETE + INSERT OR
1589
+ * REPLACE inside a native transaction on rollback) rather than a SQL
1590
+ * `SAVEPOINT`, since the core `transaction` calls the rollback thunk only on
1591
+ * failure with no commit-on-success signal — a long-lived `SAVEPOINT` would
1592
+ * leave the connection uncommitted (lost on close). Every backend interaction
1593
+ * runs through `#guard`, which maps a thrown backend `SQLiteError` (or any
1594
+ * unexpected non-`SQLiteError` throw) to a typed {@link DatabaseError} never
1595
+ * a raw backend error escapes `DriverInterface`: `CONSTRAINT` `CONFLICT`, the
1596
+ * wrapper's own `CLOSED` → `CLOSED`, `BUSY` (a locked database that outlasted
1597
+ * the configured `timeout`) a retryable `DRIVER` (`context.retryable` is
1598
+ * `true`), and `UNKNOWN` / any other throw → `DRIVER`. The original error is
1599
+ * preserved as `context.cause`. A `DatabaseError` this driver throws directly
1600
+ * (`CLOSED` from the `#require` gate, `NOT_FOUND` from `#table`, `MIGRATION`
1601
+ * from a migration-plan fault) passes through `#guard` unchanged, never
1602
+ * re-wrapped.
1717
1603
  */
1718
1604
  var SQLiteDriver = class {
1719
1605
  #path;
@@ -1750,7 +1636,7 @@ var SQLiteDriver = class {
1750
1636
  for (const [name, value] of Object.entries(this.#options.pragmas ?? {})) database.pragma(name, value);
1751
1637
  const map = /* @__PURE__ */ new Map();
1752
1638
  const identities = /* @__PURE__ */ new Map();
1753
- database.transaction(() => {
1639
+ database.transact(() => {
1754
1640
  this.#ensureMetadataTable(database);
1755
1641
  const stored = this.#readMetadata(database);
1756
1642
  const deployed = normalizeDriverSchema(stored?.schema ?? owned);
@@ -1768,11 +1654,11 @@ var SQLiteDriver = class {
1768
1654
  for (const table of deployed) {
1769
1655
  const absent = missing.get(table.name);
1770
1656
  if (absent === void 0) {
1771
- database.exec(schemaToTable(table));
1772
- for (const sql of schemaToIndexes(table)) database.exec(sql);
1657
+ database.execute(schemaToTable(table));
1658
+ for (const sql of schemaToIndexes(table)) database.execute(sql);
1773
1659
  } else for (const [index, group] of table.indexes.entries()) if (absent.includes(deriveSQLiteIndexName(table.name, group))) {
1774
1660
  const sql = schemaToIndexes(table)[index];
1775
- if (sql !== void 0) database.exec(sql);
1661
+ if (sql !== void 0) database.execute(sql);
1776
1662
  }
1777
1663
  identities.set(table.name, previousIdentities.get(table.name) ?? {});
1778
1664
  }
@@ -1844,7 +1730,7 @@ var SQLiteDriver = class {
1844
1730
  const conditionsExact = conditions.every((condition) => matchesConditionExactly(condition, schema));
1845
1731
  const columnExact = matchesAggregateExactly(operation, column, schema);
1846
1732
  if (conditionsExact && columnExact) return this.#guard(() => {
1847
- const { sql, parameters } = compileWhere(conditions, schema);
1733
+ const { sql, parameters } = compileWhereSQL(conditions, schema);
1848
1734
  const value = this.#require().prepare("SELECT " + compileAggregateSQL(operation, column) + " AS value FROM " + quoteIdentifier(table) + (sql === "" ? "" : " " + sql)).get(parameters)?.value;
1849
1735
  return value === null || value === void 0 ? void 0 : Number(value);
1850
1736
  });
@@ -1857,7 +1743,7 @@ var SQLiteDriver = class {
1857
1743
  return new DriverIterator(this.#stream(table, input)[Symbol.asyncIterator](), () => this.#root());
1858
1744
  }
1859
1745
  /**
1860
- * Begin a native transaction — real `BEGIN`, `COMMIT`, `ROLLBACK`.
1746
+ * Begins a native transaction — real `BEGIN`, `COMMIT`, `ROLLBACK`.
1861
1747
  *
1862
1748
  * @remarks
1863
1749
  * The callback receives a scoped {@link StorageInterface}. Fulfillment
@@ -1904,23 +1790,22 @@ var SQLiteDriver = class {
1904
1790
  }
1905
1791
  }
1906
1792
  /**
1907
- * Apply a {@link Migration} plan by executing each step's projected DDL
1793
+ * Applies a {@link Migration} plan by executing each step's projected DDL
1908
1794
  * ({@link import('../compilers.js').stepToSQL}).
1909
1795
  *
1910
1796
  * @remarks
1911
- * Atomicity is provided by whichever native transaction is active: when
1912
- * this driver's own `transaction()` callback is active (the
1913
- * core's versioned reconcile / migrate path joins migrate + stamp under
1914
- * one native `BEGIN`), the plan's DDL runs directly inside that enclosing
1915
- * transaction — a mid-plan failure rejects the callback and the driver
1916
- * rolls it back. node:sqlite (and SQLite
1917
- * generally) rejects a nested `BEGIN`, so this driver must never open a
1797
+ * Atomicity is provided by whichever native transaction is active: when this
1798
+ * driver's own `transaction()` callback is active (the core's versioned
1799
+ * reconcile / migrate path joins migrate + stamp under one native `BEGIN`),
1800
+ * the plan's DDL runs directly inside that enclosing transaction — a mid-plan
1801
+ * failure rejects the callback and the driver rolls it back. node:sqlite (and
1802
+ * SQLite generally) rejects a nested `BEGIN`, so this driver must never open a
1918
1803
  * second native transaction while one is already open. Otherwise (no
1919
1804
  * enclosing transaction), `migrate` wraps the plan in its own native
1920
1805
  * `database.transaction` — atomic on its own: a mid-plan failure rolls
1921
1806
  * back every DDL statement already applied by the plan. A scoped migration
1922
1807
  * uses one fixed internal savepoint literal because the published SQLite
1923
- * wrapper intentionally exposes raw `exec` but no savepoint manager. That
1808
+ * wrapper intentionally exposes raw `execute` but no savepoint manager. That
1924
1809
  * savepoint contains a caught inner migration so the outer callback
1925
1810
  * transaction remains active and may continue safely. A step referencing a
1926
1811
  * table not in this driver's declared schema (and that is not itself a
@@ -1940,7 +1825,7 @@ var SQLiteDriver = class {
1940
1825
  metadata: owned.metadata.schema
1941
1826
  });
1942
1827
  this.#guard(() => {
1943
- database.transaction(() => {
1828
+ database.transact(() => {
1944
1829
  this.#applyPlan(database, owned);
1945
1830
  if (owned.metadata !== void 0) this.#writeMetadata(database, owned.metadata);
1946
1831
  });
@@ -1949,7 +1834,7 @@ var SQLiteDriver = class {
1949
1834
  this.#identities = identities;
1950
1835
  }
1951
1836
  /**
1952
- * Read the persisted {@link DriverMetadata} from the reserved `_metadata` table.
1837
+ * Reads the persisted {@link DriverMetadata} from the reserved `_metadata` table.
1953
1838
  *
1954
1839
  * @returns The last-stamped `DriverMetadata`, or `undefined` when never stamped
1955
1840
  * (or the stored row is malformed)
@@ -1959,7 +1844,7 @@ var SQLiteDriver = class {
1959
1844
  return this.#metadata();
1960
1845
  }
1961
1846
  /**
1962
- * Persist an owned metadata snapshot into the reserved `_metadata` table's
1847
+ * Persists an owned metadata snapshot into the reserved `_metadata` table's
1963
1848
  * single row.
1964
1849
  *
1965
1850
  * @param metadata - The {@link DriverMetadata} to persist
@@ -2014,11 +1899,11 @@ var SQLiteDriver = class {
2014
1899
  }
2015
1900
  this.#guard(() => {
2016
1901
  const current = this.#require();
2017
- current.transaction(() => {
1902
+ current.transact(() => {
2018
1903
  for (const [name, replacement] of replacements) {
2019
- current.exec("DELETE FROM " + quoteIdentifier(name));
1904
+ current.execute("DELETE FROM " + quoteIdentifier(name));
2020
1905
  const statement = current.prepare("INSERT OR REPLACE INTO " + quoteIdentifier(name) + " (" + replacement.names.map(quoteIdentifier).join(", ") + ") VALUES (" + replacement.names.map(() => "?").join(", ") + ")");
2021
- for (const values of replacement.values) statement.run(values);
1906
+ for (const values of replacement.values) statement.execute(values);
2022
1907
  }
2023
1908
  });
2024
1909
  });
@@ -2039,7 +1924,7 @@ var SQLiteDriver = class {
2039
1924
  const values = extractValues(encoded, names, table);
2040
1925
  const statement = this.#require().prepare("INSERT OR REPLACE INTO " + quoteIdentifier(table) + " (" + names.map(quoteIdentifier).join(", ") + ") VALUES (" + names.map(() => "?").join(", ") + ")");
2041
1926
  checkAbort(options?.signal);
2042
- statement.run(values);
1927
+ statement.execute(values);
2043
1928
  });
2044
1929
  }
2045
1930
  async #insert(table, key, row, options) {
@@ -2050,7 +1935,7 @@ var SQLiteDriver = class {
2050
1935
  const values = extractValues(encoded, names, table);
2051
1936
  const statement = this.#require().prepare("INSERT INTO " + quoteIdentifier(table) + " (" + names.map(quoteIdentifier).join(", ") + ") VALUES (" + names.map(() => "?").join(", ") + ")");
2052
1937
  checkAbort(options?.signal);
2053
- statement.run(values);
1938
+ statement.execute(values);
2054
1939
  });
2055
1940
  }
2056
1941
  async #delete(table, key, options) {
@@ -2058,7 +1943,7 @@ var SQLiteDriver = class {
2058
1943
  return this.#guard(() => {
2059
1944
  const statement = this.#require().prepare("DELETE FROM " + quoteIdentifier(table) + " WHERE " + quoteIdentifier(schema.primary) + " = ?");
2060
1945
  checkAbort(options?.signal);
2061
- return statement.run([this.#key(key, schema)]).changes > 0;
1946
+ return statement.execute([this.#key(key, schema)]).changes > 0;
2062
1947
  });
2063
1948
  }
2064
1949
  async #keys(table) {
@@ -2120,14 +2005,14 @@ var SQLiteDriver = class {
2120
2005
  async #clear(table) {
2121
2006
  this.#table(table);
2122
2007
  this.#guard(() => {
2123
- this.#require().prepare("DELETE FROM " + quoteIdentifier(table)).run();
2008
+ this.#require().prepare("DELETE FROM " + quoteIdentifier(table)).execute();
2124
2009
  });
2125
2010
  }
2126
2011
  async #metadata() {
2127
2012
  return this.#guard(() => this.#readMetadata(this.#require()));
2128
2013
  }
2129
2014
  #ensureMetadataTable(database) {
2130
- database.exec("CREATE TABLE IF NOT EXISTS " + quoteIdentifier(METADATA_TABLE) + " (\"id\" INTEGER, \"version\" INTEGER, \"schema\" TEXT, PRIMARY KEY (\"id\"))");
2015
+ database.execute("CREATE TABLE IF NOT EXISTS " + quoteIdentifier(METADATA_TABLE) + " (\"id\" INTEGER, \"version\" INTEGER, \"schema\" TEXT, PRIMARY KEY (\"id\"))");
2131
2016
  }
2132
2017
  #validateTable(database, schema) {
2133
2018
  const object = database.prepare("SELECT \"type\" AS \"category\" FROM \"sqlite_schema\" WHERE \"name\" = ?").get([schema.name]);
@@ -2262,7 +2147,7 @@ var SQLiteDriver = class {
2262
2147
  this.#guard(() => this.#writeMetadata(database, owned));
2263
2148
  }
2264
2149
  #writeMetadata(database, metadata) {
2265
- database.prepare("INSERT OR REPLACE INTO " + quoteIdentifier(METADATA_TABLE) + " (\"id\", \"version\", \"schema\") VALUES (1, ?, ?)").run([metadata.version, JSON.stringify(metadata.schema)]);
2150
+ database.prepare("INSERT OR REPLACE INTO " + quoteIdentifier(METADATA_TABLE) + " (\"id\", \"version\", \"schema\") VALUES (1, ?, ?)").execute([metadata.version, JSON.stringify(metadata.schema)]);
2266
2151
  }
2267
2152
  #capability(token) {
2268
2153
  return {
@@ -2321,16 +2206,16 @@ var SQLiteDriver = class {
2321
2206
  metadata: owned.metadata.schema
2322
2207
  });
2323
2208
  this.#guard(() => {
2324
- database.exec("SAVEPOINT \"_orkestrel_migration\"");
2209
+ database.execute("SAVEPOINT \"_orkestrel_migration\"");
2325
2210
  try {
2326
2211
  this.#applyPlan(database, owned);
2327
2212
  if (owned.metadata !== void 0) this.#writeMetadata(database, owned.metadata);
2328
- database.exec("RELEASE SAVEPOINT \"_orkestrel_migration\"");
2213
+ database.execute("RELEASE SAVEPOINT \"_orkestrel_migration\"");
2329
2214
  } catch (error) {
2330
2215
  try {
2331
- database.exec("ROLLBACK TO SAVEPOINT \"_orkestrel_migration\"");
2216
+ database.execute("ROLLBACK TO SAVEPOINT \"_orkestrel_migration\"");
2332
2217
  } finally {
2333
- database.exec("RELEASE SAVEPOINT \"_orkestrel_migration\"");
2218
+ database.execute("RELEASE SAVEPOINT \"_orkestrel_migration\"");
2334
2219
  }
2335
2220
  throw error;
2336
2221
  }
@@ -2406,13 +2291,13 @@ var SQLiteDriver = class {
2406
2291
  });
2407
2292
  }
2408
2293
  #applyPlan(database, input) {
2409
- for (const step of input.plan.steps) for (const sql of stepToSQL(step)) database.exec(sql);
2294
+ for (const step of input.plan.steps) for (const sql of stepToSQL(step)) database.execute(sql);
2410
2295
  }
2411
2296
  };
2412
2297
  //#endregion
2413
2298
  //#region src/server/factories.ts
2414
2299
  /**
2415
- * Create a persistent JSON-file {@link DriverInterface} for the core database layer.
2300
+ * Creates a persistent JSON-file {@link DriverInterface} for the core database layer.
2416
2301
  *
2417
2302
  * @remarks
2418
2303
  * Pass it to `createDatabase` from `@orkestrel/database` to run the typed
@@ -2420,9 +2305,10 @@ var SQLiteDriver = class {
2420
2305
  * `Table` / `Query` API is unchanged; only where the bytes live changes.
2421
2306
  * The driver is the reference `MemoryDriver` plus JSON-file persistence: `open` loads
2422
2307
  * the file, every mutation flushes the whole store back, and querying runs through
2423
- * the core engine over `scan` (it is scan-only no native `records` / `count` /
2424
- * `aggregate`). A missing, corrupt, or wrong-shaped file starts empty rather than
2425
- * throwing.
2308
+ * the core engine's `matchesQuery`. The driver implements the native `stream`
2309
+ * hook and neither `records` nor `aggregate`, so the engine answers every query
2310
+ * on either path. A missing, corrupt, or wrong-shaped file starts empty rather
2311
+ * than throwing.
2426
2312
  *
2427
2313
  * @param path - The JSON file path data is loaded from and flushed to
2428
2314
  * @returns A {@link DriverInterface} backed by a JSON file
@@ -2444,7 +2330,7 @@ function createJSONDriver(path) {
2444
2330
  return new JSONDriver(path);
2445
2331
  }
2446
2332
  /**
2447
- * Create a trusted-mode SQLite {@link DriverInterface} for the core database layer.
2333
+ * Creates a trusted-mode SQLite {@link DriverInterface} for the core database layer.
2448
2334
  *
2449
2335
  * @remarks
2450
2336
  * Pass it to `createDatabase` from `@orkestrel/database` to run the typed
@@ -2483,6 +2369,6 @@ function createSQLiteDriver(options) {
2483
2369
  return new SQLiteDriver(options);
2484
2370
  }
2485
2371
  //#endregion
2486
- export { EXACT_COLUMN_STORAGE, EXACT_RANGE_COLUMN_STORAGE, JSONDriver, METADATA_TABLE, SQLiteDriver, compileAggregateSQL, compileColumnSQL, compileConditionSQL, compileFieldSQL, compileJSONTypeSQL, compileOrder, compilePage, compileQuerySQL, compileWhere, createJSONDriver, createSQLiteDriver, decodeRow, decodeValue, deriveSQLiteIndexName, encodeRow, encodeValue, escapeLike, extractValues, findColumnStorage, inferValueStorage, matchesAbsentPath, matchesAggregateExactly, matchesConditionExactly, matchesDeclaredStorage, matchesOrderExactly, matchesQueryExactly, matchesSQLiteAffinity, quoteIdentifier, schemaToIndexes, schemaToTable, stepToSQL };
2372
+ export { EXACT_COLUMN_STORAGE, EXACT_RANGE_COLUMN_STORAGE, JSONDriver, METADATA_TABLE, SQLiteDriver, compileAggregateSQL, compileColumnSQL, compileConditionSQL, compileFieldSQL, compileJSONTypeSQL, compileOrderSQL, compilePageSQL, compileQuerySQL, compileWhereSQL, createJSONDriver, createSQLiteDriver, decodeRow, decodeValue, deriveSQLiteIndexName, encodeRow, encodeValue, extractValues, inferValueStorage, matchesAbsentPath, matchesAggregateExactly, matchesConditionExactly, matchesDeclaredStorage, matchesOrderExactly, matchesQueryExactly, matchesSQLiteAffinity, quoteIdentifier, schemaToIndexes, schemaToTable, stepToSQL };
2487
2373
 
2488
2374
  //# sourceMappingURL=index.js.map