@rindle/wasm 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/build.sh CHANGED
@@ -15,11 +15,14 @@ PROFILE="${1:-wasm-release}"
15
15
  TARGET=wasm32-unknown-unknown
16
16
  FEATURES=wasm
17
17
  ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
18
+ # The Cargo workspace lives under rust/; the wasm artifact ships into this JS package's pkg/ (which
19
+ # stays at the repo root). Build from rust/ so `-p rindle` and target/ resolve; emit into packages/wasm/pkg.
20
+ RUST_ROOT="$ROOT/rust"
18
21
  OUT="${RINDLE_WASM_OUT:-$ROOT/packages/wasm/pkg}"
19
22
  BINDGEN_TARGET="${RINDLE_WASM_BINDGEN_TARGET:-web}"
20
23
  export PATH="$HOME/.cargo/bin:$PATH"
21
24
 
22
- cd "$ROOT"
25
+ cd "$RUST_ROOT"
23
26
 
24
27
  # `-p rindle`: build ONLY the C-toolchain-free core crate for wasm32 — not the whole workspace
25
28
  # (the SQLite members `rindle-sqlite`/`rindle-replica` and `rindle-fuzz`'s `getrandom` don't compile to
@@ -29,9 +32,9 @@ cd "$ROOT"
29
32
  # don't emit a colliding `librindle.so`, cargo#6313); the `.wasm` artifact needs `cdylib`, requested
30
33
  # here just for this wasm32 build. Produces `target/$TARGET/<profile>/rindle.wasm` either way.
31
34
  case "$PROFILE" in
32
- dev) cargo rustc -p rindle --target "$TARGET" --no-default-features --features "$FEATURES" --crate-type cdylib; WASM="$ROOT/target/$TARGET/debug/rindle.wasm" ;;
33
- release) cargo rustc -p rindle --release --target "$TARGET" --no-default-features --features "$FEATURES" --crate-type cdylib; WASM="$ROOT/target/$TARGET/release/rindle.wasm" ;;
34
- *) cargo rustc -p rindle --profile "$PROFILE" --target "$TARGET" --no-default-features --features "$FEATURES" --crate-type cdylib; WASM="$ROOT/target/$TARGET/$PROFILE/rindle.wasm" ;;
35
+ dev) cargo rustc -p rindle --target "$TARGET" --no-default-features --features "$FEATURES" --crate-type cdylib; WASM="$RUST_ROOT/target/$TARGET/debug/rindle.wasm" ;;
36
+ release) cargo rustc -p rindle --release --target "$TARGET" --no-default-features --features "$FEATURES" --crate-type cdylib; WASM="$RUST_ROOT/target/$TARGET/release/rindle.wasm" ;;
37
+ *) cargo rustc -p rindle --profile "$PROFILE" --target "$TARGET" --no-default-features --features "$FEATURES" --crate-type cdylib; WASM="$RUST_ROOT/target/$TARGET/$PROFILE/rindle.wasm" ;;
35
38
  esac
36
39
 
37
40
  wasm-bindgen --target "$BINDGEN_TARGET" --out-dir "$OUT" --out-name rindle "$WASM"
package/dist/index.d.ts CHANGED
@@ -9,6 +9,12 @@ export interface WasmWriteTxn {
9
9
  remove(table: string, row: unknown[]): void;
10
10
  edit(table: string, oldRow: unknown[], newRow: unknown[]): void;
11
11
  get(table: string, pk: unknown[]): unknown[] | undefined;
12
+ /** Run a one-shot query over the state this txn is mutating — the live base plus this
13
+ * txn's own staged writes-so-far (read-your-writes; 203-MUTATOR-READS-DESIGN.md §5.2).
14
+ * Synchronous (over a lazy read-cache fork of the staged buffer). Returns the query's rows
15
+ * as keyed objects with their materialized `related` children nested by name (identical in
16
+ * shape to a `view.data` row), in the query's order. */
17
+ query(ast: Ast): unknown[];
12
18
  commit(): Array<{
13
19
  queryId: number;
14
20
  events: unknown[];
@@ -37,6 +43,7 @@ export declare function initWasm(moduleOrPath?: unknown): Promise<void>;
37
43
  export declare class WasmBackend<S extends ColsMap> implements Backend {
38
44
  private readonly db;
39
45
  private handler;
46
+ private boundaryHandler;
40
47
  /** Local-only table names (`201-LOCAL-ONLY-TABLES-DESIGN.md` §4): registered UNTRACKED (so the
41
48
  * optimistic rewind never reverts them) and the only tables {@link writeLocal} accepts. */
42
49
  private readonly localTables;
@@ -65,11 +72,21 @@ export declare class WasmBackend<S extends ColsMap> implements Backend {
65
72
  unregisterQuery(qid: QueryId): void;
66
73
  mutate(mutations: Mutation[]): Promise<void>;
67
74
  onEvent(handler: (qid: QueryId, ev: ChangeEvent) => void): void;
75
+ /** Register the Store's commit-boundary handler ({@link Backend.onCommitBoundary}): `dispatch`
76
+ * calls it around each commit's per-query batch delivery so the Store can fold every affected
77
+ * view before notifying any subscriber. */
78
+ onCommitBoundary(handler: (phase: "begin" | "end") => void): void;
68
79
  /** Deliver one commit's per-query batches. Non-reentrant (#15): if a delivery is already in
69
80
  * progress (a subscriber re-entered via write()), enqueue and let the active drain pick it
70
81
  * up FIFO, so each query folds commits in order. Per-query isolated (#11): a view's fold or
71
82
  * subscriber throwing does NOT drop sibling queries' batches — the first error is re-raised
72
- * only after every query has been delivered. */
83
+ * only after every query has been delivered.
84
+ *
85
+ * Cross-view-atomic notification: each commit is bracketed with `boundaryHandler("begin"/"end")`
86
+ * so the Store folds ALL of this commit's views before notifying ANY subscriber (a subscriber
87
+ * re-reading a sibling view then sees post-commit data). `begin`/`end` stay balanced even if a
88
+ * fold throws (the `finally`), and a re-entrant write enqueued during the `end` flush drains as
89
+ * its own bracketed commit in the next loop turn — preserving per-query commit order (#15). */
73
90
  private dispatch;
74
91
  /** Run `f` against a raw staged write txn (with the §4.1 `get` read path), commit, and
75
92
  * dispatch the resulting batches on the ordinary event stream. Inside an open server
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -33,6 +33,11 @@ export function initWasm(moduleOrPath) {
33
33
  export class WasmBackend {
34
34
  db;
35
35
  handler = () => { };
36
+ // The Store's commit-boundary handler ({@link Backend.onCommitBoundary}): `dispatch` brackets
37
+ // each commit's per-query batch delivery with `begin`/`end` so the Store folds every affected
38
+ // view before notifying any subscriber (cross-view-atomic notification). Defaults to a no-op so
39
+ // a Store that never registers it (or none at all) just gets per-event notification.
40
+ boundaryHandler = () => { };
36
41
  /** Local-only table names (`201-LOCAL-ONLY-TABLES-DESIGN.md` §4): registered UNTRACKED (so the
37
42
  * optimistic rewind never reverts them) and the only tables {@link writeLocal} accepts. */
38
43
  localTables;
@@ -110,11 +115,23 @@ export class WasmBackend {
110
115
  onEvent(handler) {
111
116
  this.handler = handler;
112
117
  }
118
+ /** Register the Store's commit-boundary handler ({@link Backend.onCommitBoundary}): `dispatch`
119
+ * calls it around each commit's per-query batch delivery so the Store can fold every affected
120
+ * view before notifying any subscriber. */
121
+ onCommitBoundary(handler) {
122
+ this.boundaryHandler = handler;
123
+ }
113
124
  /** Deliver one commit's per-query batches. Non-reentrant (#15): if a delivery is already in
114
125
  * progress (a subscriber re-entered via write()), enqueue and let the active drain pick it
115
126
  * up FIFO, so each query folds commits in order. Per-query isolated (#11): a view's fold or
116
127
  * subscriber throwing does NOT drop sibling queries' batches — the first error is re-raised
117
- * only after every query has been delivered. */
128
+ * only after every query has been delivered.
129
+ *
130
+ * Cross-view-atomic notification: each commit is bracketed with `boundaryHandler("begin"/"end")`
131
+ * so the Store folds ALL of this commit's views before notifying ANY subscriber (a subscriber
132
+ * re-reading a sibling view then sees post-commit data). `begin`/`end` stay balanced even if a
133
+ * fold throws (the `finally`), and a re-entrant write enqueued during the `end` flush drains as
134
+ * its own bracketed commit in the next loop turn — preserving per-query commit order (#15). */
118
135
  dispatch(batches) {
119
136
  this.dispatchQueue.push(batches);
120
137
  if (this.draining)
@@ -122,18 +139,34 @@ export class WasmBackend {
122
139
  this.draining = true;
123
140
  let firstError;
124
141
  let hasError = false;
142
+ const note = (err) => {
143
+ if (!hasError) {
144
+ hasError = true;
145
+ firstError = err;
146
+ }
147
+ };
125
148
  try {
126
149
  while (this.dispatchQueue.length) {
127
150
  const next = this.dispatchQueue.shift();
128
- for (const b of next) {
151
+ if (next.length === 0)
152
+ continue; // an empty commit (no query changed) — no barrier needed
153
+ this.boundaryHandler("begin");
154
+ try {
155
+ for (const b of next) {
156
+ try {
157
+ this.handler(b.queryId, { type: "batch", events: b.events });
158
+ }
159
+ catch (err) {
160
+ note(err);
161
+ }
162
+ }
163
+ }
164
+ finally {
129
165
  try {
130
- this.handler(b.queryId, { type: "batch", events: b.events });
166
+ this.boundaryHandler("end"); // flush: notify every folded view's subscribers
131
167
  }
132
168
  catch (err) {
133
- if (!hasError) {
134
- hasError = true;
135
- firstError = err;
136
- }
169
+ note(err);
137
170
  }
138
171
  }
139
172
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rindle/wasm",
3
- "version": "0.2.0",
3
+ "version": "0.4.2",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -29,7 +29,7 @@
29
29
  "README.md"
30
30
  ],
31
31
  "dependencies": {
32
- "@rindle/client": "0.2.0"
32
+ "@rindle/client": "0.4.2"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/node": "^22.10.0",
package/pkg/rindle.d.ts CHANGED
@@ -191,6 +191,25 @@ export class WriteTxn {
191
191
  * mutations re-invoked so far), which is exactly what re-invocation must read.
192
192
  */
193
193
  get(table: string, pk: any): any;
194
+ /**
195
+ * Run a one-shot query (a `where`/`orderBy`/`limit`/join AST) over the state this
196
+ * transaction is mutating — the live base **plus** this txn's own staged writes-so-far
197
+ * (`203-MUTATOR-READS-DESIGN.md` §5.2; the same read-your-writes contract `get`
198
+ * provides, §4.1). Returns the query's rows as keyed JS objects with their materialized
199
+ * `related` children nested by name — presented identically to a `view.data` row of the
200
+ * same query ([`marshal::caught_node_to_js`]) — in the query's order.
201
+ *
202
+ * Mechanically this is [`Db::query`] minus the persisted `QueryReg`, pointed at the
203
+ * per-table read-cache forks (§4): for every table the AST reads it seeds a cache fork
204
+ * ([`ensure_fork`](Self::ensure_fork)) and registers a throwaway COW **fork-of-fork** of
205
+ * it as a *scratch* source node — `add_memory_source` takes the source by value, so the
206
+ * cache fork stays in `forks` for later reads/writes. It then builds a transient
207
+ * pipeline over those scratch nodes, hydrates the snapshot, and tears **everything**
208
+ * down — the pipeline (incl. its sink) and every scratch source — on **every** exit
209
+ * path, including a malformed-AST build failure (invariant 4). No durable sink is
210
+ * registered and nothing is delivered to any live query.
211
+ */
212
+ query(ast_json: any): any;
194
213
  /**
195
214
  * Stage a remove of `row` from `table`.
196
215
  */
@@ -236,6 +255,7 @@ export interface InitOutput {
236
255
  readonly writetxn_commit: (a: number) => [number, number, number];
237
256
  readonly writetxn_edit: (a: number, b: number, c: number, d: any, e: any) => [number, number];
238
257
  readonly writetxn_get: (a: number, b: number, c: number, d: any) => [number, number, number];
258
+ readonly writetxn_query: (a: number, b: any) => [number, number, number];
239
259
  readonly writetxn_remove: (a: number, b: number, c: number, d: any) => [number, number];
240
260
  readonly writetxn_rollback: (a: number) => void;
241
261
  readonly __wbindgen_malloc: (a: number, b: number) => number;
package/pkg/rindle.js CHANGED
@@ -355,6 +355,33 @@ export class WriteTxn {
355
355
  }
356
356
  return takeFromExternrefTable0(ret[0]);
357
357
  }
358
+ /**
359
+ * Run a one-shot query (a `where`/`orderBy`/`limit`/join AST) over the state this
360
+ * transaction is mutating — the live base **plus** this txn's own staged writes-so-far
361
+ * (`203-MUTATOR-READS-DESIGN.md` §5.2; the same read-your-writes contract `get`
362
+ * provides, §4.1). Returns the query's rows as keyed JS objects with their materialized
363
+ * `related` children nested by name — presented identically to a `view.data` row of the
364
+ * same query ([`marshal::caught_node_to_js`]) — in the query's order.
365
+ *
366
+ * Mechanically this is [`Db::query`] minus the persisted `QueryReg`, pointed at the
367
+ * per-table read-cache forks (§4): for every table the AST reads it seeds a cache fork
368
+ * ([`ensure_fork`](Self::ensure_fork)) and registers a throwaway COW **fork-of-fork** of
369
+ * it as a *scratch* source node — `add_memory_source` takes the source by value, so the
370
+ * cache fork stays in `forks` for later reads/writes. It then builds a transient
371
+ * pipeline over those scratch nodes, hydrates the snapshot, and tears **everything**
372
+ * down — the pipeline (incl. its sink) and every scratch source — on **every** exit
373
+ * path, including a malformed-AST build failure (invariant 4). No durable sink is
374
+ * registered and nothing is delivered to any live query.
375
+ * @param {any} ast_json
376
+ * @returns {any}
377
+ */
378
+ query(ast_json) {
379
+ const ret = wasm.writetxn_query(this.__wbg_ptr, ast_json);
380
+ if (ret[2]) {
381
+ throw takeFromExternrefTable0(ret[1]);
382
+ }
383
+ return takeFromExternrefTable0(ret[0]);
384
+ }
358
385
  /**
359
386
  * Stage a remove of `row` from `table`.
360
387
  * @param {string} table
Binary file
@@ -24,6 +24,7 @@ export const writetxn_add: (a: number, b: number, c: number, d: any) => [number,
24
24
  export const writetxn_commit: (a: number) => [number, number, number];
25
25
  export const writetxn_edit: (a: number, b: number, c: number, d: any, e: any) => [number, number];
26
26
  export const writetxn_get: (a: number, b: number, c: number, d: any) => [number, number, number];
27
+ export const writetxn_query: (a: number, b: any) => [number, number, number];
27
28
  export const writetxn_remove: (a: number, b: number, c: number, d: any) => [number, number];
28
29
  export const writetxn_rollback: (a: number) => void;
29
30
  export const __wbindgen_malloc: (a: number, b: number) => number;
package/src/index.ts CHANGED
@@ -39,6 +39,12 @@ export interface WasmWriteTxn {
39
39
  remove(table: string, row: unknown[]): void;
40
40
  edit(table: string, oldRow: unknown[], newRow: unknown[]): void;
41
41
  get(table: string, pk: unknown[]): unknown[] | undefined;
42
+ /** Run a one-shot query over the state this txn is mutating — the live base plus this
43
+ * txn's own staged writes-so-far (read-your-writes; 203-MUTATOR-READS-DESIGN.md §5.2).
44
+ * Synchronous (over a lazy read-cache fork of the staged buffer). Returns the query's rows
45
+ * as keyed objects with their materialized `related` children nested by name (identical in
46
+ * shape to a `view.data` row), in the query's order. */
47
+ query(ast: Ast): unknown[];
42
48
  commit(): Array<{ queryId: number; events: unknown[] }>;
43
49
  rollback(): void;
44
50
  }
@@ -78,6 +84,11 @@ type BatchSet = Array<{ queryId: number; events: unknown[] }>;
78
84
  export class WasmBackend<S extends ColsMap> implements Backend {
79
85
  private readonly db: WasmDb;
80
86
  private handler: (qid: QueryId, ev: ChangeEvent) => void = () => {};
87
+ // The Store's commit-boundary handler ({@link Backend.onCommitBoundary}): `dispatch` brackets
88
+ // each commit's per-query batch delivery with `begin`/`end` so the Store folds every affected
89
+ // view before notifying any subscriber (cross-view-atomic notification). Defaults to a no-op so
90
+ // a Store that never registers it (or none at all) just gets per-event notification.
91
+ private boundaryHandler: (phase: "begin" | "end") => void = () => {};
81
92
  /** Local-only table names (`201-LOCAL-ONLY-TABLES-DESIGN.md` §4): registered UNTRACKED (so the
82
93
  * optimistic rewind never reverts them) and the only tables {@link writeLocal} accepts. */
83
94
  private readonly localTables: Set<string>;
@@ -159,28 +170,54 @@ export class WasmBackend<S extends ColsMap> implements Backend {
159
170
  this.handler = handler;
160
171
  }
161
172
 
173
+ /** Register the Store's commit-boundary handler ({@link Backend.onCommitBoundary}): `dispatch`
174
+ * calls it around each commit's per-query batch delivery so the Store can fold every affected
175
+ * view before notifying any subscriber. */
176
+ onCommitBoundary(handler: (phase: "begin" | "end") => void): void {
177
+ this.boundaryHandler = handler;
178
+ }
179
+
162
180
  /** Deliver one commit's per-query batches. Non-reentrant (#15): if a delivery is already in
163
181
  * progress (a subscriber re-entered via write()), enqueue and let the active drain pick it
164
182
  * up FIFO, so each query folds commits in order. Per-query isolated (#11): a view's fold or
165
183
  * subscriber throwing does NOT drop sibling queries' batches — the first error is re-raised
166
- * only after every query has been delivered. */
184
+ * only after every query has been delivered.
185
+ *
186
+ * Cross-view-atomic notification: each commit is bracketed with `boundaryHandler("begin"/"end")`
187
+ * so the Store folds ALL of this commit's views before notifying ANY subscriber (a subscriber
188
+ * re-reading a sibling view then sees post-commit data). `begin`/`end` stay balanced even if a
189
+ * fold throws (the `finally`), and a re-entrant write enqueued during the `end` flush drains as
190
+ * its own bracketed commit in the next loop turn — preserving per-query commit order (#15). */
167
191
  private dispatch(batches: BatchSet): void {
168
192
  this.dispatchQueue.push(batches);
169
193
  if (this.draining) return; // an outer drain is running; it will deliver this set
170
194
  this.draining = true;
171
195
  let firstError: unknown;
172
196
  let hasError = false;
197
+ const note = (err: unknown) => {
198
+ if (!hasError) {
199
+ hasError = true;
200
+ firstError = err;
201
+ }
202
+ };
173
203
  try {
174
204
  while (this.dispatchQueue.length) {
175
205
  const next = this.dispatchQueue.shift()!;
176
- for (const b of next) {
206
+ if (next.length === 0) continue; // an empty commit (no query changed) — no barrier needed
207
+ this.boundaryHandler("begin");
208
+ try {
209
+ for (const b of next) {
210
+ try {
211
+ this.handler(b.queryId, { type: "batch", events: b.events as never });
212
+ } catch (err) {
213
+ note(err);
214
+ }
215
+ }
216
+ } finally {
177
217
  try {
178
- this.handler(b.queryId, { type: "batch", events: b.events as never });
218
+ this.boundaryHandler("end"); // flush: notify every folded view's subscribers
179
219
  } catch (err) {
180
- if (!hasError) {
181
- hasError = true;
182
- firstError = err;
183
- }
220
+ note(err);
184
221
  }
185
222
  }
186
223
  }