@bjornpagen/bumbledb 0.14.0 → 0.17.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.
- package/COOKBOOK.md +58 -62
- package/README.md +82 -56
- package/dist/capacity.d.ts +24 -136
- package/dist/capacity.d.ts.map +1 -1
- package/dist/capacity.js +18 -40
- package/dist/capacity.js.map +1 -1
- package/dist/closed.d.ts +0 -156
- package/dist/closed.d.ts.map +1 -1
- package/dist/closed.js +0 -104
- package/dist/closed.js.map +1 -1
- package/dist/db.d.ts +93 -290
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +713 -556
- package/dist/db.js.map +1 -1
- package/dist/face.d.ts +0 -133
- package/dist/face.d.ts.map +1 -1
- package/dist/face.js +0 -33
- package/dist/face.js.map +1 -1
- package/dist/fields.d.ts +1 -145
- package/dist/fields.d.ts.map +1 -1
- package/dist/fields.js +2 -91
- package/dist/fields.js.map +1 -1
- package/dist/index.d.ts +13 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -20
- package/dist/index.js.map +1 -1
- package/dist/law.d.ts +111 -93
- package/dist/law.d.ts.map +1 -1
- package/dist/law.js +23 -27
- package/dist/law.js.map +1 -1
- package/dist/lower.d.ts +9 -35
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +8 -53
- package/dist/lower.js.map +1 -1
- package/dist/marshal.d.ts +0 -65
- package/dist/marshal.d.ts.map +1 -1
- package/dist/marshal.js +0 -72
- package/dist/marshal.js.map +1 -1
- package/dist/native.d.ts +97 -390
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js +39 -61
- package/dist/native.js.map +1 -1
- package/dist/query/atom.d.ts +10 -276
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js +1 -96
- package/dist/query/atom.js.map +1 -1
- package/dist/query/find.d.ts +10 -76
- package/dist/query/find.d.ts.map +1 -1
- package/dist/query/find.js +0 -30
- package/dist/query/find.js.map +1 -1
- package/dist/query/lower.d.ts +64 -146
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +19 -256
- package/dist/query/lower.js.map +1 -1
- package/dist/query/parse-ir.d.ts +0 -7
- package/dist/query/parse-ir.d.ts.map +1 -1
- package/dist/query/parse-ir.js +1 -13
- package/dist/query/parse-ir.js.map +1 -1
- package/dist/query/run.d.ts +0 -36
- package/dist/query/run.d.ts.map +1 -1
- package/dist/query/run.js +0 -44
- package/dist/query/run.js.map +1 -1
- package/dist/query/scope.d.ts +24 -180
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +2 -66
- package/dist/query/scope.js.map +1 -1
- package/dist/relation.d.ts +2 -50
- package/dist/relation.d.ts.map +1 -1
- package/dist/relation.js +2 -37
- package/dist/relation.js.map +1 -1
- package/dist/schema.d.ts +13 -63
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +118 -92
- package/dist/schema.js.map +1 -1
- package/dist/spec.d.ts +1 -140
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js +1 -68
- package/dist/spec.js.map +1 -1
- package/dist/statements.d.ts +6 -137
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +16 -119
- package/dist/statements.js.map +1 -1
- package/package.json +3 -3
- package/src/capacity.ts +26 -140
- package/src/closed.ts +5 -206
- package/src/db.ts +997 -854
- package/src/face.ts +0 -142
- package/src/fields.ts +4 -172
- package/src/index.ts +32 -35
- package/src/law.ts +201 -129
- package/src/lower.ts +8 -53
- package/src/marshal.ts +1 -85
- package/src/native.ts +192 -413
- package/src/query/atom.ts +26 -313
- package/src/query/find.ts +24 -110
- package/src/query/lower.ts +132 -377
- package/src/query/parse-ir.ts +1 -14
- package/src/query/run.ts +0 -45
- package/src/query/scope.ts +25 -186
- package/src/relation.ts +2 -66
- package/src/schema.ts +143 -122
- package/src/spec.ts +1 -160
- package/src/statements.ts +22 -174
- package/dist/exhume.d.ts +0 -143
- package/dist/exhume.d.ts.map +0 -1
- package/dist/exhume.js +0 -166
- package/dist/exhume.js.map +0 -1
- package/src/exhume.ts +0 -267
package/src/face.ts
CHANGED
|
@@ -1,50 +1,13 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Faces — the projection-with-selection value both containments and
|
|
3
|
-
* windows consume: `on(Account, "holder")` the common single-field
|
|
4
|
-
* position, `on(Booking, ["room", "during"])` the composite/pointwise
|
|
5
|
-
* position (one spelling, arity-generic), `on(Account.where({ kind:
|
|
6
|
-
* Kind.Savings }), "id")` the σ-carrying source, `on(Kind, "id")` a closed
|
|
7
|
-
* relation's sealed shape opened through its synthetic `id`,
|
|
8
|
-
* `on(Kind.where({ mastered: true }), "id")` the ψ-selected closed source
|
|
9
|
-
* (the selection lowered as-is — the ENGINE folds it against the sealed
|
|
10
|
-
* extension at validate, never the SDK). Projection is
|
|
11
|
-
* positional: tuple order is preserved in the type, and the statement
|
|
12
|
-
* constructors pair the two sides' tuples by arity ({@link SameArity}) AND
|
|
13
|
-
* by structural shape ({@link SameShapes}) — every projected field's
|
|
14
|
-
* kind/width/element/roster quadruple is read off the schema type (the
|
|
15
|
-
* minimal kernel: descriptors are pure structure, and a closed reference's
|
|
16
|
-
* roster IS part of that structure) and compared positionwise. There is no
|
|
17
|
-
* domain to compare at construction — domains are LAW-BORN: the statements
|
|
18
|
-
* themselves define the equivalence classes, and `schema()` is where they
|
|
19
|
-
* aggregate and get judged (the one-generator-per-class wall).
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
1
|
import * as errors from "@superbuilders/errors"
|
|
23
2
|
import type { AnyClosed, AnySelectedClosed, PayloadField } from "#closed.ts"
|
|
24
3
|
import type { AnyField } from "#fields.ts"
|
|
25
4
|
import type { AnyRelation, AnySelected, FieldsShape, RelationFields, SelectionBinding } from "#relation.ts"
|
|
26
5
|
import { renderLiteralSet } from "#spec.ts"
|
|
27
6
|
|
|
28
|
-
/** The empty σ of a selection-free face, shared by every bare projection. */
|
|
29
7
|
const emptySelection: readonly SelectionBinding[] = Object.freeze([])
|
|
30
8
|
|
|
31
|
-
/**
|
|
32
|
-
* The OWNER a face source resolves to: a selected relation — ordinary σ or
|
|
33
|
-
* closed ψ, one shape — projects from its underlying relation; a bare
|
|
34
|
-
* relation or closed relation is its own owner. The type-level twin of
|
|
35
|
-
* {@link faceParts}'s split, and what a statement's face `data` carries at
|
|
36
|
-
* its EXACT type — `schema()`'s law-typing reads the owner's literal name
|
|
37
|
-
* (and the projection tuple) straight off the statement type.
|
|
38
|
-
*/
|
|
39
9
|
type OwnerOf<S extends FaceSource> = S extends AnySelected | AnySelectedClosed ? S["relation"] : S
|
|
40
10
|
|
|
41
|
-
/**
|
|
42
|
-
* Splits a face source into its owner and σ: a selected relation — ordinary
|
|
43
|
-
* σ or closed ψ, one shape — carries its own bindings (`relation` is the
|
|
44
|
-
* discriminant — the property exists on no relation or closed value, and
|
|
45
|
-
* `closed()` reserves the name against handle collisions); a bare relation
|
|
46
|
-
* or closed relation carries none.
|
|
47
|
-
*/
|
|
48
11
|
function faceParts(source: FaceSource): {
|
|
49
12
|
readonly owner: FaceOwner
|
|
50
13
|
readonly selection: readonly SelectionBinding[]
|
|
@@ -55,51 +18,24 @@ function faceParts(source: FaceSource): {
|
|
|
55
18
|
return { owner: source, selection: emptySelection }
|
|
56
19
|
}
|
|
57
20
|
|
|
58
|
-
/** The relation a face projects from — ordinary or closed. */
|
|
59
21
|
type FaceOwner = AnyRelation | AnyClosed
|
|
60
22
|
|
|
61
|
-
/**
|
|
62
|
-
* A face's runtime description: owner, π (written order), σ (resolved
|
|
63
|
-
* bindings). Generic over the owner and projection so a STATEMENT value
|
|
64
|
-
* carries its paired coordinates at their exact types — the honest runtime
|
|
65
|
-
* properties (`owner.name`, `projection`) ARE the type-level carrier
|
|
66
|
-
* `schema()`'s law-typing reads; the defaults are the wide shape every
|
|
67
|
-
* renderer and lowering walk consumes.
|
|
68
|
-
*/
|
|
69
23
|
interface FaceData<O extends FaceOwner = FaceOwner, P extends readonly string[] = readonly string[]> {
|
|
70
24
|
readonly owner: O
|
|
71
25
|
readonly projection: P
|
|
72
26
|
readonly selection: readonly SelectionBinding[]
|
|
73
27
|
}
|
|
74
28
|
|
|
75
|
-
/**
|
|
76
|
-
* A face value. `S` is the source exactly as written (the relation,
|
|
77
|
-
* selected relation, or closed relation `on()` was handed — the statement
|
|
78
|
-
* constructors resolve each projected field's DOMAIN through it), and `P`
|
|
79
|
-
* is the projection tuple as written (its length is the positional-pairing
|
|
80
|
-
* arity). Both are honest runtime properties, not phantoms — and `data`
|
|
81
|
-
* carries the resolved owner at its exact type, which is what a statement
|
|
82
|
-
* value hands to `schema()`'s law-typing.
|
|
83
|
-
*/
|
|
84
29
|
interface Face<S extends FaceSource, P extends readonly string[]> {
|
|
85
30
|
readonly source: S
|
|
86
31
|
readonly projection: P
|
|
87
32
|
readonly data: FaceData<OwnerOf<S>, P>
|
|
88
33
|
}
|
|
89
34
|
|
|
90
|
-
/** Any face value, whatever its source and projection. */
|
|
91
35
|
type AnyFace = Face<FaceSource, readonly string[]>
|
|
92
36
|
|
|
93
|
-
/** What `on()` accepts: a relation, a closed relation, or either with a selection applied. */
|
|
94
37
|
type FaceSource = AnyRelation | AnyClosed | AnySelected | AnySelectedClosed
|
|
95
38
|
|
|
96
|
-
/**
|
|
97
|
-
* The field names a face over `S` may project: a relation's declared
|
|
98
|
-
* fields; a selected relation's underlying fields; a closed relation's
|
|
99
|
-
* SEALED shape — the synthetic `id` plus its declared payload columns,
|
|
100
|
-
* bare or ψ-selected alike (`docs/architecture/70-api.md`: statement field
|
|
101
|
-
* names address the sealed shape).
|
|
102
|
-
*/
|
|
103
39
|
type FaceFields<S extends FaceSource> = S extends AnySelected
|
|
104
40
|
? keyof RelationFields<S["relation"]> & string
|
|
105
41
|
: S extends AnySelectedClosed
|
|
@@ -110,27 +46,6 @@ type FaceFields<S extends FaceSource> = S extends AnySelected
|
|
|
110
46
|
? "id" | (keyof Row & string)
|
|
111
47
|
: never
|
|
112
48
|
|
|
113
|
-
/**
|
|
114
|
-
* One descriptor's structural comparand: the kind/width/element/roster
|
|
115
|
-
* quadruple — exactly the structure the minimal kernel carries. The first
|
|
116
|
-
* three slots compare exactly as the engine's Q1 law pairs positions
|
|
117
|
-
* (`schema/validate.rs`): a `bytes` width is bound (bytes<16> vs bytes<32>
|
|
118
|
-
* mismatch), while an INTERVAL width is FREE — the pointwise judgments
|
|
119
|
-
* quantify over points, which carry an element domain and not a width, so
|
|
120
|
-
* `interval(u64)` pairs with `interval(u64, 1n)` (recipe 9's extent/slot
|
|
121
|
-
* mirrors, recipe 29's mixed-width zones) and the width slot reads
|
|
122
|
-
* `undefined` for every interval. Elements stay bound: u64-vs-i64 interval
|
|
123
|
-
* pairs still mismatch. The ROSTER slot is SDK-only structure (the engine's
|
|
124
|
-
* wire carries plain u64s): a closed reference contributes its vocabulary
|
|
125
|
-
* NAME literal paired with its handle union — the faithful encoding of the
|
|
126
|
-
* runtime's roster VALUE-IDENTITY judgment, so two same-shaped vocabularies
|
|
127
|
-
* mismatch at compile time exactly as they throw at construction — every
|
|
128
|
-
* other kind `undefined`, so a plain u64 face cannot pair with a closed
|
|
129
|
-
* `[id]` face — the vocabulary's own descriptor (`Kind.id`) is the ONE
|
|
130
|
-
* spelling of a closed reference at this surface, and a bare column cannot
|
|
131
|
-
* alias a vocabulary through a declared law. The runtime twin is the
|
|
132
|
-
* statement constructors' roster-identity walk (`statements.ts`).
|
|
133
|
-
*/
|
|
134
49
|
type ShapeOf<F extends AnyField> = readonly [
|
|
135
50
|
F["kind"],
|
|
136
51
|
F extends { readonly element: unknown } ? undefined : F extends { readonly width: infer W } ? W : undefined,
|
|
@@ -142,18 +57,8 @@ type ShapeOf<F extends AnyField> = readonly [
|
|
|
142
57
|
: undefined
|
|
143
58
|
]
|
|
144
59
|
|
|
145
|
-
/** One field's structural shape within a declared field block (`undefined` when the name is foreign). */
|
|
146
60
|
type ShapeIn<Fields extends FieldsShape, K extends string> = K extends keyof Fields ? ShapeOf<Fields[K]> : undefined
|
|
147
61
|
|
|
148
|
-
/**
|
|
149
|
-
* The structural SHAPE of one projected field, read off the source's
|
|
150
|
-
* schema type — an ordinary or selected relation's field contributes its
|
|
151
|
-
* descriptor's triple; a closed relation (bare or ψ-selected) contributes
|
|
152
|
-
* its synthetic `id` as a u64 and its payload columns' declared
|
|
153
|
-
* descriptors' triples through the closed value's typed `columns` carrier
|
|
154
|
-
* (whose runtime twin is the frozen `columns` record the mint carries).
|
|
155
|
-
* The engine stays the final authority at `Db.create`/`Db.open`.
|
|
156
|
-
*/
|
|
157
62
|
type ProjectedShape<S extends FaceSource, K extends string> = S extends AnySelected
|
|
158
63
|
? ShapeIn<RelationFields<S["relation"]>, K>
|
|
159
64
|
: S extends AnySelectedClosed
|
|
@@ -171,22 +76,14 @@ type ProjectedShape<S extends FaceSource, K extends string> = S extends AnySelec
|
|
|
171
76
|
: ShapeIn<Cols, K>
|
|
172
77
|
: undefined
|
|
173
78
|
|
|
174
|
-
/** The positionwise structural-shape tuple of a projection over `S`. */
|
|
175
79
|
type ShapesOf<S extends FaceSource, P extends readonly string[]> = {
|
|
176
80
|
readonly [I in keyof P]: ProjectedShape<S, P[I] & string>
|
|
177
81
|
}
|
|
178
82
|
|
|
179
|
-
/** The shape tuple a face projects, positionwise — the comparand of {@link SameShapes}. */
|
|
180
83
|
type FaceShapes<F extends AnyFace> = F extends Face<infer S, infer P> ? ShapesOf<S, P> : never
|
|
181
84
|
|
|
182
|
-
/** The projection arity of a face. */
|
|
183
85
|
type Arity<F extends AnyFace> = F["projection"]["length"]
|
|
184
86
|
|
|
185
|
-
/**
|
|
186
|
-
* The legible arity-mismatch verdict: when the two faces of a containment,
|
|
187
|
-
* bijection, or window project different numbers of fields, this type is
|
|
188
|
-
* intersected into the second face's parameter and names both arities.
|
|
189
|
-
*/
|
|
190
87
|
interface FaceArityMismatch<Left, Right> {
|
|
191
88
|
readonly "face arity mismatch — positional pairing requires both sides to project equally many fields": readonly [
|
|
192
89
|
Left,
|
|
@@ -194,11 +91,6 @@ interface FaceArityMismatch<Left, Right> {
|
|
|
194
91
|
]
|
|
195
92
|
}
|
|
196
93
|
|
|
197
|
-
/**
|
|
198
|
-
* Resolves to `unknown` (a no-op intersection) when the two faces project
|
|
199
|
-
* equally many fields, and to {@link FaceArityMismatch} otherwise — the
|
|
200
|
-
* named helper the statement constructors constrain with.
|
|
201
|
-
*/
|
|
202
94
|
type SameArity<A extends AnyFace, B extends AnyFace> =
|
|
203
95
|
Arity<A> extends Arity<B>
|
|
204
96
|
? Arity<B> extends Arity<A>
|
|
@@ -206,14 +98,6 @@ type SameArity<A extends AnyFace, B extends AnyFace> =
|
|
|
206
98
|
: FaceArityMismatch<Arity<A>, Arity<B>>
|
|
207
99
|
: FaceArityMismatch<Arity<A>, Arity<B>>
|
|
208
100
|
|
|
209
|
-
/**
|
|
210
|
-
* The legible shape-mismatch verdict: when the two faces of a containment,
|
|
211
|
-
* bijection, or window project structurally incompatible fields at any
|
|
212
|
-
* position, this type is intersected into the second face's parameter and
|
|
213
|
-
* names both shape tuples — a u64 face against a str face, a bytes width
|
|
214
|
-
* mismatch, an interval element mismatch, or a bare column against a
|
|
215
|
-
* closed reference (the roster slot) is a COMPILE error.
|
|
216
|
-
*/
|
|
217
101
|
interface FaceShapeMismatch<Left, Right> {
|
|
218
102
|
readonly "face shape mismatch — positionwise kind, width, element, and closed roster must be equal on both sides": readonly [
|
|
219
103
|
Left,
|
|
@@ -221,17 +105,6 @@ interface FaceShapeMismatch<Left, Right> {
|
|
|
221
105
|
]
|
|
222
106
|
}
|
|
223
107
|
|
|
224
|
-
/**
|
|
225
|
-
* Resolves to `unknown` (a no-op intersection) when the two faces project
|
|
226
|
-
* positionwise-equal structural shapes, and to {@link FaceShapeMismatch}
|
|
227
|
-
* otherwise. Equality is mutual tuple assignability over the
|
|
228
|
-
* kind/width/element/roster quadruples. This is the whole
|
|
229
|
-
* construction-time wall — deliberately: there is no domain to compare
|
|
230
|
-
* here (the roster is descriptor STRUCTURE, not a domain). The domain wall
|
|
231
|
-
* lives where domains are BORN: `schema()` computes every field's class
|
|
232
|
-
* from the statement list and holds the one-generator-per-class law, and
|
|
233
|
-
* query joins compare class names off the schema type.
|
|
234
|
-
*/
|
|
235
108
|
type SameShapes<A extends AnyFace, B extends AnyFace> =
|
|
236
109
|
FaceShapes<A> extends FaceShapes<B>
|
|
237
110
|
? FaceShapes<B> extends FaceShapes<A>
|
|
@@ -239,16 +112,6 @@ type SameShapes<A extends AnyFace, B extends AnyFace> =
|
|
|
239
112
|
: FaceShapeMismatch<FaceShapes<A>, FaceShapes<B>>
|
|
240
113
|
: FaceShapeMismatch<FaceShapes<A>, FaceShapes<B>>
|
|
241
114
|
|
|
242
|
-
/**
|
|
243
|
-
* Projects a face — one spelling, arity-generic: `on(Account, "holder")`
|
|
244
|
-
* for the common single-field position, `on(Booking, ["room", "during"])`
|
|
245
|
-
* for the composite/pointwise position (the interval-pointwise `==` and
|
|
246
|
-
* coverage recipes), `on(Account.where({...}), "id")` for a σ-carrying
|
|
247
|
-
* source. Field names are typechecked against the source (unknown field =
|
|
248
|
-
* type error, names autocomplete); tuple order is preserved (positional
|
|
249
|
-
* pairing with the other side, macro parity). The empty projection is
|
|
250
|
-
* unwritable by signature — it has no meaning in the statement grammar.
|
|
251
|
-
*/
|
|
252
115
|
function on<S extends FaceSource, const F extends FaceFields<S>>(source: S, field: F): Face<S, readonly [F]>
|
|
253
116
|
function on<S extends FaceSource, const P extends readonly [FaceFields<S>, ...FaceFields<S>[]]>(
|
|
254
117
|
source: S,
|
|
@@ -292,11 +155,6 @@ function faceMinted<S extends FaceSource, P extends readonly string[]>(
|
|
|
292
155
|
)
|
|
293
156
|
}
|
|
294
157
|
|
|
295
|
-
/**
|
|
296
|
-
* Renders one face in the exact macro notation — `Name(p1, p2 | f == lit,
|
|
297
|
-
* g == {a, b})`, the selection block only when σ is nonempty (the engine
|
|
298
|
-
* renderer's own shape, `schema/render.rs`).
|
|
299
|
-
*/
|
|
300
158
|
function renderFace(face: FaceData): string {
|
|
301
159
|
const projection = face.projection.join(", ")
|
|
302
160
|
if (face.selection.length === 0) {
|
package/src/fields.ts
CHANGED
|
@@ -1,20 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Field descriptors — the value half of the `schema!` field grammar
|
|
3
|
-
* (`docs/architecture/70-api.md`), MINIMAL edition: `bool`, `u64`, `i64`,
|
|
4
|
-
* `str`, `bytes(n)`, `interval(u64|i64[, width])`, each a plain frozen value
|
|
5
|
-
* that IS its own descriptor type — `{ kind, width?, element?, fresh? }` —
|
|
6
|
-
* honest at runtime and in the type alike. A field's VALUE type is its bare
|
|
7
|
-
* structural type (`u64` → `bigint`, `str` → `string`, `bytes(n)` →
|
|
8
|
-
* `Uint8Array`, intervals → `{ start, end }`): no brands, no phantoms, no
|
|
9
|
-
* minting casts. A descriptor carries STRUCTURE ONLY — domains are never
|
|
10
|
-
* declared anywhere (the owner ruling: THE LAWS TYPE THE COLUMNS): a
|
|
11
|
-
* field's domain is COMPUTED by `schema()` from the statement list, where
|
|
12
|
-
* the dependencies themselves induce the equivalence classes. The macro's
|
|
13
|
-
* refusals are reproduced representationally: `.fresh` exists only on u64,
|
|
14
|
-
* and no field-level constraint vocabulary of any kind exists —
|
|
15
|
-
* `unique`/`fk` are unwritable, not rejected.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
1
|
import * as errors from "@superbuilders/errors"
|
|
19
2
|
import type { LiteralSpec } from "#spec.ts"
|
|
20
3
|
|
|
@@ -24,7 +7,7 @@ import type { LiteralSpec } from "#spec.ts"
|
|
|
24
7
|
* The ray is representable (`end` = the element type's MAX_END); widths
|
|
25
8
|
* and signedness are NOT modeled on the value — they are descriptor-type
|
|
26
9
|
* labels the engine judges at the typed write boundary. Interval fields
|
|
27
|
-
* derive no order (the Rust refusal
|
|
10
|
+
* derive no order (the Rust refusal,,
|
|
28
11
|
* so no comparators exist on the value type.
|
|
29
12
|
*/
|
|
30
13
|
interface IntervalValue {
|
|
@@ -46,83 +29,38 @@ function span(start: bigint, end: bigint): IntervalValue {
|
|
|
46
29
|
return Object.freeze({ start, end })
|
|
47
30
|
}
|
|
48
31
|
|
|
49
|
-
/**
|
|
50
|
-
* A closed relation's roster as seen from a referencing field: the handle
|
|
51
|
-
* namespace `where()` selections and ground axioms resolve bare handle ids
|
|
52
|
-
* through (the macro's own rule: a handle is legal exactly on a field that
|
|
53
|
-
* references a closed relation). The roster is PRECISE in BOTH slots —
|
|
54
|
-
* `Name` carries the vocabulary's literal name and `H` the literal handle
|
|
55
|
-
* names in declaration order (the unbound `string` defaults exist only as
|
|
56
|
-
* the fallback where no roster is in scope). The name literal is
|
|
57
|
-
* load-bearing: the runtime twins judge roster VALUE IDENTITY, so two
|
|
58
|
-
* same-shaped vocabularies (`Yes/No` twice) are distinct — carrying the
|
|
59
|
-
* name makes the type the faithful encoding of that judgment, and a
|
|
60
|
-
* cross-vocabulary pairing fails at compile time, not construction. The
|
|
61
|
-
* runtime twin is the same frozen declaration-order value that was always
|
|
62
|
-
* there.
|
|
63
|
-
*/
|
|
64
32
|
interface ClosedRoster<Name extends string = string, H extends string = string> {
|
|
65
33
|
readonly name: Name
|
|
66
34
|
readonly handles: readonly H[]
|
|
67
35
|
}
|
|
68
36
|
|
|
69
|
-
/** The `bool` field descriptor: value type `boolean`. No `.fresh` (macro parity). */
|
|
70
37
|
interface BoolField {
|
|
71
38
|
readonly kind: "bool"
|
|
72
39
|
}
|
|
73
40
|
|
|
74
|
-
/** The `str` field descriptor: value type `string`. No `.fresh` (macro parity). */
|
|
75
41
|
interface StrField {
|
|
76
42
|
readonly kind: "str"
|
|
77
43
|
}
|
|
78
44
|
|
|
79
|
-
/**
|
|
80
|
-
* A `fresh`-marked u64 field descriptor — `id: u64.fresh`. The mark is a
|
|
81
|
-
* structural label (`fresh: true`) in the descriptor type AND on the
|
|
82
|
-
* runtime value; it implies the key `R(field) -> R`, which the ENGINE
|
|
83
|
-
* materializes (`SchemaDescriptor::materialized_statements`), and it makes
|
|
84
|
-
* the field a GENERATOR — `schema()` names its equivalence class by the
|
|
85
|
-
* declaration coordinate (`"Account.id"`). Terminal: no builder property
|
|
86
|
-
* survives the mark.
|
|
87
|
-
*/
|
|
88
45
|
interface FreshU64Field {
|
|
89
46
|
readonly kind: "u64"
|
|
90
47
|
readonly fresh: true
|
|
91
48
|
}
|
|
92
49
|
|
|
93
|
-
/**
|
|
94
|
-
* The `u64` field descriptor. `.fresh` marks the field as engine-minted —
|
|
95
|
-
* the property doubles as the mark itself: on an unmarked descriptor it
|
|
96
|
-
* holds the marked descriptor, on a marked one it IS the literal `true`
|
|
97
|
-
* (one structural property, read either way).
|
|
98
|
-
*/
|
|
99
50
|
interface U64Field {
|
|
100
51
|
readonly kind: "u64"
|
|
101
52
|
readonly fresh: FreshU64Field
|
|
102
53
|
}
|
|
103
54
|
|
|
104
|
-
/** The `i64` field descriptor. Terminal: `.fresh` is legal on u64 only. */
|
|
105
55
|
interface I64Field {
|
|
106
56
|
readonly kind: "i64"
|
|
107
57
|
}
|
|
108
58
|
|
|
109
|
-
/**
|
|
110
|
-
* A `bytes<N>` field descriptor. The width is a descriptor-type label
|
|
111
|
-
* (load-bearing: the engine enforces it at the write boundary) and the
|
|
112
|
-
* value type is bare `Uint8Array`. No order is derived — no comparators
|
|
113
|
-
* exist on the value type (the engine refuses order on bytes).
|
|
114
|
-
*/
|
|
115
59
|
interface BytesField<Width extends number = number> {
|
|
116
60
|
readonly kind: "bytes"
|
|
117
61
|
readonly width: Width
|
|
118
62
|
}
|
|
119
63
|
|
|
120
|
-
/**
|
|
121
|
-
* An interval field descriptor — `interval(i64)` general (rays
|
|
122
|
-
* representable), `interval(u64, w)` the fixed-width family. Element and
|
|
123
|
-
* width are descriptor-type labels; the value type is always the bare
|
|
124
|
-
* {@link IntervalValue}.
|
|
125
|
-
*/
|
|
126
64
|
interface IntervalField<
|
|
127
65
|
Element extends "u64" | "i64" = "u64" | "i64",
|
|
128
66
|
Width extends bigint | undefined = bigint | undefined
|
|
@@ -132,34 +70,13 @@ interface IntervalField<
|
|
|
132
70
|
readonly width: Width
|
|
133
71
|
}
|
|
134
72
|
|
|
135
|
-
/**
|
|
136
|
-
* A closed relation's reference field descriptor (`Kind.id`) — a u64
|
|
137
|
-
* descriptor carrying the closed linkage: the roster resolves handle
|
|
138
|
-
* literals in selections and ground axioms, and `schema()` names the id's
|
|
139
|
-
* generator class `"Kind.id"`. The handle union `H` is the field's VALUE
|
|
140
|
-
* TYPE (see {@link Infer}); `kind: "u64"` stays load-bearing for the class
|
|
141
|
-
* map and JoinOk, which compare kind/class/width/element. Terminal: no
|
|
142
|
-
* `.fresh` — a vocabulary's rows are ground axioms, never minted.
|
|
143
|
-
*/
|
|
144
73
|
interface ClosedIdField<Name extends string = string, H extends string = string> {
|
|
145
74
|
readonly kind: "u64"
|
|
146
75
|
readonly closed: ClosedRoster<Name, H>
|
|
147
76
|
}
|
|
148
77
|
|
|
149
|
-
/** Any field descriptor, whatever its kind or marks. */
|
|
150
78
|
type AnyField = BoolField | StrField | U64Field | FreshU64Field | I64Field | BytesField | IntervalField | ClosedIdField
|
|
151
79
|
|
|
152
|
-
/**
|
|
153
|
-
* The bare structural VALUE type of a field descriptor — the one total
|
|
154
|
-
* definition every fact, result row, and query term reads: `bool` →
|
|
155
|
-
* `boolean`, `str` → `string`, `u64`/`i64` → `bigint`, `bytes<N>` →
|
|
156
|
-
* `Uint8Array`, intervals → {@link IntervalValue}, and a closed reference →
|
|
157
|
-
* its PRECISE handle union (`"DirectPass" | "Failed"` — the string-literal
|
|
158
|
-
* union IS the value type at the TS surface; the engine keeps u64 row ids
|
|
159
|
-
* and the marshal owns the bijection). The closed arm precedes the `u64`
|
|
160
|
-
* arm because a closed reference is structurally a u64 descriptor plus the
|
|
161
|
-
* roster.
|
|
162
|
-
*/
|
|
163
80
|
type Infer<F extends AnyField> = F extends { readonly kind: "bool" }
|
|
164
81
|
? boolean
|
|
165
82
|
: F extends { readonly kind: "str" }
|
|
@@ -186,13 +103,6 @@ function literalShapeError(context: string, expected: string, value: unknown): E
|
|
|
186
103
|
return errors.new(`${context}: expected ${expected}, got ${typeof value}`)
|
|
187
104
|
}
|
|
188
105
|
|
|
189
|
-
/**
|
|
190
|
-
* The roster a field descriptor carries — THE one reader: present exactly
|
|
191
|
-
* on a closed-reference descriptor (the structural `closed` property of
|
|
192
|
-
* {@link ClosedIdField}), absent on every other field kind. Tolerates
|
|
193
|
-
* `undefined` so name-lookup misses flow through without a re-spelled
|
|
194
|
-
* probe at every call site.
|
|
195
|
-
*/
|
|
196
106
|
function rosterOf(field: AnyField | undefined): ClosedRoster | undefined {
|
|
197
107
|
if (field !== undefined && "closed" in field) {
|
|
198
108
|
return field.closed
|
|
@@ -200,7 +110,6 @@ function rosterOf(field: AnyField | undefined): ClosedRoster | undefined {
|
|
|
200
110
|
return undefined
|
|
201
111
|
}
|
|
202
112
|
|
|
203
|
-
/** Narrows an interval-shaped value: a plain object with bigint start/end — THE one interval predicate. */
|
|
204
113
|
function isIntervalValue(value: unknown): value is IntervalValue {
|
|
205
114
|
return (
|
|
206
115
|
typeof value === "object" &&
|
|
@@ -212,15 +121,6 @@ function isIntervalValue(value: unknown): value is IntervalValue {
|
|
|
212
121
|
)
|
|
213
122
|
}
|
|
214
123
|
|
|
215
|
-
/**
|
|
216
|
-
* Resolves one closed-handle literal: the handle NAME, verified against the
|
|
217
|
-
* roster — an unknown name is a construction error, the belt the wide
|
|
218
|
-
* fallback type deliberately does not provide (structural values make any
|
|
219
|
-
* string spellable here; the roster judges). The name IS the value at the
|
|
220
|
-
* TS surface (the drizzle law); the wire literal already crossed as
|
|
221
|
-
* `{ kind: "handle", handle }`, so the output — and every fingerprint
|
|
222
|
-
* derived from it — is untouched.
|
|
223
|
-
*/
|
|
224
124
|
function handleLiteral(closed: ClosedRoster, value: unknown): LiteralSpec {
|
|
225
125
|
if (typeof value !== "string") {
|
|
226
126
|
throw literalShapeError("selection literal", `a ${closed.name} handle name (string)`, value)
|
|
@@ -231,7 +131,6 @@ function handleLiteral(closed: ClosedRoster, value: unknown): LiteralSpec {
|
|
|
231
131
|
return { kind: "handle", handle: value }
|
|
232
132
|
}
|
|
233
133
|
|
|
234
|
-
/** Lowers one interval literal at its element type. */
|
|
235
134
|
function intervalLiteral(element: "u64" | "i64", value: unknown): LiteralSpec {
|
|
236
135
|
if (!isIntervalValue(value)) {
|
|
237
136
|
throw literalShapeError("selection literal", "interval ({ start, end } bigints)", value)
|
|
@@ -242,20 +141,6 @@ function intervalLiteral(element: "u64" | "i64", value: unknown): LiteralSpec {
|
|
|
242
141
|
return { kind: "value", value: { kind: "intervalI64", start: value.start, end: value.end } }
|
|
243
142
|
}
|
|
244
143
|
|
|
245
|
-
/**
|
|
246
|
-
* Rejects a declaration name that JavaScript would re-order, and a name
|
|
247
|
-
* that would break the class map's coordinate encoding. Declaration order =
|
|
248
|
-
* ordinal ids is the law relations, columns, and schemas all lean on, and
|
|
249
|
-
* it is carried by object-literal key order — which ECMA-262's
|
|
250
|
-
* OrdinaryOwnPropertyKeys breaks for integer-index keys (they enumerate
|
|
251
|
-
* first, ascending, regardless of where they were written). A `.` in a name
|
|
252
|
-
* would make the law engine's `${relation}.${field}` coordinate template
|
|
253
|
-
* non-injective at BOTH tiers (relation `"A.B"` field `"x"` and relation
|
|
254
|
-
* `"A"` field `"B.x"` are one coordinate), silently merging unrelated law
|
|
255
|
-
* classes — banned here, which is exact macro parity: Rust identifiers
|
|
256
|
-
* cannot contain dots. Both are construction errors, exactly as an
|
|
257
|
-
* unparseable name is a macro expansion error.
|
|
258
|
-
*/
|
|
259
144
|
function assertDeclarationOrderKey(where: string, name: string): void {
|
|
260
145
|
if (/^(?:0|[1-9][0-9]*)$/.test(name)) {
|
|
261
146
|
throw errors.new(
|
|
@@ -269,18 +154,6 @@ function assertDeclarationOrderKey(where: string, name: string): void {
|
|
|
269
154
|
}
|
|
270
155
|
}
|
|
271
156
|
|
|
272
|
-
/**
|
|
273
|
-
* Rejects a declaration record whose prototype was replaced. A plain
|
|
274
|
-
* `__proto__: {...}` property in an object literal is ECMA-262 Annex B's
|
|
275
|
-
* prototype SETTER, not a data property — the entry never becomes an own
|
|
276
|
-
* enumerable key, so the declared handle/field/relation would silently
|
|
277
|
-
* vanish from every `Object.keys`/`Object.entries` walk while the type
|
|
278
|
-
* tier still admits its name. A non-default prototype on a declaration
|
|
279
|
-
* literal proves exactly that spelling, so it is a construction error; the
|
|
280
|
-
* computed spelling `["__proto__"]: {...}` creates an own data property
|
|
281
|
-
* and is admitted (no name is reserved). `Object.create(null)` records
|
|
282
|
-
* stay admissible.
|
|
283
|
-
*/
|
|
284
157
|
function assertDeclarationRecord(where: string, record: object): void {
|
|
285
158
|
const proto = Object.getPrototypeOf(record)
|
|
286
159
|
if (proto !== Object.prototype && proto !== null) {
|
|
@@ -290,46 +163,23 @@ function assertDeclarationRecord(where: string, record: object): void {
|
|
|
290
163
|
}
|
|
291
164
|
}
|
|
292
165
|
|
|
293
|
-
/** The one fresh-marked u64 descriptor (the `.fresh` property of the unmarked one). */
|
|
294
166
|
const freshU64: FreshU64Field = Object.freeze({ kind: "u64", fresh: true })
|
|
295
167
|
|
|
296
|
-
/** The one `u64` constructor value. */
|
|
297
168
|
const u64: U64Field = Object.freeze({ kind: "u64", fresh: freshU64 })
|
|
298
169
|
|
|
299
|
-
/** The one `i64` constructor value. */
|
|
300
170
|
const i64: I64Field = Object.freeze({ kind: "i64" })
|
|
301
171
|
|
|
302
|
-
/** The one `bool` constructor value. */
|
|
303
172
|
const bool: BoolField = Object.freeze({ kind: "bool" })
|
|
304
173
|
|
|
305
|
-
/** The one `str` constructor value. */
|
|
306
174
|
const str: StrField = Object.freeze({ kind: "str" })
|
|
307
175
|
|
|
308
|
-
/**
|
|
309
|
-
* The `bytes<N>` field constructor. The width is mandatory and a
|
|
310
|
-
* descriptor-type label; `width` is validated to 1..=64 here because the
|
|
311
|
-
* grammar pins that range at declaration (`docs/architecture/70-api.md`
|
|
312
|
-
* § the `schema!` grammar: N ∈ 1..=64 — bare `bytes` does not parse), the
|
|
313
|
-
* macro-expansion boundary's analog being construction.
|
|
314
|
-
*/
|
|
315
176
|
function bytes<const Width extends number>(width: Width): BytesField<Width> {
|
|
316
177
|
if (!Number.isInteger(width) || width < 1 || width > 64) {
|
|
317
|
-
throw errors.new(
|
|
318
|
-
`bytes width must be an integer in 1..=64 (got ${width}) — docs/architecture/70-api.md pins the range at declaration`
|
|
319
|
-
)
|
|
178
|
+
throw errors.new(`bytes width must be an integer in 1..=64 (got ${width}) — the range is pinned at declaration`)
|
|
320
179
|
}
|
|
321
180
|
return Object.freeze({ kind: "bytes", width })
|
|
322
181
|
}
|
|
323
182
|
|
|
324
|
-
/**
|
|
325
|
-
* The interval field constructor — `interval(u64)` / `interval(i64)` for
|
|
326
|
-
* the general type (rays representable), `interval(u64, w)` for the
|
|
327
|
-
* fixed-width family whose width IS a descriptor-type label. The element is
|
|
328
|
-
* spelled with the u64/i64 constructor values themselves, never a string.
|
|
329
|
-
* `width >= 1` is validated here because the grammar pins it at declaration
|
|
330
|
-
* (`docs/architecture/70-api.md`: w ≥ 1; `interval<u64, 0>` is an
|
|
331
|
-
* expansion error naming the field).
|
|
332
|
-
*/
|
|
333
183
|
function interval<Element extends U64Field | I64Field>(element: Element): IntervalField<Element["kind"], undefined>
|
|
334
184
|
function interval<Element extends U64Field | I64Field, const Width extends bigint>(
|
|
335
185
|
element: Element,
|
|
@@ -341,21 +191,11 @@ function interval(element: U64Field | I64Field, width?: bigint): IntervalField<"
|
|
|
341
191
|
throw errors.new(`interval element must be the u64 or i64 field constructor (got ${elementKind})`)
|
|
342
192
|
}
|
|
343
193
|
if (width !== undefined && width < 1n) {
|
|
344
|
-
throw errors.new(
|
|
345
|
-
`interval width must be >= 1 (got ${width}) — docs/architecture/70-api.md pins w >= 1 at declaration`
|
|
346
|
-
)
|
|
194
|
+
throw errors.new(`interval width must be >= 1 (got ${width}) — w >= 1 is pinned at declaration`)
|
|
347
195
|
}
|
|
348
196
|
return Object.freeze({ kind: "interval", element: elementKind, width })
|
|
349
197
|
}
|
|
350
198
|
|
|
351
|
-
/**
|
|
352
|
-
* Lowers one host literal at its field position to the wire
|
|
353
|
-
* {@link LiteralSpec} — the selection-literal machine ground axioms and
|
|
354
|
-
* `where()` bindings both ride (one machine, same errors — the macro's own
|
|
355
|
-
* rule). A value on a closed-reference field IS its handle NAME (verified
|
|
356
|
-
* against the roster: an unknown name is a construction error); everything
|
|
357
|
-
* else lowers to a plain value tagged by the field's structural kind.
|
|
358
|
-
*/
|
|
359
199
|
function literalOf(field: AnyField, value: unknown): LiteralSpec {
|
|
360
200
|
const roster = rosterOf(field)
|
|
361
201
|
if (roster !== undefined) {
|
|
@@ -384,15 +224,7 @@ function literalOf(field: AnyField, value: unknown): LiteralSpec {
|
|
|
384
224
|
if (typeof value !== "string") {
|
|
385
225
|
throw literalShapeError("selection literal", "string", value)
|
|
386
226
|
}
|
|
387
|
-
|
|
388
|
-
* The marshal's bijection law at the schema-literal seam
|
|
389
|
-
* (`marshal.ts` cellOf): a lone surrogate would cross dbCreate
|
|
390
|
-
* lossily (stored as U+FFFD engine-side), collapsing two
|
|
391
|
-
* distinct TS schema values into one stored theory/fingerprint
|
|
392
|
-
* and splitting the canonical statement rendering from the
|
|
393
|
-
* SDK's. All three string-admission seams — fact row, query
|
|
394
|
-
* literal/param, schema literal — enforce the one law.
|
|
395
|
-
*/
|
|
227
|
+
|
|
396
228
|
if (!value.isWellFormed()) {
|
|
397
229
|
throw literalShapeError("selection literal", "well-formed string", value)
|
|
398
230
|
}
|