@bjornpagen/bumbledb 0.2.0 → 0.4.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 +503 -427
- package/README.md +84 -36
- package/dist/closed.d.ts +111 -38
- package/dist/closed.d.ts.map +1 -1
- package/dist/closed.js +94 -99
- package/dist/closed.js.map +1 -1
- package/dist/db.d.ts +16 -2
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +46 -8
- package/dist/db.js.map +1 -1
- package/dist/face.d.ts +114 -69
- package/dist/face.d.ts.map +1 -1
- package/dist/face.js +38 -21
- package/dist/face.js.map +1 -1
- package/dist/fields.d.ts +72 -87
- package/dist/fields.d.ts.map +1 -1
- package/dist/fields.js +35 -67
- package/dist/fields.js.map +1 -1
- package/dist/index.d.ts +18 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -7
- package/dist/index.js.map +1 -1
- package/dist/law.d.ts +224 -0
- package/dist/law.d.ts.map +1 -0
- package/dist/law.js +224 -0
- package/dist/law.js.map +1 -0
- package/dist/lower.d.ts +17 -10
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +34 -23
- 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 +67 -6
- package/dist/marshal.js.map +1 -1
- package/dist/native.d.ts +6 -2
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js.map +1 -1
- package/dist/query/atom.d.ts +139 -56
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js +7 -1
- package/dist/query/atom.js.map +1 -1
- package/dist/query/lower.d.ts +71 -56
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +341 -69
- package/dist/query/lower.js.map +1 -1
- package/dist/query/predicate.d.ts +10 -9
- package/dist/query/predicate.d.ts.map +1 -1
- package/dist/query/predicate.js +2 -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 +26 -6
- package/dist/query/run.js.map +1 -1
- package/dist/query/scope.d.ts +100 -43
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +89 -30
- package/dist/query/scope.js.map +1 -1
- package/dist/query/select.d.ts +5 -5
- package/dist/query/select.d.ts.map +1 -1
- package/dist/relation.d.ts +29 -15
- package/dist/relation.d.ts.map +1 -1
- package/dist/relation.js +45 -17
- package/dist/relation.js.map +1 -1
- package/dist/schema.d.ts +41 -3
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +16 -2
- package/dist/schema.js.map +1 -1
- package/dist/spec.d.ts +10 -8
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js.map +1 -1
- package/dist/statements.d.ts +67 -31
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +97 -20
- package/dist/statements.js.map +1 -1
- package/package.json +2 -2
- package/src/closed.ts +214 -146
- package/src/db.ts +65 -10
- package/src/face.ts +169 -102
- package/src/fields.ts +97 -164
- package/src/index.ts +43 -18
- package/src/law.ts +519 -0
- package/src/lower.ts +36 -23
- package/src/marshal.ts +74 -7
- package/src/native.ts +6 -2
- package/src/query/atom.ts +155 -65
- package/src/query/lower.ts +572 -167
- package/src/query/predicate.ts +43 -33
- package/src/query/run.ts +26 -6
- package/src/query/scope.ts +161 -51
- package/src/query/select.ts +5 -5
- package/src/relation.ts +60 -26
- package/src/schema.ts +48 -7
- package/src/spec.ts +10 -8
- package/src/statements.ts +165 -46
package/README.md
CHANGED
|
@@ -4,6 +4,8 @@ Type-theoretic TypeScript SDK for the [bumbledb](https://github.com/bjornpagen/b
|
|
|
4
4
|
|
|
5
5
|
bumbledb models data as relations judged by statements (functionality, containment, cardinality) and queried with Datalog expressed as plain values — no SQL, no query-string parser. The SDK is a thin, fully typed surface over an in-process native engine (LMDB storage, MVCC snapshots, a single-writer witnessed write loop).
|
|
6
6
|
|
|
7
|
+
The surface is structural to the bone. Relation declarations are pure structure — kind, width, element, fresh, nothing else — and domains are never declared anywhere: **the laws type the columns**. `schema()` computes every field's equivalence class from the statement list itself, so the containments and mirrors you already write ARE the typing, at compile time and again at construction. Values stay bare (`bigint`, `string`, …); identity lives in the class the laws compute, not in a wrapper.
|
|
8
|
+
|
|
7
9
|
> **Research-grade, one platform.** This is a `0.x` release of an embedded engine under active development. It targets a single platform today (below), the API is not yet frozen across `0.x`, and the FFI ABI is pinned exactly per version. Treat it as an early adopter's tool, not a production datastore.
|
|
8
10
|
|
|
9
11
|
## Platform support
|
|
@@ -18,32 +20,51 @@ pnpm add @bjornpagen/bumbledb
|
|
|
18
20
|
|
|
19
21
|
## Quick start
|
|
20
22
|
|
|
21
|
-
Declare
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
Declare relations as pure structure, let the statement list type every column,
|
|
24
|
+
write facts through a transaction, and query with Datalog as values.
|
|
25
|
+
Everything is typed end to end — bare structural values in law-computed
|
|
26
|
+
classes, inferred query rows, and rejections that arrive as data rather than
|
|
27
|
+
exceptions.
|
|
24
28
|
|
|
25
29
|
```ts
|
|
26
|
-
import {
|
|
27
|
-
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
//
|
|
42
|
-
|
|
30
|
+
import { bool, closed, contained, Db, gt, type Infer, key, on, query, relation, schema, u64 } from "@bjornpagen/bumbledb"
|
|
31
|
+
|
|
32
|
+
// A closed relation: a sealed roster of axioms with typed payload columns.
|
|
33
|
+
// At the host surface a handle is its NAME — the string literal "DirectPass"
|
|
34
|
+
// is the one spelling, and closed columns type as the handle union.
|
|
35
|
+
const Kind = closed(
|
|
36
|
+
"Kind",
|
|
37
|
+
{ mastered: bool, rank: u64 },
|
|
38
|
+
{
|
|
39
|
+
DirectPass: { mastered: true, rank: 30n },
|
|
40
|
+
JudgedPass: { mastered: true, rank: 20n },
|
|
41
|
+
Failed: { mastered: false, rank: 10n }
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
// Relations are pure structure — no domain is declared anywhere.
|
|
46
|
+
// `u64.fresh` marks an engine-minted primary key.
|
|
47
|
+
const Attempt = relation("Attempt", { id: u64.fresh, kind: Kind.id })
|
|
48
|
+
const Certificate = relation("Certificate", { attempt: u64, kind: Kind.id })
|
|
49
|
+
|
|
50
|
+
// THE LAWS TYPE THE COLUMNS: schema() computes every field's class FROM this
|
|
51
|
+
// statement list — the containments are the typing. The last statement uses
|
|
52
|
+
// ψ-selection: a certificate may only ever cite a mastered kind.
|
|
53
|
+
const Review = schema("Review", { Kind, Attempt, Certificate }, [
|
|
54
|
+
contained(on(Attempt, "kind"), on(Kind, "id")),
|
|
55
|
+
key(Certificate, ["attempt"]),
|
|
56
|
+
contained(on(Certificate, "attempt"), on(Attempt, "id")),
|
|
57
|
+
contained(on(Certificate, "kind"), on(Kind.where({ mastered: true }), "id"))
|
|
58
|
+
])
|
|
59
|
+
|
|
60
|
+
const db = await Db.create("./review.db", Review)
|
|
61
|
+
|
|
62
|
+
// Write. The delta is judged against every statement at commit. A closed
|
|
63
|
+
// column takes the handle name — a wrong string is a compile error AND a
|
|
64
|
+
// marshal refusal.
|
|
43
65
|
const result = db.write((tx) => {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
tx.insert(Account, { holder: ada.id })
|
|
66
|
+
const attempt = tx.insert(Attempt, { kind: "DirectPass" }) // attempt.id minted, a bare bigint
|
|
67
|
+
tx.insert(Certificate, { attempt: attempt.id, kind: "DirectPass" })
|
|
47
68
|
})
|
|
48
69
|
|
|
49
70
|
// Rejection-as-data: no throw — a rejected commit is a typed value carrying
|
|
@@ -54,28 +75,55 @@ if (!result.ok) {
|
|
|
54
75
|
}
|
|
55
76
|
}
|
|
56
77
|
|
|
57
|
-
// Query: Datalog as values.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
78
|
+
// Query: Datalog as values. Vars are named and typed by the class of their
|
|
79
|
+
// first binding; params are typed by use; rows are typed from the select.
|
|
80
|
+
// `gt` is one of the free comparison exports.
|
|
81
|
+
const certifiedAbove = query(Review).rule((r) => {
|
|
82
|
+
const { a, k, rank } = r.vars("a", "k", "rank")
|
|
83
|
+
return r
|
|
84
|
+
.match(Certificate, { attempt: a, kind: k })
|
|
85
|
+
.match(Kind, { id: k, mastered: true, rank }) // ψ on the read side too
|
|
86
|
+
.where(gt(rank, r.param("floor")))
|
|
87
|
+
.select("a", "rank")
|
|
62
88
|
})
|
|
63
89
|
|
|
64
|
-
const prepared = db.prepare(
|
|
65
|
-
const rows = db.execute(prepared, {
|
|
90
|
+
const prepared = db.prepare(certifiedAbove)
|
|
91
|
+
const rows = db.execute(prepared, { floor: 15n }) // rows: { a: bigint; rank: bigint }[]
|
|
92
|
+
console.log(rows)
|
|
93
|
+
|
|
94
|
+
// Host dispatch over the sealed roster is native `switch` narrowing over
|
|
95
|
+
// the handle union ("DirectPass" | "JudgedPass" | "Failed") — exhaustive
|
|
96
|
+
// via `satisfies never`; the sealed axioms read back typed.
|
|
97
|
+
function describe(kind: Infer<typeof Kind.id>): string {
|
|
98
|
+
switch (kind) {
|
|
99
|
+
case "DirectPass":
|
|
100
|
+
case "JudgedPass":
|
|
101
|
+
return `mastered, rank ${Kind.axioms[kind].rank}`
|
|
102
|
+
case "Failed":
|
|
103
|
+
return "not mastered"
|
|
104
|
+
default:
|
|
105
|
+
return kind satisfies never
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
console.log(describe("JudgedPass")) // "mastered, rank 20"
|
|
66
109
|
```
|
|
67
110
|
|
|
111
|
+
Every `ts` fence in this README is extracted and type-checked against the
|
|
112
|
+
real surface by `test/readme.test.ts` — the examples cannot drift.
|
|
113
|
+
|
|
68
114
|
## Surface
|
|
69
115
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
- The `
|
|
73
|
-
- The
|
|
74
|
-
- The
|
|
116
|
+
The drizzle law governs this surface: the SDK's job at the host boundary is translation, not abstraction — every database idiom arrives as the modern TypeScript idiom for that concept, and the SDK never invents an operator where the language already has one.
|
|
117
|
+
|
|
118
|
+
- The structural type kernel — fields as pure structure (`bool`, `bytes`, `i64`, `u64`, `str`, `interval`, `span`), `relation()`, and `closed()` sealed rosters with typed axiom payloads. A closed reference's value type IS the handle union (`Infer` speaks it); dispatch is native `switch` narrowing with `satisfies never` exhaustiveness. Domains are never declared: `schema()` computes every field's class from the statement list.
|
|
119
|
+
- The statement algebra — `schema()`, `key`, `contained`, `mirrors`, `window`; faces via `on` (set membership is a plain array in `.where`); counts via `exactly`, `atLeast`, `atMost`, `between`, `none`; ψ-selection via `.where` on relations and closed rosters.
|
|
120
|
+
- The `Db` runtime — `Db.create`/`Db.open`, path-cached stores, transactions, typed violations, scoped snapshot reads, the witnessed write loop with `abandon`.
|
|
121
|
+
- The query surface — Datalog as values, `query(S).rule(r => ...)`: named vars, params typed by use, negation, aggregates, and the free comparison/connective exports (`eq`, `ne`, `lt`, `le`, `gt`, `ge`, `and`, `or`, `not`, `allen`/`ALLEN`, `pointIn`, `covers`); set membership at a closed field is a plain array in the match record (`r.match(Ticket, { priority: ["Normal", "Urgent"] })` — closed-only there: an ordinary field's membership is a bound `r.inSet` param); stratified recursion via `program()`; `db.prepare` as a plain value.
|
|
122
|
+
- The exhume surface — `Db.exhume`, the schema-independent read path: a store's self-described shapes and raw facts by name, with typed refusals (`ErrExhumeNoDescriptor`, `ErrExhumeFormatMismatch`, `ErrExhumeCorruption`).
|
|
75
123
|
|
|
76
124
|
## Cookbook
|
|
77
125
|
|
|
78
|
-
The engine cookbook's 29 modeling recipes, translated to this SDK's structural API: [COOKBOOK.md](./COOKBOOK.md).
|
|
126
|
+
The engine cookbook's 29 modeling recipes, translated to this SDK's structural API: [COOKBOOK.md](./COOKBOOK.md). Two referees hold it: `test/cookbook-doc.test.ts` extracts the document's own `ts` fences and type-checks them against the real surface (the doc itself cannot drift), and `test/cookbook.test.ts` runs compiled copies of the recipes — each schema admitted by the real engine, its fingerprint asserted against the cross-host goldens the Rust cookbook suite also pins, every query snippet lowered through `db.prepare`.
|
|
79
127
|
|
|
80
128
|
## Architecture
|
|
81
129
|
|
package/dist/closed.d.ts
CHANGED
|
@@ -1,22 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Closed relations (`docs/architecture/10-data-model.md` § closed
|
|
3
3
|
* relations): a vocabulary whose extension is declared in the schema — two
|
|
4
|
-
* tiers, one function.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* "
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
4
|
+
* tiers, one function. Bare tier: `closed("Kind", ["Checking",
|
|
5
|
+
* "Savings"])`. Payload tier: `closed("Sev", { pages: bool }, { Critical:
|
|
6
|
+
* { pages: true }, ... })` — one call, three arguments (the curried tier-2
|
|
7
|
+
* spelling is DELETED — canonical utterance): the axioms record IS the
|
|
8
|
+
* handle declaration, every handle carrying every column exactly once
|
|
9
|
+
* (type-enforced). At the host surface a handle is its NAME — a string
|
|
10
|
+
* literal of the roster's union (the drizzle law: translation, not
|
|
11
|
+
* abstraction; dispatch over a vocabulary is native `switch` narrowing, so
|
|
12
|
+
* no match operator is minted and no handle constants exist — the literal
|
|
13
|
+
* `"Checking"` is the ONE spelling). Handles are pure DATA, not properties
|
|
14
|
+
* of the value, so NO handle name is reserved: a vocabulary may legally
|
|
15
|
+
* contain handles named `match`, `where`, or `id` — the axioms record and
|
|
16
|
+
* the roster are their own namespaces. The value's whole surface: `name`;
|
|
17
|
+
* `id` — the field descriptor carrying the CLOSED LINKAGE (the roster —
|
|
18
|
+
* pure structure, no declared domain: the laws type the columns, and
|
|
19
|
+
* `schema()` names the id's generator class `"Kind.id"`) for other
|
|
20
|
+
* relations' field blocks (`kind: Kind.id`); `data` (the lowering
|
|
21
|
+
* carrier); `axioms` (payload readback, `Kind.axioms`); `columns` (the
|
|
22
|
+
* runtime twin of the `Cols` type parameter, which the face layer's
|
|
23
|
+
* structural wall reads); and — exactly when payload columns exist —
|
|
24
|
+
* `where()`, the ψ-selection surface (`Kind.where({ mastered: true })` as a
|
|
25
|
+
* face source), resolved through the ONE selection machine
|
|
26
|
+
* (`relation.ts::resolveSelection`); the bare tier has no payload columns
|
|
27
|
+
* to select on, so `.where` is absent there, at the type AND on the value.
|
|
28
|
+
* No fact type and no insert surface exist — closed relations are
|
|
29
|
+
* unwritable by construction: the value simply lacks the writable relation
|
|
30
|
+
* shape.
|
|
18
31
|
*/
|
|
19
32
|
import { type AnyField, type ClosedIdField, type Infer } from "#fields.ts";
|
|
33
|
+
import { type SelectionBinding, type SelectionInput } from "#relation.ts";
|
|
20
34
|
import type { LiteralSpec } from "#spec.ts";
|
|
21
35
|
/**
|
|
22
36
|
* A payload column of a closed relation: any field descriptor except a
|
|
@@ -25,6 +39,19 @@ import type { LiteralSpec } from "#spec.ts";
|
|
|
25
39
|
type PayloadField = Exclude<AnyField, {
|
|
26
40
|
readonly fresh: true;
|
|
27
41
|
}>;
|
|
42
|
+
/**
|
|
43
|
+
* A declared payload column BLOCK: name → descriptor, with `id`
|
|
44
|
+
* unspellable — the sealed shape mints the synthetic `id` itself (ordinal
|
|
45
|
+
* 0 of the matchable fields), so a declared column named `id` would be
|
|
46
|
+
* shadowed by the synthetic slot everywhere the shape resolves by name
|
|
47
|
+
* (`matchFieldsOf`, the projected face, `spec.rs`'s resolver). The wall is
|
|
48
|
+
* typed here and judged again at construction in {@link mintClosed} — the
|
|
49
|
+
* runtime twin for untyped callers, warmer and earlier than the engine's
|
|
50
|
+
* `DuplicateFieldName` at `Db.create`.
|
|
51
|
+
*/
|
|
52
|
+
type PayloadColumns = Record<string, PayloadField> & {
|
|
53
|
+
readonly id?: never;
|
|
54
|
+
};
|
|
28
55
|
/** One declared payload column: name plus its field descriptor. */
|
|
29
56
|
interface ClosedColumn {
|
|
30
57
|
readonly name: string;
|
|
@@ -67,36 +94,77 @@ type Axioms<Handles extends string, Cols extends Record<string, PayloadField>> =
|
|
|
67
94
|
interface ClosedCore<Name extends string, Handles extends string, Cols extends Record<string, PayloadField>> {
|
|
68
95
|
readonly name: Name;
|
|
69
96
|
/**
|
|
70
|
-
* The
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
97
|
+
* The closed reference descriptor: `kind: Kind.id` in another relation's
|
|
98
|
+
* field block is the reference through which handle literals become
|
|
99
|
+
* legal in that relation's selections. Pure structure plus the PRECISE
|
|
100
|
+
* roster (`ClosedIdField<Handles>` — the handle union is the field's
|
|
101
|
+
* value type under `Infer`); the referencing field's domain is law-born:
|
|
102
|
+
* `schema()` computes it from the declared containment (`"Kind.id"`, the
|
|
103
|
+
* generator class).
|
|
74
104
|
*/
|
|
75
|
-
readonly id: ClosedIdField
|
|
105
|
+
readonly id: ClosedIdField<Handles>;
|
|
76
106
|
readonly data: ClosedData;
|
|
77
107
|
/** Payload readback: handle to its declared column values, bare and structural. */
|
|
78
108
|
readonly axioms: Axioms<Handles, Cols>;
|
|
79
109
|
/**
|
|
80
|
-
* The declared payload columns, name →
|
|
110
|
+
* The declared payload columns, name → field descriptor — an HONEST
|
|
81
111
|
* frozen runtime record (the descriptors themselves, by identity), and
|
|
82
|
-
* the typed carrier a projected payload column's
|
|
112
|
+
* the typed carrier a projected payload column's structural shape is
|
|
83
113
|
* recovered through off the schema type (the face layer's
|
|
84
|
-
* `
|
|
114
|
+
* `ProjectedShape` reads it; `data.columns` carries the same
|
|
85
115
|
* descriptors in declaration order for the lowering).
|
|
86
116
|
*/
|
|
87
117
|
readonly columns: Cols;
|
|
88
|
-
/** The weld: declaration-order id back to its handle, or undefined beyond the roster. */
|
|
89
|
-
fromId(id: bigint): Handles | undefined;
|
|
90
118
|
}
|
|
91
119
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
120
|
+
* The `where()` argument of a closed relation: EXACTLY the relation
|
|
121
|
+
* surface's {@link SelectionInput}, over the declared payload columns — the
|
|
122
|
+
* ONE selection vocabulary, so a spelling change there (H3's membership
|
|
123
|
+
* arrays) flows through with no local change here. The synthetic `id` is
|
|
124
|
+
* deliberately unspellable ({@link PayloadColumns} refuses an `id` column):
|
|
125
|
+
* an id selection is spelled only as handle literals on the REFERENCING
|
|
126
|
+
* side (the canonical-utterance law).
|
|
96
127
|
*/
|
|
97
|
-
type
|
|
98
|
-
|
|
99
|
-
|
|
128
|
+
type ClosedSelectionInput<Cols extends Record<string, PayloadField>> = SelectionInput<Cols>;
|
|
129
|
+
/**
|
|
130
|
+
* A closed relation with a ψ selection applied — what `on()` consumes as a
|
|
131
|
+
* σ-carrying closed source (`on(Kind.where({ mastered: true }), "id")`).
|
|
132
|
+
* Deliberately the SAME discriminant shape as the ordinary `Selected`
|
|
133
|
+
* (`relation`/`selection` — `face.ts::faceParts` splits both by `"relation"
|
|
134
|
+
* in source`), and structurally UNMISTAKABLE for one: an `AnyClosed` lacks
|
|
135
|
+
* the relation shape (no `fields` record, no `RelationData`).
|
|
136
|
+
*/
|
|
137
|
+
interface SelectedClosed<Name extends string, Handles extends string, Cols extends Record<string, PayloadField>> {
|
|
138
|
+
readonly relation: Closed<Name, Handles, Cols>;
|
|
139
|
+
readonly selection: readonly SelectionBinding[];
|
|
140
|
+
}
|
|
141
|
+
/** Any ψ-selected closed relation value. */
|
|
142
|
+
interface AnySelectedClosed {
|
|
143
|
+
readonly relation: AnyClosed;
|
|
144
|
+
readonly selection: readonly SelectionBinding[];
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* The ψ-selection surface of a payload-tier closed value. The selection is
|
|
148
|
+
* resolved EAGERLY against the declared columns and lowered as-is — the SDK
|
|
149
|
+
* never pre-folds ψ into an id set: pass-through lowering is what the macro
|
|
150
|
+
* does, and the ENGINE folds against the sealed extension at validate
|
|
151
|
+
* (`compile_member_set`).
|
|
152
|
+
*/
|
|
153
|
+
interface ClosedSelectable<Name extends string, Handles extends string, Cols extends Record<string, PayloadField>> {
|
|
154
|
+
where(selection: ClosedSelectionInput<Cols>): SelectedClosed<Name, Handles, Cols>;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* A closed relation value: the core surface plus — exactly when payload
|
|
158
|
+
* columns exist — `where()` (the bare tier has nothing to select on, so
|
|
159
|
+
* the method is ABSENT there, not merely uncallable). NOTHING else:
|
|
160
|
+
* handles are data on the roster, never properties of the value (the
|
|
161
|
+
* handle constants, the match operator, and the id-to-handle weld died
|
|
162
|
+
* with the bigint era — dispatch is native `switch` narrowing over the
|
|
163
|
+
* handle union).
|
|
164
|
+
*/
|
|
165
|
+
type Closed<Name extends string, Handles extends string, Cols extends Record<string, PayloadField>> = [
|
|
166
|
+
keyof Cols
|
|
167
|
+
] extends [never] ? ClosedCore<Name, Handles, Cols> : ClosedCore<Name, Handles, Cols> & ClosedSelectable<Name, Handles, Cols>;
|
|
100
168
|
/** Any closed relation value, whatever its roster and columns. */
|
|
101
169
|
interface AnyClosed {
|
|
102
170
|
readonly name: string;
|
|
@@ -108,13 +176,18 @@ interface AnyClosed {
|
|
|
108
176
|
/** Bare tier: `closed("Kind", ["Checking", "Savings"])` — handles only. */
|
|
109
177
|
declare function closed<const Name extends string, const Handles extends readonly [string, ...string[]]>(name: Name, handles: Handles): Closed<Name, Handles[number], Record<never, never>>;
|
|
110
178
|
/**
|
|
111
|
-
* Payload tier: declared columns
|
|
112
|
-
* { mastered: bool }
|
|
113
|
-
* false } })`. The
|
|
114
|
-
*
|
|
115
|
-
*
|
|
179
|
+
* Payload tier: declared columns AND ground axioms, one call — `closed(
|
|
180
|
+
* "Grade", { mastered: bool }, { DirectPass: { mastered: true }, Failed:
|
|
181
|
+
* { mastered: false } })`. The curried tier-2 spelling is DELETED
|
|
182
|
+
* (canonical utterance): `Cols` infers from the column block, the handle
|
|
183
|
+
* set from the axioms record's keys (reverse mapped-type inference), and
|
|
184
|
+
* every row is contextually checked against the declared columns — a
|
|
185
|
+
* wrong-typed value errors ON its property. The axioms record's keys ARE
|
|
186
|
+
* the handles (declaration order = key order, integer-index names
|
|
187
|
+
* rejected); every row carries every column exactly once (type-enforced by
|
|
188
|
+
* {@link Axioms}).
|
|
116
189
|
*/
|
|
117
|
-
declare function closed<const Name extends string, const Cols extends
|
|
118
|
-
export type { AnyClosed, AxiomRow, Axioms, Closed, ClosedColumn, ClosedCore, ClosedData, ClosedRow, PayloadField };
|
|
190
|
+
declare function closed<const Name extends string, const Cols extends PayloadColumns, Handles extends string>(name: Name, columns: Cols, axioms: Axioms<Handles, Cols>): Closed<Name, Handles, Cols>;
|
|
191
|
+
export type { AnyClosed, AnySelectedClosed, AxiomRow, Axioms, Closed, ClosedColumn, ClosedCore, ClosedData, ClosedRow, ClosedSelectable, ClosedSelectionInput, PayloadField, SelectedClosed };
|
|
119
192
|
export { closed };
|
|
120
193
|
//# sourceMappingURL=closed.d.ts.map
|
package/dist/closed.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"closed.d.ts","sourceRoot":"","sources":["../src/closed.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"closed.d.ts","sourceRoot":"","sources":["../src/closed.ts"],"names":[],"mappings":"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"}
|