@bjornpagen/bumbledb 0.2.0 → 0.4.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 (94) hide show
  1. package/COOKBOOK.md +503 -427
  2. package/README.md +84 -36
  3. package/dist/closed.d.ts +111 -38
  4. package/dist/closed.d.ts.map +1 -1
  5. package/dist/closed.js +94 -99
  6. package/dist/closed.js.map +1 -1
  7. package/dist/db.d.ts +16 -2
  8. package/dist/db.d.ts.map +1 -1
  9. package/dist/db.js +46 -8
  10. package/dist/db.js.map +1 -1
  11. package/dist/face.d.ts +114 -69
  12. package/dist/face.d.ts.map +1 -1
  13. package/dist/face.js +38 -21
  14. package/dist/face.js.map +1 -1
  15. package/dist/fields.d.ts +72 -87
  16. package/dist/fields.d.ts.map +1 -1
  17. package/dist/fields.js +35 -67
  18. package/dist/fields.js.map +1 -1
  19. package/dist/index.d.ts +18 -13
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +11 -7
  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/marshal.d.ts +33 -6
  32. package/dist/marshal.d.ts.map +1 -1
  33. package/dist/marshal.js +67 -6
  34. package/dist/marshal.js.map +1 -1
  35. package/dist/native.d.ts +6 -2
  36. package/dist/native.d.ts.map +1 -1
  37. package/dist/native.js.map +1 -1
  38. package/dist/query/atom.d.ts +139 -56
  39. package/dist/query/atom.d.ts.map +1 -1
  40. package/dist/query/atom.js +7 -1
  41. package/dist/query/atom.js.map +1 -1
  42. package/dist/query/lower.d.ts +71 -56
  43. package/dist/query/lower.d.ts.map +1 -1
  44. package/dist/query/lower.js +341 -69
  45. package/dist/query/lower.js.map +1 -1
  46. package/dist/query/predicate.d.ts +10 -9
  47. package/dist/query/predicate.d.ts.map +1 -1
  48. package/dist/query/predicate.js +2 -2
  49. package/dist/query/predicate.js.map +1 -1
  50. package/dist/query/run.d.ts +15 -5
  51. package/dist/query/run.d.ts.map +1 -1
  52. package/dist/query/run.js +26 -6
  53. package/dist/query/run.js.map +1 -1
  54. package/dist/query/scope.d.ts +100 -43
  55. package/dist/query/scope.d.ts.map +1 -1
  56. package/dist/query/scope.js +89 -30
  57. package/dist/query/scope.js.map +1 -1
  58. package/dist/query/select.d.ts +5 -5
  59. package/dist/query/select.d.ts.map +1 -1
  60. package/dist/relation.d.ts +29 -15
  61. package/dist/relation.d.ts.map +1 -1
  62. package/dist/relation.js +45 -17
  63. package/dist/relation.js.map +1 -1
  64. package/dist/schema.d.ts +41 -3
  65. package/dist/schema.d.ts.map +1 -1
  66. package/dist/schema.js +16 -2
  67. package/dist/schema.js.map +1 -1
  68. package/dist/spec.d.ts +10 -8
  69. package/dist/spec.d.ts.map +1 -1
  70. package/dist/spec.js.map +1 -1
  71. package/dist/statements.d.ts +67 -31
  72. package/dist/statements.d.ts.map +1 -1
  73. package/dist/statements.js +97 -20
  74. package/dist/statements.js.map +1 -1
  75. package/package.json +2 -2
  76. package/src/closed.ts +214 -146
  77. package/src/db.ts +65 -10
  78. package/src/face.ts +169 -102
  79. package/src/fields.ts +97 -164
  80. package/src/index.ts +43 -18
  81. package/src/law.ts +519 -0
  82. package/src/lower.ts +36 -23
  83. package/src/marshal.ts +74 -7
  84. package/src/native.ts +6 -2
  85. package/src/query/atom.ts +155 -65
  86. package/src/query/lower.ts +572 -167
  87. package/src/query/predicate.ts +43 -33
  88. package/src/query/run.ts +26 -6
  89. package/src/query/scope.ts +161 -51
  90. package/src/query/select.ts +5 -5
  91. package/src/relation.ts +60 -26
  92. package/src/schema.ts +48 -7
  93. package/src/spec.ts +10 -8
  94. package/src/statements.ts +165 -46
package/dist/law.d.ts ADDED
@@ -0,0 +1,224 @@
1
+ /**
2
+ * The law-typing engine (owner ruling 2026-07-18, "option 2, zero debate"):
3
+ * THE LAWS TYPE THE COLUMNS. Domains are declared nowhere — `schema()`
4
+ * computes every field's domain FROM the statement list, at BOTH the type
5
+ * level (this module's type machinery, reading the statements tuple type)
6
+ * and at runtime (a plain union-find over the same pairs), and the two
7
+ * tiers are the same computation by construction.
8
+ *
9
+ * The three class laws (ratified; implemented exactly):
10
+ *
11
+ * 1. GENERATORS — a `fresh` field is a generator and names its class by
12
+ * its declaration coordinate (`"Account.id"`); a closed relation's
13
+ * synthetic id is a generator named `"Kind.id"`.
14
+ * 2. GENERATOR-LESS classes are named by their least member coordinate
15
+ * in relation-declaration × field-declaration order (readable off the
16
+ * relation record and each member's frozen field list at the VALUE
17
+ * tier — deterministic, pinned forever; the wire reads only this
18
+ * tier). At the TYPE tier the same class is carried as its
19
+ * member-coordinate SET (see {@link ClassOfCoord}): TypeScript's
20
+ * union member order is not observably deterministic, so a type-level
21
+ * least-member pick would drift between compilations — the set is the
22
+ * canonical deterministic spelling, the runtime name is always a
23
+ * member of it, and the join judgment is identical at both tiers.
24
+ * 3. BARE — a field in no law has NO class and pairs only with bare in
25
+ * queries (the deliberate sum-domain pointer stays legal).
26
+ *
27
+ * THE WALL: a class containing more than one generator is a contradiction
28
+ * (two mints cannot share a carrier) — a schema-level COMPILE error (the
29
+ * named, self-locating {@link ClassWall}: which generator coordinates
30
+ * collided, through which paired slots) with a construction-time runtime
31
+ * twin (`computeClasses` throws with the same content, naming the exact
32
+ * statement).
33
+ *
34
+ * Every paired face of the statement tuple unions its positionwise field
35
+ * slots: containment (ψ-selected targets included — a selection changes
36
+ * pairing not at all), the `==` bijection, and window source/target pairs.
37
+ * `key()` statements pair nothing (an FD constrains one relation's own
38
+ * rows; it identifies no carriers).
39
+ *
40
+ * The type tier reads pairs off the statement types' exact face data, so
41
+ * spell the statement list INLINE in `schema()` (the `const` type
42
+ * parameter keeps the tuple precise). A widened `Statement[]` list
43
+ * degrades the TYPE tier to generators-only (no pair is readable off a
44
+ * widened type) — the runtime map stays complete and authoritative, and
45
+ * the wire lowering reads only the runtime map. Every loop below is
46
+ * tail-recursive with an accumulator, so the machinery rides TypeScript's
47
+ * tail-recursion elimination at primer scale (~40 relations, ~200 slots,
48
+ * ~123 statements); should a schema ever exceed the compiler's limits, tsc
49
+ * fails LOUDLY with its own instantiation-depth error — the map is never
50
+ * silently widened.
51
+ */
52
+ import type { AnyClosed } from "#closed.ts";
53
+ import type { FaceData } from "#face.ts";
54
+ import type { AnyRelation, RelationFields } from "#relation.ts";
55
+ import type { SchemaRelation, SchemaRelations } from "#schema.ts";
56
+ import { type Statement } from "#statements.ts";
57
+ /** One relation's computed classes: field name → class name, `undefined` = bare. */
58
+ type RelationClasses = {
59
+ readonly [field: string]: string | undefined;
60
+ };
61
+ /**
62
+ * The class map a schema carries — relation name → field name → the
63
+ * computed class name (`undefined` = bare). THE domain authority: queries
64
+ * and the wire lowering read domains from here and nowhere else. The wide
65
+ * shape is the default every `Schema`-generic surface accepts; a concrete
66
+ * schema's `classes` property carries the EXACT computed map
67
+ * ({@link ClassesOf}) at the type level and the frozen runtime twin
68
+ * (`computeClasses`) at the value level — one property, two tiers, one
69
+ * computation.
70
+ */
71
+ type SchemaClasses = {
72
+ readonly [relation: string]: RelationClasses;
73
+ };
74
+ /** Looks one relation's class record up in a schema's class map (absent relation = no classes). */
75
+ type ClassRecordOf<Classes extends SchemaClasses, N extends string> = N extends keyof Classes ? Classes[N] : Record<never, never>;
76
+ /** Looks one field's class up in a relation's class record (absent field = bare). */
77
+ type ClassLookup<CR, K> = K extends keyof CR ? CR[K] & (string | undefined) : undefined;
78
+ /** A closed member's declared payload-column record (`never` on ordinary relations). */
79
+ type MemberColumns<M> = M extends AnyClosed ? M["columns"] : never;
80
+ /** The field names of one schema member: a relation's declared fields; a closed relation's sealed `id` + columns. */
81
+ type MemberFieldNames<M extends SchemaRelation> = M extends AnyClosed ? "id" | (keyof MemberColumns<M> & string) : M extends AnyRelation ? keyof RelationFields<M> & string : never;
82
+ /** The fresh-marked field names of one field block. */
83
+ type FreshFieldNames<Fields> = {
84
+ [F in keyof Fields & string]: Fields[F] extends {
85
+ readonly fresh: true;
86
+ } ? F : never;
87
+ }[keyof Fields & string];
88
+ /** One member's generator coordinates: fresh fields; a closed relation's synthetic id. */
89
+ type MemberGenerators<N extends string, M extends SchemaRelation> = M extends AnyClosed ? `${N}.id` : M extends AnyRelation ? `${N}.${FreshFieldNames<RelationFields<M>>}` : never;
90
+ /** Every generator coordinate of a relation record (a union). */
91
+ type GeneratorsOf<Rels extends SchemaRelations> = {
92
+ [N in keyof Rels & string]: MemberGenerators<N, Rels[N]>;
93
+ }[keyof Rels & string];
94
+ /** One paired-slot pair of coordinates. */
95
+ type Pair = readonly [string, string];
96
+ /** A list of slot pairs. */
97
+ type PairList = readonly Pair[];
98
+ /** Zips two faces' projections into coordinate pairs, positionwise. */
99
+ type ZipCoords<SN extends string, SP extends readonly string[], TN extends string, TP extends readonly string[], Acc extends PairList = []> = SP extends readonly [infer SH extends string, ...infer ST extends readonly string[]] ? TP extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ? ZipCoords<SN, ST, TN, TT, readonly [...Acc, readonly [`${SN}.${SH}`, `${TN}.${TH}`]]> : Acc : Acc;
100
+ /**
101
+ * One statement's slot pairs: containments (bidirectional included — pair
102
+ * unions are symmetric) and windows pair their two faces positionwise;
103
+ * `key()` pairs nothing. A widened face (owner name or projection no
104
+ * longer literal) contributes nothing — the runtime map stays complete.
105
+ */
106
+ type StatementPairs<St extends Statement> = St["data"] extends {
107
+ readonly source: infer S extends FaceData;
108
+ readonly target: infer T extends FaceData;
109
+ } ? string extends S["owner"]["name"] ? [] : string extends T["owner"]["name"] ? [] : ZipCoords<S["owner"]["name"], S["projection"], T["owner"]["name"], T["projection"]> : [];
110
+ /** Every slot pair of a statements tuple, in written order. */
111
+ type PairsOf<Stmts extends readonly Statement[], Acc extends PairList = []> = Stmts extends readonly [
112
+ infer H extends Statement,
113
+ ...infer T extends readonly Statement[]
114
+ ] ? PairsOf<T, readonly [...Acc, ...StatementPairs<H>]> : Acc;
115
+ /** The component (a union of coordinates) containing `X`, or `never` when `X` is in none. */
116
+ type CompOf<Comps extends readonly string[], X extends string> = Comps extends readonly [
117
+ infer H extends string,
118
+ ...infer T extends readonly string[]
119
+ ] ? [X] extends [H] ? H : CompOf<T, X> : never;
120
+ /** Rebuilds the component list without the component `C` (components are disjoint; identity is mutual extension). */
121
+ type WithoutComp<Comps extends readonly string[], C extends string, Acc extends readonly string[] = []> = Comps extends readonly [infer H extends string, ...infer T extends readonly string[]] ? [H, C] extends [C, H] ? WithoutComp<T, C, Acc> : WithoutComp<T, C, readonly [...Acc, H]> : Acc;
122
+ /** Unions one pair into the component list: create, extend, keep, or merge. */
123
+ type AddPair<Comps extends readonly string[], A extends string, B extends string> = [
124
+ CompOf<Comps, A>,
125
+ CompOf<Comps, B>
126
+ ] extends [infer CA extends string, infer CB extends string] ? [CA] extends [never] ? [CB] extends [never] ? readonly [...Comps, A | B] : readonly [...WithoutComp<Comps, CB>, CB | A] : [CB] extends [never] ? readonly [...WithoutComp<Comps, CA>, CA | B] : [CA, CB] extends [CB, CA] ? Comps : readonly [...WithoutComp<WithoutComp<Comps, CA>, CB>, CA | CB] : Comps;
127
+ /** Folds every pair into connected components (tail-recursive — the whole walk is one loop). */
128
+ type BuildComps<Pairs extends PairList, Comps extends readonly string[] = readonly []> = Pairs extends readonly [
129
+ infer P extends Pair,
130
+ ...infer T extends PairList
131
+ ] ? BuildComps<T, AddPair<Comps, P[0], P[1]>> : Comps;
132
+ /** Whether a union holds two or more members (`All` captures the whole union across distribution). */
133
+ type IsMulti<U, All = U> = [U] extends [never] ? false : U extends unknown ? ([All] extends [U] ? false : true) : never;
134
+ /**
135
+ * The named, self-locating compile verdict of the one-generator wall: the
136
+ * generator coordinates that collided and the paired slots (rendered
137
+ * `A.x ~ B.y`, statement order) whose chain unified them. Intersected into
138
+ * `schema()`'s statements parameter, so the error lands ON the statement
139
+ * list with this key naming the law. The runtime twin throws from
140
+ * `computeClasses` with the same content, naming the exact statement.
141
+ */
142
+ interface ClassWall<Generators extends string, Chain extends readonly string[]> {
143
+ readonly "schema class wall — the statements unify two generators into one class (two mints cannot share a carrier)": {
144
+ readonly generators: Generators;
145
+ readonly through: Chain;
146
+ };
147
+ }
148
+ /** The paired slots lying inside component `C`, rendered — the wall's self-locating chain. */
149
+ type ChainOf<Pairs extends PairList, C extends string, Acc extends readonly string[] = []> = Pairs extends readonly [
150
+ infer P extends Pair,
151
+ ...infer T extends PairList
152
+ ] ? [P[0]] extends [C] ? ChainOf<T, C, readonly [...Acc, `${P[0]} ~ ${P[1]}`]> : ChainOf<T, C, Acc> : Acc;
153
+ /** Scans the components for a two-generator class: `unknown` (lawful) or the {@link ClassWall}. */
154
+ type WallScan<Comps extends readonly string[], Gens extends string, Pairs extends PairList> = Comps extends readonly [
155
+ infer H extends string,
156
+ ...infer T extends readonly string[]
157
+ ] ? true extends IsMulti<Extract<H, Gens>> ? ClassWall<Extract<H, Gens>, ChainOf<Pairs, H>> : WallScan<T, Gens, Pairs> : unknown;
158
+ /**
159
+ * The one-generator-per-class law as a constraint: resolves to `unknown`
160
+ * (a no-op intersection into the statements parameter) when the statement
161
+ * list is lawful, and to the named {@link ClassWall} otherwise.
162
+ */
163
+ type LawfulStatements<Rels extends SchemaRelations, Stmts extends readonly Statement[]> = WallScan<BuildComps<PairsOf<Stmts>>, GeneratorsOf<Rels>, PairsOf<Stmts>>;
164
+ /**
165
+ * One coordinate's class per the three laws, at the TYPE tier: its
166
+ * component's single generator (the exact literal — a generator names its
167
+ * class); a component-less generator is its own class; a component-less
168
+ * non-generator is bare (`undefined`); and a GENERATOR-LESS component is
169
+ * carried as its member-coordinate SET (the union of the component's
170
+ * coordinates — a canonical, deterministic type). The set REPRESENTS the
171
+ * runtime's least-member class name faithfully: the runtime name is by
172
+ * construction a member, two slots share a class exactly when their sets
173
+ * are identical (so `JoinOk` judges identically at both tiers), and bare
174
+ * never equals a set. The least-member PICK itself is deliberately not
175
+ * made at the type tier: TypeScript's union member order is not observably
176
+ * deterministic (the same key union tuples differently across checking
177
+ * contexts — measured, not conjectured), so any type-level "least in
178
+ * declaration order" would drift between compilations; the ratified
179
+ * declaration-order name lives at the VALUE tier (`computeClasses`), which
180
+ * is the only tier the wire reads.
181
+ */
182
+ type ClassOfCoord<Comps extends readonly string[], Gens extends string, C extends string> = [CompOf<Comps, C>] extends [
183
+ infer M extends string
184
+ ] ? [M] extends [never] ? [C] extends [Gens] ? C : undefined : [Extract<M, Gens>] extends [infer G extends string] ? [G] extends [never] ? M : G : never : never;
185
+ /** The computed class map over precomputed components/generators. */
186
+ type ComputedClasses<Rels extends SchemaRelations, Comps extends readonly string[], Gens extends string> = {
187
+ readonly [N in keyof Rels & string]: {
188
+ readonly [F in MemberFieldNames<Rels[N]>]: ClassOfCoord<Comps, Gens, `${N}.${F}`>;
189
+ };
190
+ };
191
+ /**
192
+ * THE type-level class map of a schema: relation name → field name → the
193
+ * law-computed class (`undefined` = bare) — what `schema()` returns as the
194
+ * `classes` property's type, and what query joins compare. Generator
195
+ * classes are exact name literals; generator-less classes are their
196
+ * member-coordinate sets (see {@link ClassOfCoord} — the runtime map's
197
+ * least-member name is always a member, so the property type is honest).
198
+ */
199
+ type ClassesOf<Rels extends SchemaRelations, Stmts extends readonly Statement[]> = ComputedClasses<Rels, BuildComps<PairsOf<Stmts>>, GeneratorsOf<Rels>>;
200
+ /**
201
+ * Computes the class map — the runtime twin of {@link ClassesOf}, the SAME
202
+ * computation as a plain union-find: every paired face's positionwise slot
203
+ * pairs union their coordinates; a fresh field or closed id is a generator
204
+ * naming its class; a generator-less class is named by its least member in
205
+ * relation-declaration × field-declaration order; a slot in no law is bare
206
+ * (`undefined`). The one-generator wall throws HERE, naming the two
207
+ * coordinates and the statement that unified them — the same content the
208
+ * compile-tier {@link ClassWall} carries. The returned map is frozen, own
209
+ * properties throughout (arbitrary field names ride own-property
210
+ * definition, never the object protocol).
211
+ */
212
+ declare function computeClasses(name: string, relations: SchemaRelations, statements: readonly Statement[]): SchemaClasses;
213
+ /**
214
+ * The trusted seam of the class-map mint (the `refsComplete` pattern): the
215
+ * checkable facts — one own record per declared relation, one own entry
216
+ * per declared field (the closed sealed shape's `id` included), everything
217
+ * frozen — are verified before the runtime map is admitted at the computed
218
+ * {@link ClassesOf} type. The NAME agreement of the two tiers is pinned by
219
+ * the generated fixture probes (the runtime/type diff check).
220
+ */
221
+ declare function classesComplete<Classes extends SchemaClasses>(classes: SchemaClasses, relations: SchemaRelations): classes is Classes;
222
+ export type { ClassesOf, ClassLookup, ClassRecordOf, ClassWall, LawfulStatements, RelationClasses, SchemaClasses };
223
+ export { classesComplete, computeClasses };
224
+ //# sourceMappingURL=law.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"law.d.ts","sourceRoot":"","sources":["../src/law.ts"],"names":[],"mappings":"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"}
package/dist/law.js ADDED
@@ -0,0 +1,224 @@
1
+ /**
2
+ * The law-typing engine (owner ruling 2026-07-18, "option 2, zero debate"):
3
+ * THE LAWS TYPE THE COLUMNS. Domains are declared nowhere — `schema()`
4
+ * computes every field's domain FROM the statement list, at BOTH the type
5
+ * level (this module's type machinery, reading the statements tuple type)
6
+ * and at runtime (a plain union-find over the same pairs), and the two
7
+ * tiers are the same computation by construction.
8
+ *
9
+ * The three class laws (ratified; implemented exactly):
10
+ *
11
+ * 1. GENERATORS — a `fresh` field is a generator and names its class by
12
+ * its declaration coordinate (`"Account.id"`); a closed relation's
13
+ * synthetic id is a generator named `"Kind.id"`.
14
+ * 2. GENERATOR-LESS classes are named by their least member coordinate
15
+ * in relation-declaration × field-declaration order (readable off the
16
+ * relation record and each member's frozen field list at the VALUE
17
+ * tier — deterministic, pinned forever; the wire reads only this
18
+ * tier). At the TYPE tier the same class is carried as its
19
+ * member-coordinate SET (see {@link ClassOfCoord}): TypeScript's
20
+ * union member order is not observably deterministic, so a type-level
21
+ * least-member pick would drift between compilations — the set is the
22
+ * canonical deterministic spelling, the runtime name is always a
23
+ * member of it, and the join judgment is identical at both tiers.
24
+ * 3. BARE — a field in no law has NO class and pairs only with bare in
25
+ * queries (the deliberate sum-domain pointer stays legal).
26
+ *
27
+ * THE WALL: a class containing more than one generator is a contradiction
28
+ * (two mints cannot share a carrier) — a schema-level COMPILE error (the
29
+ * named, self-locating {@link ClassWall}: which generator coordinates
30
+ * collided, through which paired slots) with a construction-time runtime
31
+ * twin (`computeClasses` throws with the same content, naming the exact
32
+ * statement).
33
+ *
34
+ * Every paired face of the statement tuple unions its positionwise field
35
+ * slots: containment (ψ-selected targets included — a selection changes
36
+ * pairing not at all), the `==` bijection, and window source/target pairs.
37
+ * `key()` statements pair nothing (an FD constrains one relation's own
38
+ * rows; it identifies no carriers).
39
+ *
40
+ * The type tier reads pairs off the statement types' exact face data, so
41
+ * spell the statement list INLINE in `schema()` (the `const` type
42
+ * parameter keeps the tuple precise). A widened `Statement[]` list
43
+ * degrades the TYPE tier to generators-only (no pair is readable off a
44
+ * widened type) — the runtime map stays complete and authoritative, and
45
+ * the wire lowering reads only the runtime map. Every loop below is
46
+ * tail-recursive with an accumulator, so the machinery rides TypeScript's
47
+ * tail-recursion elimination at primer scale (~40 relations, ~200 slots,
48
+ * ~123 statements); should a schema ever exceed the compiler's limits, tsc
49
+ * fails LOUDLY with its own instantiation-depth error — the map is never
50
+ * silently widened.
51
+ */
52
+ import * as errors from "@superbuilders/errors";
53
+ import { renderStatement } from "#statements.ts";
54
+ /** Reads every member's coordinates off the relation record, declaration order throughout. */
55
+ function memberCoords(relations) {
56
+ const out = [];
57
+ for (const [relationName, member] of Object.entries(relations)) {
58
+ if ("handles" in member.data) {
59
+ const fields = [
60
+ { name: "id", generator: true },
61
+ ...member.data.columns.map(function columnCoord(column) {
62
+ return { name: column.name, generator: false };
63
+ })
64
+ ];
65
+ out.push({ relation: relationName, fields });
66
+ continue;
67
+ }
68
+ const fields = member.data.fields.map(function fieldCoord(declared) {
69
+ return { name: declared.name, generator: "fresh" in declared.field && declared.field.fresh === true };
70
+ });
71
+ out.push({ relation: relationName, fields });
72
+ }
73
+ return out;
74
+ }
75
+ /** Builds the union-find. */
76
+ function makeUnionFind() {
77
+ const parent = new Map();
78
+ const generators = new Map();
79
+ function find(coord) {
80
+ const at = parent.get(coord);
81
+ if (at === undefined) {
82
+ parent.set(coord, coord);
83
+ return coord;
84
+ }
85
+ if (at === coord) {
86
+ return coord;
87
+ }
88
+ const root = find(at);
89
+ parent.set(coord, root);
90
+ return root;
91
+ }
92
+ return {
93
+ find,
94
+ union(a, b) {
95
+ const rootA = find(a);
96
+ const rootB = find(b);
97
+ if (rootA === rootB) {
98
+ return rootA;
99
+ }
100
+ parent.set(rootB, rootA);
101
+ const merged = [...(generators.get(rootA) ?? []), ...(generators.get(rootB) ?? [])];
102
+ generators.delete(rootB);
103
+ if (merged.length > 0) {
104
+ generators.set(rootA, merged);
105
+ }
106
+ return rootA;
107
+ },
108
+ generatorsOf(root) {
109
+ return generators.get(root) ?? [];
110
+ },
111
+ markGenerator(coord) {
112
+ const root = find(coord);
113
+ generators.set(root, [...(generators.get(root) ?? []), coord]);
114
+ }
115
+ };
116
+ }
117
+ /** The paired faces of one statement, or undefined for a key (an FD pairs nothing). */
118
+ function statementFaces(statement) {
119
+ const data = statement.data;
120
+ if (data.kind === "key") {
121
+ return undefined;
122
+ }
123
+ return [data.source, data.target];
124
+ }
125
+ /**
126
+ * Computes the class map — the runtime twin of {@link ClassesOf}, the SAME
127
+ * computation as a plain union-find: every paired face's positionwise slot
128
+ * pairs union their coordinates; a fresh field or closed id is a generator
129
+ * naming its class; a generator-less class is named by its least member in
130
+ * relation-declaration × field-declaration order; a slot in no law is bare
131
+ * (`undefined`). The one-generator wall throws HERE, naming the two
132
+ * coordinates and the statement that unified them — the same content the
133
+ * compile-tier {@link ClassWall} carries. The returned map is frozen, own
134
+ * properties throughout (arbitrary field names ride own-property
135
+ * definition, never the object protocol).
136
+ */
137
+ function computeClasses(name, relations, statements) {
138
+ const members = memberCoords(relations);
139
+ const uf = makeUnionFind();
140
+ const paired = new Set();
141
+ const generatorSet = new Set();
142
+ for (const member of members) {
143
+ for (const field of member.fields) {
144
+ const coord = `${member.relation}.${field.name}`;
145
+ uf.find(coord);
146
+ if (field.generator) {
147
+ generatorSet.add(coord);
148
+ uf.markGenerator(coord);
149
+ }
150
+ }
151
+ }
152
+ for (const statement of statements) {
153
+ const faces = statementFaces(statement);
154
+ if (faces === undefined) {
155
+ continue;
156
+ }
157
+ const [source, target] = faces;
158
+ source.projection.forEach(function unionSlot(fieldName, position) {
159
+ const targetField = target.projection[position];
160
+ if (targetField === undefined) {
161
+ return;
162
+ }
163
+ const coordA = `${source.owner.name}.${fieldName}`;
164
+ const coordB = `${target.owner.name}.${targetField}`;
165
+ paired.add(coordA);
166
+ paired.add(coordB);
167
+ const root = uf.union(coordA, coordB);
168
+ const gens = uf.generatorsOf(root);
169
+ if (gens.length > 1) {
170
+ throw errors.new(`schema ${name}: the statements unify two generators into one class — ${gens.join(" and ")} (two mints cannot share a carrier) — ${renderStatement(statement)}`);
171
+ }
172
+ });
173
+ }
174
+ const names = new Map();
175
+ for (const member of members) {
176
+ for (const field of member.fields) {
177
+ const coord = `${member.relation}.${field.name}`;
178
+ const root = uf.find(coord);
179
+ if (!names.has(root)) {
180
+ const gens = uf.generatorsOf(root);
181
+ names.set(root, gens[0] ?? coord);
182
+ }
183
+ }
184
+ }
185
+ const classes = {};
186
+ for (const member of members) {
187
+ const record = {};
188
+ for (const field of member.fields) {
189
+ const coord = `${member.relation}.${field.name}`;
190
+ const classed = paired.has(coord) || generatorSet.has(coord);
191
+ Object.defineProperty(record, field.name, {
192
+ value: classed ? names.get(uf.find(coord)) : undefined,
193
+ enumerable: true
194
+ });
195
+ }
196
+ Object.freeze(record);
197
+ Object.defineProperty(classes, member.relation, { value: record, enumerable: true });
198
+ }
199
+ return Object.freeze(classes);
200
+ }
201
+ /**
202
+ * The trusted seam of the class-map mint (the `refsComplete` pattern): the
203
+ * checkable facts — one own record per declared relation, one own entry
204
+ * per declared field (the closed sealed shape's `id` included), everything
205
+ * frozen — are verified before the runtime map is admitted at the computed
206
+ * {@link ClassesOf} type. The NAME agreement of the two tiers is pinned by
207
+ * the generated fixture probes (the runtime/type diff check).
208
+ */
209
+ function classesComplete(classes, relations) {
210
+ if (!Object.isFrozen(classes)) {
211
+ return false;
212
+ }
213
+ return memberCoords(relations).every(function relationMinted(member) {
214
+ const record = classes[member.relation];
215
+ if (record === undefined || !Object.isFrozen(record)) {
216
+ return false;
217
+ }
218
+ return member.fields.every(function fieldMinted(field) {
219
+ return Object.hasOwn(record, field.name);
220
+ });
221
+ });
222
+ }
223
+ export { classesComplete, computeClasses };
224
+ //# sourceMappingURL=law.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"law.js","sourceRoot":"","sources":["../src/law.ts"],"names":[],"mappings":"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"}
package/dist/lower.d.ts CHANGED
@@ -8,29 +8,36 @@
8
8
  * fixed key order, so serialization is deterministic (byte-stable).
9
9
  */
10
10
  import type { AnyClosed } from "#closed.ts";
11
+ import type { RelationClasses } from "#law.ts";
11
12
  import type { AnyRelation } from "#relation.ts";
12
13
  import type { AnySchema } from "#schema.ts";
13
14
  import type { RelationSpec, SchemaSpec } from "#spec.ts";
14
15
  /**
15
16
  * Lowers one ordinary relation to its `RelationSpec` fragment: fields in
16
- * declaration order, `extension: undefined` (the option is the kind).
17
+ * declaration order, each carrying its law-computed class name as the
18
+ * `newtype` (`classes` — the schema's class record for this relation;
19
+ * bare fields carry `undefined`), `extension: undefined` (the option is
20
+ * the kind).
17
21
  */
18
- declare function lowerRelation(relation: AnyRelation): RelationSpec;
22
+ declare function lowerRelation(relation: AnyRelation, classes: RelationClasses): RelationSpec;
19
23
  /**
20
24
  * Lowers one closed relation to its `RelationSpec` fragment: declared
21
25
  * intrinsic columns only (the engine materializes the synthetic `id`),
22
- * the HANDLE DOMAIN as its handle newtype the `id` descriptor's own
23
- * `` `${name}Id` `` label (Rust's `closed relation Kind as KindId`), the
24
- * same string every referencing field carries, which is exactly how the
25
- * engine resolves a handle literal back to its roster — and the ground
26
- * axioms in declaration order (row id = index); the literals were already
27
- * lowered at `closed()` construction.
26
+ * the handle newtype the COMPUTED class name of the id's generator
27
+ * class (`"Kind.id"`, always present: a closed id is a generator), which
28
+ * every referencing field shares by law (how the engine resolves a handle
29
+ * literal back to its roster) — and the ground axioms in declaration
30
+ * order (row id = index); the literals were already lowered at `closed()`
31
+ * construction.
28
32
  */
29
- declare function lowerClosed(member: AnyClosed): RelationSpec;
33
+ declare function lowerClosed(member: AnyClosed, classes: RelationClasses): RelationSpec;
30
34
  /**
31
35
  * Lowers a whole theory to the `SchemaSpec` the bridge takes: relations in
32
36
  * record declaration order, DECLARED statements only in written order (the
33
- * engine materializes the fresh-implied and closed auto-keys itself).
37
+ * engine materializes the fresh-implied and closed auto-keys itself), and
38
+ * every field's `newtype` slot fed from the schema's law-computed class
39
+ * map — the ONE domain authority (fingerprint-neutral: the engine drops
40
+ * newtypes at descriptor lowering).
34
41
  */
35
42
  declare function lower(theory: AnySchema): SchemaSpec;
36
43
  export { lower, lowerClosed, lowerRelation };
@@ -1 +1 @@
1
- {"version":3,"file":"lower.d.ts","sourceRoot":"","sources":["../src/lower.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAG3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,YAAY,CAAA;AAC3D,OAAO,KAAK,EAGX,YAAY,EACZ,UAAU,EAIV,MAAM,UAAU,CAAA;AA0FjB;;;GAGG;AACH,iBAAS,aAAa,CAAC,QAAQ,EAAE,WAAW,GAAG,YAAY,CAK1D;AAED;;;;;;;;;GASG;AACH,iBAAS,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,YAAY,CAQpD;AAED;;;;GAIG;AACH,iBAAS,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,UAAU,CAQ5C;AAED,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,CAAA"}
1
+ {"version":3,"file":"lower.d.ts","sourceRoot":"","sources":["../src/lower.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAG3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,YAAY,CAAA;AAC3D,OAAO,KAAK,EAGX,YAAY,EACZ,UAAU,EAIV,MAAM,UAAU,CAAA;AA4FjB;;;;;;GAMG;AACH,iBAAS,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,GAAG,YAAY,CAKpF;AAED;;;;;;;;;GASG;AACH,iBAAS,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,GAAG,YAAY,CAQ9E;AAKD;;;;;;;GAOG;AACH,iBAAS,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,UAAU,CAS5C;AAED,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,CAAA"}
package/dist/lower.js CHANGED
@@ -38,17 +38,19 @@ function valueTypeOf(field) {
38
38
  }
39
39
  /**
40
40
  * Lowers one field descriptor to its {@link FieldSpec}: the structural
41
- * type, the DOMAIN label as the wire's `newtype` (the macro's `as NewType`
42
- * namecarried for engine handle resolution, dropped at descriptor
43
- * lowering, never fingerprinted), and the structural fresh mark (`fresh`
44
- * is the literal `true` exactly on a fresh-marked u64 on an unmarked one
45
- * the property holds the marked descriptor, never `true`).
41
+ * type, the structural fresh mark (`fresh` is the literal `true` exactly
42
+ * on a fresh-marked u64 on an unmarked one the property holds the marked
43
+ * descriptor, never `true`), and the wire's `newtype` the COMPUTED class
44
+ * name `schema()` derived from the statement list (the laws type the
45
+ * columns), `undefined` on a bare field. The engine reads newtypes for
46
+ * handle resolution and the coherence check only and DROPS them at
47
+ * descriptor lowering — class names are never fingerprinted.
46
48
  */
47
- function lowerField(name, field) {
49
+ function lowerField(name, field, newtype) {
48
50
  return {
49
51
  name,
50
52
  valueType: valueTypeOf(field),
51
- newtype: field.domain,
53
+ newtype,
52
54
  fresh: "fresh" in field && field.fresh === true
53
55
  };
54
56
  }
@@ -91,44 +93,53 @@ function lowerStatement(statement) {
91
93
  }
92
94
  /**
93
95
  * Lowers one ordinary relation to its `RelationSpec` fragment: fields in
94
- * declaration order, `extension: undefined` (the option is the kind).
96
+ * declaration order, each carrying its law-computed class name as the
97
+ * `newtype` (`classes` — the schema's class record for this relation;
98
+ * bare fields carry `undefined`), `extension: undefined` (the option is
99
+ * the kind).
95
100
  */
96
- function lowerRelation(relation) {
101
+ function lowerRelation(relation, classes) {
97
102
  const fields = relation.data.fields.map(function lowerDeclared(declared) {
98
- return lowerField(declared.name, declared.field);
103
+ return lowerField(declared.name, declared.field, classes[declared.name]);
99
104
  });
100
105
  return { name: relation.name, newtype: undefined, fields, extension: undefined };
101
106
  }
102
107
  /**
103
108
  * Lowers one closed relation to its `RelationSpec` fragment: declared
104
109
  * intrinsic columns only (the engine materializes the synthetic `id`),
105
- * the HANDLE DOMAIN as its handle newtype the `id` descriptor's own
106
- * `` `${name}Id` `` label (Rust's `closed relation Kind as KindId`), the
107
- * same string every referencing field carries, which is exactly how the
108
- * engine resolves a handle literal back to its roster — and the ground
109
- * axioms in declaration order (row id = index); the literals were already
110
- * lowered at `closed()` construction.
110
+ * the handle newtype the COMPUTED class name of the id's generator
111
+ * class (`"Kind.id"`, always present: a closed id is a generator), which
112
+ * every referencing field shares by law (how the engine resolves a handle
113
+ * literal back to its roster) — and the ground axioms in declaration
114
+ * order (row id = index); the literals were already lowered at `closed()`
115
+ * construction.
111
116
  */
112
- function lowerClosed(member) {
117
+ function lowerClosed(member, classes) {
113
118
  const fields = member.data.columns.map(function lowerColumn(column) {
114
- return lowerField(column.name, column.field);
119
+ return lowerField(column.name, column.field, classes[column.name]);
115
120
  });
116
121
  const extension = member.data.rows.map(function lowerRow(row) {
117
122
  return { handle: row.handle, values: row.values };
118
123
  });
119
- return { name: member.name, newtype: member.id.domain, fields, extension };
124
+ return { name: member.name, newtype: classes.id, fields, extension };
120
125
  }
126
+ /** The frozen empty class record a relation outside the schema's map lowers under (nothing classed). */
127
+ const noClasses = Object.freeze({});
121
128
  /**
122
129
  * Lowers a whole theory to the `SchemaSpec` the bridge takes: relations in
123
130
  * record declaration order, DECLARED statements only in written order (the
124
- * engine materializes the fresh-implied and closed auto-keys itself).
131
+ * engine materializes the fresh-implied and closed auto-keys itself), and
132
+ * every field's `newtype` slot fed from the schema's law-computed class
133
+ * map — the ONE domain authority (fingerprint-neutral: the engine drops
134
+ * newtypes at descriptor lowering).
125
135
  */
126
136
  function lower(theory) {
127
- const relations = Object.values(theory.relations).map(function lowerMember(member) {
137
+ const relations = Object.entries(theory.relations).map(function lowerMember([name, member]) {
138
+ const classes = theory.classes[name] ?? noClasses;
128
139
  if (isClosedMember(member)) {
129
- return lowerClosed(member);
140
+ return lowerClosed(member, classes);
130
141
  }
131
- return lowerRelation(member);
142
+ return lowerRelation(member, classes);
132
143
  });
133
144
  return { relations, statements: theory.statements.map(lowerStatement) };
134
145
  }