@bjornpagen/bumbledb 1.2.1 → 1.3.1

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 +240 -9
  2. package/README.md +9 -6
  3. package/dist/alternatives.d.ts +25 -0
  4. package/dist/alternatives.d.ts.map +1 -0
  5. package/dist/alternatives.js +59 -0
  6. package/dist/alternatives.js.map +1 -0
  7. package/dist/changes.d.ts +0 -1
  8. package/dist/changes.d.ts.map +1 -1
  9. package/dist/changes.js +2 -8
  10. package/dist/changes.js.map +1 -1
  11. package/dist/codec.d.ts +8 -1
  12. package/dist/codec.d.ts.map +1 -1
  13. package/dist/codec.js +29 -2
  14. package/dist/codec.js.map +1 -1
  15. package/dist/db-native.d.ts +2 -9
  16. package/dist/db-native.d.ts.map +1 -1
  17. package/dist/db-native.js.map +1 -1
  18. package/dist/index.d.ts +5 -4
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +2 -2
  21. package/dist/index.js.map +1 -1
  22. package/dist/internal/log.d.ts +4 -4
  23. package/dist/internal/log.d.ts.map +1 -1
  24. package/dist/internal/log.js +2 -2
  25. package/dist/internal/log.js.map +1 -1
  26. package/dist/native.d.ts +23 -9
  27. package/dist/native.d.ts.map +1 -1
  28. package/dist/native.js.map +1 -1
  29. package/dist/query/atom.d.ts +2 -1
  30. package/dist/query/atom.d.ts.map +1 -1
  31. package/dist/query/atom.js.map +1 -1
  32. package/dist/query/compute.d.ts +19 -4
  33. package/dist/query/compute.d.ts.map +1 -1
  34. package/dist/query/compute.js +17 -13
  35. package/dist/query/compute.js.map +1 -1
  36. package/dist/query/description.d.ts +10 -2
  37. package/dist/query/description.d.ts.map +1 -1
  38. package/dist/query/description.js +14 -5
  39. package/dist/query/description.js.map +1 -1
  40. package/dist/query/find.d.ts +13 -6
  41. package/dist/query/find.d.ts.map +1 -1
  42. package/dist/query/find.js +1 -1
  43. package/dist/query/find.js.map +1 -1
  44. package/dist/query/lower.d.ts +14 -2
  45. package/dist/query/lower.d.ts.map +1 -1
  46. package/dist/query/lower.js +64 -50
  47. package/dist/query/lower.js.map +1 -1
  48. package/dist/query/parse-ir.d.ts.map +1 -1
  49. package/dist/query/parse-ir.js +26 -3
  50. package/dist/query/parse-ir.js.map +1 -1
  51. package/dist/query/scope.d.ts.map +1 -1
  52. package/dist/query/scope.js +6 -1
  53. package/dist/query/scope.js.map +1 -1
  54. package/dist/query/segments.d.ts +20 -0
  55. package/dist/query/segments.d.ts.map +1 -0
  56. package/dist/query/segments.js +35 -0
  57. package/dist/query/segments.js.map +1 -0
  58. package/dist/runtime-codes.d.ts +1 -1
  59. package/dist/runtime-codes.d.ts.map +1 -1
  60. package/dist/runtime-codes.js +1 -0
  61. package/dist/runtime-codes.js.map +1 -1
  62. package/dist/runtime-errors.d.ts +23 -3
  63. package/dist/runtime-errors.d.ts.map +1 -1
  64. package/dist/runtime-errors.js +16 -3
  65. package/dist/runtime-errors.js.map +1 -1
  66. package/dist/runtime-native.d.ts +3 -8
  67. package/dist/runtime-native.d.ts.map +1 -1
  68. package/dist/runtime-native.js.map +1 -1
  69. package/dist/runtime.d.ts +0 -23
  70. package/dist/runtime.d.ts.map +1 -1
  71. package/dist/runtime.js +0 -36
  72. package/dist/runtime.js.map +1 -1
  73. package/dist/scalar.d.ts +46 -94
  74. package/dist/scalar.d.ts.map +1 -1
  75. package/dist/scalar.js +69 -156
  76. package/dist/scalar.js.map +1 -1
  77. package/dist/schema-file.d.ts +7 -0
  78. package/dist/schema-file.d.ts.map +1 -0
  79. package/dist/schema-file.js +24 -0
  80. package/dist/schema-file.js.map +1 -0
  81. package/pack-provenance.json +4 -4
  82. package/package.json +4 -4
  83. package/src/alternatives.ts +95 -0
  84. package/src/changes.ts +2 -8
  85. package/src/codec.ts +43 -3
  86. package/src/db-native.ts +2 -10
  87. package/src/index.ts +23 -6
  88. package/src/internal/log.ts +2 -4
  89. package/src/native.ts +21 -7
  90. package/src/query/atom.ts +2 -0
  91. package/src/query/compute.ts +46 -16
  92. package/src/query/description.ts +38 -8
  93. package/src/query/find.ts +37 -26
  94. package/src/query/lower.ts +89 -52
  95. package/src/query/parse-ir.ts +27 -3
  96. package/src/query/scope.ts +8 -1
  97. package/src/query/segments.ts +61 -0
  98. package/src/runtime-codes.ts +1 -0
  99. package/src/runtime-errors.ts +16 -3
  100. package/src/runtime-native.ts +1 -9
  101. package/src/runtime.ts +1 -70
  102. package/src/scalar.ts +138 -285
  103. package/src/schema-file.ts +38 -0
  104. package/dist/migration.d.ts +0 -31
  105. package/dist/migration.d.ts.map +0 -1
  106. package/dist/migration.js +0 -47
  107. package/dist/migration.js.map +0 -1
  108. package/src/migration.ts +0 -61
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-file.d.ts","sourceRoot":"","sources":["../src/schema-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAG/B,OAAO,EAAE,OAAO,EAAW,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAS1C,QAAA,MAAM,sBAAsB,2FAQ1B,CAAA;AAEF,QAAA,MAAM,sBAAsB,2FAY1B,CAAA;AAEF,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,CAAA"}
@@ -0,0 +1,24 @@
1
+ import { Effect } from "effect";
2
+ import { dbNative } from "#db-native.ts";
3
+ import { nativeOperationWith, runtimeHandle } from "#runtime.ts";
4
+ import { DbError, dbError } from "#runtime-errors.ts";
5
+ const decoder = new TextDecoder("utf-8", { fatal: true });
6
+ function text(operation, bytes) {
7
+ if (bytes === null)
8
+ throw dbError(operation, { _tag: "Internal" });
9
+ return decoder.decode(bytes);
10
+ }
11
+ const internalSchemaSnapshot = Effect.fn("internalSchemaSnapshot")(function* (spec) {
12
+ const runtime = yield* runtimeHandle();
13
+ return yield* nativeOperationWith("internalSchemaSnapshot", (callback) => dbNative.runtimeSchemaSnapshot(runtime, spec, callback), dbNative.runtimeBytesTake, (bytes) => text("internalSchemaSnapshot", bytes));
14
+ });
15
+ const internalSchemaBindings = Effect.fn("internalSchemaBindings")(function* (snapshot) {
16
+ if (typeof snapshot !== "string" || !snapshot.isWellFormed()) {
17
+ return yield* Effect.fail(new DbError({ operation: "internalSchemaBindings", reason: { _tag: "InvalidArgument" } }));
18
+ }
19
+ const runtime = yield* runtimeHandle();
20
+ const bytes = new TextEncoder().encode(snapshot);
21
+ return yield* nativeOperationWith("internalSchemaBindings", (callback) => dbNative.runtimeSchemaBindings(runtime, bytes, callback), dbNative.runtimeBytesTake, (bytes) => text("internalSchemaBindings", bytes));
22
+ });
23
+ export { internalSchemaBindings, internalSchemaSnapshot };
24
+ //# sourceMappingURL=schema-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-file.js","sourceRoot":"","sources":["../src/schema-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAGrD,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;AAEzD,SAAS,IAAI,CAAC,SAAiB,EAAE,KAAwB;IACxD,IAAI,KAAK,KAAK,IAAI;QAAE,MAAM,OAAO,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAA;IAClE,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC7B,CAAC;AAED,MAAM,sBAAsB,GAAG,MAAM,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAgB;IAC7F,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,aAAa,EAAE,CAAA;IACtC,OAAO,KAAK,CAAC,CAAC,mBAAmB,CAChC,wBAAwB,EACxB,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,EACrE,QAAQ,CAAC,gBAAgB,EACzB,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAChD,CAAA;AACF,CAAC,CAAC,CAAA;AAEF,MAAM,sBAAsB,GAAG,MAAM,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,QAAQ,CAAC,EAAE,QAAgB;IAC7F,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,CAAC;QAC9D,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,EAAE,SAAS,EAAE,wBAAwB,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC,CAAA;IACrH,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,aAAa,EAAE,CAAA;IACtC,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAChD,OAAO,KAAK,CAAC,CAAC,mBAAmB,CAChC,wBAAwB,EACxB,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,EACtE,QAAQ,CAAC,gBAAgB,EACzB,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAChD,CAAA;AACF,CAAC,CAAC,CAAA;AAEF,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,CAAA"}
@@ -1,7 +1,7 @@
1
1
  {
2
- "candidateSourceDigest": "ca9592096bd15b3f2a56e586a074505ae6695befdad7ed4df816af59a0ae1bf5",
3
- "specificationRevision": "87e9a83ee21d1f843c73ac6e7057b2b740db75aae70a553b8053b4f38e87bd2d",
4
- "stagedAt": "2026-09-11T13:37:03.509Z",
2
+ "candidateSourceDigest": "7109ef17978c17a195301260c8b4cd2736ce785646c46c61d61bf7850c4299da",
3
+ "specificationRevision": "91f64ebf5ccf285a072aeff41ca364d1e837259e4273f9be12a0a5959c38a45e",
4
+ "stagedAt": "2026-09-12T00:04:00.990Z",
5
5
  "package": "@bjornpagen/bumbledb",
6
- "version": "1.2.1"
6
+ "version": "1.3.1"
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bjornpagen/bumbledb",
3
- "version": "1.2.1",
3
+ "version": "1.3.1",
4
4
  "description": "Effect-native embedded relational database for TypeScript: typed schemas and queries, exact floats, commit-time constraints",
5
5
  "type": "module",
6
6
  "exports": {
@@ -57,8 +57,8 @@
57
57
  },
58
58
  "private": false,
59
59
  "optionalDependencies": {
60
- "@bjornpagen/bumbledb-darwin-arm64": "1.2.1",
61
- "@bjornpagen/bumbledb-linux-arm64": "1.2.1",
62
- "@bjornpagen/bumbledb-linux-x64": "1.2.1"
60
+ "@bjornpagen/bumbledb-darwin-arm64": "1.3.1",
61
+ "@bjornpagen/bumbledb-linux-arm64": "1.3.1",
62
+ "@bjornpagen/bumbledb-linux-x64": "1.3.1"
63
63
  }
64
64
  }
@@ -0,0 +1,95 @@
1
+ import { type AnyClosed, closedDescriptor, closedId, sealedFieldOf } from "#closed.ts"
2
+ import { AuthoringError } from "#errors.ts"
3
+ import type { Face, SameArity, SameShapes } from "#face.ts"
4
+ import { type ClosedIdField, signaturesAgree } from "#fields.ts"
5
+ import type { RelationFields } from "#relation.ts"
6
+ import {
7
+ type ContainmentStatement,
8
+ type KeyStatement,
9
+ type MirrorsStatement,
10
+ statementDescriptor
11
+ } from "#statements.ts"
12
+ import { recordValue } from "#values.ts"
13
+
14
+ type KeyFace<K extends KeyStatement> = Face<K["owner"], K["projection"]>
15
+ type ScalarKey<K extends KeyStatement> =
16
+ Extract<RelationFields<K["owner"]>[K["projection"][number]], { readonly kind: "interval" }> extends never
17
+ ? unknown
18
+ : { readonly "alternative identity keys must be scalar": never }
19
+ type Discriminator<P extends KeyStatement, C extends AnyClosed> = {
20
+ [F in keyof RelationFields<P["owner"]>]: RelationFields<P["owner"]>[F] extends ClosedIdField<C["name"], C["handles"]>
21
+ ? F
22
+ : never
23
+ }[keyof RelationFields<P["owner"]>] &
24
+ string
25
+
26
+ function scalarKey(input: KeyStatement): KeyStatement {
27
+ const checked = statementDescriptor(input)
28
+ if (checked.kind !== "key") throw new AuthoringError({ message: "alternatives: expected a key statement" })
29
+ for (const name of checked.projection) {
30
+ if (sealedFieldOf(checked.owner, name)?.kind === "interval")
31
+ throw new AuthoringError({
32
+ message: "alternatives: identity keys must be scalar; interval keys prove point coverage"
33
+ })
34
+ }
35
+ return checked
36
+ }
37
+
38
+ /**
39
+ * Exhaustive closed alternatives, expanded into ordinary laws. Declare the
40
+ * supplied keys in the schema once; this helper emits only the discriminator
41
+ * containment followed by one mirrors statement per handle in roster order.
42
+ * No new statement kind or assembled payload representation is introduced.
43
+ */
44
+ function alternatives<
45
+ P extends KeyStatement,
46
+ C extends AnyClosed,
47
+ const Arms extends Record<C["handles"][number], KeyStatement>
48
+ >(
49
+ parent: P & ScalarKey<P>,
50
+ discriminator: Discriminator<NoInfer<P>, NoInfer<C>>,
51
+ roster: C,
52
+ arms: Arms &
53
+ Record<Exclude<keyof Arms, C["handles"][number]>, never> & {
54
+ readonly [H in C["handles"][number]]: ScalarKey<Arms[H]> &
55
+ SameArity<KeyFace<P>, KeyFace<Arms[H]>> &
56
+ SameShapes<KeyFace<P>, KeyFace<Arms[H]>>
57
+ }
58
+ ): readonly (ContainmentStatement | MirrorsStatement)[] {
59
+ const primary = scalarKey(parent)
60
+ const closed = closedDescriptor(roster)
61
+ const field = sealedFieldOf(primary.owner, discriminator)
62
+ if (field === undefined || !signaturesAgree(field, closedId(closed)))
63
+ throw new AuthoringError({ message: "alternatives: discriminator must reference the supplied closed roster" })
64
+ const payloads = recordValue("alternative arms", arms, closed.handles)
65
+ const statements: (ContainmentStatement | MirrorsStatement)[] = [
66
+ statementDescriptor({
67
+ kind: "containment",
68
+ source: { owner: primary.owner, projection: [discriminator], selection: [] },
69
+ target: { owner: closed, projection: ["id"], selection: [] }
70
+ })
71
+ ]
72
+ const children = new Set<string>([primary.owner.name])
73
+ for (const handle of closed.handles) {
74
+ const child = scalarKey(payloads[handle] as KeyStatement)
75
+ if (children.has(child.owner.name))
76
+ throw new AuthoringError({
77
+ message: `alternatives: each arm needs its own payload relation (${child.owner.name})`
78
+ })
79
+ children.add(child.owner.name)
80
+ statements.push(
81
+ statementDescriptor({
82
+ kind: "mirrors",
83
+ source: {
84
+ owner: primary.owner,
85
+ projection: primary.projection,
86
+ selection: [{ field: discriminator, set: { kind: "one", literal: { kind: "handle", handle } } }]
87
+ },
88
+ target: { owner: child.owner, projection: child.projection, selection: [] }
89
+ })
90
+ )
91
+ }
92
+ return Object.freeze(statements)
93
+ }
94
+
95
+ export { alternatives }
package/src/changes.ts CHANGED
@@ -93,7 +93,6 @@ interface DraftState {
93
93
  interface ChangesInternal {
94
94
  readonly handle: ChangesHandle
95
95
  readonly schemaId: SchemaId
96
- closed: boolean
97
96
  }
98
97
 
99
98
  const changesInternals = new WeakMap<object, ChangesInternal>()
@@ -320,7 +319,6 @@ function acquireChanges<S extends AnySchema>(
320
319
  Effect.suspend(() => {
321
320
  const internal = changesInternals.get(changes)
322
321
  if (internal === undefined) return Effect.void
323
- internal.closed = true
324
322
  return releaseOwner("ChangeSet.close", (callback) => dbNative.runtimeChangesClose(internal.handle, callback))
325
323
  }),
326
324
  { interruptible: true }
@@ -330,7 +328,7 @@ function acquireChanges<S extends AnySchema>(
330
328
  function makeChangeSet<S extends AnySchema>(theory: S, wire: ChangesWire, schemaId: SchemaId): ChangeSet<S> {
331
329
  const handle = wire.changes
332
330
  const relations = Object.values(theory.relations)
333
- const internal: ChangesInternal = { handle, schemaId, closed: false }
331
+ const internal: ChangesInternal = { handle, schemaId }
334
332
  const value: ChangeSet<S> = {
335
333
  schemaId,
336
334
  counts: Object.freeze({ ...wire.counts }),
@@ -351,7 +349,6 @@ function makeChangeSet<S extends AnySchema>(theory: S, wire: ChangesWire, schema
351
349
  const right = internalChanges(other)
352
350
  if (right === undefined || right.schemaId !== schemaId)
353
351
  return Effect.fail(refusal("ChangeSet.compose", "InvalidArgument"))
354
- if (internal.closed || right.closed) return Effect.fail(refusal("ChangeSet.compose", "ClosedHandle"))
355
352
  return acquireChanges(
356
353
  theory,
357
354
  schemaId,
@@ -365,10 +362,7 @@ function makeChangeSet<S extends AnySchema>(theory: S, wire: ChangesWire, schema
365
362
  })
366
363
  },
367
364
  close() {
368
- return Effect.suspend(() => {
369
- internal.closed = true
370
- return drainClose("ChangeSet.close", (callback) => dbNative.runtimeChangesClose(handle, callback))
371
- })
365
+ return drainClose("ChangeSet.close", (callback) => dbNative.runtimeChangesClose(handle, callback))
372
366
  }
373
367
  }
374
368
  Object.freeze(value)
package/src/codec.ts CHANGED
@@ -3,7 +3,7 @@ import { membersAgree } from "#closed.ts"
3
3
  import { schemaTables } from "#compile.ts"
4
4
  import { dbNative } from "#db-native.ts"
5
5
  import { AuthoringError } from "#errors.ts"
6
- import type { AnyField } from "#fields.ts"
6
+ import { type AnyField, fieldDescriptor, type Infer } from "#fields.ts"
7
7
  import { lower } from "#lower.ts"
8
8
  import { type AnyRelation, type Fact, relationDescriptor, relationFields } from "#relation.ts"
9
9
  import type { CellValue } from "#rows.ts"
@@ -141,7 +141,8 @@ function decodeTaggedF64(value: unknown): number | undefined {
141
141
  }
142
142
 
143
143
  /** Decode representation, then judge the value through the shared interpreter. */
144
- function decodeBoundaryValue(context: string, field: AnyField, input: unknown): unknown {
144
+ function decodeBoundaryValue<F extends AnyField>(context: string, field: F, input: unknown): Infer<F>
145
+ function decodeBoundaryValue(context: string, field: AnyField, input: unknown): Infer<AnyField> {
145
146
  if ("closed" in field) return fieldValue(context, field, input)
146
147
  let decoded: unknown = input
147
148
  switch (field.kind) {
@@ -167,6 +168,35 @@ function decodeBoundaryValue(context: string, field: AnyField, input: unknown):
167
168
  return fieldValue(context, field, decoded)
168
169
  }
169
170
 
171
+ /** The host-value schema, using the same interpreter as facts and row codecs. */
172
+ function fieldSchema<F extends AnyField>(field: F) {
173
+ const descriptor = fieldDescriptor("fieldSchema", field)
174
+ return EffectSchema.declare((value: unknown): value is Infer<F> => {
175
+ try {
176
+ fieldValue("fieldSchema", descriptor, value)
177
+ return true
178
+ } catch {
179
+ return false
180
+ }
181
+ })
182
+ }
183
+
184
+ /** Encode one field's host value in the canonical JSON-boundary form. */
185
+ function encodeBoundaryField<F extends AnyField>(field: F, value: Infer<F>): Result.Result<unknown, DbError> {
186
+ return Result.try({
187
+ try: () => encodeBoundaryValue("encodeBoundaryField", fieldDescriptor("encodeBoundaryField", field), value),
188
+ catch: (cause) => argumentError("encodeBoundaryField", cause)
189
+ })
190
+ }
191
+
192
+ /** Strict JSON-boundary decoding, returning the field's canonical host value. */
193
+ function decodeBoundaryField<F extends AnyField>(field: F, input: unknown): Result.Result<Infer<F>, DbError> {
194
+ return Result.try({
195
+ try: () => decodeBoundaryValue("decodeBoundaryField", fieldDescriptor("decodeBoundaryField", field), input),
196
+ catch: (cause) => argumentError("decodeBoundaryField", cause)
197
+ })
198
+ }
199
+
170
200
  /** Pure schema-tagged JSON encoding of complete rows. */
171
201
  function encodeBoundaryRows<R extends AnyRelation>(
172
202
  relation: R,
@@ -286,4 +316,14 @@ const decodeRows = Effect.fn("decodeRows")(function* <R extends AnyRelation>(sha
286
316
  })
287
317
 
288
318
  export type { RowShape }
289
- export { decodeBoundaryRows, decodeRows, encodeBoundaryRows, encodeRows, rowSchema, rowShape }
319
+ export {
320
+ decodeBoundaryField,
321
+ decodeBoundaryRows,
322
+ decodeRows,
323
+ encodeBoundaryField,
324
+ encodeBoundaryRows,
325
+ encodeRows,
326
+ fieldSchema,
327
+ rowSchema,
328
+ rowShape
329
+ }
package/src/db-native.ts CHANGED
@@ -226,16 +226,8 @@ interface DbBridge {
226
226
  bytes: Uint8Array,
227
227
  callback: () => void
228
228
  ): OperationHandle
229
-
230
- /**
231
- * Read-only migration-codec integration over native `schema_file` and
232
- * `migration::{plan, manifest}` through the shared executor: bounded
233
- * owned input, bounded owned JSON response bytes, one registered
234
- * cancellable operation. Neither verb opens, initializes, freezes or
235
- * migrates a database.
236
- */
237
- runtimeMigrationSchema(runtime: RuntimeHandle, spec: SchemaSpec, callback: () => void): OperationHandle
238
- runtimeMigrationRead(runtime: RuntimeHandle, request: Uint8Array, callback: () => void): OperationHandle
229
+ runtimeSchemaSnapshot(runtime: RuntimeHandle, spec: SchemaSpec, callback: () => void): OperationHandle
230
+ runtimeSchemaBindings(runtime: RuntimeHandle, snapshot: Uint8Array, callback: () => void): OperationHandle
239
231
  }
240
232
 
241
233
  // The fresh-addon roster test pins this private declaration exactly as it
package/src/index.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  * or disposal twin. The raw native bridge is not exported from this barrel.
7
7
  */
8
8
 
9
+ export { alternatives } from "#alternatives.ts"
9
10
  export type {
10
11
  BoundsOnTarget,
11
12
  CapacityWeight,
@@ -27,7 +28,17 @@ export type {
27
28
  } from "#closed.ts"
28
29
  export { closed, closedId } from "#closed.ts"
29
30
  export type { RowShape } from "#codec.ts"
30
- export { decodeBoundaryRows, decodeRows, encodeBoundaryRows, encodeRows, rowSchema, rowShape } from "#codec.ts"
31
+ export {
32
+ decodeBoundaryField,
33
+ decodeBoundaryRows,
34
+ decodeRows,
35
+ encodeBoundaryField,
36
+ encodeBoundaryRows,
37
+ encodeRows,
38
+ fieldSchema,
39
+ rowSchema,
40
+ rowShape
41
+ } from "#codec.ts"
31
42
  export type { CompiledSchema, SchemaId } from "#compile.ts"
32
43
  export { Schema } from "#compile.ts"
33
44
  export type {
@@ -112,7 +123,13 @@ export type { FindColumn } from "#query/atom.ts"
112
123
  export { ALLEN } from "#query/atom.ts"
113
124
  export type { AnyComputeExpr, ComputeExpr, ComputeValue, QueryNode } from "#query/compute.ts"
114
125
  export { Compute } from "#query/compute.ts"
115
- export type { DescriptionParameter, DescriptionRow, DescriptionTable, QueryDescription } from "#query/description.ts"
126
+ export type {
127
+ DescriptionHead,
128
+ DescriptionParameter,
129
+ DescriptionRow,
130
+ DescriptionTable,
131
+ QueryDescription
132
+ } from "#query/description.ts"
116
133
  export { describeQuery, queryFromDescription } from "#query/description.ts"
117
134
  export type { Agg, HeadRecordOf, RowOfFind } from "#query/find.ts"
118
135
  export type {
@@ -147,6 +164,7 @@ export type {
147
164
  VarsOf
148
165
  } from "#query/scope.ts"
149
166
  export { v } from "#query/scope.ts"
167
+ export type { IntervalVar, SegmentOp, Segments } from "#query/segments.ts"
150
168
  export type {
151
169
  AnyRelation,
152
170
  Fact,
@@ -164,17 +182,16 @@ export { NativeRuntime } from "#runtime.ts"
164
182
  export type { CloseReport, OutstandingWork } from "#runtime-errors.ts"
165
183
  export { CloseFailure, DbError, dbError, runtimeErrorCodes } from "#runtime-errors.ts"
166
184
  export type {
185
+ IntervalKind,
167
186
  NumericCast,
168
- ScalarExpr,
169
- ScalarFieldRef,
187
+ Rounding,
188
+ ScalarInputKind,
170
189
  ScalarKind,
171
- ScalarLeafScope,
172
190
  ScalarLiteral,
173
191
  ScalarNode,
174
192
  ScalarResultKind,
175
193
  ScalarValue
176
194
  } from "#scalar.ts"
177
- export { Scalar } from "#scalar.ts"
178
195
  export type { AnySchema, Schema as SchemaDeclaration, SchemaRelation, SchemaRelations } from "#schema.ts"
179
196
  export { schema } from "#schema.ts"
180
197
  export type { AnySelected, FieldsOf, Selected, SelectionBinding, SelectionInput } from "#selection.ts"
@@ -12,7 +12,6 @@ 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"
15
- export { internalMigrationRead, internalMigrationSchema } from "#migration.ts"
16
15
  export {
17
16
  internalBlake3,
18
17
  internalDescriptor,
@@ -22,11 +21,10 @@ export {
22
21
  } from "#native.ts"
23
22
  export type { CompleteResult } from "#result.ts"
24
23
  export { factCellsOf } from "#rows.ts"
25
- export type { NativeRuntimeOptions, RepositoryLock } from "#runtime.ts"
24
+ export type { NativeRuntimeOptions } from "#runtime.ts"
26
25
  export {
27
26
  finalizeClose,
28
27
  hashChunk,
29
- internalAcquireRepositoryLock,
30
28
  NativeRuntime,
31
29
  nativeOperation,
32
30
  nativeOperationWith,
@@ -41,8 +39,8 @@ export type {
41
39
  InspectionWire,
42
40
  NativeKind,
43
41
  OperationHandle,
44
- RepositoryLockHandle,
45
42
  RuntimeHandle
46
43
  } from "#runtime-native.ts"
47
44
  export { runtimeNative } from "#runtime-native.ts"
48
45
  export { schemasAgree } from "#schema.ts"
46
+ export { internalSchemaBindings, internalSchemaSnapshot } from "#schema-file.ts"
package/src/native.ts CHANGED
@@ -82,13 +82,21 @@ type HeadOpIr = "sum" | "mean" | "min" | "max" | "count" | "pack"
82
82
 
83
83
  /**
84
84
  * The computed-find scalar expression (C05 `FindTerm::Compute(ScalarExpr)`):
85
- * exactly the frozen core roster, spelled as the migration plan JSON spells
85
+ * exactly the frozen core roster, spelled as the canonical scalar JSON spells
86
86
  * the same expressions (one grammar, no second evaluator). `var` binds a
87
87
  * rule variable ordinal on this lane.
88
88
  */
89
89
  type NumericCastIr = "toF64" | "toF64Exact" | "toI64Exact" | "toU64Exact"
90
90
 
91
91
  type ScalarExprIr =
92
+ | { readonly kind: "measure"; readonly expr: ScalarExprIr }
93
+ | {
94
+ readonly kind: "mulDiv"
95
+ readonly a: ScalarExprIr
96
+ readonly b: ScalarExprIr
97
+ readonly divisor: ScalarExprIr
98
+ readonly rounding: import("#scalar.ts").Rounding
99
+ }
92
100
  | { readonly kind: "var"; readonly var: number }
93
101
  | { readonly kind: "literal"; readonly value: TaggedValue }
94
102
  | { readonly kind: "negate"; readonly expr: ScalarExprIr }
@@ -114,6 +122,12 @@ type FoldOpIr =
114
122
  | { readonly kind: "max" }
115
123
 
116
124
  type FindTermIr =
125
+ | {
126
+ readonly kind: "segments"
127
+ readonly op: import("#query/segments.ts").SegmentOp
128
+ readonly left: number
129
+ readonly right: number
130
+ }
117
131
  | { readonly kind: "var"; readonly var: number }
118
132
  | { readonly kind: "compute"; readonly expr: ScalarExprIr }
119
133
  | { readonly kind: "count" }
@@ -280,7 +294,7 @@ type LogAccess =
280
294
  readonly operation: string
281
295
  readonly intent:
282
296
  | { readonly kind: "erasure" }
283
- | { readonly kind: "migration"; readonly planSetDigest: Uint8Array; readonly target: string }
297
+ | { readonly kind: "transition"; readonly contractDigest: Uint8Array; readonly target: string }
284
298
  }
285
299
 
286
300
  type LogLifecycle =
@@ -297,10 +311,10 @@ type LogLifecycle =
297
311
  readonly reason:
298
312
  | { readonly kind: "erasure" }
299
313
  | {
300
- readonly kind: "migrationAborted"
314
+ readonly kind: "transitionAborted"
301
315
  readonly sourceDatabase: string
302
316
  readonly sourceIncarnation: string
303
- readonly planSetDigest: Uint8Array
317
+ readonly contractDigest: Uint8Array
304
318
  }
305
319
  }
306
320
 
@@ -313,7 +327,7 @@ type LogActivation =
313
327
  readonly cause:
314
328
  | { readonly kind: "create" }
315
329
  | { readonly kind: "restore" }
316
- | { readonly kind: "migration"; readonly planSetDigest: Uint8Array }
330
+ | { readonly kind: "transition"; readonly contractDigest: Uint8Array }
317
331
  }
318
332
 
319
333
  interface LogAuthority {
@@ -327,10 +341,10 @@ type LogGenesisProvenance =
327
341
  | { readonly kind: "create" }
328
342
  | { readonly kind: "restore"; readonly sourceEvidence: Uint8Array }
329
343
  | {
330
- readonly kind: "migration"
344
+ readonly kind: "transition"
331
345
  readonly sourceDatabase: string
332
346
  readonly sourceIncarnation: string
333
- readonly planSetDigest: Uint8Array
347
+ readonly contractDigest: Uint8Array
334
348
  }
335
349
 
336
350
  interface LogGenesis {
package/src/query/atom.ts CHANGED
@@ -16,6 +16,7 @@ import type {
16
16
  ShapeOf
17
17
  } from "#query/scope.ts"
18
18
  import { isTerm, term } from "#query/scope.ts"
19
+ import type { Segments } from "#query/segments.ts"
19
20
  import type { FieldsShape } from "#relation.ts"
20
21
  import type { ScalarKind } from "#scalar.ts"
21
22
  import type { Uuid } from "#uuid.ts"
@@ -75,6 +76,7 @@ type AggData =
75
76
 
76
77
  /** Compute `expr` is the shared `#scalar.ts` query-var node (one grammar). */
77
78
  type FindEntryData =
79
+ | Segments
78
80
  | { readonly kind: "var"; readonly over: AnyVar }
79
81
  | { readonly kind: "aggregate"; readonly agg: AggData }
80
82
  | { readonly kind: "compute"; readonly expr: QueryNode; readonly result: ScalarKind }
@@ -1,19 +1,11 @@
1
- /**
2
- * Query-scoped scalar expressions (C05 `FindTerm::Compute`): the
3
- * variable-addressed leaf scope over the ONE shared operator roster in
4
- * `#scalar.ts`. Leaves are bound query variables that lower to `VarId`s.
5
- * Operators are the shared constructors — this module only admits known
6
- * schema kinds at query-var leaves.
7
- *
8
- * `ComputeExpr<K>` is a `ScalarNode<"query-var", K>`. Distinct I64 and U64
9
- * survive host inference; they do not collapse to plain `bigint`.
10
- */
1
+ /** Query scalar expressions use the same nodes that native preparation reads.
2
+ * Distinct i64 and u64 kinds survive TypeScript's shared bigint carrier. */
11
3
  import { AuthoringError } from "#errors.ts"
12
4
  import type { AnyField } from "#fields.ts"
13
5
  import { bool as boolField, f64 as f64Field, i64 as i64Field, rosterOf, u64 as u64Field } from "#fields.ts"
14
6
  import type { AnyVar } from "#query/scope.ts"
15
7
  import { isTerm, term } from "#query/scope.ts"
16
- import type { ScalarKind, ScalarLiteral, ScalarNode } from "#scalar.ts"
8
+ import type { Rounding, ScalarKind, ScalarLiteral, ScalarNode } from "#scalar.ts"
17
9
  import {
18
10
  checkBool,
19
11
  checkF64,
@@ -27,16 +19,18 @@ import {
27
19
  scalarCast,
28
20
  scalarFloatPredicate,
29
21
  scalarLiteral,
22
+ scalarMeasure,
23
+ scalarMulDiv,
30
24
  scalarNegate
31
25
  } from "#scalar.ts"
32
26
 
33
- /** Query-var tree: the shared AST restricted to this leaf scope. */
34
- type QueryNode = ScalarNode<"query-var">
27
+ /** Query expression, including interval leaves consumed by measure. */
28
+ type QueryNode = ScalarNode
35
29
 
36
30
  /** Host value for a derived query compute kind. */
37
31
  type ComputeValue<K extends ScalarKind> = K extends "f64" ? number : K extends "bool" ? boolean : bigint
38
32
 
39
- type ComputeExpr<K extends ScalarKind> = ScalarNode<"query-var", K>
33
+ type ComputeExpr<K extends ScalarKind> = ScalarNode<K>
40
34
 
41
35
  type AnyComputeExpr = ComputeExpr<"u64"> | ComputeExpr<"i64"> | ComputeExpr<"f64"> | ComputeExpr<"bool">
42
36
 
@@ -61,7 +55,10 @@ type OperandKind<O> =
61
55
  : never
62
56
 
63
57
  function isComputeExpr(value: unknown): value is AnyComputeExpr {
64
- return isScalarNode(value) && value.scope === "query-var" && value.result !== "unresolved"
58
+ return (
59
+ isScalarNode(value) &&
60
+ (value.result === "u64" || value.result === "i64" || value.result === "f64" || value.result === "bool")
61
+ )
65
62
  }
66
63
 
67
64
  function varKindOf(where: string, ref: AnyVar): ScalarKind {
@@ -93,7 +90,7 @@ function asQueryNode(where: string, operand: Operand): QueryNode {
93
90
  }
94
91
 
95
92
  function literal<K extends ScalarKind>(value: ScalarLiteral): ComputeExpr<K> {
96
- return scalarLiteral("query-var", value) as ComputeExpr<K>
93
+ return scalarLiteral(value) as ComputeExpr<K>
97
94
  }
98
95
 
99
96
  function u64(value: bigint): ComputeExpr<"u64"> {
@@ -167,6 +164,37 @@ function negate<O extends SignedOperand>(operand: O): ComputeExpr<OperandKind<O>
167
164
  return scalarNegate(where, asQueryNode(where, operand)) as ComputeExpr<OperandKind<O> & ("i64" | "f64")>
168
165
  }
169
166
 
167
+ type IntegerOperand =
168
+ | ComputeExpr<"u64">
169
+ | ComputeExpr<"i64">
170
+ | (AnyVar & { readonly field: { readonly kind: "i64" | "u64" } })
171
+
172
+ function mulDiv<A extends IntegerOperand, B extends IntegerOperand, D extends IntegerOperand>(
173
+ a: A,
174
+ b: B & (OperandKind<A> extends OperandKind<B> ? unknown : never),
175
+ divisor: D & (OperandKind<A> extends OperandKind<D> ? unknown : never),
176
+ rounding: Rounding
177
+ ): ComputeExpr<OperandKind<A>> {
178
+ return scalarMulDiv(
179
+ "Compute.mulDiv",
180
+ asQueryNode("Compute.mulDiv", a),
181
+ asQueryNode("Compute.mulDiv", b),
182
+ asQueryNode("Compute.mulDiv", divisor),
183
+ rounding
184
+ ) as ComputeExpr<OperandKind<A>>
185
+ }
186
+
187
+ function measure<V extends AnyVar & { readonly field: { readonly kind: "interval" } }>(
188
+ interval: V
189
+ ): ComputeExpr<V["field"] extends { readonly element: "f64" } ? "f64" : "u64"> {
190
+ if (!isTerm(interval) || interval[term] !== "var" || interval.field.kind !== "interval")
191
+ throw new AuthoringError({ message: "Compute.measure: expected an interval variable" })
192
+ const kind = { u64: "intervalU64", i64: "intervalI64", f64: "intervalF64" } as const
193
+ return scalarMeasure("Compute.measure", queryVarLeaf(interval, kind[interval.field.element])) as ComputeExpr<
194
+ V["field"] extends { readonly element: "f64" } ? "f64" : "u64"
195
+ >
196
+ }
197
+
170
198
  function toF64(operand: ArithmeticOperand): ComputeExpr<"f64"> {
171
199
  const where = "Compute.toF64"
172
200
  return scalarCast(where, "toF64", "f64", asQueryNode(where, operand)) as ComputeExpr<"f64">
@@ -225,6 +253,8 @@ const Compute = Object.freeze({
225
253
  subtract,
226
254
  multiply,
227
255
  divide,
256
+ mulDiv,
257
+ measure,
228
258
  toF64,
229
259
  toF64Exact,
230
260
  toI64Exact,