@livestore/wa-sqlite 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 (62) hide show
  1. package/README.md +46 -36
  2. package/dist/README.md +13 -13
  3. package/dist/fts5/wa-sqlite.mjs +1 -1
  4. package/dist/fts5/wa-sqlite.node.mjs +1 -1
  5. package/dist/fts5/wa-sqlite.node.wasm +0 -0
  6. package/dist/fts5/wa-sqlite.wasm +0 -0
  7. package/dist/wa-sqlite-async.mjs +1 -1
  8. package/dist/wa-sqlite-async.wasm +0 -0
  9. package/dist/wa-sqlite-jspi.mjs +1 -1
  10. package/dist/wa-sqlite-jspi.wasm +0 -0
  11. package/dist/wa-sqlite.mjs +1 -1
  12. package/dist/wa-sqlite.node.mjs +1 -1
  13. package/dist/wa-sqlite.node.wasm +0 -0
  14. package/dist/wa-sqlite.wasm +0 -0
  15. package/package.json +40 -29
  16. package/src/FacadeVFS.js +252 -261
  17. package/src/VFS.js +84 -85
  18. package/src/WebLocksMixin.js +357 -351
  19. package/src/examples/AccessHandlePoolVFS.js +185 -194
  20. package/src/examples/IDBBatchAtomicVFS.js +429 -409
  21. package/src/examples/IDBMirrorVFS.js +402 -409
  22. package/src/examples/MemoryAsyncVFS.js +32 -37
  23. package/src/examples/MemoryVFS.js +71 -75
  24. package/src/examples/OPFSAdaptiveVFS.js +206 -206
  25. package/src/examples/OPFSAnyContextVFS.js +141 -140
  26. package/src/examples/OPFSCoopSyncVFS.js +297 -299
  27. package/src/examples/OPFSPermutedVFS.js +529 -540
  28. package/src/examples/README.md +27 -15
  29. package/src/examples/tag.js +27 -27
  30. package/src/sqlite-api.js +910 -941
  31. package/src/sqlite-constants.js +246 -232
  32. package/src/types/globals.d.ts +52 -52
  33. package/src/types/index.d.ts +586 -576
  34. package/test/AccessHandlePoolVFS.test.js +21 -21
  35. package/test/IDBBatchAtomicVFS.test.js +69 -69
  36. package/test/IDBMirrorVFS.test.js +21 -21
  37. package/test/MemoryAsyncVFS.test.js +21 -21
  38. package/test/MemoryVFS.test.js +21 -21
  39. package/test/OPFSAdaptiveVFS.test.js +21 -21
  40. package/test/OPFSAnyContextVFS.test.js +21 -21
  41. package/test/OPFSCoopSyncVFS.test.js +21 -21
  42. package/test/OPFSPermutedVFS.test.js +21 -21
  43. package/test/TestContext.js +44 -41
  44. package/test/WebLocksMixin.test.js +369 -360
  45. package/test/api.test.js +23 -23
  46. package/test/api_exec.js +72 -61
  47. package/test/api_misc.js +53 -54
  48. package/test/api_statements.js +271 -279
  49. package/test/callbacks.test.js +492 -478
  50. package/test/data/idbv5.json +1135 -1
  51. package/test/sql.test.js +30 -30
  52. package/test/sql_0001.js +49 -33
  53. package/test/sql_0002.js +55 -34
  54. package/test/sql_0003.js +85 -49
  55. package/test/sql_0004.js +76 -47
  56. package/test/sql_0005.js +60 -44
  57. package/test/test-worker.js +171 -163
  58. package/test/vfs_xAccess.js +1 -2
  59. package/test/vfs_xClose.js +50 -49
  60. package/test/vfs_xOpen.js +73 -72
  61. package/test/vfs_xRead.js +31 -31
  62. package/test/vfs_xWrite.js +30 -29
@@ -1,299 +1,300 @@
1
1
  // Copyright 2024 Roy T. Hashimoto. All Rights Reserved.
2
- import { FacadeVFS } from '../FacadeVFS.js';
3
- import * as VFS from '../VFS.js';
4
- import { WebLocksMixin } from '../WebLocksMixin.js';
2
+ import { FacadeVFS } from '../FacadeVFS.js'
3
+ import * as VFS from '../VFS.js'
4
+ import { WebLocksMixin } from '../WebLocksMixin.js'
5
5
 
6
6
  /**
7
- * @param {string} pathname
8
- * @param {boolean} create
7
+ * @param {string} pathname
8
+ * @param {boolean} create
9
9
  * @returns {Promise<[FileSystemDirectoryHandle, string]>}
10
10
  */
11
11
  async function getPathComponents(pathname, create) {
12
- const [_, directories, filename] = pathname.match(/[/]?(.*)[/](.*)$/);
12
+ const [_, directories, filename] = pathname.match(/[/]?(.*)[/](.*)$/)
13
13
 
14
- let directoryHandle = await navigator.storage.getDirectory();
14
+ let directoryHandle = await navigator.storage.getDirectory()
15
15
  for (const directory of directories.split('/')) {
16
16
  if (directory) {
17
- directoryHandle = await directoryHandle.getDirectoryHandle(directory, { create });
17
+ directoryHandle = await directoryHandle.getDirectoryHandle(directory, { create })
18
18
  }
19
19
  }
20
- return [directoryHandle, filename];
21
- };
20
+ return [directoryHandle, filename]
21
+ }
22
22
 
23
23
  class File {
24
- /** @type {string} */ pathname;
25
- /** @type {number} */ flags;
26
- /** @type {FileSystemFileHandle} */ fileHandle;
27
- /** @type {Blob?} */ blob;
28
- /** @type {FileSystemWritableFileStream?} */ writable;
24
+ /** @type {string} */ pathname
25
+ /** @type {number} */ flags
26
+ /** @type {FileSystemFileHandle} */ fileHandle
27
+ /** @type {Blob?} */ blob
28
+ /** @type {FileSystemWritableFileStream?} */ writable
29
29
 
30
30
  constructor(pathname, flags) {
31
- this.pathname = pathname;
32
- this.flags = flags;
31
+ this.pathname = pathname
32
+ this.flags = flags
33
33
  }
34
34
  }
35
35
 
36
36
  export class OPFSAnyContextVFS extends WebLocksMixin(FacadeVFS) {
37
- /** @type {Map<number, File>} */ mapIdToFile = new Map();
38
- lastError = null;
37
+ /** @type {Map<number, File>} */ mapIdToFile = new Map()
38
+ lastError = null
39
39
 
40
- log = null;
40
+ log = null
41
41
 
42
42
  static async create(name, module, options) {
43
- const vfs = new OPFSAnyContextVFS(name, module, options);
44
- await vfs.isReady();
45
- return vfs;
43
+ const vfs = new OPFSAnyContextVFS(name, module, options)
44
+ await vfs.isReady()
45
+ return vfs
46
46
  }
47
47
 
48
48
  constructor(name, module, options = {}) {
49
- super(name, module, options);
49
+ super(name, module, options)
50
50
  }
51
-
51
+
52
52
  getFilename(fileId) {
53
- const pathname = this.mapIdToFile.get(fileId).pathname;
53
+ const pathname = this.mapIdToFile.get(fileId).pathname
54
54
  return `OPFS:${pathname}`
55
55
  }
56
56
 
57
57
  /**
58
- * @param {string?} zName
59
- * @param {number} fileId
60
- * @param {number} flags
61
- * @param {DataView} pOutFlags
58
+ * @param {string?} zName
59
+ * @param {number} fileId
60
+ * @param {number} flags
61
+ * @param {DataView} pOutFlags
62
62
  * @returns {Promise<number>}
63
63
  */
64
64
  async jOpen(zName, fileId, flags, pOutFlags) {
65
65
  try {
66
- const url = new URL(zName || Math.random().toString(36).slice(2), 'file://');
67
- const pathname = url.pathname;
68
-
69
- const file = new File(pathname, flags);
70
- this.mapIdToFile.set(fileId, file);
71
-
72
- const create = !!(flags & VFS.SQLITE_OPEN_CREATE);
73
- const [directoryHandle, filename] = await getPathComponents(pathname, create);
74
- file.fileHandle = await directoryHandle.getFileHandle(filename, { create });
75
-
76
- pOutFlags.setInt32(0, flags, true);
77
- return VFS.SQLITE_OK;
66
+ const url = new URL(zName || Math.random().toString(36).slice(2), 'file://')
67
+ const pathname = url.pathname
68
+
69
+ const file = new File(pathname, flags)
70
+ this.mapIdToFile.set(fileId, file)
71
+
72
+ const create = !!(flags & VFS.SQLITE_OPEN_CREATE)
73
+ const [directoryHandle, filename] = await getPathComponents(pathname, create)
74
+ file.fileHandle = await directoryHandle.getFileHandle(filename, { create })
75
+
76
+ pOutFlags.setInt32(0, flags, true)
77
+ return VFS.SQLITE_OK
78
78
  } catch (e) {
79
- this.lastError = e;
80
- return VFS.SQLITE_CANTOPEN;
79
+ this.lastError = e
80
+ return VFS.SQLITE_CANTOPEN
81
81
  }
82
82
  }
83
83
 
84
84
  /**
85
- * @param {string} zName
86
- * @param {number} syncDir
85
+ * @param {string} zName
86
+ * @param {number} syncDir
87
87
  * @returns {Promise<number>}
88
88
  */
89
89
  async jDelete(zName, syncDir) {
90
90
  try {
91
- const url = new URL(zName, 'file://');
92
- const pathname = url.pathname;
93
-
94
- const [directoryHandle, name] = await getPathComponents(pathname, false);
95
- const result = directoryHandle.removeEntry(name, { recursive: false });
91
+ const url = new URL(zName, 'file://')
92
+ const pathname = url.pathname
93
+
94
+ const [directoryHandle, name] = await getPathComponents(pathname, false)
95
+ const result = directoryHandle.removeEntry(name, { recursive: false })
96
96
  if (syncDir) {
97
- await result;
97
+ await result
98
98
  }
99
- return VFS.SQLITE_OK;
99
+ return VFS.SQLITE_OK
100
100
  } catch (e) {
101
- return VFS.SQLITE_IOERR_DELETE;
101
+ return VFS.SQLITE_IOERR_DELETE
102
102
  }
103
103
  }
104
104
 
105
105
  /**
106
- * @param {string} zName
107
- * @param {number} flags
108
- * @param {DataView} pResOut
106
+ * @param {string} zName
107
+ * @param {number} flags
108
+ * @param {DataView} pResOut
109
109
  * @returns {Promise<number>}
110
110
  */
111
111
  async jAccess(zName, flags, pResOut) {
112
112
  try {
113
- const url = new URL(zName, 'file://');
114
- const pathname = url.pathname;
113
+ const url = new URL(zName, 'file://')
114
+ const pathname = url.pathname
115
115
 
116
- const [directoryHandle, dbName] = await getPathComponents(pathname, false);
117
- const fileHandle = await directoryHandle.getFileHandle(dbName, { create: false });
118
- pResOut.setInt32(0, 1, true);
119
- return VFS.SQLITE_OK;
116
+ const [directoryHandle, dbName] = await getPathComponents(pathname, false)
117
+ const fileHandle = await directoryHandle.getFileHandle(dbName, { create: false })
118
+ pResOut.setInt32(0, 1, true)
119
+ return VFS.SQLITE_OK
120
120
  } catch (e) {
121
121
  if (e.name === 'NotFoundError') {
122
- pResOut.setInt32(0, 0, true);
123
- return VFS.SQLITE_OK;
122
+ pResOut.setInt32(0, 0, true)
123
+ return VFS.SQLITE_OK
124
124
  }
125
- this.lastError = e;
126
- return VFS.SQLITE_IOERR_ACCESS;
125
+ this.lastError = e
126
+ return VFS.SQLITE_IOERR_ACCESS
127
127
  }
128
128
  }
129
129
 
130
130
  /**
131
- * @param {number} fileId
131
+ * @param {number} fileId
132
132
  * @returns {Promise<number>}
133
133
  */
134
134
  async jClose(fileId) {
135
135
  try {
136
- const file = this.mapIdToFile.get(fileId);
137
- this.mapIdToFile.delete(fileId);
136
+ const file = this.mapIdToFile.get(fileId)
137
+ this.mapIdToFile.delete(fileId)
138
138
 
139
- await file.writable?.close();
139
+ await file.writable?.close()
140
140
  if (file?.flags & VFS.SQLITE_OPEN_DELETEONCLOSE) {
141
- const [directoryHandle, name] = await getPathComponents(file.pathname, false);
142
- await directoryHandle.removeEntry(name, { recursive: false });
141
+ const [directoryHandle, name] = await getPathComponents(file.pathname, false)
142
+ await directoryHandle.removeEntry(name, { recursive: false })
143
143
  }
144
- return VFS.SQLITE_OK;
144
+ return VFS.SQLITE_OK
145
145
  } catch (e) {
146
- return VFS.SQLITE_IOERR_DELETE;
146
+ return VFS.SQLITE_IOERR_DELETE
147
147
  }
148
148
  }
149
149
 
150
150
  /**
151
- * @param {number} fileId
152
- * @param {Uint8Array} pData
151
+ * @param {number} fileId
152
+ * @param {Uint8Array} pData
153
153
  * @param {number} iOffset
154
154
  * @returns {Promise<number>}
155
155
  */
156
156
  async jRead(fileId, pData, iOffset) {
157
157
  try {
158
- const file = this.mapIdToFile.get(fileId);
158
+ const file = this.mapIdToFile.get(fileId)
159
159
 
160
160
  if (file.writable) {
161
- await file.writable.close();
162
- file.writable = null;
163
- file.blob = null;
161
+ await file.writable.close()
162
+ file.writable = null
163
+ file.blob = null
164
164
  }
165
165
  if (!file.blob) {
166
- file.blob = await file.fileHandle.getFile();
166
+ file.blob = await file.fileHandle.getFile()
167
167
  }
168
168
 
169
- const bytesRead = await file.blob.slice(iOffset, iOffset + pData.byteLength)
169
+ const bytesRead = await file.blob
170
+ .slice(iOffset, iOffset + pData.byteLength)
170
171
  .arrayBuffer()
171
- .then(arrayBuffer => {
172
- pData.set(new Uint8Array(arrayBuffer));
173
- return arrayBuffer.byteLength;
174
- });
172
+ .then((arrayBuffer) => {
173
+ pData.set(new Uint8Array(arrayBuffer))
174
+ return arrayBuffer.byteLength
175
+ })
175
176
 
176
177
  if (bytesRead < pData.byteLength) {
177
- pData.fill(0, bytesRead);
178
- return VFS.SQLITE_IOERR_SHORT_READ;
178
+ pData.fill(0, bytesRead)
179
+ return VFS.SQLITE_IOERR_SHORT_READ
179
180
  }
180
- return VFS.SQLITE_OK;
181
+ return VFS.SQLITE_OK
181
182
  } catch (e) {
182
- this.lastError = e;
183
- return VFS.SQLITE_IOERR_READ;
183
+ this.lastError = e
184
+ return VFS.SQLITE_IOERR_READ
184
185
  }
185
186
  }
186
187
 
187
188
  /**
188
- * @param {number} fileId
189
- * @param {Uint8Array} pData
189
+ * @param {number} fileId
190
+ * @param {Uint8Array} pData
190
191
  * @param {number} iOffset
191
192
  * @returns {Promise<number>}
192
193
  */
193
194
  async jWrite(fileId, pData, iOffset) {
194
195
  try {
195
- const file = this.mapIdToFile.get(fileId);
196
+ const file = this.mapIdToFile.get(fileId)
196
197
 
197
198
  if (!file.writable) {
198
- file.writable = await file.fileHandle.createWritable({ keepExistingData: true });
199
+ file.writable = await file.fileHandle.createWritable({ keepExistingData: true })
199
200
  }
200
- await file.writable.seek(iOffset);
201
- await file.writable.write(pData.subarray());
202
- file.blob = null;
201
+ await file.writable.seek(iOffset)
202
+ await file.writable.write(pData.subarray())
203
+ file.blob = null
203
204
 
204
- return VFS.SQLITE_OK;
205
+ return VFS.SQLITE_OK
205
206
  } catch (e) {
206
- this.lastError = e;
207
- return VFS.SQLITE_IOERR_WRITE;
207
+ this.lastError = e
208
+ return VFS.SQLITE_IOERR_WRITE
208
209
  }
209
210
  }
210
211
 
211
212
  /**
212
- * @param {number} fileId
213
- * @param {number} iSize
213
+ * @param {number} fileId
214
+ * @param {number} iSize
214
215
  * @returns {Promise<number>}
215
216
  */
216
217
  async jTruncate(fileId, iSize) {
217
218
  try {
218
- const file = this.mapIdToFile.get(fileId);
219
+ const file = this.mapIdToFile.get(fileId)
219
220
 
220
221
  if (!file.writable) {
221
- file.writable = await file.fileHandle.createWritable({ keepExistingData: true });
222
+ file.writable = await file.fileHandle.createWritable({ keepExistingData: true })
222
223
  }
223
- await file.writable.truncate(iSize);
224
- file.blob = null;
225
- return VFS.SQLITE_OK;
224
+ await file.writable.truncate(iSize)
225
+ file.blob = null
226
+ return VFS.SQLITE_OK
226
227
  } catch (e) {
227
- this.lastError = e;
228
- return VFS.SQLITE_IOERR_TRUNCATE;
228
+ this.lastError = e
229
+ return VFS.SQLITE_IOERR_TRUNCATE
229
230
  }
230
231
  }
231
232
 
232
233
  /**
233
- * @param {number} fileId
234
- * @param {number} flags
234
+ * @param {number} fileId
235
+ * @param {number} flags
235
236
  * @returns {Promise<number>}
236
237
  */
237
238
  async jSync(fileId, flags) {
238
239
  try {
239
- const file = this.mapIdToFile.get(fileId);
240
- await file.writable?.close();
241
- file.writable = null;
242
- file.blob = null;
243
- return VFS.SQLITE_OK;
240
+ const file = this.mapIdToFile.get(fileId)
241
+ await file.writable?.close()
242
+ file.writable = null
243
+ file.blob = null
244
+ return VFS.SQLITE_OK
244
245
  } catch (e) {
245
- this.lastError = e;
246
- return VFS.SQLITE_IOERR_FSYNC;
246
+ this.lastError = e
247
+ return VFS.SQLITE_IOERR_FSYNC
247
248
  }
248
249
  }
249
250
 
250
251
  /**
251
- * @param {number} fileId
252
- * @param {DataView} pSize64
252
+ * @param {number} fileId
253
+ * @param {DataView} pSize64
253
254
  * @returns {Promise<number>}
254
255
  */
255
256
  async jFileSize(fileId, pSize64) {
256
257
  try {
257
- const file = this.mapIdToFile.get(fileId);
258
+ const file = this.mapIdToFile.get(fileId)
258
259
 
259
260
  if (file.writable) {
260
- await file.writable.close();
261
- file.writable = null;
262
- file.blob = null;
261
+ await file.writable.close()
262
+ file.writable = null
263
+ file.blob = null
263
264
  }
264
265
  if (!file.blob) {
265
- file.blob = await file.fileHandle.getFile();
266
+ file.blob = await file.fileHandle.getFile()
266
267
  }
267
- pSize64.setBigInt64(0, BigInt(file.blob.size), true);
268
- return VFS.SQLITE_OK;
268
+ pSize64.setBigInt64(0, BigInt(file.blob.size), true)
269
+ return VFS.SQLITE_OK
269
270
  } catch (e) {
270
- this.lastError = e;
271
- return VFS.SQLITE_IOERR_FSTAT;
271
+ this.lastError = e
272
+ return VFS.SQLITE_IOERR_FSTAT
272
273
  }
273
274
  }
274
275
 
275
276
  /**
276
- * @param {number} fileId
277
- * @param {number} lockType
277
+ * @param {number} fileId
278
+ * @param {number} lockType
278
279
  * @returns {Promise<number>}
279
280
  */
280
281
  async jLock(fileId, lockType) {
281
282
  if (lockType === VFS.SQLITE_LOCK_SHARED) {
282
283
  // Make sure to get a current readable view of the file.
283
- const file = this.mapIdToFile.get(fileId);
284
- file.blob = null;
284
+ const file = this.mapIdToFile.get(fileId)
285
+ file.blob = null
285
286
  }
286
287
 
287
288
  // Call the actual unlock implementation.
288
- return super.jLock(fileId, lockType);
289
+ return super.jLock(fileId, lockType)
289
290
  }
290
291
 
291
292
  jGetLastError(zBuf) {
292
293
  if (this.lastError) {
293
- console.error(this.lastError);
294
- const outputArray = zBuf.subarray(0, zBuf.byteLength - 1);
295
- const { written } = new TextEncoder().encodeInto(this.lastError.message, outputArray);
296
- zBuf[written] = 0;
294
+ console.error(this.lastError)
295
+ const outputArray = zBuf.subarray(0, zBuf.byteLength - 1)
296
+ const { written } = new TextEncoder().encodeInto(this.lastError.message, outputArray)
297
+ zBuf[written] = 0
297
298
  }
298
299
  return VFS.SQLITE_OK
299
300
  }