@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.
Files changed (103) hide show
  1. package/COOKBOOK.md +1394 -0
  2. package/README.md +4 -0
  3. package/dist/closed.d.ts +60 -37
  4. package/dist/closed.d.ts.map +1 -1
  5. package/dist/closed.js +159 -40
  6. package/dist/closed.js.map +1 -1
  7. package/dist/count.d.ts +64 -17
  8. package/dist/count.d.ts.map +1 -1
  9. package/dist/count.js +37 -14
  10. package/dist/count.js.map +1 -1
  11. package/dist/db.d.ts +15 -7
  12. package/dist/db.d.ts.map +1 -1
  13. package/dist/db.js +13 -5
  14. package/dist/db.js.map +1 -1
  15. package/dist/exhume.d.ts +12 -11
  16. package/dist/exhume.d.ts.map +1 -1
  17. package/dist/exhume.js +7 -6
  18. package/dist/exhume.js.map +1 -1
  19. package/dist/face.d.ts +79 -19
  20. package/dist/face.d.ts.map +1 -1
  21. package/dist/face.js +14 -15
  22. package/dist/face.js.map +1 -1
  23. package/dist/fields.d.ts +158 -129
  24. package/dist/fields.d.ts.map +1 -1
  25. package/dist/fields.js +80 -81
  26. package/dist/fields.js.map +1 -1
  27. package/dist/index.d.ts +21 -21
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +13 -12
  30. package/dist/index.js.map +1 -1
  31. package/dist/lower.d.ts +6 -3
  32. package/dist/lower.d.ts.map +1 -1
  33. package/dist/lower.js +48 -17
  34. package/dist/lower.js.map +1 -1
  35. package/dist/marshal.d.ts +36 -21
  36. package/dist/marshal.d.ts.map +1 -1
  37. package/dist/marshal.js +41 -25
  38. package/dist/marshal.js.map +1 -1
  39. package/dist/native.js +2 -2
  40. package/dist/query/atom.d.ts +332 -174
  41. package/dist/query/atom.d.ts.map +1 -1
  42. package/dist/query/atom.js +72 -172
  43. package/dist/query/atom.js.map +1 -1
  44. package/dist/query/lower.d.ts +295 -107
  45. package/dist/query/lower.d.ts.map +1 -1
  46. package/dist/query/lower.js +860 -388
  47. package/dist/query/lower.js.map +1 -1
  48. package/dist/query/predicate.d.ts +69 -88
  49. package/dist/query/predicate.d.ts.map +1 -1
  50. package/dist/query/predicate.js +118 -72
  51. package/dist/query/predicate.js.map +1 -1
  52. package/dist/query/run.d.ts +19 -16
  53. package/dist/query/run.d.ts.map +1 -1
  54. package/dist/query/run.js +31 -24
  55. package/dist/query/run.js.map +1 -1
  56. package/dist/query/scope.d.ts +139 -123
  57. package/dist/query/scope.d.ts.map +1 -1
  58. package/dist/query/scope.js +71 -115
  59. package/dist/query/scope.js.map +1 -1
  60. package/dist/query/select.d.ts +102 -80
  61. package/dist/query/select.d.ts.map +1 -1
  62. package/dist/query/select.js +39 -34
  63. package/dist/query/select.js.map +1 -1
  64. package/dist/relation.d.ts +33 -36
  65. package/dist/relation.d.ts.map +1 -1
  66. package/dist/relation.js +15 -16
  67. package/dist/relation.js.map +1 -1
  68. package/dist/schema.d.ts.map +1 -1
  69. package/dist/schema.js +19 -8
  70. package/dist/schema.js.map +1 -1
  71. package/dist/spec.d.ts +6 -5
  72. package/dist/spec.d.ts.map +1 -1
  73. package/dist/spec.js.map +1 -1
  74. package/dist/statements.d.ts +56 -31
  75. package/dist/statements.d.ts.map +1 -1
  76. package/dist/statements.js +38 -13
  77. package/dist/statements.js.map +1 -1
  78. package/package.json +4 -3
  79. package/src/closed.ts +271 -93
  80. package/src/count.ts +112 -18
  81. package/src/db.ts +22 -12
  82. package/src/exhume.ts +12 -11
  83. package/src/face.ts +114 -22
  84. package/src/fields.ts +261 -217
  85. package/src/index.ts +50 -59
  86. package/src/lower.ts +62 -20
  87. package/src/marshal.ts +48 -30
  88. package/src/native.ts +2 -2
  89. package/src/query/atom.ts +480 -376
  90. package/src/query/lower.ts +1341 -542
  91. package/src/query/predicate.ts +198 -161
  92. package/src/query/run.ts +35 -25
  93. package/src/query/scope.ts +188 -218
  94. package/src/query/select.ts +168 -93
  95. package/src/relation.ts +38 -44
  96. package/src/schema.ts +22 -12
  97. package/src/spec.ts +6 -5
  98. package/src/statements.ts +69 -26
  99. package/dist/brand.d.ts +0 -59
  100. package/dist/brand.d.ts.map +0 -1
  101. package/dist/brand.js +0 -47
  102. package/dist/brand.js.map +0 -1
  103. 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 kernel
4
- * (brands, fields, `relation()`, `closed()` — PRD-05), the statement
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: scoped vars/params,
9
- * atoms, negation, conditions, aggregates, engine recursion via predicates,
10
- * `db.prepare` as a plain value PRD-08), and the exhume surface
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, deliberately untyped
13
- * course-serialization PRD-02). The raw native bridge is not exported (the
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
- Field,
81
- FieldData,
82
- FieldValue,
83
- FreshU64Newtype,
83
+ FreshU64Field,
84
+ I64Ctor,
84
85
  I64Field,
85
- I64Newtype,
86
86
  Infer,
87
+ IntervalCtor,
87
88
  IntervalField,
88
- IntervalNewtype,
89
+ IntervalValue,
89
90
  StrField,
90
- U64Field,
91
- U64Newtype
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
- AnyBodyItem,
106
- AnyCondition,
107
- ComparisonItem,
108
- ConditionTreeItem,
109
- Duration,
110
- MatchAtom,
111
- MatchInput,
112
- TermInput
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
- QueryBuild,
123
+ QueryData,
136
124
  QueryParams,
125
+ QueryRelation,
137
126
  QueryRow,
138
- Scope
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
- Predicate,
143
- PredicateBindings,
144
- PredicateRuleInput,
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 { FieldSpec, RelationSpec, SchemaSpec, SideSpec, StatementSpec } from "#spec.ts"
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] as const
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 lowerField(declared) {
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 relation's own name as its handle newtype, and the ground axioms in
85
- * declaration order (row id = index) the literals were already lowered
86
- * at `closed()` construction.
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.name, fields, extension }
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 (PRD-07): fact object ⇄ positional `FactValue[]` by
3
- * field ordinal, schema-directed, in ONE place only. The write side lowers
4
- * named host objects to rows in the relation's field-declaration order
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 with brands applied by assertion — the store
7
- * is the proof carrier: a row the engine admitted IS a legal fact of its
8
- * relation, so readback asserts the brand instead of re-judging the value
9
- * (the same trust direction as Rust's typed readback). Shape mismatches
10
- * here are genuine failures and THROW typed; they are never domain data.
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 { FieldData } from "#fields.ts"
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) branded
21
- * id. A relation with no fresh field returns the empty object.
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 (statements are untyped values), so the type admits any partial fact
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 type (never guessed). Brands
70
- * are phantoms, so the runtime values are exactly the wire's natural JS
71
- * values; only widths and domains are left to the engine's own judge.
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: FieldData, value: unknown): FactValue {
74
- switch (field.type.kind) {
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 "string": {
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 "fixedBytes": {
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 it, so the brand is
166
- * asserted, not re-derived. The checkable half (completeness) is verified;
167
- * the phantom half (brands) is carried by the store's own judgment.
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 isBrandedFact<R extends AnyRelation>(
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
- * branded fresh ids — same assertion direction as {@link isBrandedFact}.
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.minted || minted[declared.name] !== undefined
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, branded, frozen
194
- * fact object — the inverse of {@link rowOf}, ordinal-directed by the same
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 (!isBrandedFact(relation, decoded)) {
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
- * (docs/road-to-1.0.0/prd-03-arch-split-packaging.md).
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