@bjornpagen/bumbledb 0.2.0 → 0.3.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 (84) hide show
  1. package/COOKBOOK.md +462 -406
  2. package/README.md +66 -31
  3. package/dist/closed.d.ts +121 -25
  4. package/dist/closed.d.ts.map +1 -1
  5. package/dist/closed.js +108 -42
  6. package/dist/closed.js.map +1 -1
  7. package/dist/db.d.ts +12 -1
  8. package/dist/db.d.ts.map +1 -1
  9. package/dist/db.js +20 -5
  10. package/dist/db.js.map +1 -1
  11. package/dist/face.d.ts +100 -55
  12. package/dist/face.d.ts.map +1 -1
  13. package/dist/face.js +36 -10
  14. package/dist/face.js.map +1 -1
  15. package/dist/fields.d.ts +50 -79
  16. package/dist/fields.d.ts.map +1 -1
  17. package/dist/fields.js +20 -53
  18. package/dist/fields.js.map +1 -1
  19. package/dist/index.d.ts +17 -12
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +10 -6
  22. package/dist/index.js.map +1 -1
  23. package/dist/law.d.ts +224 -0
  24. package/dist/law.d.ts.map +1 -0
  25. package/dist/law.js +224 -0
  26. package/dist/law.js.map +1 -0
  27. package/dist/lower.d.ts +17 -10
  28. package/dist/lower.d.ts.map +1 -1
  29. package/dist/lower.js +34 -23
  30. package/dist/lower.js.map +1 -1
  31. package/dist/native.d.ts +6 -2
  32. package/dist/native.d.ts.map +1 -1
  33. package/dist/native.js.map +1 -1
  34. package/dist/query/atom.d.ts +88 -50
  35. package/dist/query/atom.d.ts.map +1 -1
  36. package/dist/query/atom.js +4 -1
  37. package/dist/query/atom.js.map +1 -1
  38. package/dist/query/lower.d.ts +71 -56
  39. package/dist/query/lower.d.ts.map +1 -1
  40. package/dist/query/lower.js +90 -43
  41. package/dist/query/lower.js.map +1 -1
  42. package/dist/query/predicate.d.ts +10 -9
  43. package/dist/query/predicate.d.ts.map +1 -1
  44. package/dist/query/predicate.js +2 -2
  45. package/dist/query/predicate.js.map +1 -1
  46. package/dist/query/scope.d.ts +76 -41
  47. package/dist/query/scope.d.ts.map +1 -1
  48. package/dist/query/scope.js +77 -30
  49. package/dist/query/scope.js.map +1 -1
  50. package/dist/query/select.d.ts +5 -5
  51. package/dist/query/select.d.ts.map +1 -1
  52. package/dist/relation.d.ts +21 -8
  53. package/dist/relation.d.ts.map +1 -1
  54. package/dist/relation.js +13 -7
  55. package/dist/relation.js.map +1 -1
  56. package/dist/schema.d.ts +41 -3
  57. package/dist/schema.d.ts.map +1 -1
  58. package/dist/schema.js +16 -2
  59. package/dist/schema.js.map +1 -1
  60. package/dist/spec.d.ts +7 -6
  61. package/dist/spec.d.ts.map +1 -1
  62. package/dist/spec.js.map +1 -1
  63. package/dist/statements.d.ts +61 -31
  64. package/dist/statements.d.ts.map +1 -1
  65. package/dist/statements.js +22 -17
  66. package/dist/statements.js.map +1 -1
  67. package/package.json +2 -2
  68. package/src/closed.ts +243 -68
  69. package/src/db.ts +23 -5
  70. package/src/face.ts +162 -84
  71. package/src/fields.ts +57 -136
  72. package/src/index.ts +42 -16
  73. package/src/law.ts +519 -0
  74. package/src/lower.ts +36 -23
  75. package/src/native.ts +6 -2
  76. package/src/query/atom.ts +105 -58
  77. package/src/query/lower.ts +271 -139
  78. package/src/query/predicate.ts +43 -33
  79. package/src/query/scope.ts +125 -49
  80. package/src/query/select.ts +5 -5
  81. package/src/relation.ts +15 -9
  82. package/src/schema.ts +48 -7
  83. package/src/spec.ts +7 -6
  84. package/src/statements.ts +83 -43
package/src/query/atom.ts CHANGED
@@ -25,8 +25,11 @@
25
25
  */
26
26
 
27
27
  import * as errors from "@superbuilders/errors"
28
- import type { AnyField, Infer, IntervalValue } from "#fields.ts"
28
+ import type { AnyClosed } from "#closed.ts"
29
+ import type { AnyField, ClosedIdField, Infer, IntervalValue } from "#fields.ts"
30
+ import type { ClassLookup, ClassRecordOf, SchemaClasses } from "#law.ts"
29
31
  import type {
32
+ ClassedField,
30
33
  Duration,
31
34
  EnvShape,
32
35
  JoinOk,
@@ -38,7 +41,31 @@ import type {
38
41
  Var
39
42
  } from "#query/scope.ts"
40
43
  import { isTerm } from "#query/scope.ts"
41
- import type { AnyRelation, FieldsShape, Relation } from "#relation.ts"
44
+ import type { AnyRelation, FieldsShape, RelationFields } from "#relation.ts"
45
+
46
+ /**
47
+ * What a query atom matches over: an ordinary relation or a CLOSED
48
+ * vocabulary (ψ query atoms — the engine folds a resolvable closed atom
49
+ * into a plan-constant member set at prepare, or joins the L1-resident
50
+ * virtual image when the shape does not fold; the SDK never pre-folds and
51
+ * never knows which — transparency is the contract).
52
+ */
53
+ type MatchOwner = AnyRelation | AnyClosed
54
+
55
+ /**
56
+ * The matchable field block of an atom owner: a relation's declared
57
+ * fields; a closed relation's SEALED shape — the synthetic `id` (the
58
+ * roster-carrying descriptor) first, then the declared payload columns
59
+ * read through the typed `columns` carrier (the one source of payload
60
+ * typing — no parallel column table exists). The runtime twin is
61
+ * `matchFieldsOf` in `#query/lower.ts`; the id-first ordinal shift the two
62
+ * tiers share is pinned by the lowering golden.
63
+ */
64
+ type MatchFields<R extends MatchOwner> = R extends AnyClosed
65
+ ? { readonly id: ClosedIdField } & R["columns"]
66
+ : R extends AnyRelation
67
+ ? RelationFields<R>
68
+ : never
42
69
 
43
70
  /** One atom-binding position as runtime data. */
44
71
  type BindingTermData =
@@ -47,16 +74,17 @@ type BindingTermData =
47
74
  | { readonly kind: "setParam"; readonly name: string }
48
75
  | { readonly kind: "literal"; readonly value: unknown }
49
76
 
50
- /** One resolved binding: the field's name, its descriptor, and the term. */
77
+ /** One resolved binding: the field's name, its descriptor, its law-computed class, and the term. */
51
78
  interface BindingEntry {
52
79
  readonly field: string
53
80
  readonly data: AnyField
81
+ readonly class: string | undefined
54
82
  readonly term: BindingTermData
55
83
  }
56
84
 
57
- /** One EDB atom as runtime data (either polarity — polarity is the rule item's). */
85
+ /** One EDB atom as runtime data (either polarity — polarity is the rule item's; a closed owner is a ψ atom). */
58
86
  interface AtomData {
59
- readonly relation: AnyRelation
87
+ readonly relation: MatchOwner
60
88
  readonly bindings: readonly BindingEntry[]
61
89
  }
62
90
 
@@ -136,8 +164,8 @@ interface ParamUse {
136
164
  interface RuleData {
137
165
  readonly items: readonly RuleItem[]
138
166
  readonly select: readonly SelectColumn[]
139
- /** Variable name → the field descriptor its FIRST positive binding carries (the runtime env). */
140
- readonly varFields: Readonly<Record<string, AnyField>>
167
+ /** Variable name → the classed slot its FIRST positive binding carries (the runtime env — descriptor + class). */
168
+ readonly varFields: Readonly<Record<string, ClassedField>>
141
169
  readonly paramUses: readonly ParamUse[]
142
170
  }
143
171
 
@@ -174,50 +202,61 @@ type MatchShape<F extends FieldsShape> = {
174
202
  readonly [K in keyof F]?: BindingInput<F[K]>
175
203
  }
176
204
 
205
+ /**
206
+ * One field position of a bindings record as a classed slot: the declared
207
+ * descriptor plus the slot's law-computed class, read off the relation's
208
+ * class record (`CR` — the schema class map's entry for the atom's
209
+ * relation). The one shape every join judgment compares.
210
+ */
211
+ type SlotAt<F extends FieldsShape, CR, K> = {
212
+ readonly field: F[K & keyof F]
213
+ readonly class: ClassLookup<CR, K>
214
+ }
215
+
177
216
  /**
178
217
  * The var binding's judgment against the incoming rule environment: a name
179
- * already bound must land on a domain-equal field.
218
+ * already bound must land on a class-equal slot (bare pairs only with bare).
180
219
  */
181
- type EnvJoinOk<Env extends EnvShape, F extends FieldsShape, K, N extends string> = N extends keyof Env
182
- ? JoinOk<Env[N], F[K & keyof F]>
220
+ type EnvJoinOk<Env extends EnvShape, F extends FieldsShape, CR, K, N extends string> = N extends keyof Env
221
+ ? JoinOk<Env[N], SlotAt<F, CR, K>>
183
222
  : true
184
223
 
185
224
  /**
186
225
  * The var binding's judgment against its OWN record's siblings: two
187
226
  * bindings of one var name inside a single bindings record are the same
188
227
  * join the environment check judges across atoms, so every same-named
189
- * sibling must be domain-equal too. Without this arm two FIRST occurrences
228
+ * sibling must be class-equal too. Without this arm two FIRST occurrences
190
229
  * of one name (a record the environment has not seen yet) would meet no
191
- * check at all — the intra-atom join would silently cross domains.
230
+ * check at all — the intra-atom join would silently cross classes.
192
231
  */
193
- type SiblingJoinOk<F extends FieldsShape, B, K extends keyof B, N extends string> = false extends {
194
- [K2 in Exclude<keyof B & keyof F, K>]: B[K2] extends Var<N> ? JoinOk<F[K2], F[K & keyof F]> : true
232
+ type SiblingJoinOk<F extends FieldsShape, CR, B, K extends keyof B, N extends string> = false extends {
233
+ [K2 in Exclude<keyof B & keyof F, K>]: B[K2] extends Var<N> ? JoinOk<SlotAt<F, CR, K2>, SlotAt<F, CR, K>> : true
195
234
  }[Exclude<keyof B & keyof F, K>]
196
235
  ? false
197
236
  : true
198
237
 
199
238
  /**
200
239
  * The per-property join judgment of a bindings record: a var binding must
201
- * be domain-equal to the rule environment's binding of the name AND to
202
- * every same-named sibling of its own record (a cross-domain reuse maps
240
+ * be class-equal to the rule environment's binding of the name AND to
241
+ * every same-named sibling of its own record (a cross-class reuse maps
203
242
  * the property to `never` — the compile error the old value brand carried,
204
- * now structural).
243
+ * now law-born off the schema type's class map).
205
244
  */
206
- type BindingOk<Env extends EnvShape, F extends FieldsShape, B, K extends keyof B> =
245
+ type BindingOk<Env extends EnvShape, F extends FieldsShape, CR, B, K extends keyof B> =
207
246
  B[K] extends Var<infer N extends string>
208
- ? [EnvJoinOk<Env, F, K, N>, SiblingJoinOk<F, B, K, N>] extends [true, true]
247
+ ? [EnvJoinOk<Env, F, CR, K, N>, SiblingJoinOk<F, CR, B, K, N>] extends [true, true]
209
248
  ? true
210
249
  : false
211
250
  : true
212
251
 
213
252
  /** The validated bindings record (intersect with the inferred `B` — errors land on the offending property). */
214
- type CheckBindings<Env extends EnvShape, F extends FieldsShape, B> = {
215
- readonly [K in keyof B]: K extends keyof F ? (BindingOk<Env, F, B, K> extends true ? B[K] : never) : never
253
+ type CheckBindings<Env extends EnvShape, F extends FieldsShape, CR, B> = {
254
+ readonly [K in keyof B]: K extends keyof F ? (BindingOk<Env, F, CR, B, K> extends true ? B[K] : never) : never
216
255
  }
217
256
 
218
- /** The environment a bindings record contributes: var name → the bound field's descriptor. */
219
- type BindEnv<F extends FieldsShape, B> = {
220
- readonly [K in keyof B & keyof F as B[K] extends Var<infer N extends string> ? N : never]: F[K]
257
+ /** The environment a bindings record contributes: var name → the bound slot (descriptor + class). */
258
+ type BindEnv<F extends FieldsShape, CR, B> = {
259
+ readonly [K in keyof B & keyof F as B[K] extends Var<infer N extends string> ? N : never]: SlotAt<F, CR, K>
221
260
  }
222
261
 
223
262
  /** The params-object fragments a bindings record contributes (one union member per param use). */
@@ -257,9 +296,9 @@ interface Tree<Ch extends readonly AnyTreeChild[]> {
257
296
  * membership at `.where` IS the safety rule, a compile error before it is
258
297
  * the engine's refusal.
259
298
  */
260
- interface NotAtom<F extends FieldsShape, B> {
299
+ interface NotAtom<R extends MatchOwner, B> {
261
300
  readonly cond: "not"
262
- readonly relation: Relation<string, F>
301
+ readonly relation: R
263
302
  readonly bindings: B
264
303
  }
265
304
 
@@ -270,7 +309,7 @@ type AnyCmp = Cmp<CmpKind, unknown, unknown, unknown>
270
309
  type AnyTreeChild = AnyCmp | Tree<readonly AnyTreeChild[]>
271
310
 
272
311
  /** Any negated-atom value. */
273
- type AnyNotAtom = NotAtom<FieldsShape, unknown>
312
+ type AnyNotAtom = NotAtom<MatchOwner, unknown>
274
313
 
275
314
  /** Any `.where` input: a comparison, a condition tree, or a negated atom. */
276
315
  type AnyCond = AnyCmp | Tree<readonly AnyTreeChild[]> | AnyNotAtom
@@ -464,26 +503,29 @@ function or<const C extends readonly AnyTreeChild[]>(...children: C): Tree<C> {
464
503
  * rejects every binding some matching fact extends. A negated atom binds
465
504
  * nothing, only rejects: every variable it names must be positively bound
466
505
  * in the rule, which `.where`'s environment check makes a COMPILE error
467
- * (the engine's safety refusal stands behind it).
506
+ * (the engine's safety refusal stands behind it). A CLOSED owner is legal
507
+ * here too — the engine folds a resolvable negated closed atom to the
508
+ * COMPLEMENT of its member set (domain-witness guarded), and the SDK's
509
+ * negation rules apply to it unchanged.
468
510
  */
469
- function not<Name extends string, F extends FieldsShape, const B extends MatchShape<F>>(
470
- relation: Relation<Name, F>,
511
+ function not<R extends MatchOwner, const B extends MatchShape<MatchFields<R>>>(
512
+ relation: R,
471
513
  bindings: B
472
- ): NotAtom<F, B> {
473
- const value: NotAtom<F, B> = { cond: "not", relation, bindings }
514
+ ): NotAtom<R, B> {
515
+ const value: NotAtom<R, B> = { cond: "not", relation, bindings }
474
516
  return Object.freeze(value)
475
517
  }
476
518
 
477
519
  /** Whether a var name is bound in the environment at an orderable (u64/i64) field. */
478
520
  type OrderVarOk<Env extends EnvShape, N extends string> = N extends keyof Env
479
- ? Env[N]["kind"] extends "u64" | "i64"
521
+ ? Env[N]["field"]["kind"] extends "u64" | "i64"
480
522
  ? true
481
523
  : false
482
524
  : false
483
525
 
484
526
  /** Whether a var name is bound at an interval field. */
485
527
  type IntervalVarOk<Env extends EnvShape, N extends string> = N extends keyof Env
486
- ? Env[N]["kind"] extends "interval"
528
+ ? Env[N]["field"]["kind"] extends "interval"
487
529
  ? true
488
530
  : false
489
531
  : false
@@ -502,7 +544,7 @@ type PointSideOk<Env extends EnvShape, T> = T extends Var<infer N extends string
502
544
  /** One interval side's judgment. */
503
545
  type IntervalSideOk<Env extends EnvShape, T> = T extends Var<infer N extends string> ? IntervalVarOk<Env, N> : true
504
546
 
505
- /** The `eq`/`ne` judgment: left var bound; right joins it (domain-equal var, param, or an exact-type literal). */
547
+ /** The `eq`/`ne` judgment: left var bound; right joins it (class-equal var, param, or an exact-type literal). */
506
548
  type EqOk<Env extends EnvShape, L, R> =
507
549
  L extends Var<infer N extends string>
508
550
  ? N extends keyof Env
@@ -512,34 +554,36 @@ type EqOk<Env extends EnvShape, L, R> =
512
554
  : false
513
555
  : R extends Param<string> | SetParam<string>
514
556
  ? true
515
- : [R] extends [Infer<Env[N]>]
557
+ : [R] extends [Infer<Env[N]["field"]>]
516
558
  ? true
517
559
  : false
518
560
  : false
519
561
  : false
520
562
 
521
- /** One negated-atom binding's judgment: a var must be positively bound (safety) AND domain-equal. */
522
- type NotBindingOk<Env extends EnvShape, F extends AnyField, T> =
523
- T extends Var<infer N extends string> ? (N extends keyof Env ? JoinOk<Env[N], F> : false) : true
563
+ /** One negated-atom binding's judgment: a var must be positively bound (safety) AND class-equal. */
564
+ type NotBindingOk<Env extends EnvShape, S extends ClassedField, T> =
565
+ T extends Var<infer N extends string> ? (N extends keyof Env ? JoinOk<Env[N], S> : false) : true
524
566
 
525
- /** The whole negated atom's judgment. */
526
- type NotOk<Env extends EnvShape, F extends FieldsShape, B> = false extends {
527
- [K in keyof B]: NotBindingOk<Env, K extends keyof F ? F[K] : never, B[K]>
567
+ /** The whole negated atom's judgment (`CR` — the negated relation's class record off the schema class map). */
568
+ type NotOk<Env extends EnvShape, F extends FieldsShape, CR, B> = false extends {
569
+ [K in keyof B]: NotBindingOk<Env, SlotAt<F, CR, K>, B[K]>
528
570
  }[keyof B]
529
571
  ? false
530
572
  : true
531
573
 
532
574
  /**
533
575
  * One condition's judgment against the rule environment — the type-level
534
- * twin of the engine's comparison roster: domain-equal joins, orderable
535
- * order sides (an interval var under a non-`pointIn` op is exactly here
536
- * refused), kind-correct `pointIn`/`covers`/`allen` sides, and negated-atom
537
- * safety. The leading `[AnyTreeChild] extends [C]` arm is the recursion's
538
- * base case: at an UNRESOLVED constraint (the whole condition union — or a
539
- * tree's child union, which is the union itself) the judgment is vacuously
540
- * true without it the constraint instantiation recurses into itself.
576
+ * twin of the engine's comparison roster: class-equal joins (off the
577
+ * schema type's class map), orderable order sides (an interval var under a
578
+ * non-`pointIn` op is exactly here refused), kind-correct
579
+ * `pointIn`/`covers`/`allen` sides, and negated-atom safety (the negated
580
+ * relation's class record is resolved through `Classes` by its name). The
581
+ * leading `[AnyTreeChild] extends [C]` arm is the recursion's base case:
582
+ * at an UNRESOLVED constraint (the whole condition union or a tree's
583
+ * child union, which is the union itself) the judgment is vacuously true —
584
+ * without it the constraint instantiation recurses into itself.
541
585
  */
542
- type CondOkBool<Env extends EnvShape, C> = [AnyTreeChild] extends [C]
586
+ type CondOkBool<Env extends EnvShape, Classes extends SchemaClasses, C> = [AnyTreeChild] extends [C]
543
587
  ? true
544
588
  : C extends Cmp<infer Op, infer L, infer R, unknown>
545
589
  ? Op extends "eq" | "ne"
@@ -558,23 +602,24 @@ type CondOkBool<Env extends EnvShape, C> = [AnyTreeChild] extends [C]
558
602
  : false
559
603
  : false
560
604
  : C extends Tree<infer Ch extends readonly AnyTreeChild[]>
561
- ? false extends CondOkBool<Env, Ch[number]>
605
+ ? false extends CondOkBool<Env, Classes, Ch[number]>
562
606
  ? false
563
607
  : true
564
- : C extends NotAtom<infer F extends FieldsShape, infer B>
565
- ? NotOk<Env, F, B>
608
+ : C extends NotAtom<infer R extends MatchOwner, infer B>
609
+ ? NotOk<Env, MatchFields<R>, ClassRecordOf<Classes, R["name"]>, B>
566
610
  : false
567
611
 
568
612
  /** The validated `.where` argument (intersect with the inferred condition type). */
569
- type CheckCond<Env extends EnvShape, C> = CondOkBool<Env, C> extends true ? C : never
613
+ type CheckCond<Env extends EnvShape, Classes extends SchemaClasses, C> =
614
+ CondOkBool<Env, Classes, C> extends true ? C : never
570
615
 
571
616
  /** The `eq`/`ne` params contribution: the param typed by the left variable's field. */
572
617
  type EqParams<Env extends EnvShape, L, R> =
573
618
  L extends Var<infer N extends string>
574
619
  ? R extends Param<infer P extends string>
575
- ? { readonly [Q in P]: Infer<Env[N & keyof Env]> }
620
+ ? { readonly [Q in P]: Infer<Env[N & keyof Env]["field"]> }
576
621
  : R extends SetParam<infer P extends string>
577
- ? { readonly [Q in P]: readonly Infer<Env[N & keyof Env]>[] }
622
+ ? { readonly [Q in P]: readonly Infer<Env[N & keyof Env]["field"]>[] }
578
623
  : never
579
624
  : never
580
625
 
@@ -607,8 +652,8 @@ type CondParams<Env extends EnvShape, C> = [AnyTreeChild] extends [C]
607
652
  : never
608
653
  : C extends Tree<infer Ch extends readonly AnyTreeChild[]>
609
654
  ? CondParams<Env, Ch[number]>
610
- : C extends NotAtom<infer F extends FieldsShape, infer B>
611
- ? BindParams<F, B>
655
+ : C extends NotAtom<infer R extends MatchOwner, infer B>
656
+ ? BindParams<MatchFields<R>, B>
612
657
  : never
613
658
 
614
659
  /** The flattened params record one bindings record contributes. */
@@ -643,6 +688,8 @@ export type {
643
688
  IntervalSide,
644
689
  IntervalVarOk,
645
690
  MaskData,
691
+ MatchFields,
692
+ MatchOwner,
646
693
  MatchShape,
647
694
  NotAtom,
648
695
  OrderSide,