@bjornpagen/bumbledb 1.0.0 → 1.1.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 (102) hide show
  1. package/COOKBOOK.md +64 -27
  2. package/README.md +21 -20
  3. package/dist/capacity.d.ts +1 -1
  4. package/dist/changes.d.ts +4 -5
  5. package/dist/changes.d.ts.map +1 -1
  6. package/dist/changes.js +37 -34
  7. package/dist/changes.js.map +1 -1
  8. package/dist/close.d.ts +2 -2
  9. package/dist/codec.d.ts +5 -6
  10. package/dist/codec.d.ts.map +1 -1
  11. package/dist/codec.js +6 -6
  12. package/dist/codec.js.map +1 -1
  13. package/dist/compile.d.ts +4 -6
  14. package/dist/compile.d.ts.map +1 -1
  15. package/dist/compile.js +6 -6
  16. package/dist/compile.js.map +1 -1
  17. package/dist/db-native.d.ts +43 -56
  18. package/dist/db-native.d.ts.map +1 -1
  19. package/dist/db-native.js.map +1 -1
  20. package/dist/db.d.ts +43 -28
  21. package/dist/db.d.ts.map +1 -1
  22. package/dist/db.js +77 -63
  23. package/dist/db.js.map +1 -1
  24. package/dist/errors.d.ts +4 -8
  25. package/dist/errors.d.ts.map +1 -1
  26. package/dist/errors.js +4 -8
  27. package/dist/errors.js.map +1 -1
  28. package/dist/fields.d.ts +4 -5
  29. package/dist/fields.d.ts.map +1 -1
  30. package/dist/fields.js.map +1 -1
  31. package/dist/index.d.ts +4 -4
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +2 -2
  34. package/dist/index.js.map +1 -1
  35. package/dist/internal/log.d.ts +4 -4
  36. package/dist/internal/log.d.ts.map +1 -1
  37. package/dist/internal/log.js +1 -1
  38. package/dist/internal/log.js.map +1 -1
  39. package/dist/law.d.ts +1 -1
  40. package/dist/migration.d.ts +5 -7
  41. package/dist/migration.d.ts.map +1 -1
  42. package/dist/migration.js +8 -9
  43. package/dist/migration.js.map +1 -1
  44. package/dist/native.d.ts +2 -2
  45. package/dist/native.d.ts.map +1 -1
  46. package/dist/native.js.map +1 -1
  47. package/dist/query/lower.d.ts +1 -1
  48. package/dist/result.d.ts +10 -25
  49. package/dist/result.d.ts.map +1 -1
  50. package/dist/result.js +7 -12
  51. package/dist/result.js.map +1 -1
  52. package/dist/rows.d.ts +10 -16
  53. package/dist/rows.d.ts.map +1 -1
  54. package/dist/rows.js +8 -45
  55. package/dist/rows.js.map +1 -1
  56. package/dist/runtime-codes.d.ts +1 -1
  57. package/dist/runtime-codes.d.ts.map +1 -1
  58. package/dist/runtime-codes.js +1 -2
  59. package/dist/runtime-codes.js.map +1 -1
  60. package/dist/runtime-errors.d.ts +3 -15
  61. package/dist/runtime-errors.d.ts.map +1 -1
  62. package/dist/runtime-errors.js +1 -5
  63. package/dist/runtime-errors.js.map +1 -1
  64. package/dist/runtime-native.d.ts +18 -48
  65. package/dist/runtime-native.d.ts.map +1 -1
  66. package/dist/runtime-native.js.map +1 -1
  67. package/dist/runtime.d.ts +12 -29
  68. package/dist/runtime.d.ts.map +1 -1
  69. package/dist/runtime.js +16 -57
  70. package/dist/runtime.js.map +1 -1
  71. package/dist/shape.d.ts +3 -4
  72. package/dist/shape.d.ts.map +1 -1
  73. package/dist/spec.d.ts +2 -2
  74. package/dist/spec.js +1 -1
  75. package/dist/statements.js +2 -2
  76. package/dist/statements.js.map +1 -1
  77. package/pack-provenance.json +3 -3
  78. package/package.json +4 -4
  79. package/src/capacity.ts +1 -1
  80. package/src/changes.ts +50 -48
  81. package/src/close.ts +2 -2
  82. package/src/codec.ts +8 -24
  83. package/src/compile.ts +8 -10
  84. package/src/db-native.ts +37 -83
  85. package/src/db.ts +156 -135
  86. package/src/errors.ts +4 -8
  87. package/src/fields.ts +4 -5
  88. package/src/index.ts +6 -5
  89. package/src/internal/log.ts +2 -7
  90. package/src/law.ts +1 -1
  91. package/src/migration.ts +8 -16
  92. package/src/native.ts +2 -3
  93. package/src/query/lower.ts +1 -1
  94. package/src/result.ts +16 -45
  95. package/src/rows.ts +12 -65
  96. package/src/runtime-codes.ts +1 -2
  97. package/src/runtime-errors.ts +1 -5
  98. package/src/runtime-native.ts +15 -68
  99. package/src/runtime.ts +53 -122
  100. package/src/shape.ts +3 -4
  101. package/src/spec.ts +2 -2
  102. package/src/statements.ts +2 -2
package/src/db.ts CHANGED
@@ -9,7 +9,7 @@ import type {
9
9
  ApplyOutcomeWire,
10
10
  DbInspectionWire,
11
11
  ExpectedWire,
12
- SessionHandle,
12
+ PreparedHandle,
13
13
  SnapshotHandle,
14
14
  WitnessWire
15
15
  } from "#db-native.ts"
@@ -25,8 +25,8 @@ import type { CompleteResult } from "#result.ts"
25
25
  import { internalResult, makeCompleteResult } from "#result.ts"
26
26
  import type { CellValue } from "#rows.ts"
27
27
  import { factOfCells, keyCellsOf } from "#rows.ts"
28
- import type { ExecutionPolicy, NativeRuntime } from "#runtime.ts"
29
- import { nativeOperationWith, policyWire, runtimeHandle } from "#runtime.ts"
28
+ import type { NativeRuntime } from "#runtime.ts"
29
+ import { nativeOperationWith, runtimeHandle } from "#runtime.ts"
30
30
  import type { CloseReport } from "#runtime-errors.ts"
31
31
  import { DbError } from "#runtime-errors.ts"
32
32
  import type { DirectoryHandle } from "#runtime-native.ts"
@@ -35,12 +35,12 @@ import type { AnySchema } from "#schema.ts"
35
35
  import type { Key, QueryTemplate, Rel } from "#shape.ts"
36
36
 
37
37
  /**
38
- * The chapter 35 core surface: `Db.create`/`Db.open`, scoped coherent
39
- * `Snapshot`s, reusable `ExecutionSession`s, the shared `QueryReader`
38
+ * The core surface: `Db.create`/`Db.open`, scoped coherent
39
+ * `Snapshot`s, reusable `PreparedQuery`s, the shared `QueryReader`
40
40
  * capability, one immutable final-state `apply`, bounded `inspect` and
41
41
  * honest `close`. Effect-only: every method constructs a lazy effect; all
42
- * native work runs on the ONE bounded runtime executor under an explicit
43
- * `ExecutionPolicy`; resources are scoped with `CloseFailure`-defect
42
+ * native work runs on the shared executor with cooperative cancellation.
43
+ * Resources are scoped with `CloseFailure`-defect
44
44
  * finalizers. There is no Promise/sync/disposal twin, no transaction
45
45
  * callback, no per-row fiber and no Proxy row anywhere.
46
46
  *
@@ -59,8 +59,8 @@ interface CoreWitness {
59
59
 
60
60
  type ApplyExpected = { readonly kind: "any" } | { readonly kind: "exact"; readonly at: CoreWitness }
61
61
 
62
- /** Core work policy plus the expected-state intent (chapter 35). */
63
- type ApplyOptions = ExecutionPolicy & { readonly expected: ApplyExpected }
62
+ /** Expected-state intent for an atomic apply. */
63
+ type ApplyOptions = { readonly expected: ApplyExpected }
64
64
 
65
65
  type ApplyOutcome =
66
66
  | { readonly kind: "accepted"; readonly witness: CoreWitness }
@@ -68,53 +68,66 @@ type ApplyOutcome =
68
68
  | { readonly kind: "invariant-rejected"; readonly violations: readonly Violation[] }
69
69
  | { readonly kind: "moved"; readonly witnessed: CoreWitness; readonly current: CoreWitness }
70
70
 
71
- /** Bounded database diagnostics: measurements, never retained rows. */
71
+ /** Storage measurements, not heap usage or mapped-page residency. */
72
+ interface StorageInspection {
73
+ /** Reserved virtual address range for the LMDB mapping. */
74
+ readonly virtualMapBytes: bigint
75
+ /** File length; may include sparse regions and free pages. */
76
+ readonly populatedFileBytes: bigint
77
+ /** LMDB's non-free branch, leaf and overflow pages. Not resident RAM. */
78
+ readonly nonFreePageBytes: bigint
79
+ /** Allocated filesystem blocks, or null when the OS cannot report them. */
80
+ readonly allocatedDiskBytes: bigint | null
81
+ }
82
+
83
+ /** Database diagnostics: measurements, never retained rows. */
72
84
  interface DbInspection {
73
85
  readonly schemaId: SchemaId
74
86
  readonly generation: bigint
75
- readonly mapBytes: bigint
76
- readonly populatedBytes: bigint
77
- readonly diskBytes: bigint
78
- readonly residentEstimateBytes: bigint
87
+ readonly storage: StorageInspection
79
88
  readonly retainedOperations: bigint
80
89
  }
81
90
 
82
91
  /**
83
- * The one shared read capability (chapter 30): the same typed `get` and
92
+ * The shared read capability: the same typed `get` and
84
93
  * `execute` on a core snapshot and on a log published snapshot, so a
85
94
  * cross-package read helper takes this interface with no adapter. Missing
86
95
  * key is `Option.none`, never a fake I/O error or nullable row. It carries
87
96
  * no writable authority — never a `Db`, an `apply`, or a raw transaction.
88
97
  */
89
98
  interface QueryReader<S extends AnySchema> {
90
- get<R extends Rel<S>>(relation: R, key: Key<R>, work: ExecutionPolicy): Effect.Effect<Option.Option<Fact<R>>, DbError>
99
+ get<R extends Rel<S>>(relation: R, key: Key<R>): Effect.Effect<Option.Option<Fact<R>>, DbError>
91
100
  execute<P extends ParamsRecord, A>(
92
101
  query: QueryTemplate<S, P, A>,
93
- params: P,
94
- work: ExecutionPolicy
102
+ params: P
95
103
  ): Effect.Effect<CompleteResult<A>, DbError, Scope.Scope>
104
+ prepare<P extends ParamsRecord, A>(
105
+ query: QueryTemplate<S, P, A>
106
+ ): Effect.Effect<PreparedQuery<P, A>, DbError, Scope.Scope>
96
107
  }
97
108
 
98
109
  interface Snapshot<S extends AnySchema> extends QueryReader<S> {
99
110
  readonly witness: CoreWitness
100
- session(work: ExecutionPolicy): Effect.Effect<ExecutionSession<S>, DbError, Scope.Scope>
101
111
  close(): Effect.Effect<CloseReport>
102
112
  }
103
113
 
104
- interface ExecutionSession<S extends AnySchema> {
105
- execute<P extends ParamsRecord, A>(
106
- query: QueryTemplate<S, P, A>,
107
- params: P,
108
- work: ExecutionPolicy
109
- ): Effect.Effect<CompleteResult<A>, DbError, Scope.Scope>
114
+ /** One compiled plan and its reusable buffers, pinned to the preparing snapshot.
115
+ * Closing it releases its own state, not the snapshot or completed results.
116
+ */
117
+ interface PreparedQuery<P extends ParamsRecord, A> {
118
+ execute(params: P): Effect.Effect<CompleteResult<A>, DbError, Scope.Scope>
119
+ /** Drop reusable execution buffers, keeping the compiled query and snapshot. */
120
+ releaseMemory(): Effect.Effect<void, DbError>
110
121
  close(): Effect.Effect<CloseReport>
111
122
  }
112
123
 
113
124
  interface Db<S extends AnySchema> {
114
125
  readonly schemaId: SchemaId
115
- snapshot(work: ExecutionPolicy): Effect.Effect<Snapshot<S>, DbError, Scope.Scope>
126
+ snapshot(): Effect.Effect<Snapshot<S>, DbError, Scope.Scope>
116
127
  apply(changes: ChangeSet<S>, options: ApplyOptions): Effect.Effect<ApplyOutcome, DbError>
117
- inspect(work: ExecutionPolicy): Effect.Effect<DbInspection, DbError>
128
+ inspect(): Effect.Effect<DbInspection, DbError>
129
+ /** Clear shared query caches without invalidating live snapshots or results. */
130
+ clearCache(): Effect.Effect<void, DbError>
118
131
  close(): Effect.Effect<CloseReport>
119
132
  }
120
133
 
@@ -142,7 +155,7 @@ function outcomeOf(wire: ApplyOutcomeWire): ApplyOutcome {
142
155
  /**
143
156
  * Validates the query template's schema binding (identity, the membership
144
157
  * rule) and lowers it to IR plus wire params. Pure host preparation; the
145
- * engine's IR validation under budget remains the authority.
158
+ * engine's IR validation remains the authority.
146
159
  */
147
160
  function preparedOf<S extends AnySchema>(
148
161
  theory: S,
@@ -168,29 +181,29 @@ interface SnapshotState<S extends AnySchema> {
168
181
 
169
182
  function executeOn<S extends AnySchema, A>(
170
183
  state: SnapshotState<S>,
171
- session: SessionHandle | undefined,
172
184
  query: AnyQuery,
173
- params: Readonly<Record<string, unknown>>,
174
- work: ExecutionPolicy
185
+ params: Readonly<Record<string, unknown>>
175
186
  ): Effect.Effect<CompleteResult<A>, DbError, Scope.Scope> {
176
- return Effect.acquireRelease(
187
+ return scopedResult(
177
188
  Effect.gen(function* () {
178
189
  const prepared = yield* Effect.try({
179
190
  try: () => preparedOf(state.theory, query, params),
180
191
  catch: (cause) => (cause instanceof DbError ? cause : refusal("QueryReader.execute", "InvalidArgument"))
181
192
  })
182
- const wire = policyWire(work, "QueryReader.execute")
183
193
  const handle = yield* nativeOperationWith(
184
194
  "QueryReader.execute",
185
- (callback) =>
186
- session === undefined
187
- ? dbNative.runtimeSnapshotExecute(state.handle, wire, prepared.ir, prepared.wire, callback)
188
- : dbNative.runtimeSessionExecute(session, wire, prepared.ir, prepared.wire, callback),
195
+ (callback) => dbNative.runtimeSnapshotExecute(state.handle, prepared.ir, prepared.wire, callback),
189
196
  dbNative.runtimeResultTake,
190
197
  (value) => value
191
198
  )
192
199
  return makeCompleteResult<A>(handle, prepared.finds)
193
- }),
200
+ })
201
+ )
202
+ }
203
+
204
+ function scopedResult<A>(acquire: Effect.Effect<CompleteResult<A>, DbError>) {
205
+ return Effect.acquireRelease(
206
+ acquire,
194
207
  (result) =>
195
208
  Effect.suspend(() => {
196
209
  const internal = internalResultHandle(result)
@@ -210,8 +223,7 @@ function internalResultHandle(result: object) {
210
223
  function getOn<S extends AnySchema, R extends Rel<S>>(
211
224
  state: SnapshotState<S>,
212
225
  relation: R,
213
- key: Key<R>,
214
- work: ExecutionPolicy
226
+ key: Key<R>
215
227
  ): Effect.Effect<Option.Option<Fact<R>>, DbError> {
216
228
  return Effect.gen(function* () {
217
229
  if (state.theory.relations[relation.name] !== relation) {
@@ -229,15 +241,7 @@ function getOn<S extends AnySchema, R extends Rel<S>>(
229
241
  })
230
242
  const row = yield* nativeOperationWith(
231
243
  "QueryReader.get",
232
- (callback) =>
233
- dbNative.runtimeSnapshotGet(
234
- state.handle,
235
- policyWire(work, "QueryReader.get"),
236
- relationId,
237
- primary.statementId,
238
- cells,
239
- callback
240
- ),
244
+ (callback) => dbNative.runtimeSnapshotGet(state.handle, relationId, primary.statementId, cells, callback),
241
245
  dbNative.runtimeRowTake,
242
246
  (value) => value
243
247
  )
@@ -248,46 +252,83 @@ function getOn<S extends AnySchema, R extends Rel<S>>(
248
252
  })
249
253
  }
250
254
 
251
- function makeSession<S extends AnySchema>(state: SnapshotState<S>, handle: SessionHandle): ExecutionSession<S> {
252
- const session: ExecutionSession<S> = {
253
- execute(query, params, work) {
254
- return executeOn(state, handle, query, params, work)
255
+ function makePrepared<P extends ParamsRecord, A>(
256
+ handle: PreparedHandle,
257
+ definitions: AnyQuery["data"]["params"],
258
+ finds: AnyQuery["data"]["finds"]
259
+ ): PreparedQuery<P, A> {
260
+ return Object.freeze({
261
+ releaseMemory() {
262
+ return nativeOperationWith(
263
+ "PreparedQuery.releaseMemory",
264
+ (callback) => dbNative.runtimePreparedReleaseMemory(handle, callback),
265
+ runtimeNative.runtimeTake,
266
+ () => undefined
267
+ )
268
+ },
269
+ execute(params: P) {
270
+ return scopedResult(
271
+ Effect.gen(function* () {
272
+ const args = yield* Effect.try({
273
+ try: () => wireParams(definitions, params),
274
+ catch: () => refusal("PreparedQuery.execute", "InvalidArgument")
275
+ })
276
+ const result = yield* nativeOperationWith(
277
+ "PreparedQuery.execute",
278
+ (callback) => dbNative.runtimePreparedExecute(handle, args, callback),
279
+ dbNative.runtimeResultTake,
280
+ (value) => makeCompleteResult<A>(value, finds)
281
+ )
282
+ return result
283
+ })
284
+ )
255
285
  },
256
286
  close() {
257
- return drainClose("ExecutionSession.close", (callback) => dbNative.runtimeSessionClose(handle, callback))
287
+ return drainClose("PreparedQuery.close", (callback) => dbNative.runtimePreparedClose(handle, callback))
258
288
  }
259
- }
260
- Object.freeze(session)
261
- sessionHandles.set(session, handle)
262
- return session
289
+ })
290
+ }
291
+
292
+ function prepareOn<S extends AnySchema, P extends ParamsRecord, A>(
293
+ state: SnapshotState<S>,
294
+ query: QueryTemplate<S, P, A>
295
+ ): Effect.Effect<PreparedQuery<P, A>, DbError, Scope.Scope> {
296
+ return Effect.gen(function* () {
297
+ const ir = yield* Effect.try({
298
+ try: () => {
299
+ if (query.schema !== state.theory) {
300
+ throw refusal("QueryReader.prepare", "InvalidArgument")
301
+ }
302
+ return lowerQuery(query)
303
+ },
304
+ catch: () => refusal("QueryReader.prepare", "InvalidArgument")
305
+ })
306
+ const handle = yield* Effect.acquireRelease(
307
+ nativeOperationWith(
308
+ "QueryReader.prepare",
309
+ (callback) => dbNative.runtimeSnapshotPrepare(state.handle, ir, callback),
310
+ dbNative.runtimePreparedTake,
311
+ (value) => value
312
+ ),
313
+ (value) => releaseOwner("PreparedQuery.close", (callback) => dbNative.runtimePreparedClose(value, callback)),
314
+ { interruptible: true }
315
+ )
316
+ return makePrepared<P, A>(handle, query.data.params, query.data.finds)
317
+ })
263
318
  }
264
319
 
265
320
  function makeSnapshot<S extends AnySchema>(theory: S, handle: SnapshotHandle, witness: CoreWitness): Snapshot<S> {
266
321
  const state: SnapshotState<S> = { theory, handle }
267
322
  const snapshot: Snapshot<S> = {
268
323
  witness,
269
- get(relation, key, work) {
270
- return getOn(state, relation, key, work)
324
+ get(relation, key) {
325
+ return getOn(state, relation, key)
271
326
  },
272
- execute(query, params, work) {
273
- return executeOn(state, undefined, query, params, work)
327
+ execute(query, params) {
328
+ return executeOn(state, query, params)
274
329
  },
275
- session(work) {
276
- return Effect.acquireRelease(
277
- nativeOperationWith(
278
- "Snapshot.session",
279
- (callback) => dbNative.runtimeSnapshotSession(handle, policyWire(work, "Snapshot.session"), callback),
280
- dbNative.runtimeSessionTake,
281
- (value) => makeSession(state, value)
282
- ),
283
- (session) =>
284
- Effect.suspend(() =>
285
- releaseOwner("ExecutionSession.close", (callback) =>
286
- dbNative.runtimeSessionClose(sessionHandles.get(session) ?? missingSession(), callback)
287
- )
288
- ),
289
- { interruptible: true }
290
- )
330
+ prepare(query) {
331
+ return prepareOn(state, query)
291
332
  },
292
333
  close() {
293
334
  return drainClose("Snapshot.close", (callback) => dbNative.runtimeSnapshotClose(handle, callback))
@@ -298,12 +339,6 @@ function makeSnapshot<S extends AnySchema>(theory: S, handle: SnapshotHandle, wi
298
339
  return snapshot
299
340
  }
300
341
 
301
- const sessionHandles = new WeakMap<object, SessionHandle>()
302
-
303
- function missingSession(): never {
304
- throw new DbError({ operation: "ExecutionSession.close", reason: { _tag: "Internal" } })
305
- }
306
-
307
342
  interface DbState {
308
343
  readonly theory: AnySchema
309
344
  readonly db: DbHandle
@@ -314,11 +349,19 @@ interface DbState {
314
349
  function makeDb<S extends AnySchema>(theory: S, state: DbState): Db<S> {
315
350
  const value: Db<S> = {
316
351
  schemaId: state.schemaId,
317
- snapshot(work) {
352
+ clearCache() {
353
+ return nativeOperationWith(
354
+ "Db.clearCache",
355
+ (callback) => dbNative.runtimeDbClearCache(state.db, callback),
356
+ runtimeNative.runtimeTake,
357
+ () => undefined
358
+ )
359
+ },
360
+ snapshot() {
318
361
  return Effect.acquireRelease(
319
362
  nativeOperationWith(
320
363
  "Db.snapshot",
321
- (callback) => dbNative.runtimeDbSnapshot(state.db, policyWire(work, "Db.snapshot"), callback),
364
+ (callback) => dbNative.runtimeDbSnapshot(state.db, callback),
322
365
  dbNative.runtimeSnapshotTake,
323
366
  (wire) => makeSnapshot(theory, wire.snapshot, witnessOf(wire.witness))
324
367
  ),
@@ -348,33 +391,29 @@ function makeDb<S extends AnySchema>(theory: S, state: DbState): Db<S> {
348
391
  : { kind: "exact", store: options.expected.at.store, generation: options.expected.at.generation }
349
392
  return yield* nativeOperationWith(
350
393
  "Db.apply",
351
- (callback) =>
352
- dbNative.runtimeDbApply(state.db, policyWire(options, "Db.apply"), internal.handle, expected, callback),
394
+ (callback) => dbNative.runtimeDbApply(state.db, internal.handle, expected, callback),
353
395
  dbNative.runtimeApplyTake,
354
396
  outcomeOf
355
397
  )
356
398
  })
357
399
  },
358
- inspect(work) {
400
+ inspect() {
359
401
  return nativeOperationWith(
360
402
  "Db.inspect",
361
- (callback) => dbNative.runtimeDbInspect(state.db, policyWire(work, "Db.inspect"), callback),
403
+ (callback) => dbNative.runtimeDbInspect(state.db, callback),
362
404
  dbNative.runtimeDbInspectTake,
363
405
  (wire: DbInspectionWire): DbInspection =>
364
406
  Object.freeze({
365
407
  schemaId: state.schemaId,
366
408
  generation: wire.generation,
367
- mapBytes: wire.mapBytes,
368
- populatedBytes: wire.populatedBytes,
369
- diskBytes: wire.diskBytes,
370
- residentEstimateBytes: wire.residentEstimateBytes,
409
+ storage: Object.freeze(wire.storage),
371
410
  retainedOperations: wire.retainedOperations
372
411
  })
373
412
  )
374
413
  },
375
414
  close() {
376
415
  // The one close authority: database child first, then the
377
- // directory owner releases its kernel lock LAST (C09). Both
416
+ // directory owner releases its kernel lock LAST. Both
378
417
  // joins are idempotent natively.
379
418
  return drainClose("Db.close", (callback) => runtimeNative.runtimeManagedDbClose(state.db, callback)).pipe(
380
419
  Effect.flatMap((report) =>
@@ -402,23 +441,18 @@ function openDatabase<S extends AnySchema>(
402
441
  operation: "Db.create" | "Db.open",
403
442
  path: string,
404
443
  schema: S,
405
- work: ExecutionPolicy,
406
444
  create: boolean
407
445
  ): Effect.Effect<Db<S>, DbError, NativeRuntime | Scope.Scope> {
408
446
  return Effect.gen(function* () {
409
447
  const runtime = yield* runtimeHandle()
410
- const compiled: CompiledSchema<S> = yield* CoreSchema.compile(schema, work)
448
+ const compiled: CompiledSchema<S> = yield* CoreSchema.compile(schema)
411
449
  const spec = lower(schema)
412
- const wire = yield* Effect.try({
413
- try: () => policyWire(work, operation),
414
- catch: () => refusal(operation, "InvalidArgument")
415
- })
416
- // Compound acquisition (TS-003): register the directory owner and
450
+ // Compound acquisition: register the directory owner and
417
451
  // its finalizer BEFORE any interruptible child-open step.
418
452
  const directory = yield* Effect.acquireRelease(
419
453
  nativeOperationWith(
420
454
  operation,
421
- (callback) => runtimeNative.runtimeDirectoryAcquire(runtime, wire, path, callback),
455
+ (callback) => runtimeNative.runtimeDirectoryAcquire(runtime, path, callback),
422
456
  runtimeNative.runtimeDirectoryTake,
423
457
  (value) => value
424
458
  ),
@@ -432,7 +466,7 @@ function openDatabase<S extends AnySchema>(
432
466
  Effect.gen(function* () {
433
467
  const outcome = yield* nativeOperationWith(
434
468
  operation,
435
- (callback) => runtimeNative.runtimeDirectoryDbOpen(directory, wire, CHILD, spec, create, callback),
469
+ (callback) => runtimeNative.runtimeDirectoryDbOpen(directory, CHILD, spec, create, callback),
436
470
  runtimeNative.runtimeDbTake,
437
471
  (value) => value
438
472
  ).pipe(
@@ -477,24 +511,24 @@ const dbStates = new WeakMap<object, DbState>()
477
511
  /**
478
512
  * `Db.create` is the explicit constructor and refuses existing authority;
479
513
  * `Db.open` of a missing or unreadable database never creates an empty
480
- * replacement (chapter 30). Both compile the schema through the same
514
+ * replacement. Both compile the schema through the same
481
515
  * implementation as `Schema.compile` — prior compilation is optional.
482
516
  */
483
517
  const Db = Object.freeze({
484
- create<S extends AnySchema>(path: string, schema: S, work: ExecutionPolicy) {
485
- return openDatabase("Db.create", path, schema, work, true)
518
+ create<S extends AnySchema>(path: string, schema: S) {
519
+ return openDatabase("Db.create", path, schema, true)
486
520
  },
487
- open<S extends AnySchema>(path: string, schema: S, work: ExecutionPolicy) {
488
- return openDatabase("Db.open", path, schema, work, false)
521
+ open<S extends AnySchema>(path: string, schema: S) {
522
+ return openDatabase("Db.open", path, schema, false)
489
523
  }
490
524
  })
491
525
 
492
526
  /**
493
- * Private log-integration seam (C10): wraps a PUBLISHED core snapshot
527
+ * Private log integration: wraps a published core snapshot
494
528
  * handle — minted by the internal log machine's native open/snapshot verbs
495
529
  * — in the exact core `QueryReader` plus the scoped session acquisition
496
- * (`PublishedSnapshot extends QueryReader` in chapter 35; the log adds
497
- * identity/stamps/freshness AROUND this capability, never a second reader).
530
+ * (the log adds identity, stamps and freshness around this capability,
531
+ * never a second reader).
498
532
  * The argument is the log package's branded handle for the same native
499
533
  * registry entry, so the one cast below is a cross-package respelling of
500
534
  * one native capability — the native side re-judges kind/generation/owner
@@ -506,32 +540,18 @@ function internalPublishedReader<S extends AnySchema>(
506
540
  ): {
507
541
  readonly get: QueryReader<S>["get"]
508
542
  readonly execute: QueryReader<S>["execute"]
509
- readonly session: (work: ExecutionPolicy) => Effect.Effect<ExecutionSession<S>, DbError, Scope.Scope>
543
+ readonly prepare: QueryReader<S>["prepare"]
510
544
  } {
511
545
  const state: SnapshotState<S> = { theory, handle: core as SnapshotHandle }
512
546
  return Object.freeze({
513
- get<R extends Rel<S>>(relation: R, key: Key<R>, work: ExecutionPolicy) {
514
- return getOn(state, relation, key, work)
547
+ get<R extends Rel<S>>(relation: R, key: Key<R>) {
548
+ return getOn(state, relation, key)
515
549
  },
516
- execute<P extends ParamsRecord, A>(queryValue: QueryTemplate<S, P, A>, params: P, work: ExecutionPolicy) {
517
- return executeOn<S, A>(state, undefined, queryValue as AnyQuery, params, work)
550
+ execute<P extends ParamsRecord, A>(queryValue: QueryTemplate<S, P, A>, params: P) {
551
+ return executeOn<S, A>(state, queryValue as AnyQuery, params)
518
552
  },
519
- session(work: ExecutionPolicy) {
520
- return Effect.acquireRelease(
521
- nativeOperationWith(
522
- "Snapshot.session",
523
- (callback) => dbNative.runtimeSnapshotSession(state.handle, policyWire(work, "Snapshot.session"), callback),
524
- dbNative.runtimeSessionTake,
525
- (value) => makeSession(state, value)
526
- ),
527
- (session) =>
528
- Effect.suspend(() =>
529
- releaseOwner("ExecutionSession.close", (callback) =>
530
- dbNative.runtimeSessionClose(sessionHandles.get(session) ?? missingSession(), callback)
531
- )
532
- ),
533
- { interruptible: true }
534
- )
553
+ prepare<P extends ParamsRecord, A>(queryValue: QueryTemplate<S, P, A>) {
554
+ return prepareOn(state, queryValue)
535
555
  }
536
556
  })
537
557
  }
@@ -542,8 +562,9 @@ export type {
542
562
  ApplyOutcome,
543
563
  CoreWitness,
544
564
  DbInspection,
545
- ExecutionSession,
565
+ PreparedQuery,
546
566
  QueryReader,
547
- Snapshot
567
+ Snapshot,
568
+ StorageInspection
548
569
  }
549
570
  export { Db, internalPublishedReader }
package/src/errors.ts CHANGED
@@ -1,14 +1,10 @@
1
1
  import { Data } from "effect"
2
2
 
3
3
  /**
4
- * Pure authoring refusals and SDK-invariant defects. These are the ONLY
5
- * non-`DbError` throw families in the core package: chapter 35 permits
6
- * programmer-facing AST misuse to throw synchronously (no I/O ever), and a
7
- * contradiction between SDK and native state is a defect, not a domain
8
- * outcome. Every operational failure of effectful work is the single
9
- * `DbError` tagged-reason class in `#runtime-errors.ts` — the old
10
- * per-surface `Err*` wrapper family is deleted (duplicate error wrappers
11
- * are banned by C02/C10).
4
+ * Pure authoring failures, SDK-invariant defects and internal native-boundary
5
+ * diagnostics. AST misuse can throw synchronously without I/O. Runtime
6
+ * adapters translate operational failures into the public `DbError` class
7
+ * in `#runtime-errors.ts`; contradictions in SDK/native state remain defects.
12
8
  */
13
9
 
14
10
  /** A pure schema, query, parameter, or value-authoring refusal. */
package/src/fields.ts CHANGED
@@ -21,8 +21,8 @@ interface IntervalValue {
21
21
  }
22
22
 
23
23
  /**
24
- * A half-open dense float interval `[start, end)` as a plain value object
25
- * (chapter 11): two canonical binary64 bounds on the dense numeric line.
24
+ * A half-open dense float interval `[start, end)` as a plain value object:
25
+ * two canonical binary64 bounds on the dense numeric line.
26
26
  * NaN is never an endpoint, signed zero is normalized at the checked
27
27
  * constructor and again by the native boundary, and strict `start < end`
28
28
  * makes empty spans unrepresentable through {@link span}. Infinite bounds
@@ -35,8 +35,7 @@ interface FloatIntervalValue {
35
35
 
36
36
  /**
37
37
  * Constructs a checked interval literal — the `start..end` spelling.
38
- * Half-open and nonempty by construction. This is one of chapter 35's
39
- * "checked small interval constructors": genuinely fallible pure parsing
38
+ * Half-open and nonempty by construction. Fallible pure parsing
40
39
  * returns `Result` (use `Effect.fromResult(span(...))` inside a generator),
41
40
  * never hidden I/O and never a thrown domain outcome.
42
41
  *
@@ -109,7 +108,7 @@ interface F64Field {
109
108
  }
110
109
 
111
110
  /**
112
- * The application-owned 128-bit identity scalar (chapter 30/34): sixteen
111
+ * The application-owned 128-bit identity scalar: sixteen
113
112
  * exact bytes, spelled as the canonical hyphenated UUID {@link Uuid}
114
113
  * host value. There is no `fresh` mark anywhere: the database issues no
115
114
  * identity, and key laws are declared statements.
package/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @bjornpagen/bumbledb — the Effect-native TypeScript SDK for the
3
- * bumbledb embedded relational engine (chapter 35 surface). Pure
3
+ * bumbledb embedded relational engine. Pure
4
4
  * schema/query/scalar construction is synchronous metadata; all work is
5
5
  * lazy, scoped and bounded on the one native runtime. No Promise, sync,
6
6
  * or disposal twin. The raw native bridge is not exported from this barrel.
@@ -43,9 +43,10 @@ export type {
43
43
  ApplyOutcome,
44
44
  CoreWitness,
45
45
  DbInspection,
46
- ExecutionSession,
46
+ PreparedQuery,
47
47
  QueryReader,
48
- Snapshot
48
+ Snapshot,
49
+ StorageInspection
49
50
  } from "#db.ts"
50
51
  export { Db } from "#db.ts"
51
52
  export {
@@ -149,8 +150,8 @@ export type {
149
150
  export { relation } from "#relation.ts"
150
151
  export type { CompleteResult } from "#result.ts"
151
152
  export type { CellValue } from "#rows.ts"
152
- export { cellBytes, cellOf, factOfCells, flatRowsOf, keyCellsOf } from "#rows.ts"
153
- export type { ExecutionPolicy, NativeRuntimeOptions } from "#runtime.ts"
153
+ export { cellOf, factOfCells, flatRowsOf, keyCellsOf } from "#rows.ts"
154
+ export type { NativeRuntimeOptions } from "#runtime.ts"
154
155
  export { NativeRuntime } from "#runtime.ts"
155
156
  export type { CloseReport, OutstandingWork } from "#runtime-errors.ts"
156
157
  export { CloseFailure, DbError, dbError, runtimeErrorCodes } from "#runtime-errors.ts"
@@ -8,7 +8,7 @@ export type { ChangeDraft } from "#changes.ts"
8
8
  export { ChangeSet, internalChanges } from "#changes.ts"
9
9
  export type { CompiledSchema, SchemaId } from "#compile.ts"
10
10
  export { Schema } from "#compile.ts"
11
- export type { ExecutionSession, QueryReader } from "#db.ts"
11
+ export type { PreparedQuery, QueryReader } from "#db.ts"
12
12
  export { Db, internalPublishedReader } from "#db.ts"
13
13
  export type { SnapshotHandle } from "#db-native.ts"
14
14
  export { lower } from "#lower.ts"
@@ -21,31 +21,26 @@ export {
21
21
  nativeBindingIsLoaded
22
22
  } from "#native.ts"
23
23
  export type { CompleteResult } from "#result.ts"
24
- export type { ExecutionPolicy, NativeRuntimeOptions, RepositoryLock } from "#runtime.ts"
24
+ export type { NativeRuntimeOptions, RepositoryLock } from "#runtime.ts"
25
25
  export {
26
- deliveryResultBytes,
27
26
  finalizeClose,
28
27
  hashChunk,
29
28
  internalAcquireRepositoryLock,
30
29
  NativeRuntime,
31
30
  nativeOperation,
32
31
  nativeOperationWith,
33
- policyWire,
34
32
  runtimeHandle
35
33
  } from "#runtime.ts"
36
34
  export type { CloseReport, OutstandingWork } from "#runtime-errors.ts"
37
35
  export { CloseFailure, DbError, dbError, runtimeErrorCodes } from "#runtime-errors.ts"
38
36
  export type {
39
37
  Capability,
40
- CloseDrain,
41
38
  CloseWire,
42
39
  DirectoryHandle,
43
40
  InspectionWire,
44
41
  NativeKind,
45
42
  OperationHandle,
46
- PolicyWire,
47
43
  RepositoryLockHandle,
48
- ResourceHeader,
49
44
  RuntimeHandle
50
45
  } from "#runtime-native.ts"
51
46
  export { runtimeNative } from "#runtime-native.ts"
package/src/law.ts CHANGED
@@ -50,7 +50,7 @@ import { AuthoringError } from "#errors.ts"
50
50
  * widened type) — the runtime map stays complete and authoritative, and
51
51
  * the wire lowering reads only the runtime map. Every loop below is
52
52
  * tail-recursive with an accumulator, so the machinery rides TypeScript's
53
- * tail-recursion elimination at primer scale (~40 relations, ~200 slots,
53
+ * tail-recursion elimination for large schemas (~40 relations, ~200 slots,
54
54
  * ~123 statements); should a schema ever exceed the compiler's limits, tsc
55
55
  * fails LOUDLY with its own instantiation-depth error — the map is never
56
56
  * silently widened.