@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/src/fields.ts CHANGED
@@ -1,21 +1,18 @@
1
1
  /**
2
2
  * Field descriptors — the value half of the `schema!` field grammar
3
- * (`docs/architecture/70-api.md`), STRUCTURAL edition: `bool`, `u64`, `i64`,
3
+ * (`docs/architecture/70-api.md`), MINIMAL edition: `bool`, `u64`, `i64`,
4
4
  * `str`, `bytes(n)`, `interval(u64|i64[, width])`, each a plain frozen value
5
- * that IS its own descriptor type — `{ kind, domain, fresh?, width?,
6
- * element? }` — honest at runtime and in the type alike. A field's VALUE
7
- * type is its bare structural type (`u64` → `bigint`, `str` → `string`,
8
- * `bytes(n)` → `Uint8Array`, intervals → `{ start, end }`): no brands, no
9
- * phantoms, no minting casts. The domain is a string LABEL in the
10
- * descriptor type, attached by `.as("HolderId")` (the mirror of Rust's
11
- * `as HolderId`); same-string domains link fields, and the relational
12
- * builders (statements, queries) compare the labels structurally the
13
- * domain wall lives in the builders and the engine, never on the value.
14
- * The macro's refusals are reproduced representationally: `.as` exists only
15
- * where Rust's `as` is legal (u64, i64, bytes, intervals — never bool/str),
16
- * `.fresh` exists only on u64 (bare or after `.as`), and no field-level
17
- * constraint vocabulary of any kind exists — `unique`/`fk` are unwritable,
18
- * not rejected.
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.
19
16
  */
20
17
 
21
18
  import * as errors from "@superbuilders/errors"
@@ -23,8 +20,8 @@ import type { LiteralSpec } from "#spec.ts"
23
20
 
24
21
  /**
25
22
  * A half-open interval `[start, end)` as a plain value object — the ONE
26
- * interval value type, whatever the field's element domain or width label.
27
- * The ray is representable (`end` = the element domain's MAX_END); widths
23
+ * interval value type, whatever the field's element type or width label.
24
+ * The ray is representable (`end` = the element type's MAX_END); widths
28
25
  * and signedness are NOT modeled on the value — they are descriptor-type
29
26
  * labels the engine judges at the typed write boundary. Interval fields
30
27
  * derive no order (the Rust refusal, `docs/architecture/10-data-model.md`),
@@ -52,68 +49,56 @@ function span(start: bigint, end: bigint): IntervalValue {
52
49
  /**
53
50
  * A closed relation's roster as seen from a referencing field: the handle
54
51
  * namespace `where()` selections and ground axioms resolve bare handle ids
55
- * through (the macro's own rule: a handle is legal exactly on a field whose
56
- * domain is a closed relation's handle domain).
52
+ * through (the macro's own rule: a handle is legal exactly on a field that
53
+ * references a closed relation). The handle union is PRECISE — `H` carries
54
+ * the literal handle names in declaration order (the unbound `string`
55
+ * default exists only as the fallback where no roster is in scope); the
56
+ * runtime twin is the same frozen declaration-order array that was always
57
+ * there.
57
58
  */
58
- interface ClosedRoster {
59
+ interface ClosedRoster<H extends string = string> {
59
60
  readonly name: string
60
- readonly handles: readonly string[]
61
+ readonly handles: readonly H[]
61
62
  }
62
63
 
63
- /** The `bool` field descriptor: value type `boolean`. No `.as`, no `.fresh` (macro parity). */
64
+ /** The `bool` field descriptor: value type `boolean`. No `.fresh` (macro parity). */
64
65
  interface BoolField {
65
66
  readonly kind: "bool"
66
- readonly domain: undefined
67
67
  }
68
68
 
69
- /** The `str` field descriptor: value type `string`. No `.as`, no `.fresh` (macro parity). */
69
+ /** The `str` field descriptor: value type `string`. No `.fresh` (macro parity). */
70
70
  interface StrField {
71
71
  readonly kind: "str"
72
- readonly domain: undefined
73
72
  }
74
73
 
75
74
  /**
76
- * A `fresh`-marked u64 field descriptor — `id: u64.as("AccountId").fresh`
77
- * (Rust: `id: u64 as AccountId, fresh`). The mark is a structural label
78
- * (`fresh: true`) in the descriptor type AND on the runtime value; it
79
- * implies the key `R(field) -> R`, which the ENGINE materializes
80
- * (`SchemaDescriptor::materialized_statements`). Terminal: no builder
81
- * property survives the mark.
75
+ * A `fresh`-marked u64 field descriptor — `id: u64.fresh`. The mark is a
76
+ * structural label (`fresh: true`) in the descriptor type AND on the
77
+ * runtime value; it implies the key `R(field) -> R`, which the ENGINE
78
+ * materializes (`SchemaDescriptor::materialized_statements`), and it makes
79
+ * the field a GENERATOR — `schema()` names its equivalence class by the
80
+ * declaration coordinate (`"Account.id"`). Terminal: no builder property
81
+ * survives the mark.
82
82
  */
83
- interface FreshU64Field<Domain extends string | undefined = undefined> {
83
+ interface FreshU64Field {
84
84
  readonly kind: "u64"
85
- readonly domain: Domain
86
85
  readonly fresh: true
87
86
  }
88
87
 
89
88
  /**
90
- * A domain-labeled u64 field descriptor `const HolderId =
91
- * u64.as("HolderId")` (Rust: `u64 as HolderId`). The label lives in the
92
- * descriptor type only; the value type stays bare `bigint`. `.fresh` marks
93
- * the field as engine-minted — the property doubles as the mark itself:
94
- * on an unmarked descriptor it holds the marked descriptor, on a marked
95
- * one it IS the literal `true` (one structural property, read either way).
89
+ * The `u64` field descriptor. `.fresh` marks the field as engine-minted —
90
+ * the property doubles as the mark itself: on an unmarked descriptor it
91
+ * holds the marked descriptor, on a marked one it IS the literal `true`
92
+ * (one structural property, read either way).
96
93
  */
97
- interface U64Field<Domain extends string | undefined = undefined> {
94
+ interface U64Field {
98
95
  readonly kind: "u64"
99
- readonly domain: Domain
100
- readonly fresh: FreshU64Field<Domain>
96
+ readonly fresh: FreshU64Field
101
97
  }
102
98
 
103
- /** The `u64` constructor value: a bare u64 descriptor plus `.as` (one application — `.as` is absent on the result). */
104
- interface U64Ctor extends U64Field<undefined> {
105
- as<const Domain extends string>(domain: Domain): U64Field<Domain>
106
- }
107
-
108
- /** A domain-labeled i64 field descriptor. Terminal: `.fresh` is legal on u64 only. */
109
- interface I64Field<Domain extends string | undefined = undefined> {
99
+ /** The `i64` field descriptor. Terminal: `.fresh` is legal on u64 only. */
100
+ interface I64Field {
110
101
  readonly kind: "i64"
111
- readonly domain: Domain
112
- }
113
-
114
- /** The `i64` constructor value: a bare i64 descriptor plus `.as`. */
115
- interface I64Ctor extends I64Field<undefined> {
116
- as<const Domain extends string>(domain: Domain): I64Field<Domain>
117
102
  }
118
103
 
119
104
  /**
@@ -122,15 +107,9 @@ interface I64Ctor extends I64Field<undefined> {
122
107
  * value type is bare `Uint8Array`. No order is derived — no comparators
123
108
  * exist on the value type (the engine refuses order on bytes).
124
109
  */
125
- interface BytesField<Width extends number = number, Domain extends string | undefined = undefined> {
110
+ interface BytesField<Width extends number = number> {
126
111
  readonly kind: "bytes"
127
112
  readonly width: Width
128
- readonly domain: Domain
129
- }
130
-
131
- /** A `bytes(n)` constructor value: a bare bytes descriptor plus `.as`. */
132
- interface BytesCtor<Width extends number = number> extends BytesField<Width, undefined> {
133
- as<const Domain extends string>(domain: Domain): BytesField<Width, Domain>
134
113
  }
135
114
 
136
115
  /**
@@ -141,67 +120,56 @@ interface BytesCtor<Width extends number = number> extends BytesField<Width, und
141
120
  */
142
121
  interface IntervalField<
143
122
  Element extends "u64" | "i64" = "u64" | "i64",
144
- Width extends bigint | undefined = bigint | undefined,
145
- Domain extends string | undefined = undefined
123
+ Width extends bigint | undefined = bigint | undefined
146
124
  > {
147
125
  readonly kind: "interval"
148
126
  readonly element: Element
149
127
  readonly width: Width
150
- readonly domain: Domain
151
- }
152
-
153
- /** An `interval(e[, w])` constructor value: a bare interval descriptor plus `.as`. */
154
- interface IntervalCtor<
155
- Element extends "u64" | "i64" = "u64" | "i64",
156
- Width extends bigint | undefined = bigint | undefined
157
- > extends IntervalField<Element, Width, undefined> {
158
- as<const Domain extends string>(domain: Domain): IntervalField<Element, Width, Domain>
159
128
  }
160
129
 
161
130
  /**
162
131
  * A closed relation's reference field descriptor (`Kind.id`) — a u64
163
- * descriptor whose domain is the closed relation's handle domain
164
- * (`"KindId"`, mirroring Rust's `closed relation Kind as KindId`) and
165
- * whose roster resolves bare handle ids in selections and ground axioms.
166
- * Terminal: no `.as`, no `.fresh` its domain IS the closed relation's.
132
+ * descriptor carrying the closed linkage: the roster resolves handle
133
+ * literals in selections and ground axioms, and `schema()` names the id's
134
+ * generator class `"Kind.id"`. The handle union `H` is the field's VALUE
135
+ * TYPE (see {@link Infer}); `kind: "u64"` stays load-bearing for the class
136
+ * map and JoinOk, which compare kind/class/width/element. Terminal: no
137
+ * `.fresh` — a vocabulary's rows are ground axioms, never minted.
167
138
  */
168
- interface ClosedIdField<Domain extends string = string> {
139
+ interface ClosedIdField<H extends string = string> {
169
140
  readonly kind: "u64"
170
- readonly domain: Domain
171
- readonly closed: ClosedRoster
141
+ readonly closed: ClosedRoster<H>
172
142
  }
173
143
 
174
- /** Any field descriptor, whatever its kind, domain label, or marks. */
175
- type AnyField =
176
- | BoolField
177
- | StrField
178
- | U64Field<string | undefined>
179
- | FreshU64Field<string | undefined>
180
- | I64Field<string | undefined>
181
- | BytesField<number, string | undefined>
182
- | IntervalField<"u64" | "i64", bigint | undefined, string | undefined>
183
- | ClosedIdField
144
+ /** Any field descriptor, whatever its kind or marks. */
145
+ type AnyField = BoolField | StrField | U64Field | FreshU64Field | I64Field | BytesField | IntervalField | ClosedIdField
184
146
 
185
147
  /**
186
148
  * The bare structural VALUE type of a field descriptor — the one total
187
149
  * definition every fact, result row, and query term reads: `bool` →
188
- * `boolean`, `str` → `string`, `u64`/`i64` → `bigint` (domain labels
189
- * included the label never touches the value), `bytes<N>`
190
- * `Uint8Array`, intervals {@link IntervalValue}.
150
+ * `boolean`, `str` → `string`, `u64`/`i64` → `bigint`, `bytes<N>`
151
+ * `Uint8Array`, intervals {@link IntervalValue}, and a closed reference
152
+ * its PRECISE handle union (`"DirectPass" | "Failed"` the string-literal
153
+ * union IS the value type at the TS surface; the engine keeps u64 row ids
154
+ * and the marshal owns the bijection). The closed arm precedes the `u64`
155
+ * arm because a closed reference is structurally a u64 descriptor plus the
156
+ * roster.
191
157
  */
192
158
  type Infer<F extends AnyField> = F extends { readonly kind: "bool" }
193
159
  ? boolean
194
160
  : F extends { readonly kind: "str" }
195
161
  ? string
196
- : F extends { readonly kind: "u64" }
197
- ? bigint
198
- : F extends { readonly kind: "i64" }
162
+ : F extends { readonly closed: { readonly handles: readonly (infer H extends string)[] } }
163
+ ? H
164
+ : F extends { readonly kind: "u64" }
199
165
  ? bigint
200
- : F extends { readonly kind: "bytes" }
201
- ? Uint8Array
202
- : F extends { readonly kind: "interval" }
203
- ? IntervalValue
204
- : never
166
+ : F extends { readonly kind: "i64" }
167
+ ? bigint
168
+ : F extends { readonly kind: "bytes" }
169
+ ? Uint8Array
170
+ : F extends { readonly kind: "interval" }
171
+ ? IntervalValue
172
+ : never
205
173
 
206
174
  /**
207
175
  * The typed shape refusal of the selection-literal machine — reached only
@@ -224,22 +192,22 @@ function isIntervalLiteral(value: unknown): value is IntervalValue {
224
192
  }
225
193
 
226
194
  /**
227
- * Resolves one closed-handle literal: the handle id (a bare bigint) back to
228
- * its handle NAME through the roster an out-of-roster id is a
229
- * construction error, the belt the type level deliberately does not provide
230
- * (structural values make any bigint spellable here; the roster judges).
195
+ * Resolves one closed-handle literal: the handle NAME, verified against the
196
+ * roster an unknown name is a construction error, the belt the wide
197
+ * fallback type deliberately does not provide (structural values make any
198
+ * string spellable here; the roster judges). The name IS the value at the
199
+ * TS surface (the drizzle law); the wire literal already crossed as
200
+ * `{ kind: "handle", handle }`, so the output — and every fingerprint
201
+ * derived from it — is untouched.
231
202
  */
232
203
  function handleLiteral(closed: ClosedRoster, value: unknown): LiteralSpec {
233
- if (typeof value !== "bigint") {
234
- throw literalShapeError(`a ${closed.name} handle id (bigint)`, value)
204
+ if (typeof value !== "string") {
205
+ throw literalShapeError(`a ${closed.name} handle name (string)`, value)
235
206
  }
236
- const handle = closed.handles[Number(value)]
237
- if (handle === undefined) {
238
- throw errors.new(
239
- `closed relation ${closed.name} has no handle with id ${value} (roster holds ${closed.handles.length})`
240
- )
207
+ if (!closed.handles.includes(value)) {
208
+ throw errors.new(`"${value}" is not a handle of ${closed.name} — the roster is ${closed.handles.join(", ")}`)
241
209
  }
242
- return { kind: "handle", handle }
210
+ return { kind: "handle", handle: value }
243
211
  }
244
212
 
245
213
  /** Lowers one interval literal at its element type. */
@@ -271,35 +239,20 @@ function assertDeclarationOrderKey(where: string, name: string): void {
271
239
  }
272
240
  }
273
241
 
274
- /** Builds one fresh-marked u64 descriptor (the `.fresh` property of an unmarked one). */
275
- function freshU64<Domain extends string | undefined>(domain: Domain): FreshU64Field<Domain> {
276
- return Object.freeze({ kind: "u64", domain, fresh: true })
277
- }
242
+ /** The one fresh-marked u64 descriptor (the `.fresh` property of the unmarked one). */
243
+ const freshU64: FreshU64Field = Object.freeze({ kind: "u64", fresh: true })
278
244
 
279
245
  /** The one `u64` constructor value. */
280
- const u64: U64Ctor = Object.freeze({
281
- kind: "u64",
282
- domain: undefined,
283
- fresh: freshU64(undefined),
284
- as<const Domain extends string>(domain: Domain): U64Field<Domain> {
285
- return Object.freeze({ kind: "u64", domain, fresh: freshU64(domain) })
286
- }
287
- })
246
+ const u64: U64Field = Object.freeze({ kind: "u64", fresh: freshU64 })
288
247
 
289
248
  /** The one `i64` constructor value. */
290
- const i64: I64Ctor = Object.freeze({
291
- kind: "i64",
292
- domain: undefined,
293
- as<const Domain extends string>(domain: Domain): I64Field<Domain> {
294
- return Object.freeze({ kind: "i64", domain })
295
- }
296
- })
249
+ const i64: I64Field = Object.freeze({ kind: "i64" })
297
250
 
298
251
  /** The one `bool` constructor value. */
299
- const bool: BoolField = Object.freeze({ kind: "bool", domain: undefined })
252
+ const bool: BoolField = Object.freeze({ kind: "bool" })
300
253
 
301
254
  /** The one `str` constructor value. */
302
- const str: StrField = Object.freeze({ kind: "str", domain: undefined })
255
+ const str: StrField = Object.freeze({ kind: "str" })
303
256
 
304
257
  /**
305
258
  * The `bytes<N>` field constructor. The width is mandatory and a
@@ -308,20 +261,13 @@ const str: StrField = Object.freeze({ kind: "str", domain: undefined })
308
261
  * § the `schema!` grammar: N ∈ 1..=64 — bare `bytes` does not parse), the
309
262
  * macro-expansion boundary's analog being construction.
310
263
  */
311
- function bytes<const Width extends number>(width: Width): BytesCtor<Width> {
264
+ function bytes<const Width extends number>(width: Width): BytesField<Width> {
312
265
  if (!Number.isInteger(width) || width < 1 || width > 64) {
313
266
  throw errors.new(
314
267
  `bytes width must be an integer in 1..=64 (got ${width}) — docs/architecture/70-api.md pins the range at declaration`
315
268
  )
316
269
  }
317
- return Object.freeze({
318
- kind: "bytes",
319
- width,
320
- domain: undefined,
321
- as<const Domain extends string>(domain: Domain): BytesField<Width, Domain> {
322
- return Object.freeze({ kind: "bytes", width, domain })
323
- }
324
- })
270
+ return Object.freeze({ kind: "bytes", width })
325
271
  }
326
272
 
327
273
  /**
@@ -333,12 +279,12 @@ function bytes<const Width extends number>(width: Width): BytesCtor<Width> {
333
279
  * (`docs/architecture/70-api.md`: w ≥ 1; `interval<u64, 0>` is an
334
280
  * expansion error naming the field).
335
281
  */
336
- function interval<Element extends U64Ctor | I64Ctor>(element: Element): IntervalCtor<Element["kind"], undefined>
337
- function interval<Element extends U64Ctor | I64Ctor, const Width extends bigint>(
282
+ function interval<Element extends U64Field | I64Field>(element: Element): IntervalField<Element["kind"], undefined>
283
+ function interval<Element extends U64Field | I64Field, const Width extends bigint>(
338
284
  element: Element,
339
285
  width: Width
340
- ): IntervalCtor<Element["kind"], Width>
341
- function interval(element: U64Ctor | I64Ctor, width?: bigint): IntervalCtor<"u64" | "i64", bigint | undefined> {
286
+ ): IntervalField<Element["kind"], Width>
287
+ function interval(element: U64Field | I64Field, width?: bigint): IntervalField<"u64" | "i64", bigint | undefined> {
342
288
  const elementKind = element.kind
343
289
  if (elementKind !== "u64" && elementKind !== "i64") {
344
290
  throw errors.new(`interval element must be the u64 or i64 field constructor (got ${elementKind})`)
@@ -348,25 +294,16 @@ function interval(element: U64Ctor | I64Ctor, width?: bigint): IntervalCtor<"u64
348
294
  `interval width must be >= 1 (got ${width}) — docs/architecture/70-api.md pins w >= 1 at declaration`
349
295
  )
350
296
  }
351
- return Object.freeze({
352
- kind: "interval",
353
- element: elementKind,
354
- width,
355
- domain: undefined,
356
- as<const Domain extends string>(domain: Domain): IntervalField<"u64" | "i64", bigint | undefined, Domain> {
357
- return Object.freeze({ kind: "interval", element: elementKind, width, domain })
358
- }
359
- })
297
+ return Object.freeze({ kind: "interval", element: elementKind, width })
360
298
  }
361
299
 
362
300
  /**
363
301
  * Lowers one host literal at its field position to the wire
364
302
  * {@link LiteralSpec} — the selection-literal machine ground axioms and
365
303
  * `where()` bindings both ride (one machine, same errors — the macro's own
366
- * rule). A value on a closed-reference field resolves to its handle NAME
367
- * (the id is verified against the roster: an out-of-roster id is a
368
- * construction error); everything else lowers to a plain value tagged by
369
- * the field's structural kind.
304
+ * rule). A value on a closed-reference field IS its handle NAME (verified
305
+ * against the roster: an unknown name is a construction error); everything
306
+ * else lowers to a plain value tagged by the field's structural kind.
370
307
  */
371
308
  function literalOf(field: AnyField, value: unknown): LiteralSpec {
372
309
  if ("closed" in field) {
@@ -411,19 +348,15 @@ function literalOf(field: AnyField, value: unknown): LiteralSpec {
411
348
  export type {
412
349
  AnyField,
413
350
  BoolField,
414
- BytesCtor,
415
351
  BytesField,
416
352
  ClosedIdField,
417
353
  ClosedRoster,
418
354
  FreshU64Field,
419
- I64Ctor,
420
355
  I64Field,
421
356
  Infer,
422
- IntervalCtor,
423
357
  IntervalField,
424
358
  IntervalValue,
425
359
  StrField,
426
- U64Ctor,
427
360
  U64Field
428
361
  }
429
362
  export { assertDeclarationOrderKey, bool, bytes, i64, interval, literalOf, span, str, u64 }
package/src/index.ts CHANGED
@@ -1,16 +1,20 @@
1
1
  /**
2
2
  * @bjornpagen/bumbledb — the type-theoretic TypeScript SDK for the
3
3
  * bumbledb embedded relational engine. Public surface: the structural type
4
- * kernel (fields with schema-level domain labels, `relation()`,
5
- * `closed()`), the statement
6
- * algebra with `schema()` and `SchemaSpec` lowering (PRD-06), the `Db`
4
+ * kernel (fields as pure structure, `relation()`, `closed()` — domains are
5
+ * never declared: THE LAWS TYPE THE COLUMNS, `schema()` computing every
6
+ * field's equivalence class FROM the statement list at both tiers), the
7
+ * statement algebra with `schema()` and `SchemaSpec` lowering (PRD-06), the `Db`
7
8
  * runtime (path-cached stores, transactions, typed violations, scoped
8
9
  * snapshot reads, the witnessed write loop with `abandon` — PRD-07, zero
9
10
  * closables), the query surface (Datalog as values, kysely-shaped:
10
11
  * `query(S).rule(r => r.match(...).where(...).select(...))` with
11
12
  * string-named domain-typed vars, params typed by use, negation,
12
13
  * conditions, aggregates, and stratified recursion via `program()`/`rec` —
13
- * `db.prepare` as a plain value), and the exhume surface
14
+ * `db.prepare` as a plain value; the comparison/connective builders are
15
+ * also free exports, and the free names `eq`/`not`/`and`/`or` collide with
16
+ * common host identifiers — import aliasing is the answer; the SDK does
17
+ * not rename for collision-avoidance), and the exhume surface
14
18
  * (`Db.exhume` — the one schema-independent read path: the store's
15
19
  * self-described shapes and raw facts by name, typed at bare structural
16
20
  * values, deliberately schema-free). The raw native bridge is not exported.
@@ -18,6 +22,7 @@
18
22
 
19
23
  export type {
20
24
  AnyClosed,
25
+ AnySelectedClosed,
21
26
  AxiomRow,
22
27
  Axioms,
23
28
  Closed,
@@ -25,7 +30,9 @@ export type {
25
30
  ClosedCore,
26
31
  ClosedData,
27
32
  ClosedRow,
28
- PayloadField
33
+ ClosedSelectionInput,
34
+ PayloadField,
35
+ SelectedClosed
29
36
  } from "#closed.ts"
30
37
  export { closed } from "#closed.ts"
31
38
  export type { Count } from "#count.ts"
@@ -43,7 +50,7 @@ export type {
43
50
  WitnessedWriteResult,
44
51
  WriteResult
45
52
  } from "#db.ts"
46
- export { abandon, Db } from "#db.ts"
53
+ export { abandon, Db, ErrNewtypeMismatch } from "#db.ts"
47
54
  export type {
48
55
  Exhumed,
49
56
  ExhumedAxiom,
@@ -63,35 +70,32 @@ export type {
63
70
  Face,
64
71
  FaceArityMismatch,
65
72
  FaceData,
66
- FaceDomainMismatch,
67
- FaceDomains,
68
73
  FaceFields,
69
74
  FaceOwner,
75
+ FaceShapeMismatch,
76
+ FaceShapes,
70
77
  FaceSource,
71
- OneOf,
78
+ OwnerOf,
72
79
  SameArity,
73
- SameDomains
80
+ SameShapes
74
81
  } from "#face.ts"
75
- export { on, oneOf } from "#face.ts"
82
+ export { on } from "#face.ts"
76
83
  export type {
77
84
  AnyField,
78
85
  BoolField,
79
- BytesCtor,
80
86
  BytesField,
81
87
  ClosedIdField,
82
88
  ClosedRoster,
83
89
  FreshU64Field,
84
- I64Ctor,
85
90
  I64Field,
86
91
  Infer,
87
- IntervalCtor,
88
92
  IntervalField,
89
93
  IntervalValue,
90
94
  StrField,
91
- U64Ctor,
92
95
  U64Field
93
96
  } from "#fields.ts"
94
97
  export { bool, bytes, i64, interval, span, str, u64 } from "#fields.ts"
98
+ export type { ClassesOf, ClassWall, LawfulStatements, RelationClasses, SchemaClasses } from "#law.ts"
95
99
  export { lower, lowerClosed, lowerRelation } from "#lower.ts"
96
100
  export type { KeyFact, Minted } from "#marshal.ts"
97
101
  export type {
@@ -106,6 +110,8 @@ export type {
106
110
  AnyCond,
107
111
  BindingInput,
108
112
  Cmp,
113
+ MatchFields,
114
+ MatchOwner,
109
115
  MatchShape,
110
116
  NotAtom,
111
117
  RecData,
@@ -113,7 +119,7 @@ export type {
113
119
  SelectColumn,
114
120
  Tree
115
121
  } from "#query/atom.ts"
116
- export { ALLEN } from "#query/atom.ts"
122
+ export { ALLEN, allen, and, covers, eq, ge, gt, le, lt, ne, not, or, pointIn } from "#query/atom.ts"
117
123
  export type {
118
124
  AnyQuery,
119
125
  AnyRuleValue,
@@ -136,7 +142,17 @@ export type {
136
142
  export { lowerQuery, query } from "#query/lower.ts"
137
143
  export type { ProgramScope, Rec } from "#query/predicate.ts"
138
144
  export { program } from "#query/predicate.ts"
139
- export type { Duration, MaskParam, Param, ParamEntry, ParamsRecord, SetParam, Var } from "#query/scope.ts"
145
+ export type {
146
+ ClassedField,
147
+ Duration,
148
+ MaskParam,
149
+ Param,
150
+ ParamEntry,
151
+ ParamsRecord,
152
+ SetParam,
153
+ Var,
154
+ VarsRecord
155
+ } from "#query/scope.ts"
140
156
  export type { Agg, SelectEntry } from "#query/select.ts"
141
157
  export type {
142
158
  AnyRelation,
@@ -172,5 +188,14 @@ export type {
172
188
  WindowSpec
173
189
  } from "#spec.ts"
174
190
  export { renderLiteral, renderLiteralSet, renderWindow } from "#spec.ts"
175
- export type { KeyData, KeyStatement, Statement, StatementData } from "#statements.ts"
191
+ export type {
192
+ ContainedStatement,
193
+ ContainmentData,
194
+ KeyData,
195
+ KeyStatement,
196
+ Statement,
197
+ StatementData,
198
+ WindowData,
199
+ WindowStatement
200
+ } from "#statements.ts"
176
201
  export { contained, key, mirrors, renderStatement, window } from "#statements.ts"