@bjornpagen/bumbledb 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COOKBOOK.md +1450 -0
- package/README.md +69 -30
- package/dist/closed.d.ts +157 -38
- package/dist/closed.d.ts.map +1 -1
- package/dist/closed.js +232 -47
- package/dist/closed.js.map +1 -1
- package/dist/count.d.ts +64 -17
- package/dist/count.d.ts.map +1 -1
- package/dist/count.js +37 -14
- package/dist/count.js.map +1 -1
- package/dist/db.d.ts +27 -8
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +33 -10
- package/dist/db.js.map +1 -1
- package/dist/exhume.d.ts +12 -11
- package/dist/exhume.d.ts.map +1 -1
- package/dist/exhume.js +7 -6
- package/dist/exhume.js.map +1 -1
- package/dist/face.d.ts +135 -30
- package/dist/face.d.ts.map +1 -1
- package/dist/face.js +44 -19
- package/dist/face.js.map +1 -1
- package/dist/fields.d.ts +130 -130
- package/dist/fields.d.ts.map +1 -1
- package/dist/fields.js +60 -94
- package/dist/fields.js.map +1 -1
- package/dist/index.d.ts +29 -24
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -14
- package/dist/index.js.map +1 -1
- package/dist/law.d.ts +224 -0
- package/dist/law.d.ts.map +1 -0
- package/dist/law.js +224 -0
- package/dist/law.js.map +1 -0
- package/dist/lower.d.ts +17 -7
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +66 -24
- package/dist/lower.js.map +1 -1
- package/dist/marshal.d.ts +36 -21
- package/dist/marshal.d.ts.map +1 -1
- package/dist/marshal.js +41 -25
- package/dist/marshal.js.map +1 -1
- package/dist/native.d.ts +6 -2
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js +2 -2
- package/dist/native.js.map +1 -1
- package/dist/query/atom.d.ts +370 -174
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js +75 -172
- package/dist/query/atom.js.map +1 -1
- package/dist/query/lower.d.ts +312 -109
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +906 -387
- package/dist/query/lower.js.map +1 -1
- package/dist/query/predicate.d.ts +70 -88
- package/dist/query/predicate.d.ts.map +1 -1
- package/dist/query/predicate.js +118 -72
- package/dist/query/predicate.js.map +1 -1
- package/dist/query/run.d.ts +19 -16
- package/dist/query/run.d.ts.map +1 -1
- package/dist/query/run.js +31 -24
- package/dist/query/run.js.map +1 -1
- package/dist/query/scope.d.ts +178 -127
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +111 -108
- package/dist/query/scope.js.map +1 -1
- package/dist/query/select.d.ts +102 -80
- package/dist/query/select.d.ts.map +1 -1
- package/dist/query/select.js +39 -34
- package/dist/query/select.js.map +1 -1
- package/dist/relation.d.ts +48 -38
- package/dist/relation.d.ts.map +1 -1
- package/dist/relation.js +24 -19
- package/dist/relation.js.map +1 -1
- package/dist/schema.d.ts +41 -3
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +34 -9
- package/dist/schema.js.map +1 -1
- package/dist/spec.d.ts +7 -5
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js.map +1 -1
- package/dist/statements.d.ts +91 -36
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +42 -12
- package/dist/statements.js.map +1 -1
- package/package.json +4 -3
- package/src/closed.ts +448 -95
- package/src/count.ts +112 -18
- package/src/db.ts +45 -17
- package/src/exhume.ts +12 -11
- package/src/face.ts +211 -41
- package/src/fields.ts +199 -234
- package/src/index.ts +78 -61
- package/src/law.ts +519 -0
- package/src/lower.ts +82 -27
- package/src/marshal.ts +48 -30
- package/src/native.ts +8 -4
- package/src/query/atom.ts +525 -374
- package/src/query/lower.ts +1469 -538
- package/src/query/predicate.ts +208 -161
- package/src/query/run.ts +35 -25
- package/src/query/scope.ts +264 -218
- package/src/query/select.ts +168 -93
- package/src/relation.ts +47 -47
- package/src/schema.ts +69 -18
- package/src/spec.ts +7 -5
- package/src/statements.ts +124 -41
- package/dist/brand.d.ts +0 -59
- package/dist/brand.d.ts.map +0 -1
- package/dist/brand.js +0 -47
- package/dist/brand.js.map +0 -1
- package/src/brand.ts +0 -82
package/src/marshal.ts
CHANGED
|
@@ -1,24 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The marshal layer
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* The marshal layer: fact object ⇄ positional `FactValue[]` by field
|
|
3
|
+
* ordinal, schema-directed, in ONE place only. The write side lowers named
|
|
4
|
+
* host objects to rows in the relation's field-declaration order
|
|
5
5
|
* (declaration order = ordinal ids, the macro's law); the read side decodes
|
|
6
|
-
* rows back to named objects
|
|
7
|
-
* is
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
6
|
+
* rows back to named objects of BARE structural values — the marshal
|
|
7
|
+
* boundary is pure both ways. CAST-FREE, LITERALLY: with structural values
|
|
8
|
+
* there is no brand to assert on the way out (the historical "one
|
|
9
|
+
* sanctioned marshal cast" died with the brand era), so product code
|
|
10
|
+
* carries zero casts — the only trusted seams are the completeness
|
|
11
|
+
* PREDICATES below, which verify the checkable half (every declared field
|
|
12
|
+
* present) and rely on the store as the proof carrier for the rest: a row
|
|
13
|
+
* the engine admitted IS a legal fact of its relation (the same trust
|
|
14
|
+
* direction as Rust's typed readback). Shape mismatches here are genuine
|
|
15
|
+
* failures and THROW typed; they are never domain data.
|
|
11
16
|
*/
|
|
12
17
|
|
|
13
18
|
import * as errors from "@superbuilders/errors"
|
|
14
|
-
import type {
|
|
19
|
+
import type { AnyField } from "#fields.ts"
|
|
15
20
|
import type { FactValue } from "#native.ts"
|
|
16
21
|
import type { AnyRelation, Fact, FreshKeys, RelationData } from "#relation.ts"
|
|
17
22
|
|
|
23
|
+
/**
|
|
24
|
+
* The fresh-mark probe: `true` exactly for a `.fresh`-marked u64 descriptor
|
|
25
|
+
* (the S1 kernel's one structural mark — an unmarked u64's `fresh` property
|
|
26
|
+
* holds the MARKED descriptor, so the probe compares against the literal
|
|
27
|
+
* `true`, never truthiness).
|
|
28
|
+
*/
|
|
29
|
+
function isFreshField(field: AnyField): boolean {
|
|
30
|
+
return "fresh" in field && field.fresh === true
|
|
31
|
+
}
|
|
32
|
+
|
|
18
33
|
/**
|
|
19
34
|
* The inferred object type `tx.insert` returns: one property per
|
|
20
|
-
* fresh-marked field of `R`, carrying the minted (or resupplied)
|
|
21
|
-
*
|
|
35
|
+
* fresh-marked field of `R`, carrying the minted (or resupplied) id as a
|
|
36
|
+
* bare `bigint`. A relation with no fresh field returns the empty object.
|
|
22
37
|
*/
|
|
23
38
|
type Minted<R extends AnyRelation> = { [K in FreshKeys<R>]: Fact<R>[K] }
|
|
24
39
|
|
|
@@ -30,7 +45,8 @@ type Minted<R extends AnyRelation> = { [K in FreshKeys<R>]: Fact<R>[K] }
|
|
|
30
45
|
* relation's primary key is always its fresh field. When `R` carries a
|
|
31
46
|
* fresh field the type demands exactly that field; otherwise the primary
|
|
32
47
|
* key lives in the schema's statement list, which the type system cannot
|
|
33
|
-
* see (
|
|
48
|
+
* see (the schema's statement list is not carried in the schema's type,
|
|
49
|
+
* only in the KeyStatement values themselves), so the type admits any partial fact
|
|
34
50
|
* and the projection is verified at runtime — a missing key field throws
|
|
35
51
|
* naming the projection.
|
|
36
52
|
*/
|
|
@@ -66,12 +82,13 @@ function recordOf(fact: object): Record<string, unknown> {
|
|
|
66
82
|
|
|
67
83
|
/**
|
|
68
84
|
* Marshals one host cell at its field position to the natural wire value,
|
|
69
|
-
* schema-directed by the field's structural
|
|
70
|
-
* are
|
|
71
|
-
* values;
|
|
85
|
+
* schema-directed by the field descriptor's structural kind (never
|
|
86
|
+
* guessed). Values are bare, so the runtime values ARE the wire's natural
|
|
87
|
+
* JS values; widths and domain labels are the engine's own judgment at the
|
|
88
|
+
* write boundary.
|
|
72
89
|
*/
|
|
73
|
-
function cellOf(context: string, field:
|
|
74
|
-
switch (field.
|
|
90
|
+
function cellOf(context: string, field: AnyField, value: unknown): FactValue {
|
|
91
|
+
switch (field.kind) {
|
|
75
92
|
case "bool": {
|
|
76
93
|
if (typeof value !== "boolean") {
|
|
77
94
|
throw cellShapeError(context, "boolean", value)
|
|
@@ -85,7 +102,7 @@ function cellOf(context: string, field: FieldData, value: unknown): FactValue {
|
|
|
85
102
|
}
|
|
86
103
|
return value
|
|
87
104
|
}
|
|
88
|
-
case "
|
|
105
|
+
case "str": {
|
|
89
106
|
if (typeof value !== "string") {
|
|
90
107
|
throw cellShapeError(context, "string", value)
|
|
91
108
|
}
|
|
@@ -101,7 +118,7 @@ function cellOf(context: string, field: FieldData, value: unknown): FactValue {
|
|
|
101
118
|
}
|
|
102
119
|
return value
|
|
103
120
|
}
|
|
104
|
-
case "
|
|
121
|
+
case "bytes": {
|
|
105
122
|
if (!(value instanceof Uint8Array)) {
|
|
106
123
|
throw cellShapeError(context, "Uint8Array", value)
|
|
107
124
|
}
|
|
@@ -162,11 +179,11 @@ function keyRowOf(
|
|
|
162
179
|
|
|
163
180
|
/**
|
|
164
181
|
* The read-side trusted seam: a decoded row carrying every declared field
|
|
165
|
-
* IS a fact of its relation — the engine admitted
|
|
166
|
-
*
|
|
167
|
-
*
|
|
182
|
+
* IS a fact of its relation — the engine admitted the row, and the values
|
|
183
|
+
* are BARE structural values, so nothing is asserted beyond presence (no
|
|
184
|
+
* brand exists to re-derive; the store is the proof carrier).
|
|
168
185
|
*/
|
|
169
|
-
function
|
|
186
|
+
function isCompleteFact<R extends AnyRelation>(
|
|
170
187
|
relation: R,
|
|
171
188
|
decoded: Readonly<Record<string, FactValue>>
|
|
172
189
|
): decoded is Readonly<Record<string, FactValue>> & Fact<R> {
|
|
@@ -178,21 +195,22 @@ function isBrandedFact<R extends AnyRelation>(
|
|
|
178
195
|
/**
|
|
179
196
|
* The insert-return trusted seam: the collected fresh cells of one insert
|
|
180
197
|
* (minted by the engine or resupplied by the caller) are the relation's
|
|
181
|
-
*
|
|
198
|
+
* fresh ids as bare bigints — same presence-only direction as
|
|
199
|
+
* {@link isCompleteFact}.
|
|
182
200
|
*/
|
|
183
201
|
function isMintedFresh<R extends AnyRelation>(
|
|
184
202
|
relation: R,
|
|
185
203
|
minted: Readonly<Record<string, FactValue>>
|
|
186
204
|
): minted is Readonly<Record<string, FactValue>> & Minted<R> {
|
|
187
205
|
return relation.data.fields.every(function presentWhenFresh(declared) {
|
|
188
|
-
return !declared.field
|
|
206
|
+
return !isFreshField(declared.field) || minted[declared.name] !== undefined
|
|
189
207
|
})
|
|
190
208
|
}
|
|
191
209
|
|
|
192
210
|
/**
|
|
193
|
-
* Unmarshals one positional row to the relation's named,
|
|
194
|
-
*
|
|
195
|
-
* declaration order.
|
|
211
|
+
* Unmarshals one positional row to the relation's named, frozen fact object
|
|
212
|
+
* of bare structural values — the inverse of {@link rowOf},
|
|
213
|
+
* ordinal-directed by the same declaration order.
|
|
196
214
|
*/
|
|
197
215
|
function factOf<R extends AnyRelation>(relation: R, row: readonly FactValue[]): Fact<R> {
|
|
198
216
|
const data = relation.data
|
|
@@ -210,11 +228,11 @@ function factOf<R extends AnyRelation>(relation: R, row: readonly FactValue[]):
|
|
|
210
228
|
decoded[declared.name] = cell
|
|
211
229
|
})
|
|
212
230
|
Object.freeze(decoded)
|
|
213
|
-
if (!
|
|
231
|
+
if (!isCompleteFact(relation, decoded)) {
|
|
214
232
|
throw errors.new(`relation ${data.name}: decoded row is not a complete fact`)
|
|
215
233
|
}
|
|
216
234
|
return decoded
|
|
217
235
|
}
|
|
218
236
|
|
|
219
237
|
export type { KeyFact, Minted }
|
|
220
|
-
export { cellOf, factOf, isMintedFresh, keyRowOf, recordOf, rowOf }
|
|
238
|
+
export { cellOf, factOf, isFreshField, isMintedFresh, keyRowOf, recordOf, rowOf }
|
package/src/native.ts
CHANGED
|
@@ -244,13 +244,17 @@ interface Violation {
|
|
|
244
244
|
* `dbCreate`/`dbOpen`'s domain outcome. `schemaError` covers both spec
|
|
245
245
|
* resolution (unresolvable names, banned spellings — every issue in one
|
|
246
246
|
* message) and schema validation at the declaration boundary;
|
|
247
|
-
* `
|
|
247
|
+
* `newtypeMismatch` is the coherence wall's own kind — a spec whose
|
|
248
|
+
* statement pairs faces with disagreeing newtype labels (the engine twin
|
|
249
|
+
* of the schema-level class wall; unreachable through the typed builder,
|
|
250
|
+
* which computes every label from the laws, so only a raw spec can reach
|
|
251
|
+
* it); `fingerprintMismatch` is `dbOpen`'s stored-theory refusal.
|
|
248
252
|
*/
|
|
249
253
|
type DbOpenResult =
|
|
250
254
|
| { readonly ok: true; readonly db: DbHandle }
|
|
251
255
|
| {
|
|
252
256
|
readonly ok: false
|
|
253
|
-
readonly kind: "schemaError" | "fingerprintMismatch"
|
|
257
|
+
readonly kind: "schemaError" | "newtypeMismatch" | "fingerprintMismatch"
|
|
254
258
|
readonly message: string
|
|
255
259
|
}
|
|
256
260
|
|
|
@@ -479,8 +483,8 @@ const SHIPPED_PLATFORMS = "darwin-arm64"
|
|
|
479
483
|
* It resolves the per-platform binary package by name (see
|
|
480
484
|
* {@link loadNativeBinding}); the addon never crosses as a relative path.
|
|
481
485
|
* createRequire is the only unflagged Node-API addon loader in ESM, and this
|
|
482
|
-
* file is the package's single sanctioned FFI boundary
|
|
483
|
-
*
|
|
486
|
+
* file is the package's single sanctioned FFI boundary (the arch-split
|
|
487
|
+
* packaging ruling).
|
|
484
488
|
*/
|
|
485
489
|
const requireNative = createRequire(import.meta.url)
|
|
486
490
|
|