@bjornpagen/bumbledb 0.10.0 → 0.12.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 +5 -9
- 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 +12 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -11
- 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 +77 -51
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js.map +1 -1
- package/dist/query/atom.d.ts +94 -112
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js +8 -17
- 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 +128 -124
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +366 -258
- 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 +8 -4
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +7 -9
- package/dist/statements.js.map +1 -1
- package/package.json +2 -2
- package/src/db.ts +182 -443
- package/src/index.ts +11 -24
- package/src/lower.ts +8 -1
- package/src/native.ts +79 -43
- package/src/query/atom.ts +105 -138
- package/src/query/find.ts +39 -80
- package/src/query/lower.ts +626 -434
- 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 +17 -13
- 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`: CQ/Reach eliminator, rec/main
|
|
3
|
+
* nonempty, aggregate finds split (Count has no `over`; folds require
|
|
4
|
+
* it), head/find alignment. The engine validator remains the one roster
|
|
5
|
+
* authority — 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.kind === "reach") {
|
|
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
|
@@ -70,7 +70,12 @@ interface ContainmentData<Src extends FaceData = FaceData, Tgt extends FaceData
|
|
|
70
70
|
readonly kind: "containment"
|
|
71
71
|
readonly source: Src
|
|
72
72
|
readonly target: Tgt
|
|
73
|
-
|
|
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
|
|
74
79
|
}
|
|
75
80
|
|
|
76
81
|
/**
|
|
@@ -88,7 +93,7 @@ interface CapacityData<Tgt extends FaceData = FaceData, Src extends FaceData = F
|
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
/** One statement's runtime description, tagged by form. */
|
|
91
|
-
type StatementData = KeyData<AnyRelation, readonly string[]> | ContainmentData | CapacityData
|
|
96
|
+
type StatementData = KeyData<AnyRelation, readonly string[]> | ContainmentData | MirrorsData | CapacityData
|
|
92
97
|
|
|
93
98
|
/**
|
|
94
99
|
* The admission brand — a module-private symbol, deliberately unexported
|
|
@@ -128,7 +133,7 @@ function isStatement(value: unknown): value is Statement {
|
|
|
128
133
|
* {@link Statement}.
|
|
129
134
|
*/
|
|
130
135
|
interface ContainedStatement<Src extends FaceData, Tgt extends FaceData> extends Statement {
|
|
131
|
-
readonly data: ContainmentData<Src, Tgt>
|
|
136
|
+
readonly data: ContainmentData<Src, Tgt> | MirrorsData<Src, Tgt>
|
|
132
137
|
}
|
|
133
138
|
|
|
134
139
|
/** A capacity statement as a TYPED value — the {@link ContainedStatement} of the capacity form. */
|
|
@@ -247,8 +252,7 @@ function contained<A extends AnyFace, B extends AnyFace>(
|
|
|
247
252
|
const data: ContainmentData<A["data"], B["data"]> = Object.freeze({
|
|
248
253
|
kind: "containment",
|
|
249
254
|
source: source.data,
|
|
250
|
-
target: target.data
|
|
251
|
-
bidirectional: false
|
|
255
|
+
target: target.data
|
|
252
256
|
})
|
|
253
257
|
const statement = Object.freeze({ data, [admitted]: true as const })
|
|
254
258
|
assertArityAgreement(data.source, data.target, statement)
|
|
@@ -269,11 +273,10 @@ function mirrors<A extends AnyFace, B extends AnyFace>(
|
|
|
269
273
|
source: A,
|
|
270
274
|
target: B & SameArity<A, B> & SameShapes<A, B>
|
|
271
275
|
): ContainedStatement<A["data"], B["data"]> {
|
|
272
|
-
const data:
|
|
273
|
-
kind: "
|
|
276
|
+
const data: MirrorsData<A["data"], B["data"]> = Object.freeze({
|
|
277
|
+
kind: "mirrors",
|
|
274
278
|
source: source.data,
|
|
275
|
-
target: target.data
|
|
276
|
-
bidirectional: true
|
|
279
|
+
target: target.data
|
|
277
280
|
})
|
|
278
281
|
const statement = Object.freeze({ data, [admitted]: true as const })
|
|
279
282
|
assertArityAgreement(data.source, data.target, statement)
|
|
@@ -445,10 +448,10 @@ function renderStatement(statement: Statement): string {
|
|
|
445
448
|
switch (data.kind) {
|
|
446
449
|
case "key":
|
|
447
450
|
return `${data.owner.name}(${data.projection.join(", ")}) -> ${data.owner.name}`
|
|
448
|
-
case "containment":
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
451
|
+
case "containment":
|
|
452
|
+
return `${renderFace(data.source)} <= ${renderFace(data.target)}`
|
|
453
|
+
case "mirrors":
|
|
454
|
+
return `${renderFace(data.source)} == ${renderFace(data.target)}`
|
|
452
455
|
case "capacity":
|
|
453
456
|
return `${renderFace(data.target)} <=${renderWeight(data.weight)}${renderCapacityWindow(data.window)} ${renderFace(data.source)}`
|
|
454
457
|
}
|
|
@@ -461,6 +464,7 @@ export type {
|
|
|
461
464
|
ContainmentData,
|
|
462
465
|
KeyData,
|
|
463
466
|
KeyStatement,
|
|
467
|
+
MirrorsData,
|
|
464
468
|
Statement,
|
|
465
469
|
StatementData
|
|
466
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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"}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Stratified recursion — engine recursion as values, mirroring the IR's
|
|
3
|
-
* cut exactly (`ir::Program`/`PredicateDef`/`AtomSource::Idb`;
|
|
4
|
-
* `docs/architecture/20-query-ir.md` § engine recursion):
|
|
5
|
-
*
|
|
6
|
-
* program(S, (p) => {
|
|
7
|
-
* const reach = p.rec("reach")
|
|
8
|
-
* reach.rule((r) => {
|
|
9
|
-
* const n = v(Node)
|
|
10
|
-
* return r.match(Node, { id: n.id }).where(r.eq(n.id, r.param("root"))).find({ c: n.id })
|
|
11
|
-
* })
|
|
12
|
-
* reach.rule((r) => {
|
|
13
|
-
* const e = v(Parent)
|
|
14
|
-
* return r.match(Parent, { child: e.child, parent: e.parent }).idb(reach, { c: e.parent }).find({ c: e.child })
|
|
15
|
-
* })
|
|
16
|
-
* return p.output((r) => {
|
|
17
|
-
* const post = v(Posting)
|
|
18
|
-
* return r.match(Posting, { account: post.account, minor: post.minor })
|
|
19
|
-
* .idb(reach, { c: post.account }).find({ total: r.sum(post.minor) })
|
|
20
|
-
* })
|
|
21
|
-
* })
|
|
22
|
-
*
|
|
23
|
-
* `p.rec(name)` declares one recursive predicate (declaration order = its
|
|
24
|
-
* dense `PredId`); `rec.rule(...)` attaches one clause — its builder's
|
|
25
|
-
* `idb` accepts ONLY the rec itself (the self-recursion cut as a
|
|
26
|
-
* type-level boundary: mutual recursion is unwritable) and its `find` head
|
|
27
|
-
* projects bound variables only (aggregation/measure through a cycle is
|
|
28
|
-
* unrepresentable — the strata judge's roster, made unwritable);
|
|
29
|
-
* `p.output(...)` seals the recs and builds the output rules, whose `idb`
|
|
30
|
-
* folds any FINISHED stratum by NAMED record over its head keys (recipe
|
|
31
|
-
* 25's form). The rec value `.rule` returns carries the params its rules
|
|
32
|
-
* used — thread it into the output's `idb` and the program's inferred
|
|
33
|
-
* `Params` stays exactly the params the rules use. Everything deeper —
|
|
34
|
-
* strata legality, signature sealing, the three oracles — is the ENGINE's
|
|
35
|
-
* judge, surfacing typed at prepare.
|
|
36
|
-
*/
|
|
37
|
-
import type { SchemaClasses } from "#law.ts";
|
|
38
|
-
import type { AnyRuleValue, HeadOf, HeadShape, OutputRuleScope, ParamsOf, Query, RecRef, RecRuleScope, RowOf } from "#query/lower.ts";
|
|
39
|
-
import type { Flatten, ParamsRecord, ShapeOf } from "#query/scope.ts";
|
|
40
|
-
import { inferred } from "#query/scope.ts";
|
|
41
|
-
import type { Schema, SchemaRelations } from "#schema.ts";
|
|
42
|
-
/**
|
|
43
|
-
* One recursive predicate HANDLE: `rec.rule(...)` attaches a clause and
|
|
44
|
-
* returns the SAME rec under a widened params type (the runtime data is
|
|
45
|
-
* shared — either handle is the self-reference; the returned one carries
|
|
46
|
-
* the rules' params for the output to thread) and under the head signature
|
|
47
|
-
* the FIRST rule sealed (every later rule derives the same head — the
|
|
48
|
-
* runtime alignment check's law), so a threaded handle's `idb` joins are
|
|
49
|
-
* arity- and domain-checked against the head.
|
|
50
|
-
*/
|
|
51
|
-
interface Rec<Rels extends SchemaRelations, Name extends string, P extends ParamsRecord, Head extends HeadShape = undefined, Classes extends SchemaClasses = SchemaClasses> extends RecRef<Name, P, Head> {
|
|
52
|
-
rule<RV extends AnyRuleValue>(build: (r: RecRuleScope<Rels, Name, Classes>) => RV): Rec<Rels, Name, Flatten<P & ParamsOf<RV>>, Head extends undefined ? HeadOf<RV> : Head, Classes>;
|
|
53
|
-
readonly [inferred]?: {
|
|
54
|
-
readonly params: P;
|
|
55
|
-
readonly head: Head;
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
/** One output-rule builder function. */
|
|
59
|
-
type OutputBuild<Rels extends SchemaRelations, Classes extends SchemaClasses = SchemaClasses> = (r: OutputRuleScope<Rels, Classes>) => AnyRuleValue;
|
|
60
|
-
/** A build function's rule value. */
|
|
61
|
-
type BuiltRule<F> = F extends (r: never) => infer RV ? RV : never;
|
|
62
|
-
/** The union row of a tuple of output builds. */
|
|
63
|
-
type OutputRow<Builds extends readonly OutputBuild<SchemaRelations, SchemaClasses>[]> = RowOf<BuiltRule<Builds[number]>>;
|
|
64
|
-
/** The intersected params record of a tuple of output builds. */
|
|
65
|
-
type OutputParams<Builds extends readonly OutputBuild<SchemaRelations, SchemaClasses>[]> = ShapeOf<ParamsOf<BuiltRule<Builds[number]>>>;
|
|
66
|
-
/**
|
|
67
|
-
* The program scope: declare recs, attach their rules, then declare the
|
|
68
|
-
* output — which seals the recs (a later `rec`/`rule` is a construction
|
|
69
|
-
* error) and returns the program as an ordinary query value.
|
|
70
|
-
*/
|
|
71
|
-
interface ProgramScope<Rels extends SchemaRelations, Classes extends SchemaClasses = SchemaClasses> {
|
|
72
|
-
/** Declares one recursive predicate; declaration order = its dense `PredId`. */
|
|
73
|
-
rec<const Name extends string>(name: Name): Rec<Rels, Name, Record<never, never>, undefined, Classes>;
|
|
74
|
-
/**
|
|
75
|
-
* Declares the output predicate (one rule per build; multiple rules =
|
|
76
|
-
* set union) and seals the program. Must be what the `program()`
|
|
77
|
-
* callback returns.
|
|
78
|
-
*/
|
|
79
|
-
output<const Builds extends readonly OutputBuild<Rels, Classes>[]>(...builds: Builds): Query<Rels, OutputRow<Builds>, OutputParams<Builds>, Classes>;
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Builds a stratified program over a schema. The callback declares recs
|
|
83
|
-
* and their rules through the scope and MUST return `p.output(...)` — the
|
|
84
|
-
* sealed program is an ordinary query value: `db.prepare` lowers it to
|
|
85
|
-
* the one `ProgramIr` shape the engine executes under the per-stratum
|
|
86
|
-
* fixpoint driver.
|
|
87
|
-
*/
|
|
88
|
-
declare function program<Rels extends SchemaRelations, Classes extends SchemaClasses, Q extends Query<Rels, unknown, ParamsRecord, Classes>>(theory: Schema<Rels, Classes>, build: (p: ProgramScope<Rels, Classes>) => Q): Q;
|
|
89
|
-
export type { OutputBuild, ProgramScope, Rec };
|
|
90
|
-
export { program };
|
|
91
|
-
//# sourceMappingURL=predicate.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"predicate.d.ts","sourceRoot":"","sources":["../../src/query/predicate.ts"],"names":[],"mappings":"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"}
|