@bjornpagen/bumbledb 0.10.0 → 0.12.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 (69) hide show
  1. package/COOKBOOK.md +155 -136
  2. package/README.md +5 -9
  3. package/dist/db.d.ts +77 -109
  4. package/dist/db.d.ts.map +1 -1
  5. package/dist/db.js +121 -339
  6. package/dist/db.js.map +1 -1
  7. package/dist/index.d.ts +12 -17
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +8 -11
  10. package/dist/index.js.map +1 -1
  11. package/dist/lower.d.ts.map +1 -1
  12. package/dist/lower.js +8 -1
  13. package/dist/lower.js.map +1 -1
  14. package/dist/native.d.ts +77 -51
  15. package/dist/native.d.ts.map +1 -1
  16. package/dist/native.js.map +1 -1
  17. package/dist/query/atom.d.ts +94 -112
  18. package/dist/query/atom.d.ts.map +1 -1
  19. package/dist/query/atom.js +8 -17
  20. package/dist/query/atom.js.map +1 -1
  21. package/dist/query/find.d.ts +18 -35
  22. package/dist/query/find.d.ts.map +1 -1
  23. package/dist/query/find.js +13 -32
  24. package/dist/query/find.js.map +1 -1
  25. package/dist/query/lower.d.ts +128 -124
  26. package/dist/query/lower.d.ts.map +1 -1
  27. package/dist/query/lower.js +366 -258
  28. package/dist/query/lower.js.map +1 -1
  29. package/dist/query/parse-ir.d.ts +12 -0
  30. package/dist/query/parse-ir.d.ts.map +1 -0
  31. package/dist/query/parse-ir.js +71 -0
  32. package/dist/query/parse-ir.js.map +1 -0
  33. package/dist/query/run.d.ts +2 -2
  34. package/dist/query/run.d.ts.map +1 -1
  35. package/dist/query/run.js +2 -13
  36. package/dist/query/run.js.map +1 -1
  37. package/dist/query/scope.d.ts +4 -16
  38. package/dist/query/scope.d.ts.map +1 -1
  39. package/dist/query/scope.js +1 -6
  40. package/dist/query/scope.js.map +1 -1
  41. package/dist/schema.js +2 -2
  42. package/dist/schema.js.map +1 -1
  43. package/dist/statements.d.ts +8 -4
  44. package/dist/statements.d.ts.map +1 -1
  45. package/dist/statements.js +7 -9
  46. package/dist/statements.js.map +1 -1
  47. package/package.json +2 -2
  48. package/src/db.ts +182 -443
  49. package/src/index.ts +11 -24
  50. package/src/lower.ts +8 -1
  51. package/src/native.ts +79 -43
  52. package/src/query/atom.ts +105 -138
  53. package/src/query/find.ts +39 -80
  54. package/src/query/lower.ts +626 -434
  55. package/src/query/parse-ir.ts +82 -0
  56. package/src/query/run.ts +2 -14
  57. package/src/query/scope.ts +3 -21
  58. package/src/schema.ts +2 -2
  59. package/src/statements.ts +17 -13
  60. package/dist/order.d.ts +0 -87
  61. package/dist/order.d.ts.map +0 -1
  62. package/dist/order.js +0 -153
  63. package/dist/order.js.map +0 -1
  64. package/dist/query/predicate.d.ts +0 -91
  65. package/dist/query/predicate.d.ts.map +0 -1
  66. package/dist/query/predicate.js +0 -156
  67. package/dist/query/predicate.js.map +0 -1
  68. package/src/order.ts +0 -234
  69. package/src/query/predicate.ts +0 -269
package/src/index.ts CHANGED
@@ -5,24 +5,22 @@
5
5
  * never declared: THE LAWS TYPE THE COLUMNS, `schema()` computing every
6
6
  * field's equivalence class FROM the statement list at both tiers), the
7
7
  * statement algebra with `schema()` and `SchemaSpec` lowering (PRD-06), the `Db`
8
- * runtime (path-cached stores, transactions, typed violations, scoped
9
- * snapshot reads, the witnessed write loop with `abandon` — PRD-07, zero
10
- * closables), the query surface (Datalog as values, kysely-shaped:
8
+ * runtime (exclusive-lock stores, transactions, typed violations, scoped
9
+ * snapshot reads, one-shot `write`/`writeFrom` with `abandon` — PRD-07, zero
10
+ * closables), the query surface (kysely-shaped:
11
11
  * `query(S).rule(r => { const { id, name } = v(Holder); return r.match(Holder, { id, name }).find({ name }) })` —
12
12
  * variables minted by `v()` and joined by OBJECT REFERENCE (reuse is the
13
13
  * join), the head a `find` RECORD whose keys name the answer columns
14
14
  * (renames are real), params still STRING-named, plus negation,
15
- * conditions, aggregates, and stratified recursion via `program()`/`rec` —
15
+ * conditions, aggregates, and interiors / one linear rec via
16
+ * `q.interior` / `q.reach` —
16
17
  * `db.prepare` as a plain value; the comparison/connective builders are
17
18
  * also free exports, and the free names `eq`/`not`/`and`/`or` collide with
18
19
  * common host identifiers — import aliasing is the answer; the SDK does
19
20
  * not rename for collision-avoidance), the exhume surface
20
21
  * (`Db.exhume` — the one schema-independent read path: the store's
21
22
  * self-described shapes and raw facts by name, typed at bare structural
22
- * values, deliberately schema-free), and the answer-ordering helpers
23
- * (`by`/`desc` — sort keys as data for the language's own `.sort`; answers
24
- * are sets, the engine never orders, and limit is the language's own
25
- * `.slice`). The raw native bridge is not exported.
23
+ * values, deliberately schema-free). The raw native bridge is not exported.
26
24
  */
27
25
 
28
26
  export type {
@@ -63,7 +61,7 @@ export type {
63
61
  Violation,
64
62
  WriteResult
65
63
  } from "#db.ts"
66
- export { abandon, Db, ErrNewtypeMismatch, ErrWitnessedLivelock, WITNESSED_ATTEMPT_CAP } from "#db.ts"
64
+ export { abandon, Db, ErrGenerationMoved, ErrNewtypeMismatch } from "#db.ts"
67
65
  export type {
68
66
  Exhumed,
69
67
  ExhumedAxiom,
@@ -112,21 +110,14 @@ export { bool, bytes, i64, interval, span, str, u64 } from "#fields.ts"
112
110
  export type { ClassesOf, ClassWall, LawfulStatements, RelationClasses, SchemaClasses } from "#law.ts"
113
111
  export { lower, lowerClosed, lowerRelation } from "#lower.ts"
114
112
  export type { KeyFact, Minted } from "#marshal.ts"
115
- export type {
116
- FactValue,
117
- OccurrenceDrift,
118
- ProgramIr,
119
- Staleness,
120
- StatementKindTag
121
- } from "#native.ts"
122
- export type { Desc, EngineOrderable, SortKey } from "#order.ts"
123
- export { by, desc } from "#order.ts"
113
+ export type { FactValue, ParsedQuery, QueryIr, StatementKindTag } from "#native.ts"
124
114
 
125
115
  export type {
126
116
  AnyCond,
127
117
  BindingInput,
128
118
  Cmp,
129
119
  FindColumn,
120
+ InteriorData,
130
121
  MatchShape,
131
122
  NotAtom,
132
123
  RecData,
@@ -138,29 +129,25 @@ export type { Agg, FindEntry } from "#query/find.ts"
138
129
  export type {
139
130
  AnyQuery,
140
131
  AnyRuleValue,
141
- OutputRuleChain,
142
- OutputRuleScope,
143
132
  Query,
144
133
  QueryData,
145
134
  QueryParams,
135
+ QueryReachStart,
146
136
  QueryRelation,
147
137
  QueryRow,
148
138
  QueryRuleChain,
149
139
  QueryRuleScope,
150
140
  QueryStart,
151
- RecRef,
152
141
  RecRuleChain,
153
142
  RecRuleScope,
154
143
  RuleValue,
155
144
  TermOps
156
145
  } from "#query/lower.ts"
157
146
  export { lowerQuery, query } from "#query/lower.ts"
158
- export type { ProgramScope, Rec } from "#query/predicate.ts"
159
- export { program } from "#query/predicate.ts"
147
+ export { parseQueryIr } from "#query/parse-ir.ts"
160
148
  export type {
161
149
  ClassedField,
162
150
  Duration,
163
- MaskParam,
164
151
  MatchFields,
165
152
  MatchOwner,
166
153
  Param,
package/src/lower.ts CHANGED
@@ -96,7 +96,14 @@ function lowerStatement(statement: Statement): StatementSpec {
96
96
  kind: "containment",
97
97
  source: lowerFace(data.source),
98
98
  target: lowerFace(data.target),
99
- bidirectional: data.bidirectional
99
+ bidirectional: false
100
+ }
101
+ case "mirrors":
102
+ return {
103
+ kind: "containment",
104
+ source: lowerFace(data.source),
105
+ target: lowerFace(data.target),
106
+ bidirectional: true
100
107
  }
101
108
  case "capacity":
102
109
  return {
package/src/native.ts CHANGED
@@ -41,7 +41,7 @@ type ExhumeHandle = { readonly __brand: "bumbledb.exhume" }
41
41
  */
42
42
  type TxHandle = { readonly __brand: "bumbledb.tx" }
43
43
 
44
- /** One prepared query/program (plan pinned at prepare). */
44
+ /** One prepared query (plan pinned at prepare). */
45
45
  type PreparedHandle = { readonly __brand: "bumbledb.prepared" }
46
46
 
47
47
  /** A half-open interval `[start, end)` as it crosses the boundary. */
@@ -60,10 +60,9 @@ type FactValue = boolean | bigint | string | Uint8Array | IntervalValue
60
60
 
61
61
  /**
62
62
  * One tagged engine value — the 1:1 mirror of `bumbledb::Value` for the
63
- * positions no schema field directs (IR literals, query params). The spec's
64
- * `ValueSpec` vocabulary plus the bind-time-only Allen mask.
63
+ * positions no schema field directs (IR literals, query params).
65
64
  */
66
- type TaggedValue = ValueSpec | { readonly kind: "allenMask"; readonly mask: number }
65
+ type TaggedValue = ValueSpec
67
66
 
68
67
  /**
69
68
  * One positional execution argument: a tagged scalar, or a param SET
@@ -72,27 +71,44 @@ type TaggedValue = ValueSpec | { readonly kind: "allenMask"; readonly mask: numb
72
71
  type QueryParam = TaggedValue | { readonly kind: "set"; readonly values: readonly TaggedValue[] }
73
72
 
74
73
  /**
75
- * The IR mirror (`bumbledb::ir`, 1:1): relations, fields, predicates, and
74
+ * The IR mirror (`bumbledb::ir`, 1:1): relations, fields, interiors, and
76
75
  * params by NUMERIC id — the SDK resolves names through the manifest and
77
- * sends ids; the bridge never sees names in queries. A plain query is sent
78
- * as its degenerate one-predicate program.
76
+ * sends ids; the bridge never sees names in queries. Q1 is a tagged sum:
77
+ * CQ carries no rec; Reach carries `rec` by value.
79
78
  */
80
- interface ProgramIr {
81
- readonly predicates: readonly PredicateDefIr[]
82
- readonly output: number
83
- }
79
+ type QueryIr =
80
+ | {
81
+ readonly kind: "cq"
82
+ readonly interiors: readonly InteriorIr[]
83
+ readonly head: readonly HeadTermIr[]
84
+ readonly rules: readonly RuleIr[]
85
+ }
86
+ | {
87
+ readonly kind: "reach"
88
+ readonly interiors: readonly InteriorIr[]
89
+ readonly rec: RecIr
90
+ readonly head: readonly HeadTermIr[]
91
+ readonly rules: readonly RuleIr[]
92
+ }
84
93
 
85
- /** One predicate: the head shape its rules align against, and the rules. */
86
- interface PredicateDefIr {
94
+ /** One named interior: the head shape its rules align against, and the rules. */
95
+ interface InteriorIr {
87
96
  readonly head: readonly HeadTermIr[]
88
97
  readonly rules: readonly RuleIr[]
89
98
  }
90
99
 
100
+ /** The linear rec on a Reach query: shared head, base arms, rec arms. */
101
+ interface RecIr {
102
+ readonly head: readonly HeadTermIr[]
103
+ readonly base: readonly RuleIr[]
104
+ readonly rec: readonly RuleIr[]
105
+ }
106
+
91
107
  /** One head position: a plain variable slot or an aggregate-op kind. */
92
108
  type HeadTermIr = { readonly kind: "var" } | { readonly kind: "aggregate"; readonly op: HeadOpIr }
93
109
 
94
110
  /** The var-free aggregate-op kind at a head position. */
95
- type HeadOpIr = "sum" | "min" | "max" | "count" | "countDistinct" | "argMax" | "argMin" | "pack"
111
+ type HeadOpIr = "sum" | "min" | "max" | "count" | "pack"
96
112
 
97
113
  /** One rule: conjunctive body, anti-join atoms, condition trees. */
98
114
  interface RuleIr {
@@ -102,12 +118,23 @@ interface RuleIr {
102
118
  readonly conditions: readonly ConditionTreeIr[]
103
119
  }
104
120
 
105
- /** One find term (mirrors `ir::FindTerm`). */
121
+ /** One find term (mirrors `ir::FindTerm`). Count carries no `over`; folds require it. */
122
+ type FoldOpIr = { readonly kind: "sum" } | { readonly kind: "min" } | { readonly kind: "max" }
123
+
124
+ type ArgOpIr = FoldOpIr | { readonly kind: "pack" }
125
+
106
126
  type FindTermIr =
107
127
  | { readonly kind: "var"; readonly var: number }
108
- | { readonly kind: "aggregate"; readonly op: AggOpIr; readonly over?: number }
128
+ | { readonly kind: "aggregate"; readonly op: { readonly kind: "count" } }
129
+ | { readonly kind: "aggregate"; readonly op: ArgOpIr; readonly over: number }
109
130
  | { readonly kind: "measure"; readonly var: number }
110
- | { readonly kind: "aggregateMeasure"; readonly op: AggOpIr; readonly over: number }
131
+ | { readonly kind: "aggregateMeasure"; readonly op: FoldOpIr; readonly over: number }
132
+
133
+ /** Host brand: only {@link parseQueryIr} and `lowerQuery` inhabit this. Phantom — not a runtime key. */
134
+ declare const parsedQueryBrand: unique symbol
135
+
136
+ /** A `QueryIr` that passed the host shape parse (rec/main nonempty, aggregate finds split). */
137
+ type ParsedQuery = QueryIr & { readonly [parsedQueryBrand]: true }
111
138
 
112
139
  /** One aggregate operator (mirrors `ir::AggOp`; Arg ops carry their key). */
113
140
  type AggOpIr =
@@ -115,15 +142,12 @@ type AggOpIr =
115
142
  | { readonly kind: "min" }
116
143
  | { readonly kind: "max" }
117
144
  | { readonly kind: "count" }
118
- | { readonly kind: "countDistinct" }
119
- | { readonly kind: "argMax"; readonly key: number }
120
- | { readonly kind: "argMin"; readonly key: number }
121
145
  | { readonly kind: "pack" }
122
146
 
123
- /** Where an atom draws its facts: a stored relation or a program predicate. */
147
+ /** Where an atom draws its facts: a stored relation or a derived table. */
124
148
  type AtomSourceIr =
125
149
  | { readonly kind: "edb"; readonly relation: number }
126
- | { readonly kind: "idb"; readonly pred: number }
150
+ | { readonly kind: "interior"; readonly interior: number }
127
151
 
128
152
  /**
129
153
  * One atom: named-field bindings as `[fieldId, term]` pairs; absence of a
@@ -142,11 +166,6 @@ type TermIr =
142
166
  | { readonly kind: "literal"; readonly value: TaggedValue }
143
167
  | { readonly kind: "measure"; readonly var: number }
144
168
 
145
- /** The `Allen` comparison's mask position: a literal mask or a param. */
146
- type MaskTermIr =
147
- | { readonly kind: "literal"; readonly mask: number }
148
- | { readonly kind: "param"; readonly param: number }
149
-
150
169
  /** One comparison operator (mirrors `ir::CmpOp`). */
151
170
  type CmpOpIr =
152
171
  | { readonly kind: "eq" }
@@ -155,7 +174,7 @@ type CmpOpIr =
155
174
  | { readonly kind: "le" }
156
175
  | { readonly kind: "gt" }
157
176
  | { readonly kind: "ge" }
158
- | { readonly kind: "allen"; readonly mask: MaskTermIr }
177
+ | { readonly kind: "allen"; readonly mask: number }
159
178
  | { readonly kind: "pointIn" }
160
179
 
161
180
  /** One comparison condition. */
@@ -236,14 +255,27 @@ interface ViolationFact {
236
255
  * accumulates in u128 and the value crosses WHOLE as bigint (C3:
237
256
  * truncation is unrepresentable).
238
257
  */
239
- interface Violation {
240
- readonly statementId: number
241
- readonly kind: StatementKindTag
242
- readonly canonical: string
243
- readonly direction?: "sourceUnsatisfied" | "targetRequired"
244
- readonly measure?: bigint
245
- readonly facts: readonly ViolationFact[]
246
- }
258
+ type Violation =
259
+ | {
260
+ readonly statementId: number
261
+ readonly kind: "functionality"
262
+ readonly canonical: string
263
+ readonly facts: readonly ViolationFact[]
264
+ }
265
+ | {
266
+ readonly statementId: number
267
+ readonly kind: "containment"
268
+ readonly canonical: string
269
+ readonly direction: "sourceUnsatisfied" | "targetRequired"
270
+ readonly facts: readonly ViolationFact[]
271
+ }
272
+ | {
273
+ readonly statementId: number
274
+ readonly kind: "capacity"
275
+ readonly canonical: string
276
+ readonly measure: bigint
277
+ readonly facts: readonly ViolationFact[]
278
+ }
247
279
 
248
280
  /**
249
281
  * `dbCreate`/`dbOpen`'s domain outcome. `schemaError` spans both spec
@@ -349,7 +381,8 @@ interface Explain {
349
381
  readonly subsumed: ReadonlyArray<Readonly<Record<string, unknown>>>
350
382
  readonly dead: ReadonlyArray<Readonly<Record<string, unknown>>>
351
383
  readonly rules: ReadonlyArray<Readonly<Record<string, unknown>>>
352
- readonly strata: ReadonlyArray<Readonly<Record<string, unknown>>>
384
+ readonly interiors: ReadonlyArray<Readonly<Record<string, unknown>>>
385
+ readonly reach?: Readonly<Record<string, unknown>>
353
386
  }
354
387
 
355
388
  interface Native {
@@ -494,13 +527,13 @@ interface Native {
494
527
  txAbort(tx: TxHandle): void
495
528
 
496
529
  /**
497
- * Prepares a program (IR as data, ids only; plan pinned at prepare).
530
+ * Prepares a query (IR as data, ids only; plan pinned at prepare).
498
531
  * Roster errors return as data.
499
532
  */
500
- dbPrepare(db: DbHandle, program: ProgramIr): PrepareResult
533
+ dbPrepare(db: DbHandle, query: ParsedQuery): PrepareResult
501
534
  /**
502
535
  * Executes against a snapshot with positional params. One-copy owned
503
- * rows out, column order = the program's head order; answers are a set
536
+ * rows out, column order = the query's head order; answers are a set
504
537
  * — the host sorts.
505
538
  */
506
539
  preparedExecute(prepared: PreparedHandle, snap: SnapshotHandle, params: readonly QueryParam[]): FactValue[][]
@@ -608,6 +641,7 @@ function bridged<T>(context: string, run: () => T): T {
608
641
 
609
642
  export type {
610
643
  AggOpIr,
644
+ ArgOpIr,
611
645
  AtomIr,
612
646
  AtomSourceIr,
613
647
  CmpOpIr,
@@ -621,22 +655,24 @@ export type {
621
655
  Explain,
622
656
  FactValue,
623
657
  FindTermIr,
658
+ FoldOpIr,
624
659
  HeadOpIr,
625
660
  HeadTermIr,
661
+ InteriorIr,
626
662
  IntervalValue,
627
663
  Manifest,
628
664
  ManifestField,
629
665
  ManifestRelation,
630
666
  ManifestRow,
631
667
  ManifestStatement,
632
- MaskTermIr,
633
668
  Native,
634
669
  OccurrenceDrift,
635
- PredicateDefIr,
670
+ ParsedQuery,
636
671
  PreparedHandle,
637
672
  PrepareResult,
638
- ProgramIr,
673
+ QueryIr,
639
674
  QueryParam,
675
+ RecIr,
640
676
  RuleIr,
641
677
  SnapshotHandle,
642
678
  SnapshotOpened,