@livestore/sqlite-wasm 0.0.0-snapshot-9507e455a5c1ff8ca4b9414bde007fe51bb2bcd0 → 0.0.0-snapshot-9a455c26eafff7fa10c95dadbab62f61092aceaa

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.
@@ -8,7 +8,7 @@ export const makeOpfsDb = ({ sqlite3, directory, fileName, }) => Effect.gen(func
8
8
  const pathSegment = safePath.length === 0 ? '' : `-${safePath}`;
9
9
  const vfsName = `opfs${pathSegment}`;
10
10
  if (sqlite3.vfs_registered.has(vfsName) === false) {
11
- const vfs = yield* AccessHandlePoolVFS.create(vfsName, directory, sqlite3.module);
11
+ const vfs = yield* Effect.promise(() => AccessHandlePoolVFS.create(vfsName, directory, sqlite3.module));
12
12
  sqlite3.vfs_register(vfs, false);
13
13
  opfsVfsMap.set(vfsName, vfs);
14
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/browser/opfs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAyB,MAAM,yBAAyB,CAAA;AAGvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAE9D,MAAM,SAAS,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;AAC9D,MAAM,UAAU,GAAG,IAAI,GAAG,EAA+B,CAAA;AAEzD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EACzB,OAAO,EACP,SAAS,EACT,QAAQ,GAKT,EAAkG,EAAE,CACnG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,kDAAkD;IAClD,MAAM,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,eAAe,EAAE,GAAG,CAAC,CAAA;IAC3D,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,CAAA;IAC/D,MAAM,OAAO,GAAG,OAAO,WAAW,EAAE,CAAA;IAEpC,IAAI,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,EAAE,CAAC;QAClD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,EAAG,OAAe,CAAC,MAAM,CAAC,CAAA;QAE1F,OAAO,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAChC,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;IAC9B,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;IACnE,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAE,CAAA;IAEpC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,CAAA;AAC3B,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/browser/opfs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAGhD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAE9D,MAAM,SAAS,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;AAC9D,MAAM,UAAU,GAAG,IAAI,GAAG,EAA+B,CAAA;AAEzD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EACzB,OAAO,EACP,SAAS,EACT,QAAQ,GAKT,EAAE,EAAE,CACH,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,kDAAkD;IAClD,MAAM,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,eAAe,EAAE,GAAG,CAAC,CAAA;IAC3D,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,CAAA;IAC/D,MAAM,OAAO,GAAG,OAAO,WAAW,EAAE,CAAA;IAEpC,IAAI,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,EAAE,CAAC;QAClD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,EAAG,OAAe,CAAC,MAAM,CAAC,CAAC,CAAA;QAEhH,OAAO,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAChC,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;IAC9B,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;IACnE,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAE,CAAA;IAEpC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,CAAA;AAC3B,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA"}
@@ -1,3 +1,3 @@
1
1
  export declare const HEADER_OFFSET_DATA = 4096;
2
- export declare const decodeAccessHandlePoolFilename: (file: File) => Promise<string>;
2
+ export declare const decodeSAHPoolFilename: (file: File) => Promise<string>;
3
3
  //# sourceMappingURL=opfs-sah-pool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"opfs-sah-pool.d.ts","sourceRoot":"","sources":["../../../src/browser/opfs/opfs-sah-pool.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,kBAAkB,OAAc,CAAA;AAO7C,eAAO,MAAM,8BAA8B,GAAU,MAAM,IAAI,KAAG,OAAO,CAAC,MAAM,CA+B/E,CAAA"}
1
+ {"version":3,"file":"opfs-sah-pool.d.ts","sourceRoot":"","sources":["../../../src/browser/opfs/opfs-sah-pool.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,kBAAkB,OAAc,CAAA;AAO7C,eAAO,MAAM,qBAAqB,GAAU,MAAM,IAAI,KAAG,OAAO,CAAC,MAAM,CA+BtE,CAAA"}
@@ -9,7 +9,7 @@ const HEADER_OFFSET_DIGEST = HEADER_CORPUS_SIZE;
9
9
  export const HEADER_OFFSET_DATA = SECTOR_SIZE;
10
10
  const PERSISTENT_FILE_TYPES = VFS.SQLITE_OPEN_MAIN_DB | VFS.SQLITE_OPEN_MAIN_JOURNAL | VFS.SQLITE_OPEN_SUPER_JOURNAL | VFS.SQLITE_OPEN_WAL;
11
11
  const textDecoder = new TextDecoder();
12
- export const decodeAccessHandlePoolFilename = async (file) => {
12
+ export const decodeSAHPoolFilename = async (file) => {
13
13
  // Read the path and digest of the path from the file.
14
14
  const corpus = new Uint8Array(await file.slice(0, HEADER_CORPUS_SIZE).arrayBuffer());
15
15
  // Delete files not expected to be present.
@@ -1 +1 @@
1
- {"version":3,"file":"opfs-sah-pool.js","sourceRoot":"","sources":["../../../src/browser/opfs/opfs-sah-pool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"opfs-sah-pool.js","sourceRoot":"","sources":["../../../src/browser/opfs/opfs-sah-pool.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livestore/sqlite-wasm",
3
- "version": "0.0.0-snapshot-9507e455a5c1ff8ca4b9414bde007fe51bb2bcd0",
3
+ "version": "0.0.0-snapshot-9a455c26eafff7fa10c95dadbab62f61092aceaa",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -30,10 +30,10 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@cloudflare/workers-types": "4.20250923.0",
33
- "@livestore/common": "0.0.0-snapshot-9507e455a5c1ff8ca4b9414bde007fe51bb2bcd0",
34
- "@livestore/common-cf": "0.0.0-snapshot-9507e455a5c1ff8ca4b9414bde007fe51bb2bcd0",
35
- "@livestore/utils": "0.0.0-snapshot-9507e455a5c1ff8ca4b9414bde007fe51bb2bcd0",
36
- "@livestore/wa-sqlite": "0.0.0-snapshot-9507e455a5c1ff8ca4b9414bde007fe51bb2bcd0"
33
+ "@livestore/common": "0.0.0-snapshot-9a455c26eafff7fa10c95dadbab62f61092aceaa",
34
+ "@livestore/common-cf": "0.0.0-snapshot-9a455c26eafff7fa10c95dadbab62f61092aceaa",
35
+ "@livestore/utils": "0.0.0-snapshot-9a455c26eafff7fa10c95dadbab62f61092aceaa",
36
+ "@livestore/wa-sqlite": "0.0.0-snapshot-9a455c26eafff7fa10c95dadbab62f61092aceaa"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/chrome": "0.1.4",
package/src/FacadeVFS.ts CHANGED
@@ -1,9 +1,4 @@
1
1
  // Based on https://github.com/rhashimoto/wa-sqlite/blob/master/src/FacadeVFS.js
2
- //
3
- // This TypeScript version lives in @livestore/sqlite-wasm instead of @livestore/wa-sqlite because:
4
- // - @livestore/wa-sqlite is a direct wrapper of upstream wa-sqlite (kept as JavaScript for easier upstream sync)
5
- // - @livestore/sqlite-wasm is where we add TypeScript abstractions on top of wa-sqlite
6
-
7
2
  /** biome-ignore-all lint/complexity/useLiteralKeys: not needed for this file */
8
3
  /** biome-ignore-all lint/correctness/noUnusedFunctionParameters: not needed for this file */
9
4
  /** biome-ignore-all lint/complexity/noUselessConstructor: keep constructor for compatibility */
@@ -0,0 +1,18 @@
1
+ // https://developer.mozilla.org/en-US/docs/Web/API/FileSystemSyncAccessHandle
2
+ interface FileSystemSyncAccessHandle {
3
+ close: () => void
4
+ flush: () => Promise<void>
5
+ getSize: () => number
6
+ read: (buffer: Uint8Array<ArrayBuffer> | Uint32Array, options?: FileSystemReadWriteOptions) => number
7
+ truncate: (newSize: number) => void
8
+ write: (buffer: Uint8Array<ArrayBuffer> | Uint32Array, options?: FileSystemReadWriteOptions) => number
9
+ seek: (offset: number) => void
10
+ }
11
+
12
+ interface FileSystemReadWriteOptions {
13
+ at?: number
14
+ }
15
+
16
+ interface FileSystemFileHandle {
17
+ createSyncAccessHandle: () => Promise<FileSystemSyncAccessHandle>
18
+ }
@@ -1,5 +1,5 @@
1
1
  import type { MakeSqliteDb, PersistenceInfo, SqliteDb } from '@livestore/common'
2
- import { Effect, Hash, type Opfs, type Scope } from '@livestore/utils/effect'
2
+ import { Effect, Hash } from '@livestore/utils/effect'
3
3
  import type { SQLiteAPI } from '@livestore/wa-sqlite'
4
4
  import type { MemoryVFS } from '@livestore/wa-sqlite/src/examples/MemoryVFS.js'
5
5
 
@@ -10,11 +10,6 @@ import { makeOpfsDb } from './opfs/index.ts'
10
10
 
11
11
  export * from './opfs/opfs-sah-pool.ts'
12
12
 
13
- type WebDatabaseReq = {
14
- dbPointer: number
15
- persistenceInfo: PersistenceInfo
16
- }
17
-
18
13
  export type WebDatabaseMetadataInMemory = {
19
14
  _tag: 'in-memory'
20
15
  vfs: MemoryVFS
@@ -52,29 +47,18 @@ export type WebDatabaseInputOpfs = {
52
47
  configureDb?: (db: SqliteDb) => void
53
48
  }
54
49
 
55
- type MakeInMemoryWebDatabase = MakeSqliteDb<WebDatabaseReq, WebDatabaseInputInMemory, WebDatabaseMetadataInMemory>
50
+ export type WebDatabaseInput = WebDatabaseInputInMemory | WebDatabaseInputOpfs
56
51
 
57
- type MakeOpfsWebDatabase = MakeSqliteDb<
58
- WebDatabaseReq,
59
- WebDatabaseInputOpfs,
60
- WebDatabaseMetadataOpfs,
61
- Opfs.Opfs | Scope.Scope
52
+ export type MakeWebSqliteDb = MakeSqliteDb<
53
+ { dbPointer: number; persistenceInfo: PersistenceInfo },
54
+ WebDatabaseInput,
55
+ WebDatabaseMetadata
62
56
  >
63
57
 
64
- export function sqliteDbFactory({ sqlite3 }: { sqlite3: SQLiteAPI }) {
65
- function makeDb(input: WebDatabaseInputInMemory): ReturnType<MakeInMemoryWebDatabase>
66
- function makeDb(input: WebDatabaseInputOpfs): ReturnType<MakeOpfsWebDatabase>
67
- function makeDb(
68
- input: WebDatabaseInputInMemory | WebDatabaseInputOpfs,
69
- ): ReturnType<
70
- MakeSqliteDb<
71
- WebDatabaseReq,
72
- WebDatabaseInputInMemory | WebDatabaseInputOpfs,
73
- WebDatabaseMetadata,
74
- Opfs.Opfs | Scope.Scope
75
- >
76
- > {
77
- return Effect.gen(function* () {
58
+ export const sqliteDbFactory =
59
+ ({ sqlite3 }: { sqlite3: SQLiteAPI }): MakeWebSqliteDb =>
60
+ (input: WebDatabaseInput) =>
61
+ Effect.gen(function* () {
78
62
  if (input._tag === 'in-memory') {
79
63
  const { dbPointer, vfs } = makeInMemoryDb(sqlite3)
80
64
  return makeSqliteDb<WebDatabaseMetadataInMemory>({
@@ -89,7 +73,7 @@ export function sqliteDbFactory({ sqlite3 }: { sqlite3: SQLiteAPI }) {
89
73
  fileName: ':memory:',
90
74
  },
91
75
  },
92
- })
76
+ }) as any
93
77
  }
94
78
 
95
79
  // TODO figure out the actual max length
@@ -126,9 +110,3 @@ export function sqliteDbFactory({ sqlite3 }: { sqlite3: SQLiteAPI }) {
126
110
  },
127
111
  })
128
112
  })
129
- }
130
-
131
- return makeDb
132
- }
133
-
134
- export type MakeWebSqliteDb = ReturnType<typeof sqliteDbFactory>
@@ -1,5 +1,5 @@
1
+ import { Effect, Schedule, Schema } from '@livestore/utils/effect'
1
2
  // Based on https://github.com/rhashimoto/wa-sqlite/blob/master/src/examples/AccessHandlePoolVFS.js
2
- import { Effect, Opfs, Runtime, Schedule, Schema, type Scope, Stream } from '@livestore/utils/effect'
3
3
  import * as VFS from '@livestore/wa-sqlite/src/VFS.js'
4
4
  import { FacadeVFS } from '../../FacadeVFS.ts'
5
5
 
@@ -62,9 +62,6 @@ export class AccessHandlePoolVFS extends FacadeVFS {
62
62
  #directoryPath
63
63
  #directoryHandle: FileSystemDirectoryHandle | undefined
64
64
 
65
- // Runtime for executing Effect operations
66
- readonly #runtime: Runtime.Runtime<Opfs.Opfs | Scope.Scope>
67
-
68
65
  // The OPFS files all have randomly-generated names that do not match
69
66
  // the SQLite files whose data they contain. This map links those names
70
67
  // with their respective OPFS access handles.
@@ -78,33 +75,17 @@ export class AccessHandlePoolVFS extends FacadeVFS {
78
75
 
79
76
  #mapIdToFile = new Map<number, { path: string; flags: number; accessHandle: FileSystemSyncAccessHandle }>()
80
77
 
81
- static create = Effect.fn(function* (name: string, directoryPath: string, module: any) {
82
- const runtime = yield* Effect.runtime<Opfs.Opfs | Scope.Scope>()
83
- const vfs = new AccessHandlePoolVFS({ name, directoryPath, module, runtime })
84
- yield* Effect.promise(() => vfs.isReady())
78
+ static async create(name: string, directoryPath: string, module: any) {
79
+ const vfs = new AccessHandlePoolVFS(name, directoryPath, module)
80
+ await vfs.isReady()
85
81
  return vfs
86
- })
87
-
88
- constructor({
89
- name,
90
- directoryPath,
91
- module,
92
- runtime,
93
- }: { name: string; directoryPath: string; module: any; runtime: Runtime.Runtime<Opfs.Opfs | Scope.Scope> }) {
82
+ }
83
+
84
+ constructor(name: string, directoryPath: string, module: any) {
94
85
  super(name, module)
95
86
  this.#directoryPath = directoryPath
96
- this.#runtime = runtime
97
87
  }
98
88
 
99
- /**
100
- * Get the OPFS file name that contains the data for the given SQLite file.
101
- *
102
- * @remarks
103
- *
104
- * This would be for one of the files in the pool managed by this VFS.
105
- * It's not the same as the SQLite file name. It's a randomly-generated
106
- * string that is not meaningful to the application.
107
- */
108
89
  getOpfsFileName(zName: string) {
109
90
  const path = this.#getPath(zName)
110
91
  const accessHandle = this.#mapPathToAccessHandle.get(path)!
@@ -131,7 +112,7 @@ export class AccessHandlePoolVFS extends FacadeVFS {
131
112
  })
132
113
  }
133
114
 
134
- const fileSize = Opfs.Opfs.syncGetSize(accessHandle).pipe(Runtime.runSync(this.#runtime))
115
+ const fileSize = accessHandle.getSize()
135
116
  if (fileSize <= HEADER_OFFSET_DATA) {
136
117
  throw new OpfsError({
137
118
  path,
@@ -143,9 +124,7 @@ export class AccessHandlePoolVFS extends FacadeVFS {
143
124
 
144
125
  const payloadSize = fileSize - HEADER_OFFSET_DATA
145
126
  const payload = new Uint8Array(payloadSize)
146
- const bytesRead = Opfs.Opfs.syncRead(accessHandle, payload, { at: HEADER_OFFSET_DATA }).pipe(
147
- Runtime.runSync(this.#runtime),
148
- )
127
+ const bytesRead = accessHandle.read(payload, { at: HEADER_OFFSET_DATA })
149
128
  if (bytesRead !== payloadSize) {
150
129
  throw new OpfsError({
151
130
  path,
@@ -158,7 +137,7 @@ export class AccessHandlePoolVFS extends FacadeVFS {
158
137
  resetAccessHandle(zName: string) {
159
138
  const path = this.#getPath(zName)
160
139
  const accessHandle = this.#mapPathToAccessHandle.get(path)!
161
- Opfs.Opfs.syncTruncate(accessHandle, HEADER_OFFSET_DATA).pipe(Runtime.runSync(this.#runtime))
140
+ accessHandle.truncate(HEADER_OFFSET_DATA)
162
141
  // accessHandle.write(new Uint8Array(), { at: HEADER_OFFSET_DATA })
163
142
  // accessHandle.flush()
164
143
  }
@@ -199,7 +178,7 @@ export class AccessHandlePoolVFS extends FacadeVFS {
199
178
  jClose(fileId: number): number {
200
179
  const file = this.#mapIdToFile.get(fileId)
201
180
  if (file) {
202
- Opfs.Opfs.syncFlush(file.accessHandle).pipe(Runtime.runSync(this.#runtime))
181
+ file.accessHandle.flush()
203
182
  this.#mapIdToFile.delete(fileId)
204
183
  if (file.flags & VFS.SQLITE_OPEN_DELETEONCLOSE) {
205
184
  this.#deletePath(file.path)
@@ -210,9 +189,9 @@ export class AccessHandlePoolVFS extends FacadeVFS {
210
189
 
211
190
  jRead(fileId: number, pData: Uint8Array<ArrayBuffer>, iOffset: number): number {
212
191
  const file = this.#mapIdToFile.get(fileId)!
213
- const nBytes = Opfs.Opfs.syncRead(file.accessHandle, pData.subarray(), {
192
+ const nBytes = file.accessHandle.read(pData.subarray(), {
214
193
  at: HEADER_OFFSET_DATA + iOffset,
215
- }).pipe(Runtime.runSync(this.#runtime))
194
+ })
216
195
  if (nBytes < pData.byteLength) {
217
196
  pData.fill(0, nBytes, pData.byteLength)
218
197
  return VFS.SQLITE_IOERR_SHORT_READ
@@ -222,27 +201,27 @@ export class AccessHandlePoolVFS extends FacadeVFS {
222
201
 
223
202
  jWrite(fileId: number, pData: Uint8Array<ArrayBuffer>, iOffset: number): number {
224
203
  const file = this.#mapIdToFile.get(fileId)!
225
- const nBytes = Opfs.Opfs.syncWrite(file.accessHandle, pData.subarray(), {
204
+ const nBytes = file.accessHandle.write(pData.subarray(), {
226
205
  at: HEADER_OFFSET_DATA + iOffset,
227
- }).pipe(Runtime.runSync(this.#runtime))
206
+ })
228
207
  return nBytes === pData.byteLength ? VFS.SQLITE_OK : VFS.SQLITE_IOERR
229
208
  }
230
209
 
231
210
  jTruncate(fileId: number, iSize: number): number {
232
211
  const file = this.#mapIdToFile.get(fileId)!
233
- Opfs.Opfs.syncTruncate(file.accessHandle, HEADER_OFFSET_DATA + iSize).pipe(Runtime.runSync(this.#runtime))
212
+ file.accessHandle.truncate(HEADER_OFFSET_DATA + iSize)
234
213
  return VFS.SQLITE_OK
235
214
  }
236
215
 
237
216
  jSync(fileId: number, _flags: number): number {
238
217
  const file = this.#mapIdToFile.get(fileId)!
239
- Opfs.Opfs.syncFlush(file.accessHandle).pipe(Runtime.runSync(this.#runtime))
218
+ file.accessHandle.flush()
240
219
  return VFS.SQLITE_OK
241
220
  }
242
221
 
243
222
  jFileSize(fileId: number, pSize64: DataView): number {
244
223
  const file = this.#mapIdToFile.get(fileId)!
245
- const size = Opfs.Opfs.syncGetSize(file.accessHandle).pipe(Runtime.runSync(this.#runtime)) - HEADER_OFFSET_DATA
224
+ const size = file.accessHandle.getSize() - HEADER_OFFSET_DATA
246
225
  pSize64.setBigInt64(0, BigInt(size), true)
247
226
  return VFS.SQLITE_OK
248
227
  }
@@ -267,16 +246,20 @@ export class AccessHandlePoolVFS extends FacadeVFS {
267
246
  return VFS.SQLITE_OK
268
247
  }
269
248
 
270
- close() {
249
+ async close() {
271
250
  this.#releaseAccessHandles()
272
251
  }
273
252
 
274
253
  async isReady() {
275
254
  if (!this.#directoryHandle) {
276
255
  // All files are stored in a single directory.
277
- this.#directoryHandle = await Opfs.getDirectoryHandleByPath(this.#directoryPath, { create: true }).pipe(
278
- Runtime.runPromise(this.#runtime),
279
- )
256
+ let handle = await navigator.storage.getDirectory()
257
+ for (const d of this.#directoryPath.split('/')) {
258
+ if (d) {
259
+ handle = await handle.getDirectoryHandle(d, { create: true })
260
+ }
261
+ }
262
+ this.#directoryHandle = handle
280
263
 
281
264
  await this.#acquireAccessHandles()
282
265
  if (this.getCapacity() === 0) {
@@ -316,12 +299,14 @@ export class AccessHandlePoolVFS extends FacadeVFS {
316
299
  async addCapacity(n: number): Promise<number> {
317
300
  for (let i = 0; i < n; ++i) {
318
301
  const name = Math.random().toString(36).replace('0.', '')
319
- const accessHandle = await Opfs.Opfs.getFileHandle(this.#directoryHandle!, name, { create: true }).pipe(
320
- Effect.andThen((handle) => Opfs.Opfs.createSyncAccessHandle(handle)),
321
- Effect.mapError((error) => new OpfsError({ cause: error, path: name })),
322
- Effect.retry(Schedule.exponentialBackoff10Sec),
323
- Runtime.runPromise(this.#runtime),
324
- )
302
+ const handle = await this.#directoryHandle!.getFileHandle(name, {
303
+ create: true,
304
+ })
305
+
306
+ const accessHandle = await Effect.tryPromise({
307
+ try: () => handle.createSyncAccessHandle(),
308
+ catch: (cause) => new OpfsError({ cause, path: name }),
309
+ }).pipe(Effect.retry(Schedule.exponentialBackoff10Sec), Effect.runPromise)
325
310
  this.#mapAccessHandleToName.set(accessHandle, name)
326
311
 
327
312
  this.#setAssociatedPath(accessHandle, '', 0)
@@ -341,7 +326,7 @@ export class AccessHandlePoolVFS extends FacadeVFS {
341
326
 
342
327
  const name = this.#mapAccessHandleToName.get(accessHandle)!
343
328
  accessHandle.close()
344
- Opfs.Opfs.removeEntry(this.#directoryHandle!, name).pipe(Runtime.runPromise(this.#runtime))
329
+ await this.#directoryHandle!.removeEntry(name)
345
330
  this.#mapAccessHandleToName.delete(accessHandle)
346
331
  this.#availableAccessHandles.delete(accessHandle)
347
332
  ++nRemoved
@@ -350,24 +335,21 @@ export class AccessHandlePoolVFS extends FacadeVFS {
350
335
  }
351
336
 
352
337
  async #acquireAccessHandles() {
353
- const handlesStream = Opfs.Opfs.values(this.#directoryHandle!).pipe(Runtime.runSync(this.#runtime))
354
-
355
338
  // Enumerate all the files in the directory.
356
- const files = await handlesStream.pipe(
357
- Stream.filter((handle): handle is FileSystemFileHandle => handle.kind === 'file'),
358
- Stream.map((fileHandle) => [fileHandle.name, fileHandle] as const),
359
- Stream.runCollectReadonlyArray,
360
- Runtime.runPromise(this.#runtime),
361
- )
339
+ const files = [] as [string, FileSystemFileHandle][]
340
+ for await (const [name, handle] of this.#directoryHandle!) {
341
+ if (handle.kind === 'file') {
342
+ files.push([name, handle as FileSystemFileHandle])
343
+ }
344
+ }
362
345
 
363
346
  // Open access handles in parallel, separating associated and unassociated.
364
347
  await Promise.all(
365
348
  files.map(async ([name, handle]) => {
366
- const accessHandle = await Opfs.Opfs.createSyncAccessHandle(handle).pipe(
367
- Effect.mapError((error) => new OpfsError({ cause: error, path: name })),
368
- Effect.retry(Schedule.exponentialBackoff10Sec),
369
- Runtime.runPromise(this.#runtime),
370
- )
349
+ const accessHandle = await Effect.tryPromise({
350
+ try: () => handle.createSyncAccessHandle(),
351
+ catch: (cause) => new OpfsError({ cause, path: name }),
352
+ }).pipe(Effect.retry(Schedule.exponentialBackoff10Sec), Effect.runPromise)
371
353
  this.#mapAccessHandleToName.set(accessHandle, name)
372
354
  const path = this.#getAssociatedPath(accessHandle)
373
355
  if (path) {
@@ -396,7 +378,7 @@ export class AccessHandlePoolVFS extends FacadeVFS {
396
378
  #getAssociatedPath(accessHandle: FileSystemSyncAccessHandle): string {
397
379
  // Read the path and digest of the path from the file.
398
380
  const corpus = new Uint8Array(HEADER_CORPUS_SIZE)
399
- Opfs.Opfs.syncRead(accessHandle, corpus, { at: 0 }).pipe(Runtime.runSync(this.#runtime))
381
+ accessHandle.read(corpus, { at: 0 })
400
382
 
401
383
  // Delete files not expected to be present.
402
384
  const dataView = new DataView(corpus.buffer, corpus.byteOffset)
@@ -408,7 +390,7 @@ export class AccessHandlePoolVFS extends FacadeVFS {
408
390
  }
409
391
 
410
392
  const fileDigest = new Uint32Array(HEADER_DIGEST_SIZE / 4)
411
- Opfs.Opfs.syncRead(accessHandle, fileDigest, { at: HEADER_OFFSET_DIGEST }).pipe(Runtime.runSync(this.#runtime))
393
+ accessHandle.read(fileDigest, { at: HEADER_OFFSET_DIGEST })
412
394
 
413
395
  // Verify the digest.
414
396
  const computedDigest = this.#computeDigest(corpus)
@@ -420,7 +402,7 @@ export class AccessHandlePoolVFS extends FacadeVFS {
420
402
  // truncated in #setAssociatedPath after the header is written. If
421
403
  // an interruption occurs right before the truncation then garbage
422
404
  // may remain in the file.
423
- Opfs.Opfs.syncTruncate(accessHandle, HEADER_OFFSET_DATA).pipe(Runtime.runSync(this.#runtime))
405
+ accessHandle.truncate(HEADER_OFFSET_DATA)
424
406
  }
425
407
  return new TextDecoder().decode(corpus.subarray(0, pathBytes))
426
408
  } else {
@@ -448,9 +430,9 @@ export class AccessHandlePoolVFS extends FacadeVFS {
448
430
 
449
431
  // Write the OPFS file header, including the digest.
450
432
  const digest = this.#computeDigest(corpus)
451
- Opfs.Opfs.syncWrite(accessHandle, corpus, { at: 0 }).pipe(Runtime.runSync(this.#runtime))
452
- Opfs.Opfs.syncWrite(accessHandle, digest, { at: HEADER_OFFSET_DIGEST }).pipe(Runtime.runSync(this.#runtime))
453
- Opfs.Opfs.syncFlush(accessHandle).pipe(Runtime.runSync(this.#runtime))
433
+ accessHandle.write(corpus, { at: 0 })
434
+ accessHandle.write(digest, { at: HEADER_OFFSET_DIGEST })
435
+ accessHandle.flush()
454
436
 
455
437
  if (path) {
456
438
  this.#mapPathToAccessHandle.set(path, accessHandle)
@@ -458,7 +440,7 @@ export class AccessHandlePoolVFS extends FacadeVFS {
458
440
  } else {
459
441
  // This OPFS file doesn't represent any SQLite file so it doesn't
460
442
  // need to keep any data.
461
- Opfs.Opfs.syncTruncate(accessHandle, HEADER_OFFSET_DATA).pipe(Runtime.runSync(this.#runtime))
443
+ accessHandle.truncate(HEADER_OFFSET_DATA)
462
444
  this.#availableAccessHandles.add(accessHandle)
463
445
  }
464
446
  }
@@ -1,4 +1,4 @@
1
- import { Effect, type Opfs, type Scope } from '@livestore/utils/effect'
1
+ import { Effect } from '@livestore/utils/effect'
2
2
  import type * as WaSqlite from '@livestore/wa-sqlite'
3
3
 
4
4
  import { AccessHandlePoolVFS } from './AccessHandlePoolVFS.ts'
@@ -14,7 +14,7 @@ export const makeOpfsDb = ({
14
14
  sqlite3: WaSqlite.SQLiteAPI
15
15
  directory: string
16
16
  fileName: string
17
- }): Effect.Effect<{ dbPointer: number; vfs: AccessHandlePoolVFS }, never, Opfs.Opfs | Scope.Scope> =>
17
+ }) =>
18
18
  Effect.gen(function* () {
19
19
  // Replace all special characters with underscores
20
20
  const safePath = directory.replaceAll(/["*/:<>?\\|]/g, '_')
@@ -22,7 +22,7 @@ export const makeOpfsDb = ({
22
22
  const vfsName = `opfs${pathSegment}`
23
23
 
24
24
  if (sqlite3.vfs_registered.has(vfsName) === false) {
25
- const vfs = yield* AccessHandlePoolVFS.create(vfsName, directory, (sqlite3 as any).module)
25
+ const vfs = yield* Effect.promise(() => AccessHandlePoolVFS.create(vfsName, directory, (sqlite3 as any).module))
26
26
 
27
27
  sqlite3.vfs_register(vfs, false)
28
28
  opfsVfsMap.set(vfsName, vfs)
@@ -14,7 +14,7 @@ const PERSISTENT_FILE_TYPES =
14
14
 
15
15
  const textDecoder = new TextDecoder()
16
16
 
17
- export const decodeAccessHandlePoolFilename = async (file: File): Promise<string> => {
17
+ export const decodeSAHPoolFilename = async (file: File): Promise<string> => {
18
18
  // Read the path and digest of the path from the file.
19
19
  const corpus = new Uint8Array(await file.slice(0, HEADER_CORPUS_SIZE).arrayBuffer())
20
20