@rindle/client 0.2.0 → 0.4.2
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/dist/ast.d.ts +11 -0
- package/dist/ast.d.ts.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/mutation-ops.d.ts +140 -0
- package/dist/mutation-ops.d.ts.map +1 -0
- package/dist/mutation-ops.js +60 -0
- package/dist/mutation-ops.js.map +1 -0
- package/dist/operators.d.ts +5 -0
- package/dist/operators.d.ts.map +1 -1
- package/dist/operators.js +5 -0
- package/dist/operators.js.map +1 -1
- package/dist/query.d.ts +65 -9
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +56 -1
- package/dist/query.js.map +1 -1
- package/dist/resolve.d.ts +40 -0
- package/dist/resolve.d.ts.map +1 -0
- package/dist/resolve.js +109 -0
- package/dist/resolve.js.map +1 -0
- package/dist/schema.d.ts +53 -5
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +65 -4
- package/dist/schema.js.map +1 -1
- package/dist/ssr.d.ts +14 -0
- package/dist/ssr.d.ts.map +1 -1
- package/dist/ssr.js +15 -0
- package/dist/ssr.js.map +1 -1
- package/dist/store.d.ts +47 -15
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +163 -25
- package/dist/store.js.map +1 -1
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/view.d.ts +43 -5
- package/dist/view.d.ts.map +1 -1
- package/dist/view.js +87 -22
- package/dist/view.js.map +1 -1
- package/package.json +1 -1
- package/src/ast.ts +11 -0
- package/src/index.ts +29 -1
- package/src/mutation-ops.ts +190 -0
- package/src/operators.ts +5 -0
- package/src/query.ts +142 -13
- package/src/resolve.ts +136 -0
- package/src/schema.ts +130 -5
- package/src/ssr.ts +21 -0
- package/src/store.ts +157 -34
- package/src/types.ts +35 -1
- package/src/view.ts +103 -22
package/dist/view.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ColType, FlatChange, ResultType, WireSchema } from "./types.ts";
|
|
1
|
+
import type { ColType, FlatChange, QueryId, ResultType, WireSchema } from "./types.ts";
|
|
2
2
|
/** Per-level column types (parallel to the WireSchema), used to JSON.parse json columns on
|
|
3
3
|
* projection. Built by the Store from the typed schema; absent ⇒ no parsing (bare values). */
|
|
4
4
|
export interface ViewTypes {
|
|
@@ -9,6 +9,15 @@ export interface ViewTypes {
|
|
|
9
9
|
export interface ArrayView<R> {
|
|
10
10
|
/** The current materialized result (reference-stable where data is unchanged). */
|
|
11
11
|
readonly data: readonly R[];
|
|
12
|
+
/** The engine query id the Store assigned this view (1:1 with the view). The same `qid` the raw
|
|
13
|
+
* change stream ({@link Store.subscribeChanges}) tags each frame with, so a consumer can
|
|
14
|
+
* correlate this query with its `ChangeEvent`s (e.g. to bind a narrator) straight off
|
|
15
|
+
* `materialize(query).qid` — no separate handle needed. */
|
|
16
|
+
readonly qid: QueryId;
|
|
17
|
+
/** The query's view `WireSchema` (the position→name source for {@link resolveChange}), captured
|
|
18
|
+
* from its `hello` frame. `null` while PENDING — a remote backend's `hello` arrives async; an
|
|
19
|
+
* in-process backend (wasm/replica) populates it synchronously during `materialize`. */
|
|
20
|
+
readonly schema: WireSchema | null;
|
|
12
21
|
/** The query's SERVER-CHANNEL state (`unknown` while loading, `complete` once server-authoritative;
|
|
13
22
|
* the `error` variant is reserved and currently unproduced). A pending optimistic mutation no
|
|
14
23
|
* longer moves this — it is a separate axis (FOLDED-MUTATIONS-DESIGN §7). `complete` for backends
|
|
@@ -26,6 +35,10 @@ export interface ArrayView<R> {
|
|
|
26
35
|
export interface SingularArrayView<R> {
|
|
27
36
|
/** The single current row, or `null` when the query matches nothing. */
|
|
28
37
|
readonly data: R | null;
|
|
38
|
+
/** The engine query id — see {@link ArrayView.qid}. */
|
|
39
|
+
readonly qid: QueryId;
|
|
40
|
+
/** The query's view `WireSchema` — see {@link ArrayView.schema}. */
|
|
41
|
+
readonly schema: WireSchema | null;
|
|
29
42
|
/** The query's lifecycle state — see {@link ArrayView.resultType}. */
|
|
30
43
|
readonly resultType: ResultType;
|
|
31
44
|
/** Subscribe; fires immediately with the current row, then after each applied batch (and after
|
|
@@ -40,12 +53,15 @@ export declare class SingularView<R> implements SingularArrayView<R> {
|
|
|
40
53
|
private readonly inner;
|
|
41
54
|
constructor(inner: ArrayView<R>);
|
|
42
55
|
get data(): R | null;
|
|
56
|
+
get qid(): QueryId;
|
|
57
|
+
get schema(): WireSchema | null;
|
|
43
58
|
get resultType(): ResultType;
|
|
44
59
|
subscribe(listener: (data: R | null) => void): () => void;
|
|
45
60
|
destroy(): void;
|
|
46
61
|
}
|
|
47
62
|
export declare class FlatArrayView<R = unknown> implements ArrayView<R> {
|
|
48
|
-
private
|
|
63
|
+
private readonly _qid;
|
|
64
|
+
private _schema;
|
|
49
65
|
private types?;
|
|
50
66
|
private seeded;
|
|
51
67
|
private top;
|
|
@@ -53,7 +69,9 @@ export declare class FlatArrayView<R = unknown> implements ArrayView<R> {
|
|
|
53
69
|
private cached;
|
|
54
70
|
private rt;
|
|
55
71
|
private readonly listeners;
|
|
56
|
-
constructor(schema?: WireSchema, types?: ViewTypes);
|
|
72
|
+
constructor(schema?: WireSchema, types?: ViewTypes, qid?: QueryId);
|
|
73
|
+
get qid(): QueryId;
|
|
74
|
+
get schema(): WireSchema | null;
|
|
57
75
|
get resultType(): ResultType;
|
|
58
76
|
/** Set the query's lifecycle state (the Store routes the backend's per-query signal here).
|
|
59
77
|
* Notifies subscribers on a change so a status-bound listener (React `useQueryStatus`) re-reads,
|
|
@@ -72,14 +90,34 @@ export declare class FlatArrayView<R = unknown> implements ArrayView<R> {
|
|
|
72
90
|
seed(rows: readonly R[]): void;
|
|
73
91
|
/** Apply a batch (the hydrate snapshot or one transaction's events) in order, then
|
|
74
92
|
* notify subscribers once. Order is significant (FLAT-CHANGES-DESIGN.md §5.4). A no-op
|
|
75
|
-
* while pending (changes never precede the `hello` that resets the schema).
|
|
76
|
-
|
|
93
|
+
* while pending (changes never precede the `hello` that resets the schema).
|
|
94
|
+
*
|
|
95
|
+
* `enrichRemoves` ⇒ before a removed node is dropped, reconstruct its full subtree and attach it
|
|
96
|
+
* to the `remove` op's `node` (in place, so the same event object the Store fans out to its
|
|
97
|
+
* change subscribers carries it). Off by default — paid only when a consumer asked for it, and
|
|
98
|
+
* only on a real eviction (an rc-decrement that keeps the row leaves `node` absent).
|
|
99
|
+
*
|
|
100
|
+
* `deferNotify` ⇒ fold but do NOT notify; the caller is responsible for calling {@link flush}
|
|
101
|
+
* later. The Store uses this to fold every view in one commit before notifying any subscriber
|
|
102
|
+
* (cross-view-atomic notification — `Store.onCommitBoundary`); standalone use leaves it off, so
|
|
103
|
+
* a bare view still fires its subscribers after each applied batch.
|
|
104
|
+
*
|
|
105
|
+
* Returns whether the batch changed the view (so a deferring caller knows it must be flushed). */
|
|
106
|
+
applyChanges(events: FlatChange[], enrichRemoves?: boolean, deferNotify?: boolean): boolean;
|
|
107
|
+
/** Notify subscribers with the current data. The deferred half of {@link applyChanges} (when
|
|
108
|
+
* `deferNotify` was set): the Store calls this at the commit-notify barrier — after every view
|
|
109
|
+
* touched by the same commit has folded — so a subscriber that re-reads a sibling view inside
|
|
110
|
+
* its callback observes post-commit data, never a torn mid-commit state. */
|
|
111
|
+
flush(): void;
|
|
77
112
|
get data(): readonly R[];
|
|
78
113
|
subscribe(listener: (data: readonly R[]) => void): () => void;
|
|
79
114
|
destroy(): void;
|
|
80
115
|
private applyAt;
|
|
81
116
|
private applyOp;
|
|
82
117
|
private applyAdd;
|
|
118
|
+
/** Drop one path to `row`. Returns the evicted {@link Node} (its full subtree intact) when the
|
|
119
|
+
* last path went away — `null` when another path still holds it (rc decremented, nothing left
|
|
120
|
+
* the result). */
|
|
83
121
|
private applyRemove;
|
|
84
122
|
private applyEdit;
|
|
85
123
|
private project;
|
package/dist/view.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAU,UAAU,EAAY,UAAU,EAAa,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"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"}
|
package/dist/view.js
CHANGED
|
@@ -18,6 +18,12 @@ export class SingularView {
|
|
|
18
18
|
get data() {
|
|
19
19
|
return this.inner.data[0] ?? null;
|
|
20
20
|
}
|
|
21
|
+
get qid() {
|
|
22
|
+
return this.inner.qid;
|
|
23
|
+
}
|
|
24
|
+
get schema() {
|
|
25
|
+
return this.inner.schema;
|
|
26
|
+
}
|
|
21
27
|
get resultType() {
|
|
22
28
|
return this.inner.resultType;
|
|
23
29
|
}
|
|
@@ -67,14 +73,35 @@ function buildNode(wnode, schema) {
|
|
|
67
73
|
function cloneNode(n) {
|
|
68
74
|
return { row: n.row.slice(), rc: n.rc, rels: n.rels.map((r) => r.map(cloneNode)), out: null };
|
|
69
75
|
}
|
|
76
|
+
/** Reconstruct a positional {@link WireNode} (row + its populated child slots) from a maintained
|
|
77
|
+
* {@link Node} — the inverse of {@link buildNode}. Used to attach a removed subtree to a `remove`
|
|
78
|
+
* op so a change consumer (a narrator) can resolve its nested subs, which a bare positional remove
|
|
79
|
+
* (just the leaving row) cannot carry. Only in-view (`child !== null`), non-empty slots are emitted,
|
|
80
|
+
* matching how an `add` node ships only populated relationships. */
|
|
81
|
+
function toWireNode(node, schema) {
|
|
82
|
+
const rels = [];
|
|
83
|
+
for (const rel of schema.relationships) {
|
|
84
|
+
if (rel.child === null)
|
|
85
|
+
continue;
|
|
86
|
+
const childList = node.rels[rel.slot] ?? [];
|
|
87
|
+
if (childList.length === 0)
|
|
88
|
+
continue;
|
|
89
|
+
rels.push({ rel: rel.slot, children: childList.map((c) => toWireNode(c, rel.child)) });
|
|
90
|
+
}
|
|
91
|
+
return { row: node.row, rels };
|
|
92
|
+
}
|
|
70
93
|
function rowsEqual(a, b) {
|
|
71
94
|
return a.length === b.length && a.every((v, i) => Object.is(v, b[i]));
|
|
72
95
|
}
|
|
73
96
|
const EMPTY = Object.freeze([]);
|
|
74
97
|
export class FlatArrayView {
|
|
98
|
+
// The engine query id (Store-assigned, 1:1 with this view), exposed read-only via {@link qid}.
|
|
99
|
+
// `0` ⇒ unbound (a bare view never registered with a Store); the Store passes it at construction.
|
|
100
|
+
_qid;
|
|
75
101
|
// `null` ⇒ PENDING (no schema yet): a remote backend's `hello` arrives async, so the view
|
|
76
102
|
// exists (and reads as `[]`) before its schema lands. Set by `reset` (first hello / re-hydrate).
|
|
77
|
-
schema
|
|
103
|
+
// Exposed read-only via the {@link schema} getter (the position→name source for `resolveChange`).
|
|
104
|
+
_schema;
|
|
78
105
|
types;
|
|
79
106
|
// SSR first-paint seed (SSR-DESIGN.md §6): pre-projected rows installed by `seed`, returned by
|
|
80
107
|
// `data` WHILE pending (no live schema yet). Cleared on `reset` — the first live `hello` —
|
|
@@ -88,9 +115,16 @@ export class FlatArrayView {
|
|
|
88
115
|
// (the optimistic backend: `unknown` until hydrated, etc.).
|
|
89
116
|
rt = "complete";
|
|
90
117
|
listeners = new Set();
|
|
91
|
-
constructor(schema, types) {
|
|
92
|
-
this.
|
|
118
|
+
constructor(schema, types, qid = 0) {
|
|
119
|
+
this._schema = schema ?? null;
|
|
93
120
|
this.types = types;
|
|
121
|
+
this._qid = qid;
|
|
122
|
+
}
|
|
123
|
+
get qid() {
|
|
124
|
+
return this._qid;
|
|
125
|
+
}
|
|
126
|
+
get schema() {
|
|
127
|
+
return this._schema;
|
|
94
128
|
}
|
|
95
129
|
get resultType() {
|
|
96
130
|
return this.rt;
|
|
@@ -110,7 +144,7 @@ export class FlatArrayView {
|
|
|
110
144
|
* the caller's view reference and its subscribers survive a re-subscribe. Does NOT notify —
|
|
111
145
|
* the snapshot that follows (`applyChanges`) does, avoiding an empty-then-filled flicker. */
|
|
112
146
|
reset(schema, types) {
|
|
113
|
-
this.
|
|
147
|
+
this._schema = schema;
|
|
114
148
|
this.types = types;
|
|
115
149
|
this.seeded = null; // live data takes over; the seed was first-paint only
|
|
116
150
|
this.top = [];
|
|
@@ -127,24 +161,45 @@ export class FlatArrayView {
|
|
|
127
161
|
}
|
|
128
162
|
/** Apply a batch (the hydrate snapshot or one transaction's events) in order, then
|
|
129
163
|
* notify subscribers once. Order is significant (FLAT-CHANGES-DESIGN.md §5.4). A no-op
|
|
130
|
-
* while pending (changes never precede the `hello` that resets the schema).
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
164
|
+
* while pending (changes never precede the `hello` that resets the schema).
|
|
165
|
+
*
|
|
166
|
+
* `enrichRemoves` ⇒ before a removed node is dropped, reconstruct its full subtree and attach it
|
|
167
|
+
* to the `remove` op's `node` (in place, so the same event object the Store fans out to its
|
|
168
|
+
* change subscribers carries it). Off by default — paid only when a consumer asked for it, and
|
|
169
|
+
* only on a real eviction (an rc-decrement that keeps the row leaves `node` absent).
|
|
170
|
+
*
|
|
171
|
+
* `deferNotify` ⇒ fold but do NOT notify; the caller is responsible for calling {@link flush}
|
|
172
|
+
* later. The Store uses this to fold every view in one commit before notifying any subscriber
|
|
173
|
+
* (cross-view-atomic notification — `Store.onCommitBoundary`); standalone use leaves it off, so
|
|
174
|
+
* a bare view still fires its subscribers after each applied batch.
|
|
175
|
+
*
|
|
176
|
+
* Returns whether the batch changed the view (so a deferring caller knows it must be flushed). */
|
|
177
|
+
applyChanges(events, enrichRemoves = false, deferNotify = false) {
|
|
178
|
+
if (this._schema === null)
|
|
179
|
+
return false;
|
|
134
180
|
let changed = false;
|
|
135
181
|
for (const e of events)
|
|
136
|
-
changed = this.applyAt(this.top, this.
|
|
182
|
+
changed = this.applyAt(this.top, this._schema, e.path, e.op, 0, enrichRemoves) || changed;
|
|
137
183
|
if (!changed)
|
|
138
|
-
return;
|
|
184
|
+
return false;
|
|
139
185
|
this.dirty = true;
|
|
186
|
+
if (!deferNotify)
|
|
187
|
+
this.notify();
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
/** Notify subscribers with the current data. The deferred half of {@link applyChanges} (when
|
|
191
|
+
* `deferNotify` was set): the Store calls this at the commit-notify barrier — after every view
|
|
192
|
+
* touched by the same commit has folded — so a subscriber that re-reads a sibling view inside
|
|
193
|
+
* its callback observes post-commit data, never a torn mid-commit state. */
|
|
194
|
+
flush() {
|
|
140
195
|
this.notify();
|
|
141
196
|
}
|
|
142
197
|
get data() {
|
|
143
|
-
if (this.
|
|
198
|
+
if (this._schema === null)
|
|
144
199
|
return this.seeded ?? EMPTY;
|
|
145
200
|
if (!this.dirty && this.cached !== null)
|
|
146
201
|
return this.cached;
|
|
147
|
-
this.cached = this.top.map((n) => this.project(n, this.
|
|
202
|
+
this.cached = this.top.map((n) => this.project(n, this._schema, this.types));
|
|
148
203
|
this.dirty = false;
|
|
149
204
|
return this.cached;
|
|
150
205
|
}
|
|
@@ -160,9 +215,9 @@ export class FlatArrayView {
|
|
|
160
215
|
this.top = [];
|
|
161
216
|
}
|
|
162
217
|
// --- apply -------------------------------------------------------------------
|
|
163
|
-
applyAt(list, schema, path, op, depth) {
|
|
218
|
+
applyAt(list, schema, path, op, depth, enrichRemoves) {
|
|
164
219
|
if (depth === path.length) {
|
|
165
|
-
return this.applyOp(list, schema, op);
|
|
220
|
+
return this.applyOp(list, schema, op, enrichRemoves);
|
|
166
221
|
}
|
|
167
222
|
const seg = path[depth];
|
|
168
223
|
const child = schema.relationships[seg.rel]?.child;
|
|
@@ -172,16 +227,22 @@ export class FlatArrayView {
|
|
|
172
227
|
if (!found)
|
|
173
228
|
throw new Error("flat ArrayView: parent not found at path hop (inconsistent stream)");
|
|
174
229
|
const node = list[index];
|
|
175
|
-
const changed = this.applyAt(node.rels[seg.rel], child, path, op, depth + 1);
|
|
230
|
+
const changed = this.applyAt(node.rels[seg.rel], child, path, op, depth + 1, enrichRemoves);
|
|
176
231
|
if (changed)
|
|
177
232
|
node.out = null; // a descendant changed → this node must re-project its rel array
|
|
178
233
|
return changed;
|
|
179
234
|
}
|
|
180
|
-
applyOp(list, schema, op) {
|
|
235
|
+
applyOp(list, schema, op, enrichRemoves) {
|
|
181
236
|
if (op.tag === "add")
|
|
182
237
|
return this.applyAdd(list, schema, op.node);
|
|
183
|
-
if (op.tag === "remove")
|
|
184
|
-
|
|
238
|
+
if (op.tag === "remove") {
|
|
239
|
+
const removed = this.applyRemove(list, schema, op.row);
|
|
240
|
+
// Attach the full removed subtree (in place) for an opted-in consumer; absent when the row
|
|
241
|
+
// only lost a reference (rc > 1) and so did not actually leave the result.
|
|
242
|
+
if (removed && enrichRemoves)
|
|
243
|
+
op.node = toWireNode(removed, schema);
|
|
244
|
+
return removed !== null;
|
|
245
|
+
}
|
|
185
246
|
return this.applyEdit(list, schema, op.old, op.new);
|
|
186
247
|
}
|
|
187
248
|
applyAdd(list, schema, wnode) {
|
|
@@ -193,16 +254,20 @@ export class FlatArrayView {
|
|
|
193
254
|
list.splice(at.index, 0, buildNode(wnode, schema));
|
|
194
255
|
return true;
|
|
195
256
|
}
|
|
257
|
+
/** Drop one path to `row`. Returns the evicted {@link Node} (its full subtree intact) when the
|
|
258
|
+
* last path went away — `null` when another path still holds it (rc decremented, nothing left
|
|
259
|
+
* the result). */
|
|
196
260
|
applyRemove(list, schema, row) {
|
|
197
261
|
const at = binarySearch(list, row, schema.sort);
|
|
198
262
|
if (!at.found)
|
|
199
263
|
throw new Error("flat ArrayView: remove of a non-existent node");
|
|
200
|
-
|
|
264
|
+
const node = list[at.index];
|
|
265
|
+
if (node.rc === 1) {
|
|
201
266
|
list.splice(at.index, 1);
|
|
202
|
-
return
|
|
267
|
+
return node;
|
|
203
268
|
}
|
|
204
|
-
|
|
205
|
-
return
|
|
269
|
+
node.rc -= 1;
|
|
270
|
+
return null;
|
|
206
271
|
}
|
|
207
272
|
applyEdit(list, schema, oldRow, newRow) {
|
|
208
273
|
if (rowsEqual(oldRow, newRow))
|
package/dist/view.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/ast.ts
CHANGED
|
@@ -90,5 +90,16 @@ export interface Ast {
|
|
|
90
90
|
* with a plain singular join + the same projection instead of a `reduce`. Only meaningful
|
|
91
91
|
* with `aggregate`; absent ⇒ `false`. */
|
|
92
92
|
aggregatePrecomputed?: boolean;
|
|
93
|
+
/** Top-level `GROUP BY` columns (names), meaningful only alongside a root {@link Ast.aggregate}
|
|
94
|
+
* (`REDUCE-DESIGN.md` §8). Empty + `aggregate` set ⇒ a **global** aggregate (one `[count]` row);
|
|
95
|
+
* non-empty ⇒ one `[group…, count]` row per distinct value-tuple. Distinct from a relationship
|
|
96
|
+
* aggregate's implicit grouping (the correlation child key). Absent on the wire ⇒ empty. */
|
|
97
|
+
groupBy?: string[];
|
|
98
|
+
/** `HAVING` — a filter over the **post-aggregation** rows of a root {@link Ast.aggregate}
|
|
99
|
+
* (`REDUCE-DESIGN.md` §4: a filter directly above the `reduce`). Its condition addresses the
|
|
100
|
+
* aggregate's *output* columns — the {@link Ast.groupBy} columns and the synthetic `count`
|
|
101
|
+
* column — not base-table columns (those go in {@link Ast.where}, which filters rows *below* the
|
|
102
|
+
* reduce). Absent ⇒ no post-aggregation filter. */
|
|
103
|
+
having?: Condition;
|
|
93
104
|
orderBy?: OrderPart[];
|
|
94
105
|
}
|
package/src/index.ts
CHANGED
|
@@ -2,19 +2,47 @@
|
|
|
2
2
|
// comparator, Backend seam, and the ArrayView contract. (The ArrayView folding impl + the
|
|
3
3
|
// Store/backend wiring land in later slices.)
|
|
4
4
|
|
|
5
|
-
export * from "./schema.ts"; // table/columns/primaryKey, createSchema/extendSchema, string/number/boolean/json, Col, RowOf, Row, TableDef, tableSpec, SCHEMA
|
|
5
|
+
export * from "./schema.ts"; // table/columns/primaryKey, createSchema/extendSchema, refineTable/refineSchema, string/number/boolean/json, Col, RowOf, Row, TableDef, tableSpec, SCHEMA
|
|
6
6
|
export * from "./operators.ts"; // eq/ne/gt/ge/lt/le/like/notLike/ilike/notIlike/inList/notInList/is/isNot, and/or, Pred, Cond, Arg
|
|
7
7
|
export * from "./query.ts"; // Query, QueryRoot, queries/newQueryBuilder, defineQuery/NamedQuery, exists, notExists, defineFragment/Fragment/FragmentRef/isFragment
|
|
8
8
|
export * from "./view.ts"; // ArrayView, SingularArrayView, FlatArrayView, SingularView, ViewTypes
|
|
9
9
|
export * from "./store.ts"; // Store, WriteTx, AssembledNode, DehydratedQuery, DehydratedState
|
|
10
10
|
export * from "./ssr.ts"; // createServerStore, ServerStore, OneShotBackend, OneShotQueryFn, OneShotResult, ServerStoreOptions
|
|
11
11
|
|
|
12
|
+
export { resolveChange, subRow } from "./resolve.ts"; // positional FlatChange → named rows (inverse of the wire encoder)
|
|
13
|
+
export type { NamedRow, ResolvedChange } from "./resolve.ts";
|
|
14
|
+
|
|
15
|
+
export type { KeyedRow, MutationOp, ServerWriteTx } from "./mutation-ops.ts"; // isomorphic mutation op vocabulary
|
|
16
|
+
// shared (generator) mutator seam — one body, sync on the client + async on the server
|
|
17
|
+
export {
|
|
18
|
+
driveMutationAsync,
|
|
19
|
+
driveMutationSync,
|
|
20
|
+
isGeneratorMutator,
|
|
21
|
+
isoTx,
|
|
22
|
+
shared,
|
|
23
|
+
} from "./mutation-ops.ts";
|
|
24
|
+
export type {
|
|
25
|
+
ArgSchema,
|
|
26
|
+
AsyncEffectExec,
|
|
27
|
+
BatchEffect,
|
|
28
|
+
IsoTx,
|
|
29
|
+
MutationGen,
|
|
30
|
+
MutatorCtx,
|
|
31
|
+
ReadEffect,
|
|
32
|
+
SharedMutator,
|
|
33
|
+
SharedMutatorWithArgs,
|
|
34
|
+
SyncEffectExec,
|
|
35
|
+
YieldEffect,
|
|
36
|
+
} from "./mutation-ops.ts";
|
|
37
|
+
|
|
12
38
|
export { stableKey } from "./key.ts"; // canonical viewKey for an AST (shared with @rindle/react)
|
|
13
39
|
|
|
14
40
|
export { COMPARATOR_VERSION, compareNumber, compareRows, compareString, compareValue } from "./compare.ts";
|
|
15
41
|
|
|
16
42
|
export type {
|
|
17
43
|
Backend,
|
|
44
|
+
BackendDevObserver,
|
|
45
|
+
BackendServerDelta,
|
|
18
46
|
ChangeEvent,
|
|
19
47
|
ColType,
|
|
20
48
|
FlatChange,
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
// Isomorphic mutation ops — the backend-agnostic "rindle mutation" vocabulary
|
|
2
|
+
// (MUTATORS-ISOMORPHIC plan). A mutator names WHAT it writes (insert/update/upsert/
|
|
3
|
+
// insertIgnore/delete over a keyed row), not HOW — the server renders dialect SQL and the
|
|
4
|
+
// client applies to its local engine. This lives in `@rindle/client` (the leaf both tiers
|
|
5
|
+
// import); the SQL renderer that consumes it is server-only (`@rindle/api-server`).
|
|
6
|
+
|
|
7
|
+
import type { WireValue } from "./types.ts";
|
|
8
|
+
|
|
9
|
+
/** A keyed row: column name → cell. The ergonomic write shape (validated against the schema at
|
|
10
|
+
* runtime). JSON columns carry their raw JSON string (a {@link WireValue}), never a parsed object. */
|
|
11
|
+
export type KeyedRow = Record<string, WireValue>;
|
|
12
|
+
|
|
13
|
+
/** One structured write intent — the discriminated union that mirrors the write half of the client
|
|
14
|
+
* `MutationTx` 1:1. Keyed (column-name addressed), so it is independent of column order. */
|
|
15
|
+
export type MutationOp =
|
|
16
|
+
| { kind: "insert"; table: string; row: KeyedRow } // a FULL row (every column present)
|
|
17
|
+
| { kind: "upsert"; table: string; row: KeyedRow } // full row; replace non-pk cols on pk conflict
|
|
18
|
+
| { kind: "insertIgnore"; table: string; row: KeyedRow } // full row; do nothing on pk conflict
|
|
19
|
+
| { kind: "update"; table: string; row: KeyedRow } // pk cols + the non-pk cols to change
|
|
20
|
+
| { kind: "delete"; table: string; pk: KeyedRow }; // pk cols only
|
|
21
|
+
|
|
22
|
+
/** The ASYNC server-side write surface a mutator runs against. Semantically the twin of the client's
|
|
23
|
+
* synchronous `MutationTx` write methods — same names, same keyed-row arguments — but every op is a
|
|
24
|
+
* Promise so a Postgres backend can execute it live against an open transaction (read-your-writes).
|
|
25
|
+
* A rindle/daemon backend resolves writes immediately (accumulate) and serves `row` from committed
|
|
26
|
+
* state. `insert` requires every column; `update`/`delete` require the pk columns. */
|
|
27
|
+
export interface ServerWriteTx {
|
|
28
|
+
/** Insert a FULL row (every column named; missing or unknown columns throw). */
|
|
29
|
+
insert(table: string, row: KeyedRow): Promise<void>;
|
|
30
|
+
/** Update the row identified by the pk columns; only the named non-pk columns change. A missing
|
|
31
|
+
* row is a NO-OP. */
|
|
32
|
+
update(table: string, row: KeyedRow): Promise<void>;
|
|
33
|
+
/** Insert, or fully replace when the pk already exists (a FULL row, like `insert`). */
|
|
34
|
+
upsert(table: string, row: KeyedRow): Promise<void>;
|
|
35
|
+
/** Insert a FULL row, or do nothing if the pk already exists (the SQL twin of the client
|
|
36
|
+
* `if (!tx.row(pk)) tx.insert(row)` pattern). */
|
|
37
|
+
insertIgnore(table: string, row: KeyedRow): Promise<void>;
|
|
38
|
+
/** Delete the row identified by the pk columns. A missing row is a NO-OP. */
|
|
39
|
+
delete(table: string, pk: KeyedRow): Promise<void>;
|
|
40
|
+
/** Read one row by primary key, through the OPEN transaction on both backends
|
|
41
|
+
* (read-your-writes: live on Postgres; via an interactive mutation session on the daemon,
|
|
42
|
+
* DAEMON-INTERACTIVE-TXN-DESIGN.md §5.3). */
|
|
43
|
+
row(table: string, pk: KeyedRow): Promise<KeyedRow | undefined>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// --------------------------------------------------------------------------- shared (generator) mutators
|
|
47
|
+
//
|
|
48
|
+
// The isomorphic mutator seam (MUTATORS-ISOMORPHIC plan §"one body, two tiers"): a mutator is a
|
|
49
|
+
// GENERATOR that `yield`s effects instead of an async/sync function. A generator is neither sync nor
|
|
50
|
+
// async — the tier's DRIVER decides — so ONE body runs synchronously against the browser wasm engine
|
|
51
|
+
// AND against a live async Postgres transaction on the server. Writes are `yield`ed and pipelined by
|
|
52
|
+
// the driver (never individually awaited by the body); a `yield tx.row(...)` is the one thing that
|
|
53
|
+
// suspends, evaluating to the read row. `yield tx.all([...])` fans reads out (Promise.all on the
|
|
54
|
+
// server, in-order on the client) — order-preserving on both tiers, so the body stays deterministic.
|
|
55
|
+
|
|
56
|
+
/** A point read a generator mutator yields; the driver resolves it and feeds the row back through
|
|
57
|
+
* `gen.next(row)`. Read-your-writes on every tier: the client reads its local engine, and both
|
|
58
|
+
* server backends read the open transaction (the daemon via an interactive mutation session). */
|
|
59
|
+
export type ReadEffect = { kind: "row"; table: string; pk: KeyedRow };
|
|
60
|
+
|
|
61
|
+
/** A fan-out a generator mutator yields: run several effects "together". The server driver resolves
|
|
62
|
+
* them with `Promise.all`; the client driver runs them in array order (already synchronous). Results
|
|
63
|
+
* return in the SAME order on both tiers, so the mutator stays deterministic. The `yield` evaluates
|
|
64
|
+
* to `(KeyedRow | undefined)[]` at runtime (cast it — the generator's single next-type is a row). */
|
|
65
|
+
export type BatchEffect = { kind: "all"; effects: readonly YieldEffect[] };
|
|
66
|
+
|
|
67
|
+
/** Everything a generator mutator may `yield`: a write {@link MutationOp}, a {@link ReadEffect}, or a
|
|
68
|
+
* {@link BatchEffect}. */
|
|
69
|
+
export type YieldEffect = MutationOp | ReadEffect | BatchEffect;
|
|
70
|
+
|
|
71
|
+
/** The tier-AGNOSTIC effect factory a generator mutator writes against. Every method just BUILDS an
|
|
72
|
+
* effect to `yield` — it performs no I/O and holds no state, so the single {@link isoTx} instance is
|
|
73
|
+
* shared by every mutator on both tiers; only the driver differs. `insert`/`upsert`/`insertIgnore`
|
|
74
|
+
* take a FULL row; `update`/`delete` take the pk columns (`update` adds the columns to change). */
|
|
75
|
+
export interface IsoTx {
|
|
76
|
+
insert(table: string, row: KeyedRow): MutationOp;
|
|
77
|
+
update(table: string, row: KeyedRow): MutationOp;
|
|
78
|
+
upsert(table: string, row: KeyedRow): MutationOp;
|
|
79
|
+
insertIgnore(table: string, row: KeyedRow): MutationOp;
|
|
80
|
+
delete(table: string, pk: KeyedRow): MutationOp;
|
|
81
|
+
row(table: string, pk: KeyedRow): ReadEffect;
|
|
82
|
+
all(effects: readonly YieldEffect[]): BatchEffect;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** The one shared effect factory (stateless — see {@link IsoTx}). */
|
|
86
|
+
export const isoTx: IsoTx = {
|
|
87
|
+
insert: (table, row) => ({ kind: "insert", table, row }),
|
|
88
|
+
update: (table, row) => ({ kind: "update", table, row }),
|
|
89
|
+
upsert: (table, row) => ({ kind: "upsert", table, row }),
|
|
90
|
+
insertIgnore: (table, row) => ({ kind: "insertIgnore", table, row }),
|
|
91
|
+
delete: (table, pk) => ({ kind: "delete", table, pk }),
|
|
92
|
+
row: (table, pk) => ({ kind: "row", table, pk }),
|
|
93
|
+
all: (effects) => ({ kind: "all", effects }),
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/** The minimal per-invocation context a shared mutator sees on BOTH tiers: the acting principal. The
|
|
97
|
+
* server injects its AUTHENTICATED user; the client injects its local user. (The server's own
|
|
98
|
+
* `MutationContext` is a superset of this.) */
|
|
99
|
+
export interface MutatorCtx {
|
|
100
|
+
user: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** What a generator mutator IS: `yield tx.<op>()` on every side effect; a `yield tx.row()` expression
|
|
104
|
+
* evaluates to the row. Neither sync nor async — the tier's driver decides, which is what lets one
|
|
105
|
+
* body run synchronously on the client and against a live async transaction on the server. */
|
|
106
|
+
export type MutationGen = Generator<YieldEffect, void, KeyedRow | undefined>;
|
|
107
|
+
|
|
108
|
+
/** A generator (isomorphic) mutator, shared verbatim by both tiers: the client trusts typed `args`,
|
|
109
|
+
* the server parses untrusted args into `Args` before invoking. */
|
|
110
|
+
export type SharedMutator<Args, Ctx extends MutatorCtx = MutatorCtx> = (
|
|
111
|
+
tx: IsoTx,
|
|
112
|
+
args: Args,
|
|
113
|
+
ctx: Ctx,
|
|
114
|
+
) => MutationGen;
|
|
115
|
+
|
|
116
|
+
/** The minimal arg validator a shared mutator can carry so the SERVER can parse UNTRUSTED wire args
|
|
117
|
+
* before driving it (the client trusts its typed callsites and never calls this). Structural on
|
|
118
|
+
* purpose — a zod schema satisfies it as-is — so `@rindle/client` stays validator-library-agnostic. */
|
|
119
|
+
export interface ArgSchema<Args> {
|
|
120
|
+
parse(raw: unknown): Args;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** A shared mutator that CARRIES its own arg validator, co-located at the def site (`shared(schema,
|
|
124
|
+
* gen)`). The client registers it exactly like a bare generator mutator — the `.args` validator is
|
|
125
|
+
* inert there (typed callsites skip the parse); the server ({@link runSharedMutation}, via the
|
|
126
|
+
* api-server's `sharedApiMutators`) reads `.args` to parse untrusted wire args before driving the
|
|
127
|
+
* SAME body. */
|
|
128
|
+
export type SharedMutatorWithArgs<Args, Ctx extends MutatorCtx = MutatorCtx> = SharedMutator<Args, Ctx> & {
|
|
129
|
+
args: ArgSchema<Args>;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/** Co-locate a shared (generator) mutator with the validator for its args — pairing the arg SHAPE
|
|
133
|
+
* with the body that consumes it at ONE site, so neither tier restates it (the client derives its
|
|
134
|
+
* callsite type from `Args`; the server parses untrusted args through `.args`). Returns the SAME
|
|
135
|
+
* generator function with an `args` property attached (`Object.assign` mutates + returns it), so the
|
|
136
|
+
* registered value is byte-for-byte what the client drove before: {@link isGeneratorMutator} still
|
|
137
|
+
* detects it and it still `satisfies ClientRegistry`. */
|
|
138
|
+
export function shared<Args, Ctx extends MutatorCtx = MutatorCtx>(
|
|
139
|
+
args: ArgSchema<Args>,
|
|
140
|
+
run: SharedMutator<Args, Ctx>,
|
|
141
|
+
): SharedMutatorWithArgs<Args, Ctx> {
|
|
142
|
+
return Object.assign(run, { args });
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** True iff `fn` is a generator function (a shared/isomorphic mutator) rather than a plain function —
|
|
146
|
+
* the driver accepts both forms. Detected structurally (native `GeneratorFunction`). */
|
|
147
|
+
export function isGeneratorMutator(fn: unknown): fn is (...args: never[]) => MutationGen {
|
|
148
|
+
return (
|
|
149
|
+
typeof fn === "function" &&
|
|
150
|
+
(fn as { constructor?: { name?: string } }).constructor?.name === "GeneratorFunction"
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** A tier's SYNCHRONOUS effect executor (the browser wasm engine): apply a write, resolve a read —
|
|
155
|
+
* both immediate. */
|
|
156
|
+
export interface SyncEffectExec {
|
|
157
|
+
apply(op: MutationOp): void;
|
|
158
|
+
read(table: string, pk: KeyedRow): KeyedRow | undefined;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Drive a generator mutator SYNCHRONOUSLY (the client, inside the wasm write transaction). Each
|
|
162
|
+
* yielded write applies immediately; each read is resolved and fed back; a batch runs in order. */
|
|
163
|
+
export function driveMutationSync(gen: MutationGen, exec: SyncEffectExec): void {
|
|
164
|
+
const run = (eff: YieldEffect): KeyedRow | undefined => {
|
|
165
|
+
if (eff.kind === "row") return exec.read(eff.table, eff.pk);
|
|
166
|
+
if (eff.kind === "all") return eff.effects.map(run) as unknown as KeyedRow | undefined;
|
|
167
|
+
exec.apply(eff);
|
|
168
|
+
return undefined;
|
|
169
|
+
};
|
|
170
|
+
for (let step = gen.next(); !step.done; step = gen.next(run(step.value)));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** A tier's ASYNCHRONOUS effect executor (the server transaction): every op is a Promise. */
|
|
174
|
+
export interface AsyncEffectExec {
|
|
175
|
+
apply(op: MutationOp): Promise<void>;
|
|
176
|
+
read(table: string, pk: KeyedRow): Promise<KeyedRow | undefined>;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Drive a generator mutator ASYNCHRONOUSLY (the server, against the open transaction). Writes are
|
|
180
|
+
* awaited (harmless: a single interactive Postgres connection serializes statements anyway, and the
|
|
181
|
+
* daemon backend resolves them instantly), reads suspend, and a batch fans out with `Promise.all`. */
|
|
182
|
+
export async function driveMutationAsync(gen: MutationGen, exec: AsyncEffectExec): Promise<void> {
|
|
183
|
+
const run = async (eff: YieldEffect): Promise<KeyedRow | undefined> => {
|
|
184
|
+
if (eff.kind === "row") return exec.read(eff.table, eff.pk);
|
|
185
|
+
if (eff.kind === "all") return (await Promise.all(eff.effects.map(run))) as unknown as KeyedRow | undefined;
|
|
186
|
+
await exec.apply(eff);
|
|
187
|
+
return undefined;
|
|
188
|
+
};
|
|
189
|
+
for (let step = gen.next(); !step.done; step = gen.next(await run(step.value)));
|
|
190
|
+
}
|
package/src/operators.ts
CHANGED
|
@@ -37,6 +37,11 @@ export const inList = <V>(values: V[]): Pred<V> => mk("IN", values as LitValue);
|
|
|
37
37
|
export const notInList = <V>(values: V[]): Pred<V> => mk("NOT IN", values as LitValue);
|
|
38
38
|
export const is = <V>(v: V): Pred<V> => mk("IS", v as LitValue);
|
|
39
39
|
export const isNot = <V>(v: V): Pred<V> => mk("IS NOT", v as LitValue);
|
|
40
|
+
/** `IS NULL` — a field-agnostic null check. `V` is inferred from the field's expected `Arg<V>`
|
|
41
|
+
* (e.g. `where.signedAt(isNull())`), so it fits a column of any type without a cast. */
|
|
42
|
+
export const isNull = <V = never>(): Pred<V> => mk("IS", null);
|
|
43
|
+
/** `IS NOT NULL` — the negation of {@link isNull}; `V` is inferred from the field, like {@link isNull}. */
|
|
44
|
+
export const isNotNull = <V = never>(): Pred<V> => mk("IS NOT", null);
|
|
40
45
|
|
|
41
46
|
/** A field argument: its typed predicate, or a bare value (bare = `eq` sugar). */
|
|
42
47
|
export type Arg<V> = Pred<V> | V;
|