@rindle/wasm 0.1.2 → 0.1.3

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/index.d.ts CHANGED
@@ -37,6 +37,9 @@ export declare function initWasm(moduleOrPath?: unknown): Promise<void>;
37
37
  export declare class WasmBackend<S extends ColsMap> implements Backend {
38
38
  private readonly db;
39
39
  private handler;
40
+ /** Local-only table names (`201-LOCAL-ONLY-TABLES-DESIGN.md` §4): registered UNTRACKED (so the
41
+ * optimistic rewind never reverts them) and the only tables {@link writeLocal} accepts. */
42
+ private readonly localTables;
40
43
  private readonly dispatchQueue;
41
44
  private draining;
42
45
  constructor(schema: Schema<S>);
@@ -44,11 +47,15 @@ export declare class WasmBackend<S extends ColsMap> implements Backend {
44
47
  * (`AGGREGATE-SYNC-DESIGN.md` §3.3) that is not in the typed schema. The
45
48
  * `NormalizedBackend` registers each such `__agg_*` table once, before a query that reads
46
49
  * it, so the local engine can join to it (the relationship `count` it backs is shipped by
47
- * the server, never recomputed). */
50
+ * the server, never recomputed). Always synced (tracked) — synthetic tables are never local. */
48
51
  registerTable(name: string, spec: {
49
52
  columns: string[];
50
53
  primaryKey: number[];
51
54
  }): void;
55
+ /** Direct-commit a batch of LOCAL-only writes (`201-LOCAL-ONLY-TABLES-DESIGN.md` §6): push them
56
+ * straight through the engine on the ordinary delivery path, OUTSIDE any optimistic cycle (a
57
+ * local table is untracked, so it never rebases). Rejects a synced/tracked table (M2). */
58
+ writeLocal(mutations: Mutation[]): void;
52
59
  /** Remove a synthetic aggregate table registered by {@link registerTable}, once the last
53
60
  * query reading it has been unregistered (`AGGREGATE-SYNC-DESIGN.md` §4): frees the engine
54
61
  * source + its optimistic baseline so aggregate state is reclaimed, not permanent. Throws
@@ -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
@@ -6,7 +6,7 @@
6
6
  // needs an explicit, one-time init — `await initWasm()` — before constructing a backend.
7
7
  // In Node the bytes are read from the package; in a browser/bundler the wasm is fetched.
8
8
  import init, { Db } from "../pkg/rindle.js";
9
- import { Store, tableSpec } from "@rindle/client";
9
+ import { localTableNames, Store, tableSpec } from "@rindle/client";
10
10
  export * from "@rindle/client";
11
11
  let initialized = null;
12
12
  /** Initialize the wasm module (idempotent). Call once at startup before `new WasmBackend`
@@ -33,6 +33,9 @@ export function initWasm(moduleOrPath) {
33
33
  export class WasmBackend {
34
34
  db;
35
35
  handler = () => { };
36
+ /** Local-only table names (`201-LOCAL-ONLY-TABLES-DESIGN.md` §4): registered UNTRACKED (so the
37
+ * optimistic rewind never reverts them) and the only tables {@link writeLocal} accepts. */
38
+ localTables;
36
39
  // Non-reentrant delivery (#15): commits dispatch through a FIFO queue. A subscriber that
37
40
  // synchronously triggers another write enqueues that commit's batches; they drain only after
38
41
  // the in-flight commit's batches finish, preserving per-query commit order regardless of what
@@ -41,17 +44,40 @@ export class WasmBackend {
41
44
  draining = false;
42
45
  constructor(schema) {
43
46
  this.db = new Db();
47
+ this.localTables = localTableNames(schema);
44
48
  for (const name of Object.keys(schema.tables)) {
45
- this.db.registerTable(name, tableSpec(schema.tables[name]));
49
+ // A local table registers as a source but skips optimistic tracking (C1) — the `local` bit
50
+ // crosses to the engine here.
51
+ this.db.registerTable(name, tableSpec(schema.tables[name]), this.localTables.has(name));
46
52
  }
47
53
  }
48
54
  /** Register an additional base table after construction — for a SYNTHETIC aggregate table
49
55
  * (`AGGREGATE-SYNC-DESIGN.md` §3.3) that is not in the typed schema. The
50
56
  * `NormalizedBackend` registers each such `__agg_*` table once, before a query that reads
51
57
  * it, so the local engine can join to it (the relationship `count` it backs is shipped by
52
- * the server, never recomputed). */
58
+ * the server, never recomputed). Always synced (tracked) — synthetic tables are never local. */
53
59
  registerTable(name, spec) {
54
- this.db.registerTable(name, spec);
60
+ this.db.registerTable(name, spec, false);
61
+ }
62
+ /** Direct-commit a batch of LOCAL-only writes (`201-LOCAL-ONLY-TABLES-DESIGN.md` §6): push them
63
+ * straight through the engine on the ordinary delivery path, OUTSIDE any optimistic cycle (a
64
+ * local table is untracked, so it never rebases). Rejects a synced/tracked table (M2). */
65
+ writeLocal(mutations) {
66
+ for (const m of mutations) {
67
+ if (!this.localTables.has(m.table)) {
68
+ throw new Error(`writeLocal: table "${m.table}" is not local-only — a direct commit to a synced table is reverted on the next rewind (M2).`);
69
+ }
70
+ }
71
+ this.writeWith((tx) => {
72
+ for (const m of mutations) {
73
+ if (m.op === "add")
74
+ tx.add(m.table, m.row);
75
+ else if (m.op === "remove")
76
+ tx.remove(m.table, m.row);
77
+ else
78
+ tx.edit(m.table, m.old, m.new);
79
+ }
80
+ });
55
81
  }
56
82
  /** Remove a synthetic aggregate table registered by {@link registerTable}, once the last
57
83
  * query reading it has been unregistered (`AGGREGATE-SYNC-DESIGN.md` §4): frees the engine
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.1.2",
3
+ "version": "0.1.3",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -27,7 +27,7 @@
27
27
  "README.md"
28
28
  ],
29
29
  "dependencies": {
30
- "@rindle/client": "0.1.2"
30
+ "@rindle/client": "0.1.3"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^22.10.0",
package/pkg/rindle.d.ts CHANGED
@@ -25,9 +25,19 @@ export class Db {
25
25
  /**
26
26
  * Register a base table from a `SchemaSpec` (`{ columns, primaryKey, sort? }` —
27
27
  * [`marshal::schema_from_js`]; any `relationships` in the spec are ignored — nesting
28
- * is query-local via `sub`). Seeds an empty shared source. Idempotent per name.
28
+ * is query-local via `sub`). Seeds an empty shared source.
29
+ *
30
+ * `local` marks a **local-only** table (`201-LOCAL-ONLY-TABLES-DESIGN.md` §3.1): it is
31
+ * registered as a source but **NOT optimistically tracked** — so the §1.3 `rewind` never
32
+ * iterates it (it has no `sync` baseline to revert to), and a direct write to it persists
33
+ * across every server cycle (C1). A synced table tracks as before.
34
+ *
35
+ * Idempotent ONLY when the re-registration is truly identical — same schema **and** same
36
+ * locality (N1a). A genuine collision (one name claiming two different shapes/localities)
37
+ * errors loudly rather than silently no-op'ing, so the `__agg_*`/`_rindle_*` prefix ban
38
+ * (`createSchema`, N1) has a loud backstop instead of a silent one.
29
39
  */
30
- registerTable(table: string, schema: any): void;
40
+ registerTable(table: string, schema: any, local: boolean): void;
31
41
  /**
32
42
  * Open a §1.3 reconcile cycle against the coherent server delta `deltas` —
33
43
  * an array of base-table row ops `{ table, type: "add"|"remove"|"edit", row,
@@ -210,7 +220,7 @@ export interface InitOutput {
210
220
  readonly db_destroyQuery: (a: number, b: number) => void;
211
221
  readonly db_new: () => number;
212
222
  readonly db_query: (a: number, b: number, c: any) => [number, number, number];
213
- readonly db_registerTable: (a: number, b: number, c: number, d: any) => [number, number];
223
+ readonly db_registerTable: (a: number, b: number, c: number, d: any, e: number) => [number, number];
214
224
  readonly db_serverBatchBegin: (a: number, b: any) => [number, number];
215
225
  readonly db_serverBatchEnd: (a: number) => [number, number, number];
216
226
  readonly db_unregisterTable: (a: number, b: number, c: number) => [number, number];
package/pkg/rindle.js CHANGED
@@ -49,14 +49,25 @@ export class Db {
49
49
  /**
50
50
  * Register a base table from a `SchemaSpec` (`{ columns, primaryKey, sort? }` —
51
51
  * [`marshal::schema_from_js`]; any `relationships` in the spec are ignored — nesting
52
- * is query-local via `sub`). Seeds an empty shared source. Idempotent per name.
52
+ * is query-local via `sub`). Seeds an empty shared source.
53
+ *
54
+ * `local` marks a **local-only** table (`201-LOCAL-ONLY-TABLES-DESIGN.md` §3.1): it is
55
+ * registered as a source but **NOT optimistically tracked** — so the §1.3 `rewind` never
56
+ * iterates it (it has no `sync` baseline to revert to), and a direct write to it persists
57
+ * across every server cycle (C1). A synced table tracks as before.
58
+ *
59
+ * Idempotent ONLY when the re-registration is truly identical — same schema **and** same
60
+ * locality (N1a). A genuine collision (one name claiming two different shapes/localities)
61
+ * errors loudly rather than silently no-op'ing, so the `__agg_*`/`_rindle_*` prefix ban
62
+ * (`createSchema`, N1) has a loud backstop instead of a silent one.
53
63
  * @param {string} table
54
64
  * @param {any} schema
65
+ * @param {boolean} local
55
66
  */
56
- registerTable(table, schema) {
67
+ registerTable(table, schema, local) {
57
68
  const ptr0 = passStringToWasm0(table, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
58
69
  const len0 = WASM_VECTOR_LEN;
59
- const ret = wasm.db_registerTable(this.__wbg_ptr, ptr0, len0, schema);
70
+ const ret = wasm.db_registerTable(this.__wbg_ptr, ptr0, len0, schema, local);
60
71
  if (ret[1]) {
61
72
  throw takeFromExternrefTable0(ret[0]);
62
73
  }
Binary file
@@ -8,7 +8,7 @@ export const __wbg_writetxn_free: (a: number, b: number) => void;
8
8
  export const db_destroyQuery: (a: number, b: number) => void;
9
9
  export const db_new: () => number;
10
10
  export const db_query: (a: number, b: number, c: any) => [number, number, number];
11
- export const db_registerTable: (a: number, b: number, c: number, d: any) => [number, number];
11
+ export const db_registerTable: (a: number, b: number, c: number, d: any, e: number) => [number, number];
12
12
  export const db_serverBatchBegin: (a: number, b: any) => [number, number];
13
13
  export const db_serverBatchEnd: (a: number) => [number, number, number];
14
14
  export const db_unregisterTable: (a: number, b: number, c: number) => [number, number];
package/src/index.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  // In Node the bytes are read from the package; in a browser/bundler the wasm is fetched.
8
8
 
9
9
  import init, { Db } from "../pkg/rindle.js";
10
- import { Store, tableSpec } from "@rindle/client";
10
+ import { localTableNames, Store, tableSpec } from "@rindle/client";
11
11
  import type {
12
12
  Ast,
13
13
  Backend,
@@ -22,7 +22,7 @@ export * from "@rindle/client";
22
22
 
23
23
  // The wasm Db surface this backend uses (kept local so it doesn't depend on the generated .d.ts).
24
24
  interface WasmDb {
25
- registerTable(table: string, spec: { columns: string[]; primaryKey: number[] }): void;
25
+ registerTable(table: string, spec: { columns: string[]; primaryKey: number[] }, local: boolean): void;
26
26
  unregisterTable(table: string): void;
27
27
  query(queryId: number, ast: Ast): { comparatorVersion: number; schema: unknown; snapshot: unknown[] };
28
28
  destroyQuery(queryId: number): void;
@@ -78,6 +78,9 @@ type BatchSet = Array<{ queryId: number; events: unknown[] }>;
78
78
  export class WasmBackend<S extends ColsMap> implements Backend {
79
79
  private readonly db: WasmDb;
80
80
  private handler: (qid: QueryId, ev: ChangeEvent) => void = () => {};
81
+ /** Local-only table names (`201-LOCAL-ONLY-TABLES-DESIGN.md` §4): registered UNTRACKED (so the
82
+ * optimistic rewind never reverts them) and the only tables {@link writeLocal} accepts. */
83
+ private readonly localTables: Set<string>;
81
84
 
82
85
  // Non-reentrant delivery (#15): commits dispatch through a FIFO queue. A subscriber that
83
86
  // synchronously triggers another write enqueues that commit's batches; they drain only after
@@ -88,8 +91,11 @@ export class WasmBackend<S extends ColsMap> implements Backend {
88
91
 
89
92
  constructor(schema: Schema<S>) {
90
93
  this.db = new Db() as unknown as WasmDb;
94
+ this.localTables = localTableNames(schema);
91
95
  for (const name of Object.keys(schema.tables)) {
92
- this.db.registerTable(name, tableSpec(schema.tables[name]));
96
+ // A local table registers as a source but skips optimistic tracking (C1) — the `local` bit
97
+ // crosses to the engine here.
98
+ this.db.registerTable(name, tableSpec(schema.tables[name]), this.localTables.has(name));
93
99
  }
94
100
  }
95
101
 
@@ -97,9 +103,27 @@ export class WasmBackend<S extends ColsMap> implements Backend {
97
103
  * (`AGGREGATE-SYNC-DESIGN.md` §3.3) that is not in the typed schema. The
98
104
  * `NormalizedBackend` registers each such `__agg_*` table once, before a query that reads
99
105
  * it, so the local engine can join to it (the relationship `count` it backs is shipped by
100
- * the server, never recomputed). */
106
+ * the server, never recomputed). Always synced (tracked) — synthetic tables are never local. */
101
107
  registerTable(name: string, spec: { columns: string[]; primaryKey: number[] }): void {
102
- this.db.registerTable(name, spec);
108
+ this.db.registerTable(name, spec, false);
109
+ }
110
+
111
+ /** Direct-commit a batch of LOCAL-only writes (`201-LOCAL-ONLY-TABLES-DESIGN.md` §6): push them
112
+ * straight through the engine on the ordinary delivery path, OUTSIDE any optimistic cycle (a
113
+ * local table is untracked, so it never rebases). Rejects a synced/tracked table (M2). */
114
+ writeLocal(mutations: Mutation[]): void {
115
+ for (const m of mutations) {
116
+ if (!this.localTables.has(m.table)) {
117
+ throw new Error(`writeLocal: table "${m.table}" is not local-only — a direct commit to a synced table is reverted on the next rewind (M2).`);
118
+ }
119
+ }
120
+ this.writeWith((tx) => {
121
+ for (const m of mutations) {
122
+ if (m.op === "add") tx.add(m.table, m.row);
123
+ else if (m.op === "remove") tx.remove(m.table, m.row);
124
+ else tx.edit(m.table, m.old, m.new);
125
+ }
126
+ });
103
127
  }
104
128
 
105
129
  /** Remove a synthetic aggregate table registered by {@link registerTable}, once the last