@bjornpagen/bumbledb 0.14.0 → 0.17.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 (108) hide show
  1. package/COOKBOOK.md +58 -62
  2. package/README.md +82 -56
  3. package/dist/capacity.d.ts +24 -136
  4. package/dist/capacity.d.ts.map +1 -1
  5. package/dist/capacity.js +18 -40
  6. package/dist/capacity.js.map +1 -1
  7. package/dist/closed.d.ts +0 -156
  8. package/dist/closed.d.ts.map +1 -1
  9. package/dist/closed.js +0 -104
  10. package/dist/closed.js.map +1 -1
  11. package/dist/db.d.ts +93 -290
  12. package/dist/db.d.ts.map +1 -1
  13. package/dist/db.js +713 -556
  14. package/dist/db.js.map +1 -1
  15. package/dist/face.d.ts +0 -133
  16. package/dist/face.d.ts.map +1 -1
  17. package/dist/face.js +0 -33
  18. package/dist/face.js.map +1 -1
  19. package/dist/fields.d.ts +1 -145
  20. package/dist/fields.d.ts.map +1 -1
  21. package/dist/fields.js +2 -91
  22. package/dist/fields.js.map +1 -1
  23. package/dist/index.d.ts +13 -23
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +11 -20
  26. package/dist/index.js.map +1 -1
  27. package/dist/law.d.ts +111 -93
  28. package/dist/law.d.ts.map +1 -1
  29. package/dist/law.js +23 -27
  30. package/dist/law.js.map +1 -1
  31. package/dist/lower.d.ts +9 -35
  32. package/dist/lower.d.ts.map +1 -1
  33. package/dist/lower.js +8 -53
  34. package/dist/lower.js.map +1 -1
  35. package/dist/marshal.d.ts +0 -65
  36. package/dist/marshal.d.ts.map +1 -1
  37. package/dist/marshal.js +0 -72
  38. package/dist/marshal.js.map +1 -1
  39. package/dist/native.d.ts +97 -390
  40. package/dist/native.d.ts.map +1 -1
  41. package/dist/native.js +39 -61
  42. package/dist/native.js.map +1 -1
  43. package/dist/query/atom.d.ts +10 -276
  44. package/dist/query/atom.d.ts.map +1 -1
  45. package/dist/query/atom.js +1 -96
  46. package/dist/query/atom.js.map +1 -1
  47. package/dist/query/find.d.ts +10 -76
  48. package/dist/query/find.d.ts.map +1 -1
  49. package/dist/query/find.js +0 -30
  50. package/dist/query/find.js.map +1 -1
  51. package/dist/query/lower.d.ts +64 -146
  52. package/dist/query/lower.d.ts.map +1 -1
  53. package/dist/query/lower.js +19 -256
  54. package/dist/query/lower.js.map +1 -1
  55. package/dist/query/parse-ir.d.ts +0 -7
  56. package/dist/query/parse-ir.d.ts.map +1 -1
  57. package/dist/query/parse-ir.js +1 -13
  58. package/dist/query/parse-ir.js.map +1 -1
  59. package/dist/query/run.d.ts +0 -36
  60. package/dist/query/run.d.ts.map +1 -1
  61. package/dist/query/run.js +0 -44
  62. package/dist/query/run.js.map +1 -1
  63. package/dist/query/scope.d.ts +24 -180
  64. package/dist/query/scope.d.ts.map +1 -1
  65. package/dist/query/scope.js +2 -66
  66. package/dist/query/scope.js.map +1 -1
  67. package/dist/relation.d.ts +2 -50
  68. package/dist/relation.d.ts.map +1 -1
  69. package/dist/relation.js +2 -37
  70. package/dist/relation.js.map +1 -1
  71. package/dist/schema.d.ts +13 -63
  72. package/dist/schema.d.ts.map +1 -1
  73. package/dist/schema.js +118 -92
  74. package/dist/schema.js.map +1 -1
  75. package/dist/spec.d.ts +1 -140
  76. package/dist/spec.d.ts.map +1 -1
  77. package/dist/spec.js +1 -68
  78. package/dist/spec.js.map +1 -1
  79. package/dist/statements.d.ts +6 -137
  80. package/dist/statements.d.ts.map +1 -1
  81. package/dist/statements.js +16 -119
  82. package/dist/statements.js.map +1 -1
  83. package/package.json +3 -3
  84. package/src/capacity.ts +26 -140
  85. package/src/closed.ts +5 -206
  86. package/src/db.ts +997 -854
  87. package/src/face.ts +0 -142
  88. package/src/fields.ts +4 -172
  89. package/src/index.ts +32 -35
  90. package/src/law.ts +201 -129
  91. package/src/lower.ts +8 -53
  92. package/src/marshal.ts +1 -85
  93. package/src/native.ts +192 -413
  94. package/src/query/atom.ts +26 -313
  95. package/src/query/find.ts +24 -110
  96. package/src/query/lower.ts +132 -377
  97. package/src/query/parse-ir.ts +1 -14
  98. package/src/query/run.ts +0 -45
  99. package/src/query/scope.ts +25 -186
  100. package/src/relation.ts +2 -66
  101. package/src/schema.ts +143 -122
  102. package/src/spec.ts +1 -160
  103. package/src/statements.ts +22 -174
  104. package/dist/exhume.d.ts +0 -143
  105. package/dist/exhume.d.ts.map +0 -1
  106. package/dist/exhume.js +0 -166
  107. package/dist/exhume.js.map +0 -1
  108. package/src/exhume.ts +0 -267
package/dist/native.d.ts CHANGED
@@ -1,63 +1,30 @@
1
1
  import type { SchemaSpec, ValueSpec, ValueTypeSpec } from "./spec.js";
2
- /**
3
- * The complete typed surface of the bumbledb-node napi bridge. ALL FFI
4
- * typing lives in this one file — no other module may know the `.node`
5
- * artifact exists. The bridge is a dumb bridge (PRD-04): descriptor in as
6
- * data, queries in as IR data, facts in/out as value rows, rejections out as
7
- * structured violation sets; anything smart lives in the SDK or the engine.
8
- *
9
- * Marshaling law: fact rows cross as NATURAL JS values, schema-directed by
10
- * the engine descriptor (`boolean ⇄ bool`, `bigint ⇄ u64/i64`,
11
- * `string ⇄ str`, `Uint8Array ⇄ bytes<N>`, `{ start, end }` ⇄ interval);
12
- * IR, spec, and query params cross as TAGGED plain objects mirroring the
13
- * engine's own data enums 1:1. Every u64/i64 crosses as `bigint`, never
14
- * `number`. Domain outcomes (schema errors, fingerprint mismatches,
15
- * rejections, generation moves, IR errors) are DATA; marshaling/shape
16
- * violations and use-after-close THROW.
17
- */
18
2
  /** The opaque database handle (owns the LMDB environment + exclusive lock). */
19
3
  type DbHandle = {
20
4
  readonly __brand: "bumbledb.db";
21
5
  };
22
- /** One live MVCC read snapshot. */
23
- type SnapshotHandle = {
24
- readonly __brand: "bumbledb.snapshot";
6
+ type InstanceHandle = {
7
+ readonly __brand: "bumbledb.instance";
25
8
  };
26
- /**
27
- * One exhumed store — the read-only, theory-less open (engine 70-api.md
28
- * § exhume). Lifetimes are disposables (ruled 2026-07-23, R12):
29
- * `exhumeClose` is the deterministic teardown the SDK's `Symbol.dispose`
30
- * rides — releasing the environment (and the store's exclusive lock)
31
- * scope-shaped, never a GC race; the engine-side drop remains the
32
- * reclamation-only backstop for a collected-but-undisposed handle.
33
- */
34
- type ExhumeHandle = {
35
- readonly __brand: "bumbledb.exhume";
9
+ type WitnessHandle = {
10
+ readonly __brand: "bumbledb.witness";
11
+ };
12
+ type BuilderHandle = {
13
+ readonly __brand: "bumbledb.builder";
14
+ };
15
+ type OwnedHandle = {
16
+ readonly __brand: "bumbledb.owned";
36
17
  };
37
- /**
38
- * One live write transaction — the submitted delta with the engine's
39
- * final-state point-read view. Spent by `txCommit`/`txAbort`.
40
- */
41
18
  type TxHandle = {
42
19
  readonly __brand: "bumbledb.tx";
43
20
  };
44
- /** One prepared query (plan pinned at prepare). */
45
21
  type PreparedHandle = {
46
22
  readonly __brand: "bumbledb.prepared";
47
23
  };
48
- /**
49
- * Engine mutation report as it crosses napi: both counts are engine
50
- * values, never reconstructed from JS length.
51
- */
52
24
  interface WireMutationReport {
53
25
  readonly submitted: bigint;
54
26
  readonly changed: bigint;
55
27
  }
56
- /**
57
- * Engine fresh-id range as it crosses napi. Empty cannot yield a start —
58
- * `start` is a minted id only on the nonempty arm. (C wires empty as
59
- * `{ start: 0, end_exclusive: 0 }` at that boundary only.)
60
- */
61
28
  type WireFreshRange = {
62
29
  readonly empty: true;
63
30
  } | {
@@ -65,37 +32,16 @@ type WireFreshRange = {
65
32
  readonly start: bigint;
66
33
  readonly endExclusive: bigint;
67
34
  };
68
- /** A half-open interval `[start, end)` as it crosses the boundary. */
69
35
  interface IntervalValue {
70
36
  readonly start: bigint;
71
37
  readonly end: bigint;
72
38
  }
73
- /**
74
- * One fact-row cell as a natural JS value. The expected engine type comes
75
- * from the schema descriptor (marshaling is schema-directed, never guessed):
76
- * `boolean` for bool, `bigint` for u64/i64, `string` for str, `Uint8Array`
77
- * for bytes<N> (width-checked), `{ start, end }` for intervals.
78
- */
79
39
  type FactValue = boolean | bigint | string | Uint8Array | IntervalValue;
80
- /**
81
- * One tagged engine value — the 1:1 mirror of `bumbledb::Value` for the
82
- * positions no schema field directs (IR literals, query params).
83
- */
84
40
  type TaggedValue = ValueSpec;
85
- /**
86
- * One positional execution argument: a tagged scalar, or a param SET
87
- * (`Term.paramSet` positions) as `{ kind: "set", values }`.
88
- */
89
41
  type QueryParam = TaggedValue | {
90
42
  readonly kind: "set";
91
43
  readonly values: readonly TaggedValue[];
92
44
  };
93
- /**
94
- * The IR mirror (`bumbledb::ir`, 1:1): relations, fields, interiors, and
95
- * params by NUMERIC id — the SDK resolves names through the manifest and
96
- * sends ids; the bridge never sees names in queries. Q1 is a tagged sum:
97
- * CQ carries no rec; Reach carries `rec` by value.
98
- */
99
45
  type QueryIr = {
100
46
  readonly kind: "cq";
101
47
  readonly interiors: readonly InteriorIr[];
@@ -108,34 +54,28 @@ type QueryIr = {
108
54
  readonly head: readonly HeadTermIr[];
109
55
  readonly rules: readonly RuleIr[];
110
56
  };
111
- /** One named interior: the head shape its rules align against, and the rules. */
112
57
  interface InteriorIr {
113
58
  readonly head: readonly HeadTermIr[];
114
59
  readonly rules: readonly RuleIr[];
115
60
  }
116
- /** The linear rec on a Reach query: shared head, base arms, rec arms. */
117
61
  interface RecIr {
118
62
  readonly head: readonly HeadTermIr[];
119
63
  readonly base: readonly RuleIr[];
120
64
  readonly rec: readonly RuleIr[];
121
65
  }
122
- /** One head position: a plain variable slot or an aggregate-op kind. */
123
66
  type HeadTermIr = {
124
67
  readonly kind: "var";
125
68
  } | {
126
69
  readonly kind: "aggregate";
127
70
  readonly op: HeadOpIr;
128
71
  };
129
- /** The var-free aggregate-op kind at a head position. */
130
72
  type HeadOpIr = "sum" | "min" | "max" | "count" | "pack";
131
- /** One rule: conjunctive body, anti-join atoms, condition trees. */
132
73
  interface RuleIr {
133
74
  readonly finds: readonly FindTermIr[];
134
75
  readonly atoms: readonly AtomIr[];
135
76
  readonly negated: readonly AtomIr[];
136
77
  readonly conditions: readonly ConditionTreeIr[];
137
78
  }
138
- /** One find term (mirrors `ir::FindTerm`). Count is nullary; pack and folds carry `over`. */
139
79
  type FoldOpIr = {
140
80
  readonly kind: "sum";
141
81
  } | {
@@ -155,21 +95,11 @@ type FindTermIr = {
155
95
  } | {
156
96
  readonly kind: "pack";
157
97
  readonly over: number;
158
- } | {
159
- readonly kind: "measure";
160
- readonly var: number;
161
- } | {
162
- readonly kind: "aggregateMeasure";
163
- readonly op: FoldOpIr;
164
- readonly over: number;
165
98
  };
166
- /** Host brand: only {@link parseQueryIr} and `lowerQuery` inhabit this. Phantom — not a runtime key. */
167
99
  declare const parsedQueryBrand: unique symbol;
168
- /** A `QueryIr` that passed the host shape parse (rec/main nonempty, aggregate finds split). */
169
100
  type ParsedQuery = QueryIr & {
170
101
  readonly [parsedQueryBrand]: true;
171
102
  };
172
- /** One aggregate operator (mirrors `ir::AggOp`; Arg ops carry their key). */
173
103
  type AggOpIr = {
174
104
  readonly kind: "sum";
175
105
  } | {
@@ -181,7 +111,6 @@ type AggOpIr = {
181
111
  } | {
182
112
  readonly kind: "pack";
183
113
  };
184
- /** Where an atom draws its facts: a stored relation or a derived table. */
185
114
  type AtomSourceIr = {
186
115
  readonly kind: "edb";
187
116
  readonly relation: number;
@@ -189,15 +118,10 @@ type AtomSourceIr = {
189
118
  readonly kind: "interior";
190
119
  readonly interior: number;
191
120
  };
192
- /**
193
- * One atom: named-field bindings as `[fieldId, term]` pairs; absence of a
194
- * field is the wildcard.
195
- */
196
121
  interface AtomIr {
197
122
  readonly source: AtomSourceIr;
198
123
  readonly bindings: ReadonlyArray<readonly [number, TermIr]>;
199
124
  }
200
- /** One term of an atom binding or comparison (mirrors `ir::Term`). */
201
125
  type TermIr = {
202
126
  readonly kind: "var";
203
127
  readonly var: number;
@@ -210,11 +134,7 @@ type TermIr = {
210
134
  } | {
211
135
  readonly kind: "literal";
212
136
  readonly value: TaggedValue;
213
- } | {
214
- readonly kind: "measure";
215
- readonly var: number;
216
137
  };
217
- /** One comparison operator (mirrors `ir::CmpOp`). */
218
138
  type CmpOpIr = {
219
139
  readonly kind: "eq";
220
140
  } | {
@@ -233,16 +153,11 @@ type CmpOpIr = {
233
153
  } | {
234
154
  readonly kind: "pointIn";
235
155
  };
236
- /** One comparison condition. */
237
156
  interface ComparisonIr {
238
157
  readonly op: CmpOpIr;
239
158
  readonly lhs: TermIr;
240
159
  readonly rhs: TermIr;
241
160
  }
242
- /**
243
- * The input condition grammar: any boolean combination of comparisons
244
- * (validation distributes to DNF engine-side).
245
- */
246
161
  type ConditionTreeIr = {
247
162
  readonly kind: "leaf";
248
163
  readonly cmp: ComparisonIr;
@@ -253,18 +168,12 @@ type ConditionTreeIr = {
253
168
  readonly kind: "or";
254
169
  readonly children: readonly ConditionTreeIr[];
255
170
  };
256
- /** A statement's form tag. */
257
171
  type StatementKindTag = "functionality" | "containment" | "capacity";
258
- /** One field's name, dense id, and structural type. */
259
172
  interface ManifestField {
260
173
  readonly name: string;
261
174
  readonly id: number;
262
175
  readonly valueType: ValueTypeSpec;
263
176
  }
264
- /**
265
- * One closed-relation ground axiom as manifest data: handle →
266
- * declaration-order id → (column, value) pairs.
267
- */
268
177
  interface ManifestRow {
269
178
  readonly handle: string;
270
179
  readonly id: bigint;
@@ -273,31 +182,21 @@ interface ManifestRow {
273
182
  readonly value: FactValue;
274
183
  }>;
275
184
  }
276
- /**
277
- * One relation's names and ids; a closed relation's sealed field list opens
278
- * with the synthetic (`id`, u64) handle field and carries its extension.
279
- */
280
185
  interface ManifestRelation {
281
186
  readonly name: string;
282
187
  readonly id: number;
283
188
  readonly fields: readonly ManifestField[];
284
189
  readonly extension?: readonly ManifestRow[];
285
190
  }
286
- /** One statement's identity, form tag, and canonical spelling. */
287
191
  interface ManifestStatement {
288
192
  readonly id: number;
289
193
  readonly kind: StatementKindTag;
290
194
  readonly spelling: string;
291
195
  }
292
- /**
293
- * The theory's manifest: every name → id pairing as plain data (PRD-02's
294
- * tables, one JS object) — called once per open by the SDK.
295
- */
296
196
  interface Manifest {
297
197
  readonly relations: readonly ManifestRelation[];
298
198
  readonly statements: readonly ManifestStatement[];
299
199
  }
300
- /** One offending fact of a violation, decoded to named natural values. */
301
200
  interface ViolationFact {
302
201
  readonly relation: string;
303
202
  readonly fields: ReadonlyArray<{
@@ -305,15 +204,6 @@ interface ViolationFact {
305
204
  readonly value: FactValue;
306
205
  }>;
307
206
  }
308
- /**
309
- * One violated statement of a rejected commit, rendered to plain data: the
310
- * statement id (materialized order), form tag, CANONICAL spelling (the
311
- * engine's one renderer — a bijection on legal statements, paste-back-able),
312
- * the form's direction/measure payloads, and the decoded offending facts.
313
- * `measure` is the capacity form's witnessed group total — the engine
314
- * accumulates in u128 and the value crosses WHOLE as bigint (C3:
315
- * truncation is unrepresentable).
316
- */
317
207
  type Violation = {
318
208
  readonly statementId: number;
319
209
  readonly kind: "functionality";
@@ -332,15 +222,25 @@ type Violation = {
332
222
  readonly measure: bigint;
333
223
  readonly facts: readonly ViolationFact[];
334
224
  };
225
+ type CreateResult = {
226
+ readonly tag: "accepted";
227
+ readonly db: DbHandle;
228
+ } | {
229
+ readonly tag: "rejected";
230
+ readonly violations: readonly Violation[];
231
+ } | {
232
+ readonly tag: "schemaError";
233
+ readonly message: string;
234
+ } | {
235
+ readonly tag: "newtypeMismatch";
236
+ readonly message: string;
237
+ };
335
238
  /**
336
- * `dbCreate`/`dbOpen`'s domain outcome. `schemaError` spans both spec
239
+ * `dbOpen`'s domain outcome. `schemaError` spans both spec
337
240
  * resolution (unresolvable names, banned spellings — every issue in one
338
241
  * message) and schema validation at the declaration boundary;
339
- * `newtypeMismatch` is the coherence wall's own kind — a spec whose
340
- * statement pairs faces with disagreeing newtype labels (the engine twin
341
- * of the schema-level class wall; unreachable through the typed builder,
342
- * which computes every label from the laws, so only a raw spec can reach
343
- * it); `fingerprintMismatch` is `dbOpen`'s stored-theory refusal.
242
+ * `newtypeMismatch` is the coherence wall's own kind; `fingerprintMismatch`
243
+ * is `dbOpen`'s stored-theory refusal.
344
244
  */
345
245
  type DbOpenResult = {
346
246
  readonly ok: true;
@@ -350,50 +250,26 @@ type DbOpenResult = {
350
250
  readonly kind: "schemaError" | "newtypeMismatch" | "fingerprintMismatch";
351
251
  readonly message: string;
352
252
  };
353
- /**
354
- * `dbExhume`'s domain outcome: the live exhume handle, or one of the three
355
- * adoption-era refusals as data — `descriptorMissing` (the store predates
356
- * self-describing stores and has not been adopted; the remedy is one
357
- * fingerprint-matching `dbOpen` under the creating schema),
358
- * `formatMismatch`, and `corruption` (the persisted descriptor fails its
359
- * integrity gates). Genuine failures — a missing path, a held exclusive
360
- * lock — throw.
361
- */
362
- type ExhumeResult = {
363
- readonly ok: true;
364
- readonly exhume: ExhumeHandle;
253
+ type NativeWriteOutcome = {
254
+ readonly tag: "accepted";
255
+ readonly generation: bigint;
365
256
  } | {
366
- readonly ok: false;
367
- readonly kind: "descriptorMissing" | "formatMismatch" | "corruption";
368
- readonly message: string;
369
- };
370
- /**
371
- * `dbWriteFrom`'s domain outcome: the live witnessed transaction, or the
372
- * typed stale-premise verdict (a state-changing commit landed after the
373
- * witness snapshot; retry policy is host-side).
374
- */
375
- type WriteFromResult = {
376
- readonly ok: true;
377
- readonly tx: TxHandle;
257
+ readonly tag: "rejected";
258
+ readonly violations: readonly Violation[];
378
259
  } | {
379
- readonly ok: false;
380
- readonly kind: "generationMoved";
260
+ readonly tag: "abandoned";
261
+ } | {
262
+ readonly tag: "moved";
381
263
  readonly witnessed: bigint;
382
264
  readonly current: bigint;
383
265
  };
384
- /**
385
- * `txCommit`'s domain outcome: the committed generation, or the COMPLETE
386
- * violation set (every violated statement cited once, per direction for a
387
- * containment, in materialized statement order).
388
- */
389
- type CommitResult = {
390
- readonly ok: true;
391
- readonly generation: bigint;
266
+ type AdmitResult = {
267
+ readonly tag: "accepted";
268
+ readonly value: OwnedHandle;
392
269
  } | {
393
- readonly ok: false;
270
+ readonly tag: "rejected";
394
271
  readonly violations: readonly Violation[];
395
272
  };
396
- /** `dbPrepare`'s domain outcome (IR roster errors are data). */
397
273
  type PrepareResult = {
398
274
  readonly ok: true;
399
275
  readonly prepared: PreparedHandle;
@@ -402,251 +278,82 @@ type PrepareResult = {
402
278
  readonly kind: "irError";
403
279
  readonly message: string;
404
280
  };
405
- /** One occurrence's plan drift (pinned vs live row counts). */
406
- interface OccurrenceDrift {
407
- readonly relation: number;
408
- readonly pinned: bigint;
409
- readonly live: bigint;
410
- readonly ratio: number;
411
- }
412
- /**
413
- * The pull-based plan-drift report: engine-policy-free — no threshold
414
- * exists engine-side; the host owns reprepare policy.
415
- */
416
- interface Staleness {
417
- readonly perOccurrence: readonly OccurrenceDrift[];
418
- readonly maxRatio: number;
419
- }
420
- /**
421
- * `dbSnapshot`'s reply: the live handle WITH its witnessed generation —
422
- * one crossing carries both (read inside the snapshot's own transaction,
423
- * the race-closing rule of 50-storage.md), so no second `dbGeneration`
424
- * call exists to pay or defend (finding 016's bridge shape).
425
- */
426
- type SnapshotOpened = {
427
- readonly ok: true;
428
- readonly snapshot: SnapshotHandle;
429
- readonly generation: bigint;
430
- };
431
- /**
432
- * The plan-as-data report (ruled 2026-07-23, R13): the engine's
433
- * `ExecutionStats` rendered to plain objects — camelCase keys, u64
434
- * counters as `bigint`. A diagnostic surface, EXPLICITLY UNFROZEN: the
435
- * shape follows the plan representation wherever it goes and no
436
- * compatibility claim attaches, so this typing names the stable spine
437
- * (version, emits, the plan sections) and leaves each section's leaves
438
- * open for the host to introspect.
439
- */
440
- interface Explain {
441
- readonly introspectionVersion: number;
442
- readonly emits: bigint;
443
- readonly disjointRules?: Readonly<Record<string, unknown>>;
444
- readonly subsumed: ReadonlyArray<Readonly<Record<string, unknown>>>;
445
- readonly dead: ReadonlyArray<Readonly<Record<string, unknown>>>;
446
- readonly rules: ReadonlyArray<Readonly<Record<string, unknown>>>;
447
- readonly interiors: ReadonlyArray<Readonly<Record<string, unknown>>>;
448
- readonly reach?: Readonly<Record<string, unknown>>;
449
- }
281
+ type ErrorFamilyKind = "formatMismatch" | "schemaMismatch" | "alreadyInitialized" | "destinationExists" | "publishedButUnsynced" | "environmentLocked" | "io" | "lmdb" | "readersFull" | "schema" | "validation" | "factShape" | "freshExhausted" | "closedRelationWrite" | "commitSync" | "transactionPoisoned" | "foreignPrepared" | "foreignWitness" | "param" | "capacityRayMeasure" | "derivedBudgetExceeded" | "overflow" | "resultBytesOverflow" | "corruption";
282
+ type AdmissionTag = "accepted" | "rejected";
283
+ type WriteTag = "accepted" | "rejected" | "abandoned" | "moved";
284
+ type OpenKind = "schemaError" | "newtypeMismatch" | "fingerprintMismatch";
285
+ type PrepareKind = "irError";
450
286
  interface Native {
451
- /**
452
- * Proof-of-life export (PRD-03): a non-empty string naming the bridge
453
- * crate version and the engine's storage format version — evidence the
454
- * cargo path dependency compiled, linked, and loaded through Node-API.
455
- */
456
287
  engineVersion(): string;
457
- /**
458
- * Creates a fresh DURABLE store at `path` (frozen ruling 3: no ephemeral
459
- * kind crosses this bridge). Refuses an already-initialized directory
460
- * (throws); schema failures return as data.
461
- */
462
- dbCreate(path: string, spec: SchemaSpec): DbOpenResult;
463
- /**
464
- * Opens an existing durable store, verifying format version, store
465
- * kind, and schema fingerprint (`fingerprintMismatch` as data).
466
- */
467
- dbOpen(path: string, spec: SchemaSpec): DbOpenResult;
468
- /**
469
- * Closes the handle. Dependent handles each hold the engine alive; the
470
- * environment (and its exclusive lock) releases when the last closes.
471
- */
472
- dbClose(db: DbHandle): void;
473
- /** The PRD-02 manifest — every name → id table, one plain object. */
288
+ dbCreate(path: string, spec: SchemaSpec): Promise<CreateResult>;
289
+ dbOpen(path: string, spec: SchemaSpec): Promise<DbOpenResult>;
474
290
  dbManifest(db: DbHandle): Manifest;
475
- /**
476
- * The open store's schema fingerprint, 64 lowercase hex chars — the
477
- * cross-host identity readback (`dbCreate` stored this exact value,
478
- * `dbOpen` verified it). The engine computes; the bridge hex-encodes.
479
- * Test-facing (the cross-host fingerprint lock); the SDK surface stays
480
- * bijective with the Rust surface, which exposes no fingerprint
481
- * accessor on `Db` — so no `Db` method wraps this.
482
- */
483
291
  dbFingerprint(db: DbHandle): string;
484
- /**
485
- * The current committed generation — diagnostics only. The write-side
486
- * witness is always the SNAPSHOT handle (`dbWriteFrom`), never this
487
- * integer: an integer witness would be a claim a caller could fabricate
488
- * or stale-cache (the engine's recorded refusal).
489
- */
490
292
  dbGeneration(db: DbHandle): bigint;
293
+ dbFromInstance(path: string, instance: OwnedHandle): Promise<DbHandle>;
491
294
  /**
492
- * Opens a store FROM ITS OWN PERSISTED DESCRIPTOR (the read-only,
493
- * theory-less open; engine 70-api.md § exhume) — no schema crosses in.
494
- * The three adoption-era refusals return as data ({@link ExhumeResult});
495
- * genuine failures throw. The handle's deterministic teardown is
496
- * `exhumeClose` (R12); GC reclamation remains the backstop only.
497
- */
498
- dbExhume(path: string): ExhumeResult;
499
- /**
500
- * Closes the exhume handle, releasing its environment (and the store's
501
- * exclusive lock) deterministically — the native teardown under the
502
- * SDK's `Symbol.dispose` (ruled 2026-07-23, R12: lifetimes are
503
- * disposables, never `close()` methods to remember).
504
- */
505
- exhumeClose(exhume: ExhumeHandle): void;
506
- /**
507
- * The exhumed store's persisted schema as manifest-shaped data — the
508
- * engine's own manifest rendering of the STORED descriptor: relations
509
- * in engine-id order, sealed field lists (a closed relation opens with
510
- * the synthetic (`id`, u64) handle field) with structural value types,
511
- * and closed-relation rosters.
295
+ * Runs `callback` synchronously inside the engine read lease. The
296
+ * instance handle is invalid after the callback returns; the witness
297
+ * handle is a clone and may escape.
512
298
  */
513
- exhumeDescriptor(exhume: ExhumeHandle): Manifest;
514
- /**
515
- * Full-relation export by NAME in row-id order, values marshaled per
516
- * the STORED descriptor (str already resolved through `_dict` inside
517
- * the engine; a closed relation scans its sealed roster). Each call is
518
- * one self-contained snapshot read; an unknown relation name throws.
519
- */
520
- exhumeScan(exhume: ExhumeHandle, relationName: string): FactValue[][];
521
- /**
522
- * Opens one MVCC read snapshot as a live handle, returned WITH its
523
- * witnessed generation — one crossing carries both (finding 016), so
524
- * no separate `dbGeneration` call (with its own transient read
525
- * transaction and fault-pairing close branch) exists on this path.
526
- */
527
- dbSnapshot(db: DbHandle): SnapshotOpened;
528
- /** Closes the snapshot, releasing its LMDB reader slot. */
529
- snapshotClose(snap: SnapshotHandle): void;
530
- /** Full-relation export in row-id order (one row per fact). */
531
- snapshotScan(snap: SnapshotHandle, relationId: number): FactValue[][];
532
- /** Committed-state membership of one fact (sealed field order). */
533
- snapshotContains(snap: SnapshotHandle, relationId: number, values: readonly FactValue[]): boolean;
534
- /**
535
- * Committed-state point lookup through a key statement (`keyValues` in
536
- * the statement's projection order); `null` on a miss.
537
- */
538
- snapshotGet(snap: SnapshotHandle, relationId: number, keyStatementId: number, keyValues: readonly FactValue[]): FactValue[] | null;
539
- /**
540
- * Begins a write transaction: the submitted delta. One write
541
- * transaction may be open per db handle at a time (single-writer
542
- * engine; a second begin throws rather than deadlocking the process).
543
- */
544
- dbWriteBegin(db: DbHandle): TxHandle;
545
- /**
546
- * Begins a WITNESSED write transaction: commits only if no
547
- * state-changing commit landed since `snap` was taken —
548
- * `generationMoved` as data otherwise (the optimistic
549
- * read-compute-write loop's entry; retry policy stays host-side).
550
- */
551
- dbWriteFrom(db: DbHandle, snap: SnapshotHandle): WriteFromResult;
299
+ dbRead<R>(db: DbHandle, callback: (instance: InstanceHandle, witness: WitnessHandle) => R): R;
300
+ instanceGeneration(instance: InstanceHandle): bigint;
301
+ instanceScan(instance: InstanceHandle, relationId: number): FactValue[][];
302
+ instanceCount(instance: InstanceHandle, relationId: number): bigint;
303
+ instanceContains(instance: InstanceHandle, relationId: number, values: readonly FactValue[]): boolean;
304
+ instanceGet(instance: InstanceHandle, relationId: number, keyStatementId: number, keyValues: readonly FactValue[]): FactValue[] | null;
305
+ instancePrepare(instance: InstanceHandle, query: ParsedQuery): PrepareResult;
306
+ witnessClose(witness: WitnessHandle): void;
307
+ dbWrite(db: DbHandle, callback: (tx: TxHandle) => boolean): NativeWriteOutcome;
308
+ dbWriteFrom(db: DbHandle, witness: WitnessHandle, callback: (tx: TxHandle) => boolean): NativeWriteOutcome;
552
309
  /**
553
310
  * Records a collection of inserts into the delta; returns the engine
554
- * `{ submitted, changed }` report. `rows` is an array of value-arrays
555
- * in sealed field order. Empty is lawful and still a mutation (poison
556
- * is observed). Nothing is judged until commit; shape violations throw typed.
557
- */
558
- txInsert(tx: TxHandle, relationId: number, rows: readonly (readonly FactValue[])[]): WireMutationReport;
559
- /** Records a collection of deletes; returns the engine `{ submitted, changed }` report. */
560
- txDelete(tx: TxHandle, relationId: number, rows: readonly (readonly FactValue[])[]): WireMutationReport;
561
- /**
562
- * Final-state membership (base + pending delta — the exact view the
563
- * commit judgment judges; check-then-act is race-free by construction).
311
+ * `{ submitted, changed }` report. `cells` is ONE flat row-major array
312
+ * (length rows×arity) in sealed field order, and `rows` is the EXPLICIT
313
+ * row count the caller states — the one collection crossing
314
+ * (proposals/one-representation/20): the JS side alone knows N when the
315
+ * roster is fieldless (N nullary facts project to 0 cells, so no
316
+ * derivation can recover N), and the bridge verifies
317
+ * `cells.length === rows × arity` exactly against its resident sealed
318
+ * roster before building the engine's shape-proved collection in a
319
+ * single pass. Empty (`rows === 0n`, no cells) is lawful and still a
320
+ * mutation. Nothing is judged until commit; shape violations throw
321
+ * typed, naming relation and field.
564
322
  */
323
+ txInsert(tx: TxHandle, relationId: number, rows: bigint, cells: readonly FactValue[]): WireMutationReport;
324
+ txDelete(tx: TxHandle, relationId: number, rows: bigint, cells: readonly FactValue[]): WireMutationReport;
565
325
  txContains(tx: TxHandle, relationId: number, values: readonly FactValue[]): boolean;
566
- /** Final-state point lookup through a key statement; `null` on a miss. */
567
326
  txGet(tx: TxHandle, relationId: number, keyStatementId: number, keyValues: readonly FactValue[]): FactValue[] | null;
568
- /**
569
- * Mints `count` consecutive fresh values for `(relationId, fieldId)`.
570
- * `count === 0n` is empty and does not yield a start.
571
- */
572
327
  txReserve(tx: TxHandle, relationId: number, fieldId: number, count: bigint): WireFreshRange;
573
- /**
574
- * Commits the delta: every dependency statement judged against the
575
- * final state; a rejection carries the complete violation rendering.
576
- * The handle is spent either way.
577
- */
578
- txCommit(tx: TxHandle): CommitResult;
579
- /** Aborts the delta (LMDB was never touched). The handle is spent. */
580
- txAbort(tx: TxHandle): void;
581
- /**
582
- * Prepares a query (IR as data, ids only; plan pinned at prepare).
583
- * Roster errors return as data.
584
- */
585
328
  dbPrepare(db: DbHandle, query: ParsedQuery): PrepareResult;
586
- /**
587
- * Executes against a snapshot with positional params. One-copy owned
588
- * rows out, column order = the query's head order; answers are a set
589
- * — the host sorts.
590
- */
591
- preparedExecute(prepared: PreparedHandle, snap: SnapshotHandle, params: readonly QueryParam[]): FactValue[][];
592
- /**
593
- * Plan introspection as data (ruled 2026-07-23, R13): runs the prepared
594
- * query against the snapshot with counting instrumentation (the
595
- * engine's `Snapshot::profile`, ANALYZE semantics) and returns the
596
- * structured stats — plan sections and counters as plain values.
597
- * Scalar params only (the engine's profile entry has no param-set
598
- * spelling).
599
- */
600
- preparedExplain(prepared: PreparedHandle, snap: SnapshotHandle, params: readonly QueryParam[]): Explain;
601
- /** The pull-based plan-drift signal against a snapshot. */
602
- preparedStaleness(prepared: PreparedHandle, snap: SnapshotHandle): Staleness;
603
- /** Releases the prepared query. */
329
+ preparedExecute(prepared: PreparedHandle, instance: InstanceHandle, params: readonly QueryParam[]): FactValue[][];
604
330
  preparedClose(prepared: PreparedHandle): void;
331
+ instanceBuilderNew(spec: SchemaSpec): BuilderHandle;
332
+ instanceBuilderLoad(builder: BuilderHandle, relationId: number, rows: bigint, cells: readonly FactValue[]): WireMutationReport;
333
+ instanceBuilderDelete(builder: BuilderHandle, relationId: number, rows: bigint, cells: readonly FactValue[]): WireMutationReport;
334
+ instanceBuilderReserve(builder: BuilderHandle, relationId: number, fieldId: number, count: bigint): WireFreshRange;
335
+ instanceBuilderContains(builder: BuilderHandle, relationId: number, values: readonly FactValue[]): boolean;
336
+ instanceBuilderGet(builder: BuilderHandle, relationId: number, keyStatementId: number, keyValues: readonly FactValue[]): FactValue[] | null;
337
+ instanceBuilderClose(builder: BuilderHandle): void;
338
+ instanceBuilderAdmit(builder: BuilderHandle): Promise<AdmitResult>;
339
+ ownedInstanceClose(instance: OwnedHandle): void;
340
+ ownedScan(instance: OwnedHandle, relationId: number): FactValue[][];
341
+ ownedCount(instance: OwnedHandle, relationId: number): bigint;
342
+ ownedContains(instance: OwnedHandle, relationId: number, values: readonly FactValue[]): boolean;
343
+ ownedGet(instance: OwnedHandle, relationId: number, keyStatementId: number, keyValues: readonly FactValue[]): FactValue[] | null;
344
+ ownedPrepare(instance: OwnedHandle, query: ParsedQuery): PrepareResult;
345
+ ownedExecute(prepared: PreparedHandle, instance: OwnedHandle, params: readonly QueryParam[]): FactValue[][];
605
346
  }
606
- /**
607
- * The sole platform this release ships (PRD-03 ruling 1: prebuilt-only,
608
- * darwin-arm64). The per-platform-package structure below makes adding
609
- * `darwin-x64`/`linux-*`/`win32-*` pure addition — one more `os`/`cpu`-gated
610
- * package plus a CI matrix — never a redesign. This constant names the
611
- * shipped set for the unsupported-platform message; the build's
612
- * `PUBLISH_PLATFORM` (`scripts/platform.ts` — src cannot import scripts,
613
- * the packaging boundary) and the `ts/.gitignore` carve-out spell the same
614
- * target, and the single-source pin in `test/build-platform.test.ts` holds
615
- * all three in lockstep.
616
- */
617
347
  declare const SHIPPED_PLATFORMS = "darwin-arm64";
618
- /**
619
- * Resolves and loads the native bridge from its per-platform binary package
620
- * (`@bjornpagen/bumbledb-<platform>-<arch>`) — the Biome/esbuild/napi-rs
621
- * pattern. npm/pnpm install ONLY the `optionalDependency` whose `os`/`cpu`
622
- * match the host, so a matching host resolves the addon and every other host
623
- * resolves nothing. The two failure modes are distinct and both typed:
624
- *
625
- * - the platform package is ABSENT (the expected state on any
626
- * non-darwin-arm64 host, and on a foreign `platform`/`arch` passed under
627
- * test) — an actionable unsupported-platform error naming the running
628
- * `platform-arch` and the shipped set;
629
- * - the platform package is PRESENT but its `bumbledb.node` will not load
630
- * (a genuine ABI/corruption fault) — the wrapped loader error.
631
- *
632
- * Parameterized on `platform`/`arch` so the resolution law is exercised for
633
- * foreign hosts as a unit, without spawning a foreign process.
634
- */
635
- declare function loadNativeBinding(platform: string, arch: string): Native;
636
- /**
637
- * The loaded bumbledb-node bridge for the running host. Import this object
638
- * for every native call; the resolve-and-load happens once at module
639
- * initialization and an absent or unloadable artifact fails fast here rather
640
- * than at first use.
641
- */
348
+ interface NativeBinding extends Native {
349
+ dbClose(db: DbHandle): void;
350
+ }
351
+ declare function loadNativeBinding(platform: string, arch: string): NativeBinding;
642
352
  declare const native: Native;
643
- /**
644
- * The bridge guard — THE one wrapper every native call crosses (db.ts and
645
- * exhume.ts both import it): runs one native call and wraps anything it
646
- * throws, so marshal-shape refusals and handle-lifecycle refusals cross as
647
- * genuine typed failures, never bare foreign errors.
648
- */
353
+ declare function dbClose(db: DbHandle): void;
354
+ declare function errorFromThrow(caught: unknown): Error;
649
355
  declare function bridged<T>(context: string, run: () => T): T;
650
- export type { AggOpIr, AtomIr, AtomSourceIr, CmpOpIr, CommitResult, ComparisonIr, ConditionTreeIr, DbHandle, DbOpenResult, ExhumeHandle, ExhumeResult, Explain, FactValue, FindTermIr, FoldOpIr, HeadOpIr, HeadTermIr, InteriorIr, IntervalValue, Manifest, ManifestField, ManifestRelation, ManifestRow, ManifestStatement, Native, OccurrenceDrift, ParsedQuery, PreparedHandle, PrepareResult, QueryIr, QueryParam, RecIr, RuleIr, SnapshotHandle, SnapshotOpened, Staleness, StatementKindTag, TaggedValue, TermIr, TxHandle, Violation, ViolationFact, WireFreshRange, WireMutationReport, WriteFromResult };
651
- export { bridged, loadNativeBinding, native, SHIPPED_PLATFORMS };
356
+ declare function bridgedAsync<T>(context: string, run: () => Promise<T>): Promise<T>;
357
+ export type { AdmissionTag, AdmitResult, AggOpIr, AtomIr, AtomSourceIr, BuilderHandle, CmpOpIr, ComparisonIr, ConditionTreeIr, CreateResult, DbHandle, DbOpenResult, ErrorFamilyKind, FactValue, FindTermIr, FoldOpIr, HeadOpIr, HeadTermIr, InstanceHandle, InteriorIr, IntervalValue, Manifest, ManifestField, ManifestRelation, ManifestRow, ManifestStatement, Native, NativeWriteOutcome, OpenKind, OwnedHandle, ParsedQuery, PreparedHandle, PrepareKind, PrepareResult, QueryIr, QueryParam, RecIr, RuleIr, StatementKindTag, TaggedValue, TermIr, TxHandle, Violation, ViolationFact, WireFreshRange, WireMutationReport, WitnessHandle, WriteTag };
358
+ export { bridged, bridgedAsync, dbClose, errorFromThrow, loadNativeBinding, native, SHIPPED_PLATFORMS };
652
359
  //# sourceMappingURL=native.d.ts.map