@bjornpagen/bumbledb 0.9.0 → 0.11.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 (73) hide show
  1. package/COOKBOOK.md +155 -136
  2. package/README.md +3 -7
  3. package/dist/capacity.d.ts +14 -1
  4. package/dist/capacity.d.ts.map +1 -1
  5. package/dist/capacity.js.map +1 -1
  6. package/dist/db.d.ts +77 -109
  7. package/dist/db.d.ts.map +1 -1
  8. package/dist/db.js +121 -339
  9. package/dist/db.js.map +1 -1
  10. package/dist/index.d.ts +11 -16
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +7 -10
  13. package/dist/index.js.map +1 -1
  14. package/dist/lower.d.ts.map +1 -1
  15. package/dist/lower.js +8 -1
  16. package/dist/lower.js.map +1 -1
  17. package/dist/native.d.ts +69 -50
  18. package/dist/native.d.ts.map +1 -1
  19. package/dist/native.js.map +1 -1
  20. package/dist/query/atom.d.ts +162 -122
  21. package/dist/query/atom.d.ts.map +1 -1
  22. package/dist/query/atom.js +26 -22
  23. package/dist/query/atom.js.map +1 -1
  24. package/dist/query/find.d.ts +18 -35
  25. package/dist/query/find.d.ts.map +1 -1
  26. package/dist/query/find.js +13 -32
  27. package/dist/query/find.js.map +1 -1
  28. package/dist/query/lower.d.ts +113 -122
  29. package/dist/query/lower.d.ts.map +1 -1
  30. package/dist/query/lower.js +336 -260
  31. package/dist/query/lower.js.map +1 -1
  32. package/dist/query/parse-ir.d.ts +12 -0
  33. package/dist/query/parse-ir.d.ts.map +1 -0
  34. package/dist/query/parse-ir.js +71 -0
  35. package/dist/query/parse-ir.js.map +1 -0
  36. package/dist/query/run.d.ts +2 -2
  37. package/dist/query/run.d.ts.map +1 -1
  38. package/dist/query/run.js +2 -13
  39. package/dist/query/run.js.map +1 -1
  40. package/dist/query/scope.d.ts +4 -16
  41. package/dist/query/scope.d.ts.map +1 -1
  42. package/dist/query/scope.js +1 -6
  43. package/dist/query/scope.js.map +1 -1
  44. package/dist/schema.js +2 -2
  45. package/dist/schema.js.map +1 -1
  46. package/dist/statements.d.ts +15 -9
  47. package/dist/statements.d.ts.map +1 -1
  48. package/dist/statements.js +14 -9
  49. package/dist/statements.js.map +1 -1
  50. package/package.json +2 -2
  51. package/src/capacity.ts +24 -1
  52. package/src/db.ts +182 -443
  53. package/src/index.ts +9 -23
  54. package/src/lower.ts +8 -1
  55. package/src/native.ts +69 -42
  56. package/src/query/atom.ts +255 -165
  57. package/src/query/find.ts +39 -80
  58. package/src/query/lower.ts +578 -432
  59. package/src/query/parse-ir.ts +82 -0
  60. package/src/query/run.ts +2 -14
  61. package/src/query/scope.ts +3 -21
  62. package/src/schema.ts +2 -2
  63. package/src/statements.ts +33 -17
  64. package/dist/order.d.ts +0 -87
  65. package/dist/order.d.ts.map +0 -1
  66. package/dist/order.js +0 -153
  67. package/dist/order.js.map +0 -1
  68. package/dist/query/predicate.d.ts +0 -91
  69. package/dist/query/predicate.d.ts.map +0 -1
  70. package/dist/query/predicate.js +0 -156
  71. package/dist/query/predicate.js.map +0 -1
  72. package/src/order.ts +0 -234
  73. 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
8
+ * runtime (exclusive-lock stores, transactions, typed violations, scoped
9
+ * snapshot reads, one-shot `write`/`writeFrom` with `abandon` — PRD-07, zero
10
10
  * closables), the query surface (Datalog as values, 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.recursive` —
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,8 +129,6 @@ 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,
@@ -148,19 +137,16 @@ export type {
148
137
  QueryRuleChain,
149
138
  QueryRuleScope,
150
139
  QueryStart,
151
- RecRef,
152
140
  RecRuleChain,
153
141
  RecRuleScope,
154
142
  RuleValue,
155
143
  TermOps
156
144
  } from "#query/lower.ts"
157
145
  export { lowerQuery, query } from "#query/lower.ts"
158
- export type { ProgramScope, Rec } from "#query/predicate.ts"
159
- export { program } from "#query/predicate.ts"
146
+ export { parseQueryIr } from "#query/parse-ir.ts"
160
147
  export type {
161
148
  ClassedField,
162
149
  Duration,
163
- MaskParam,
164
150
  MatchFields,
165
151
  MatchOwner,
166
152
  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,35 @@ 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.
79
77
  */
80
- interface ProgramIr {
81
- readonly predicates: readonly PredicateDefIr[]
82
- readonly output: number
78
+ interface QueryIr {
79
+ readonly interiors: readonly InteriorIr[]
80
+ readonly rec: RecIr | null
81
+ readonly head: readonly HeadTermIr[]
82
+ readonly rules: readonly RuleIr[]
83
83
  }
84
84
 
85
- /** One predicate: the head shape its rules align against, and the rules. */
86
- interface PredicateDefIr {
85
+ /** One named interior: the head shape its rules align against, and the rules. */
86
+ interface InteriorIr {
87
87
  readonly head: readonly HeadTermIr[]
88
88
  readonly rules: readonly RuleIr[]
89
89
  }
90
90
 
91
+ /** The optional linear rec: shared head, base arms, rec arms. */
92
+ interface RecIr {
93
+ readonly head: readonly HeadTermIr[]
94
+ readonly base: readonly RuleIr[]
95
+ readonly rec: readonly RuleIr[]
96
+ }
97
+
91
98
  /** One head position: a plain variable slot or an aggregate-op kind. */
92
99
  type HeadTermIr = { readonly kind: "var" } | { readonly kind: "aggregate"; readonly op: HeadOpIr }
93
100
 
94
101
  /** The var-free aggregate-op kind at a head position. */
95
- type HeadOpIr = "sum" | "min" | "max" | "count" | "countDistinct" | "argMax" | "argMin" | "pack"
102
+ type HeadOpIr = "sum" | "min" | "max" | "count" | "pack"
96
103
 
97
104
  /** One rule: conjunctive body, anti-join atoms, condition trees. */
98
105
  interface RuleIr {
@@ -102,12 +109,23 @@ interface RuleIr {
102
109
  readonly conditions: readonly ConditionTreeIr[]
103
110
  }
104
111
 
105
- /** One find term (mirrors `ir::FindTerm`). */
112
+ /** One find term (mirrors `ir::FindTerm`). Count carries no `over`; folds require it. */
113
+ type FoldOpIr = { readonly kind: "sum" } | { readonly kind: "min" } | { readonly kind: "max" }
114
+
115
+ type ArgOpIr = FoldOpIr | { readonly kind: "pack" }
116
+
106
117
  type FindTermIr =
107
118
  | { readonly kind: "var"; readonly var: number }
108
- | { readonly kind: "aggregate"; readonly op: AggOpIr; readonly over?: number }
119
+ | { readonly kind: "aggregate"; readonly op: { readonly kind: "count" } }
120
+ | { readonly kind: "aggregate"; readonly op: ArgOpIr; readonly over: number }
109
121
  | { readonly kind: "measure"; readonly var: number }
110
- | { readonly kind: "aggregateMeasure"; readonly op: AggOpIr; readonly over: number }
122
+ | { readonly kind: "aggregateMeasure"; readonly op: FoldOpIr; readonly over: number }
123
+
124
+ /** Host brand: only {@link parseQueryIr} and `lowerQuery` inhabit this. Phantom — not a runtime key. */
125
+ declare const parsedQueryBrand: unique symbol
126
+
127
+ /** A `QueryIr` that passed the host shape parse (rec/main nonempty, aggregate finds split). */
128
+ type ParsedQuery = QueryIr & { readonly [parsedQueryBrand]: true }
111
129
 
112
130
  /** One aggregate operator (mirrors `ir::AggOp`; Arg ops carry their key). */
113
131
  type AggOpIr =
@@ -115,15 +133,12 @@ type AggOpIr =
115
133
  | { readonly kind: "min" }
116
134
  | { readonly kind: "max" }
117
135
  | { readonly kind: "count" }
118
- | { readonly kind: "countDistinct" }
119
- | { readonly kind: "argMax"; readonly key: number }
120
- | { readonly kind: "argMin"; readonly key: number }
121
136
  | { readonly kind: "pack" }
122
137
 
123
- /** Where an atom draws its facts: a stored relation or a program predicate. */
138
+ /** Where an atom draws its facts: a stored relation or a derived table. */
124
139
  type AtomSourceIr =
125
140
  | { readonly kind: "edb"; readonly relation: number }
126
- | { readonly kind: "idb"; readonly pred: number }
141
+ | { readonly kind: "interior"; readonly interior: number }
127
142
 
128
143
  /**
129
144
  * One atom: named-field bindings as `[fieldId, term]` pairs; absence of a
@@ -142,11 +157,6 @@ type TermIr =
142
157
  | { readonly kind: "literal"; readonly value: TaggedValue }
143
158
  | { readonly kind: "measure"; readonly var: number }
144
159
 
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
160
  /** One comparison operator (mirrors `ir::CmpOp`). */
151
161
  type CmpOpIr =
152
162
  | { readonly kind: "eq" }
@@ -155,7 +165,7 @@ type CmpOpIr =
155
165
  | { readonly kind: "le" }
156
166
  | { readonly kind: "gt" }
157
167
  | { readonly kind: "ge" }
158
- | { readonly kind: "allen"; readonly mask: MaskTermIr }
168
+ | { readonly kind: "allen"; readonly mask: number }
159
169
  | { readonly kind: "pointIn" }
160
170
 
161
171
  /** One comparison condition. */
@@ -236,14 +246,27 @@ interface ViolationFact {
236
246
  * accumulates in u128 and the value crosses WHOLE as bigint (C3:
237
247
  * truncation is unrepresentable).
238
248
  */
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
- }
249
+ type Violation =
250
+ | {
251
+ readonly statementId: number
252
+ readonly kind: "functionality"
253
+ readonly canonical: string
254
+ readonly facts: readonly ViolationFact[]
255
+ }
256
+ | {
257
+ readonly statementId: number
258
+ readonly kind: "containment"
259
+ readonly canonical: string
260
+ readonly direction: "sourceUnsatisfied" | "targetRequired"
261
+ readonly facts: readonly ViolationFact[]
262
+ }
263
+ | {
264
+ readonly statementId: number
265
+ readonly kind: "capacity"
266
+ readonly canonical: string
267
+ readonly measure: bigint
268
+ readonly facts: readonly ViolationFact[]
269
+ }
247
270
 
248
271
  /**
249
272
  * `dbCreate`/`dbOpen`'s domain outcome. `schemaError` spans both spec
@@ -349,7 +372,8 @@ interface Explain {
349
372
  readonly subsumed: ReadonlyArray<Readonly<Record<string, unknown>>>
350
373
  readonly dead: ReadonlyArray<Readonly<Record<string, unknown>>>
351
374
  readonly rules: ReadonlyArray<Readonly<Record<string, unknown>>>
352
- readonly strata: ReadonlyArray<Readonly<Record<string, unknown>>>
375
+ readonly interiors: ReadonlyArray<Readonly<Record<string, unknown>>>
376
+ readonly reach?: Readonly<Record<string, unknown>>
353
377
  }
354
378
 
355
379
  interface Native {
@@ -494,13 +518,13 @@ interface Native {
494
518
  txAbort(tx: TxHandle): void
495
519
 
496
520
  /**
497
- * Prepares a program (IR as data, ids only; plan pinned at prepare).
521
+ * Prepares a query (IR as data, ids only; plan pinned at prepare).
498
522
  * Roster errors return as data.
499
523
  */
500
- dbPrepare(db: DbHandle, program: ProgramIr): PrepareResult
524
+ dbPrepare(db: DbHandle, query: ParsedQuery): PrepareResult
501
525
  /**
502
526
  * Executes against a snapshot with positional params. One-copy owned
503
- * rows out, column order = the program's head order; answers are a set
527
+ * rows out, column order = the query's head order; answers are a set
504
528
  * — the host sorts.
505
529
  */
506
530
  preparedExecute(prepared: PreparedHandle, snap: SnapshotHandle, params: readonly QueryParam[]): FactValue[][]
@@ -608,6 +632,7 @@ function bridged<T>(context: string, run: () => T): T {
608
632
 
609
633
  export type {
610
634
  AggOpIr,
635
+ ArgOpIr,
611
636
  AtomIr,
612
637
  AtomSourceIr,
613
638
  CmpOpIr,
@@ -621,22 +646,24 @@ export type {
621
646
  Explain,
622
647
  FactValue,
623
648
  FindTermIr,
649
+ FoldOpIr,
624
650
  HeadOpIr,
625
651
  HeadTermIr,
652
+ InteriorIr,
626
653
  IntervalValue,
627
654
  Manifest,
628
655
  ManifestField,
629
656
  ManifestRelation,
630
657
  ManifestRow,
631
658
  ManifestStatement,
632
- MaskTermIr,
633
659
  Native,
634
660
  OccurrenceDrift,
635
- PredicateDefIr,
661
+ ParsedQuery,
636
662
  PreparedHandle,
637
663
  PrepareResult,
638
- ProgramIr,
664
+ QueryIr,
639
665
  QueryParam,
666
+ RecIr,
640
667
  RuleIr,
641
668
  SnapshotHandle,
642
669
  SnapshotOpened,