@livestore/sqlite-wasm 0.4.0-dev.3 → 0.4.0-dev.5

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.
Files changed (74) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/browser/mod.d.ts +1 -0
  3. package/dist/browser/mod.d.ts.map +1 -1
  4. package/dist/browser/mod.js.map +1 -1
  5. package/dist/cf/BlockManager.d.ts +61 -0
  6. package/dist/cf/BlockManager.d.ts.map +1 -0
  7. package/dist/cf/BlockManager.js +157 -0
  8. package/dist/cf/BlockManager.js.map +1 -0
  9. package/dist/cf/CloudflareSqlVFS.d.ts +51 -0
  10. package/dist/cf/CloudflareSqlVFS.d.ts.map +1 -0
  11. package/dist/cf/CloudflareSqlVFS.js +351 -0
  12. package/dist/cf/CloudflareSqlVFS.js.map +1 -0
  13. package/dist/cf/CloudflareWorkerVFS.d.ts +72 -0
  14. package/dist/cf/CloudflareWorkerVFS.d.ts.map +1 -0
  15. package/dist/cf/CloudflareWorkerVFS.js +552 -0
  16. package/dist/cf/CloudflareWorkerVFS.js.map +1 -0
  17. package/dist/cf/mod.d.ts +43 -0
  18. package/dist/cf/mod.d.ts.map +1 -0
  19. package/dist/cf/mod.js +74 -0
  20. package/dist/cf/mod.js.map +1 -0
  21. package/dist/cf/test/async-storage/cloudflare-worker-vfs-advanced.test.d.ts +2 -0
  22. package/dist/cf/test/async-storage/cloudflare-worker-vfs-advanced.test.d.ts.map +1 -0
  23. package/dist/cf/test/async-storage/cloudflare-worker-vfs-advanced.test.js +314 -0
  24. package/dist/cf/test/async-storage/cloudflare-worker-vfs-advanced.test.js.map +1 -0
  25. package/dist/cf/test/async-storage/cloudflare-worker-vfs-core.test.d.ts +2 -0
  26. package/dist/cf/test/async-storage/cloudflare-worker-vfs-core.test.d.ts.map +1 -0
  27. package/dist/cf/test/async-storage/cloudflare-worker-vfs-core.test.js +266 -0
  28. package/dist/cf/test/async-storage/cloudflare-worker-vfs-core.test.js.map +1 -0
  29. package/dist/cf/test/async-storage/cloudflare-worker-vfs-integration.test.d.ts +2 -0
  30. package/dist/cf/test/async-storage/cloudflare-worker-vfs-integration.test.d.ts.map +1 -0
  31. package/dist/cf/test/async-storage/cloudflare-worker-vfs-integration.test.js +444 -0
  32. package/dist/cf/test/async-storage/cloudflare-worker-vfs-integration.test.js.map +1 -0
  33. package/dist/cf/test/async-storage/cloudflare-worker-vfs-reliability.test.d.ts +2 -0
  34. package/dist/cf/test/async-storage/cloudflare-worker-vfs-reliability.test.d.ts.map +1 -0
  35. package/dist/cf/test/async-storage/cloudflare-worker-vfs-reliability.test.js +334 -0
  36. package/dist/cf/test/async-storage/cloudflare-worker-vfs-reliability.test.js.map +1 -0
  37. package/dist/cf/test/sql/cloudflare-sql-vfs-core.test.d.ts +2 -0
  38. package/dist/cf/test/sql/cloudflare-sql-vfs-core.test.d.ts.map +1 -0
  39. package/dist/cf/test/sql/cloudflare-sql-vfs-core.test.js +354 -0
  40. package/dist/cf/test/sql/cloudflare-sql-vfs-core.test.js.map +1 -0
  41. package/dist/load-wasm/mod.node.d.ts.map +1 -1
  42. package/dist/load-wasm/mod.node.js +1 -2
  43. package/dist/load-wasm/mod.node.js.map +1 -1
  44. package/dist/load-wasm/mod.workerd.d.ts +2 -0
  45. package/dist/load-wasm/mod.workerd.d.ts.map +1 -0
  46. package/dist/load-wasm/mod.workerd.js +26 -0
  47. package/dist/load-wasm/mod.workerd.js.map +1 -0
  48. package/dist/make-sqlite-db.d.ts +1 -0
  49. package/dist/make-sqlite-db.d.ts.map +1 -1
  50. package/dist/make-sqlite-db.js.map +1 -1
  51. package/dist/node/NodeFS.d.ts +1 -2
  52. package/dist/node/NodeFS.d.ts.map +1 -1
  53. package/dist/node/NodeFS.js +1 -6
  54. package/dist/node/NodeFS.js.map +1 -1
  55. package/dist/node/mod.js +3 -8
  56. package/dist/node/mod.js.map +1 -1
  57. package/package.json +20 -7
  58. package/src/browser/mod.ts +1 -0
  59. package/src/cf/BlockManager.ts +225 -0
  60. package/src/cf/CloudflareSqlVFS.ts +450 -0
  61. package/src/cf/CloudflareWorkerVFS.ts +664 -0
  62. package/src/cf/README.md +60 -0
  63. package/src/cf/mod.ts +143 -0
  64. package/src/cf/test/README.md +224 -0
  65. package/src/cf/test/async-storage/cloudflare-worker-vfs-advanced.test.ts +389 -0
  66. package/src/cf/test/async-storage/cloudflare-worker-vfs-core.test.ts +322 -0
  67. package/src/cf/test/async-storage/cloudflare-worker-vfs-integration.test.ts +567 -0
  68. package/src/cf/test/async-storage/cloudflare-worker-vfs-reliability.test.ts +403 -0
  69. package/src/cf/test/sql/cloudflare-sql-vfs-core.test.ts +433 -0
  70. package/src/load-wasm/mod.node.ts +1 -2
  71. package/src/load-wasm/mod.workerd.ts +26 -0
  72. package/src/make-sqlite-db.ts +1 -0
  73. package/src/node/NodeFS.ts +1 -9
  74. package/src/node/mod.ts +3 -10
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CloudflareSqlVFS.js","sourceRoot":"","sources":["../../src/cf/CloudflareSqlVFS.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ import type { CfTypes } from '@livestore/common-cf';
2
+ import { FacadeVFS } from '../FacadeVFS.ts';
3
+ /**
4
+ * VFS implementation using Cloudflare DurableObjectStorage as the backend.
5
+ * Uses chunked storage with in-memory caching for synchronous operations.
6
+ *
7
+ * Storage Strategy:
8
+ * - Files are split into 64 KiB chunks for optimal SQLite I/O patterns
9
+ * - Metadata cached in memory for synchronous access
10
+ * - LRU cache for frequently accessed chunks
11
+ *
12
+ * Key Schema:
13
+ * - file:${path}:meta - File metadata (size, flags, chunkCount, created)
14
+ * - file:${path}:${chunkIndex} - File data chunks (64 KiB max)
15
+ * - index:files - Set of active file paths
16
+ */
17
+ export declare class CloudflareWorkerVFS extends FacadeVFS {
18
+ #private;
19
+ log: null;
20
+ static create(name: string, storage: CfTypes.DurableObjectStorage, module: any): Promise<CloudflareWorkerVFS>;
21
+ constructor(name: string, storage: CfTypes.DurableObjectStorage, module: any);
22
+ jOpen(zName: string, fileId: number, flags: number, pOutFlags: DataView): number;
23
+ jClose(fileId: number): number;
24
+ jRead(fileId: number, pData: Uint8Array, iOffset: number): number;
25
+ jWrite(fileId: number, pData: Uint8Array, iOffset: number): number;
26
+ jTruncate(fileId: number, iSize: number): number;
27
+ jSync(fileId: number, _flags: number): number;
28
+ jFileSize(fileId: number, pSize64: DataView): number;
29
+ jSectorSize(_fileId: number): number;
30
+ jDeviceCharacteristics(_fileId: number): number;
31
+ jAccess(zName: string, _flags: number, pResOut: DataView): number;
32
+ jDelete(zName: string, _syncDir: number): number;
33
+ close(): Promise<void>;
34
+ isReady(): Promise<boolean>;
35
+ /**
36
+ * Returns the number of SQLite files in the file system.
37
+ */
38
+ getSize(): number;
39
+ /**
40
+ * Returns the maximum number of SQLite files the file system can hold.
41
+ */
42
+ getCapacity(): number;
43
+ /**
44
+ * Increase the capacity of the file system by n.
45
+ */
46
+ addCapacity(n: number): Promise<number>;
47
+ /**
48
+ * Decrease the capacity of the file system by n. The capacity cannot be
49
+ * decreased to fewer than the current number of SQLite files in the
50
+ * file system.
51
+ */
52
+ removeCapacity(n: number): Promise<number>;
53
+ /**
54
+ * Flush all pending writes and sync to storage.
55
+ * This is useful for ensuring durability before critical operations.
56
+ */
57
+ syncToStorage(): Promise<void>;
58
+ /**
59
+ * Get statistics about the VFS for debugging and monitoring.
60
+ */
61
+ getStats(): {
62
+ activeFiles: number;
63
+ openFiles: number;
64
+ cachedChunks: number;
65
+ cachedMetadata: number;
66
+ pendingWrites: number;
67
+ maxFiles: number;
68
+ maxCacheSize: number;
69
+ chunkSize: number;
70
+ };
71
+ }
72
+ //# sourceMappingURL=CloudflareWorkerVFS.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CloudflareWorkerVFS.d.ts","sourceRoot":"","sources":["../../src/cf/CloudflareWorkerVFS.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAEnD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAoC3C;;;;;;;;;;;;;GAaG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;;IAChD,GAAG,OAAO;WAeG,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,oBAAoB,EAAE,MAAM,EAAE,GAAG;gBAMxE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,oBAAoB,EAAE,MAAM,EAAE,GAAG;IAoJ5E,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,GAAG,MAAM;IA6ChF,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAY9B,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IA6DjE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IA6DlE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAuDhD,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAe7C,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,MAAM;IAapD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAIpC,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAI/C,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,MAAM;IAYjE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAc1C,KAAK;IASL,OAAO;IAyCb;;OAEG;IACH,OAAO,IAAI,MAAM;IAIjB;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACG,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK7C;;;;OAIG;IACG,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAoChD;;;OAGG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAKpC;;OAEG;IACH,QAAQ;;;;;;;;;;CAoBT"}
@@ -0,0 +1,552 @@
1
+ import * as VFS from '@livestore/wa-sqlite/src/VFS.js';
2
+ import { FacadeVFS } from "../FacadeVFS.js";
3
+ const SECTOR_SIZE = 4096;
4
+ // Chunk size optimized for SQLite I/O patterns
5
+ // 64 KiB provides good balance between memory usage and I/O efficiency
6
+ // while staying well under DurableObjectStorage's 128 KiB limit
7
+ const CHUNK_SIZE = 64 * 1024; // 64 KiB
8
+ // Cache configuration for synchronous operations
9
+ const DEFAULT_CACHE_SIZE = 10; // Number of chunks to cache
10
+ const DEFAULT_MAX_FILES = 100; // Maximum number of files
11
+ // These file types are expected to persist in the file system outside
12
+ // a session. Other files will be removed on VFS start.
13
+ const PERSISTENT_FILE_TYPES = VFS.SQLITE_OPEN_MAIN_DB | VFS.SQLITE_OPEN_MAIN_JOURNAL | VFS.SQLITE_OPEN_SUPER_JOURNAL | VFS.SQLITE_OPEN_WAL;
14
+ /**
15
+ * VFS implementation using Cloudflare DurableObjectStorage as the backend.
16
+ * Uses chunked storage with in-memory caching for synchronous operations.
17
+ *
18
+ * Storage Strategy:
19
+ * - Files are split into 64 KiB chunks for optimal SQLite I/O patterns
20
+ * - Metadata cached in memory for synchronous access
21
+ * - LRU cache for frequently accessed chunks
22
+ *
23
+ * Key Schema:
24
+ * - file:${path}:meta - File metadata (size, flags, chunkCount, created)
25
+ * - file:${path}:${chunkIndex} - File data chunks (64 KiB max)
26
+ * - index:files - Set of active file paths
27
+ */
28
+ export class CloudflareWorkerVFS extends FacadeVFS {
29
+ log = null;
30
+ #storage;
31
+ #initialized = false;
32
+ // In-memory caches for synchronous operations
33
+ #metadataCache = new Map();
34
+ #chunkCache = new Map();
35
+ #activeFiles = new Set();
36
+ #openFiles = new Map();
37
+ // Configuration
38
+ #maxCacheSize;
39
+ #maxFiles;
40
+ static async create(name, storage, module) {
41
+ const vfs = new CloudflareWorkerVFS(name, storage, module);
42
+ await vfs.isReady();
43
+ return vfs;
44
+ }
45
+ constructor(name, storage, module) {
46
+ super(name, module);
47
+ this.#storage = storage;
48
+ this.#maxCacheSize = DEFAULT_CACHE_SIZE;
49
+ this.#maxFiles = DEFAULT_MAX_FILES;
50
+ }
51
+ // Storage key generation helpers
52
+ #getMetadataKey(path) {
53
+ return `file:${path}:meta`;
54
+ }
55
+ #getChunkKey(path, chunkIndex) {
56
+ return `file:${path}:${chunkIndex}`;
57
+ }
58
+ #getCacheKey(path, chunkIndex) {
59
+ return `${path}:${chunkIndex}`;
60
+ }
61
+ // Cache management
62
+ #evictLRUChunk() {
63
+ if (this.#chunkCache.size < this.#maxCacheSize)
64
+ return;
65
+ let oldestKey = '';
66
+ let oldestTime = Date.now();
67
+ for (const [key, entry] of this.#chunkCache) {
68
+ if (entry.lastAccessed < oldestTime) {
69
+ oldestTime = entry.lastAccessed;
70
+ oldestKey = key;
71
+ }
72
+ }
73
+ if (oldestKey) {
74
+ this.#chunkCache.delete(oldestKey);
75
+ }
76
+ }
77
+ #getCachedChunk(path, chunkIndex) {
78
+ const key = this.#getCacheKey(path, chunkIndex);
79
+ const entry = this.#chunkCache.get(key);
80
+ if (entry) {
81
+ entry.lastAccessed = Date.now();
82
+ return entry.data;
83
+ }
84
+ return undefined;
85
+ }
86
+ #setCachedChunk(path, chunkIndex, data) {
87
+ this.#evictLRUChunk();
88
+ const key = this.#getCacheKey(path, chunkIndex);
89
+ this.#chunkCache.set(key, {
90
+ data: data.slice(), // Copy the data
91
+ lastAccessed: Date.now(),
92
+ });
93
+ }
94
+ // Critical: Handle synchronous operations with async backend
95
+ // Strategy: Use aggressive caching + background sync for durability
96
+ // All reads must be served from cache, writes are cached immediately
97
+ // and synced to storage asynchronously
98
+ #pendingWrites = new Set();
99
+ #writePromises = new Map();
100
+ #scheduleWrite(path, operation) {
101
+ const key = `write:${path}`;
102
+ // Cancel any pending write for this path
103
+ if (this.#writePromises.has(key)) {
104
+ this.#pendingWrites.delete(key);
105
+ }
106
+ // Schedule new write
107
+ this.#pendingWrites.add(key);
108
+ const promise = operation().finally(() => {
109
+ this.#pendingWrites.delete(key);
110
+ this.#writePromises.delete(key);
111
+ });
112
+ this.#writePromises.set(key, promise);
113
+ }
114
+ async #flushPendingWrites() {
115
+ const promises = Array.from(this.#writePromises.values());
116
+ await Promise.all(promises);
117
+ }
118
+ async #loadMetadata(path) {
119
+ const cached = this.#metadataCache.get(path);
120
+ if (cached)
121
+ return cached;
122
+ const metadata = await this.#storage.get(this.#getMetadataKey(path));
123
+ if (metadata) {
124
+ this.#metadataCache.set(path, metadata);
125
+ }
126
+ return metadata;
127
+ }
128
+ async #saveMetadata(path, metadata) {
129
+ // TODO: Consider allowUnconfirmed: true for better performance
130
+ // Currently using strict consistency as requested
131
+ // Future optimization: explore allowUnconfirmed for non-critical writes
132
+ await this.#storage.put(this.#getMetadataKey(path), metadata);
133
+ this.#metadataCache.set(path, metadata);
134
+ }
135
+ async #loadChunk(path, chunkIndex) {
136
+ const cached = this.#getCachedChunk(path, chunkIndex);
137
+ if (cached)
138
+ return cached;
139
+ const chunk = await this.#storage.get(this.#getChunkKey(path, chunkIndex));
140
+ if (chunk) {
141
+ this.#setCachedChunk(path, chunkIndex, chunk);
142
+ }
143
+ return chunk;
144
+ }
145
+ async #saveChunk(path, chunkIndex, data) {
146
+ await this.#storage.put(this.#getChunkKey(path, chunkIndex), data);
147
+ this.#setCachedChunk(path, chunkIndex, data);
148
+ }
149
+ async #deleteFile(path) {
150
+ const metadata = await this.#loadMetadata(path);
151
+ if (!metadata)
152
+ return;
153
+ // Delete all chunks and metadata atomically
154
+ const keysToDelete = [this.#getMetadataKey(path)];
155
+ for (let i = 0; i < metadata.chunkCount; i++) {
156
+ keysToDelete.push(this.#getChunkKey(path, i));
157
+ }
158
+ await this.#storage.delete(keysToDelete);
159
+ // Clean up caches
160
+ this.#metadataCache.delete(path);
161
+ for (let i = 0; i < metadata.chunkCount; i++) {
162
+ this.#chunkCache.delete(this.#getCacheKey(path, i));
163
+ }
164
+ this.#activeFiles.delete(path);
165
+ // Update the file index
166
+ await this.#updateFileIndex();
167
+ }
168
+ jOpen(zName, fileId, flags, pOutFlags) {
169
+ try {
170
+ const path = zName ? this.#getPath(zName) : Math.random().toString(36);
171
+ const metadata = this.#metadataCache.get(path);
172
+ if (!metadata && flags & VFS.SQLITE_OPEN_CREATE) {
173
+ // Create new file
174
+ if (this.#activeFiles.size >= this.#maxFiles) {
175
+ throw new Error('cannot create file: capacity exceeded');
176
+ }
177
+ const newMetadata = {
178
+ size: 0,
179
+ flags,
180
+ chunkCount: 0,
181
+ created: Date.now(),
182
+ };
183
+ // Cache the metadata immediately for synchronous access
184
+ this.#metadataCache.set(path, newMetadata);
185
+ this.#activeFiles.add(path);
186
+ // Schedule async save to maintain durability
187
+ this.#scheduleWrite(path, () => this.#saveMetadata(path, newMetadata));
188
+ }
189
+ if (!this.#metadataCache.has(path)) {
190
+ throw new Error('file not found');
191
+ }
192
+ const handle = {
193
+ path,
194
+ flags,
195
+ metadata: this.#metadataCache.get(path),
196
+ };
197
+ this.#openFiles.set(fileId, handle);
198
+ pOutFlags.setInt32(0, flags, true);
199
+ return VFS.SQLITE_OK;
200
+ }
201
+ catch (e) {
202
+ console.error(e.message);
203
+ return VFS.SQLITE_CANTOPEN;
204
+ }
205
+ }
206
+ jClose(fileId) {
207
+ const handle = this.#openFiles.get(fileId);
208
+ if (handle) {
209
+ this.#openFiles.delete(fileId);
210
+ if (handle.flags & VFS.SQLITE_OPEN_DELETEONCLOSE) {
211
+ // Schedule async delete
212
+ this.#scheduleWrite(handle.path, () => this.#deleteFile(handle.path));
213
+ }
214
+ }
215
+ return VFS.SQLITE_OK;
216
+ }
217
+ jRead(fileId, pData, iOffset) {
218
+ try {
219
+ const handle = this.#openFiles.get(fileId);
220
+ if (!handle)
221
+ return VFS.SQLITE_IOERR;
222
+ const fileSize = handle.metadata.size;
223
+ const requestedBytes = pData.byteLength;
224
+ // Zero-length reads should always succeed
225
+ if (requestedBytes === 0) {
226
+ return VFS.SQLITE_OK;
227
+ }
228
+ if (iOffset >= fileSize) {
229
+ pData.fill(0);
230
+ return VFS.SQLITE_IOERR_SHORT_READ;
231
+ }
232
+ const bytesToRead = Math.min(requestedBytes, fileSize - iOffset);
233
+ const startChunk = Math.floor(iOffset / CHUNK_SIZE);
234
+ const endChunk = Math.floor((iOffset + bytesToRead - 1) / CHUNK_SIZE);
235
+ let bytesRead = 0;
236
+ for (let chunkIndex = startChunk; chunkIndex <= endChunk; chunkIndex++) {
237
+ const chunk = this.#getCachedChunk(handle.path, chunkIndex);
238
+ if (!chunk) {
239
+ // Cache miss - this is a problem for synchronous operation
240
+ // We should have preloaded chunks during initialization
241
+ console.warn(`Cache miss for chunk ${chunkIndex} of ${handle.path}`);
242
+ // Emergency: try to preload the chunk for future reads
243
+ this.#preloadChunks(handle.path, chunkIndex, 1).catch(console.error);
244
+ pData.fill(0, bytesRead);
245
+ return VFS.SQLITE_IOERR_SHORT_READ;
246
+ }
247
+ const chunkOffset = chunkIndex * CHUNK_SIZE;
248
+ const readStart = Math.max(0, iOffset - chunkOffset);
249
+ const readEnd = Math.min(chunk.length, iOffset + requestedBytes - chunkOffset);
250
+ const chunkBytesToRead = readEnd - readStart;
251
+ if (chunkBytesToRead > 0) {
252
+ pData.set(chunk.subarray(readStart, readEnd), bytesRead);
253
+ bytesRead += chunkBytesToRead;
254
+ }
255
+ }
256
+ if (bytesRead < requestedBytes) {
257
+ pData.fill(0, bytesRead, requestedBytes);
258
+ return VFS.SQLITE_IOERR_SHORT_READ;
259
+ }
260
+ return VFS.SQLITE_OK;
261
+ }
262
+ catch (e) {
263
+ console.error('jRead error:', e.message);
264
+ return VFS.SQLITE_IOERR;
265
+ }
266
+ }
267
+ jWrite(fileId, pData, iOffset) {
268
+ try {
269
+ const handle = this.#openFiles.get(fileId);
270
+ if (!handle)
271
+ return VFS.SQLITE_IOERR;
272
+ const bytesToWrite = pData.byteLength;
273
+ const startChunk = Math.floor(iOffset / CHUNK_SIZE);
274
+ const endChunk = Math.floor((iOffset + bytesToWrite - 1) / CHUNK_SIZE);
275
+ let bytesWritten = 0;
276
+ const chunksToSave = [];
277
+ for (let chunkIndex = startChunk; chunkIndex <= endChunk; chunkIndex++) {
278
+ const chunkOffset = chunkIndex * CHUNK_SIZE;
279
+ const writeStart = Math.max(0, iOffset - chunkOffset);
280
+ const writeEnd = Math.min(CHUNK_SIZE, iOffset + bytesToWrite - chunkOffset);
281
+ let chunk = this.#getCachedChunk(handle.path, chunkIndex);
282
+ if (!chunk) {
283
+ // Create new chunk
284
+ chunk = new Uint8Array(CHUNK_SIZE);
285
+ }
286
+ else {
287
+ // Copy existing chunk for modification
288
+ chunk = chunk.slice();
289
+ }
290
+ const chunkBytesToWrite = writeEnd - writeStart;
291
+ if (chunkBytesToWrite > 0) {
292
+ const dataOffset = bytesWritten;
293
+ chunk.set(pData.subarray(dataOffset, dataOffset + chunkBytesToWrite), writeStart);
294
+ bytesWritten += chunkBytesToWrite;
295
+ chunksToSave.push({ chunkIndex, data: chunk });
296
+ }
297
+ }
298
+ // Update metadata
299
+ const newSize = Math.max(handle.metadata.size, iOffset + bytesToWrite);
300
+ const newChunkCount = Math.ceil(newSize / CHUNK_SIZE);
301
+ handle.metadata.size = newSize;
302
+ handle.metadata.chunkCount = newChunkCount;
303
+ // Cache the modified chunks immediately
304
+ for (const { chunkIndex, data } of chunksToSave) {
305
+ this.#setCachedChunk(handle.path, chunkIndex, data);
306
+ }
307
+ // Schedule async saves to maintain durability
308
+ this.#scheduleWrite(handle.path, async () => {
309
+ await this.#saveMetadata(handle.path, handle.metadata);
310
+ await Promise.all(chunksToSave.map(({ chunkIndex, data }) => this.#saveChunk(handle.path, chunkIndex, data)));
311
+ });
312
+ return VFS.SQLITE_OK;
313
+ }
314
+ catch (e) {
315
+ console.error('jWrite error:', e.message);
316
+ return VFS.SQLITE_IOERR;
317
+ }
318
+ }
319
+ jTruncate(fileId, iSize) {
320
+ try {
321
+ const handle = this.#openFiles.get(fileId);
322
+ if (!handle)
323
+ return VFS.SQLITE_IOERR;
324
+ // const oldSize = handle.metadata.size
325
+ const newChunkCount = Math.ceil(iSize / CHUNK_SIZE);
326
+ const oldChunkCount = handle.metadata.chunkCount;
327
+ handle.metadata.size = iSize;
328
+ handle.metadata.chunkCount = newChunkCount;
329
+ // If truncating to smaller size, remove excess chunks
330
+ if (newChunkCount < oldChunkCount) {
331
+ const chunksToDelete = [];
332
+ for (let i = newChunkCount; i < oldChunkCount; i++) {
333
+ const cacheKey = this.#getCacheKey(handle.path, i);
334
+ this.#chunkCache.delete(cacheKey);
335
+ chunksToDelete.push(this.#getChunkKey(handle.path, i));
336
+ }
337
+ // Schedule async delete of excess chunks
338
+ if (chunksToDelete.length > 0) {
339
+ this.#scheduleWrite(handle.path, async () => {
340
+ await this.#storage.delete(chunksToDelete);
341
+ });
342
+ }
343
+ }
344
+ // If the last chunk needs to be truncated, update it
345
+ if (newChunkCount > 0) {
346
+ const lastChunkIndex = newChunkCount - 1;
347
+ const lastChunkSize = iSize - lastChunkIndex * CHUNK_SIZE;
348
+ if (lastChunkSize < CHUNK_SIZE) {
349
+ const lastChunk = this.#getCachedChunk(handle.path, lastChunkIndex);
350
+ if (lastChunk) {
351
+ const truncatedChunk = new Uint8Array(CHUNK_SIZE);
352
+ truncatedChunk.set(lastChunk.subarray(0, lastChunkSize));
353
+ this.#setCachedChunk(handle.path, lastChunkIndex, truncatedChunk);
354
+ this.#scheduleWrite(handle.path, () => this.#saveChunk(handle.path, lastChunkIndex, truncatedChunk));
355
+ }
356
+ }
357
+ }
358
+ // Schedule async metadata update
359
+ this.#scheduleWrite(handle.path, () => this.#saveMetadata(handle.path, handle.metadata));
360
+ return VFS.SQLITE_OK;
361
+ }
362
+ catch (e) {
363
+ console.error('jTruncate error:', e.message);
364
+ return VFS.SQLITE_IOERR;
365
+ }
366
+ }
367
+ jSync(fileId, _flags) {
368
+ try {
369
+ const handle = this.#openFiles.get(fileId);
370
+ if (!handle)
371
+ return VFS.SQLITE_IOERR;
372
+ // Force sync all pending writes for this file
373
+ // Note: DurableObjectStorage operations are already synchronous
374
+ // and atomic, so this is mostly a no-op
375
+ return VFS.SQLITE_OK;
376
+ }
377
+ catch (e) {
378
+ console.error('jSync error:', e.message);
379
+ return VFS.SQLITE_IOERR;
380
+ }
381
+ }
382
+ jFileSize(fileId, pSize64) {
383
+ try {
384
+ const handle = this.#openFiles.get(fileId);
385
+ if (!handle)
386
+ return VFS.SQLITE_IOERR;
387
+ pSize64.setBigInt64(0, BigInt(handle.metadata.size), true);
388
+ return VFS.SQLITE_OK;
389
+ }
390
+ catch (e) {
391
+ console.error('jFileSize error:', e.message);
392
+ return VFS.SQLITE_IOERR;
393
+ }
394
+ }
395
+ jSectorSize(_fileId) {
396
+ return SECTOR_SIZE;
397
+ }
398
+ jDeviceCharacteristics(_fileId) {
399
+ return VFS.SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN;
400
+ }
401
+ jAccess(zName, _flags, pResOut) {
402
+ try {
403
+ const path = this.#getPath(zName);
404
+ const exists = this.#activeFiles.has(path);
405
+ pResOut.setInt32(0, exists ? 1 : 0, true);
406
+ return VFS.SQLITE_OK;
407
+ }
408
+ catch (e) {
409
+ console.error('jAccess error:', e.message);
410
+ return VFS.SQLITE_IOERR;
411
+ }
412
+ }
413
+ jDelete(zName, _syncDir) {
414
+ try {
415
+ const path = this.#getPath(zName);
416
+ // Schedule async delete
417
+ this.#scheduleWrite(path, () => this.#deleteFile(path));
418
+ return VFS.SQLITE_OK;
419
+ }
420
+ catch (e) {
421
+ console.error('jDelete error:', e.message);
422
+ return VFS.SQLITE_IOERR;
423
+ }
424
+ }
425
+ async close() {
426
+ // Clear all caches
427
+ this.#metadataCache.clear();
428
+ this.#chunkCache.clear();
429
+ this.#activeFiles.clear();
430
+ this.#openFiles.clear();
431
+ this.#initialized = false;
432
+ }
433
+ async isReady() {
434
+ if (!this.#initialized) {
435
+ await this.#initializeStorage();
436
+ this.#initialized = true;
437
+ }
438
+ return true;
439
+ }
440
+ async #initializeStorage() {
441
+ // Load list of existing files
442
+ const fileList = await this.#storage.get('index:files');
443
+ if (fileList) {
444
+ for (const path of fileList) {
445
+ this.#activeFiles.add(path);
446
+ // Preload metadata for all files
447
+ await this.#loadMetadata(path);
448
+ // Preload first chunk of each file for better performance
449
+ await this.#loadChunk(path, 0);
450
+ }
451
+ }
452
+ // Clean up temporary files that shouldn't persist
453
+ await this.#cleanupTemporaryFiles();
454
+ // Update the file index to reflect any cleanup
455
+ await this.#updateFileIndex();
456
+ }
457
+ async #cleanupTemporaryFiles() {
458
+ for (const path of this.#activeFiles) {
459
+ const metadata = this.#metadataCache.get(path);
460
+ if (metadata &&
461
+ (metadata.flags & VFS.SQLITE_OPEN_DELETEONCLOSE || (metadata.flags & PERSISTENT_FILE_TYPES) === 0)) {
462
+ console.warn(`Cleaning up temporary file: ${path}`);
463
+ await this.#deleteFile(path);
464
+ }
465
+ }
466
+ }
467
+ /**
468
+ * Returns the number of SQLite files in the file system.
469
+ */
470
+ getSize() {
471
+ return this.#activeFiles.size;
472
+ }
473
+ /**
474
+ * Returns the maximum number of SQLite files the file system can hold.
475
+ */
476
+ getCapacity() {
477
+ return this.#maxFiles;
478
+ }
479
+ /**
480
+ * Increase the capacity of the file system by n.
481
+ */
482
+ async addCapacity(n) {
483
+ this.#maxFiles += n;
484
+ return n;
485
+ }
486
+ /**
487
+ * Decrease the capacity of the file system by n. The capacity cannot be
488
+ * decreased to fewer than the current number of SQLite files in the
489
+ * file system.
490
+ */
491
+ async removeCapacity(n) {
492
+ const currentSize = this.getSize();
493
+ const currentCapacity = this.getCapacity();
494
+ const newCapacity = Math.max(currentSize, currentCapacity - n);
495
+ const actualReduction = currentCapacity - newCapacity;
496
+ this.#maxFiles = newCapacity;
497
+ return actualReduction;
498
+ }
499
+ async #updateFileIndex() {
500
+ // Update the persistent file index
501
+ const fileList = Array.from(this.#activeFiles);
502
+ await this.#storage.put('index:files', fileList);
503
+ }
504
+ /**
505
+ * Preload chunks for a file to support synchronous reads.
506
+ * SQLite typically reads files sequentially, so we preload nearby chunks.
507
+ */
508
+ async #preloadChunks(path, startChunk, count = 3) {
509
+ const metadata = this.#metadataCache.get(path);
510
+ if (!metadata)
511
+ return;
512
+ const endChunk = Math.min(startChunk + count, metadata.chunkCount);
513
+ const promises = [];
514
+ for (let i = startChunk; i < endChunk; i++) {
515
+ if (!this.#getCachedChunk(path, i)) {
516
+ promises.push(this.#loadChunk(path, i).then(() => { }));
517
+ }
518
+ }
519
+ await Promise.all(promises);
520
+ }
521
+ /**
522
+ * Flush all pending writes and sync to storage.
523
+ * This is useful for ensuring durability before critical operations.
524
+ */
525
+ async syncToStorage() {
526
+ await this.#flushPendingWrites();
527
+ await this.#storage.sync();
528
+ }
529
+ /**
530
+ * Get statistics about the VFS for debugging and monitoring.
531
+ */
532
+ getStats() {
533
+ return {
534
+ activeFiles: this.#activeFiles.size,
535
+ openFiles: this.#openFiles.size,
536
+ cachedChunks: this.#chunkCache.size,
537
+ cachedMetadata: this.#metadataCache.size,
538
+ pendingWrites: this.#pendingWrites.size,
539
+ maxFiles: this.#maxFiles,
540
+ maxCacheSize: this.#maxCacheSize,
541
+ chunkSize: CHUNK_SIZE,
542
+ };
543
+ }
544
+ /**
545
+ * Convert a bare filename, path, or URL to a UNIX-style path.
546
+ */
547
+ #getPath(nameOrURL) {
548
+ const url = typeof nameOrURL === 'string' ? new URL(nameOrURL, 'file://localhost/') : nameOrURL;
549
+ return url.pathname;
550
+ }
551
+ }
552
+ //# sourceMappingURL=CloudflareWorkerVFS.js.map