@bjornpagen/bumbledb 0.1.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 (112) hide show
  1. package/COOKBOOK.md +1450 -0
  2. package/README.md +69 -30
  3. package/dist/closed.d.ts +157 -38
  4. package/dist/closed.d.ts.map +1 -1
  5. package/dist/closed.js +232 -47
  6. package/dist/closed.js.map +1 -1
  7. package/dist/count.d.ts +64 -17
  8. package/dist/count.d.ts.map +1 -1
  9. package/dist/count.js +37 -14
  10. package/dist/count.js.map +1 -1
  11. package/dist/db.d.ts +27 -8
  12. package/dist/db.d.ts.map +1 -1
  13. package/dist/db.js +33 -10
  14. package/dist/db.js.map +1 -1
  15. package/dist/exhume.d.ts +12 -11
  16. package/dist/exhume.d.ts.map +1 -1
  17. package/dist/exhume.js +7 -6
  18. package/dist/exhume.js.map +1 -1
  19. package/dist/face.d.ts +135 -30
  20. package/dist/face.d.ts.map +1 -1
  21. package/dist/face.js +44 -19
  22. package/dist/face.js.map +1 -1
  23. package/dist/fields.d.ts +130 -130
  24. package/dist/fields.d.ts.map +1 -1
  25. package/dist/fields.js +60 -94
  26. package/dist/fields.js.map +1 -1
  27. package/dist/index.d.ts +29 -24
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +19 -14
  30. package/dist/index.js.map +1 -1
  31. package/dist/law.d.ts +224 -0
  32. package/dist/law.d.ts.map +1 -0
  33. package/dist/law.js +224 -0
  34. package/dist/law.js.map +1 -0
  35. package/dist/lower.d.ts +17 -7
  36. package/dist/lower.d.ts.map +1 -1
  37. package/dist/lower.js +66 -24
  38. package/dist/lower.js.map +1 -1
  39. package/dist/marshal.d.ts +36 -21
  40. package/dist/marshal.d.ts.map +1 -1
  41. package/dist/marshal.js +41 -25
  42. package/dist/marshal.js.map +1 -1
  43. package/dist/native.d.ts +6 -2
  44. package/dist/native.d.ts.map +1 -1
  45. package/dist/native.js +2 -2
  46. package/dist/native.js.map +1 -1
  47. package/dist/query/atom.d.ts +370 -174
  48. package/dist/query/atom.d.ts.map +1 -1
  49. package/dist/query/atom.js +75 -172
  50. package/dist/query/atom.js.map +1 -1
  51. package/dist/query/lower.d.ts +312 -109
  52. package/dist/query/lower.d.ts.map +1 -1
  53. package/dist/query/lower.js +906 -387
  54. package/dist/query/lower.js.map +1 -1
  55. package/dist/query/predicate.d.ts +70 -88
  56. package/dist/query/predicate.d.ts.map +1 -1
  57. package/dist/query/predicate.js +118 -72
  58. package/dist/query/predicate.js.map +1 -1
  59. package/dist/query/run.d.ts +19 -16
  60. package/dist/query/run.d.ts.map +1 -1
  61. package/dist/query/run.js +31 -24
  62. package/dist/query/run.js.map +1 -1
  63. package/dist/query/scope.d.ts +178 -127
  64. package/dist/query/scope.d.ts.map +1 -1
  65. package/dist/query/scope.js +111 -108
  66. package/dist/query/scope.js.map +1 -1
  67. package/dist/query/select.d.ts +102 -80
  68. package/dist/query/select.d.ts.map +1 -1
  69. package/dist/query/select.js +39 -34
  70. package/dist/query/select.js.map +1 -1
  71. package/dist/relation.d.ts +48 -38
  72. package/dist/relation.d.ts.map +1 -1
  73. package/dist/relation.js +24 -19
  74. package/dist/relation.js.map +1 -1
  75. package/dist/schema.d.ts +41 -3
  76. package/dist/schema.d.ts.map +1 -1
  77. package/dist/schema.js +34 -9
  78. package/dist/schema.js.map +1 -1
  79. package/dist/spec.d.ts +7 -5
  80. package/dist/spec.d.ts.map +1 -1
  81. package/dist/spec.js.map +1 -1
  82. package/dist/statements.d.ts +91 -36
  83. package/dist/statements.d.ts.map +1 -1
  84. package/dist/statements.js +42 -12
  85. package/dist/statements.js.map +1 -1
  86. package/package.json +4 -3
  87. package/src/closed.ts +448 -95
  88. package/src/count.ts +112 -18
  89. package/src/db.ts +45 -17
  90. package/src/exhume.ts +12 -11
  91. package/src/face.ts +211 -41
  92. package/src/fields.ts +199 -234
  93. package/src/index.ts +78 -61
  94. package/src/law.ts +519 -0
  95. package/src/lower.ts +82 -27
  96. package/src/marshal.ts +48 -30
  97. package/src/native.ts +8 -4
  98. package/src/query/atom.ts +525 -374
  99. package/src/query/lower.ts +1469 -538
  100. package/src/query/predicate.ts +208 -161
  101. package/src/query/run.ts +35 -25
  102. package/src/query/scope.ts +264 -218
  103. package/src/query/select.ts +168 -93
  104. package/src/relation.ts +47 -47
  105. package/src/schema.ts +69 -18
  106. package/src/spec.ts +7 -5
  107. package/src/statements.ts +124 -41
  108. package/dist/brand.d.ts +0 -59
  109. package/dist/brand.d.ts.map +0 -1
  110. package/dist/brand.js +0 -47
  111. package/dist/brand.js.map +0 -1
  112. package/src/brand.ts +0 -82
package/README.md CHANGED
@@ -4,6 +4,8 @@ Type-theoretic TypeScript SDK for the [bumbledb](https://github.com/bjornpagen/b
4
4
 
5
5
  bumbledb models data as relations judged by statements (functionality, containment, cardinality) and queried with Datalog expressed as plain values — no SQL, no query-string parser. The SDK is a thin, fully typed surface over an in-process native engine (LMDB storage, MVCC snapshots, a single-writer witnessed write loop).
6
6
 
7
+ The surface is structural to the bone. Relation declarations are pure structure — kind, width, element, fresh, nothing else — and domains are never declared anywhere: **the laws type the columns**. `schema()` computes every field's equivalence class from the statement list itself, so the containments and mirrors you already write ARE the typing, at compile time and again at construction. Values stay bare (`bigint`, `string`, …); identity lives in the class the laws compute, not in a wrapper.
8
+
7
9
  > **Research-grade, one platform.** This is a `0.x` release of an embedded engine under active development. It targets a single platform today (below), the API is not yet frozen across `0.x`, and the FFI ABI is pinned exactly per version. Treat it as an early adopter's tool, not a production datastore.
8
10
 
9
11
  ## Platform support
@@ -18,32 +20,47 @@ pnpm add @bjornpagen/bumbledb
18
20
 
19
21
  ## Quick start
20
22
 
21
- Declare a schema, write facts through a transaction, and query with Datalog as
22
- values. Everything is typed end to end branded ids, inferred query rows, and
23
- rejections that arrive as data rather than exceptions.
23
+ Declare relations as pure structure, let the statement list type every column,
24
+ write facts through a transaction, and query with Datalog as values.
25
+ Everything is typed end to end bare structural values in law-computed
26
+ classes, inferred query rows, and rejections that arrive as data rather than
27
+ exceptions.
24
28
 
25
29
  ```ts
26
- import { Db, relation, schema, contained, on, query, match, u64, str, type Brand, type Scope } from "@bjornpagen/bumbledb"
27
-
28
- // Branded, fresh-minted id types.
29
- const HolderId = u64.newtype("HolderId")
30
- const AccountId = u64.newtype("AccountId")
30
+ import { bool, closed, contained, Db, gt, key, on, query, relation, schema, u64 } from "@bjornpagen/bumbledb"
31
+
32
+ // A closed relation: a sealed roster of axioms with typed payload columns.
33
+ const Kind = closed(
34
+ "Kind",
35
+ { mastered: bool, rank: u64 },
36
+ {
37
+ DirectPass: { mastered: true, rank: 30n },
38
+ JudgedPass: { mastered: true, rank: 20n },
39
+ Failed: { mastered: false, rank: 10n }
40
+ }
41
+ )
31
42
 
32
- // Relations. `.fresh` marks an engine-minted primary key.
33
- const Holder = relation("Holder", { id: HolderId.fresh, name: str })
34
- const Account = relation("Account", { id: AccountId.fresh, holder: HolderId })
43
+ // Relations are pure structure no domain is declared anywhere.
44
+ // `u64.fresh` marks an engine-minted primary key.
45
+ const Attempt = relation("Attempt", { id: u64.fresh, kind: Kind.id })
46
+ const Certificate = relation("Certificate", { attempt: u64, kind: Kind.id })
35
47
 
36
- // A theory: every Account.holder must reference an existing Holder.id.
37
- const Ledger = schema("Ledger", { Holder, Account }, [contained(on(Account, "holder"), on(Holder, "id"))])
48
+ // THE LAWS TYPE THE COLUMNS: schema() computes every field's class FROM this
49
+ // statement list the containments are the typing. The last statement uses
50
+ // ψ-selection: a certificate may only ever cite a mastered kind.
51
+ const Review = schema("Review", { Kind, Attempt, Certificate }, [
52
+ contained(on(Attempt, "kind"), on(Kind, "id")),
53
+ key(Certificate, ["attempt"]),
54
+ contained(on(Certificate, "attempt"), on(Attempt, "id")),
55
+ contained(on(Certificate, "kind"), on(Kind.where({ mastered: true }), "id"))
56
+ ])
38
57
 
39
- const db = await Db.create("./ledger.db", Ledger)
58
+ const db = await Db.create("./review.db", Review)
40
59
 
41
60
  // Write. The delta is judged against every statement at commit.
42
- let adaId: Brand<bigint, "HolderId"> | undefined
43
61
  const result = db.write((tx) => {
44
- const ada = tx.insert(Holder, { name: "ada" }) // ada.id is a branded HolderId
45
- adaId = ada.id
46
- tx.insert(Account, { holder: ada.id })
62
+ const attempt = tx.insert(Attempt, { kind: Kind.DirectPass }) // attempt.id minted, a bare bigint
63
+ tx.insert(Certificate, { attempt: attempt.id, kind: Kind.DirectPass })
47
64
  })
48
65
 
49
66
  // Rejection-as-data: no throw — a rejected commit is a typed value carrying
@@ -54,24 +71,46 @@ if (!result.ok) {
54
71
  }
55
72
  }
56
73
 
57
- // Query: Datalog as values. Rows are typed from the `select` shape.
58
- const accountsOf = query(Ledger, ($: Scope<(typeof Ledger)["relations"]>) => {
59
- const acct = $.var(Account.fields.id)
60
- const holder = $.param("holder", Holder.fields.id)
61
- return { rules: [[match(Account, { id: acct, holder })]], select: { acct } }
74
+ // Query: Datalog as values. Vars are named and typed by the class of their
75
+ // first binding; params are typed by use; rows are typed from the select.
76
+ // `gt` is one of the free comparison exports.
77
+ const certifiedAbove = query(Review).rule((r) => {
78
+ const { a, k, rank } = r.vars("a", "k", "rank")
79
+ return r
80
+ .match(Certificate, { attempt: a, kind: k })
81
+ .match(Kind, { id: k, mastered: true, rank }) // ψ on the read side too
82
+ .where(gt(rank, r.param("floor")))
83
+ .select("a", "rank")
62
84
  })
63
85
 
64
- const prepared = db.prepare(accountsOf)
65
- const rows = db.execute(prepared, { holder: adaId }) // rows: { acct: AccountId }[]
86
+ const prepared = db.prepare(certifiedAbove)
87
+ const rows = db.execute(prepared, { floor: 15n }) // rows: { a: bigint; rank: bigint }[]
88
+ console.log(rows)
89
+
90
+ // Host dispatch over the sealed roster — exhaustive by construction; each
91
+ // arm receives its axiom row.
92
+ const label = Kind.match(Kind.JudgedPass, {
93
+ DirectPass: (row) => `mastered, rank ${row.rank}`,
94
+ JudgedPass: (row) => `mastered, rank ${row.rank}`,
95
+ Failed: () => "not mastered"
96
+ })
97
+ console.log(label) // "mastered, rank 20"
66
98
  ```
67
99
 
100
+ Every `ts` fence in this README is extracted and type-checked against the
101
+ real surface by `test/readme.test.ts` — the examples cannot drift.
102
+
68
103
  ## Surface
69
104
 
70
- - The type kernel — brands, fields, `relation()`, `closed()`.
71
- - The statement algebra — `schema()`, `key`, `contained`, `mirrors`, `window`.
72
- - The `Db` runtime — path-cached stores, transactions, typed violations, scoped snapshot reads, the witnessed write loop.
73
- - The query surface — Datalog as values: scoped vars/params, atoms, negation, conditions, aggregates, engine recursion via predicates, `db.prepare`.
74
- - The exhume surface — `Db.exhume`, the schema-independent read path: a store's self-described shapes and raw facts by name.
105
+ - The structural type kernel — fields as pure structure (`bool`, `bytes`, `i64`, `u64`, `str`, `interval`, `span`), `relation()`, and `closed()` sealed rosters with typed axiom payloads and exhaustive host dispatch via `.match`. Domains are never declared: `schema()` computes every field's class from the statement list.
106
+ - The statement algebra — `schema()`, `key`, `contained`, `mirrors`, `window`; faces via `on`/`oneOf`; counts via `exactly`, `atLeast`, `atMost`, `between`, `none`; ψ-selection via `.where` on relations and closed rosters.
107
+ - The `Db` runtime — `Db.create`/`Db.open`, path-cached stores, transactions, typed violations, scoped snapshot reads, the witnessed write loop with `abandon`.
108
+ - The query surface — Datalog as values, `query(S).rule(r => ...)`: named vars, params typed by use, negation, aggregates, and the free comparison/connective exports (`eq`, `ne`, `lt`, `le`, `gt`, `ge`, `and`, `or`, `not`, `allen`/`ALLEN`, `pointIn`, `covers`); stratified recursion via `program()`; `db.prepare` as a plain value.
109
+ - The exhume surface — `Db.exhume`, the schema-independent read path: a store's self-described shapes and raw facts by name, with typed refusals (`ErrExhumeNoDescriptor`, `ErrExhumeFormatMismatch`, `ErrExhumeCorruption`).
110
+
111
+ ## Cookbook
112
+
113
+ The engine cookbook's 29 modeling recipes, translated to this SDK's structural API: [COOKBOOK.md](./COOKBOOK.md). Two referees hold it: `test/cookbook-doc.test.ts` extracts the document's own `ts` fences and type-checks them against the real surface (the doc itself cannot drift), and `test/cookbook.test.ts` runs compiled copies of the recipes — each schema admitted by the real engine, its fingerprint asserted against the cross-host goldens the Rust cookbook suite also pins, every query snippet lowered through `db.prepare`.
75
114
 
76
115
  ## Architecture
77
116
 
package/dist/closed.d.ts CHANGED
@@ -1,28 +1,59 @@
1
1
  /**
2
2
  * Closed relations (`docs/architecture/10-data-model.md` § closed
3
3
  * relations): a vocabulary whose extension is declared in the schema — two
4
- * tiers, one function. The emission per closed relation mirrors the macro's
5
- * (host-enum analog): handle CONSTANTS on the value (`Kind.Checking`, ids =
6
- * declaration order), the `fromId` weld, an `id` field constructor
7
- * pre-branded with the handle newtype for other relations' field blocks
8
- * (`kind: Kind.id`), and payload readback (`Kind.axioms`). No fact type and
9
- * no insert surface exist closed relations are unwritable by
10
- * construction: the value simply lacks the writable relation shape.
4
+ * tiers, one function. The emission per closed relation mirrors the
5
+ * macro's (host-enum analog): handle CONSTANTS on the value
6
+ * (`Kind.Checking`, ids = declaration order, each a BARE `bigint` no
7
+ * brand), the `fromId` weld, an `id` field descriptor carrying the CLOSED
8
+ * LINKAGE (the roster — pure structure, no declared domain: the laws type
9
+ * the columns, and `schema()` names the id's generator class `"Kind.id"`)
10
+ * for other relations' field blocks (`kind: Kind.id`), payload readback
11
+ * (`Kind.axioms`), and the declared payload column descriptors
12
+ * (`Kind.columns` — the runtime twin of the `Cols` type parameter, which
13
+ * the face layer's structural wall reads). Bare tier: `closed("Kind", ["Checking",
14
+ * "Savings"])`. Payload tier: `closed("Sev", { pages: bool }, { Critical:
15
+ * { pages: true }, ... })` — one call, three arguments (the curried tier-2
16
+ * spelling is DELETED — canonical utterance): the axioms record IS the
17
+ * handle declaration, every handle carrying every column exactly once
18
+ * (type-enforced). No fact type and no insert surface exist — closed
19
+ * relations are unwritable by construction: the value simply lacks the
20
+ * writable relation shape. Both tiers mint `match()` — exhaustive dispatch
21
+ * over the handle union (arms typed by the mapped type, so a missing or
22
+ * extra arm is a compile error; the payload tier's arm receives the typed
23
+ * axiom row). The payload tier additionally mints `where()` — the
24
+ * ψ-selection surface (`Kind.where({ mastered: true })` as a face source),
25
+ * resolved through the ONE selection machine
26
+ * (`relation.ts::resolveSelection`); the bare tier has no payload columns to
27
+ * select on, so `.where` is absent there, at the type AND on the value.
11
28
  */
12
- import type { Brand } from "#brand.ts";
13
- import { type AnyField, type ClosedIdField, type FieldData, type FieldValue } from "#fields.ts";
29
+ import type { OneOf } from "#face.ts";
30
+ import { type AnyField, type ClosedIdField, type Infer } from "#fields.ts";
31
+ import { type SelectionBinding } from "#relation.ts";
14
32
  import type { LiteralSpec } from "#spec.ts";
15
33
  /**
16
- * A payload column of a closed relation: any field constructor except a
34
+ * A payload column of a closed relation: any field descriptor except a
17
35
  * fresh-marked one (a vocabulary's rows are ground axioms, never minted).
18
36
  */
19
- type PayloadField = AnyField & {
20
- readonly data: FieldData<false>;
37
+ type PayloadField = Exclude<AnyField, {
38
+ readonly fresh: true;
39
+ }>;
40
+ /**
41
+ * A declared payload column BLOCK: name → descriptor, with `id`
42
+ * unspellable — the sealed shape mints the synthetic `id` itself (ordinal
43
+ * 0 of the matchable fields), so a declared column named `id` would be
44
+ * shadowed by the synthetic slot everywhere the shape resolves by name
45
+ * (`matchFieldsOf`, the projected face, `spec.rs`'s resolver). The wall is
46
+ * typed here and judged again at construction in {@link mintClosed} — the
47
+ * runtime twin for untyped callers, warmer and earlier than the engine's
48
+ * `DuplicateFieldName` at `Db.create`.
49
+ */
50
+ type PayloadColumns = Record<string, PayloadField> & {
51
+ readonly id?: never;
21
52
  };
22
- /** One declared payload column: name plus its field description. */
53
+ /** One declared payload column: name plus its field descriptor. */
23
54
  interface ClosedColumn {
24
55
  readonly name: string;
25
- readonly field: FieldData;
56
+ readonly field: PayloadField;
26
57
  }
27
58
  /**
28
59
  * One ground axiom, already lowered: the handle plus one wire literal per
@@ -41,57 +72,145 @@ interface ClosedData {
41
72
  readonly columns: readonly ClosedColumn[];
42
73
  readonly rows: readonly ClosedRow[];
43
74
  }
44
- /** One axiom row as the host writes and reads it: column name to host value. */
45
- type AxiomRow<Cols> = {
46
- readonly [C in keyof Cols]: FieldValue<Cols[C]>;
75
+ /** One axiom row as the host writes and reads it: column name to bare structural value. */
76
+ type AxiomRow<Cols extends Record<string, PayloadField>> = {
77
+ readonly [C in keyof Cols]: Infer<Cols[C]>;
47
78
  };
48
79
  /**
49
80
  * The whole axiom record: every handle exactly once, every column exactly
50
- * once per row — a missing or extra axiom, column, or handle is a TYPE
51
- * error (mapped over the handle tuple).
81
+ * once per row — a missing or extra column is a TYPE error (each row is
82
+ * contextually checked against the declared columns), and the handle set
83
+ * IS the record's key set.
52
84
  */
53
- type Axioms<Handles extends readonly string[], Cols> = {
54
- readonly [H in Handles[number]]: AxiomRow<Cols>;
85
+ type Axioms<Handles extends string, Cols extends Record<string, PayloadField>> = {
86
+ readonly [H in Handles]: AxiomRow<Cols>;
55
87
  };
56
88
  /**
57
89
  * The named surface of a closed relation value, minus the handle constants
58
90
  * (which {@link Closed} intersects in).
59
91
  */
60
- interface ClosedCore<Name extends string, Handles extends readonly string[], Cols> {
92
+ interface ClosedCore<Name extends string, Handles extends string, Cols extends Record<string, PayloadField>> {
61
93
  readonly name: Name;
62
94
  /**
63
- * The pre-branded u64 field constructor: `kind: Kind.id` in another
64
- * relation's field block is the reference through which bare handles
65
- * become legal in that relation's selections.
95
+ * The closed reference descriptor: `kind: Kind.id` in another relation's
96
+ * field block is the reference through which bare handle ids become
97
+ * legal in that relation's selections. Pure structure plus the roster —
98
+ * the referencing field's domain is law-born: `schema()` computes it
99
+ * from the declared containment (`"Kind.id"`, the generator class).
66
100
  */
67
- readonly id: ClosedIdField<Name>;
101
+ readonly id: ClosedIdField;
68
102
  readonly data: ClosedData;
69
- /** Payload readback: handle to its declared column values. */
103
+ /** Payload readback: handle to its declared column values, bare and structural. */
70
104
  readonly axioms: Axioms<Handles, Cols>;
105
+ /**
106
+ * The declared payload columns, name → field descriptor — an HONEST
107
+ * frozen runtime record (the descriptors themselves, by identity), and
108
+ * the typed carrier a projected payload column's structural shape is
109
+ * recovered through off the schema type (the face layer's
110
+ * `ProjectedShape` reads it; `data.columns` carries the same
111
+ * descriptors in declaration order for the lowering).
112
+ */
113
+ readonly columns: Cols;
71
114
  /** The weld: declaration-order id back to its handle, or undefined beyond the roster. */
72
- fromId(id: Brand<bigint, Name>): Handles[number] | undefined;
115
+ fromId(id: bigint): Handles | undefined;
73
116
  }
74
117
  /**
75
- * A closed relation value: the core surface plus one branded constant per
76
- * handle (`Kind.Checking: Brand<bigint, "Kind">`, ids = declaration order).
118
+ * The `where()` argument of a closed relation: per PAYLOAD column, a bare
119
+ * structural literal of that column's value type or an `oneOf(a, b, ...)`
120
+ * literal set — the ordinary `where()`'s vocabulary exactly. The synthetic
121
+ * `id` is deliberately absent: an id selection is spelled only as handle
122
+ * literals on the REFERENCING side (the canonical-utterance law).
77
123
  */
78
- type Closed<Name extends string, Handles extends readonly string[], Cols> = ClosedCore<Name, Handles, Cols> & {
79
- readonly [H in Handles[number]]: Brand<bigint, Name>;
124
+ type ClosedSelectionInput<Cols extends Record<string, PayloadField>> = {
125
+ readonly [C in keyof Cols]?: Infer<Cols[C]> | OneOf<Infer<Cols[C]>>;
80
126
  };
127
+ /**
128
+ * A closed relation with a ψ selection applied — what `on()` consumes as a
129
+ * σ-carrying closed source (`on(Kind.where({ mastered: true }), "id")`).
130
+ * Deliberately the SAME discriminant shape as the ordinary `Selected`
131
+ * (`relation`/`selection` — `face.ts::faceParts` splits both by `"relation"
132
+ * in source`), and structurally UNMISTAKABLE for one: an `AnyClosed` lacks
133
+ * the relation shape (no `fields` record, no `RelationData`).
134
+ */
135
+ interface SelectedClosed<Name extends string, Handles extends string, Cols extends Record<string, PayloadField>> {
136
+ readonly relation: Closed<Name, Handles, Cols>;
137
+ readonly selection: readonly SelectionBinding[];
138
+ }
139
+ /** Any ψ-selected closed relation value. */
140
+ interface AnySelectedClosed {
141
+ readonly relation: AnyClosed;
142
+ readonly selection: readonly SelectionBinding[];
143
+ }
144
+ /**
145
+ * The ψ-selection surface of a payload-tier closed value. The selection is
146
+ * resolved EAGERLY against the declared columns and lowered as-is — the SDK
147
+ * never pre-folds ψ into an id set: pass-through lowering is what the macro
148
+ * does, and the ENGINE folds against the sealed extension at validate
149
+ * (`compile_member_set`).
150
+ */
151
+ interface ClosedSelectable<Name extends string, Handles extends string, Cols extends Record<string, PayloadField>> {
152
+ where(selection: ClosedSelectionInput<Cols>): SelectedClosed<Name, Handles, Cols>;
153
+ }
154
+ /**
155
+ * Exhaustive dispatch over a BARE closed vocabulary: one arm per handle,
156
+ * no literal types and no brands — the handle-name union on the value's
157
+ * type IS the exhaustiveness proof (a missing arm is a missing-property
158
+ * compile error; an extra arm an excess-property compile error). The bare
159
+ * tier declares no payload, so an arm takes nothing. The arms record types
160
+ * any `bigint` in — the runtime roster refuses an out-of-vocabulary id
161
+ * with a throw, never a misdispatch.
162
+ */
163
+ interface ClosedMatchBare<Handles extends string> {
164
+ match<T>(id: bigint, arms: {
165
+ readonly [H in Handles]: () => T;
166
+ }): T;
167
+ }
168
+ /**
169
+ * Exhaustive dispatch over a PAYLOAD-tier closed vocabulary: the same
170
+ * mapped-type exhaustiveness as the bare tier, and each arm receives its
171
+ * handle's typed axiom row (the declared columns, bare and structural —
172
+ * the frozen readback row from `axioms`).
173
+ */
174
+ interface ClosedMatchPayload<Handles extends string, Cols extends Record<string, PayloadField>> {
175
+ match<T>(id: bigint, arms: {
176
+ readonly [H in Handles]: (row: AxiomRow<Cols>) => T;
177
+ }): T;
178
+ }
179
+ /**
180
+ * A closed relation value: the core surface plus one BARE constant per
181
+ * handle (`Kind.Checking: bigint`, ids = declaration order — the value is
182
+ * structural; the roster judges out-of-vocabulary ids at construction and
183
+ * the engine at commit), plus `match()` on BOTH tiers (bare arms take
184
+ * nothing; payload arms receive the typed axiom row), plus — exactly when
185
+ * payload columns exist — `where()` (the bare tier has nothing to select
186
+ * on, so the method is ABSENT there, not merely uncallable).
187
+ */
188
+ type Closed<Name extends string, Handles extends string, Cols extends Record<string, PayloadField>> = ClosedCore<Name, Handles, Cols> & {
189
+ readonly [H in Handles]: bigint;
190
+ } & ([keyof Cols] extends [never] ? ClosedMatchBare<Handles> : ClosedSelectable<Name, Handles, Cols> & ClosedMatchPayload<Handles, Cols>);
81
191
  /** Any closed relation value, whatever its roster and columns. */
82
192
  interface AnyClosed {
83
193
  readonly name: string;
84
- readonly id: ClosedIdField<string>;
194
+ readonly id: ClosedIdField;
85
195
  readonly data: ClosedData;
86
196
  readonly axioms: Readonly<Record<string, object>>;
197
+ readonly columns: Readonly<Record<string, PayloadField>>;
87
198
  }
88
199
  /** Bare tier: `closed("Kind", ["Checking", "Savings"])` — handles only. */
89
- declare function closed<const Name extends string, const Handles extends readonly [string, ...string[]]>(name: Name, handles: Handles): Closed<Name, Handles, Record<never, never>>;
200
+ declare function closed<const Name extends string, const Handles extends readonly [string, ...string[]]>(name: Name, handles: Handles): Closed<Name, Handles[number], Record<never, never>>;
90
201
  /**
91
- * Payload tier: declared columns plus ground axioms, every handle with
92
- * every column exactly once (type-enforced by {@link Axioms}).
202
+ * Payload tier: declared columns AND ground axioms, one call — `closed(
203
+ * "Grade", { mastered: bool }, { DirectPass: { mastered: true }, Failed:
204
+ * { mastered: false } })`. The curried tier-2 spelling is DELETED
205
+ * (canonical utterance): `Cols` infers from the column block, the handle
206
+ * set from the axioms record's keys (reverse mapped-type inference), and
207
+ * every row is contextually checked against the declared columns — a
208
+ * wrong-typed value errors ON its property. The axioms record's keys ARE
209
+ * the handles (declaration order = key order, integer-index names
210
+ * rejected); every row carries every column exactly once (type-enforced by
211
+ * {@link Axioms}).
93
212
  */
94
- declare function closed<const Name extends string, const Handles extends readonly [string, ...string[]], const Cols extends Record<string, PayloadField>>(name: Name, handles: Handles, columns: Cols, axioms: Axioms<Handles, Cols>): Closed<Name, Handles, Cols>;
95
- export type { AnyClosed, AxiomRow, Axioms, Closed, ClosedColumn, ClosedCore, ClosedData, ClosedRow, PayloadField };
213
+ declare function closed<const Name extends string, const Cols extends PayloadColumns, Handles extends string>(name: Name, columns: Cols, axioms: Axioms<Handles, Cols>): Closed<Name, Handles, Cols>;
214
+ export type { AnyClosed, AnySelectedClosed, AxiomRow, Axioms, Closed, ClosedColumn, ClosedCore, ClosedData, ClosedRow, ClosedSelectionInput, PayloadField, SelectedClosed };
96
215
  export { closed };
97
216
  //# sourceMappingURL=closed.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"closed.d.ts","sourceRoot":"","sources":["../src/closed.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EACN,KAAK,QAAQ,EAEb,KAAK,aAAa,EAElB,KAAK,SAAS,EACd,KAAK,UAAU,EAGf,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAsC3C;;;GAGG;AACH,KAAK,YAAY,GAAG,QAAQ,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,CAAA;CAAE,CAAA;AAElE,oEAAoE;AACpE,UAAU,YAAY;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CACzB;AAED;;;;;GAKG;AACH,UAAU,SAAS;IAClB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAA;CACvC;AAED,+CAA+C;AAC/C,UAAU,UAAU;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAA;IACzC,QAAQ,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,CAAA;CACnC;AAED,gFAAgF;AAChF,KAAK,QAAQ,CAAC,IAAI,IAAI;IAAE,QAAQ,EAAE,CAAC,IAAI,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;CAAE,CAAA;AAEzE;;;;GAIG;AACH,KAAK,MAAM,CAAC,OAAO,SAAS,SAAS,MAAM,EAAE,EAAE,IAAI,IAAI;IACtD,QAAQ,EAAE,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC;CAC/C,CAAA;AAED;;;GAGG;AACH,UAAU,UAAU,CAAC,IAAI,SAAS,MAAM,EAAE,OAAO,SAAS,SAAS,MAAM,EAAE,EAAE,IAAI;IAChF,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAC,IAAI,CAAC,CAAA;IAChC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IACtC,yFAAyF;IACzF,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;CAC5D;AAED;;;GAGG;AACH,KAAK,MAAM,CAAC,IAAI,SAAS,MAAM,EAAE,OAAO,SAAS,SAAS,MAAM,EAAE,EAAE,IAAI,IAAI,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG;IAC7G,QAAQ,EAAE,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC;CACpD,CAAA;AAED,kEAAkE;AAClE,UAAU,SAAS;IAClB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAClC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CACjD;AAED,2EAA2E;AAC3E,iBAAS,MAAM,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,EAAE,KAAK,CAAC,OAAO,SAAS,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,EAC9F,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,GACd,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;AAE9C;;;GAGG;AACH,iBAAS,MAAM,CACd,KAAK,CAAC,IAAI,SAAS,MAAM,EACzB,KAAK,CAAC,OAAO,SAAS,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,EACpD,KAAK,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EAC9C,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;AAwE1G,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,CAAA;AAClH,OAAO,EAAE,MAAM,EAAE,CAAA"}
1
+ {"version":3,"file":"closed.d.ts","sourceRoot":"","sources":["../src/closed.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,EACN,KAAK,QAAQ,EAEb,KAAK,aAAa,EAElB,KAAK,KAAK,EAEV,MAAM,YAAY,CAAA;AACnB,OAAO,EAAoB,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAwB3C;;;GAGG;AACH,KAAK,YAAY,GAAG,OAAO,CAAC,QAAQ,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAA;CAAE,CAAC,CAAA;AAE/D;;;;;;;;;GASG;AACH,KAAK,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,KAAK,CAAA;CAAE,CAAA;AAE5E,mEAAmE;AACnE,UAAU,YAAY;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAA;CAC5B;AAED;;;;;GAKG;AACH,UAAU,SAAS;IAClB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAA;CACvC;AAED,+CAA+C;AAC/C,UAAU,UAAU;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAA;IACzC,QAAQ,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,CAAA;CACnC;AAED,2FAA2F;AAC3F,KAAK,QAAQ,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,IAAI;IAAE,QAAQ,EAAE,CAAC,IAAI,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;CAAE,CAAA;AAEzG;;;;;GAKG;AACH,KAAK,MAAM,CAAC,OAAO,SAAS,MAAM,EAAE,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,IAAI;IAChF,QAAQ,EAAE,CAAC,IAAI,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC;CACvC,CAAA;AAED;;;GAGG;AACH,UAAU,UAAU,CAAC,IAAI,SAAS,MAAM,EAAE,OAAO,SAAS,MAAM,EAAE,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC;IAC1G,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,mFAAmF;IACnF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IACtC;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAA;IACtB,yFAAyF;IACzF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;CACvC;AAED;;;;;;GAMG;AACH,KAAK,oBAAoB,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,IAAI;IACtE,QAAQ,EAAE,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;CACnE,CAAA;AAED;;;;;;;GAOG;AACH,UAAU,cAAc,CAAC,IAAI,SAAS,MAAM,EAAE,OAAO,SAAS,MAAM,EAAE,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9G,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;IAC9C,QAAQ,CAAC,SAAS,EAAE,SAAS,gBAAgB,EAAE,CAAA;CAC/C;AAED,4CAA4C;AAC5C,UAAU,iBAAiB;IAC1B,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;IAC5B,QAAQ,CAAC,SAAS,EAAE,SAAS,gBAAgB,EAAE,CAAA;CAC/C;AAED;;;;;;GAMG;AACH,UAAU,gBAAgB,CAAC,IAAI,SAAS,MAAM,EAAE,OAAO,SAAS,MAAM,EAAE,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC;IAChH,KAAK,CAAC,SAAS,EAAE,oBAAoB,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;CACjF;AAED;;;;;;;;GAQG;AACH,UAAU,eAAe,CAAC,OAAO,SAAS,MAAM;IAC/C,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,QAAQ,EAAE,CAAC,IAAI,OAAO,GAAG,MAAM,CAAC;KAAE,GAAG,CAAC,CAAA;CACnE;AAED;;;;;GAKG;AACH,UAAU,kBAAkB,CAAC,OAAO,SAAS,MAAM,EAAE,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC;IAC7F,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,QAAQ,EAAE,CAAC,IAAI,OAAO,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;KAAE,GAAG,CAAC,CAAA;CACtF;AAED;;;;;;;;GAQG;AACH,KAAK,MAAM,CAAC,IAAI,SAAS,MAAM,EAAE,OAAO,SAAS,MAAM,EAAE,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,IAAI,UAAU,CAC/G,IAAI,EACJ,OAAO,EACP,IAAI,CACJ,GAAG;IAAE,QAAQ,EAAE,CAAC,IAAI,OAAO,GAAG,MAAM;CAAE,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GACnE,eAAe,CAAC,OAAO,CAAC,GACxB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAA;AAE9E,kEAAkE;AAClE,UAAU,SAAS;IAClB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACjD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAA;CACxD;AAsHD,2EAA2E;AAC3E,iBAAS,MAAM,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,EAAE,KAAK,CAAC,OAAO,SAAS,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,EAC9F,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,GACd,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;AAEtD;;;;;;;;;;;GAWG;AACH,iBAAS,MAAM,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,EAAE,KAAK,CAAC,IAAI,SAAS,cAAc,EAAE,OAAO,SAAS,MAAM,EACnG,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,IAAI,EACb,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,GAC3B,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;AA4L9B,YAAY,EACX,SAAS,EACT,iBAAiB,EACjB,QAAQ,EACR,MAAM,EACN,MAAM,EACN,YAAY,EACZ,UAAU,EACV,UAAU,EACV,SAAS,EACT,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,CAAA;AACD,OAAO,EAAE,MAAM,EAAE,CAAA"}