@aztec/kv-store 5.0.0 → 5.1.0-nightly.20260716

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.
@@ -1,13 +1,7 @@
1
- import { type Logger } from '@aztec/foundation/log';
2
- import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
3
1
  import { AztecIndexedDBStore } from './store.js';
4
2
  export { AztecIndexedDBStore } from './store.js';
5
- /**
6
- * @deprecated The IndexedDB backend is being retired. Use `@aztec/kv-store/sqlite-opfs` instead.
7
- */
8
- export declare function createStore(name: string, config: DataStoreConfig, schemaVersion?: number | undefined, log?: Logger): Promise<AztecIndexedDBStore>;
9
3
  /**
10
4
  * @deprecated The IndexedDB backend is being retired. Use `@aztec/kv-store/sqlite-opfs` instead.
11
5
  */
12
6
  export declare function openTmpStore(ephemeral?: boolean): Promise<AztecIndexedDBStore>;
13
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kZXByZWNhdGVkL2luZGV4ZWRkYi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsS0FBSyxNQUFNLEVBQWdCLE1BQU0sdUJBQXVCLENBQUM7QUFDbEUsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFHOUQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRWpELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUVqRDs7R0FFRztBQUNILHdCQUFzQixXQUFXLENBQy9CLElBQUksRUFBRSxNQUFNLEVBQ1osTUFBTSxFQUFFLGVBQWUsRUFDdkIsYUFBYSxHQUFFLE1BQU0sR0FBRyxTQUFxQixFQUM3QyxHQUFHLEdBQUUsTUFBaUMsZ0NBY3ZDO0FBRUQ7O0dBRUc7QUFDSCx3QkFBZ0IsWUFBWSxDQUFDLFNBQVMsR0FBRSxPQUFlLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBRXJGIn0=
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kZXByZWNhdGVkL2luZGV4ZWRkYi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFakQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRWpEOztHQUVHO0FBQ0gsd0JBQWdCLFlBQVksQ0FBQyxTQUFTLEdBQUUsT0FBZSxHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxDQUVyRiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/deprecated/indexeddb/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD;;GAEG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,eAAe,EACvB,aAAa,GAAE,MAAM,GAAG,SAAqB,EAC7C,GAAG,GAAE,MAAiC,gCAcvC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,GAAE,OAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAErF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/deprecated/indexeddb/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,GAAE,OAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAErF"}
@@ -1,18 +1,6 @@
1
1
  import { createLogger } from '@aztec/foundation/log';
2
- import { initStoreForRollupAndSchemaVersion } from '../../utils.js';
3
2
  import { AztecIndexedDBStore } from './store.js';
4
3
  export { AztecIndexedDBStore } from './store.js';
5
- /**
6
- * @deprecated The IndexedDB backend is being retired. Use `@aztec/kv-store/sqlite-opfs` instead.
7
- */ export async function createStore(name, config, schemaVersion = undefined, log = createLogger('kv-store')) {
8
- let { dataDirectory } = config;
9
- if (typeof dataDirectory !== 'undefined') {
10
- dataDirectory = `${dataDirectory}/${name}`;
11
- }
12
- log.info(dataDirectory ? `Creating ${name} data store at directory ${dataDirectory} with map size ${config.dataStoreMapSizeKb} KB` : `Creating ${name} ephemeral data store with map size ${config.dataStoreMapSizeKb} KB`);
13
- const store = await AztecIndexedDBStore.open(createLogger('kv-store:indexeddb'), dataDirectory ?? '', false);
14
- return initStoreForRollupAndSchemaVersion(store, schemaVersion, config.rollupAddress, log);
15
- }
16
4
  /**
17
5
  * @deprecated The IndexedDB backend is being retired. Use `@aztec/kv-store/sqlite-opfs` instead.
18
6
  */ export function openTmpStore(ephemeral = false) {
@@ -1,10 +1,8 @@
1
- import { type Logger } from '@aztec/foundation/log';
2
- import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
3
1
  import { AztecSQLiteOPFSStore } from './store.js';
4
2
  export { AztecSQLiteOPFSStore } from './store.js';
5
3
  export { SqliteEncryptionError } from './errors.js';
6
4
  export type { SqliteEncryptionErrorCode } from './errors.js';
7
- export declare function createStore(name: string, config: DataStoreConfig, schemaVersion?: number | undefined, log?: Logger): Promise<AztecSQLiteOPFSStore>;
5
+ export { OPFS_POOL_DIR_PREFIX, deleteStore, listStores, storePoolDirectory } from './manage.js';
8
6
  export declare function openTmpStore(ephemeral?: boolean): Promise<AztecSQLiteOPFSStore>;
9
7
  /**
10
8
  * Convenience helper for tests and consumers that want an encrypted sqlite-opfs
@@ -13,4 +11,4 @@ export declare function openTmpStore(ephemeral?: boolean): Promise<AztecSQLiteOP
13
11
  * on ephemeral `:memory:` databases) in an auto-generated OPFS directory.
14
12
  */
15
13
  export declare function openEncryptedStore(encryptionKey: Uint8Array, name?: string, poolDirectory?: string): Promise<AztecSQLiteOPFSStore>;
16
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zcWxpdGUtb3Bmcy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsS0FBSyxNQUFNLEVBQWdCLE1BQU0sdUJBQXVCLENBQUM7QUFDbEUsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFHOUQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRWxELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUNsRCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDcEQsWUFBWSxFQUFFLHlCQUF5QixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRTdELHdCQUFzQixXQUFXLENBQy9CLElBQUksRUFBRSxNQUFNLEVBQ1osTUFBTSxFQUFFLGVBQWUsRUFDdkIsYUFBYSxHQUFFLE1BQU0sR0FBRyxTQUFxQixFQUM3QyxHQUFHLEdBQUUsTUFBaUMsaUNBVXZDO0FBRUQsd0JBQWdCLFlBQVksQ0FBQyxTQUFTLEdBQUUsT0FBZSxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUV0RjtBQUVEOzs7OztHQUtHO0FBQ0gsd0JBQWdCLGtCQUFrQixDQUFDLGFBQWEsRUFBRSxVQUFVLEVBQUUsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLGFBQWEsQ0FBQyxFQUFFLE1BQU0saUNBRWxHIn0=
14
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zcWxpdGUtb3Bmcy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFbEQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ2xELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNwRCxZQUFZLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDN0QsT0FBTyxFQUFFLG9CQUFvQixFQUFFLFdBQVcsRUFBRSxVQUFVLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFaEcsd0JBQWdCLFlBQVksQ0FBQyxTQUFTLEdBQUUsT0FBZSxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUV0RjtBQUVEOzs7OztHQUtHO0FBQ0gsd0JBQWdCLGtCQUFrQixDQUFDLGFBQWEsRUFBRSxVQUFVLEVBQUUsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLGFBQWEsQ0FBQyxFQUFFLE1BQU0saUNBRWxHIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sqlite-opfs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAElD,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,YAAY,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAE7D,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,eAAe,EACvB,aAAa,GAAE,MAAM,GAAG,SAAqB,EAC7C,GAAG,GAAE,MAAiC,iCAUvC;AAED,wBAAgB,YAAY,CAAC,SAAS,GAAE,OAAe,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAEtF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,iCAElG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sqlite-opfs/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAElD,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,YAAY,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEhG,wBAAgB,YAAY,CAAC,SAAS,GAAE,OAAe,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAEtF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,iCAElG"}
@@ -1,14 +1,8 @@
1
1
  import { createLogger } from '@aztec/foundation/log';
2
- import { initStoreForRollupAndSchemaVersion } from '../utils.js';
3
2
  import { AztecSQLiteOPFSStore } from './store.js';
4
3
  export { AztecSQLiteOPFSStore } from './store.js';
5
4
  export { SqliteEncryptionError } from './errors.js';
6
- export async function createStore(name, config, schemaVersion = undefined, log = createLogger('kv-store')) {
7
- const { dataDirectory } = config;
8
- log.info(dataDirectory ? `Creating ${name} SQLite-OPFS data store with map size ${config.dataStoreMapSizeKb} KB` : `Creating ${name} ephemeral SQLite-OPFS data store with map size ${config.dataStoreMapSizeKb} KB`);
9
- const store = await AztecSQLiteOPFSStore.open(createLogger('kv-store:sqlite-opfs'), name, false);
10
- return initStoreForRollupAndSchemaVersion(store, schemaVersion, config.rollupAddress, log);
11
- }
5
+ export { OPFS_POOL_DIR_PREFIX, deleteStore, listStores, storePoolDirectory } from './manage.js';
12
6
  export function openTmpStore(ephemeral = false) {
13
7
  return AztecSQLiteOPFSStore.open(createLogger('kv-store:sqlite-opfs'), undefined, ephemeral);
14
8
  }
@@ -0,0 +1,20 @@
1
+ /** Prefix for the per-store OPFS SAH pool directories owned by this package. */
2
+ export declare const OPFS_POOL_DIR_PREFIX = ".aztec-kv-";
3
+ /**
4
+ * OPFS directory holding a store's SAH pool. One directory per store: the SAH-pool VFS allows only one
5
+ * concurrent instance per directory and its capacity does not grow automatically, so sharing a pool across
6
+ * stores would make concurrently opened stores contend for locks and orphaned stores exhaust pool slots.
7
+ */
8
+ export declare function storePoolDirectory(effectiveName: string): string;
9
+ /**
10
+ * Lists the names of every persistent sqlite-opfs store in this origin, by enumerating the per-store pool
11
+ * directories. Includes stores other than the current one, so wallets can surface and clean up data for
12
+ * networks/versions no longer in use.
13
+ */
14
+ export declare function listStores(): Promise<string[]>;
15
+ /**
16
+ * Permanently deletes a store by effective name (as returned by {@link listStores}). The store must be closed:
17
+ * an open store's SAH pool holds locks on the directory and the removal will reject.
18
+ */
19
+ export declare function deleteStore(effectiveName: string): Promise<void>;
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFuYWdlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3FsaXRlLW9wZnMvbWFuYWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGdGQUFnRjtBQUNoRixlQUFPLE1BQU0sb0JBQW9CLGVBQWUsQ0FBQztBQUVqRDs7OztHQUlHO0FBQ0gsd0JBQWdCLGtCQUFrQixDQUFDLGFBQWEsRUFBRSxNQUFNLEdBQUcsTUFBTSxDQUVoRTtBQUVEOzs7O0dBSUc7QUFDSCx3QkFBc0IsVUFBVSxJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQVNwRDtBQUVEOzs7R0FHRztBQUNILHdCQUFzQixXQUFXLENBQUMsYUFBYSxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBR3RFIn0=
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manage.d.ts","sourceRoot":"","sources":["../../src/sqlite-opfs/manage.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,eAAe,CAAC;AAEjD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;;GAIG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CASpD;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtE"}
@@ -0,0 +1,31 @@
1
+ /** Prefix for the per-store OPFS SAH pool directories owned by this package. */ export const OPFS_POOL_DIR_PREFIX = '.aztec-kv-';
2
+ /**
3
+ * OPFS directory holding a store's SAH pool. One directory per store: the SAH-pool VFS allows only one
4
+ * concurrent instance per directory and its capacity does not grow automatically, so sharing a pool across
5
+ * stores would make concurrently opened stores contend for locks and orphaned stores exhaust pool slots.
6
+ */ export function storePoolDirectory(effectiveName) {
7
+ return `${OPFS_POOL_DIR_PREFIX}${effectiveName}`;
8
+ }
9
+ /**
10
+ * Lists the names of every persistent sqlite-opfs store in this origin, by enumerating the per-store pool
11
+ * directories. Includes stores other than the current one, so wallets can surface and clean up data for
12
+ * networks/versions no longer in use.
13
+ */ export async function listStores() {
14
+ const root = await navigator.storage.getDirectory();
15
+ const names = [];
16
+ for await (const [entryName, handle] of root.entries()){
17
+ if (handle.kind === 'directory' && entryName.startsWith(OPFS_POOL_DIR_PREFIX)) {
18
+ names.push(entryName.slice(OPFS_POOL_DIR_PREFIX.length));
19
+ }
20
+ }
21
+ return names;
22
+ }
23
+ /**
24
+ * Permanently deletes a store by effective name (as returned by {@link listStores}). The store must be closed:
25
+ * an open store's SAH pool holds locks on the directory and the removal will reject.
26
+ */ export async function deleteStore(effectiveName) {
27
+ const root = await navigator.storage.getDirectory();
28
+ await root.removeEntry(storePoolDirectory(effectiveName), {
29
+ recursive: true
30
+ });
31
+ }
@@ -77,6 +77,18 @@ function handleClose() {
77
77
  db?.close();
78
78
  db = undefined;
79
79
  dbPath = undefined;
80
+ releasePool();
81
+ }
82
+ /**
83
+ * Releases the SAH pool's OPFS sync access handles before the terminal RPC is acked. Worker
84
+ * termination releases them only asynchronously, so without this a caller that deletes or reopens
85
+ * the store directory right after close()/delete() resolves races Chromium's cleanup
86
+ * (NoModificationAllowedError from removeEntry, or a hang installing a new pool on the directory).
87
+ * pauseVfs releases the handles without touching file contents; the worker is terminated right
88
+ * after, so the pool is never resumed.
89
+ */ function releasePool() {
90
+ pool?.pauseVfs();
91
+ pool = undefined;
80
92
  }
81
93
  async function handleExport() {
82
94
  if (!db || !dbPath) {
@@ -107,6 +119,10 @@ function handleDeleteDb(dbName) {
107
119
  } catch {
108
120
  // File may not exist; ignore.
109
121
  }
122
+ // Guarded because pauseVfs refuses (SQLITE_MISUSE) while any file is open through the VFS.
123
+ if (!db) {
124
+ releasePool();
125
+ }
110
126
  }
111
127
  function requireDb() {
112
128
  if (!db) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/kv-store",
3
- "version": "5.0.0",
3
+ "version": "5.1.0-nightly.20260716",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/interfaces/index.js",
@@ -36,12 +36,12 @@
36
36
  "./package.local.json"
37
37
  ],
38
38
  "dependencies": {
39
- "@aztec/constants": "5.0.0",
40
- "@aztec/ethereum": "5.0.0",
41
- "@aztec/foundation": "5.0.0",
42
- "@aztec/native": "5.0.0",
43
- "@aztec/sqlite3mc-wasm": "5.0.0",
44
- "@aztec/stdlib": "5.0.0",
39
+ "@aztec/constants": "5.1.0-nightly.20260716",
40
+ "@aztec/ethereum": "5.1.0-nightly.20260716",
41
+ "@aztec/foundation": "5.1.0-nightly.20260716",
42
+ "@aztec/native": "5.1.0-nightly.20260716",
43
+ "@aztec/sqlite3mc-wasm": "5.1.0-nightly.20260716",
44
+ "@aztec/stdlib": "5.1.0-nightly.20260716",
45
45
  "idb": "^8.0.0",
46
46
  "lmdb": "^3.2.0",
47
47
  "msgpackr": "^1.11.2",
@@ -1,34 +1,9 @@
1
- import { type Logger, createLogger } from '@aztec/foundation/log';
2
- import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
1
+ import { createLogger } from '@aztec/foundation/log';
3
2
 
4
- import { initStoreForRollupAndSchemaVersion } from '../../utils.js';
5
3
  import { AztecIndexedDBStore } from './store.js';
6
4
 
7
5
  export { AztecIndexedDBStore } from './store.js';
8
6
 
9
- /**
10
- * @deprecated The IndexedDB backend is being retired. Use `@aztec/kv-store/sqlite-opfs` instead.
11
- */
12
- export async function createStore(
13
- name: string,
14
- config: DataStoreConfig,
15
- schemaVersion: number | undefined = undefined,
16
- log: Logger = createLogger('kv-store'),
17
- ) {
18
- let { dataDirectory } = config;
19
- if (typeof dataDirectory !== 'undefined') {
20
- dataDirectory = `${dataDirectory}/${name}`;
21
- }
22
-
23
- log.info(
24
- dataDirectory
25
- ? `Creating ${name} data store at directory ${dataDirectory} with map size ${config.dataStoreMapSizeKb} KB`
26
- : `Creating ${name} ephemeral data store with map size ${config.dataStoreMapSizeKb} KB`,
27
- );
28
- const store = await AztecIndexedDBStore.open(createLogger('kv-store:indexeddb'), dataDirectory ?? '', false);
29
- return initStoreForRollupAndSchemaVersion(store, schemaVersion, config.rollupAddress, log);
30
- }
31
-
32
7
  /**
33
8
  * @deprecated The IndexedDB backend is being retired. Use `@aztec/kv-store/sqlite-opfs` instead.
34
9
  */
@@ -1,28 +1,11 @@
1
- import { type Logger, createLogger } from '@aztec/foundation/log';
2
- import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
1
+ import { createLogger } from '@aztec/foundation/log';
3
2
 
4
- import { initStoreForRollupAndSchemaVersion } from '../utils.js';
5
3
  import { AztecSQLiteOPFSStore } from './store.js';
6
4
 
7
5
  export { AztecSQLiteOPFSStore } from './store.js';
8
6
  export { SqliteEncryptionError } from './errors.js';
9
7
  export type { SqliteEncryptionErrorCode } from './errors.js';
10
-
11
- export async function createStore(
12
- name: string,
13
- config: DataStoreConfig,
14
- schemaVersion: number | undefined = undefined,
15
- log: Logger = createLogger('kv-store'),
16
- ) {
17
- const { dataDirectory } = config;
18
- log.info(
19
- dataDirectory
20
- ? `Creating ${name} SQLite-OPFS data store with map size ${config.dataStoreMapSizeKb} KB`
21
- : `Creating ${name} ephemeral SQLite-OPFS data store with map size ${config.dataStoreMapSizeKb} KB`,
22
- );
23
- const store = await AztecSQLiteOPFSStore.open(createLogger('kv-store:sqlite-opfs'), name, false);
24
- return initStoreForRollupAndSchemaVersion(store, schemaVersion, config.rollupAddress, log);
25
- }
8
+ export { OPFS_POOL_DIR_PREFIX, deleteStore, listStores, storePoolDirectory } from './manage.js';
26
9
 
27
10
  export function openTmpStore(ephemeral: boolean = false): Promise<AztecSQLiteOPFSStore> {
28
11
  return AztecSQLiteOPFSStore.open(createLogger('kv-store:sqlite-opfs'), undefined, ephemeral);
@@ -0,0 +1,36 @@
1
+ /** Prefix for the per-store OPFS SAH pool directories owned by this package. */
2
+ export const OPFS_POOL_DIR_PREFIX = '.aztec-kv-';
3
+
4
+ /**
5
+ * OPFS directory holding a store's SAH pool. One directory per store: the SAH-pool VFS allows only one
6
+ * concurrent instance per directory and its capacity does not grow automatically, so sharing a pool across
7
+ * stores would make concurrently opened stores contend for locks and orphaned stores exhaust pool slots.
8
+ */
9
+ export function storePoolDirectory(effectiveName: string): string {
10
+ return `${OPFS_POOL_DIR_PREFIX}${effectiveName}`;
11
+ }
12
+
13
+ /**
14
+ * Lists the names of every persistent sqlite-opfs store in this origin, by enumerating the per-store pool
15
+ * directories. Includes stores other than the current one, so wallets can surface and clean up data for
16
+ * networks/versions no longer in use.
17
+ */
18
+ export async function listStores(): Promise<string[]> {
19
+ const root = await navigator.storage.getDirectory();
20
+ const names: string[] = [];
21
+ for await (const [entryName, handle] of root.entries()) {
22
+ if (handle.kind === 'directory' && entryName.startsWith(OPFS_POOL_DIR_PREFIX)) {
23
+ names.push(entryName.slice(OPFS_POOL_DIR_PREFIX.length));
24
+ }
25
+ }
26
+ return names;
27
+ }
28
+
29
+ /**
30
+ * Permanently deletes a store by effective name (as returned by {@link listStores}). The store must be closed:
31
+ * an open store's SAH pool holds locks on the directory and the removal will reject.
32
+ */
33
+ export async function deleteStore(effectiveName: string): Promise<void> {
34
+ const root = await navigator.storage.getDirectory();
35
+ await root.removeEntry(storePoolDirectory(effectiveName), { recursive: true });
36
+ }
@@ -94,6 +94,20 @@ function handleClose(): void {
94
94
  db?.close();
95
95
  db = undefined;
96
96
  dbPath = undefined;
97
+ releasePool();
98
+ }
99
+
100
+ /**
101
+ * Releases the SAH pool's OPFS sync access handles before the terminal RPC is acked. Worker
102
+ * termination releases them only asynchronously, so without this a caller that deletes or reopens
103
+ * the store directory right after close()/delete() resolves races Chromium's cleanup
104
+ * (NoModificationAllowedError from removeEntry, or a hang installing a new pool on the directory).
105
+ * pauseVfs releases the handles without touching file contents; the worker is terminated right
106
+ * after, so the pool is never resumed.
107
+ */
108
+ function releasePool(): void {
109
+ pool?.pauseVfs();
110
+ pool = undefined;
97
111
  }
98
112
 
99
113
  async function handleExport(): Promise<Uint8Array> {
@@ -126,6 +140,10 @@ function handleDeleteDb(dbName: string): void {
126
140
  } catch {
127
141
  // File may not exist; ignore.
128
142
  }
143
+ // Guarded because pauseVfs refuses (SQLITE_MISUSE) while any file is open through the VFS.
144
+ if (!db) {
145
+ releasePool();
146
+ }
129
147
  }
130
148
 
131
149
  function requireDb(): Database {