@bjornpagen/bumbledb 0.3.0 → 0.5.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 +246 -92
- package/README.md +31 -16
- package/dist/closed.d.ts +80 -75
- package/dist/closed.d.ts.map +1 -1
- package/dist/closed.js +102 -127
- package/dist/closed.js.map +1 -1
- package/dist/db.d.ts +37 -7
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +95 -55
- package/dist/db.js.map +1 -1
- package/dist/exhume.d.ts.map +1 -1
- package/dist/exhume.js +1 -14
- package/dist/exhume.js.map +1 -1
- package/dist/face.d.ts +40 -40
- package/dist/face.d.ts.map +1 -1
- package/dist/face.js +9 -17
- package/dist/face.js.map +1 -1
- package/dist/fields.d.ts +46 -15
- package/dist/fields.d.ts.map +1 -1
- package/dist/fields.js +58 -29
- package/dist/fields.js.map +1 -1
- package/dist/index.d.ts +13 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -5
- package/dist/index.js.map +1 -1
- package/dist/law.d.ts +2 -1
- package/dist/law.d.ts.map +1 -1
- package/dist/law.js +15 -14
- package/dist/law.js.map +1 -1
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +1 -7
- package/dist/lower.js.map +1 -1
- package/dist/marshal.d.ts +33 -6
- package/dist/marshal.d.ts.map +1 -1
- package/dist/marshal.js +75 -26
- package/dist/marshal.js.map +1 -1
- package/dist/native.d.ts +21 -2
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js +20 -3
- package/dist/native.js.map +1 -1
- package/dist/order.d.ts +36 -0
- package/dist/order.d.ts.map +1 -0
- package/dist/order.js +135 -0
- package/dist/order.js.map +1 -0
- package/dist/query/atom.d.ts +76 -28
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js +12 -16
- package/dist/query/atom.js.map +1 -1
- package/dist/query/lower.d.ts +5 -8
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +308 -72
- package/dist/query/lower.js.map +1 -1
- package/dist/query/predicate.d.ts.map +1 -1
- package/dist/query/predicate.js +34 -2
- package/dist/query/predicate.js.map +1 -1
- package/dist/query/run.d.ts +15 -5
- package/dist/query/run.d.ts.map +1 -1
- package/dist/query/run.js +27 -8
- package/dist/query/run.js.map +1 -1
- package/dist/query/scope.d.ts +37 -29
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +19 -47
- package/dist/query/scope.js.map +1 -1
- package/dist/relation.d.ts +17 -29
- package/dist/relation.d.ts.map +1 -1
- package/dist/relation.js +41 -38
- package/dist/relation.js.map +1 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +7 -31
- package/dist/schema.js.map +1 -1
- package/dist/spec.d.ts +3 -2
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js.map +1 -1
- package/dist/statements.d.ts +13 -4
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +75 -8
- package/dist/statements.js.map +1 -1
- package/package.json +2 -5
- package/src/closed.ts +144 -206
- package/src/db.ts +143 -68
- package/src/exhume.ts +1 -15
- package/src/face.ts +38 -48
- package/src/fields.ts +103 -49
- package/src/index.ts +11 -10
- package/src/law.ts +15 -14
- package/src/lower.ts +2 -9
- package/src/marshal.ts +82 -31
- package/src/native.ts +22 -4
- package/src/order.ts +156 -0
- package/src/query/atom.ts +70 -35
- package/src/query/lower.ts +354 -82
- package/src/query/predicate.ts +39 -4
- package/src/query/run.ts +27 -9
- package/src/query/scope.ts +52 -70
- package/src/relation.ts +54 -68
- package/src/schema.ts +7 -33
- package/src/spec.ts +3 -2
- package/src/statements.ts +82 -8
package/src/statements.ts
CHANGED
|
@@ -8,10 +8,19 @@
|
|
|
8
8
|
* Every field reference is checked against the relation it names in the
|
|
9
9
|
* TYPE — existence through {@link FaceFields} (`on(R, "nope")` does not
|
|
10
10
|
* compile) and STRUCTURAL compatibility through {@link SameShapes}: the two
|
|
11
|
-
* faces' projected kind/width/element
|
|
12
|
-
* (the minimal kernel — descriptors are pure structure) and
|
|
13
|
-
* positionwise equal, so a u64 face against a str face, a
|
|
14
|
-
* mismatch,
|
|
11
|
+
* faces' projected kind/width/element/roster quadruples are read off the
|
|
12
|
+
* schema type (the minimal kernel — descriptors are pure structure) and
|
|
13
|
+
* constrained positionwise equal, so a u64 face against a str face, a
|
|
14
|
+
* bytes width mismatch, an interval element mismatch, or a bare column
|
|
15
|
+
* against a closed reference is a compile error. TWO of those walls carry
|
|
16
|
+
* construction-time runtime twins here for untyped callers: ARITY
|
|
17
|
+
* ({@link assertArityAgreement} — cleanup-0.5.0 ruling 9: an
|
|
18
|
+
* arity-mismatched pairing fails at the statement, never by silent
|
|
19
|
+
* truncation) and the ROSTER slot ({@link assertRosterAgreement} —
|
|
20
|
+
* roster IDENTITY, positionwise: a closed vocabulary's referencing column
|
|
21
|
+
* is spelled with the vocabulary's own id descriptor, the ONE spelling, so
|
|
22
|
+
* a plain u64 column can never alias a vocabulary through a declared law
|
|
23
|
+
* and the SDK's descriptor-keyed closed judgments stay sound). Domains are
|
|
15
24
|
* NOT compared here — there is no domain to compare at construction: the
|
|
16
25
|
* statements themselves are what define the equivalence classes, and the
|
|
17
26
|
* domain wall lives where they aggregate — `schema()` (the
|
|
@@ -26,8 +35,10 @@
|
|
|
26
35
|
*/
|
|
27
36
|
|
|
28
37
|
import * as errors from "@superbuilders/errors"
|
|
38
|
+
import { isClosedMember, sealedFieldOf } from "#closed.ts"
|
|
29
39
|
import type { Count } from "#count.ts"
|
|
30
40
|
import { type AnyFace, type FaceData, renderFace, type SameArity, type SameShapes } from "#face.ts"
|
|
41
|
+
import { type ClosedRoster, rosterOf } from "#fields.ts"
|
|
31
42
|
import type { AnyRelation, RelationFields } from "#relation.ts"
|
|
32
43
|
import { renderWindow, type WindowSpec } from "#spec.ts"
|
|
33
44
|
|
|
@@ -98,6 +109,60 @@ interface KeyStatement<R extends AnyRelation, Projection extends readonly string
|
|
|
98
109
|
readonly data: KeyData<R, Projection>
|
|
99
110
|
}
|
|
100
111
|
|
|
112
|
+
/** Renders one face position's closedness for the roster-agreement diagnostics. */
|
|
113
|
+
function renderRosterSide(roster: ClosedRoster | undefined): string {
|
|
114
|
+
return roster === undefined ? "a bare column" : `a ${roster.name} reference`
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The runtime twin of {@link SameArity} (cleanup-0.5.0 ruling 9): the two
|
|
119
|
+
* faces must project equally many fields, judged at CONSTRUCTION for
|
|
120
|
+
* untyped callers too — without it an arity-mismatched containment
|
|
121
|
+
* silently truncates to the shorter projection (this module's positionwise
|
|
122
|
+
* walk and `law.ts`'s `unionSlot` both skip unpaired positions) until
|
|
123
|
+
* `Db.create`'s colder engine refusal. The error carries the two faces'
|
|
124
|
+
* own facts: names, arities, and the rendered statement.
|
|
125
|
+
*/
|
|
126
|
+
function assertArityAgreement(source: FaceData, target: FaceData, statement: Statement): void {
|
|
127
|
+
if (source.projection.length !== target.projection.length) {
|
|
128
|
+
throw errors.new(
|
|
129
|
+
`${source.owner.name}(${source.projection.join(", ")}) and ${target.owner.name}(${target.projection.join(", ")}) project ${source.projection.length} vs ${target.projection.length} fields — positional pairing requires both faces to project equally many — ${renderStatement(statement)}`
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* The runtime twin of {@link SameShapes}'s roster slot: the two faces'
|
|
136
|
+
* projected descriptors must agree POSITIONWISE on closedness — the same
|
|
137
|
+
* roster (value identity — vocabulary identity is value identity, the
|
|
138
|
+
* SDK's membership rule everywhere) or none. Without this wall a plain u64
|
|
139
|
+
* column could alias a closed vocabulary through a declared containment
|
|
140
|
+
* (`docs/architecture/10-data-model.md` spells the ENGINE encoding that
|
|
141
|
+
* way), and every descriptor-keyed closed judgment — the orderable ban,
|
|
142
|
+
* the name↔id marshal, answer decode — would silently miss it. The
|
|
143
|
+
* vocabulary's own descriptor (`Kind.id`) is the ONE spelling of a closed
|
|
144
|
+
* reference at this surface (the canonical-utterance law); the engine
|
|
145
|
+
* cannot backstop this one — the wire carries plain u64s, no rosters.
|
|
146
|
+
* Arity agreement ({@link assertArityAgreement}) runs first, so the
|
|
147
|
+
* positionwise walk here never sees an unpaired position from a well-typed
|
|
148
|
+
* OR an untyped caller.
|
|
149
|
+
*/
|
|
150
|
+
function assertRosterAgreement(source: FaceData, target: FaceData, statement: Statement): void {
|
|
151
|
+
source.projection.forEach(function agreeAt(fieldName, position) {
|
|
152
|
+
const targetField = target.projection[position]
|
|
153
|
+
if (targetField === undefined) {
|
|
154
|
+
return
|
|
155
|
+
}
|
|
156
|
+
const sourceRoster = rosterOf(sealedFieldOf(source.owner, fieldName))
|
|
157
|
+
const targetRoster = rosterOf(sealedFieldOf(target.owner, targetField))
|
|
158
|
+
if (sourceRoster !== targetRoster) {
|
|
159
|
+
throw errors.new(
|
|
160
|
+
`${source.owner.name}.${fieldName} is ${renderRosterSide(sourceRoster)} but ${target.owner.name}.${targetField} is ${renderRosterSide(targetRoster)} — closedness rides the descriptor: a closed reference is spelled with the vocabulary's own id descriptor (one meaning, one spelling), so faces pair closed-with-closed through one roster or bare-with-bare, never across — ${renderStatement(statement)}`
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
})
|
|
164
|
+
}
|
|
165
|
+
|
|
101
166
|
/**
|
|
102
167
|
* `R(X) -> R` — the FD key form, composite keys as tuples. No selection
|
|
103
168
|
* parameter exists (the FD-with-selection shape is unrepresentable, as in
|
|
@@ -113,7 +178,7 @@ function key<
|
|
|
113
178
|
R extends AnyRelation,
|
|
114
179
|
const Projection extends readonly [keyof RelationFields<R> & string, ...(keyof RelationFields<R> & string)[]]
|
|
115
180
|
>(relation: R, fields: Projection): KeyStatement<R, Projection> {
|
|
116
|
-
if (
|
|
181
|
+
if (isClosedMember(relation)) {
|
|
117
182
|
throw errors.new(
|
|
118
183
|
`key(${relation.name}, ...): closedness already materializes ${relation.name}(id) -> ${relation.name} — an explicit key on a closed relation is rejected as a duplicate`
|
|
119
184
|
)
|
|
@@ -145,7 +210,10 @@ function contained<A extends AnyFace, B extends AnyFace>(
|
|
|
145
210
|
target: target.data,
|
|
146
211
|
bidirectional: false
|
|
147
212
|
})
|
|
148
|
-
|
|
213
|
+
const statement = Object.freeze({ data })
|
|
214
|
+
assertArityAgreement(data.source, data.target, statement)
|
|
215
|
+
assertRosterAgreement(data.source, data.target, statement)
|
|
216
|
+
return statement
|
|
149
217
|
}
|
|
150
218
|
|
|
151
219
|
/**
|
|
@@ -167,7 +235,10 @@ function mirrors<A extends AnyFace, B extends AnyFace>(
|
|
|
167
235
|
target: target.data,
|
|
168
236
|
bidirectional: true
|
|
169
237
|
})
|
|
170
|
-
|
|
238
|
+
const statement = Object.freeze({ data })
|
|
239
|
+
assertArityAgreement(data.source, data.target, statement)
|
|
240
|
+
assertRosterAgreement(data.source, data.target, statement)
|
|
241
|
+
return statement
|
|
171
242
|
}
|
|
172
243
|
|
|
173
244
|
/**
|
|
@@ -191,7 +262,10 @@ function window<B extends AnyFace, A extends AnyFace>(
|
|
|
191
262
|
window: count.window,
|
|
192
263
|
source: source.data
|
|
193
264
|
})
|
|
194
|
-
|
|
265
|
+
const statement = Object.freeze({ data })
|
|
266
|
+
assertArityAgreement(data.source, data.target, statement)
|
|
267
|
+
assertRosterAgreement(data.source, data.target, statement)
|
|
268
|
+
return statement
|
|
195
269
|
}
|
|
196
270
|
|
|
197
271
|
/**
|