@bjornpagen/bumbledb 0.9.0 → 0.11.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 +155 -136
- package/README.md +3 -7
- package/dist/capacity.d.ts +14 -1
- package/dist/capacity.d.ts.map +1 -1
- package/dist/capacity.js.map +1 -1
- package/dist/db.d.ts +77 -109
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +121 -339
- package/dist/db.js.map +1 -1
- package/dist/index.d.ts +11 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -10
- package/dist/index.js.map +1 -1
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +8 -1
- package/dist/lower.js.map +1 -1
- package/dist/native.d.ts +69 -50
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js.map +1 -1
- package/dist/query/atom.d.ts +162 -122
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js +26 -22
- package/dist/query/atom.js.map +1 -1
- package/dist/query/find.d.ts +18 -35
- package/dist/query/find.d.ts.map +1 -1
- package/dist/query/find.js +13 -32
- package/dist/query/find.js.map +1 -1
- package/dist/query/lower.d.ts +113 -122
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +336 -260
- package/dist/query/lower.js.map +1 -1
- package/dist/query/parse-ir.d.ts +12 -0
- package/dist/query/parse-ir.d.ts.map +1 -0
- package/dist/query/parse-ir.js +71 -0
- package/dist/query/parse-ir.js.map +1 -0
- package/dist/query/run.d.ts +2 -2
- package/dist/query/run.d.ts.map +1 -1
- package/dist/query/run.js +2 -13
- package/dist/query/run.js.map +1 -1
- package/dist/query/scope.d.ts +4 -16
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +1 -6
- package/dist/query/scope.js.map +1 -1
- package/dist/schema.js +2 -2
- package/dist/schema.js.map +1 -1
- package/dist/statements.d.ts +15 -9
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +14 -9
- package/dist/statements.js.map +1 -1
- package/package.json +2 -2
- package/src/capacity.ts +24 -1
- package/src/db.ts +182 -443
- package/src/index.ts +9 -23
- package/src/lower.ts +8 -1
- package/src/native.ts +69 -42
- package/src/query/atom.ts +255 -165
- package/src/query/find.ts +39 -80
- package/src/query/lower.ts +578 -432
- package/src/query/parse-ir.ts +82 -0
- package/src/query/run.ts +2 -14
- package/src/query/scope.ts +3 -21
- package/src/schema.ts +2 -2
- package/src/statements.ts +33 -17
- package/dist/order.d.ts +0 -87
- package/dist/order.d.ts.map +0 -1
- package/dist/order.js +0 -153
- package/dist/order.js.map +0 -1
- package/dist/query/predicate.d.ts +0 -91
- package/dist/query/predicate.d.ts.map +0 -1
- package/dist/query/predicate.js +0 -156
- package/dist/query/predicate.js.map +0 -1
- package/src/order.ts +0 -234
- package/src/query/predicate.ts +0 -269
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host shape parse for the wire `QueryIr`: rec/main nonempty, aggregate
|
|
3
|
+
* finds split (Count has no `over`; folds require it), head/find
|
|
4
|
+
* alignment. The engine validator remains the one roster authority —
|
|
5
|
+
* this parse refuses only shape the host type can see.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as errors from "@superbuilders/errors"
|
|
9
|
+
import type { FindTermIr, HeadTermIr, ParsedQuery, QueryIr, RuleIr } from "#native.ts"
|
|
10
|
+
|
|
11
|
+
/** Brands a shape-checked wire query so {@link Native.dbPrepare} will accept it. */
|
|
12
|
+
function parseQueryIr(ir: QueryIr): ParsedQuery {
|
|
13
|
+
if (ir.rules.length === 0) {
|
|
14
|
+
throw errors.new("parseQueryIr: main rules are empty")
|
|
15
|
+
}
|
|
16
|
+
align("query", ir.head, ir.rules)
|
|
17
|
+
ir.interiors.forEach(function checkInterior(interior, index) {
|
|
18
|
+
align(`interior ${index}`, interior.head, interior.rules)
|
|
19
|
+
})
|
|
20
|
+
if (ir.rec !== null) {
|
|
21
|
+
if (ir.rec.base.length === 0) {
|
|
22
|
+
throw errors.new("parseQueryIr: rec base is empty")
|
|
23
|
+
}
|
|
24
|
+
if (ir.rec.rec.length === 0) {
|
|
25
|
+
throw errors.new("parseQueryIr: rec step is empty")
|
|
26
|
+
}
|
|
27
|
+
align("rec base", ir.rec.head, ir.rec.base)
|
|
28
|
+
align("rec step", ir.rec.head, ir.rec.rec)
|
|
29
|
+
}
|
|
30
|
+
return ir as ParsedQuery
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** One rule list must share the head's width and var/aggregate family. */
|
|
34
|
+
function align(context: string, head: readonly HeadTermIr[], rules: readonly RuleIr[]): void {
|
|
35
|
+
for (const [ruleIndex, rule] of rules.entries()) {
|
|
36
|
+
if (rule.finds.length !== head.length) {
|
|
37
|
+
throw errors.new(
|
|
38
|
+
`${context}: rule ${ruleIndex} finds width ${rule.finds.length} does not match head width ${head.length}`
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
rule.finds.forEach(function checkFind(find, position) {
|
|
42
|
+
parseFind(`${context} rule ${ruleIndex} find ${position}`, find)
|
|
43
|
+
const family = findFamily(find)
|
|
44
|
+
if (family !== head[position]?.kind) {
|
|
45
|
+
throw errors.new(
|
|
46
|
+
`${context}: rule ${ruleIndex} find ${position} is ${family}, not head ${head[position]?.kind}`
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Count forbids `over`; every other aggregate requires it. */
|
|
54
|
+
function parseFind(context: string, find: FindTermIr): void {
|
|
55
|
+
if (find.kind !== "aggregate") {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
if (find.op.kind === "count") {
|
|
59
|
+
if ("over" in find) {
|
|
60
|
+
throw errors.new(`${context}: Count carries no over`)
|
|
61
|
+
}
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
if (!("over" in find)) {
|
|
65
|
+
throw errors.new(`${context}: fold aggregate requires over`)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Head family of one find term: measure is a var slot; measure-folds are aggregates. */
|
|
70
|
+
function findFamily(find: FindTermIr): "var" | "aggregate" {
|
|
71
|
+
switch (find.kind) {
|
|
72
|
+
case "var":
|
|
73
|
+
case "measure":
|
|
74
|
+
return "var"
|
|
75
|
+
case "aggregate":
|
|
76
|
+
case "aggregateMeasure":
|
|
77
|
+
return "aggregate"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export type { ParsedQuery }
|
|
82
|
+
export { parseQueryIr }
|
package/src/query/run.ts
CHANGED
|
@@ -20,18 +20,9 @@ import * as errors from "@superbuilders/errors"
|
|
|
20
20
|
import { handleOf } from "#marshal.ts"
|
|
21
21
|
import type { FactValue, QueryParam, TaggedValue } from "#native.ts"
|
|
22
22
|
import type { FindColumn } from "#query/atom.ts"
|
|
23
|
-
import { ALLEN_ALL_BITS } from "#query/atom.ts"
|
|
24
23
|
import { taggedCmpLiteral } from "#query/lower.ts"
|
|
25
24
|
import type { ParamEntry } from "#query/scope.ts"
|
|
26
25
|
|
|
27
|
-
/** Tags one supplied mask-param value. */
|
|
28
|
-
function wireMask(name: string, value: unknown): TaggedValue {
|
|
29
|
-
if (typeof value !== "number" || !Number.isInteger(value) || value < 0 || value > ALLEN_ALL_BITS) {
|
|
30
|
-
throw errors.new(`param ${name}: an Allen-mask param binds a 13-bit mask number built from the ALLEN constants`)
|
|
31
|
-
}
|
|
32
|
-
return { kind: "allenMask", mask: value }
|
|
33
|
-
}
|
|
34
|
-
|
|
35
26
|
/** Tags one supplied value-param cell by its anchoring use. */
|
|
36
27
|
function wireValue(entry: ParamEntry, context: string, value: unknown): TaggedValue {
|
|
37
28
|
if (entry.anchor === undefined) {
|
|
@@ -48,7 +39,7 @@ function wireValue(entry: ParamEntry, context: string, value: unknown): TaggedVa
|
|
|
48
39
|
* is a typed error naming the param; values tag by the anchoring use's
|
|
49
40
|
* structural type; a set param takes a readonly array (the empty set is
|
|
50
41
|
* legal and matches nothing — the engine's rule). A MEMBERSHIP-ARRAY
|
|
51
|
-
* entry (`membership` present — a literal set folded into the
|
|
42
|
+
* entry (`membership` present — a literal set folded into the query) is
|
|
52
43
|
* a program constant the registry already resolved through the one
|
|
53
44
|
* roster-verification point at BUILD time: it crosses as its prebuilt
|
|
54
45
|
* frozen `{ kind: "set", values }` by reference — the host's params object
|
|
@@ -63,9 +54,6 @@ function wireParams(entries: readonly ParamEntry[], supplied: Readonly<Record<st
|
|
|
63
54
|
if (value === undefined) {
|
|
64
55
|
throw errors.new(`execute params object is missing param ${entry.name}`)
|
|
65
56
|
}
|
|
66
|
-
if (entry.shape === "mask") {
|
|
67
|
-
return wireMask(entry.name, value)
|
|
68
|
-
}
|
|
69
57
|
if (entry.shape === "set") {
|
|
70
58
|
if (!Array.isArray(value)) {
|
|
71
59
|
throw errors.new(`param ${entry.name}: a set param binds a readonly array of values`)
|
|
@@ -98,7 +86,7 @@ function isAnswerRow<Row>(
|
|
|
98
86
|
}
|
|
99
87
|
|
|
100
88
|
/**
|
|
101
|
-
* Decodes positional answer rows (column order = the
|
|
89
|
+
* Decodes positional answer rows (column order = the query's head order
|
|
102
90
|
* = the select's written order) to named, frozen row objects of bare
|
|
103
91
|
* structural values. A closed column lifts its row id back to the handle
|
|
104
92
|
* NAME through the marshal's bijection — an out-of-roster id is the same
|
package/src/query/scope.ts
CHANGED
|
@@ -119,17 +119,6 @@ interface SetParam<Name extends string = string> {
|
|
|
119
119
|
readonly name: Name
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
/**
|
|
123
|
-
* An Allen-mask parameter (the IR's `MaskTerm::Param`) — the temporal
|
|
124
|
-
* relation as a bind-time argument: one prepared query answers any of the
|
|
125
|
-
* mask questions per execution. Bound to a 13-bit mask number built from
|
|
126
|
-
* the `ALLEN` constants.
|
|
127
|
-
*/
|
|
128
|
-
interface MaskParam<Name extends string = string> {
|
|
129
|
-
readonly [term]: "maskParam"
|
|
130
|
-
readonly name: Name
|
|
131
|
-
}
|
|
132
|
-
|
|
133
122
|
/**
|
|
134
123
|
* The measure of an interval-typed variable (`ir::Term::Measure`):
|
|
135
124
|
* `|[s, e)| = e − s`, u64 — legal as one side of an order comparison, as a
|
|
@@ -143,7 +132,7 @@ interface Duration<V extends AnyVar = AnyVar> {
|
|
|
143
132
|
}
|
|
144
133
|
|
|
145
134
|
/** Any scope term value. */
|
|
146
|
-
type AnyTerm = Var | Param | SetParam |
|
|
135
|
+
type AnyTerm = Var | Param | SetParam | Duration
|
|
147
136
|
|
|
148
137
|
/** Narrows an unknown position value to a scope term (vs a host literal). */
|
|
149
138
|
function isTerm(value: unknown): value is AnyTerm {
|
|
@@ -213,12 +202,6 @@ function makeSetParam<const Name extends string>(name: Name): SetParam<Name> {
|
|
|
213
202
|
return Object.freeze(value)
|
|
214
203
|
}
|
|
215
204
|
|
|
216
|
-
/** Builds one Allen-mask-parameter term. */
|
|
217
|
-
function makeMaskParam<const Name extends string>(name: Name): MaskParam<Name> {
|
|
218
|
-
const value: MaskParam<Name> = { [term]: "maskParam", name }
|
|
219
|
-
return Object.freeze(value)
|
|
220
|
-
}
|
|
221
|
-
|
|
222
205
|
/** Builds one measure term over an interval-typed variable reference. */
|
|
223
206
|
function makeDuration<const V extends AnyVar>(over: V): Duration<V> {
|
|
224
207
|
const value: Duration<V> = { [term]: "duration", over }
|
|
@@ -391,7 +374,7 @@ type InferredOf<T> = T extends { readonly [inferred]?: infer S } ? Exclude<S, un
|
|
|
391
374
|
*/
|
|
392
375
|
interface ParamEntry {
|
|
393
376
|
readonly name: string
|
|
394
|
-
readonly shape: "value" | "set"
|
|
377
|
+
readonly shape: "value" | "set"
|
|
395
378
|
readonly anchor: AnyField | "measure" | undefined
|
|
396
379
|
readonly op: "binding" | "eq" | "ne" | "lt" | "le" | "gt" | "ge" | "pointIn" | "allen"
|
|
397
380
|
readonly membership: QueryParam | undefined
|
|
@@ -405,7 +388,6 @@ export type {
|
|
|
405
388
|
Flatten,
|
|
406
389
|
InferredOf,
|
|
407
390
|
JoinOk,
|
|
408
|
-
MaskParam,
|
|
409
391
|
MatchFields,
|
|
410
392
|
MatchOwner,
|
|
411
393
|
MintClassOf,
|
|
@@ -420,4 +402,4 @@ export type {
|
|
|
420
402
|
Var,
|
|
421
403
|
VarsOf
|
|
422
404
|
}
|
|
423
|
-
export { fieldJoins, inferred, isTerm, makeDuration,
|
|
405
|
+
export { fieldJoins, inferred, isTerm, makeDuration, makeParam, makeSetParam, renderFieldKind, term, v }
|
package/src/schema.ts
CHANGED
|
@@ -138,11 +138,11 @@ function verifyHandles(name: string, statement: Statement, rendered: string): vo
|
|
|
138
138
|
function closedTargetOf(statements: readonly Statement[], owner: string, field: string): string | undefined {
|
|
139
139
|
for (const statement of statements) {
|
|
140
140
|
const data = statement.data
|
|
141
|
-
if (data.kind !== "containment") {
|
|
141
|
+
if (data.kind !== "containment" && data.kind !== "mirrors") {
|
|
142
142
|
continue
|
|
143
143
|
}
|
|
144
144
|
const pairs: Array<readonly [FaceData, FaceData]> = [[data.source, data.target]]
|
|
145
|
-
if (data.
|
|
145
|
+
if (data.kind === "mirrors") {
|
|
146
146
|
pairs.push([data.target, data.source])
|
|
147
147
|
}
|
|
148
148
|
for (const [source, target] of pairs) {
|
package/src/statements.ts
CHANGED
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
type CapacityWindow,
|
|
42
42
|
isCapacityWeight,
|
|
43
43
|
isCapacityWindow,
|
|
44
|
+
type UnitDimensionBan,
|
|
44
45
|
type UnitWindowBan,
|
|
45
46
|
unitWeight,
|
|
46
47
|
type WeightOnSource
|
|
@@ -69,7 +70,12 @@ interface ContainmentData<Src extends FaceData = FaceData, Tgt extends FaceData
|
|
|
69
70
|
readonly kind: "containment"
|
|
70
71
|
readonly source: Src
|
|
71
72
|
readonly target: Tgt
|
|
72
|
-
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
interface MirrorsData<Src extends FaceData = FaceData, Tgt extends FaceData = FaceData> {
|
|
76
|
+
readonly kind: "mirrors"
|
|
77
|
+
readonly source: Src
|
|
78
|
+
readonly target: Tgt
|
|
73
79
|
}
|
|
74
80
|
|
|
75
81
|
/**
|
|
@@ -87,7 +93,7 @@ interface CapacityData<Tgt extends FaceData = FaceData, Src extends FaceData = F
|
|
|
87
93
|
}
|
|
88
94
|
|
|
89
95
|
/** One statement's runtime description, tagged by form. */
|
|
90
|
-
type StatementData = KeyData<AnyRelation, readonly string[]> | ContainmentData | CapacityData
|
|
96
|
+
type StatementData = KeyData<AnyRelation, readonly string[]> | ContainmentData | MirrorsData | CapacityData
|
|
91
97
|
|
|
92
98
|
/**
|
|
93
99
|
* The admission brand — a module-private symbol, deliberately unexported
|
|
@@ -127,7 +133,7 @@ function isStatement(value: unknown): value is Statement {
|
|
|
127
133
|
* {@link Statement}.
|
|
128
134
|
*/
|
|
129
135
|
interface ContainedStatement<Src extends FaceData, Tgt extends FaceData> extends Statement {
|
|
130
|
-
readonly data: ContainmentData<Src, Tgt>
|
|
136
|
+
readonly data: ContainmentData<Src, Tgt> | MirrorsData<Src, Tgt>
|
|
131
137
|
}
|
|
132
138
|
|
|
133
139
|
/** A capacity statement as a TYPED value — the {@link ContainedStatement} of the capacity form. */
|
|
@@ -246,8 +252,7 @@ function contained<A extends AnyFace, B extends AnyFace>(
|
|
|
246
252
|
const data: ContainmentData<A["data"], B["data"]> = Object.freeze({
|
|
247
253
|
kind: "containment",
|
|
248
254
|
source: source.data,
|
|
249
|
-
target: target.data
|
|
250
|
-
bidirectional: false
|
|
255
|
+
target: target.data
|
|
251
256
|
})
|
|
252
257
|
const statement = Object.freeze({ data, [admitted]: true as const })
|
|
253
258
|
assertArityAgreement(data.source, data.target, statement)
|
|
@@ -268,11 +273,10 @@ function mirrors<A extends AnyFace, B extends AnyFace>(
|
|
|
268
273
|
source: A,
|
|
269
274
|
target: B & SameArity<A, B> & SameShapes<A, B>
|
|
270
275
|
): ContainedStatement<A["data"], B["data"]> {
|
|
271
|
-
const data:
|
|
272
|
-
kind: "
|
|
276
|
+
const data: MirrorsData<A["data"], B["data"]> = Object.freeze({
|
|
277
|
+
kind: "mirrors",
|
|
273
278
|
source: source.data,
|
|
274
|
-
target: target.data
|
|
275
|
-
bidirectional: true
|
|
279
|
+
target: target.data
|
|
276
280
|
})
|
|
277
281
|
const statement = Object.freeze({ data, [admitted]: true as const })
|
|
278
282
|
assertArityAgreement(data.source, data.target, statement)
|
|
@@ -357,13 +361,15 @@ function assertBoundsOnTarget(window: CapacityWindowSpec, target: FaceData, stat
|
|
|
357
361
|
* on(Device, "pool"))` bounds each pool's summed draw by the pool's own
|
|
358
362
|
* row. The two faces pair by arity AND structural shape
|
|
359
363
|
* ({@link SameShapes}), exactly as containment — the grouping join reads
|
|
360
|
-
* the same positionwise field pairing. The weight-sensitive
|
|
361
|
-
*
|
|
362
|
-
* statement "positive total" is a different, weaker law than containment)
|
|
364
|
+
* the same positionwise field pairing. The weight-sensitive bans ride the
|
|
365
|
+
* UNIT overload only: `{1..*}` ({@link UnitWindowBan} — on a weighted
|
|
366
|
+
* statement "positive total" is a different, weaker law than containment)
|
|
367
|
+
* and the `duration()` bound ({@link UnitDimensionBan} — a count of facts
|
|
368
|
+
* bounded by a span of time mixes dimensions, C18).
|
|
363
369
|
*/
|
|
364
370
|
function capacity<B extends AnyFace, W extends CapacityWindow, A extends AnyFace>(
|
|
365
371
|
target: B,
|
|
366
|
-
window: W & UnitWindowBan<W> & BoundsOnTarget<W, B>,
|
|
372
|
+
window: W & UnitWindowBan<W> & UnitDimensionBan<W> & BoundsOnTarget<W, B>,
|
|
367
373
|
source: A & SameArity<B, A> & SameShapes<B, A>
|
|
368
374
|
): CapacityStatement<B["data"], A["data"]>
|
|
369
375
|
function capacity<B extends AnyFace, M extends CapacityWeight, W extends CapacityWindow, A extends AnyFace>(
|
|
@@ -401,6 +407,15 @@ function capacity(
|
|
|
401
407
|
"`{1..*}` on the unit instance says only what the bare containment says — drop the annotation and write the containment: contained(source, target)"
|
|
402
408
|
)
|
|
403
409
|
}
|
|
410
|
+
// The C18 dimension gate, unit instance (the engine's
|
|
411
|
+
// CapacityDimensionMixing twin — ruled 2026-07-24): a count of facts
|
|
412
|
+
// bounded by a span of time mixes dimensions. Judged here for untyped
|
|
413
|
+
// callers; the engine's validate_capacity stays the final authority.
|
|
414
|
+
if (weight.kind === "unit" && window.kind === "range" && window.hi.kind === "durationField") {
|
|
415
|
+
throw errors.new(
|
|
416
|
+
`a unit (count) window against the duration() bound on ${window.hi.field} mixes dimensions (C18) — weigh the source with weigh(duration(field)), or bound by a u64 field or literal`
|
|
417
|
+
)
|
|
418
|
+
}
|
|
404
419
|
const data: CapacityData = Object.freeze({
|
|
405
420
|
kind: "capacity",
|
|
406
421
|
target: target.data,
|
|
@@ -433,10 +448,10 @@ function renderStatement(statement: Statement): string {
|
|
|
433
448
|
switch (data.kind) {
|
|
434
449
|
case "key":
|
|
435
450
|
return `${data.owner.name}(${data.projection.join(", ")}) -> ${data.owner.name}`
|
|
436
|
-
case "containment":
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
451
|
+
case "containment":
|
|
452
|
+
return `${renderFace(data.source)} <= ${renderFace(data.target)}`
|
|
453
|
+
case "mirrors":
|
|
454
|
+
return `${renderFace(data.source)} == ${renderFace(data.target)}`
|
|
440
455
|
case "capacity":
|
|
441
456
|
return `${renderFace(data.target)} <=${renderWeight(data.weight)}${renderCapacityWindow(data.window)} ${renderFace(data.source)}`
|
|
442
457
|
}
|
|
@@ -449,6 +464,7 @@ export type {
|
|
|
449
464
|
ContainmentData,
|
|
450
465
|
KeyData,
|
|
451
466
|
KeyStatement,
|
|
467
|
+
MirrorsData,
|
|
452
468
|
Statement,
|
|
453
469
|
StatementData
|
|
454
470
|
}
|
package/dist/order.d.ts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Host-side answer ordering — the census-fired convenience
|
|
3
|
-
* (`docs/architecture/70-api.md` § the freeze ledger). Answers are SETS and
|
|
4
|
-
* the ENGINE NEVER ORDERS; the language owns the sort (`rows.sort(...)`)
|
|
5
|
-
* and the limit (`.slice(0, n)`) — the drizzle law. What JS lacks is a
|
|
6
|
-
* number-returning comparator over the SDK's bigint-bearing cells, so the
|
|
7
|
-
* SDK ships exactly that: sort keys are DATA — a bare column name is
|
|
8
|
-
* ascending (the punning spelling; no `asc` wrapper exists — one spelling
|
|
9
|
-
* per meaning) and `desc(name)` is the one descending spelling — folded by
|
|
10
|
-
* `by(...)` into one row-typed comparator. Cross-type cells cannot arise
|
|
11
|
-
* within one column (one column, one domain), and the cell order is TOTAL
|
|
12
|
-
* anyway (the type-rank wall), so the comparator never throws.
|
|
13
|
-
*
|
|
14
|
-
* ZERO keys is the identity key (ruled 2026-07-25): `by()` / `desc()` are
|
|
15
|
-
* the same two spellings over BARE scalar arrays (`bigint[]` of ids, map
|
|
16
|
-
* keys) — with no column to name, the value itself is the key, there is
|
|
17
|
-
* nothing to fold, and the comparator IS the result. One ordering
|
|
18
|
-
* vocabulary, no sibling names. The identity arms are typed to EXACTLY the
|
|
19
|
-
* engine-orderable roster ({@link EngineOrderable}) because a bare scalar
|
|
20
|
-
* carries no decoded-row provenance — the type wall must carry the
|
|
21
|
-
* orderability law itself, where the row arm's cells arrive under their
|
|
22
|
-
* columns' law-typed proof.
|
|
23
|
-
*/
|
|
24
|
-
import type { FactValue } from "#native.ts";
|
|
25
|
-
/** One DESCENDING sort key, plain data — built by {@link desc}. */
|
|
26
|
-
interface Desc<K extends string> {
|
|
27
|
-
readonly key: K;
|
|
28
|
-
readonly desc: true;
|
|
29
|
-
}
|
|
30
|
-
/** One sort key: a bare column name (ascending — the punning spelling) or `desc(name)`. */
|
|
31
|
-
type SortKey<K extends string> = K | Desc<K>;
|
|
32
|
-
/**
|
|
33
|
-
* The engine-orderable scalar roster in the SDK's representation — `bigint`
|
|
34
|
-
* (U64/I64) and `boolean` (false < true — the strict 0/1 encoding IS the
|
|
35
|
-
* order), EXACTLY as `docs/architecture/10-data-model.md` § "Orderability,
|
|
36
|
-
* complete" admits it (ruled 2026-07-23, R3/R4), and nothing more:
|
|
37
|
-
* `string` is deliberately absent (intern ids are meaningless to order — a
|
|
38
|
-
* typed refusal, not a gap) and `number` is not an engine scalar at all.
|
|
39
|
-
* The identity comparators `by()`/`desc()` constrain on this alias, so
|
|
40
|
-
* sorting a `string[]` or `number[]` through them is a COMPILE error naming
|
|
41
|
-
* this roster. ONE OWNER for scalar ordering semantics: both identity arms
|
|
42
|
-
* route through the same cell order the row arm uses, whose bigint and
|
|
43
|
-
* boolean arms mirror the engine's U64/I64/Bool order exactly — a host
|
|
44
|
-
* sort over these values can never disagree with an engine order judgment
|
|
45
|
-
* (`Lt`-family, `Min`/`Max`) over the same column.
|
|
46
|
-
*/
|
|
47
|
-
type EngineOrderable = bigint | boolean;
|
|
48
|
-
/**
|
|
49
|
-
* The descending spelling — ONE name, both arities of one ordering
|
|
50
|
-
* vocabulary. `desc(name)` marks one sort key DESCENDING: plain data for
|
|
51
|
-
* {@link by} to fold (a bare name is already ascending). `desc()` — zero
|
|
52
|
-
* keys, the identity key (ruled 2026-07-25) — is the descending comparator
|
|
53
|
-
* over engine-orderable scalars themselves: a bare `bigint[]` or
|
|
54
|
-
* `boolean[]` has no column to name, so the value IS the key, there is
|
|
55
|
-
* nothing to fold, and the comparator is the result directly. The identity
|
|
56
|
-
* arm covers EXACTLY the {@link EngineOrderable} roster — `string` and
|
|
57
|
-
* `number` refuse at compile time, citing the orderability law
|
|
58
|
-
* (`10-data-model.md` § "Orderability, complete").
|
|
59
|
-
*/
|
|
60
|
-
declare function desc(): <T extends EngineOrderable>(left: T, right: T) => number;
|
|
61
|
-
declare function desc<const K extends string>(key: K): Desc<K>;
|
|
62
|
-
/**
|
|
63
|
-
* Folds sort keys into ONE comparator typed against the row —
|
|
64
|
-
* `Row extends Readonly<Record<K, FactValue>>` — so a key the row lacks, or
|
|
65
|
-
* a column typed `number` (outside the cell domain), is a COMPILE error at
|
|
66
|
-
* the `.sort` call site: the laws typed the columns, and the row type
|
|
67
|
-
* carries that proof here (parse-don't-validate). The generic RETURN is the
|
|
68
|
-
* load-bearing trick: `rows.sort(by("rank"))` instantiates `Row` from the
|
|
69
|
-
* array's own element type and checks the key set right there.
|
|
70
|
-
*
|
|
71
|
-
* ZERO keys is the identity key (ruled 2026-07-25): `by()` is the
|
|
72
|
-
* ascending comparator over engine-orderable scalars themselves —
|
|
73
|
-
* `ids.sort(by())` — for the bare arrays (`bigint[]`, map keys) the
|
|
74
|
-
* row-typed arm cannot reach because they have no column to name. One
|
|
75
|
-
* vocabulary, both arities. The identity arm is typed to EXACTLY the
|
|
76
|
-
* {@link EngineOrderable} roster: with no law-typed column standing proof
|
|
77
|
-
* over the values, the type wall carries the orderability law itself —
|
|
78
|
-
* `string` ordering is deliberately refused and `number` is not an engine
|
|
79
|
-
* scalar (`10-data-model.md` § "Orderability, complete"), so both refuse
|
|
80
|
-
* at compile time and a host sort can never disagree with an engine order
|
|
81
|
-
* judgment.
|
|
82
|
-
*/
|
|
83
|
-
declare function by(): <T extends EngineOrderable>(left: T, right: T) => number;
|
|
84
|
-
declare function by<const K extends string>(first: SortKey<K>, ...rest: ReadonlyArray<SortKey<K>>): <Row extends Readonly<Record<K, FactValue>>>(left: Row, right: Row) => number;
|
|
85
|
-
export type { Desc, EngineOrderable, SortKey };
|
|
86
|
-
export { by, desc };
|
|
87
|
-
//# sourceMappingURL=order.d.ts.map
|
package/dist/order.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"order.d.ts","sourceRoot":"","sources":["../src/order.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C,mEAAmE;AACnE,UAAU,IAAI,CAAC,CAAC,SAAS,MAAM;IAC9B,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAA;IACf,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;CACnB;AAED,2FAA2F;AAC3F,KAAK,OAAO,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;AAE5C;;;;;;;;;;;;;;GAcG;AACH,KAAK,eAAe,GAAG,MAAM,GAAG,OAAO,CAAA;AA6GvC;;;;;;;;;;;GAWG;AACH,iBAAS,IAAI,IAAI,CAAC,CAAC,SAAS,eAAe,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,MAAM,CAAA;AACzE,iBAAS,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;AAStD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,iBAAS,EAAE,IAAI,CAAC,CAAC,SAAS,eAAe,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,MAAM,CAAA;AACvE,iBAAS,EAAE,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,EACjC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EACjB,GAAG,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAChC,CAAC,GAAG,SAAS,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,KAAK,MAAM,CAAA;AA0BhF,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,CAAA;AAC9C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA"}
|
package/dist/order.js
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Host-side answer ordering — the census-fired convenience
|
|
3
|
-
* (`docs/architecture/70-api.md` § the freeze ledger). Answers are SETS and
|
|
4
|
-
* the ENGINE NEVER ORDERS; the language owns the sort (`rows.sort(...)`)
|
|
5
|
-
* and the limit (`.slice(0, n)`) — the drizzle law. What JS lacks is a
|
|
6
|
-
* number-returning comparator over the SDK's bigint-bearing cells, so the
|
|
7
|
-
* SDK ships exactly that: sort keys are DATA — a bare column name is
|
|
8
|
-
* ascending (the punning spelling; no `asc` wrapper exists — one spelling
|
|
9
|
-
* per meaning) and `desc(name)` is the one descending spelling — folded by
|
|
10
|
-
* `by(...)` into one row-typed comparator. Cross-type cells cannot arise
|
|
11
|
-
* within one column (one column, one domain), and the cell order is TOTAL
|
|
12
|
-
* anyway (the type-rank wall), so the comparator never throws.
|
|
13
|
-
*
|
|
14
|
-
* ZERO keys is the identity key (ruled 2026-07-25): `by()` / `desc()` are
|
|
15
|
-
* the same two spellings over BARE scalar arrays (`bigint[]` of ids, map
|
|
16
|
-
* keys) — with no column to name, the value itself is the key, there is
|
|
17
|
-
* nothing to fold, and the comparator IS the result. One ordering
|
|
18
|
-
* vocabulary, no sibling names. The identity arms are typed to EXACTLY the
|
|
19
|
-
* engine-orderable roster ({@link EngineOrderable}) because a bare scalar
|
|
20
|
-
* carries no decoded-row provenance — the type wall must carry the
|
|
21
|
-
* orderability law itself, where the row arm's cells arrive under their
|
|
22
|
-
* columns' law-typed proof.
|
|
23
|
-
*/
|
|
24
|
-
/**
|
|
25
|
-
* The type-rank wall: boolean 0, bigint 1, string 2, bytes 3, interval 4.
|
|
26
|
-
* One column carries one domain, so a mixed pair never arises from decoded
|
|
27
|
-
* answer rows — the wall exists to keep the cell order TOTAL (never a
|
|
28
|
-
* throw), not to be reached.
|
|
29
|
-
*/
|
|
30
|
-
function cellRank(value) {
|
|
31
|
-
if (typeof value === "boolean") {
|
|
32
|
-
return 0;
|
|
33
|
-
}
|
|
34
|
-
if (typeof value === "bigint") {
|
|
35
|
-
return 1;
|
|
36
|
-
}
|
|
37
|
-
if (typeof value === "string") {
|
|
38
|
-
return 2;
|
|
39
|
-
}
|
|
40
|
-
if (value instanceof Uint8Array) {
|
|
41
|
-
return 3;
|
|
42
|
-
}
|
|
43
|
-
return 4;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* One cell against one cell. Same-type arms: boolean orders false < true;
|
|
47
|
-
* bigint by `<`/`>`; string by the host language's own `<`/`>` (flavor,
|
|
48
|
-
* recorded); bytes bytewise over the shared prefix, then by length;
|
|
49
|
-
* intervals by start, then end. A mixed pair falls through to the
|
|
50
|
-
* type-rank wall.
|
|
51
|
-
*/
|
|
52
|
-
function cellCmp(left, right) {
|
|
53
|
-
if (typeof left === "boolean" && typeof right === "boolean") {
|
|
54
|
-
if (left === right) {
|
|
55
|
-
return 0;
|
|
56
|
-
}
|
|
57
|
-
if (left) {
|
|
58
|
-
return 1;
|
|
59
|
-
}
|
|
60
|
-
return -1;
|
|
61
|
-
}
|
|
62
|
-
if (typeof left === "bigint" && typeof right === "bigint") {
|
|
63
|
-
if (left < right) {
|
|
64
|
-
return -1;
|
|
65
|
-
}
|
|
66
|
-
if (left > right) {
|
|
67
|
-
return 1;
|
|
68
|
-
}
|
|
69
|
-
return 0;
|
|
70
|
-
}
|
|
71
|
-
if (typeof left === "string" && typeof right === "string") {
|
|
72
|
-
if (left < right) {
|
|
73
|
-
return -1;
|
|
74
|
-
}
|
|
75
|
-
if (left > right) {
|
|
76
|
-
return 1;
|
|
77
|
-
}
|
|
78
|
-
return 0;
|
|
79
|
-
}
|
|
80
|
-
if (left instanceof Uint8Array && right instanceof Uint8Array) {
|
|
81
|
-
const shared = Math.min(left.length, right.length);
|
|
82
|
-
for (let index = 0; index < shared; index += 1) {
|
|
83
|
-
const leftByte = left[index];
|
|
84
|
-
const rightByte = right[index];
|
|
85
|
-
// `index < shared` keeps both reads in bounds; the `undefined`
|
|
86
|
-
// arms are the checker's indexed-access tax, never taken.
|
|
87
|
-
if (leftByte !== undefined && rightByte !== undefined && leftByte !== rightByte) {
|
|
88
|
-
return leftByte - rightByte;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return left.length - right.length;
|
|
92
|
-
}
|
|
93
|
-
if (typeof left === "object" &&
|
|
94
|
-
!(left instanceof Uint8Array) &&
|
|
95
|
-
typeof right === "object" &&
|
|
96
|
-
!(right instanceof Uint8Array)) {
|
|
97
|
-
if (left.start < right.start) {
|
|
98
|
-
return -1;
|
|
99
|
-
}
|
|
100
|
-
if (left.start > right.start) {
|
|
101
|
-
return 1;
|
|
102
|
-
}
|
|
103
|
-
if (left.end < right.end) {
|
|
104
|
-
return -1;
|
|
105
|
-
}
|
|
106
|
-
if (left.end > right.end) {
|
|
107
|
-
return 1;
|
|
108
|
-
}
|
|
109
|
-
return 0;
|
|
110
|
-
}
|
|
111
|
-
return cellRank(left) - cellRank(right);
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* The ascending identity comparator `by()` returns — one value, minted
|
|
115
|
-
* once (`by() === by()`), {@link cellCmp} narrowed to the engine-orderable
|
|
116
|
-
* roster (the one owner of the cell order).
|
|
117
|
-
*/
|
|
118
|
-
function identityAscending(left, right) {
|
|
119
|
-
return cellCmp(left, right);
|
|
120
|
-
}
|
|
121
|
-
/** The descending identity comparator `desc()` returns — the same owner, sides flipped. */
|
|
122
|
-
function identityDescending(left, right) {
|
|
123
|
-
return cellCmp(right, left);
|
|
124
|
-
}
|
|
125
|
-
function desc(key) {
|
|
126
|
-
if (key === undefined) {
|
|
127
|
-
return identityDescending;
|
|
128
|
-
}
|
|
129
|
-
const marker = { key, desc: true };
|
|
130
|
-
return Object.freeze(marker);
|
|
131
|
-
}
|
|
132
|
-
function by(...keys) {
|
|
133
|
-
if (keys.length === 0) {
|
|
134
|
-
return identityAscending;
|
|
135
|
-
}
|
|
136
|
-
const entries = keys.map(function normalizeKey(sortKey) {
|
|
137
|
-
if (typeof sortKey === "string") {
|
|
138
|
-
return { key: sortKey, factor: 1 };
|
|
139
|
-
}
|
|
140
|
-
return { key: sortKey.key, factor: -1 };
|
|
141
|
-
});
|
|
142
|
-
return function compare(left, right) {
|
|
143
|
-
for (const entry of entries) {
|
|
144
|
-
const order = cellCmp(left[entry.key], right[entry.key]) * entry.factor;
|
|
145
|
-
if (order !== 0) {
|
|
146
|
-
return order;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
return 0;
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
export { by, desc };
|
|
153
|
-
//# sourceMappingURL=order.js.map
|
package/dist/order.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"order.js","sourceRoot":"","sources":["../src/order.ts"],"names":[],"mappings":"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"}
|