@bjornpagen/bumbledb 0.1.0 → 0.2.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 +1394 -0
- package/README.md +4 -0
- package/dist/closed.d.ts +60 -37
- package/dist/closed.d.ts.map +1 -1
- package/dist/closed.js +159 -40
- 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 +15 -7
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +13 -5
- 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 +79 -19
- package/dist/face.d.ts.map +1 -1
- package/dist/face.js +14 -15
- package/dist/face.js.map +1 -1
- package/dist/fields.d.ts +158 -129
- package/dist/fields.d.ts.map +1 -1
- package/dist/fields.js +80 -81
- package/dist/fields.js.map +1 -1
- package/dist/index.d.ts +21 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -12
- package/dist/index.js.map +1 -1
- package/dist/lower.d.ts +6 -3
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +48 -17
- 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.js +2 -2
- package/dist/query/atom.d.ts +332 -174
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js +72 -172
- package/dist/query/atom.js.map +1 -1
- package/dist/query/lower.d.ts +295 -107
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +860 -388
- package/dist/query/lower.js.map +1 -1
- package/dist/query/predicate.d.ts +69 -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 +139 -123
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +71 -115
- 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 +33 -36
- package/dist/relation.d.ts.map +1 -1
- package/dist/relation.js +15 -16
- package/dist/relation.js.map +1 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +19 -8
- package/dist/schema.js.map +1 -1
- package/dist/spec.d.ts +6 -5
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js.map +1 -1
- package/dist/statements.d.ts +56 -31
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +38 -13
- package/dist/statements.js.map +1 -1
- package/package.json +4 -3
- package/src/closed.ts +271 -93
- package/src/count.ts +112 -18
- package/src/db.ts +22 -12
- package/src/exhume.ts +12 -11
- package/src/face.ts +114 -22
- package/src/fields.ts +261 -217
- package/src/index.ts +50 -59
- package/src/lower.ts +62 -20
- package/src/marshal.ts +48 -30
- package/src/native.ts +2 -2
- package/src/query/atom.ts +480 -376
- package/src/query/lower.ts +1341 -542
- package/src/query/predicate.ts +198 -161
- package/src/query/run.ts +35 -25
- package/src/query/scope.ts +188 -218
- package/src/query/select.ts +168 -93
- package/src/relation.ts +38 -44
- package/src/schema.ts +22 -12
- package/src/spec.ts +6 -5
- package/src/statements.ts +69 -26
- 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/index.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @bjornpagen/bumbledb — the type-theoretic TypeScript SDK for the
|
|
3
|
-
* bumbledb embedded relational engine. Public surface: the type
|
|
4
|
-
* (
|
|
3
|
+
* bumbledb embedded relational engine. Public surface: the structural type
|
|
4
|
+
* kernel (fields with schema-level domain labels, `relation()`,
|
|
5
|
+
* `closed()`), the statement
|
|
5
6
|
* algebra with `schema()` and `SchemaSpec` lowering (PRD-06), the `Db`
|
|
6
7
|
* runtime (path-cached stores, transactions, typed violations, scoped
|
|
7
8
|
* snapshot reads, the witnessed write loop with `abandon` — PRD-07, zero
|
|
8
|
-
* closables), the query surface (Datalog as values:
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* closables), the query surface (Datalog as values, kysely-shaped:
|
|
10
|
+
* `query(S).rule(r => r.match(...).where(...).select(...))` with
|
|
11
|
+
* string-named domain-typed vars, params typed by use, negation,
|
|
12
|
+
* conditions, aggregates, and stratified recursion via `program()`/`rec` —
|
|
13
|
+
* `db.prepare` as a plain value), and the exhume surface
|
|
11
14
|
* (`Db.exhume` — the one schema-independent read path: the store's
|
|
12
|
-
* self-described shapes and raw facts by name,
|
|
13
|
-
*
|
|
14
|
-
* PRD-03 stub died here as scheduled).
|
|
15
|
+
* self-described shapes and raw facts by name, typed at bare structural
|
|
16
|
+
* values, deliberately schema-free). The raw native bridge is not exported.
|
|
15
17
|
*/
|
|
16
18
|
|
|
17
|
-
export type { Brand, Interval, IntervalValue } from "#brand.ts"
|
|
18
|
-
export { span } from "#brand.ts"
|
|
19
19
|
export type {
|
|
20
20
|
AnyClosed,
|
|
21
21
|
AxiomRow,
|
|
@@ -63,34 +63,35 @@ export type {
|
|
|
63
63
|
Face,
|
|
64
64
|
FaceArityMismatch,
|
|
65
65
|
FaceData,
|
|
66
|
+
FaceDomainMismatch,
|
|
67
|
+
FaceDomains,
|
|
66
68
|
FaceFields,
|
|
67
69
|
FaceOwner,
|
|
68
70
|
FaceSource,
|
|
69
71
|
OneOf,
|
|
70
|
-
SameArity
|
|
72
|
+
SameArity,
|
|
73
|
+
SameDomains
|
|
71
74
|
} from "#face.ts"
|
|
72
75
|
export { on, oneOf } from "#face.ts"
|
|
73
76
|
export type {
|
|
74
77
|
AnyField,
|
|
75
78
|
BoolField,
|
|
79
|
+
BytesCtor,
|
|
76
80
|
BytesField,
|
|
77
|
-
BytesNewtype,
|
|
78
81
|
ClosedIdField,
|
|
79
82
|
ClosedRoster,
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
FieldValue,
|
|
83
|
-
FreshU64Newtype,
|
|
83
|
+
FreshU64Field,
|
|
84
|
+
I64Ctor,
|
|
84
85
|
I64Field,
|
|
85
|
-
I64Newtype,
|
|
86
86
|
Infer,
|
|
87
|
+
IntervalCtor,
|
|
87
88
|
IntervalField,
|
|
88
|
-
|
|
89
|
+
IntervalValue,
|
|
89
90
|
StrField,
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
U64Ctor,
|
|
92
|
+
U64Field
|
|
92
93
|
} from "#fields.ts"
|
|
93
|
-
export { bool, bytes, i64, interval, str, u64 } from "#fields.ts"
|
|
94
|
+
export { bool, bytes, i64, interval, span, str, u64 } from "#fields.ts"
|
|
94
95
|
export { lower, lowerClosed, lowerRelation } from "#lower.ts"
|
|
95
96
|
export type { KeyFact, Minted } from "#marshal.ts"
|
|
96
97
|
export type {
|
|
@@ -102,51 +103,41 @@ export type {
|
|
|
102
103
|
} from "#native.ts"
|
|
103
104
|
|
|
104
105
|
export type {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
106
|
+
AnyCond,
|
|
107
|
+
BindingInput,
|
|
108
|
+
Cmp,
|
|
109
|
+
MatchShape,
|
|
110
|
+
NotAtom,
|
|
111
|
+
RecData,
|
|
112
|
+
RuleData,
|
|
113
|
+
SelectColumn,
|
|
114
|
+
Tree
|
|
113
115
|
} from "#query/atom.ts"
|
|
114
|
-
|
|
115
|
-
export {
|
|
116
|
-
ALLEN,
|
|
117
|
-
allen,
|
|
118
|
-
and,
|
|
119
|
-
covers,
|
|
120
|
-
duration,
|
|
121
|
-
ge,
|
|
122
|
-
gt,
|
|
123
|
-
is,
|
|
124
|
-
le,
|
|
125
|
-
lt,
|
|
126
|
-
match,
|
|
127
|
-
ne,
|
|
128
|
-
not,
|
|
129
|
-
or
|
|
130
|
-
} from "#query/atom.ts"
|
|
131
|
-
|
|
116
|
+
export { ALLEN } from "#query/atom.ts"
|
|
132
117
|
export type {
|
|
133
118
|
AnyQuery,
|
|
119
|
+
AnyRuleValue,
|
|
120
|
+
OutputRuleChain,
|
|
121
|
+
OutputRuleScope,
|
|
134
122
|
Query,
|
|
135
|
-
|
|
123
|
+
QueryData,
|
|
136
124
|
QueryParams,
|
|
125
|
+
QueryRelation,
|
|
137
126
|
QueryRow,
|
|
138
|
-
|
|
127
|
+
QueryRuleChain,
|
|
128
|
+
QueryRuleScope,
|
|
129
|
+
QueryStart,
|
|
130
|
+
RecRef,
|
|
131
|
+
RecRuleChain,
|
|
132
|
+
RecRuleScope,
|
|
133
|
+
RuleValue,
|
|
134
|
+
TermOps
|
|
139
135
|
} from "#query/lower.ts"
|
|
140
136
|
export { lowerQuery, query } from "#query/lower.ts"
|
|
141
|
-
export type {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
PredicateSelf
|
|
146
|
-
} from "#query/predicate.ts"
|
|
147
|
-
export type { MaskParam, Param, ParamSet, ParamsRecord, Var } from "#query/scope.ts"
|
|
148
|
-
export type { Aggregate, RowOf, SelectShape } from "#query/select.ts"
|
|
149
|
-
export { argmax, argmin, count, countDistinct, max, min, pack, sum } from "#query/select.ts"
|
|
137
|
+
export type { ProgramScope, Rec } from "#query/predicate.ts"
|
|
138
|
+
export { program } from "#query/predicate.ts"
|
|
139
|
+
export type { Duration, MaskParam, Param, ParamEntry, ParamsRecord, SetParam, Var } from "#query/scope.ts"
|
|
140
|
+
export type { Agg, SelectEntry } from "#query/select.ts"
|
|
150
141
|
export type {
|
|
151
142
|
AnyRelation,
|
|
152
143
|
AnySelected,
|
|
@@ -181,5 +172,5 @@ export type {
|
|
|
181
172
|
WindowSpec
|
|
182
173
|
} from "#spec.ts"
|
|
183
174
|
export { renderLiteral, renderLiteralSet, renderWindow } from "#spec.ts"
|
|
184
|
-
export type { KeyStatement, Statement, StatementData } from "#statements.ts"
|
|
175
|
+
export type { KeyData, KeyStatement, Statement, StatementData } from "#statements.ts"
|
|
185
176
|
export { contained, key, mirrors, renderStatement, window } from "#statements.ts"
|
package/src/lower.ts
CHANGED
|
@@ -10,9 +10,18 @@
|
|
|
10
10
|
|
|
11
11
|
import type { AnyClosed } from "#closed.ts"
|
|
12
12
|
import type { FaceData } from "#face.ts"
|
|
13
|
+
import type { AnyField } from "#fields.ts"
|
|
13
14
|
import type { AnyRelation } from "#relation.ts"
|
|
14
15
|
import type { AnySchema, SchemaRelation } from "#schema.ts"
|
|
15
|
-
import type {
|
|
16
|
+
import type {
|
|
17
|
+
FieldSpec,
|
|
18
|
+
LiteralSetSpec,
|
|
19
|
+
RelationSpec,
|
|
20
|
+
SchemaSpec,
|
|
21
|
+
SideSpec,
|
|
22
|
+
StatementSpec,
|
|
23
|
+
ValueTypeSpec
|
|
24
|
+
} from "#spec.ts"
|
|
16
25
|
import type { Statement } from "#statements.ts"
|
|
17
26
|
|
|
18
27
|
/**
|
|
@@ -23,13 +32,53 @@ function isClosedMember(member: SchemaRelation): member is AnyClosed {
|
|
|
23
32
|
return "handles" in member.data
|
|
24
33
|
}
|
|
25
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Lowers one field descriptor's structural type to the wire
|
|
37
|
+
* {@link ValueTypeSpec}: the S1 kind tags map 1:1 onto the `ValueType`
|
|
38
|
+
* vocabulary (`str` spells `string`, `bytes` spells `fixedBytes` with its
|
|
39
|
+
* width label as `len`; intervals carry element and width labels through).
|
|
40
|
+
*/
|
|
41
|
+
function valueTypeOf(field: AnyField): ValueTypeSpec {
|
|
42
|
+
switch (field.kind) {
|
|
43
|
+
case "bool":
|
|
44
|
+
return { kind: "bool" }
|
|
45
|
+
case "u64":
|
|
46
|
+
return { kind: "u64" }
|
|
47
|
+
case "i64":
|
|
48
|
+
return { kind: "i64" }
|
|
49
|
+
case "str":
|
|
50
|
+
return { kind: "string" }
|
|
51
|
+
case "bytes":
|
|
52
|
+
return { kind: "fixedBytes", len: field.width }
|
|
53
|
+
case "interval":
|
|
54
|
+
return { kind: "interval", element: field.element, width: field.width }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Lowers one field descriptor to its {@link FieldSpec}: the structural
|
|
60
|
+
* type, the DOMAIN label as the wire's `newtype` (the macro's `as NewType`
|
|
61
|
+
* name — carried for engine handle resolution, dropped at descriptor
|
|
62
|
+
* lowering, never fingerprinted), and the structural fresh mark (`fresh`
|
|
63
|
+
* is the literal `true` exactly on a fresh-marked u64 — on an unmarked one
|
|
64
|
+
* the property holds the marked descriptor, never `true`).
|
|
65
|
+
*/
|
|
66
|
+
function lowerField(name: string, field: AnyField): FieldSpec {
|
|
67
|
+
return {
|
|
68
|
+
name,
|
|
69
|
+
valueType: valueTypeOf(field),
|
|
70
|
+
newtype: field.domain,
|
|
71
|
+
fresh: "fresh" in field && field.fresh === true
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
26
75
|
/** Lowers one face to a `SideSpec`: names only, σ as (field, set) pairs. */
|
|
27
76
|
function lowerFace(face: FaceData): SideSpec {
|
|
28
77
|
return {
|
|
29
78
|
relation: face.owner.name,
|
|
30
79
|
projection: [...face.projection],
|
|
31
|
-
selection: face.selection.map(function lowerBinding(binding) {
|
|
32
|
-
return [binding.field, binding.set]
|
|
80
|
+
selection: face.selection.map(function lowerBinding(binding): readonly [string, LiteralSetSpec] {
|
|
81
|
+
return [binding.field, binding.set]
|
|
33
82
|
})
|
|
34
83
|
}
|
|
35
84
|
}
|
|
@@ -67,13 +116,8 @@ function lowerStatement(statement: Statement): StatementSpec {
|
|
|
67
116
|
* declaration order, `extension: undefined` (the option is the kind).
|
|
68
117
|
*/
|
|
69
118
|
function lowerRelation(relation: AnyRelation): RelationSpec {
|
|
70
|
-
const fields: FieldSpec[] = relation.data.fields.map(function
|
|
71
|
-
return
|
|
72
|
-
name: declared.name,
|
|
73
|
-
valueType: declared.field.type,
|
|
74
|
-
newtype: declared.field.newtype,
|
|
75
|
-
fresh: declared.field.minted
|
|
76
|
-
}
|
|
119
|
+
const fields: FieldSpec[] = relation.data.fields.map(function lowerDeclared(declared) {
|
|
120
|
+
return lowerField(declared.name, declared.field)
|
|
77
121
|
})
|
|
78
122
|
return { name: relation.name, newtype: undefined, fields, extension: undefined }
|
|
79
123
|
}
|
|
@@ -81,23 +125,21 @@ function lowerRelation(relation: AnyRelation): RelationSpec {
|
|
|
81
125
|
/**
|
|
82
126
|
* Lowers one closed relation to its `RelationSpec` fragment: declared
|
|
83
127
|
* intrinsic columns only (the engine materializes the synthetic `id`),
|
|
84
|
-
* the
|
|
85
|
-
*
|
|
86
|
-
*
|
|
128
|
+
* the HANDLE DOMAIN as its handle newtype — the `id` descriptor's own
|
|
129
|
+
* `` `${name}Id` `` label (Rust's `closed relation Kind as KindId`), the
|
|
130
|
+
* same string every referencing field carries, which is exactly how the
|
|
131
|
+
* engine resolves a handle literal back to its roster — and the ground
|
|
132
|
+
* axioms in declaration order (row id = index); the literals were already
|
|
133
|
+
* lowered at `closed()` construction.
|
|
87
134
|
*/
|
|
88
135
|
function lowerClosed(member: AnyClosed): RelationSpec {
|
|
89
136
|
const fields: FieldSpec[] = member.data.columns.map(function lowerColumn(column) {
|
|
90
|
-
return
|
|
91
|
-
name: column.name,
|
|
92
|
-
valueType: column.field.type,
|
|
93
|
-
newtype: column.field.newtype,
|
|
94
|
-
fresh: false
|
|
95
|
-
}
|
|
137
|
+
return lowerField(column.name, column.field)
|
|
96
138
|
})
|
|
97
139
|
const extension = member.data.rows.map(function lowerRow(row) {
|
|
98
140
|
return { handle: row.handle, values: row.values }
|
|
99
141
|
})
|
|
100
|
-
return { name: member.name, newtype: member.
|
|
142
|
+
return { name: member.name, newtype: member.id.domain, fields, extension }
|
|
101
143
|
}
|
|
102
144
|
|
|
103
145
|
/**
|
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
|
@@ -479,8 +479,8 @@ const SHIPPED_PLATFORMS = "darwin-arm64"
|
|
|
479
479
|
* It resolves the per-platform binary package by name (see
|
|
480
480
|
* {@link loadNativeBinding}); the addon never crosses as a relative path.
|
|
481
481
|
* createRequire is the only unflagged Node-API addon loader in ESM, and this
|
|
482
|
-
* file is the package's single sanctioned FFI boundary
|
|
483
|
-
*
|
|
482
|
+
* file is the package's single sanctioned FFI boundary (the arch-split
|
|
483
|
+
* packaging ruling).
|
|
484
484
|
*/
|
|
485
485
|
const requireNative = createRequire(import.meta.url)
|
|
486
486
|
|