@bjornpagen/bumbledb 1.3.0 → 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 (86) hide show
  1. package/COOKBOOK.md +72 -19
  2. package/README.md +9 -6
  3. package/dist/changes.d.ts +0 -1
  4. package/dist/changes.d.ts.map +1 -1
  5. package/dist/changes.js +2 -8
  6. package/dist/changes.js.map +1 -1
  7. package/dist/codec.d.ts +8 -1
  8. package/dist/codec.d.ts.map +1 -1
  9. package/dist/codec.js +29 -2
  10. package/dist/codec.js.map +1 -1
  11. package/dist/db-native.d.ts +2 -9
  12. package/dist/db-native.d.ts.map +1 -1
  13. package/dist/db-native.js.map +1 -1
  14. package/dist/index.d.ts +2 -3
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +1 -2
  17. package/dist/index.js.map +1 -1
  18. package/dist/internal/log.d.ts +4 -4
  19. package/dist/internal/log.d.ts.map +1 -1
  20. package/dist/internal/log.js +2 -2
  21. package/dist/internal/log.js.map +1 -1
  22. package/dist/native.d.ts +9 -9
  23. package/dist/native.d.ts.map +1 -1
  24. package/dist/query/compute.d.ts +3 -3
  25. package/dist/query/compute.d.ts.map +1 -1
  26. package/dist/query/compute.js +3 -12
  27. package/dist/query/compute.js.map +1 -1
  28. package/dist/query/description.js +4 -4
  29. package/dist/query/description.js.map +1 -1
  30. package/dist/query/lower.d.ts +11 -2
  31. package/dist/query/lower.d.ts.map +1 -1
  32. package/dist/query/lower.js +31 -26
  33. package/dist/query/lower.js.map +1 -1
  34. package/dist/query/parse-ir.d.ts.map +1 -1
  35. package/dist/query/parse-ir.js +4 -4
  36. package/dist/query/parse-ir.js.map +1 -1
  37. package/dist/query/scope.d.ts.map +1 -1
  38. package/dist/query/scope.js +6 -1
  39. package/dist/query/scope.js.map +1 -1
  40. package/dist/runtime-codes.d.ts +1 -1
  41. package/dist/runtime-codes.d.ts.map +1 -1
  42. package/dist/runtime-codes.js +1 -0
  43. package/dist/runtime-codes.js.map +1 -1
  44. package/dist/runtime-errors.d.ts +23 -3
  45. package/dist/runtime-errors.d.ts.map +1 -1
  46. package/dist/runtime-errors.js +16 -3
  47. package/dist/runtime-errors.js.map +1 -1
  48. package/dist/runtime-native.d.ts +3 -8
  49. package/dist/runtime-native.d.ts.map +1 -1
  50. package/dist/runtime-native.js.map +1 -1
  51. package/dist/runtime.d.ts +0 -23
  52. package/dist/runtime.d.ts.map +1 -1
  53. package/dist/runtime.js +0 -36
  54. package/dist/runtime.js.map +1 -1
  55. package/dist/scalar.d.ts +34 -104
  56. package/dist/scalar.d.ts.map +1 -1
  57. package/dist/scalar.js +12 -177
  58. package/dist/scalar.js.map +1 -1
  59. package/dist/schema-file.d.ts +7 -0
  60. package/dist/schema-file.d.ts.map +1 -0
  61. package/dist/schema-file.js +24 -0
  62. package/dist/schema-file.js.map +1 -0
  63. package/pack-provenance.json +4 -4
  64. package/package.json +4 -4
  65. package/src/changes.ts +2 -8
  66. package/src/codec.ts +43 -3
  67. package/src/db-native.ts +2 -10
  68. package/src/index.ts +11 -5
  69. package/src/internal/log.ts +2 -4
  70. package/src/native.ts +7 -7
  71. package/src/query/compute.ts +6 -15
  72. package/src/query/description.ts +4 -4
  73. package/src/query/lower.ts +56 -25
  74. package/src/query/parse-ir.ts +6 -4
  75. package/src/query/scope.ts +8 -1
  76. package/src/runtime-codes.ts +1 -0
  77. package/src/runtime-errors.ts +16 -3
  78. package/src/runtime-native.ts +1 -9
  79. package/src/runtime.ts +1 -70
  80. package/src/scalar.ts +49 -329
  81. package/src/schema-file.ts +38 -0
  82. package/dist/migration.d.ts +0 -31
  83. package/dist/migration.d.ts.map +0 -1
  84. package/dist/migration.js +0 -47
  85. package/dist/migration.js.map +0 -1
  86. package/src/migration.ts +0 -61
package/src/scalar.ts CHANGED
@@ -1,34 +1,16 @@
1
- /**
2
- * The ONE leaf-scoped scalar AST (C1/C8): one tagged literal grammar and
3
- * operator roster, parameterized by {@link ScalarLeafScope}. TypeScript never
4
- * evaluates — the native compiler binds source fields and the engine
5
- * `ScalarEvaluator` executes. Construction is constant work against cached
6
- * depth/kind summaries; it does not re-walk the tree.
7
- *
8
- * Query-var leaves carry a known schema kind. Source-field leaves stay
9
- * `unresolved` until native snapshot binding. A result kind is recorded only
10
- * when it is derivable from known operands; otherwise it stays unresolved.
11
- * Known incompatible kinds refuse here. Unresolved trees are inert metadata,
12
- * not typechecked programs.
13
- *
14
- * Wire spellings (the grammar arms, not a second flattened interpretation):
15
- * migration plan JSON — field/literal/operator nodes; one-arm literals (`{ u64: n }`)
16
- * query IR — `{ kind: "literal", value: ValueSpec }` via `literalWireOf`
17
- */
1
+ /** Query scalar nodes, with cached kind and depth. Construction is constant
2
+ * work; native preparation binds variables and evaluates the expressions. */
18
3
  import { AuthoringError } from "#errors.ts"
19
4
  import type { ScalarExprIr } from "#native.ts"
20
5
  import type { ValueSpec } from "#spec.ts"
21
6
 
22
- /** F0: leaf scope for the shared AST (C1). Query vars are typed; source fields stay unresolved. */
23
- export type ScalarLeafScope = "query-var" | "source-field"
24
-
25
7
  /** The engine's scalar result vocabulary — distinct at the type level. */
26
8
  type ScalarKind = "u64" | "i64" | "f64" | "bool"
27
9
 
28
10
  /** Cached result kind: known only when derivable; otherwise honestly unresolved. */
29
11
  type IntervalKind = "intervalU64" | "intervalI64" | "intervalF64"
30
12
  type ScalarInputKind = ScalarKind | IntervalKind
31
- type ScalarResultKind = ScalarInputKind | "unresolved"
13
+ type ScalarResultKind = ScalarInputKind
32
14
  type Rounding = "towardZero" | "nearestTiesAwayFromZero" | "nearestTiesToEven"
33
15
 
34
16
  /** Host value for a derived scalar kind. */
@@ -38,26 +20,6 @@ type NumericCast = "toF64" | "toF64Exact" | "toI64Exact" | "toU64Exact"
38
20
 
39
21
  type NumericKind = "u64" | "i64" | "f64"
40
22
 
41
- type NumericOrUnresolved = NumericKind | "unresolved"
42
-
43
- /**
44
- * Combine known numeric kinds, or stay unresolved when a source-field leaf
45
- * still needs native binding. Distinct known kinds collapse to `never`
46
- * (static refusal) and throw at the constructor.
47
- */
48
- type CombineNumeric<L, R> = L extends "unresolved"
49
- ? R extends "bool"
50
- ? never
51
- : "unresolved"
52
- : R extends "unresolved"
53
- ? L extends "bool"
54
- ? never
55
- : "unresolved"
56
- : L extends R
57
- ? L
58
- : never
59
-
60
- /** The tagged literal subset shared by every leaf scope. */
61
23
  type ScalarLiteral =
62
24
  | { readonly bool: boolean }
63
25
  | { readonly u64: bigint }
@@ -89,54 +51,32 @@ interface ScalarQueryVar {
89
51
 
90
52
  type QueryVarLeaf = { readonly kind: "var"; readonly ref: ScalarQueryVar }
91
53
 
92
- type SourceFieldLeaf = { readonly kind: "field"; readonly name: string }
93
-
94
- type ScalarLeaf<S extends ScalarLeafScope> = S extends "query-var" ? QueryVarLeaf : SourceFieldLeaf
95
-
96
- type ScalarNodeBody<S extends ScalarLeafScope> =
97
- | { readonly kind: "measure"; readonly expr: ScalarNode<S> }
54
+ type ScalarNodeBody =
55
+ | { readonly kind: "measure"; readonly expr: ScalarNode }
98
56
  | {
99
57
  readonly kind: "mulDiv"
100
- readonly a: ScalarNode<S>
101
- readonly b: ScalarNode<S>
102
- readonly divisor: ScalarNode<S>
58
+ readonly a: ScalarNode
59
+ readonly b: ScalarNode
60
+ readonly divisor: ScalarNode
103
61
  readonly rounding: Rounding
104
62
  }
105
- | ScalarLeaf<S>
63
+ | QueryVarLeaf
106
64
  | { readonly kind: "literal"; readonly value: ScalarLiteral }
107
- | { readonly kind: "negate"; readonly expr: ScalarNode<S> }
108
- | { readonly kind: "isNaN"; readonly expr: ScalarNode<S> }
109
- | { readonly kind: "isFinite"; readonly expr: ScalarNode<S> }
110
- | { readonly kind: "add"; readonly left: ScalarNode<S>; readonly right: ScalarNode<S> }
111
- | { readonly kind: "subtract"; readonly left: ScalarNode<S>; readonly right: ScalarNode<S> }
112
- | { readonly kind: "multiply"; readonly left: ScalarNode<S>; readonly right: ScalarNode<S> }
113
- | { readonly kind: "divide"; readonly left: ScalarNode<S>; readonly right: ScalarNode<S> }
114
- | { readonly kind: "cast"; readonly cast: NumericCast; readonly expr: ScalarNode<S> }
115
-
116
- /**
117
- * One authored node: roster arms plus cached `scope` / `result` / `depth`.
118
- * Summaries are construction metadata; lowering and L17 serialization read
119
- * the grammar arms and ignore the summaries.
120
- */
121
- type ScalarNode<
122
- S extends ScalarLeafScope = ScalarLeafScope,
123
- K extends ScalarResultKind = ScalarResultKind
124
- > = ScalarNodeBody<S> & {
125
- readonly scope: S
65
+ | { readonly kind: "negate"; readonly expr: ScalarNode }
66
+ | { readonly kind: "isNaN"; readonly expr: ScalarNode }
67
+ | { readonly kind: "isFinite"; readonly expr: ScalarNode }
68
+ | { readonly kind: "add"; readonly left: ScalarNode; readonly right: ScalarNode }
69
+ | { readonly kind: "subtract"; readonly left: ScalarNode; readonly right: ScalarNode }
70
+ | { readonly kind: "multiply"; readonly left: ScalarNode; readonly right: ScalarNode }
71
+ | { readonly kind: "divide"; readonly left: ScalarNode; readonly right: ScalarNode }
72
+ | { readonly kind: "cast"; readonly cast: NumericCast; readonly expr: ScalarNode }
73
+
74
+ /** Cached summaries never replace the expression grammar. */
75
+ type ScalarNode<K extends ScalarResultKind = ScalarResultKind> = ScalarNodeBody & {
126
76
  readonly result: K
127
77
  readonly depth: number
128
78
  }
129
79
 
130
- /**
131
- * Migration authoring expression (source-field scope). `K` is the cached
132
- * result kind, not a host value type: I64 and U64 remain distinct even
133
- * though both use bigint in JavaScript.
134
- */
135
- type ScalarExpr<K extends ScalarResultKind = ScalarResultKind> = ScalarNode<"source-field", K>
136
-
137
- /** A migration field read: unresolved until native snapshot binding. */
138
- type ScalarFieldRef = ScalarNode<"source-field", "unresolved"> & SourceFieldLeaf
139
-
140
80
  const MAX_SCALAR_DEPTH = 128
141
81
  const U64_MAX = (1n << 64n) - 1n
142
82
  const I64_MIN = -(1n << 63n)
@@ -149,9 +89,10 @@ function scalarAuthoringWork(): number {
149
89
  return authoringWork
150
90
  }
151
91
 
152
- function admit<
153
- const Node extends { readonly scope: ScalarLeafScope; readonly result: ScalarResultKind; readonly depth: number }
154
- >(where: string, node: Node): Readonly<Node> {
92
+ function admit<const Node extends { readonly result: ScalarResultKind; readonly depth: number }>(
93
+ where: string,
94
+ node: Node
95
+ ): Readonly<Node> {
155
96
  authoringWork += 1
156
97
  assertDepth(where, node.depth)
157
98
  return Object.freeze(node)
@@ -229,40 +170,19 @@ function assertNumeric(where: string, kind: ScalarInputKind): asserts kind is Nu
229
170
  function assertSameKind(where: string, left: ScalarInputKind, right: ScalarInputKind): ScalarInputKind {
230
171
  if (left !== right) {
231
172
  throw new AuthoringError({
232
- message: `${where}: operand kinds differ (${left} vs ${right}) — the engine has no mixed promotion; cast explicitly (Scalar.toF64/ toF64Exact/ toI64Exact/ toU64Exact)`
173
+ message: `${where}: operand kinds differ (${left} vs ${right}) — the engine has no mixed promotion; cast explicitly (Compute.toF64/ toF64Exact/ toI64Exact/ toU64Exact)`
233
174
  })
234
175
  }
235
176
  return left
236
177
  }
237
178
 
238
- function assertScope<S extends ScalarLeafScope>(where: string, left: ScalarNode<S>, right: ScalarNode<S>): S {
239
- if (left.scope !== right.scope) {
240
- throw new AuthoringError({
241
- message: `${where}: leaf scopes differ (${left.scope} vs ${right.scope}) — query-var and source-field trees do not mix`
242
- })
243
- }
244
- return left.scope
245
- }
246
-
247
179
  function combineNumeric(where: string, left: ScalarResultKind, right: ScalarResultKind): ScalarResultKind {
248
- if (left === "unresolved" || right === "unresolved") {
249
- if (left !== "unresolved") {
250
- assertNumeric(where, left)
251
- }
252
- if (right !== "unresolved") {
253
- assertNumeric(where, right)
254
- }
255
- return "unresolved"
256
- }
257
180
  assertNumeric(where, left)
258
181
  assertNumeric(where, right)
259
182
  return assertSameKind(where, left, right)
260
183
  }
261
184
 
262
185
  function negateKind(where: string, inner: ScalarResultKind): ScalarResultKind {
263
- if (inner === "unresolved") {
264
- return "unresolved"
265
- }
266
186
  if (inner !== "i64" && inner !== "f64") {
267
187
  throw new AuthoringError({
268
188
  message: `${where}: the operand is ${inner} — negation is defined over i64 and f64 only`
@@ -272,86 +192,46 @@ function negateKind(where: string, inner: ScalarResultKind): ScalarResultKind {
272
192
  }
273
193
 
274
194
  function assertCastOperand(where: string, inner: ScalarResultKind): void {
275
- if (inner === "unresolved") {
276
- return
277
- }
278
195
  assertNumeric(where, inner)
279
196
  }
280
197
 
281
198
  function assertFloatOperand(where: string, inner: ScalarResultKind): void {
282
- if (inner === "unresolved") {
283
- return
284
- }
285
199
  if (inner !== "f64") {
286
200
  throw new AuthoringError({ message: `${where}: the operand is ${inner} — the float predicates read f64` })
287
201
  }
288
202
  }
289
203
 
290
204
  function isScalarNode(value: unknown): value is ScalarNode {
291
- return (
292
- typeof value === "object" &&
293
- value !== null &&
294
- "kind" in value &&
295
- "scope" in value &&
296
- "result" in value &&
297
- "depth" in value
298
- )
299
- }
300
-
301
- function isUnresolvedScalar(node: ScalarNode): boolean {
302
- return node.result === "unresolved"
303
- }
304
-
305
- /** Source-field leaf — unresolved until L14 binds it against the verified snapshot. */
306
- function sourceField(name: string): ScalarFieldRef {
307
- if (typeof name !== "string" || name.length === 0) {
308
- throw new AuthoringError({ message: "scalar field(...) names a nonempty source field" })
309
- }
310
- return admit("Scalar.field", {
311
- kind: "field",
312
- name,
313
- scope: "source-field",
314
- result: "unresolved",
315
- depth: 1
316
- })
205
+ return typeof value === "object" && value !== null && "kind" in value && "result" in value && "depth" in value
317
206
  }
318
207
 
319
208
  /** Query-var leaf — kind is the variable's schema kind, already known. */
320
- function queryVarLeaf<K extends ScalarInputKind>(ref: ScalarQueryVar, kind: K): ScalarNode<"query-var", K> {
321
- return admit("Scalar.queryVar", {
209
+ function queryVarLeaf<K extends ScalarInputKind>(ref: ScalarQueryVar, kind: K): ScalarNode<K> {
210
+ return admit("Compute.variable", {
322
211
  kind: "var",
323
212
  ref,
324
- scope: "query-var",
325
213
  result: kind,
326
214
  depth: 1
327
215
  })
328
216
  }
329
217
 
330
- function scalarLiteral<S extends ScalarLeafScope>(scope: S, value: ScalarLiteral): ScalarNode<S, ScalarKind> {
218
+ function scalarLiteral(value: ScalarLiteral): ScalarNode<ScalarKind> {
331
219
  const kind = literalKindOf(value)
332
- return admit("Scalar.literal", {
220
+ return admit("Compute.literal", {
333
221
  kind: "literal",
334
222
  value: literalValue(value),
335
- scope,
336
223
  result: kind,
337
224
  depth: 1
338
- }) as ScalarNode<S, ScalarKind>
225
+ }) as ScalarNode<ScalarKind>
339
226
  }
340
227
 
341
228
  type BinaryOp = "add" | "subtract" | "multiply" | "divide"
342
229
 
343
- function scalarBinary<S extends ScalarLeafScope>(
344
- where: string,
345
- op: BinaryOp,
346
- left: ScalarNode<S>,
347
- right: ScalarNode<S>
348
- ): ScalarNode<S, ScalarResultKind> {
349
- const scope = assertScope(where, left, right)
230
+ function scalarBinary(where: string, op: BinaryOp, left: ScalarNode, right: ScalarNode): ScalarNode {
350
231
  return admit(where, {
351
232
  kind: op,
352
233
  left,
353
234
  right,
354
- scope,
355
235
  result: combineNumeric(where, left.result, right.result),
356
236
  depth: Math.max(left.depth, right.depth) + 1
357
237
  })
@@ -363,18 +243,15 @@ function roundingMode(value: unknown): Rounding {
363
243
  return value
364
244
  }
365
245
 
366
- function scalarMulDiv<S extends ScalarLeafScope>(
246
+ function scalarMulDiv(
367
247
  where: string,
368
- a: ScalarNode<S>,
369
- b: ScalarNode<S>,
370
- divisor: ScalarNode<S>,
248
+ a: ScalarNode,
249
+ b: ScalarNode,
250
+ divisor: ScalarNode,
371
251
  rounding: Rounding
372
- ): ScalarNode<S> {
373
- const scope = assertScope(where, a, b)
374
- assertScope(where, a, divisor)
252
+ ): ScalarNode {
375
253
  let known: "i64" | "u64" | undefined
376
254
  for (const operand of [a, b, divisor]) {
377
- if (operand.result === "unresolved") continue
378
255
  if ((operand.result !== "i64" && operand.result !== "u64") || (known !== undefined && known !== operand.result))
379
256
  throw new AuthoringError({ message: `${where}: operands must have one matching integer kind` })
380
257
  known = operand.result
@@ -385,74 +262,57 @@ function scalarMulDiv<S extends ScalarLeafScope>(
385
262
  b,
386
263
  divisor,
387
264
  rounding: roundingMode(rounding),
388
- scope,
389
- result:
390
- a.result === "unresolved" || b.result === "unresolved" || divisor.result === "unresolved"
391
- ? "unresolved"
392
- : a.result,
265
+ result: a.result,
393
266
  depth: Math.max(a.depth, b.depth, divisor.depth) + 1
394
267
  })
395
268
  }
396
269
 
397
- function scalarMeasure<S extends ScalarLeafScope>(where: string, expr: ScalarNode<S>): ScalarNode<S> {
270
+ function scalarMeasure(where: string, expr: ScalarNode): ScalarNode {
398
271
  const kind = expr.result
399
- if (kind !== "unresolved" && kind !== "intervalU64" && kind !== "intervalI64" && kind !== "intervalF64")
272
+ if (kind !== "intervalU64" && kind !== "intervalI64" && kind !== "intervalF64")
400
273
  throw new AuthoringError({ message: `${where}: measure requires an interval` })
401
274
  return admit(where, {
402
275
  kind: "measure",
403
276
  expr,
404
- scope: expr.scope,
405
- result: ({ unresolved: "unresolved", intervalF64: "f64", intervalI64: "u64", intervalU64: "u64" } as const)[kind],
277
+ result: ({ intervalF64: "f64", intervalI64: "u64", intervalU64: "u64" } as const)[kind],
406
278
  depth: expr.depth + 1
407
279
  })
408
280
  }
409
281
 
410
- function scalarNegate<S extends ScalarLeafScope>(where: string, expr: ScalarNode<S>): ScalarNode<S, ScalarResultKind> {
282
+ function scalarNegate(where: string, expr: ScalarNode): ScalarNode {
411
283
  return admit(where, {
412
284
  kind: "negate",
413
285
  expr,
414
- scope: expr.scope,
415
286
  result: negateKind(where, expr.result),
416
287
  depth: expr.depth + 1
417
288
  })
418
289
  }
419
290
 
420
- function scalarCast<S extends ScalarLeafScope>(
421
- where: string,
422
- cast: NumericCast,
423
- result: ScalarKind,
424
- expr: ScalarNode<S>
425
- ): ScalarNode<S, ScalarKind> {
291
+ function scalarCast(where: string, cast: NumericCast, result: ScalarKind, expr: ScalarNode): ScalarNode<ScalarKind> {
426
292
  assertCastOperand(where, expr.result)
427
293
  return admit(where, {
428
294
  kind: "cast",
429
295
  cast,
430
296
  expr,
431
- scope: expr.scope,
432
297
  result,
433
298
  depth: expr.depth + 1
434
299
  })
435
300
  }
436
301
 
437
- function scalarFloatPredicate<S extends ScalarLeafScope>(
438
- where: string,
439
- op: "isNaN" | "isFinite",
440
- expr: ScalarNode<S>
441
- ): ScalarNode<S, "bool"> {
302
+ function scalarFloatPredicate(where: string, op: "isNaN" | "isFinite", expr: ScalarNode): ScalarNode<"bool"> {
442
303
  assertFloatOperand(where, expr.result)
443
304
  return admit(where, {
444
305
  kind: op,
445
306
  expr,
446
- scope: expr.scope,
447
307
  result: "bool",
448
308
  depth: expr.depth + 1
449
309
  })
450
310
  }
451
311
 
452
312
  /** Query-var leaves collected once at find-binding time — not during construction. */
453
- function queryVarsOf(node: ScalarNode<"query-var">): readonly ScalarQueryVar[] {
313
+ function queryVarsOf(node: ScalarNode): readonly ScalarQueryVar[] {
454
314
  const vars: ScalarQueryVar[] = []
455
- const pending: ScalarNode<"query-var">[] = [node]
315
+ const pending: ScalarNode[] = [node]
456
316
  while (pending.length > 0) {
457
317
  const next = pending.pop()
458
318
  if (next === undefined) {
@@ -480,126 +340,16 @@ function queryVarsOf(node: ScalarNode<"query-var">): readonly ScalarQueryVar[] {
480
340
  case "divide":
481
341
  pending.push(next.left, next.right)
482
342
  break
483
- default:
484
- throw new AuthoringError({
485
- message: "queryVarsOf: a query-var tree cannot carry a source-field leaf"
486
- })
487
343
  }
488
344
  }
489
345
  return vars
490
346
  }
491
347
 
492
- function field(name: string): ScalarFieldRef {
493
- return sourceField(name)
494
- }
495
-
496
- function literal(value: ScalarLiteral): ScalarExpr<ScalarKind> {
497
- return scalarLiteral("source-field", value)
498
- }
499
-
500
- function u64(value: bigint): ScalarExpr<"u64"> {
501
- checkU64(value, "Scalar.u64")
502
- return scalarLiteral("source-field", { u64: value }) as ScalarExpr<"u64">
503
- }
504
-
505
- function i64(value: bigint): ScalarExpr<"i64"> {
506
- checkI64(value, "Scalar.i64")
507
- return scalarLiteral("source-field", { i64: value }) as ScalarExpr<"i64">
508
- }
509
-
510
- function f64(value: number): ScalarExpr<"f64"> {
511
- checkF64(value, "Scalar.f64")
512
- return scalarLiteral("source-field", { f64: value }) as ScalarExpr<"f64">
513
- }
514
-
515
- function bool(value: boolean): ScalarExpr<"bool"> {
516
- checkBool(value, "Scalar.bool")
517
- return scalarLiteral("source-field", { bool: value }) as ScalarExpr<"bool">
518
- }
519
-
520
- function negate<K extends "i64" | "f64" | "unresolved">(expr: ScalarExpr<K>): ScalarExpr<K> {
521
- return scalarNegate("Scalar.negate", expr) as ScalarExpr<K>
522
- }
523
-
524
- function add<L extends NumericOrUnresolved, R extends CombineNumeric<L, R> extends never ? never : NumericOrUnresolved>(
525
- left: ScalarExpr<L>,
526
- right: ScalarExpr<R>
527
- ): ScalarExpr<CombineNumeric<L, R>> {
528
- return scalarBinary("Scalar.add", "add", left, right) as ScalarExpr<CombineNumeric<L, R>>
529
- }
530
-
531
- function subtract<
532
- L extends NumericOrUnresolved,
533
- R extends CombineNumeric<L, R> extends never ? never : NumericOrUnresolved
534
- >(left: ScalarExpr<L>, right: ScalarExpr<R>): ScalarExpr<CombineNumeric<L, R>> {
535
- return scalarBinary("Scalar.subtract", "subtract", left, right) as ScalarExpr<CombineNumeric<L, R>>
536
- }
537
-
538
- function multiply<
539
- L extends NumericOrUnresolved,
540
- R extends CombineNumeric<L, R> extends never ? never : NumericOrUnresolved
541
- >(left: ScalarExpr<L>, right: ScalarExpr<R>): ScalarExpr<CombineNumeric<L, R>> {
542
- return scalarBinary("Scalar.multiply", "multiply", left, right) as ScalarExpr<CombineNumeric<L, R>>
543
- }
544
-
545
- function divide<
546
- L extends NumericOrUnresolved,
547
- R extends CombineNumeric<L, R> extends never ? never : NumericOrUnresolved
548
- >(left: ScalarExpr<L>, right: ScalarExpr<R>): ScalarExpr<CombineNumeric<L, R>> {
549
- return scalarBinary("Scalar.divide", "divide", left, right) as ScalarExpr<CombineNumeric<L, R>>
550
- }
551
-
552
- function mulDiv<
553
- L extends "i64" | "u64" | "unresolved",
554
- R extends CombineNumeric<L, R> extends never ? never : "i64" | "u64" | "unresolved",
555
- D extends CombineNumeric<L, D> extends never
556
- ? never
557
- : CombineNumeric<R, D> extends never
558
- ? never
559
- : "i64" | "u64" | "unresolved"
560
- >(
561
- a: ScalarExpr<L>,
562
- b: ScalarExpr<R>,
563
- divisor: ScalarExpr<D>,
564
- rounding: Rounding
565
- ): ScalarExpr<CombineNumeric<CombineNumeric<L, R>, D>> {
566
- return scalarMulDiv("Scalar.mulDiv", a, b, divisor, rounding) as ScalarExpr<CombineNumeric<CombineNumeric<L, R>, D>>
567
- }
568
-
569
- function measure(expr: ScalarFieldRef): ScalarExpr<"unresolved"> {
570
- return scalarMeasure("Scalar.measure", expr) as ScalarExpr<"unresolved">
571
- }
572
-
573
- function toF64(expr: ScalarExpr<NumericOrUnresolved>): ScalarExpr<"f64"> {
574
- return scalarCast("Scalar.toF64", "toF64", "f64", expr) as ScalarExpr<"f64">
575
- }
576
-
577
- function toF64Exact(expr: ScalarExpr<NumericOrUnresolved>): ScalarExpr<"f64"> {
578
- return scalarCast("Scalar.toF64Exact", "toF64Exact", "f64", expr) as ScalarExpr<"f64">
579
- }
580
-
581
- function toI64Exact(expr: ScalarExpr<NumericOrUnresolved>): ScalarExpr<"i64"> {
582
- return scalarCast("Scalar.toI64Exact", "toI64Exact", "i64", expr) as ScalarExpr<"i64">
583
- }
584
-
585
- function toU64Exact(expr: ScalarExpr<NumericOrUnresolved>): ScalarExpr<"u64"> {
586
- return scalarCast("Scalar.toU64Exact", "toU64Exact", "u64", expr) as ScalarExpr<"u64">
587
- }
588
-
589
- function isNaNExpr(expr: ScalarExpr<"f64" | "unresolved">): ScalarExpr<"bool"> {
590
- return scalarFloatPredicate("Scalar.isNaN", "isNaN", expr)
591
- }
592
-
593
- function isFiniteExpr(expr: ScalarExpr<"f64" | "unresolved">): ScalarExpr<"bool"> {
594
- return scalarFloatPredicate("Scalar.isFinite", "isFinite", expr)
595
- }
596
-
597
- /** One lowering walk for query variables and row-field bindings. */
598
- function scalarWire(node: ScalarNode, leaf: (node: QueryVarLeaf | SourceFieldLeaf) => number): ScalarExprIr {
348
+ /** Lower each query variable through its existing binding. */
349
+ function scalarWire(node: ScalarNode, leaf: (node: QueryVarLeaf) => number): ScalarExprIr {
599
350
  const walk = (expr: ScalarNode): ScalarExprIr => scalarWire(expr, leaf)
600
351
  switch (node.kind) {
601
352
  case "var":
602
- case "field":
603
353
  return { kind: "var", var: leaf(node) }
604
354
  case "literal":
605
355
  return { kind: "literal", value: literalWireOf(node.value) }
@@ -620,39 +370,12 @@ function scalarWire(node: ScalarNode, leaf: (node: QueryVarLeaf | SourceFieldLea
620
370
  }
621
371
  }
622
372
 
623
- /** The authoring namespace: `Scalar.field("units")`, `Scalar.add(...)`. */
624
- const Scalar = Object.freeze({
625
- field,
626
- literal,
627
- u64,
628
- i64,
629
- f64,
630
- bool,
631
- negate,
632
- add,
633
- subtract,
634
- multiply,
635
- divide,
636
- mulDiv,
637
- measure,
638
- toF64,
639
- toF64Exact,
640
- toI64Exact,
641
- toU64Exact,
642
- isNaN: isNaNExpr,
643
- isFinite: isFiniteExpr
644
- })
645
-
646
373
  export type {
647
- CombineNumeric,
648
374
  IntervalKind,
649
375
  NumericCast,
650
376
  NumericKind,
651
- NumericOrUnresolved,
652
377
  QueryVarLeaf,
653
378
  Rounding,
654
- ScalarExpr,
655
- ScalarFieldRef,
656
379
  ScalarInputKind,
657
380
  ScalarKind,
658
381
  ScalarLiteral,
@@ -660,8 +383,7 @@ export type {
660
383
  ScalarOpKind,
661
384
  ScalarQueryVar,
662
385
  ScalarResultKind,
663
- ScalarValue,
664
- SourceFieldLeaf
386
+ ScalarValue
665
387
  }
666
388
  export {
667
389
  assertDepth,
@@ -672,7 +394,6 @@ export {
672
394
  checkI64,
673
395
  checkU64,
674
396
  isScalarNode,
675
- isUnresolvedScalar,
676
397
  literalKindOf,
677
398
  literalValue,
678
399
  literalWireOf,
@@ -680,7 +401,6 @@ export {
680
401
  queryVarLeaf,
681
402
  queryVarsOf,
682
403
  roundingMode,
683
- Scalar,
684
404
  scalarAuthoringWork,
685
405
  scalarBinary,
686
406
  scalarCast,
@@ -0,0 +1,38 @@
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
+ import type { SchemaSpec } from "#spec.ts"
6
+
7
+ const decoder = new TextDecoder("utf-8", { fatal: true })
8
+
9
+ function text(operation: string, bytes: Uint8Array | null): string {
10
+ if (bytes === null) throw dbError(operation, { _tag: "Internal" })
11
+ return decoder.decode(bytes)
12
+ }
13
+
14
+ const internalSchemaSnapshot = Effect.fn("internalSchemaSnapshot")(function* (spec: SchemaSpec) {
15
+ const runtime = yield* runtimeHandle()
16
+ return yield* nativeOperationWith(
17
+ "internalSchemaSnapshot",
18
+ (callback) => dbNative.runtimeSchemaSnapshot(runtime, spec, callback),
19
+ dbNative.runtimeBytesTake,
20
+ (bytes) => text("internalSchemaSnapshot", bytes)
21
+ )
22
+ })
23
+
24
+ const internalSchemaBindings = Effect.fn("internalSchemaBindings")(function* (snapshot: string) {
25
+ if (typeof snapshot !== "string" || !snapshot.isWellFormed()) {
26
+ return yield* Effect.fail(new DbError({ operation: "internalSchemaBindings", reason: { _tag: "InvalidArgument" } }))
27
+ }
28
+ const runtime = yield* runtimeHandle()
29
+ const bytes = new TextEncoder().encode(snapshot)
30
+ return yield* nativeOperationWith(
31
+ "internalSchemaBindings",
32
+ (callback) => dbNative.runtimeSchemaBindings(runtime, bytes, callback),
33
+ dbNative.runtimeBytesTake,
34
+ (bytes) => text("internalSchemaBindings", bytes)
35
+ )
36
+ })
37
+
38
+ export { internalSchemaBindings, internalSchemaSnapshot }
@@ -1,31 +0,0 @@
1
- /**
2
- * Private log-migration integration entrypoints: the two read-only
3
- * native migration-codec verbs the `@bjornpagen/bumbledb-log/migrations`
4
- * generator imports, wired over the shared executor onto the native
5
- * `schema_file`, `migration::plan` and `migration::manifest` modules.
6
- *
7
- * Both follow `hashChunk`'s shape: bounded owned input, bounded owned JSON
8
- * response bytes, ONE registered cancellable operation under the acquired
9
- * `NativeRuntime`. The schema verb takes the SDK `SchemaSpec` object — the
10
- * same wire that already crosses the bridge for open/create — never a
11
- * respelled text form. Neither verb opens, initializes, freezes or migrates
12
- * a database; the durable migrate/activate/abort workflow is the log's
13
- * admin surface, not this seam.
14
- */
15
- import { Effect } from "effect";
16
- import { DbError } from "./runtime-errors.js";
17
- import type { SchemaSpec } from "./spec.js";
18
- /**
19
- * Canonical schema admission for the migration generator: validates the
20
- * spec natively and yields bounded JSON bytes carrying the canonical
21
- * `schemaId` and the rendered schema snapshot.
22
- */
23
- declare const internalMigrationSchema: (spec: SchemaSpec) => Effect.Effect<Uint8Array<ArrayBufferLike>, DbError, import("./runtime.js").NativeRuntime>;
24
- /**
25
- * One bounded read-only migration-codec request (plan parse/validate/
26
- * render/digest, manifest verify/append preview, plan-set digests): owned
27
- * JSON request bytes in, owned JSON response bytes out.
28
- */
29
- declare const internalMigrationRead: (request: Uint8Array<ArrayBufferLike>) => Effect.Effect<Uint8Array<ArrayBufferLike>, DbError, import("./runtime.js").NativeRuntime>;
30
- export { internalMigrationRead, internalMigrationSchema };
31
- //# sourceMappingURL=migration.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../src/migration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,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;;;;GAIG;AACH,QAAA,MAAM,uBAAuB,gHAQ3B,CAAA;AAEF;;;;GAIG;AACH,QAAA,MAAM,qBAAqB,oIAWzB,CAAA;AAEF,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,CAAA"}