@livestore/sqlite-wasm 0.4.0-dev.21 → 0.4.0-dev.23

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 (79) hide show
  1. package/README.md +1 -1
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/FacadeVFS.d.ts +0 -1
  4. package/dist/FacadeVFS.d.ts.map +1 -1
  5. package/dist/FacadeVFS.js +9 -14
  6. package/dist/FacadeVFS.js.map +1 -1
  7. package/dist/browser/mod.d.ts +2 -2
  8. package/dist/browser/mod.d.ts.map +1 -1
  9. package/dist/browser/mod.js +2 -2
  10. package/dist/browser/mod.js.map +1 -1
  11. package/dist/browser/opfs/AccessHandlePoolVFS.d.ts.map +1 -1
  12. package/dist/browser/opfs/AccessHandlePoolVFS.js +15 -13
  13. package/dist/browser/opfs/AccessHandlePoolVFS.js.map +1 -1
  14. package/dist/browser/opfs/opfs-sah-pool.js +3 -3
  15. package/dist/browser/opfs/opfs-sah-pool.js.map +1 -1
  16. package/dist/cf/CloudflareDurableObjectVFS.d.ts +104 -0
  17. package/dist/cf/CloudflareDurableObjectVFS.d.ts.map +1 -0
  18. package/dist/cf/CloudflareDurableObjectVFS.js +281 -0
  19. package/dist/cf/CloudflareDurableObjectVFS.js.map +1 -0
  20. package/dist/cf/CloudflareWorkerVFS.d.ts.map +1 -1
  21. package/dist/cf/CloudflareWorkerVFS.js +29 -28
  22. package/dist/cf/CloudflareWorkerVFS.js.map +1 -1
  23. package/dist/cf/mod.d.ts +3 -4
  24. package/dist/cf/mod.d.ts.map +1 -1
  25. package/dist/cf/mod.js +4 -12
  26. package/dist/cf/mod.js.map +1 -1
  27. package/dist/cf/test/async-storage/cloudflare-worker-vfs-advanced.test.js +5 -4
  28. package/dist/cf/test/async-storage/cloudflare-worker-vfs-advanced.test.js.map +1 -1
  29. package/dist/cf/test/async-storage/cloudflare-worker-vfs-core.test.js +3 -3
  30. package/dist/cf/test/async-storage/cloudflare-worker-vfs-core.test.js.map +1 -1
  31. package/dist/cf/test/async-storage/cloudflare-worker-vfs-integration.test.js +3 -3
  32. package/dist/cf/test/async-storage/cloudflare-worker-vfs-integration.test.js.map +1 -1
  33. package/dist/cf/test/async-storage/cloudflare-worker-vfs-reliability.test.js +3 -3
  34. package/dist/cf/test/async-storage/cloudflare-worker-vfs-reliability.test.js.map +1 -1
  35. package/dist/cf/test/sql/cloudflare-sql-vfs-core.test.js +194 -179
  36. package/dist/cf/test/sql/cloudflare-sql-vfs-core.test.js.map +1 -1
  37. package/dist/in-memory-vfs.d.ts.map +1 -1
  38. package/dist/in-memory-vfs.js +0 -1
  39. package/dist/in-memory-vfs.js.map +1 -1
  40. package/dist/load-wasm/mod.node.js +1 -1
  41. package/dist/load-wasm/mod.node.js.map +1 -1
  42. package/dist/load-wasm/mod.workerd.d.ts.map +1 -1
  43. package/dist/load-wasm/mod.workerd.js.map +1 -1
  44. package/dist/make-sqlite-db.d.ts.map +1 -1
  45. package/dist/make-sqlite-db.js +16 -4
  46. package/dist/make-sqlite-db.js.map +1 -1
  47. package/dist/node/NodeFS.d.ts.map +1 -1
  48. package/dist/node/NodeFS.js +13 -13
  49. package/dist/node/NodeFS.js.map +1 -1
  50. package/package.json +54 -15
  51. package/src/FacadeVFS.ts +9 -14
  52. package/src/browser/mod.ts +1 -1
  53. package/src/browser/opfs/AccessHandlePoolVFS.ts +33 -25
  54. package/src/browser/opfs/opfs-sah-pool.ts +3 -3
  55. package/src/cf/CloudflareDurableObjectVFS.ts +325 -0
  56. package/src/cf/CloudflareWorkerVFS.ts +41 -39
  57. package/src/cf/README.md +3 -3
  58. package/src/cf/mod.ts +10 -15
  59. package/src/cf/test/README.md +55 -26
  60. package/src/cf/test/async-storage/cloudflare-worker-vfs-advanced.test.ts +6 -4
  61. package/src/cf/test/async-storage/cloudflare-worker-vfs-core.test.ts +4 -3
  62. package/src/cf/test/async-storage/cloudflare-worker-vfs-integration.test.ts +4 -3
  63. package/src/cf/test/async-storage/cloudflare-worker-vfs-reliability.test.ts +4 -3
  64. package/src/cf/test/sql/cloudflare-sql-vfs-core.test.ts +228 -197
  65. package/src/in-memory-vfs.ts +0 -1
  66. package/src/load-wasm/mod.node.ts +1 -1
  67. package/src/load-wasm/mod.workerd.ts +0 -1
  68. package/src/make-sqlite-db.ts +24 -4
  69. package/src/node/NodeFS.ts +24 -23
  70. package/dist/cf/BlockManager.d.ts +0 -61
  71. package/dist/cf/BlockManager.d.ts.map +0 -1
  72. package/dist/cf/BlockManager.js +0 -157
  73. package/dist/cf/BlockManager.js.map +0 -1
  74. package/dist/cf/CloudflareSqlVFS.d.ts +0 -51
  75. package/dist/cf/CloudflareSqlVFS.d.ts.map +0 -1
  76. package/dist/cf/CloudflareSqlVFS.js +0 -351
  77. package/dist/cf/CloudflareSqlVFS.js.map +0 -1
  78. package/src/cf/BlockManager.ts +0 -225
  79. package/src/cf/CloudflareSqlVFS.ts +0 -450
@@ -5,11 +5,13 @@ This directory contains comprehensive tests for both SQLite WASM VFS implementat
5
5
  ## Directory Structure
6
6
 
7
7
  ### `/sql/` - SQL Storage Tests
8
- Tests for the CloudflareSqlVFS implementation, which uses Cloudflare's DurableObject SQL API for storage.
8
+
9
+ Tests for the CloudflareDurableObjectVFS implementation, which uses Cloudflare's [SQLite in DurableObjects](https://developers.cloudflare.com/durable-objects/api/sql-storage/) for storage.
9
10
 
10
11
  - **`cloudflare-sql-vfs-core.test.ts`** - Core SQL VFS functionality tests
11
12
 
12
- ### `/async-storage/` - Async Storage Tests
13
+ ### `/async-storage/` - Async Storage Tests
14
+
13
15
  Tests for the CloudflareWorkerVFS implementation, which uses DurableObjectStorage (key-value) for file storage.
14
16
 
15
17
  - **`cloudflare-worker-vfs-core.test.ts`** - Basic VFS operations (open, read, write, close, sync)
@@ -20,19 +22,22 @@ Tests for the CloudflareWorkerVFS implementation, which uses DurableObjectStorag
20
22
  ## Test Architecture
21
23
 
22
24
  ### Testing Framework
25
+
23
26
  - **Vitest** with **@cloudflare/vitest-pool-workers** for Workers runtime testing
24
27
  - **Isolated Storage** - Each test gets fresh storage instances
25
28
  - **Real Runtime** - Tests run in the actual Cloudflare Workers runtime environment
26
29
 
27
30
  ## VFS Implementation Comparison
28
31
 
29
- ### SQL Storage VFS (`CloudflareSqlVFS`)
30
- - **Backend**: Cloudflare DurableObject SQL API
31
- - **Storage Model**: Relational tables with blocks and metadata
32
- - **Advantages**: ACID transactions, complex queries, relational integrity
32
+ ### SQL Storage VFS (`CloudflareDurableObjectVFS`)
33
+
34
+ - **Backend**: Cloudflare's SQLite in Durable Objects
35
+ - **Storage Model**: Single `vfs_pages` table keyed by file path and page number
36
+ - **Advantages**: Simple synchronous SQL storage with direct page lookups
33
37
  - **Use Case**: Applications requiring complex data relationships
34
38
 
35
- ### Async Storage VFS (`CloudflareWorkerVFS`)
39
+ ### Async Storage VFS (`CloudflareWorkerVFS`)
40
+
36
41
  - **Backend**: DurableObjectStorage (key-value)
37
42
  - **Storage Model**: 64 KiB chunks with LRU caching
38
43
  - **Advantages**: Simple API, optimized for large files, better caching
@@ -41,11 +46,14 @@ Tests for the CloudflareWorkerVFS implementation, which uses DurableObjectStorag
41
46
  ## Key Design Decisions Tested
42
47
 
43
48
  ### SQL Storage Approach
44
- - **Block-based Storage**: Files stored as blocks in SQL tables
45
- - **Metadata Management**: File metadata in dedicated tables
46
- - **Transaction Safety**: ACID compliance for data integrity
49
+
50
+ - **Page-based Storage**: SQLite pages stored directly in `vfs_pages`
51
+ - **File-path Isolation**: Each logical SQLite file is scoped by `file_path`
52
+ - **Handle Tracking**: Open SQLite file handles map back to persisted file paths
53
+ - **Transaction Model**: Page writes are persisted directly through Durable Object SQL
47
54
 
48
55
  ### Async Storage Approach
56
+
49
57
  - **64 KiB Chunking Strategy**: Optimized for SQLite I/O patterns
50
58
  - **Synchronous Interface with Async Backend**: Aggressive caching + background sync
51
59
  - **Memory Management**: LRU cache for chunks, complete metadata cache
@@ -54,7 +62,9 @@ Tests for the CloudflareWorkerVFS implementation, which uses DurableObjectStorag
54
62
  ## Running Tests
55
63
 
56
64
  ### Prerequisites
65
+
57
66
  1. Install dependencies:
67
+
58
68
  ```bash
59
69
  pnpm install
60
70
  ```
@@ -96,24 +106,26 @@ pnpm test --coverage
96
106
  ## Test Structure
97
107
 
98
108
  ### SQL Storage Test Pattern
109
+
99
110
  ```typescript
100
111
  import { describe, it, expect, beforeEach } from 'vitest'
101
- import { type Cf, CloudflareSqlVFS } from '../../mod.ts'
112
+ import type { CfTypes } from '@livestore/common-cf'
113
+ import { CloudflareDurableObjectVFS } from '../../mod.ts'
102
114
 
103
115
  describe('SQL VFS Test Suite', () => {
104
- let vfs: CloudflareSqlVFS
105
- let mockSql: Cf.SqlStorage
116
+ let vfs: CloudflareDurableObjectVFS
117
+ let mockSql: CfTypes.SqlStorage
106
118
  let queryLog: string[]
107
119
 
108
120
  beforeEach(async () => {
109
121
  // Setup mock SQL storage
110
122
  mockSql = {
111
123
  exec: (query: string, ...bindings: any[]) => {
112
- // Mock SQL implementation
113
- }
124
+ // Mock SQL implementation for vfs_pages(file_path, page_no, page_data)
125
+ },
114
126
  }
115
-
116
- vfs = new CloudflareSqlVFS('test-vfs', mockSql, {})
127
+
128
+ vfs = new CloudflareDurableObjectVFS('test-vfs', mockSql, {})
117
129
  await vfs.isReady()
118
130
  })
119
131
 
@@ -122,6 +134,7 @@ describe('SQL VFS Test Suite', () => {
122
134
  ```
123
135
 
124
136
  ### Async Storage Test Pattern
137
+
125
138
  ```typescript
126
139
  import { describe, it, expect, beforeEach } from 'vitest'
127
140
  import { type Cf, CloudflareWorkerVFS } from '../../mod.ts'
@@ -133,12 +146,18 @@ describe('Async Storage VFS Test Suite', () => {
133
146
  beforeEach(async () => {
134
147
  // Setup mock DurableObjectStorage
135
148
  mockStorage = {
136
- get: async (key) => { /* mock implementation */ },
137
- put: async (key, value) => { /* mock implementation */ },
138
- delete: async (key) => { /* mock implementation */ },
149
+ get: async (key) => {
150
+ /* mock implementation */
151
+ },
152
+ put: async (key, value) => {
153
+ /* mock implementation */
154
+ },
155
+ delete: async (key) => {
156
+ /* mock implementation */
157
+ },
139
158
  // ... other methods
140
159
  }
141
-
160
+
142
161
  vfs = new CloudflareWorkerVFS('test-vfs', mockStorage, {})
143
162
  await vfs.isReady()
144
163
  })
@@ -150,12 +169,14 @@ describe('Async Storage VFS Test Suite', () => {
150
169
  ## Performance Benchmarks
151
170
 
152
171
  ### Metrics Tracked
172
+
153
173
  - **Throughput**: Operations per second
154
- - **Latency**: Response times for various operations
174
+ - **Latency**: Response times for various operations
155
175
  - **Memory Usage**: Cache effectiveness and memory consumption
156
176
  - **Storage Efficiency**: Data compression and chunking effectiveness
157
177
 
158
178
  ### Benchmark Comparisons
179
+
159
180
  - SQL vs Async Storage performance characteristics
160
181
  - Memory usage patterns between implementations
161
182
  - Scalability under different workloads
@@ -163,6 +184,7 @@ describe('Async Storage VFS Test Suite', () => {
163
184
  ## Test Data Cleanup
164
185
 
165
186
  ### Automatic Cleanup
187
+
166
188
  - **Isolated Storage**: Each test gets fresh storage instances
167
189
  - **Temporary Files**: Cleaned up automatically
168
190
  - **Cache Management**: Memory caches cleared between tests
@@ -170,24 +192,27 @@ describe('Async Storage VFS Test Suite', () => {
170
192
  ## Debugging Tests
171
193
 
172
194
  ### Logging
195
+
173
196
  - Use `console.log` for debugging (visible in test output)
174
197
  - VFS statistics available via `vfs.getStats()`
175
198
  - Storage operations logged in development mode
176
199
 
177
200
  ### Common Issues
178
- 1. **SQL Schema Issues**: Ensure proper table creation and constraints
201
+
202
+ 1. **SQL Schema Issues**: Ensure `vfs_pages(file_path, page_no, page_data)` is created as expected
179
203
  2. **Cache Misses**: Verify proper preloading in VFS initialization
180
- 3. **Async/Sync Mismatch**: Check async operations are properly handled
204
+ 3. **Handle/Path Mismatch**: Verify reads and writes use the path captured during `jOpen`
181
205
  4. **Storage Limits**: Verify chunk sizes and storage capacity
182
206
 
183
207
  ### Test Debugging
208
+
184
209
  ```typescript
185
210
  // SQL VFS debugging
186
211
  console.log('Query log:', queryLog)
187
212
  const stats = vfs.getStats()
188
213
  console.log('VFS Stats:', stats)
189
214
 
190
- // Async Storage VFS debugging
215
+ // Async Storage VFS debugging
191
216
  const metadata = await storage.get('file:/test/file.db:meta')
192
217
  console.log('File metadata:', metadata)
193
218
  ```
@@ -195,12 +220,14 @@ console.log('File metadata:', metadata)
195
220
  ## Future Enhancements
196
221
 
197
222
  ### Planned Test Additions
223
+
198
224
  1. **Performance Comparisons**: Direct SQL vs Async Storage benchmarks
199
225
  2. **Migration Tests**: Converting between storage backends
200
226
  3. **Stress Tests**: High-load scenarios for both implementations
201
227
  4. **Real SQLite Integration**: Tests with actual SQLite WASM
202
228
 
203
229
  ### Implementation Improvements
230
+
204
231
  1. **Hybrid Approach**: Combining SQL and async storage benefits
205
232
  2. **Compression Testing**: Data compression effectiveness
206
233
  3. **Caching Strategies**: Cross-implementation cache optimization
@@ -208,6 +235,7 @@ console.log('File metadata:', metadata)
208
235
  ## Contributing
209
236
 
210
237
  When adding new tests:
238
+
211
239
  1. Choose the appropriate location:
212
240
  - SQL storage tests: `/src/cf/test/sql/`
213
241
  - Async storage tests: `/src/cf/test/async-storage/`
@@ -217,8 +245,9 @@ When adding new tests:
217
245
  5. Update this documentation
218
246
 
219
247
  ### Test Guidelines
248
+
220
249
  - **Isolation**: Each test should be independent
221
250
  - **Implementation Specific**: Tests should target specific VFS features
222
251
  - **Assertions**: Use meaningful assertions with clear error messages
223
252
  - **Coverage**: Aim for comprehensive coverage of edge cases
224
- - **Performance**: Consider performance implications of each approach
253
+ - **Performance**: Consider performance implications of each approach
@@ -3,6 +3,7 @@
3
3
  import type { CfTypes } from '@livestore/common-cf'
4
4
  import * as VFS from '@livestore/wa-sqlite/src/VFS.js'
5
5
  import { beforeEach, describe, expect, it } from 'vitest'
6
+
6
7
  import { CloudflareWorkerVFS } from '../../mod.ts'
7
8
 
8
9
  describe('CloudflareWorkerVFS - Advanced Features', () => {
@@ -15,7 +16,7 @@ describe('CloudflareWorkerVFS - Advanced Features', () => {
15
16
 
16
17
  mockStorage = {
17
18
  get: (async (_key: string | string[]) => {
18
- if (Array.isArray(_key)) {
19
+ if (Array.isArray(_key) === true) {
19
20
  return new Map()
20
21
  }
21
22
  return storageData.get(_key)
@@ -32,10 +33,10 @@ describe('CloudflareWorkerVFS - Advanced Features', () => {
32
33
  },
33
34
 
34
35
  delete: (async (_key: string | string[]) => {
35
- if (Array.isArray(_key)) {
36
+ if (Array.isArray(_key) === true) {
36
37
  let count = 0
37
38
  for (const k of _key) {
38
- if (storageData.delete(k)) count++
39
+ if (storageData.delete(k) === true) count++
39
40
  }
40
41
  return count
41
42
  } else {
@@ -156,7 +157,8 @@ describe('CloudflareWorkerVFS - Advanced Features', () => {
156
157
  expect(vfs.jClose(fileId)).toBe(VFS.SQLITE_OK)
157
158
  })
158
159
 
159
- it('should handle large files that exceed cache capacity', async () => {
160
+ // TODO: Remove retry once flaky timeout is investigated (https://github.com/livestorejs/livestore/issues/1020)
161
+ it('should handle large files that exceed cache capacity', { retry: 3, timeout: 10000 }, async () => {
160
162
  const path = '/test/cache-overflow.db'
161
163
  const fileId = 1
162
164
  const flags = VFS.SQLITE_OPEN_CREATE | VFS.SQLITE_OPEN_READWRITE
@@ -3,6 +3,7 @@
3
3
  import type { CfTypes } from '@livestore/common-cf'
4
4
  import * as VFS from '@livestore/wa-sqlite/src/VFS.js'
5
5
  import { beforeEach, describe, expect, it } from 'vitest'
6
+
6
7
  import { CloudflareWorkerVFS } from '../../mod.ts'
7
8
 
8
9
  describe('CloudflareWorkerVFS - Core Functionality', () => {
@@ -15,7 +16,7 @@ describe('CloudflareWorkerVFS - Core Functionality', () => {
15
16
 
16
17
  mockStorage = {
17
18
  get: (async (_key: string | string[]) => {
18
- if (Array.isArray(_key)) {
19
+ if (Array.isArray(_key) === true) {
19
20
  return new Map()
20
21
  }
21
22
  return storageData.get(_key)
@@ -32,10 +33,10 @@ describe('CloudflareWorkerVFS - Core Functionality', () => {
32
33
  },
33
34
 
34
35
  delete: (async (_key: string | string[]) => {
35
- if (Array.isArray(_key)) {
36
+ if (Array.isArray(_key) === true) {
36
37
  let count = 0
37
38
  for (const k of _key) {
38
- if (storageData.delete(k)) count++
39
+ if (storageData.delete(k) === true) count++
39
40
  }
40
41
  return count
41
42
  } else {
@@ -3,6 +3,7 @@
3
3
  import type { CfTypes } from '@livestore/common-cf'
4
4
  import * as VFS from '@livestore/wa-sqlite/src/VFS.js'
5
5
  import { beforeEach, describe, expect, it } from 'vitest'
6
+
6
7
  import { CloudflareWorkerVFS } from '../../mod.ts'
7
8
 
8
9
  describe('CloudflareWorkerVFS - Integration Tests', () => {
@@ -17,7 +18,7 @@ describe('CloudflareWorkerVFS - Integration Tests', () => {
17
18
 
18
19
  mockStorage = {
19
20
  get: (async (_key: string | string[]) => {
20
- if (Array.isArray(_key)) {
21
+ if (Array.isArray(_key) === true) {
21
22
  storageOperations.push(`get-batch: ${_key.length} keys`)
22
23
  const result = new Map()
23
24
  for (const k of _key) {
@@ -46,11 +47,11 @@ describe('CloudflareWorkerVFS - Integration Tests', () => {
46
47
  },
47
48
 
48
49
  delete: (async (_key: string | string[]) => {
49
- if (Array.isArray(_key)) {
50
+ if (Array.isArray(_key) === true) {
50
51
  storageOperations.push(`delete-batch: ${_key.length} keys`)
51
52
  let count = 0
52
53
  for (const k of _key) {
53
- if (storageData.delete(k)) count++
54
+ if (storageData.delete(k) === true) count++
54
55
  }
55
56
  return count
56
57
  } else {
@@ -3,6 +3,7 @@
3
3
  import type { CfTypes } from '@livestore/common-cf'
4
4
  import * as VFS from '@livestore/wa-sqlite/src/VFS.js'
5
5
  import { beforeEach, describe, expect, it } from 'vitest'
6
+
6
7
  import { CloudflareWorkerVFS } from '../../mod.ts'
7
8
 
8
9
  describe('CloudflareWorkerVFS - Reliability & Error Recovery', () => {
@@ -15,7 +16,7 @@ describe('CloudflareWorkerVFS - Reliability & Error Recovery', () => {
15
16
 
16
17
  mockStorage = {
17
18
  get: (async (_key: string | string[]) => {
18
- if (Array.isArray(_key)) {
19
+ if (Array.isArray(_key) === true) {
19
20
  return new Map()
20
21
  }
21
22
  return storageData.get(_key)
@@ -32,10 +33,10 @@ describe('CloudflareWorkerVFS - Reliability & Error Recovery', () => {
32
33
  },
33
34
 
34
35
  delete: (async (_key: string | string[]) => {
35
- if (Array.isArray(_key)) {
36
+ if (Array.isArray(_key) === true) {
36
37
  let count = 0
37
38
  for (const k of _key) {
38
- if (storageData.delete(k)) count++
39
+ if (storageData.delete(k) === true) count++
39
40
  }
40
41
  return count
41
42
  } else {