@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.
Files changed (108) hide show
  1. package/COOKBOOK.md +58 -62
  2. package/README.md +82 -56
  3. package/dist/capacity.d.ts +24 -136
  4. package/dist/capacity.d.ts.map +1 -1
  5. package/dist/capacity.js +18 -40
  6. package/dist/capacity.js.map +1 -1
  7. package/dist/closed.d.ts +0 -156
  8. package/dist/closed.d.ts.map +1 -1
  9. package/dist/closed.js +0 -104
  10. package/dist/closed.js.map +1 -1
  11. package/dist/db.d.ts +93 -290
  12. package/dist/db.d.ts.map +1 -1
  13. package/dist/db.js +713 -556
  14. package/dist/db.js.map +1 -1
  15. package/dist/face.d.ts +0 -133
  16. package/dist/face.d.ts.map +1 -1
  17. package/dist/face.js +0 -33
  18. package/dist/face.js.map +1 -1
  19. package/dist/fields.d.ts +1 -145
  20. package/dist/fields.d.ts.map +1 -1
  21. package/dist/fields.js +2 -91
  22. package/dist/fields.js.map +1 -1
  23. package/dist/index.d.ts +13 -23
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +11 -20
  26. package/dist/index.js.map +1 -1
  27. package/dist/law.d.ts +111 -93
  28. package/dist/law.d.ts.map +1 -1
  29. package/dist/law.js +23 -27
  30. package/dist/law.js.map +1 -1
  31. package/dist/lower.d.ts +9 -35
  32. package/dist/lower.d.ts.map +1 -1
  33. package/dist/lower.js +8 -53
  34. package/dist/lower.js.map +1 -1
  35. package/dist/marshal.d.ts +0 -65
  36. package/dist/marshal.d.ts.map +1 -1
  37. package/dist/marshal.js +0 -72
  38. package/dist/marshal.js.map +1 -1
  39. package/dist/native.d.ts +97 -390
  40. package/dist/native.d.ts.map +1 -1
  41. package/dist/native.js +39 -61
  42. package/dist/native.js.map +1 -1
  43. package/dist/query/atom.d.ts +10 -276
  44. package/dist/query/atom.d.ts.map +1 -1
  45. package/dist/query/atom.js +1 -96
  46. package/dist/query/atom.js.map +1 -1
  47. package/dist/query/find.d.ts +10 -76
  48. package/dist/query/find.d.ts.map +1 -1
  49. package/dist/query/find.js +0 -30
  50. package/dist/query/find.js.map +1 -1
  51. package/dist/query/lower.d.ts +64 -146
  52. package/dist/query/lower.d.ts.map +1 -1
  53. package/dist/query/lower.js +19 -256
  54. package/dist/query/lower.js.map +1 -1
  55. package/dist/query/parse-ir.d.ts +0 -7
  56. package/dist/query/parse-ir.d.ts.map +1 -1
  57. package/dist/query/parse-ir.js +1 -13
  58. package/dist/query/parse-ir.js.map +1 -1
  59. package/dist/query/run.d.ts +0 -36
  60. package/dist/query/run.d.ts.map +1 -1
  61. package/dist/query/run.js +0 -44
  62. package/dist/query/run.js.map +1 -1
  63. package/dist/query/scope.d.ts +24 -180
  64. package/dist/query/scope.d.ts.map +1 -1
  65. package/dist/query/scope.js +2 -66
  66. package/dist/query/scope.js.map +1 -1
  67. package/dist/relation.d.ts +2 -50
  68. package/dist/relation.d.ts.map +1 -1
  69. package/dist/relation.js +2 -37
  70. package/dist/relation.js.map +1 -1
  71. package/dist/schema.d.ts +13 -63
  72. package/dist/schema.d.ts.map +1 -1
  73. package/dist/schema.js +118 -92
  74. package/dist/schema.js.map +1 -1
  75. package/dist/spec.d.ts +1 -140
  76. package/dist/spec.d.ts.map +1 -1
  77. package/dist/spec.js +1 -68
  78. package/dist/spec.js.map +1 -1
  79. package/dist/statements.d.ts +6 -137
  80. package/dist/statements.d.ts.map +1 -1
  81. package/dist/statements.js +16 -119
  82. package/dist/statements.js.map +1 -1
  83. package/package.json +3 -3
  84. package/src/capacity.ts +26 -140
  85. package/src/closed.ts +5 -206
  86. package/src/db.ts +997 -854
  87. package/src/face.ts +0 -142
  88. package/src/fields.ts +4 -172
  89. package/src/index.ts +32 -35
  90. package/src/law.ts +201 -129
  91. package/src/lower.ts +8 -53
  92. package/src/marshal.ts +1 -85
  93. package/src/native.ts +192 -413
  94. package/src/query/atom.ts +26 -313
  95. package/src/query/find.ts +24 -110
  96. package/src/query/lower.ts +132 -377
  97. package/src/query/parse-ir.ts +1 -14
  98. package/src/query/run.ts +0 -45
  99. package/src/query/scope.ts +25 -186
  100. package/src/relation.ts +2 -66
  101. package/src/schema.ts +143 -122
  102. package/src/spec.ts +1 -160
  103. package/src/statements.ts +22 -174
  104. package/dist/exhume.d.ts +0 -143
  105. package/dist/exhume.d.ts.map +0 -1
  106. package/dist/exhume.js +0 -166
  107. package/dist/exhume.js.map +0 -1
  108. package/src/exhume.ts +0 -267
package/src/lower.ts CHANGED
@@ -3,9 +3,13 @@
3
3
  * data (`#spec.ts`), which the napi bridge marshals verbatim. Lowering is
4
4
  * TOTAL on well-typed inputs — no validation lives here beyond what the
5
5
  * types and the construction boundaries already guarantee — and it is the
6
- * only place statement internals are read for the wire. Ordering is
7
- * declaration order throughout, and every output object is built with one
8
- * fixed key order, so serialization is deterministic (byte-stable).
6
+ * only place statement internals are read for the wire. In particular,
7
+ * lowering never emits an engine-refused containment target: it accepts
8
+ * only `schema` outputs, and `schema`'s target-key wall already
9
+ * refused any non-key target projection (60-containment-parity —
10
+ * totality INHERITED, not re-checked). Ordering is declaration order
11
+ * throughout, and every output object is built with one fixed key order,
12
+ * so serialization is deterministic (byte-stable).
9
13
  */
10
14
 
11
15
  import * as errors from "@superbuilders/errors"
@@ -27,12 +31,6 @@ import type {
27
31
  } from "#spec.ts"
28
32
  import type { Statement } from "#statements.ts"
29
33
 
30
- /**
31
- * Lowers one field descriptor's structural type to the wire
32
- * {@link ValueTypeSpec}: the S1 kind tags map 1:1 onto the `ValueType`
33
- * vocabulary (`str` spells `string`, `bytes` spells `fixedBytes` with its
34
- * width label as `len`; intervals carry element and width labels through).
35
- */
36
34
  function valueTypeOf(field: AnyField): ValueTypeSpec {
37
35
  switch (field.kind) {
38
36
  case "bool":
@@ -50,16 +48,6 @@ function valueTypeOf(field: AnyField): ValueTypeSpec {
50
48
  }
51
49
  }
52
50
 
53
- /**
54
- * Lowers one field descriptor to its {@link FieldSpec}: the structural
55
- * type, the structural fresh mark (`fresh` is the literal `true` exactly
56
- * on a fresh-marked u64 — on an unmarked one the property holds the marked
57
- * descriptor, never `true`), and the wire's `newtype` — the COMPUTED class
58
- * name `schema()` derived from the statement list (the laws type the
59
- * columns), `undefined` on a bare field. The engine reads newtypes for
60
- * handle resolution and the coherence check only and DROPS them at
61
- * descriptor lowering — class names are never fingerprinted.
62
- */
63
51
  function lowerField(name: string, field: AnyField, newtype: string | undefined): FieldSpec {
64
52
  return {
65
53
  name,
@@ -69,7 +57,6 @@ function lowerField(name: string, field: AnyField, newtype: string | undefined):
69
57
  }
70
58
  }
71
59
 
72
- /** Lowers one face to a `SideSpec`: names only, σ as (field, set) pairs. */
73
60
  function lowerFace(face: FaceData): SideSpec {
74
61
  return {
75
62
  relation: face.owner.name,
@@ -80,12 +67,6 @@ function lowerFace(face: FaceData): SideSpec {
80
67
  }
81
68
  }
82
69
 
83
- /**
84
- * Lowers one statement. `mirrors` stays ONE spec statement
85
- * (`bidirectional: true`) — the engine performs the `==` lowering to two
86
- * adjacent containments, `source <= target` first, exactly as the macro
87
- * does.
88
- */
89
70
  function lowerStatement(statement: Statement): StatementSpec {
90
71
  const data = statement.data
91
72
  switch (data.kind) {
@@ -116,13 +97,6 @@ function lowerStatement(statement: Statement): StatementSpec {
116
97
  }
117
98
  }
118
99
 
119
- /**
120
- * Lowers one ordinary relation to its `RelationSpec` fragment: fields in
121
- * declaration order, each carrying its law-computed class name as the
122
- * `newtype` (`classes` — the schema's class record for this relation;
123
- * bare fields carry `undefined`), `closed: undefined` (the option is the
124
- * kind — one sum, R7).
125
- */
126
100
  function lowerRelation(relation: AnyRelation, classes: RelationClasses): RelationSpec {
127
101
  const fields: FieldSpec[] = relation.data.fields.map(function lowerDeclared(declared) {
128
102
  return lowerField(declared.name, declared.field, classes[declared.name])
@@ -130,16 +104,6 @@ function lowerRelation(relation: AnyRelation, classes: RelationClasses): Relatio
130
104
  return { name: relation.name, fields, closed: undefined }
131
105
  }
132
106
 
133
- /**
134
- * Lowers one closed relation to its `RelationSpec` fragment: declared
135
- * intrinsic columns only (the engine materializes the synthetic `id`) and
136
- * the fused closedness sum (R7) — the handle newtype (the COMPUTED class
137
- * name of the id's generator class, `"Kind.id"`, always present: a closed
138
- * id is a generator; every referencing field shares it by law, which is
139
- * how the engine resolves a handle literal back to its roster) together
140
- * with the ground axioms in declaration order (row id = index); the
141
- * literals were already lowered at `closed()` construction.
142
- */
143
107
  function lowerClosed(member: AnyClosed, classes: RelationClasses): RelationSpec {
144
108
  const fields: FieldSpec[] = member.data.columns.map(function lowerColumn(column) {
145
109
  return lowerField(column.name, column.field, classes[column.name])
@@ -154,17 +118,8 @@ function lowerClosed(member: AnyClosed, classes: RelationClasses): RelationSpec
154
118
  return { name: member.name, fields, closed: { newtype, rows } }
155
119
  }
156
120
 
157
- /** The frozen empty class record a relation outside the schema's map lowers under (nothing classed). */
158
121
  const noClasses: RelationClasses = Object.freeze({})
159
122
 
160
- /**
161
- * Lowers a whole theory to the `SchemaSpec` the bridge takes: relations in
162
- * record declaration order, DECLARED statements only in written order (the
163
- * engine materializes the fresh-implied and closed auto-keys itself), and
164
- * every field's `newtype` slot fed from the schema's law-computed class
165
- * map — the ONE domain authority (fingerprint-neutral: the engine drops
166
- * newtypes at descriptor lowering).
167
- */
168
123
  function lower(theory: AnySchema): SchemaSpec {
169
124
  const relations: RelationSpec[] = Object.entries(theory.relations).map(function lowerMember([name, member]) {
170
125
  const classes = theory.classes[name] ?? noClasses
@@ -176,4 +131,4 @@ function lower(theory: AnySchema): SchemaSpec {
176
131
  return { relations, statements: theory.statements.map(lowerStatement) }
177
132
  }
178
133
 
179
- export { lower, lowerClosed, lowerRelation }
134
+ export { lower }
package/src/marshal.ts CHANGED
@@ -33,42 +33,14 @@ import { isIntervalValue, literalShapeError, rosterOf } from "#fields.ts"
33
33
  import type { FactValue } from "#native.ts"
34
34
  import type { AnyRelation, Fact, FreshKeys, RelationData } from "#relation.ts"
35
35
 
36
- /**
37
- * The fresh-mark probe: `true` exactly for a `.fresh`-marked u64 descriptor
38
- * (the S1 kernel's one structural mark — an unmarked u64's `fresh` property
39
- * holds the MARKED descriptor, so the probe compares against the literal
40
- * `true`, never truthiness).
41
- */
42
36
  function isFreshField(field: AnyField): boolean {
43
37
  return "fresh" in field && field.fresh === true
44
38
  }
45
39
 
46
- /**
47
- * The key object `get` reads through. THE PRIMARY-KEY RULE: `get` always
48
- * reads through the PRIMARY candidate key — the first-declared one in the
49
- * engine's materialized statement order (fresh-implied keys first, closed
50
- * auto-keys second, declared `key()` statements last), so a fresh-bearing
51
- * relation's primary key is always its fresh field. When `R` carries a
52
- * fresh field the type demands exactly that field; otherwise the primary
53
- * key lives in the schema's statement list, which the type system cannot
54
- * see (the schema's statement list is not carried in the schema's type,
55
- * only in the KeyStatement values themselves), so the type admits any partial fact
56
- * and the projection is verified at runtime — a missing key field throws
57
- * naming the projection.
58
- */
59
40
  type KeyFact<R extends AnyRelation> = [FreshKeys<R>] extends [never]
60
41
  ? Partial<Fact<R>>
61
42
  : { [K in FreshKeys<R>]: Fact<R>[K] }
62
43
 
63
- /**
64
- * Reprojects any host object to a string-indexed record — the boundary
65
- * through which generic fact objects (whose type parameters carry no index
66
- * signature) enter the name-directed marshaling below, without a cast. An
67
- * ALLOCATION-FREE IDENTITY (the admission predicate is the type
68
- * reprojection; the value passes through untouched): every consumer
69
- * downstream — `rowOf`, `keyRowOf`, the query param marshal — only READS
70
- * properties, so no copy is warranted.
71
- */
72
44
  function recordOf(fact: object): Readonly<Record<string, unknown>> {
73
45
  if (!isStringIndexed(fact)) {
74
46
  throw errors.new("fact object is not string-indexable")
@@ -76,13 +48,6 @@ function recordOf(fact: object): Readonly<Record<string, unknown>> {
76
48
  return fact
77
49
  }
78
50
 
79
- /**
80
- * The trusted admission seam of {@link recordOf}: every JS object IS
81
- * string-indexable (property reads on absent names yield `undefined`,
82
- * which every consumer already guards), so the predicate verifies the one
83
- * checkable fact — objecthood — and admits the value at the indexed type
84
- * without a copy or a cast.
85
- */
86
51
  function isStringIndexed(value: object): value is Readonly<Record<string, unknown>> {
87
52
  return typeof value === "object" || typeof value === "function"
88
53
  }
@@ -106,14 +71,6 @@ function closedCellOf(context: string, closed: ClosedRoster, name: string): Fact
106
71
  return BigInt(id)
107
72
  }
108
73
 
109
- /**
110
- * The read half of the closed bijection: one u64 row id back to its handle
111
- * NAME (`Number(cell)` is safe — the sealed extension holds at most 256
112
- * rows, engine law). An id outside the roster THROWS pointed, never a
113
- * silent fallback and never `undefined`: the state is reachable only in a
114
- * store whose closed-typed column was never pinned by its containment law,
115
- * and the error names that missing piece.
116
- */
117
74
  function handleOf(context: string, closed: ClosedRoster, cell: FactValue): string {
118
75
  if (typeof cell !== "bigint") {
119
76
  throw literalShapeError(context, `a ${closed.name} handle id (bigint)`, cell)
@@ -127,17 +84,6 @@ function handleOf(context: string, closed: ClosedRoster, cell: FactValue): strin
127
84
  return handle
128
85
  }
129
86
 
130
- /**
131
- * Marshals one host cell at its field position to the natural wire value,
132
- * schema-directed by the field descriptor's structural kind (never
133
- * guessed). A closed-referencing cell arrives as its handle NAME and
134
- * lowers through {@link closedCellOf} — the arm precedes the switch
135
- * because a closed reference is structurally a u64 descriptor plus the
136
- * roster (the same precedence `Infer` pins at the type level). Everything
137
- * else is bare, so the runtime values ARE the wire's natural JS values;
138
- * widths and domain labels are the engine's own judgment at the write
139
- * boundary.
140
- */
141
87
  function cellOf(context: string, field: AnyField, value: unknown): FactValue {
142
88
  const roster = rosterOf(field)
143
89
  if (roster !== undefined) {
@@ -164,13 +110,7 @@ function cellOf(context: string, field: AnyField, value: unknown): FactValue {
164
110
  if (typeof value !== "string") {
165
111
  throw literalShapeError(context, "string", value)
166
112
  }
167
- /**
168
- * A lone surrogate would be lossily replaced with U+FFFD at the
169
- * bridge's UTF-8 crossing — the stored fact would differ from the
170
- * written one, and distinct JS strings would collapse to one fact.
171
- * The bijection law refuses it here, the one seam every write and
172
- * lookup lowers through.
173
- */
113
+
174
114
  if (!value.isWellFormed()) {
175
115
  throw literalShapeError(context, "well-formed string", value)
176
116
  }
@@ -191,11 +131,6 @@ function cellOf(context: string, field: AnyField, value: unknown): FactValue {
191
131
  }
192
132
  }
193
133
 
194
- /**
195
- * Marshals one complete fact object to its positional row, in field
196
- * declaration order (= ordinal ids). Every declared field must be present.
197
- * Mint with `tx.reserve` first; insert takes complete facts.
198
- */
199
134
  function rowOf(relation: RelationData, fact: Readonly<Record<string, unknown>>): FactValue[] {
200
135
  return relation.fields.map(function marshalCell(declared) {
201
136
  const value = fact[declared.name]
@@ -206,12 +141,6 @@ function rowOf(relation: RelationData, fact: Readonly<Record<string, unknown>>):
206
141
  })
207
142
  }
208
143
 
209
- /**
210
- * Marshals a key object through a key statement's projection, in the
211
- * statement's projection order (what the engine's keyed point reads take).
212
- * A key field absent from the object throws naming the primary projection
213
- * (the {@link KeyFact} rule's runtime half).
214
- */
215
144
  function keyRowOf(
216
145
  relation: RelationData,
217
146
  projection: readonly string[],
@@ -234,12 +163,6 @@ function keyRowOf(
234
163
  })
235
164
  }
236
165
 
237
- /**
238
- * The read-side trusted seam: a decoded row carrying every declared field
239
- * IS a fact of its relation — the engine admitted the row, and the values
240
- * are BARE structural values, so nothing is asserted beyond presence (no
241
- * brand exists to re-derive; the store is the proof carrier).
242
- */
243
166
  function isCompleteFact<R extends AnyRelation>(
244
167
  relation: R,
245
168
  decoded: Readonly<Record<string, FactValue>>
@@ -249,13 +172,6 @@ function isCompleteFact<R extends AnyRelation>(
249
172
  })
250
173
  }
251
174
 
252
- /**
253
- * Unmarshals one positional row to the relation's named, frozen fact object
254
- * of bare structural values — the inverse of {@link rowOf},
255
- * ordinal-directed by the same declaration order. Closed-referencing cells
256
- * lift id → handle NAME through {@link handleOf} (the read half of the
257
- * bijection), so every fact a user sees speaks the roster's vocabulary.
258
- */
259
175
  function factOf<R extends AnyRelation>(relation: R, row: readonly FactValue[]): Fact<R> {
260
176
  const data = relation.data
261
177
  if (row.length !== data.fields.length) {