@rindle/client 0.1.0-rc.5
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/LICENSE +201 -0
- package/README.md +65 -0
- package/dist/ast.d.ts +83 -0
- package/dist/ast.d.ts.map +1 -0
- package/dist/ast.js +5 -0
- package/dist/ast.js.map +1 -0
- package/dist/compare.d.ts +17 -0
- package/dist/compare.d.ts.map +1 -0
- package/dist/compare.js +81 -0
- package/dist/compare.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/key.d.ts +2 -0
- package/dist/key.d.ts.map +1 -0
- package/dist/key.js +26 -0
- package/dist/key.js.map +1 -0
- package/dist/operators.d.ts +39 -0
- package/dist/operators.d.ts.map +1 -0
- package/dist/operators.js +45 -0
- package/dist/operators.js.map +1 -0
- package/dist/query.d.ts +280 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +348 -0
- package/dist/query.js.map +1 -0
- package/dist/schema.d.ts +111 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +92 -0
- package/dist/schema.js.map +1 -0
- package/dist/ssr.d.ts +73 -0
- package/dist/ssr.d.ts.map +1 -0
- package/dist/ssr.js +66 -0
- package/dist/ssr.js.map +1 -0
- package/dist/store.d.ts +90 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +225 -0
- package/dist/store.js.map +1 -0
- package/dist/types.d.ts +250 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +20 -0
- package/dist/types.js.map +1 -0
- package/dist/view.d.ts +88 -0
- package/dist/view.d.ts.map +1 -0
- package/dist/view.js +294 -0
- package/dist/view.js.map +1 -0
- package/package.json +36 -0
- package/src/ast.ts +94 -0
- package/src/compare.ts +85 -0
- package/src/index.ts +57 -0
- package/src/key.ts +23 -0
- package/src/operators.ts +68 -0
- package/src/query.ts +734 -0
- package/src/schema.ts +181 -0
- package/src/ssr.ts +115 -0
- package/src/store.ts +279 -0
- package/src/types.ts +234 -0
- package/src/view.ts +348 -0
package/dist/query.js
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
// The fluent, type-safe query builder. It accumulates state immutably and compiles to the
|
|
2
|
+
// Zero-wire {@link Ast} via `.ast()` (which the wasm `Db.query`/a remote server parses).
|
|
3
|
+
//
|
|
4
|
+
// Two runtime Proxies give the requested ergonomics (WASM-CLIENT-DESIGN.md §6):
|
|
5
|
+
// - `where` is callable (`where(or(...))`) AND a field proxy (`where.closed(false)`);
|
|
6
|
+
// - `where<Field>(…)` camelCase sugar (`whereClosed(false)`) is intercepted too.
|
|
7
|
+
// Both are fully typed via mapped types + template-literal keys.
|
|
8
|
+
import { stableKey } from "./key.js";
|
|
9
|
+
import { fieldCondition } from "./operators.js";
|
|
10
|
+
import { isRelationship, SCHEMA } from "./schema.js";
|
|
11
|
+
const STAMP_NAMED_QUERY = Symbol("rindle.stampNamedQuery");
|
|
12
|
+
function stampNamedQuery(query, name, args) {
|
|
13
|
+
const stamp = query[STAMP_NAMED_QUERY];
|
|
14
|
+
if (typeof stamp !== "function") {
|
|
15
|
+
throw new Error("defineQuery's build must return a Query built by newQueryBuilder/queries");
|
|
16
|
+
}
|
|
17
|
+
return stamp(name, args);
|
|
18
|
+
}
|
|
19
|
+
export function defineQuery(name, validateOrBuild, maybeBuild) {
|
|
20
|
+
const hasValidator = maybeBuild !== undefined;
|
|
21
|
+
const validate = (hasValidator ? validateOrBuild : (raw) => raw);
|
|
22
|
+
const build = (hasValidator ? maybeBuild : validateOrBuild);
|
|
23
|
+
const resolve = (rawArgs, ...ctx) => build(validate(rawArgs), ...ctx);
|
|
24
|
+
// The wire identity is (name, args) ONLY — ctx is never stamped, so it never crosses the wire.
|
|
25
|
+
const call = (args, ...ctx) => stampNamedQuery(build(validate(args), ...ctx), name, args ?? null);
|
|
26
|
+
return Object.assign(call, { queryName: name, resolve });
|
|
27
|
+
}
|
|
28
|
+
// ----------------------------- fragments (FRAGMENT-COMPOSITION-DESIGN.md, Phase 0) -----------------------------
|
|
29
|
+
const FRAGMENT_BRAND = Symbol("rindle.fragment");
|
|
30
|
+
/**
|
|
31
|
+
* Define a co-located, composable {@link Fragment}: a named selection over `table`. The returned
|
|
32
|
+
* value is callable (the `build` transform), so it threads through the existing `sub`/`Rels`
|
|
33
|
+
* spine — no GraphQL, no codegen, no schema change (design §3).
|
|
34
|
+
*
|
|
35
|
+
* ```ts
|
|
36
|
+
* const UserAvatar = defineFragment(schema.user, (f) => f.select("id", "name", "avatarUrl"));
|
|
37
|
+
* const CommentRow = defineFragment(schema.comment, (f) =>
|
|
38
|
+
* f.select("id", "body", "authorId")
|
|
39
|
+
* .sub("author", schema.user, { parent: ["authorId"], child: ["id"] }, UserAvatar));
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export function defineFragment(table, build) {
|
|
43
|
+
const frag = (q) => build(q);
|
|
44
|
+
return Object.assign(frag, { table, [FRAGMENT_BRAND]: true });
|
|
45
|
+
}
|
|
46
|
+
/** Runtime guard: is `v` a {@link Fragment} (a `defineFragment` value, not a plain build fn)? */
|
|
47
|
+
export function isFragment(v) {
|
|
48
|
+
return typeof v === "function" && v[FRAGMENT_BRAND] === true;
|
|
49
|
+
}
|
|
50
|
+
function emptyState(table) {
|
|
51
|
+
return { table, wheres: [], orderBy: [], related: [], one: false };
|
|
52
|
+
}
|
|
53
|
+
function compile(s) {
|
|
54
|
+
const ast = { table: s.table };
|
|
55
|
+
if (s.alias !== undefined)
|
|
56
|
+
ast.alias = s.alias;
|
|
57
|
+
if (s.wheres.length === 1)
|
|
58
|
+
ast.where = s.wheres[0];
|
|
59
|
+
else if (s.wheres.length > 1)
|
|
60
|
+
ast.where = { type: "and", conditions: s.wheres };
|
|
61
|
+
if (s.related.length > 0)
|
|
62
|
+
ast.related = s.related;
|
|
63
|
+
if (s.start !== undefined)
|
|
64
|
+
ast.start = s.start;
|
|
65
|
+
if (s.orderBy.length > 0)
|
|
66
|
+
ast.orderBy = s.orderBy;
|
|
67
|
+
if (s.limit !== undefined)
|
|
68
|
+
ast.limit = s.limit;
|
|
69
|
+
if (s.one)
|
|
70
|
+
ast.one = true;
|
|
71
|
+
if (s.select && s.select.length > 0)
|
|
72
|
+
ast.select = s.select;
|
|
73
|
+
return ast;
|
|
74
|
+
}
|
|
75
|
+
/** Build a child AST for `sub`/`exists`: a fresh child query, the optional `build`, compiled. */
|
|
76
|
+
function childAst(child, build) {
|
|
77
|
+
const cm = child[SCHEMA];
|
|
78
|
+
let cq = makeQuery(cm, emptyState(cm.name));
|
|
79
|
+
if (build)
|
|
80
|
+
cq = build(cq);
|
|
81
|
+
return cq.ast();
|
|
82
|
+
}
|
|
83
|
+
/** Resolve the two `sub`/`countAs`/`exists` call shapes to a common `{ child, corr, build }`:
|
|
84
|
+
* either a named {@link Relationship} (`(rel, build?)`) or an explicit `(child, corr, build?)`. */
|
|
85
|
+
function resolveCorrelated(a, b, c) {
|
|
86
|
+
if (isRelationship(a)) {
|
|
87
|
+
return {
|
|
88
|
+
child: a.child,
|
|
89
|
+
corr: { parent: [...a.correlation.parent], child: [...a.correlation.child] },
|
|
90
|
+
build: b,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
child: a,
|
|
95
|
+
corr: b,
|
|
96
|
+
build: c,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
// ----------------------------- the merge pass (`include`, FRAGMENT-COMPOSITION-DESIGN §5) -----------
|
|
100
|
+
//
|
|
101
|
+
// `include(fragment)` folds a fragment's selection into the CURRENT node (same table). The merge is
|
|
102
|
+
// canonical (sorted) so include order is irrelevant — `q.include(A).include(B)` and
|
|
103
|
+
// `q.include(B).include(A)` compile to byte-identical ASTs → one `viewKey` → one materialization
|
|
104
|
+
// (§10.5). Two fragments that spread the same relationship `alias` are merged recursively; if they
|
|
105
|
+
// disagree on what rows that edge selects (correlation / table / where / orderBy / limit / paging /
|
|
106
|
+
// aggregate), that is an unresolvable conflict and we throw (§10.2).
|
|
107
|
+
function uniqSort(cols) {
|
|
108
|
+
return [...new Set(cols)].sort();
|
|
109
|
+
}
|
|
110
|
+
/** Merge two same-node *fragment* selections: an empty (absent) `select` means "all columns", so
|
|
111
|
+
* merging "all" with anything stays "all" (§5). Both sides here are fragment-contributed. */
|
|
112
|
+
function mergeNestedSelect(a, b) {
|
|
113
|
+
if (a === undefined || a.length === 0 || b === undefined || b.length === 0)
|
|
114
|
+
return undefined;
|
|
115
|
+
return uniqSort([...a, ...b]);
|
|
116
|
+
}
|
|
117
|
+
/** Merge a fragment's `select` into the ROOTING query's `select`. A pure **union** — this mirrors
|
|
118
|
+
* the type level (`Sel | FSel`, where a fragment that selects nothing contributes `never`) and keeps
|
|
119
|
+
* `q.include(Frag)` equivalent to applying `Frag(q)`. An absent `select` (on either side) means
|
|
120
|
+
* "contributes no columns", NOT "all columns" — so a relationship-only fragment (e.g. an edge that
|
|
121
|
+
* just `sub`s, no root columns) doesn't blow the projection open. The result is "all columns" (a
|
|
122
|
+
* dropped `select`) only when nothing anywhere selected, i.e. the union is empty. (This differs from
|
|
123
|
+
* {@link mergeNestedSelect}: a *nested* same-alias child is an INTERSECTION of row types at the
|
|
124
|
+
* type level — `Proj<A> & Proj<B>` — so there a no-select side, meaning "all child columns", wins.) */
|
|
125
|
+
function mergeRootSelect(baseSel, fragSel) {
|
|
126
|
+
const union = uniqSort([...(baseSel ?? []), ...(fragSel ?? [])]);
|
|
127
|
+
return union.length === 0 ? undefined : union;
|
|
128
|
+
}
|
|
129
|
+
function aliasOf(csq) {
|
|
130
|
+
return csq.subquery.alias ?? "";
|
|
131
|
+
}
|
|
132
|
+
/** A canonical key over everything that defines *which* rows a related edge yields — the fields
|
|
133
|
+
* two same-alias spreads must AGREE on (select + related are merged, so they're excluded). */
|
|
134
|
+
function edgeShapeKey(csq) {
|
|
135
|
+
const sq = csq.subquery;
|
|
136
|
+
return stableKey({
|
|
137
|
+
correlation: csq.correlation,
|
|
138
|
+
system: csq.system,
|
|
139
|
+
table: sq.table,
|
|
140
|
+
where: sq.where,
|
|
141
|
+
orderBy: sq.orderBy,
|
|
142
|
+
limit: sq.limit,
|
|
143
|
+
start: sq.start,
|
|
144
|
+
one: sq.one,
|
|
145
|
+
aggregate: sq.aggregate,
|
|
146
|
+
aggregatePrecomputed: sq.aggregatePrecomputed,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
/** Merge the `select` + nested `related` of two same-alias subqueries (callers verified the edge
|
|
150
|
+
* shape agrees). Returns a canonical (sorted) AST, omitting empty `select`/`related` like compile. */
|
|
151
|
+
function mergeSubqueryAst(base, frag) {
|
|
152
|
+
const out = { ...base };
|
|
153
|
+
const select = mergeNestedSelect(base.select, frag.select);
|
|
154
|
+
if (select === undefined)
|
|
155
|
+
delete out.select;
|
|
156
|
+
else
|
|
157
|
+
out.select = select;
|
|
158
|
+
const related = mergeRelatedLists(base.related ?? [], frag.related ?? []);
|
|
159
|
+
if (related.length === 0)
|
|
160
|
+
delete out.related;
|
|
161
|
+
else
|
|
162
|
+
out.related = related;
|
|
163
|
+
return out;
|
|
164
|
+
}
|
|
165
|
+
/** Merge two related lists by `alias`: same alias ⇒ recurse (after an edge-shape agreement check);
|
|
166
|
+
* distinct aliases ⇒ kept side by side. Output is ordered by alias (canonical, §10.5). */
|
|
167
|
+
function mergeRelatedLists(base, add) {
|
|
168
|
+
const byAlias = new Map();
|
|
169
|
+
for (const csq of base)
|
|
170
|
+
byAlias.set(aliasOf(csq), csq);
|
|
171
|
+
for (const csq of add) {
|
|
172
|
+
const alias = aliasOf(csq);
|
|
173
|
+
const existing = byAlias.get(alias);
|
|
174
|
+
if (existing === undefined) {
|
|
175
|
+
byAlias.set(alias, csq);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (edgeShapeKey(existing) !== edgeShapeKey(csq)) {
|
|
179
|
+
throw new Error(`include(): conflicting definitions for relationship "${alias}" — two fragments spread the ` +
|
|
180
|
+
`same alias with different correlation/table/where/orderBy/limit. Give them distinct aliases ` +
|
|
181
|
+
`or align them (FRAGMENT-COMPOSITION-DESIGN §10.2).`);
|
|
182
|
+
}
|
|
183
|
+
byAlias.set(alias, { ...existing, subquery: mergeSubqueryAst(existing.subquery, csq.subquery) });
|
|
184
|
+
}
|
|
185
|
+
return [...byAlias.values()].sort((a, b) => {
|
|
186
|
+
const x = aliasOf(a);
|
|
187
|
+
const y = aliasOf(b);
|
|
188
|
+
return x < y ? -1 : x > y ? 1 : 0;
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
/** Fold an `include`d fragment's compiled AST into the current builder {@link State}. An included
|
|
192
|
+
* fragment contributes only `select` + nested relationships; it may not constrain the node's row
|
|
193
|
+
* set / window — adding a root `where` (§10.3) or `orderBy`/`limit`/`start`/`one` throws. */
|
|
194
|
+
function mergeIncludedFragment(s, frag) {
|
|
195
|
+
if (frag.where !== undefined) {
|
|
196
|
+
throw new Error("include(): a fragment may not add a root `where` — only the rooting query filters " +
|
|
197
|
+
"(FRAGMENT-COMPOSITION-DESIGN §10.3).");
|
|
198
|
+
}
|
|
199
|
+
if (frag.orderBy !== undefined || frag.limit !== undefined || frag.start !== undefined || frag.one) {
|
|
200
|
+
throw new Error("include(): a fragment may not set a root `orderBy`/`limit`/`start`/`one` — it contributes only " +
|
|
201
|
+
"`select` and nested relationships (those define the node's window, which is the rooting query's job).");
|
|
202
|
+
}
|
|
203
|
+
const select = mergeRootSelect(s.select, frag.select);
|
|
204
|
+
const next = { ...s, related: mergeRelatedLists(s.related, frag.related ?? []) };
|
|
205
|
+
if (select === undefined)
|
|
206
|
+
delete next.select;
|
|
207
|
+
else
|
|
208
|
+
next.select = select;
|
|
209
|
+
return next;
|
|
210
|
+
}
|
|
211
|
+
// Internal: the runtime is untyped (Proxy magic); the public `Query<C,Rels>` type is the contract.
|
|
212
|
+
function makeQuery(meta, s, onMat, named) {
|
|
213
|
+
const next = (patch) => makeQuery(meta, { ...s, ...patch }, onMat, named);
|
|
214
|
+
const applyField = (field, arg) => next({ wheres: [...s.wheres, fieldCondition(field, arg)] });
|
|
215
|
+
let proxy;
|
|
216
|
+
const base = {
|
|
217
|
+
name: named?.name,
|
|
218
|
+
args: named?.args,
|
|
219
|
+
where: (cond) => next({ wheres: [...s.wheres, cond] }),
|
|
220
|
+
orderBy: (col, dir) => next({ orderBy: [...s.orderBy, [col, dir]] }),
|
|
221
|
+
select: (...cols) => next({ select: [...(s.select ?? []), ...cols] }),
|
|
222
|
+
limit: (n) => next({ limit: n }),
|
|
223
|
+
start: (cursor, opts) => next({ start: { row: { ...cursor }, exclusive: opts?.exclusive ?? false } }),
|
|
224
|
+
one: () => next({ one: true }),
|
|
225
|
+
include: (fragment) => {
|
|
226
|
+
const fragTable = fragment.table;
|
|
227
|
+
if (fragTable[SCHEMA].name !== s.table) {
|
|
228
|
+
throw new Error(`include(): the fragment is over "${fragTable[SCHEMA].name}" but this query is over "${s.table}". ` +
|
|
229
|
+
`include() merges a fragment into the SAME table — use sub() to nest a different table.`);
|
|
230
|
+
}
|
|
231
|
+
const fragAst = childAst(fragTable, fragment);
|
|
232
|
+
return makeQuery(meta, mergeIncludedFragment(s, fragAst), onMat, named);
|
|
233
|
+
},
|
|
234
|
+
sub: (alias, childOrRel, b, c) => {
|
|
235
|
+
const { child, corr, build } = resolveCorrelated(childOrRel, b, c);
|
|
236
|
+
const sub = childAst(child, build);
|
|
237
|
+
sub.alias = alias;
|
|
238
|
+
const csq = {
|
|
239
|
+
correlation: { parentField: corr.parent, childField: corr.child },
|
|
240
|
+
subquery: sub,
|
|
241
|
+
};
|
|
242
|
+
return next({ related: [...s.related, csq] });
|
|
243
|
+
},
|
|
244
|
+
countAs: (alias, childOrRel, b, c) => {
|
|
245
|
+
// Same correlated-child mechanism as `sub`, but mark the child a `count` aggregate:
|
|
246
|
+
// the builder lowers it to a scalar-projected singular relationship (REDUCE-DESIGN §9).
|
|
247
|
+
const { child, corr, build } = resolveCorrelated(childOrRel, b, c);
|
|
248
|
+
const sub = childAst(child, build);
|
|
249
|
+
sub.alias = alias;
|
|
250
|
+
sub.aggregate = "count";
|
|
251
|
+
const csq = {
|
|
252
|
+
correlation: { parentField: corr.parent, childField: corr.child },
|
|
253
|
+
subquery: sub,
|
|
254
|
+
};
|
|
255
|
+
return next({ related: [...s.related, csq] });
|
|
256
|
+
},
|
|
257
|
+
ast: () => compile(s),
|
|
258
|
+
materialize: () => {
|
|
259
|
+
if (!onMat)
|
|
260
|
+
throw new Error("materialize() requires a Store — use store.query.<table>");
|
|
261
|
+
return onMat(proxy);
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
// `where` is callable AND a field proxy.
|
|
265
|
+
const whereProxy = new Proxy(base.where, {
|
|
266
|
+
get(_t, prop) {
|
|
267
|
+
if (typeof prop === "string")
|
|
268
|
+
return (arg) => applyField(prop, arg);
|
|
269
|
+
return undefined;
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
proxy = new Proxy(base, {
|
|
273
|
+
get(target, prop) {
|
|
274
|
+
if (prop === "where")
|
|
275
|
+
return whereProxy;
|
|
276
|
+
if (prop === STAMP_NAMED_QUERY)
|
|
277
|
+
return (name, args) => makeQuery(meta, s, onMat, { name, args });
|
|
278
|
+
if (typeof prop === "string" && prop.length > 5 && prop.startsWith("where")) {
|
|
279
|
+
const field = prop[5].toLowerCase() + prop.slice(6);
|
|
280
|
+
return (arg) => applyField(field, arg);
|
|
281
|
+
}
|
|
282
|
+
return target[prop];
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
return proxy;
|
|
286
|
+
}
|
|
287
|
+
function existsImpl(child, corr, build, op,
|
|
288
|
+
// `"permissions"` ⇒ a server-only, non-syncing gate (`exists_noSync`): the normalized
|
|
289
|
+
// serializer prunes its witnesses so the permission table is never synced to the client.
|
|
290
|
+
system, opts) {
|
|
291
|
+
const sub = childAst(child, build);
|
|
292
|
+
sub.alias = child[SCHEMA].name;
|
|
293
|
+
const related = {
|
|
294
|
+
correlation: { parentField: corr.parent, childField: corr.child },
|
|
295
|
+
subquery: sub,
|
|
296
|
+
};
|
|
297
|
+
if (system)
|
|
298
|
+
related.system = system;
|
|
299
|
+
return {
|
|
300
|
+
type: "correlatedSubquery",
|
|
301
|
+
op,
|
|
302
|
+
related,
|
|
303
|
+
...(opts?.scalar ? { scalar: true } : {}),
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
export function exists(a, b, c, d) {
|
|
307
|
+
const { child, corr, build } = resolveCorrelated(a, b, c);
|
|
308
|
+
const opts = (isRelationship(a) ? c : d);
|
|
309
|
+
return existsImpl(child, corr, build, "EXISTS", undefined, opts);
|
|
310
|
+
}
|
|
311
|
+
export function notExists(a, b, c, d) {
|
|
312
|
+
const { child, corr, build } = resolveCorrelated(a, b, c);
|
|
313
|
+
const opts = (isRelationship(a) ? c : d);
|
|
314
|
+
return existsImpl(child, corr, build, "NOT EXISTS", undefined, opts);
|
|
315
|
+
}
|
|
316
|
+
export function existsNoSync(a, b, c) {
|
|
317
|
+
const { child, corr, build } = resolveCorrelated(a, b, c);
|
|
318
|
+
return existsImpl(child, corr, build, "EXISTS", "permissions");
|
|
319
|
+
}
|
|
320
|
+
export function notExistsNoSync(a, b, c) {
|
|
321
|
+
const { child, corr, build } = resolveCorrelated(a, b, c);
|
|
322
|
+
return existsImpl(child, corr, build, "NOT EXISTS", "permissions");
|
|
323
|
+
}
|
|
324
|
+
/** A typed query entry over a schema: `queries(schema).issue.where.closed(false)…`. */
|
|
325
|
+
export function queries(schema, onMaterialize) {
|
|
326
|
+
return new Proxy({}, {
|
|
327
|
+
get(_t, prop) {
|
|
328
|
+
if (typeof prop !== "string")
|
|
329
|
+
return undefined;
|
|
330
|
+
// Framework/JS introspection probes are never table names — return undefined instead of
|
|
331
|
+
// throwing so the query root (and a `Store` carrying it) can be safely enumerated by code
|
|
332
|
+
// that inspects objects. React 19's dev-mode prop diffing reads `$$typeof` on every prop
|
|
333
|
+
// value; `then` is the thenable check; `toJSON` is JSON serialization. A real typo'd table
|
|
334
|
+
// (`store.query.isue`) is a plain identifier and still throws below.
|
|
335
|
+
if (prop[0] === "$" || prop === "then" || prop === "toJSON")
|
|
336
|
+
return undefined;
|
|
337
|
+
const meta = schema.tables[prop];
|
|
338
|
+
if (!meta)
|
|
339
|
+
throw new Error(`unknown table: ${prop}`);
|
|
340
|
+
return makeQuery(meta, emptyState(meta.name), onMaterialize);
|
|
341
|
+
},
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
/** A schema-bound query-builder factory for portable client/server query definitions. */
|
|
345
|
+
export function newQueryBuilder(schema) {
|
|
346
|
+
return queries(schema);
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { Arg, Cond } from "./operators.ts";
|
|
2
|
+
import type { ColType } from "./types.ts";
|
|
3
|
+
/** A column descriptor. `type` drives the comparator + JSON parsing; `__t` is a phantom. */
|
|
4
|
+
export interface Col<T> {
|
|
5
|
+
readonly type: ColType;
|
|
6
|
+
readonly __t?: T;
|
|
7
|
+
}
|
|
8
|
+
export type ColT<X> = X extends Col<infer T> ? T : never;
|
|
9
|
+
export type AnyCols = Record<string, Col<unknown>>;
|
|
10
|
+
export type RowOf<C extends AnyCols> = {
|
|
11
|
+
[K in keyof C]: ColT<C[K]>;
|
|
12
|
+
};
|
|
13
|
+
export declare const string: () => Col<string>;
|
|
14
|
+
export declare const number: () => Col<number>;
|
|
15
|
+
export declare const boolean: () => Col<boolean>;
|
|
16
|
+
export declare const json: <T = unknown>() => Col<T>;
|
|
17
|
+
/** Metadata key on a {@link TableDef} (a `unique symbol`, so no column name collides). */
|
|
18
|
+
export declare const SCHEMA: unique symbol;
|
|
19
|
+
export interface TableMeta<N extends string = string, C extends AnyCols = AnyCols> {
|
|
20
|
+
readonly name: N;
|
|
21
|
+
readonly columns: C;
|
|
22
|
+
readonly primaryKey: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
export type TableDef<N extends string, C extends AnyCols> = {
|
|
25
|
+
readonly [SCHEMA]: TableMeta<N, C>;
|
|
26
|
+
} & {
|
|
27
|
+
readonly [K in keyof C]: (arg: Arg<ColT<C[K]>>) => Cond<RowOf<C>>;
|
|
28
|
+
};
|
|
29
|
+
/** Any table, for positions that only read its metadata. The field-factory part of a
|
|
30
|
+
* `TableDef` is invariant in `C`, so callers constrain on the `[SCHEMA]` meta only — to
|
|
31
|
+
* which every concrete `TableDef<N, C>` is assignable. */
|
|
32
|
+
export type TableLike<C extends AnyCols> = {
|
|
33
|
+
readonly [SCHEMA]: TableMeta<string, C>;
|
|
34
|
+
};
|
|
35
|
+
export type AnyTable = TableLike<AnyCols>;
|
|
36
|
+
/** The row type of a table definition: `Row<typeof issue>` → `{ id: string; … }`. The
|
|
37
|
+
* whole-table ergonomic form of {@link RowOf}, so app code derives its row interfaces from
|
|
38
|
+
* the schema instead of hand-maintaining a parallel twin. */
|
|
39
|
+
export type Row<T extends AnyTable> = RowOf<T[typeof SCHEMA]["columns"]>;
|
|
40
|
+
/** `table("issue").columns({ id: string(), … }).primaryKey("id")`. */
|
|
41
|
+
export declare function table<N extends string>(name: N): {
|
|
42
|
+
columns<C extends AnyCols>(cols: C): {
|
|
43
|
+
primaryKey<K extends keyof C & string>(...keys: K[]): TableDef<N, C>;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
/** Read a table's metadata (columns / PK / name). */
|
|
47
|
+
export declare function tableMeta(t: AnyTable): TableMeta;
|
|
48
|
+
/** name → columns, derived from the tables array (for typing `store.query.<table>`). */
|
|
49
|
+
export type SchemaOf<T extends readonly AnyTable[]> = {
|
|
50
|
+
[E in T[number] as E[typeof SCHEMA]["name"]]: E[typeof SCHEMA]["columns"];
|
|
51
|
+
};
|
|
52
|
+
/** name → columns, the resolved schema map carried in the {@link Schema} type. */
|
|
53
|
+
export type ColsMap = Record<string, AnyCols>;
|
|
54
|
+
export interface Schema<S extends ColsMap = ColsMap> {
|
|
55
|
+
readonly tables: Readonly<Record<string, TableMeta>>;
|
|
56
|
+
/** Phantom carrying name→columns for query-root inference (never read at runtime). */
|
|
57
|
+
readonly __cols: S;
|
|
58
|
+
}
|
|
59
|
+
export declare function createSchema<const T extends readonly AnyTable[]>(opts: {
|
|
60
|
+
tables: T;
|
|
61
|
+
}): Schema<SchemaOf<T>>;
|
|
62
|
+
/** Brand on a {@link Relationship} value (a `unique symbol`, distinct from a {@link TableDef}). */
|
|
63
|
+
declare const RELATIONSHIP_BRAND: unique symbol;
|
|
64
|
+
/**
|
|
65
|
+
* A reusable, typed JOIN between two tables — the correlation declared once (design §4). Built with
|
|
66
|
+
* {@link rel}; parameterized by the parent columns `PC` (so a `sub` checks the relationship belongs to
|
|
67
|
+
* the query's table) and the child columns `CC` (which flow into the nested result type). Pass it to
|
|
68
|
+
* `sub`/`countAs`/`exists` in place of an explicit `child` + `{ parent, child }` correlation.
|
|
69
|
+
*/
|
|
70
|
+
export interface Relationship<PC extends AnyCols, CC extends AnyCols> {
|
|
71
|
+
/** The child table the relationship points at. */
|
|
72
|
+
readonly child: TableLike<CC>;
|
|
73
|
+
/** Correlation keys: `parent[i]` (a parent column) joins to `child[i]` (a child column). */
|
|
74
|
+
readonly correlation: {
|
|
75
|
+
readonly parent: readonly string[];
|
|
76
|
+
readonly child: readonly string[];
|
|
77
|
+
};
|
|
78
|
+
/** Phantom binding the parent columns so `Query<C>.sub(alias, rel)` rejects a rel for another table. */
|
|
79
|
+
readonly __parent?: PC;
|
|
80
|
+
readonly [RELATIONSHIP_BRAND]: true;
|
|
81
|
+
}
|
|
82
|
+
/** Any relationship, for positions that only read its correlation / child table. */
|
|
83
|
+
export type AnyRelationship = Relationship<AnyCols, AnyCols>;
|
|
84
|
+
/**
|
|
85
|
+
* Declare a relationship once: `rel(issue, user, { ownerId: "id" })` means `issue.ownerId → user.id`.
|
|
86
|
+
* `mapping` is `{ [parentColumn]: childColumn }` (a composite join is multiple entries). The `parent`
|
|
87
|
+
* table is used only to type-check the keys; pass the result to `sub`/`countAs`/`exists`.
|
|
88
|
+
*/
|
|
89
|
+
export declare function rel<PC extends AnyCols, CC extends AnyCols>(_parent: TableLike<PC>, child: TableLike<CC>, mapping: Partial<Record<keyof PC & string, keyof CC & string>>): Relationship<PC, CC>;
|
|
90
|
+
/** A typed registry of named {@link Relationship}s — `defineRelationships({ issueOwner: rel(...) })`.
|
|
91
|
+
* A thin identity helper that names the bag and constrains its values; the keys are yours to choose. */
|
|
92
|
+
export declare function defineRelationships<R extends Record<string, AnyRelationship>>(rels: R): R;
|
|
93
|
+
/** Runtime guard: is `v` a {@link Relationship} value (not a table or a plain object)? */
|
|
94
|
+
export declare function isRelationship(v: unknown): v is AnyRelationship;
|
|
95
|
+
/** The `SchemaSpec` (`columns` + `primaryKey` indices) the wasm `Db.registerTable` wants. */
|
|
96
|
+
export declare function tableSpec(meta: TableMeta): {
|
|
97
|
+
columns: string[];
|
|
98
|
+
primaryKey: number[];
|
|
99
|
+
};
|
|
100
|
+
/** The client's per-table flat schema (name + column order + PK indices), the shape a
|
|
101
|
+
* normalized `hello` advertises (NORMALIZED-CHANGES-DESIGN.md §3). Used to validate a
|
|
102
|
+
* server hello against the CLIENT's own typed schema so a column-order / PK skew is caught
|
|
103
|
+
* instead of silently transposing positional cells (CRIT#4). Sorted by name for stable
|
|
104
|
+
* ordering. */
|
|
105
|
+
export declare function normalizedTableSchemas<S extends ColsMap>(schema: Schema<S>): {
|
|
106
|
+
name: string;
|
|
107
|
+
columns: string[];
|
|
108
|
+
primaryKey: number[];
|
|
109
|
+
}[];
|
|
110
|
+
export {};
|
|
111
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// The typed schema: `table("issue").columns({...}).primaryKey("id")` + `createSchema`.
|
|
2
|
+
//
|
|
3
|
+
// A table definition doubles as a field→condition factory (a runtime Proxy):
|
|
4
|
+
// `issue.priority(gt(8))` produces a `Cond<RowOf<issue>>`. THAT is where the table type is
|
|
5
|
+
// bound — which is why `or`/`exists` are plain top-level functions, no closure needed
|
|
6
|
+
// (WASM-CLIENT-DESIGN.md §6). Schema metadata is stored under a `unique symbol` key so it
|
|
7
|
+
// never collides with a column name.
|
|
8
|
+
import { fieldCondition } from "./operators.js";
|
|
9
|
+
export const string = () => ({ type: "string" });
|
|
10
|
+
export const number = () => ({ type: "number" });
|
|
11
|
+
export const boolean = () => ({ type: "boolean" });
|
|
12
|
+
export const json = () => ({ type: "json" });
|
|
13
|
+
/** Metadata key on a {@link TableDef} (a `unique symbol`, so no column name collides). */
|
|
14
|
+
export const SCHEMA = Symbol("rindle.schema");
|
|
15
|
+
/** `table("issue").columns({ id: string(), … }).primaryKey("id")`. */
|
|
16
|
+
export function table(name) {
|
|
17
|
+
return {
|
|
18
|
+
columns(cols) {
|
|
19
|
+
return {
|
|
20
|
+
primaryKey(...keys) {
|
|
21
|
+
return makeTableDef({ name, columns: cols, primaryKey: keys });
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function makeTableDef(meta) {
|
|
28
|
+
return new Proxy({}, {
|
|
29
|
+
get(_target, prop) {
|
|
30
|
+
if (prop === SCHEMA)
|
|
31
|
+
return meta;
|
|
32
|
+
if (typeof prop === "string")
|
|
33
|
+
return (arg) => fieldCondition(prop, arg);
|
|
34
|
+
return undefined;
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/** Read a table's metadata (columns / PK / name). */
|
|
39
|
+
export function tableMeta(t) {
|
|
40
|
+
return t[SCHEMA];
|
|
41
|
+
}
|
|
42
|
+
export function createSchema(opts) {
|
|
43
|
+
const tables = {};
|
|
44
|
+
for (const t of opts.tables) {
|
|
45
|
+
const m = t[SCHEMA];
|
|
46
|
+
tables[m.name] = m;
|
|
47
|
+
}
|
|
48
|
+
return { tables };
|
|
49
|
+
}
|
|
50
|
+
// ----------------------------- relationships (FRAGMENT-COMPOSITION-DESIGN §4.2, named edges) -----
|
|
51
|
+
//
|
|
52
|
+
// A relationship is the correlation (`parent.col → child.col`) declared ONCE as a value, so `sub`,
|
|
53
|
+
// `countAs`, and `exists` don't restate `{ parent, child }` keys at every spread/filter site. It is a
|
|
54
|
+
// plain typed value (not registered on the schema), passed where `(child, corr)` used to go.
|
|
55
|
+
/** Brand on a {@link Relationship} value (a `unique symbol`, distinct from a {@link TableDef}). */
|
|
56
|
+
const RELATIONSHIP_BRAND = Symbol("rindle.relationship");
|
|
57
|
+
/**
|
|
58
|
+
* Declare a relationship once: `rel(issue, user, { ownerId: "id" })` means `issue.ownerId → user.id`.
|
|
59
|
+
* `mapping` is `{ [parentColumn]: childColumn }` (a composite join is multiple entries). The `parent`
|
|
60
|
+
* table is used only to type-check the keys; pass the result to `sub`/`countAs`/`exists`.
|
|
61
|
+
*/
|
|
62
|
+
export function rel(_parent, child, mapping) {
|
|
63
|
+
const parent = Object.keys(mapping);
|
|
64
|
+
const childKeys = parent.map((k) => mapping[k]);
|
|
65
|
+
return { child, correlation: { parent, child: childKeys }, [RELATIONSHIP_BRAND]: true };
|
|
66
|
+
}
|
|
67
|
+
/** A typed registry of named {@link Relationship}s — `defineRelationships({ issueOwner: rel(...) })`.
|
|
68
|
+
* A thin identity helper that names the bag and constrains its values; the keys are yours to choose. */
|
|
69
|
+
export function defineRelationships(rels) {
|
|
70
|
+
return rels;
|
|
71
|
+
}
|
|
72
|
+
/** Runtime guard: is `v` a {@link Relationship} value (not a table or a plain object)? */
|
|
73
|
+
export function isRelationship(v) {
|
|
74
|
+
return typeof v === "object" && v !== null && v[RELATIONSHIP_BRAND] === true;
|
|
75
|
+
}
|
|
76
|
+
/** The `SchemaSpec` (`columns` + `primaryKey` indices) the wasm `Db.registerTable` wants. */
|
|
77
|
+
export function tableSpec(meta) {
|
|
78
|
+
const columns = Object.keys(meta.columns);
|
|
79
|
+
const primaryKey = meta.primaryKey.map((k) => columns.indexOf(k));
|
|
80
|
+
return { columns, primaryKey };
|
|
81
|
+
}
|
|
82
|
+
/** The client's per-table flat schema (name + column order + PK indices), the shape a
|
|
83
|
+
* normalized `hello` advertises (NORMALIZED-CHANGES-DESIGN.md §3). Used to validate a
|
|
84
|
+
* server hello against the CLIENT's own typed schema so a column-order / PK skew is caught
|
|
85
|
+
* instead of silently transposing positional cells (CRIT#4). Sorted by name for stable
|
|
86
|
+
* ordering. */
|
|
87
|
+
export function normalizedTableSchemas(schema) {
|
|
88
|
+
return Object.keys(schema.tables)
|
|
89
|
+
.sort()
|
|
90
|
+
.map((name) => ({ name, ...tableSpec(schema.tables[name]) }));
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,EAAE;AACF,6EAA6E;AAC7E,2FAA2F;AAC3F,sFAAsF;AACtF,0FAA0F;AAC1F,qCAAqC;AAGrC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAYhD,MAAM,CAAC,MAAM,MAAM,GAAG,GAAgB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC9D,MAAM,CAAC,MAAM,MAAM,GAAG,GAAgB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC9D,MAAM,CAAC,MAAM,OAAO,GAAG,GAAiB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AACjE,MAAM,CAAC,MAAM,IAAI,GAAG,GAAwB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AAElE,0FAA0F;AAC1F,MAAM,CAAC,MAAM,MAAM,GAAkB,MAAM,CAAC,eAAe,CAAC,CAAC;AA4B7D,sEAAsE;AACtE,MAAM,UAAU,KAAK,CAAmB,IAAO;IAC7C,OAAO;QACL,OAAO,CAAoB,IAAO;YAChC,OAAO;gBACL,UAAU,CAA6B,GAAG,IAAS;oBACjD,OAAO,YAAY,CAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvE,CAAC;aACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAsC,IAAqB;IAC9E,OAAO,IAAI,KAAK,CAAC,EAAsC,EAAE;QACvD,GAAG,CAAC,OAAO,EAAE,IAAI;YACf,IAAI,IAAI,KAAK,MAAM;gBAAE,OAAO,IAAI,CAAC;YACjC,IAAI,OAAO,IAAI,KAAK,QAAQ;gBAAE,OAAO,CAAC,GAAY,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACjF,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAA8B,CAAC;AAClC,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,SAAS,CAAC,CAAW;IACnC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AACnB,CAAC;AAgBD,MAAM,UAAU,YAAY,CAAsC,IAEjE;IACC,MAAM,MAAM,GAA8B,EAAE,CAAC;IAC7C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;QACpB,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,EAAE,MAAM,EAAyB,CAAC;AAC3C,CAAC;AAED,oGAAoG;AACpG,EAAE;AACF,mGAAmG;AACnG,sGAAsG;AACtG,6FAA6F;AAE7F,mGAAmG;AACnG,MAAM,kBAAkB,GAAkB,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAqBxE;;;;GAIG;AACH,MAAM,UAAU,GAAG,CACjB,OAAsB,EACtB,KAAoB,EACpB,OAA8D;IAE9D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAsB,CAAW,CAAC,CAAC;IAC/E,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,CAAC;AAC1F,CAAC;AAED;yGACyG;AACzG,MAAM,UAAU,mBAAmB,CAA4C,IAAO;IACpF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,cAAc,CAAC,CAAU;IACvC,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAK,CAA8B,CAAC,kBAAkB,CAAC,KAAK,IAAI,CAAC;AAC7G,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,SAAS,CAAC,IAAe;IACvC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;AACjC,CAAC;AAED;;;;gBAIgB;AAChB,MAAM,UAAU,sBAAsB,CACpC,MAAiB;IAEjB,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;SAC9B,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAClE,CAAC"}
|