@optimystic/db-p2p-storage-ns 0.24.1 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,10 +5,10 @@ Android, native — not React Native). Provides:
5
5
 
6
6
  - **`SqliteRawStorage`** — the `IRawStorage` a NativeScript node uses to
7
7
  persist block metadata, revisions, pending transactions, committed
8
- transactions, and materialized blocks across app restarts. It is a thin
9
- shell over the shared `KvRawStorage` kernel driven by `SqliteStoreDriver`:
10
- the kernel owns all JSON serialization, the driver maps the five logical
11
- stores onto the five SQLite tables.
8
+ transactions, commit proofs, and materialized blocks across app restarts.
9
+ It is a thin shell over the shared `KvRawStorage` kernel driven by
10
+ `SqliteStoreDriver`: the kernel owns all JSON serialization, the driver
11
+ maps the six logical stores onto the six SQLite tables.
12
12
  - **`SqliteKVStore`** — implements `IKVStore` for the persistent transaction
13
13
  state used to recover crashed two-phase commits.
14
14
  - **`loadOrCreateNSPeerKey`** — generates an Ed25519 libp2p private key on
@@ -75,7 +75,7 @@ the mutex to preserve read concurrency.
75
75
  ## Persistence model
76
76
 
77
77
  The package opens a single SQLite database (`optimystic.sqlite` by default
78
- in the NativeScript app's documents directory) with six tables. The five
78
+ in the NativeScript app's documents directory) with seven tables. The six
79
79
  block-storage tables keep their original columns and keys, but their value
80
80
  columns are now **BLOB**: `SqliteStoreDriver` binds/reads the kernel's raw
81
81
  `Uint8Array` bytes and the shared `KvRawStorage` kernel owns the JSON/UTF-8
@@ -90,6 +90,7 @@ into; keys stay TEXT/INTEGER.
90
90
  | `revisions` | `(block_id, rev)` | `BLOB` (`action_id` col) | `ActionId` |
91
91
  | `pending` | `(block_id, action_id)` | `BLOB` | `Transform` |
92
92
  | `transactions` | `(block_id, action_id)` | `BLOB` | `Transform` |
93
+ | `proofs` | `(block_id, rev)` | `BLOB` | `BlockCommitProof` |
93
94
  | `materialized` | `(block_id, action_id)` | `BLOB` | `IBlock` |
94
95
  | `kv` | `key` | `s_val` (TEXT) or `b_val` (BLOB) | — (not kernel-backed) |
95
96
 
package/dist/src/db.d.ts CHANGED
@@ -81,7 +81,7 @@ export declare const DEFAULT_DB_VERSION = 1;
81
81
  /**
82
82
  * Schema for the NativeScript storage backend.
83
83
  *
84
- * Mirrors the IndexedDB object stores 1:1. The five block-storage stores keep
84
+ * Mirrors the IndexedDB object stores 1:1. The six block-storage stores keep
85
85
  * their original columns and keys, but their value columns are now BLOB: the
86
86
  * shared `KvRawStorage` kernel (driven by `SqliteStoreDriver`) owns all JSON /
87
87
  * UTF-8 (de)serialization, so the driver only ever binds/reads the kernel's raw
@@ -93,6 +93,9 @@ export declare const DEFAULT_DB_VERSION = 1;
93
93
  * holds the kernel's encoded `ActionId` bytes (BLOB).
94
94
  * - `pending` → uncommitted transform bytes keyed by `(block_id, action_id)`.
95
95
  * - `transactions` → committed transform bytes keyed by `(block_id, action_id)`.
96
+ * - `proofs` → `BlockCommitProof` bytes keyed by `(block_id, rev)` — the same key
97
+ * shape as `revisions`, deliberately NOT the action keyspace (an action id is
98
+ * caller-chosen, so no reserved id could be relied on).
96
99
  * - `materialized` → materialized block bytes keyed by `(block_id, action_id)`.
97
100
  * - `kv` → generic string keyspace shared by `IKVStore` (`s_val`) and the
98
101
  * identity helper (`b_val`). NOT kernel-backed; unchanged. The two columns
@@ -105,9 +108,9 @@ export declare const DEFAULT_DB_VERSION = 1;
105
108
  * throwing). There is no migration. Safe today because this backend is
106
109
  * NativeScript-only with no shipped production data; if a build ever ships to
107
110
  * devices that later upgrade, add a `user_version` bump that drops+recreates
108
- * these five tables (or a real migration) before assuming BLOB rows.
111
+ * these six tables (or a real migration) before assuming BLOB rows.
109
112
  */
110
- export declare const SCHEMA_SQL = "\nCREATE TABLE IF NOT EXISTS metadata (\n\tblock_id TEXT PRIMARY KEY,\n\tvalue BLOB NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS revisions (\n\tblock_id TEXT NOT NULL,\n\trev INTEGER NOT NULL,\n\taction_id BLOB NOT NULL,\n\tPRIMARY KEY (block_id, rev)\n);\n\nCREATE TABLE IF NOT EXISTS pending (\n\tblock_id TEXT NOT NULL,\n\taction_id TEXT NOT NULL,\n\tvalue BLOB NOT NULL,\n\tPRIMARY KEY (block_id, action_id)\n);\n\nCREATE TABLE IF NOT EXISTS transactions (\n\tblock_id TEXT NOT NULL,\n\taction_id TEXT NOT NULL,\n\tvalue BLOB NOT NULL,\n\tPRIMARY KEY (block_id, action_id)\n);\n\nCREATE TABLE IF NOT EXISTS materialized (\n\tblock_id TEXT NOT NULL,\n\taction_id TEXT NOT NULL,\n\tvalue BLOB NOT NULL,\n\tPRIMARY KEY (block_id, action_id)\n);\n\nCREATE TABLE IF NOT EXISTS kv (\n\tkey TEXT PRIMARY KEY,\n\ts_val TEXT,\n\tb_val BLOB\n);\n";
113
+ export declare const SCHEMA_SQL = "\nCREATE TABLE IF NOT EXISTS metadata (\n\tblock_id TEXT PRIMARY KEY,\n\tvalue BLOB NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS revisions (\n\tblock_id TEXT NOT NULL,\n\trev INTEGER NOT NULL,\n\taction_id BLOB NOT NULL,\n\tPRIMARY KEY (block_id, rev)\n);\n\nCREATE TABLE IF NOT EXISTS pending (\n\tblock_id TEXT NOT NULL,\n\taction_id TEXT NOT NULL,\n\tvalue BLOB NOT NULL,\n\tPRIMARY KEY (block_id, action_id)\n);\n\nCREATE TABLE IF NOT EXISTS transactions (\n\tblock_id TEXT NOT NULL,\n\taction_id TEXT NOT NULL,\n\tvalue BLOB NOT NULL,\n\tPRIMARY KEY (block_id, action_id)\n);\n\nCREATE TABLE IF NOT EXISTS proofs (\n\tblock_id TEXT NOT NULL,\n\trev INTEGER NOT NULL,\n\tvalue BLOB NOT NULL,\n\tPRIMARY KEY (block_id, rev)\n);\n\nCREATE TABLE IF NOT EXISTS materialized (\n\tblock_id TEXT NOT NULL,\n\taction_id TEXT NOT NULL,\n\tvalue BLOB NOT NULL,\n\tPRIMARY KEY (block_id, action_id)\n);\n\nCREATE TABLE IF NOT EXISTS kv (\n\tkey TEXT PRIMARY KEY,\n\ts_val TEXT,\n\tb_val BLOB\n);\n";
111
114
  /**
112
115
  * Apply pragmas, run the schema DDL, and stamp `user_version` so future
113
116
  * migrations can branch on it. Idempotent — safe to call on every open.
@@ -1 +1 @@
1
- {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,kFAAkF;AAClF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;AAE9D,oEAAoE;AACpE,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC/B,0EAA0E;IAC1E,GAAG,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,gEAAgE;IAChE,GAAG,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAC9D,oFAAoF;IACpF,GAAG,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;CACpD;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,iBAAiB;IACjC,6EAA6E;IAC7E,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;CACtC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,QAAQ;IACxB,yFAAyF;IACzF,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,2FAA2F;IAC3F,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;IACtC;;;;;;;;;;OAUG;IACH,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,iBAAiB,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACtE,qCAAqC;IACrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,eAAO,MAAM,eAAe,sBAAsB,CAAC;AACnD,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,UAAU,+2BAuCtB,CAAC;AAQF;;;GAGG;AACH,wBAAsB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,GAAE,MAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAUnG;AAED;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC"}
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,kFAAkF;AAClF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;AAE9D,oEAAoE;AACpE,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC/B,0EAA0E;IAC1E,GAAG,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,gEAAgE;IAChE,GAAG,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAC9D,oFAAoF;IACpF,GAAG,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;CACpD;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,iBAAiB;IACjC,6EAA6E;IAC7E,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;CACtC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,QAAQ;IACxB,yFAAyF;IACzF,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,2FAA2F;IAC3F,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;IACtC;;;;;;;;;;OAUG;IACH,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,iBAAiB,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACtE,qCAAqC;IACrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,eAAO,MAAM,eAAe,sBAAsB,CAAC;AACnD,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,UAAU,mhCA8CtB,CAAC;AAQF;;;GAGG;AACH,wBAAsB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,GAAE,MAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAUnG;AAED;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC"}
package/dist/src/db.js CHANGED
@@ -15,7 +15,7 @@ export const DEFAULT_DB_VERSION = 1;
15
15
  /**
16
16
  * Schema for the NativeScript storage backend.
17
17
  *
18
- * Mirrors the IndexedDB object stores 1:1. The five block-storage stores keep
18
+ * Mirrors the IndexedDB object stores 1:1. The six block-storage stores keep
19
19
  * their original columns and keys, but their value columns are now BLOB: the
20
20
  * shared `KvRawStorage` kernel (driven by `SqliteStoreDriver`) owns all JSON /
21
21
  * UTF-8 (de)serialization, so the driver only ever binds/reads the kernel's raw
@@ -27,6 +27,9 @@ export const DEFAULT_DB_VERSION = 1;
27
27
  * holds the kernel's encoded `ActionId` bytes (BLOB).
28
28
  * - `pending` → uncommitted transform bytes keyed by `(block_id, action_id)`.
29
29
  * - `transactions` → committed transform bytes keyed by `(block_id, action_id)`.
30
+ * - `proofs` → `BlockCommitProof` bytes keyed by `(block_id, rev)` — the same key
31
+ * shape as `revisions`, deliberately NOT the action keyspace (an action id is
32
+ * caller-chosen, so no reserved id could be relied on).
30
33
  * - `materialized` → materialized block bytes keyed by `(block_id, action_id)`.
31
34
  * - `kv` → generic string keyspace shared by `IKVStore` (`s_val`) and the
32
35
  * identity helper (`b_val`). NOT kernel-backed; unchanged. The two columns
@@ -39,7 +42,7 @@ export const DEFAULT_DB_VERSION = 1;
39
42
  * throwing). There is no migration. Safe today because this backend is
40
43
  * NativeScript-only with no shipped production data; if a build ever ships to
41
44
  * devices that later upgrade, add a `user_version` bump that drops+recreates
42
- * these five tables (or a real migration) before assuming BLOB rows.
45
+ * these six tables (or a real migration) before assuming BLOB rows.
43
46
  */
44
47
  export const SCHEMA_SQL = `
45
48
  CREATE TABLE IF NOT EXISTS metadata (
@@ -68,6 +71,13 @@ CREATE TABLE IF NOT EXISTS transactions (
68
71
  PRIMARY KEY (block_id, action_id)
69
72
  );
70
73
 
74
+ CREATE TABLE IF NOT EXISTS proofs (
75
+ block_id TEXT NOT NULL,
76
+ rev INTEGER NOT NULL,
77
+ value BLOB NOT NULL,
78
+ PRIMARY KEY (block_id, rev)
79
+ );
80
+
71
81
  CREATE TABLE IF NOT EXISTS materialized (
72
82
  block_id TEXT NOT NULL,
73
83
  action_id TEXT NOT NULL,
@@ -1 +1 @@
1
- {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAyEH,MAAM,CAAC,MAAM,eAAe,GAAG,mBAAmB,CAAC;AACnD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuCzB,CAAC;AAEF,+EAA+E;AAC/E,MAAM,WAAW,GAAG;;;CAGnB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,EAAY,EAAE,UAAkB,kBAAkB;IACnF,0EAA0E;IAC1E,6EAA6E;IAC7E,4EAA4E;IAC5E,4EAA4E;IAC5E,iFAAiF;IACjF,MAAM,EAAE,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC,GAAG,EAAE,CAAC;IACpD,MAAM,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3B,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1B,MAAM,EAAE,CAAC,IAAI,CAAC,yBAAyB,OAAO,EAAE,CAAC,CAAC;AACnD,CAAC"}
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAyEH,MAAM,CAAC,MAAM,eAAe,GAAG,mBAAmB,CAAC;AACnD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8CzB,CAAC;AAEF,+EAA+E;AAC/E,MAAM,WAAW,GAAG;;;CAGnB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,EAAY,EAAE,UAAkB,kBAAkB;IACnF,0EAA0E;IAC1E,6EAA6E;IAC7E,4EAA4E;IAC5E,4EAA4E;IAC5E,iFAAiF;IACjF,MAAM,EAAE,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC,GAAG,EAAE,CAAC;IACpD,MAAM,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3B,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1B,MAAM,EAAE,CAAC,IAAI,CAAC,yBAAyB,OAAO,EAAE,CAAC,CAAC;AACnD,CAAC"}
@@ -120,7 +120,7 @@ class NSPluginStatement {
120
120
  // concurrency. A read issued while a write transaction is open on this same
121
121
  // connection observes that transaction's UNCOMMITTED rows (read-your-connection
122
122
  // semantics). Fine today: the only transaction writer is same-block promote
123
- // under the commit latch, and cross-block reads are independent. If a future
123
+ // under the block's write latch, and cross-block reads are independent. If a future
124
124
  // caller reads a block on this connection while another op's transaction on the
125
125
  // same rows is mid-flight, it may see uncommitted state — serialize reads too if
126
126
  // that ever matters.
@@ -1 +1 @@
1
- {"version":3,"file":"ns-opener.js","sourceRoot":"","sources":["../../src/ns-opener.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,kBAAkB,EAA4H,MAAM,SAAS,CAAC;AAmBrM;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACvC,OAAe,eAAe,EAC9B,UAAkB,kBAAkB;IAEpC,MAAM,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,gCAA0C,CAAC,CAA8B,CAAC;IACvG,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,OAAO,CAAC;AAChB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,GAAe;IAC7C,OAAO,IAAI,iBAAiB,CAAC,GAAG,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,iBAAiB;IAGO;IAFZ,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;IAE/C,YAA6B,GAAe;QAAf,QAAG,GAAH,GAAG,CAAY;IAAG,CAAC;IAEhD,KAAK,CAAC,IAAI,CAAC,GAAW;QACrB,oEAAoE;QACpE,+DAA+D;QAC/D,MAAM,UAAU,GAAG,GAAG;aACpB,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aAClB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC5B,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;YACrC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;gBACpC,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACnC,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,GAAW;QAClB,8DAA8D;QAC9D,OAAO,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,WAAW,CAAI,EAAyC;QAC7D,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;YACtC,sEAAsE;YACtE,uEAAuE;YACvE,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;YAC1C,IAAI,CAAC;gBACJ,iEAAiE;gBACjE,oDAAoD;gBACpD,MAAM,EAAE,GAAsB;oBAC7B,OAAO,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC;iBAC9D,CAAC;gBACF,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC5B,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACjC,OAAO,MAAM,CAAC;YACf,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,IAAI,CAAC;oBACJ,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;gBACpC,CAAC;gBAAC,MAAM,CAAC;oBACR,8DAA8D;gBAC/D,CAAC;gBACD,MAAM,GAAG,CAAC;YACX,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAK;QACV,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACD;AAED,MAAM,iBAAiB;IAQJ;IACA;IACA;IATlB;;;;;OAKG;IACH,YACkB,GAAe,EACf,GAAW,EACX,KAAuB;QAFvB,QAAG,GAAH,GAAG,CAAY;QACf,QAAG,GAAH,GAAG,CAAQ;QACX,UAAK,GAAL,KAAK,CAAkB;IACtC,CAAC;IAEJ,KAAK,CAAC,GAAG,CAAC,GAAG,MAAqB;QACjC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACP,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC1C,CAAC;IACF,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAG,MAAqB;QACjC,6EAA6E;QAC7E,4EAA4E;QAC5E,gFAAgF;QAChF,4EAA4E;QAC5E,6EAA6E;QAC7E,gFAAgF;QAChF,iFAAiF;QACjF,qBAAqB;QACrB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACjD,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QACxD,OAAO,GAAgB,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAG,MAAqB;QACjC,+EAA+E;QAC/E,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACrD,OAAO,IAAmB,CAAC;IAC5B,CAAC;CACD"}
1
+ {"version":3,"file":"ns-opener.js","sourceRoot":"","sources":["../../src/ns-opener.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,kBAAkB,EAA4H,MAAM,SAAS,CAAC;AAmBrM;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACvC,OAAe,eAAe,EAC9B,UAAkB,kBAAkB;IAEpC,MAAM,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,gCAA0C,CAAC,CAA8B,CAAC;IACvG,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,OAAO,CAAC;AAChB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,GAAe;IAC7C,OAAO,IAAI,iBAAiB,CAAC,GAAG,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,iBAAiB;IAGO;IAFZ,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;IAE/C,YAA6B,GAAe;QAAf,QAAG,GAAH,GAAG,CAAY;IAAG,CAAC;IAEhD,KAAK,CAAC,IAAI,CAAC,GAAW;QACrB,oEAAoE;QACpE,+DAA+D;QAC/D,MAAM,UAAU,GAAG,GAAG;aACpB,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aAClB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC5B,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;YACrC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;gBACpC,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACnC,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,GAAW;QAClB,8DAA8D;QAC9D,OAAO,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,WAAW,CAAI,EAAyC;QAC7D,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;YACtC,sEAAsE;YACtE,uEAAuE;YACvE,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;YAC1C,IAAI,CAAC;gBACJ,iEAAiE;gBACjE,oDAAoD;gBACpD,MAAM,EAAE,GAAsB;oBAC7B,OAAO,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC;iBAC9D,CAAC;gBACF,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC5B,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACjC,OAAO,MAAM,CAAC;YACf,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,IAAI,CAAC;oBACJ,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;gBACpC,CAAC;gBAAC,MAAM,CAAC;oBACR,8DAA8D;gBAC/D,CAAC;gBACD,MAAM,GAAG,CAAC;YACX,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAK;QACV,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACD;AAED,MAAM,iBAAiB;IAQJ;IACA;IACA;IATlB;;;;;OAKG;IACH,YACkB,GAAe,EACf,GAAW,EACX,KAAuB;QAFvB,QAAG,GAAH,GAAG,CAAY;QACf,QAAG,GAAH,GAAG,CAAQ;QACX,UAAK,GAAL,KAAK,CAAkB;IACtC,CAAC;IAEJ,KAAK,CAAC,GAAG,CAAC,GAAG,MAAqB;QACjC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACP,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC1C,CAAC;IACF,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAG,MAAqB;QACjC,6EAA6E;QAC7E,4EAA4E;QAC5E,gFAAgF;QAChF,4EAA4E;QAC5E,oFAAoF;QACpF,gFAAgF;QAChF,iFAAiF;QACjF,qBAAqB;QACrB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACjD,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QACxD,OAAO,GAAgB,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAG,MAAqB;QACjC,+EAA+E;QAC/E,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACrD,OAAO,IAAmB,CAAC;IAC5B,CAAC;CACD"}
@@ -1,11 +1,10 @@
1
1
  import type { ActionId, BlockId } from '@optimystic/db-core';
2
- import { KvRawStorage, type RawStoreDriver } from '@optimystic/db-p2p';
2
+ import { KvRawStorage, type RawStoreDriver, type StoreIdentity } from '@optimystic/db-p2p';
3
3
  import type { SqliteDb } from './db.js';
4
4
  /**
5
- * SQLite {@link RawStoreDriver}: the five logical block-storage stores mapped to
6
- * the five relational tables (`metadata`, `revisions`, `pending`, `transactions`,
7
- * `materialized`) with their original columns and keys. This is a code refactor,
8
- * not a storage-format change at the SQL level.
5
+ * SQLite {@link RawStoreDriver}: the six logical block-storage stores mapped to
6
+ * the six relational tables (`metadata`, `revisions`, `pending`, `transactions`,
7
+ * `proofs`, `materialized`) with their original columns and keys.
9
8
  *
10
9
  * `KvRawStorage` now owns all JSON serialization, so this driver only ever
11
10
  * reads/writes `Uint8Array` values: the value columns are BLOB and SQLite binds
@@ -22,7 +21,9 @@ import type { SqliteDb } from './db.js';
22
21
  export declare class SqliteStoreDriver implements RawStoreDriver {
23
22
  private readonly db;
24
23
  private readonly stmts;
24
+ private readonly identity;
25
25
  constructor(db: SqliteDb);
26
+ storeIdentity(): StoreIdentity;
26
27
  getMetadata(blockId: BlockId): Promise<Uint8Array | undefined>;
27
28
  putMetadata(blockId: BlockId, value: Uint8Array): Promise<void>;
28
29
  getRevision(blockId: BlockId, rev: number): Promise<Uint8Array | undefined>;
@@ -34,6 +35,8 @@ export declare class SqliteStoreDriver implements RawStoreDriver {
34
35
  listPendingActionIds(blockId: BlockId): AsyncIterable<ActionId>;
35
36
  getTransaction(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined>;
36
37
  putTransaction(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void>;
38
+ getProof(blockId: BlockId, rev: number): Promise<Uint8Array | undefined>;
39
+ putProof(blockId: BlockId, rev: number, value: Uint8Array): Promise<void>;
37
40
  getMaterialized(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined>;
38
41
  putMaterialized(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void>;
39
42
  deleteMaterialized(blockId: BlockId, actionId: ActionId): Promise<void>;
@@ -56,6 +59,7 @@ export declare class SqliteStoreDriver implements RawStoreDriver {
56
59
  export declare class SqliteRawStorage extends KvRawStorage {
57
60
  listBlockIds: () => AsyncIterable<BlockId>;
58
61
  getApproximateBytesUsed: () => Promise<number>;
62
+ getStoreIdentity: () => StoreIdentity;
59
63
  constructor(db: SqliteDb);
60
64
  }
61
65
  //# sourceMappingURL=sqlite-storage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-storage.d.ts","sourceRoot":"","sources":["../../src/sqlite-storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,EAAE,QAAQ,EAAmB,MAAM,SAAS,CAAC;AAKzD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,iBAAkB,YAAW,cAAc;IAsB3C,OAAO,CAAC,QAAQ,CAAC,EAAE;IArB/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAmBpB;gBAE2B,EAAE,EAAE,QAAQ;IA6BnC,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAK9D,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/D,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAK3E,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3E,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,aAAa,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAYhH,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAKjF,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlF,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC;IAUhE,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAKrF,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtF,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAKtF,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvF,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAMvE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB3D,YAAY,IAAI,aAAa,CAAC,OAAO,CAAC;IAOvC,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;CAY7C;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,gBAAiB,SAAQ,YAAY;IACzC,YAAY,EAAE,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;IAC3C,uBAAuB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;gBAE3C,EAAE,EAAE,QAAQ;CAGxB"}
1
+ {"version":3,"file":"sqlite-storage.d.ts","sourceRoot":"","sources":["../../src/sqlite-storage.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,10 @@
1
- import { KvRawStorage } from '@optimystic/db-p2p';
1
+ import { KvRawStorage, identityForHandle } from '@optimystic/db-p2p';
2
2
  import { createLogger } from './logger.js';
3
3
  const log = createLogger('storage:sqlite');
4
4
  /**
5
- * SQLite {@link RawStoreDriver}: the five logical block-storage stores mapped to
6
- * the five relational tables (`metadata`, `revisions`, `pending`, `transactions`,
7
- * `materialized`) with their original columns and keys. This is a code refactor,
8
- * not a storage-format change at the SQL level.
5
+ * SQLite {@link RawStoreDriver}: the six logical block-storage stores mapped to
6
+ * the six relational tables (`metadata`, `revisions`, `pending`, `transactions`,
7
+ * `proofs`, `materialized`) with their original columns and keys.
9
8
  *
10
9
  * `KvRawStorage` now owns all JSON serialization, so this driver only ever
11
10
  * reads/writes `Uint8Array` values: the value columns are BLOB and SQLite binds
@@ -22,8 +21,14 @@ const log = createLogger('storage:sqlite');
22
21
  export class SqliteStoreDriver {
23
22
  db;
24
23
  stmts;
24
+ // NOTE: identity is the HANDLE object, so two handles opened over the same SQLite FILE read
25
+ // as two identities. Resolving that would mean naming the underlying database file, which
26
+ // `SqliteDb` does not expose. The package opener (`ns-opener.ts`) hands out one handle per
27
+ // file in practice, so this is the reachable case, not the complete one.
28
+ identity;
25
29
  constructor(db) {
26
30
  this.db = db;
31
+ this.identity = identityForHandle('sqlite-handle', db);
27
32
  this.stmts = {
28
33
  getMetadata: db.prepare('SELECT value FROM metadata WHERE block_id = ?'),
29
34
  saveMetadata: db.prepare('INSERT OR REPLACE INTO metadata (block_id, value) VALUES (?, ?)'),
@@ -42,6 +47,8 @@ export class SqliteStoreDriver {
42
47
  listBlockIds: db.prepare('SELECT block_id FROM metadata'),
43
48
  getTransaction: db.prepare('SELECT value FROM transactions WHERE block_id = ? AND action_id = ?'),
44
49
  saveTransaction: db.prepare('INSERT OR REPLACE INTO transactions (block_id, action_id, value) VALUES (?, ?, ?)'),
50
+ getProof: db.prepare('SELECT value FROM proofs WHERE block_id = ? AND rev = ?'),
51
+ saveProof: db.prepare('INSERT OR REPLACE INTO proofs (block_id, rev, value) VALUES (?, ?, ?)'),
45
52
  getMaterialized: db.prepare('SELECT value FROM materialized WHERE block_id = ? AND action_id = ?'),
46
53
  saveMaterialized: db.prepare('INSERT OR REPLACE INTO materialized (block_id, action_id, value) VALUES (?, ?, ?)'),
47
54
  deleteMaterialized: db.prepare('DELETE FROM materialized WHERE block_id = ? AND action_id = ?'),
@@ -49,6 +56,9 @@ export class SqliteStoreDriver {
49
56
  pageSize: db.prepare('PRAGMA page_size'),
50
57
  };
51
58
  }
59
+ storeIdentity() {
60
+ return this.identity;
61
+ }
52
62
  // --- metadata ---
53
63
  async getMetadata(blockId) {
54
64
  const row = await this.stmts.getMetadata.get(blockId);
@@ -100,6 +110,14 @@ export class SqliteStoreDriver {
100
110
  async putTransaction(blockId, actionId, value) {
101
111
  await this.stmts.saveTransaction.run(blockId, actionId, value);
102
112
  }
113
+ // --- proofs (keyed (block_id, rev) like revisions; no delete — see RawStoreDriver.getProof) ---
114
+ async getProof(blockId, rev) {
115
+ const row = await this.stmts.getProof.get(blockId, rev);
116
+ return row ? row.value : undefined;
117
+ }
118
+ async putProof(blockId, rev, value) {
119
+ await this.stmts.saveProof.run(blockId, rev, value);
120
+ }
103
121
  // --- materialized ---
104
122
  async getMaterialized(blockId, actionId) {
105
123
  const row = await this.stmts.getMaterialized.get(blockId, actionId);
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-storage.js","sourceRoot":"","sources":["../../src/sqlite-storage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sqlite-storage.js","sourceRoot":"","sources":["../../src/sqlite-storage.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optimystic/db-p2p-storage-ns",
3
- "version": "0.24.1",
3
+ "version": "0.25.0",
4
4
  "type": "module",
5
5
  "description": "NativeScript SQLite storage backend for @optimystic/db-p2p",
6
6
  "main": "dist/src/index.js",
@@ -53,8 +53,8 @@
53
53
  "typescript": "^5.9.3"
54
54
  },
55
55
  "dependencies": {
56
- "@optimystic/db-core": "^0.24.1",
57
- "@optimystic/db-p2p": "^0.24.1",
56
+ "@optimystic/db-core": "^0.25.0",
57
+ "@optimystic/db-p2p": "^0.25.0",
58
58
  "debug": "^4.4.3"
59
59
  },
60
60
  "peerDependencies": {
package/src/db.ts CHANGED
@@ -88,7 +88,7 @@ export const DEFAULT_DB_VERSION = 1;
88
88
  /**
89
89
  * Schema for the NativeScript storage backend.
90
90
  *
91
- * Mirrors the IndexedDB object stores 1:1. The five block-storage stores keep
91
+ * Mirrors the IndexedDB object stores 1:1. The six block-storage stores keep
92
92
  * their original columns and keys, but their value columns are now BLOB: the
93
93
  * shared `KvRawStorage` kernel (driven by `SqliteStoreDriver`) owns all JSON /
94
94
  * UTF-8 (de)serialization, so the driver only ever binds/reads the kernel's raw
@@ -100,6 +100,9 @@ export const DEFAULT_DB_VERSION = 1;
100
100
  * holds the kernel's encoded `ActionId` bytes (BLOB).
101
101
  * - `pending` → uncommitted transform bytes keyed by `(block_id, action_id)`.
102
102
  * - `transactions` → committed transform bytes keyed by `(block_id, action_id)`.
103
+ * - `proofs` → `BlockCommitProof` bytes keyed by `(block_id, rev)` — the same key
104
+ * shape as `revisions`, deliberately NOT the action keyspace (an action id is
105
+ * caller-chosen, so no reserved id could be relied on).
103
106
  * - `materialized` → materialized block bytes keyed by `(block_id, action_id)`.
104
107
  * - `kv` → generic string keyspace shared by `IKVStore` (`s_val`) and the
105
108
  * identity helper (`b_val`). NOT kernel-backed; unchanged. The two columns
@@ -112,7 +115,7 @@ export const DEFAULT_DB_VERSION = 1;
112
115
  * throwing). There is no migration. Safe today because this backend is
113
116
  * NativeScript-only with no shipped production data; if a build ever ships to
114
117
  * devices that later upgrade, add a `user_version` bump that drops+recreates
115
- * these five tables (or a real migration) before assuming BLOB rows.
118
+ * these six tables (or a real migration) before assuming BLOB rows.
116
119
  */
117
120
  export const SCHEMA_SQL = `
118
121
  CREATE TABLE IF NOT EXISTS metadata (
@@ -141,6 +144,13 @@ CREATE TABLE IF NOT EXISTS transactions (
141
144
  PRIMARY KEY (block_id, action_id)
142
145
  );
143
146
 
147
+ CREATE TABLE IF NOT EXISTS proofs (
148
+ block_id TEXT NOT NULL,
149
+ rev INTEGER NOT NULL,
150
+ value BLOB NOT NULL,
151
+ PRIMARY KEY (block_id, rev)
152
+ );
153
+
144
154
  CREATE TABLE IF NOT EXISTS materialized (
145
155
  block_id TEXT NOT NULL,
146
156
  action_id TEXT NOT NULL,
package/src/ns-opener.ts CHANGED
@@ -142,7 +142,7 @@ class NSPluginStatement implements SqliteStatement {
142
142
  // concurrency. A read issued while a write transaction is open on this same
143
143
  // connection observes that transaction's UNCOMMITTED rows (read-your-connection
144
144
  // semantics). Fine today: the only transaction writer is same-block promote
145
- // under the commit latch, and cross-block reads are independent. If a future
145
+ // under the block's write latch, and cross-block reads are independent. If a future
146
146
  // caller reads a block on this connection while another op's transaction on the
147
147
  // same rows is mid-flight, it may see uncommitted state — serialize reads too if
148
148
  // that ever matters.
@@ -1,217 +1,243 @@
1
- import type { ActionId, BlockId } from '@optimystic/db-core';
2
- import { KvRawStorage, type RawStoreDriver } from '@optimystic/db-p2p';
3
- import type { SqliteDb, SqliteStatement } from './db.js';
4
- import { createLogger } from './logger.js';
5
-
6
- const log = createLogger('storage:sqlite');
7
-
8
- /**
9
- * SQLite {@link RawStoreDriver}: the five logical block-storage stores mapped to
10
- * the five relational tables (`metadata`, `revisions`, `pending`, `transactions`,
11
- * `materialized`) with their original columns and keys. This is a code refactor,
12
- * not a storage-format change at the SQL level.
13
- *
14
- * `KvRawStorage` now owns all JSON serialization, so this driver only ever
15
- * reads/writes `Uint8Array` values: the value columns are BLOB and SQLite binds
16
- * a `Uint8Array` as a BLOB and returns it as a `Uint8Array`, so no codec lives
17
- * here (a TEXT column would risk UTF-8 coercion corrupting non-ASCII JSON bytes).
18
- * Everything SQLite-specific stays: each CRUD op goes through a prepared
19
- * statement bound once in the constructor; range/list queries drain their rows
20
- * (`.all(...)`) before yielding so no cursor straddles a consumer's `await`; and
21
- * `promote` runs as a single `db.transaction(fn)` — `BEGIN IMMEDIATE; INSERT…;
22
- * DELETE…; COMMIT;` — whose three statements are re-prepared against the OPEN
23
- * transaction so they run on the held mutex slot without re-locking (which would
24
- * deadlock — see `st-nativescript-sqlite-transaction-mutex`).
25
- */
26
- export class SqliteStoreDriver implements RawStoreDriver {
27
- private readonly stmts: {
28
- getMetadata: SqliteStatement;
29
- saveMetadata: SqliteStatement;
30
- getRevision: SqliteStatement;
31
- saveRevision: SqliteStatement;
32
- listRevisionsAsc: SqliteStatement;
33
- listRevisionsDesc: SqliteStatement;
34
- getPending: SqliteStatement;
35
- savePending: SqliteStatement;
36
- deletePending: SqliteStatement;
37
- listPending: SqliteStatement;
38
- listBlockIds: SqliteStatement;
39
- getTransaction: SqliteStatement;
40
- saveTransaction: SqliteStatement;
41
- getMaterialized: SqliteStatement;
42
- saveMaterialized: SqliteStatement;
43
- deleteMaterialized: SqliteStatement;
44
- pageCount: SqliteStatement;
45
- pageSize: SqliteStatement;
46
- };
47
-
48
- constructor(private readonly db: SqliteDb) {
49
- this.stmts = {
50
- getMetadata: db.prepare('SELECT value FROM metadata WHERE block_id = ?'),
51
- saveMetadata: db.prepare('INSERT OR REPLACE INTO metadata (block_id, value) VALUES (?, ?)'),
52
- getRevision: db.prepare('SELECT action_id FROM revisions WHERE block_id = ? AND rev = ?'),
53
- saveRevision: db.prepare('INSERT OR REPLACE INTO revisions (block_id, rev, action_id) VALUES (?, ?, ?)'),
54
- listRevisionsAsc: db.prepare('SELECT rev, action_id FROM revisions WHERE block_id = ? AND rev BETWEEN ? AND ? ORDER BY rev ASC'),
55
- listRevisionsDesc: db.prepare('SELECT rev, action_id FROM revisions WHERE block_id = ? AND rev BETWEEN ? AND ? ORDER BY rev DESC'),
56
- getPending: db.prepare('SELECT value FROM pending WHERE block_id = ? AND action_id = ?'),
57
- savePending: db.prepare('INSERT OR REPLACE INTO pending (block_id, action_id, value) VALUES (?, ?, ?)'),
58
- deletePending: db.prepare('DELETE FROM pending WHERE block_id = ? AND action_id = ?'),
59
- listPending: db.prepare('SELECT action_id FROM pending WHERE block_id = ? ORDER BY action_id ASC'),
60
- // metadata.block_id is the PRIMARY KEY, so each row is a distinct block id —
61
- // no dedup needed. NOTE: drains the whole metadata table up front; if a peer
62
- // ever holds millions of blocks and this SELECT becomes a startup-latency
63
- // problem, page it (LIMIT/OFFSET or keyset) — fine at current scale.
64
- listBlockIds: db.prepare('SELECT block_id FROM metadata'),
65
- getTransaction: db.prepare('SELECT value FROM transactions WHERE block_id = ? AND action_id = ?'),
66
- saveTransaction: db.prepare('INSERT OR REPLACE INTO transactions (block_id, action_id, value) VALUES (?, ?, ?)'),
67
- getMaterialized: db.prepare('SELECT value FROM materialized WHERE block_id = ? AND action_id = ?'),
68
- saveMaterialized: db.prepare('INSERT OR REPLACE INTO materialized (block_id, action_id, value) VALUES (?, ?, ?)'),
69
- deleteMaterialized: db.prepare('DELETE FROM materialized WHERE block_id = ? AND action_id = ?'),
70
- pageCount: db.prepare('PRAGMA page_count'),
71
- pageSize: db.prepare('PRAGMA page_size'),
72
- };
73
- }
74
-
75
- // --- metadata ---
76
-
77
- async getMetadata(blockId: BlockId): Promise<Uint8Array | undefined> {
78
- const row = await this.stmts.getMetadata.get(blockId);
79
- return row ? (row.value as Uint8Array) : undefined;
80
- }
81
-
82
- async putMetadata(blockId: BlockId, value: Uint8Array): Promise<void> {
83
- await this.stmts.saveMetadata.run(blockId, value);
84
- }
85
-
86
- // --- revisions ---
87
-
88
- async getRevision(blockId: BlockId, rev: number): Promise<Uint8Array | undefined> {
89
- const row = await this.stmts.getRevision.get(blockId, rev);
90
- return row ? (row.action_id as Uint8Array) : undefined;
91
- }
92
-
93
- async putRevision(blockId: BlockId, rev: number, value: Uint8Array): Promise<void> {
94
- await this.stmts.saveRevision.run(blockId, rev, value);
95
- }
96
-
97
- async *rangeRevisions(blockId: BlockId, lo: number, hi: number, reverse: boolean): AsyncIterable<[number, Uint8Array]> {
98
- // `.all(...)` materializes every row before we yield, so no SQLite cursor
99
- // straddles the consumer's awaits (the kernel's drain-before-yield contract).
100
- const stmt = reverse ? this.stmts.listRevisionsDesc : this.stmts.listRevisionsAsc;
101
- const rows = await stmt.all(blockId, lo, hi);
102
- for (const row of rows) {
103
- yield [row.rev as number, row.action_id as Uint8Array];
104
- }
105
- }
106
-
107
- // --- pending ---
108
-
109
- async getPending(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined> {
110
- const row = await this.stmts.getPending.get(blockId, actionId);
111
- return row ? (row.value as Uint8Array) : undefined;
112
- }
113
-
114
- async putPending(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void> {
115
- await this.stmts.savePending.run(blockId, actionId, value);
116
- }
117
-
118
- async deletePending(blockId: BlockId, actionId: ActionId): Promise<void> {
119
- await this.stmts.deletePending.run(blockId, actionId);
120
- }
121
-
122
- async *listPendingActionIds(blockId: BlockId): AsyncIterable<ActionId> {
123
- // Drained by `.all(...)` before yielding — same rationale as rangeRevisions.
124
- const rows = await this.stmts.listPending.all(blockId);
125
- for (const row of rows) {
126
- yield row.action_id as ActionId;
127
- }
128
- }
129
-
130
- // --- transactions ---
131
-
132
- async getTransaction(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined> {
133
- const row = await this.stmts.getTransaction.get(blockId, actionId);
134
- return row ? (row.value as Uint8Array) : undefined;
135
- }
136
-
137
- async putTransaction(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void> {
138
- await this.stmts.saveTransaction.run(blockId, actionId, value);
139
- }
140
-
141
- // --- materialized ---
142
-
143
- async getMaterialized(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined> {
144
- const row = await this.stmts.getMaterialized.get(blockId, actionId);
145
- return row ? (row.value as Uint8Array) : undefined;
146
- }
147
-
148
- async putMaterialized(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void> {
149
- await this.stmts.saveMaterialized.run(blockId, actionId, value);
150
- }
151
-
152
- async deleteMaterialized(blockId: BlockId, actionId: ActionId): Promise<void> {
153
- await this.stmts.deleteMaterialized.run(blockId, actionId);
154
- }
155
-
156
- // --- promote (the only cross-key atomic op) ---
157
-
158
- async promote(blockId: BlockId, actionId: ActionId): Promise<void> {
159
- await this.db.transaction(async (tx) => {
160
- // Prepare against the open transaction so these three statements run on
161
- // the held mutex slot without re-locking the connection (which would
162
- // deadlock). Re-preparing is cheap — the driver caches by SQL text.
163
- const getPending = tx.prepare('SELECT value FROM pending WHERE block_id = ? AND action_id = ?');
164
- const saveTransaction = tx.prepare('INSERT OR REPLACE INTO transactions (block_id, action_id, value) VALUES (?, ?, ?)');
165
- const deletePending = tx.prepare('DELETE FROM pending WHERE block_id = ? AND action_id = ?');
166
- const row = await getPending.get(blockId, actionId);
167
- if (!row) {
168
- throw new Error(`Pending action ${actionId} not found for block ${blockId}`);
169
- }
170
- await saveTransaction.run(blockId, actionId, row.value as Uint8Array);
171
- await deletePending.run(blockId, actionId);
172
- });
173
- }
174
-
175
- // --- optional passthroughs ---
176
-
177
- async *listBlockIds(): AsyncIterable<BlockId> {
178
- const rows = await this.stmts.listBlockIds.all();
179
- for (const row of rows) {
180
- yield row.block_id as BlockId;
181
- }
182
- }
183
-
184
- async approximateBytesUsed(): Promise<number> {
185
- try {
186
- const pageCountRow = await this.stmts.pageCount.get();
187
- const pageSizeRow = await this.stmts.pageSize.get();
188
- const pages = (pageCountRow?.page_count as number | undefined) ?? 0;
189
- const size = (pageSizeRow?.page_size as number | undefined) ?? 0;
190
- return pages * size;
191
- } catch (err) {
192
- log('PRAGMA page_count/page_size failed: %o', err);
193
- return 0;
194
- }
195
- }
196
- }
197
-
198
- /**
199
- * SQLite-backed {@link IRawStorage} for NativeScript peers, now a thin shell over
200
- * the shared {@link KvRawStorage} kernel driven by a {@link SqliteStoreDriver}.
201
- * The public name/constructor (`new SqliteRawStorage(db)`) is unchanged so
202
- * existing imports keep resolving; the kernel supplies the `IRawStorage` surface
203
- * and the driver supplies SQLite behavior.
204
- *
205
- * `listBlockIds`/`getApproximateBytesUsed` are re-declared here as always-present
206
- * (the SQLite driver always implements them, so the kernel constructor always
207
- * wires them) — the base declares them optional, but every NS consumer relies on
208
- * them.
209
- */
210
- export class SqliteRawStorage extends KvRawStorage {
211
- declare listBlockIds: () => AsyncIterable<BlockId>;
212
- declare getApproximateBytesUsed: () => Promise<number>;
213
-
214
- constructor(db: SqliteDb) {
215
- super(new SqliteStoreDriver(db));
216
- }
217
- }
1
+ import type { ActionId, BlockId } from '@optimystic/db-core';
2
+ import { KvRawStorage, identityForHandle, type RawStoreDriver, type StoreIdentity } from '@optimystic/db-p2p';
3
+ import type { SqliteDb, SqliteStatement } from './db.js';
4
+ import { createLogger } from './logger.js';
5
+
6
+ const log = createLogger('storage:sqlite');
7
+
8
+ /**
9
+ * SQLite {@link RawStoreDriver}: the six logical block-storage stores mapped to
10
+ * the six relational tables (`metadata`, `revisions`, `pending`, `transactions`,
11
+ * `proofs`, `materialized`) with their original columns and keys.
12
+ *
13
+ * `KvRawStorage` now owns all JSON serialization, so this driver only ever
14
+ * reads/writes `Uint8Array` values: the value columns are BLOB and SQLite binds
15
+ * a `Uint8Array` as a BLOB and returns it as a `Uint8Array`, so no codec lives
16
+ * here (a TEXT column would risk UTF-8 coercion corrupting non-ASCII JSON bytes).
17
+ * Everything SQLite-specific stays: each CRUD op goes through a prepared
18
+ * statement bound once in the constructor; range/list queries drain their rows
19
+ * (`.all(...)`) before yielding so no cursor straddles a consumer's `await`; and
20
+ * `promote` runs as a single `db.transaction(fn)` — `BEGIN IMMEDIATE; INSERT…;
21
+ * DELETE…; COMMIT;` — whose three statements are re-prepared against the OPEN
22
+ * transaction so they run on the held mutex slot without re-locking (which would
23
+ * deadlock — see `st-nativescript-sqlite-transaction-mutex`).
24
+ */
25
+ export class SqliteStoreDriver implements RawStoreDriver {
26
+ private readonly stmts: {
27
+ getMetadata: SqliteStatement;
28
+ saveMetadata: SqliteStatement;
29
+ getRevision: SqliteStatement;
30
+ saveRevision: SqliteStatement;
31
+ listRevisionsAsc: SqliteStatement;
32
+ listRevisionsDesc: SqliteStatement;
33
+ getPending: SqliteStatement;
34
+ savePending: SqliteStatement;
35
+ deletePending: SqliteStatement;
36
+ listPending: SqliteStatement;
37
+ listBlockIds: SqliteStatement;
38
+ getTransaction: SqliteStatement;
39
+ saveTransaction: SqliteStatement;
40
+ getProof: SqliteStatement;
41
+ saveProof: SqliteStatement;
42
+ getMaterialized: SqliteStatement;
43
+ saveMaterialized: SqliteStatement;
44
+ deleteMaterialized: SqliteStatement;
45
+ pageCount: SqliteStatement;
46
+ pageSize: SqliteStatement;
47
+ };
48
+
49
+ // NOTE: identity is the HANDLE object, so two handles opened over the same SQLite FILE read
50
+ // as two identities. Resolving that would mean naming the underlying database file, which
51
+ // `SqliteDb` does not expose. The package opener (`ns-opener.ts`) hands out one handle per
52
+ // file in practice, so this is the reachable case, not the complete one.
53
+ private readonly identity: StoreIdentity;
54
+
55
+ constructor(private readonly db: SqliteDb) {
56
+ this.identity = identityForHandle('sqlite-handle', db);
57
+ this.stmts = {
58
+ getMetadata: db.prepare('SELECT value FROM metadata WHERE block_id = ?'),
59
+ saveMetadata: db.prepare('INSERT OR REPLACE INTO metadata (block_id, value) VALUES (?, ?)'),
60
+ getRevision: db.prepare('SELECT action_id FROM revisions WHERE block_id = ? AND rev = ?'),
61
+ saveRevision: db.prepare('INSERT OR REPLACE INTO revisions (block_id, rev, action_id) VALUES (?, ?, ?)'),
62
+ listRevisionsAsc: db.prepare('SELECT rev, action_id FROM revisions WHERE block_id = ? AND rev BETWEEN ? AND ? ORDER BY rev ASC'),
63
+ listRevisionsDesc: db.prepare('SELECT rev, action_id FROM revisions WHERE block_id = ? AND rev BETWEEN ? AND ? ORDER BY rev DESC'),
64
+ getPending: db.prepare('SELECT value FROM pending WHERE block_id = ? AND action_id = ?'),
65
+ savePending: db.prepare('INSERT OR REPLACE INTO pending (block_id, action_id, value) VALUES (?, ?, ?)'),
66
+ deletePending: db.prepare('DELETE FROM pending WHERE block_id = ? AND action_id = ?'),
67
+ listPending: db.prepare('SELECT action_id FROM pending WHERE block_id = ? ORDER BY action_id ASC'),
68
+ // metadata.block_id is the PRIMARY KEY, so each row is a distinct block id —
69
+ // no dedup needed. NOTE: drains the whole metadata table up front; if a peer
70
+ // ever holds millions of blocks and this SELECT becomes a startup-latency
71
+ // problem, page it (LIMIT/OFFSET or keyset) — fine at current scale.
72
+ listBlockIds: db.prepare('SELECT block_id FROM metadata'),
73
+ getTransaction: db.prepare('SELECT value FROM transactions WHERE block_id = ? AND action_id = ?'),
74
+ saveTransaction: db.prepare('INSERT OR REPLACE INTO transactions (block_id, action_id, value) VALUES (?, ?, ?)'),
75
+ getProof: db.prepare('SELECT value FROM proofs WHERE block_id = ? AND rev = ?'),
76
+ saveProof: db.prepare('INSERT OR REPLACE INTO proofs (block_id, rev, value) VALUES (?, ?, ?)'),
77
+ getMaterialized: db.prepare('SELECT value FROM materialized WHERE block_id = ? AND action_id = ?'),
78
+ saveMaterialized: db.prepare('INSERT OR REPLACE INTO materialized (block_id, action_id, value) VALUES (?, ?, ?)'),
79
+ deleteMaterialized: db.prepare('DELETE FROM materialized WHERE block_id = ? AND action_id = ?'),
80
+ pageCount: db.prepare('PRAGMA page_count'),
81
+ pageSize: db.prepare('PRAGMA page_size'),
82
+ };
83
+ }
84
+
85
+ storeIdentity(): StoreIdentity {
86
+ return this.identity;
87
+ }
88
+
89
+ // --- metadata ---
90
+
91
+ async getMetadata(blockId: BlockId): Promise<Uint8Array | undefined> {
92
+ const row = await this.stmts.getMetadata.get(blockId);
93
+ return row ? (row.value as Uint8Array) : undefined;
94
+ }
95
+
96
+ async putMetadata(blockId: BlockId, value: Uint8Array): Promise<void> {
97
+ await this.stmts.saveMetadata.run(blockId, value);
98
+ }
99
+
100
+ // --- revisions ---
101
+
102
+ async getRevision(blockId: BlockId, rev: number): Promise<Uint8Array | undefined> {
103
+ const row = await this.stmts.getRevision.get(blockId, rev);
104
+ return row ? (row.action_id as Uint8Array) : undefined;
105
+ }
106
+
107
+ async putRevision(blockId: BlockId, rev: number, value: Uint8Array): Promise<void> {
108
+ await this.stmts.saveRevision.run(blockId, rev, value);
109
+ }
110
+
111
+ async *rangeRevisions(blockId: BlockId, lo: number, hi: number, reverse: boolean): AsyncIterable<[number, Uint8Array]> {
112
+ // `.all(...)` materializes every row before we yield, so no SQLite cursor
113
+ // straddles the consumer's awaits (the kernel's drain-before-yield contract).
114
+ const stmt = reverse ? this.stmts.listRevisionsDesc : this.stmts.listRevisionsAsc;
115
+ const rows = await stmt.all(blockId, lo, hi);
116
+ for (const row of rows) {
117
+ yield [row.rev as number, row.action_id as Uint8Array];
118
+ }
119
+ }
120
+
121
+ // --- pending ---
122
+
123
+ async getPending(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined> {
124
+ const row = await this.stmts.getPending.get(blockId, actionId);
125
+ return row ? (row.value as Uint8Array) : undefined;
126
+ }
127
+
128
+ async putPending(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void> {
129
+ await this.stmts.savePending.run(blockId, actionId, value);
130
+ }
131
+
132
+ async deletePending(blockId: BlockId, actionId: ActionId): Promise<void> {
133
+ await this.stmts.deletePending.run(blockId, actionId);
134
+ }
135
+
136
+ async *listPendingActionIds(blockId: BlockId): AsyncIterable<ActionId> {
137
+ // Drained by `.all(...)` before yielding — same rationale as rangeRevisions.
138
+ const rows = await this.stmts.listPending.all(blockId);
139
+ for (const row of rows) {
140
+ yield row.action_id as ActionId;
141
+ }
142
+ }
143
+
144
+ // --- transactions ---
145
+
146
+ async getTransaction(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined> {
147
+ const row = await this.stmts.getTransaction.get(blockId, actionId);
148
+ return row ? (row.value as Uint8Array) : undefined;
149
+ }
150
+
151
+ async putTransaction(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void> {
152
+ await this.stmts.saveTransaction.run(blockId, actionId, value);
153
+ }
154
+
155
+ // --- proofs (keyed (block_id, rev) like revisions; no delete — see RawStoreDriver.getProof) ---
156
+
157
+ async getProof(blockId: BlockId, rev: number): Promise<Uint8Array | undefined> {
158
+ const row = await this.stmts.getProof.get(blockId, rev);
159
+ return row ? (row.value as Uint8Array) : undefined;
160
+ }
161
+
162
+ async putProof(blockId: BlockId, rev: number, value: Uint8Array): Promise<void> {
163
+ await this.stmts.saveProof.run(blockId, rev, value);
164
+ }
165
+
166
+ // --- materialized ---
167
+
168
+ async getMaterialized(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined> {
169
+ const row = await this.stmts.getMaterialized.get(blockId, actionId);
170
+ return row ? (row.value as Uint8Array) : undefined;
171
+ }
172
+
173
+ async putMaterialized(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void> {
174
+ await this.stmts.saveMaterialized.run(blockId, actionId, value);
175
+ }
176
+
177
+ async deleteMaterialized(blockId: BlockId, actionId: ActionId): Promise<void> {
178
+ await this.stmts.deleteMaterialized.run(blockId, actionId);
179
+ }
180
+
181
+ // --- promote (the only cross-key atomic op) ---
182
+
183
+ async promote(blockId: BlockId, actionId: ActionId): Promise<void> {
184
+ await this.db.transaction(async (tx) => {
185
+ // Prepare against the open transaction so these three statements run on
186
+ // the held mutex slot without re-locking the connection (which would
187
+ // deadlock). Re-preparing is cheap — the driver caches by SQL text.
188
+ const getPending = tx.prepare('SELECT value FROM pending WHERE block_id = ? AND action_id = ?');
189
+ const saveTransaction = tx.prepare('INSERT OR REPLACE INTO transactions (block_id, action_id, value) VALUES (?, ?, ?)');
190
+ const deletePending = tx.prepare('DELETE FROM pending WHERE block_id = ? AND action_id = ?');
191
+ const row = await getPending.get(blockId, actionId);
192
+ if (!row) {
193
+ throw new Error(`Pending action ${actionId} not found for block ${blockId}`);
194
+ }
195
+ await saveTransaction.run(blockId, actionId, row.value as Uint8Array);
196
+ await deletePending.run(blockId, actionId);
197
+ });
198
+ }
199
+
200
+ // --- optional passthroughs ---
201
+
202
+ async *listBlockIds(): AsyncIterable<BlockId> {
203
+ const rows = await this.stmts.listBlockIds.all();
204
+ for (const row of rows) {
205
+ yield row.block_id as BlockId;
206
+ }
207
+ }
208
+
209
+ async approximateBytesUsed(): Promise<number> {
210
+ try {
211
+ const pageCountRow = await this.stmts.pageCount.get();
212
+ const pageSizeRow = await this.stmts.pageSize.get();
213
+ const pages = (pageCountRow?.page_count as number | undefined) ?? 0;
214
+ const size = (pageSizeRow?.page_size as number | undefined) ?? 0;
215
+ return pages * size;
216
+ } catch (err) {
217
+ log('PRAGMA page_count/page_size failed: %o', err);
218
+ return 0;
219
+ }
220
+ }
221
+ }
222
+
223
+ /**
224
+ * SQLite-backed {@link IRawStorage} for NativeScript peers, now a thin shell over
225
+ * the shared {@link KvRawStorage} kernel driven by a {@link SqliteStoreDriver}.
226
+ * The public name/constructor (`new SqliteRawStorage(db)`) is unchanged so
227
+ * existing imports keep resolving; the kernel supplies the `IRawStorage` surface
228
+ * and the driver supplies SQLite behavior.
229
+ *
230
+ * `listBlockIds`/`getApproximateBytesUsed` are re-declared here as always-present
231
+ * (the SQLite driver always implements them, so the kernel constructor always
232
+ * wires them) — the base declares them optional, but every NS consumer relies on
233
+ * them.
234
+ */
235
+ export class SqliteRawStorage extends KvRawStorage {
236
+ declare listBlockIds: () => AsyncIterable<BlockId>;
237
+ declare getApproximateBytesUsed: () => Promise<number>;
238
+ declare getStoreIdentity: () => StoreIdentity;
239
+
240
+ constructor(db: SqliteDb) {
241
+ super(new SqliteStoreDriver(db));
242
+ }
243
+ }