indexeddbshim 12.0.0 → 13.0.0

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 (101) hide show
  1. package/README.md +1 -1
  2. package/badges/licenses-badge-dev.svg +1 -1
  3. package/dist/CFG.d.ts +80 -0
  4. package/dist/CFG.d.ts.map +1 -0
  5. package/dist/DOMException.d.ts +71 -0
  6. package/dist/DOMException.d.ts.map +1 -0
  7. package/dist/DOMStringList.d.ts +20 -0
  8. package/dist/DOMStringList.d.ts.map +1 -0
  9. package/dist/Event.d.ts +21 -0
  10. package/dist/Event.d.ts.map +1 -0
  11. package/dist/IDBCursor.d.ts +288 -0
  12. package/dist/IDBCursor.d.ts.map +1 -0
  13. package/dist/IDBDatabase.d.ts +143 -0
  14. package/dist/IDBDatabase.d.ts.map +1 -0
  15. package/dist/IDBFactory.d.ts +96 -0
  16. package/dist/IDBFactory.d.ts.map +1 -0
  17. package/dist/IDBIndex.d.ts +243 -0
  18. package/dist/IDBIndex.d.ts.map +1 -0
  19. package/dist/IDBKeyRange.d.ts +79 -0
  20. package/dist/IDBKeyRange.d.ts.map +1 -0
  21. package/dist/IDBObjectStore.d.ts +273 -0
  22. package/dist/IDBObjectStore.d.ts.map +1 -0
  23. package/dist/IDBRequest.d.ts +88 -0
  24. package/dist/IDBRequest.d.ts.map +1 -0
  25. package/dist/IDBTransaction.d.ts +270 -0
  26. package/dist/IDBTransaction.d.ts.map +1 -0
  27. package/dist/IDBVersionChangeEvent.d.ts +22 -0
  28. package/dist/IDBVersionChangeEvent.d.ts.map +1 -0
  29. package/dist/Key.d.ts +214 -0
  30. package/dist/Key.d.ts.map +1 -0
  31. package/dist/Sca.d.ts +31 -0
  32. package/dist/Sca.d.ts.map +1 -0
  33. package/dist/UnicodeIdentifiers.d.ts +3 -0
  34. package/dist/UnicodeIdentifiers.d.ts.map +1 -0
  35. package/dist/browser-UnicodeIdentifiers.d.ts +2 -0
  36. package/dist/browser-UnicodeIdentifiers.d.ts.map +1 -0
  37. package/dist/browser-noninvasive.d.ts +3 -0
  38. package/dist/browser-noninvasive.d.ts.map +1 -0
  39. package/dist/browser.d.ts +2 -0
  40. package/dist/browser.d.ts.map +1 -0
  41. package/dist/cmp.d.ts +9 -0
  42. package/dist/cmp.d.ts.map +1 -0
  43. package/dist/indexeddbshim-Key.js +553 -252
  44. package/dist/indexeddbshim-Key.js.map +1 -1
  45. package/dist/indexeddbshim-Key.min.js +2 -2
  46. package/dist/indexeddbshim-Key.min.js.map +1 -1
  47. package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs +17560 -1302
  48. package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs.map +1 -1
  49. package/dist/indexeddbshim-UnicodeIdentifiers.js +4367 -1604
  50. package/dist/indexeddbshim-UnicodeIdentifiers.js.map +1 -1
  51. package/dist/indexeddbshim-UnicodeIdentifiers.min.js +2 -2
  52. package/dist/indexeddbshim-UnicodeIdentifiers.min.js.map +1 -1
  53. package/dist/indexeddbshim-node.cjs +17556 -1302
  54. package/dist/indexeddbshim-node.cjs.map +1 -1
  55. package/dist/indexeddbshim-noninvasive.js +4362 -1604
  56. package/dist/indexeddbshim-noninvasive.js.map +1 -1
  57. package/dist/indexeddbshim-noninvasive.min.js +2 -2
  58. package/dist/indexeddbshim-noninvasive.min.js.map +1 -1
  59. package/dist/indexeddbshim.js +4362 -1604
  60. package/dist/indexeddbshim.js.map +1 -1
  61. package/dist/indexeddbshim.min.js +2 -2
  62. package/dist/indexeddbshim.min.js.map +1 -1
  63. package/dist/node-UnicodeIdentifiers.d.ts +8 -0
  64. package/dist/node-UnicodeIdentifiers.d.ts.map +1 -0
  65. package/dist/node.d.ts +8 -0
  66. package/dist/node.d.ts.map +1 -0
  67. package/dist/nodeWebSQL.d.ts +3 -0
  68. package/dist/nodeWebSQL.d.ts.map +1 -0
  69. package/dist/setGlobalVars.d.ts +79 -0
  70. package/dist/setGlobalVars.d.ts.map +1 -0
  71. package/dist/unicode-regex.d.ts +3 -0
  72. package/dist/unicode-regex.d.ts.map +1 -0
  73. package/dist/util.d.ts +174 -0
  74. package/dist/util.d.ts.map +1 -0
  75. package/index.html +1 -1
  76. package/package.json +51 -37
  77. package/src/CFG.js +89 -11
  78. package/src/DOMException.js +117 -31
  79. package/src/DOMStringList.js +93 -3
  80. package/src/Event.js +19 -4
  81. package/src/IDBCursor.js +350 -76
  82. package/src/IDBDatabase.js +88 -10
  83. package/src/IDBFactory.js +331 -61
  84. package/src/IDBIndex.js +393 -110
  85. package/src/IDBKeyRange.js +90 -17
  86. package/src/IDBObjectStore.js +347 -86
  87. package/src/IDBRequest.js +59 -1
  88. package/src/IDBTransaction.js +254 -46
  89. package/src/IDBVersionChangeEvent.js +28 -3
  90. package/src/Key.d.ts +1 -0
  91. package/src/Key.js +272 -162
  92. package/src/Sca.js +29 -4
  93. package/src/browser-UnicodeIdentifiers.js +5 -1
  94. package/src/cmp.js +5 -5
  95. package/src/node-UnicodeIdentifiers.js +9 -0
  96. package/src/node.js +5 -0
  97. package/src/nodeWebSQL.js +11 -5
  98. package/src/setGlobalVars.js +159 -22
  99. package/src/unicode-regex.js +2 -0
  100. package/src/util.js +229 -40
  101. package/typings/shimIndexedDB.d.ts +9 -0
package/src/IDBIndex.js CHANGED
@@ -1,4 +1,4 @@
1
- import SyncPromise from 'sync-promise';
1
+ import SyncPromise from 'sync-promise-expanded';
2
2
  import {createDOMException} from './DOMException.js';
3
3
  import {IDBCursor, IDBCursorWithValue} from './IDBCursor.js';
4
4
  import * as util from './util.js';
@@ -11,22 +11,70 @@ import IDBObjectStore from './IDBObjectStore.js';
11
11
 
12
12
  const readonlyProperties = ['objectStore', 'keyPath', 'multiEntry', 'unique'];
13
13
 
14
- /* eslint-disable jsdoc/check-param-names */
14
+ /**
15
+ * @typedef {number} Integer
16
+ */
17
+
18
+ /**
19
+ * @typedef {{
20
+ * columnName: string,
21
+ * keyPath: import('./Key.js').KeyPath,
22
+ * optionalParams: {
23
+ * unique: boolean,
24
+ * multiEntry: boolean
25
+ * }
26
+ * deleted?: boolean,
27
+ * __deleted?: boolean,
28
+ * cursors?: import('./IDBCursor.js').IDBCursorWithValueFull[],
29
+ * }} IDBIndexProperties
30
+ */
31
+
15
32
  /**
16
33
  * IDB Index.
17
34
  * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBIndex
18
- * @param {IDBObjectStore} store
19
- * @param {IDBIndexProperties} indexProperties
20
35
  * @class
21
36
  */
22
37
  function IDBIndex () {
23
- /* eslint-enable jsdoc/check-param-names */
24
38
  throw new TypeError('Illegal constructor');
25
39
  }
26
40
  const IDBIndexAlias = IDBIndex;
41
+
42
+ /**
43
+ * @typedef {IDBIndex & {
44
+ * name: string,
45
+ * keyPath: import('./Key.js').KeyPath,
46
+ * multiEntry: boolean,
47
+ * unique: boolean,
48
+ * objectStore: import('./IDBObjectStore.js').IDBObjectStoreFull,
49
+ * __pendingCreate?: boolean,
50
+ * __deleted?: boolean,
51
+ * __originalName: string,
52
+ * __currentName: string,
53
+ * __pendingName?: string,
54
+ * __pendingDelete?: boolean,
55
+ * __name: string,
56
+ * __multiEntry: boolean,
57
+ * __unique: boolean,
58
+ * __objectStore: import('./IDBObjectStore.js').IDBObjectStoreFull,
59
+ * __keyPath: import('./Key.js').KeyPath,
60
+ * __recreated?: boolean
61
+ * }} IDBIndexFull
62
+ */
63
+
64
+ /**
65
+ *
66
+ * @param {import('./IDBObjectStore.js').IDBObjectStoreFull} store
67
+ * @param {IDBIndexProperties} indexProperties
68
+ * @returns {IDBIndexFull}
69
+ */
27
70
  IDBIndex.__createInstance = function (store, indexProperties) {
71
+ /**
72
+ * @class
73
+ * @this {IDBIndexFull}
74
+ */
28
75
  function IDBIndex () {
29
76
  const me = this;
77
+ // @ts-expect-error It's ok
30
78
  me[Symbol.toStringTag] = 'IDBIndex';
31
79
  util.defineReadonlyProperties(me, readonlyProperties);
32
80
  me.__objectStore = store;
@@ -38,16 +86,31 @@ IDBIndex.__createInstance = function (store, indexProperties) {
38
86
  me.__deleted = Boolean(indexProperties.__deleted);
39
87
  me.__objectStore.__cursors = indexProperties.cursors || [];
40
88
  Object.defineProperty(me, '__currentName', {
89
+ /**
90
+ * @this {IDBIndexFull}
91
+ * @returns {string}
92
+ */
41
93
  get () {
42
- return '__pendingName' in me ? me.__pendingName : me.name;
94
+ return '__pendingName' in me
95
+ ? /** @type {string} */ (me.__pendingName)
96
+ : me.name;
43
97
  }
44
98
  });
45
99
  Object.defineProperty(me, 'name', {
46
100
  enumerable: false,
47
101
  configurable: false,
102
+ /**
103
+ * @this {IDBIndexFull}
104
+ * @returns {string}
105
+ */
48
106
  get () {
49
107
  return this.__name;
50
108
  },
109
+ /**
110
+ * @param {string} newName
111
+ * @this {IDBIndexFull}
112
+ * @returns {void}
113
+ */
51
114
  set (newName) {
52
115
  const me = this;
53
116
  newName = util.convertToDOMString(newName);
@@ -72,7 +135,9 @@ IDBIndex.__createInstance = function (store, indexProperties) {
72
135
  objectStore.__indexes[newName] = me;
73
136
  objectStore.indexNames.splice(objectStore.indexNames.indexOf(oldName), 1, newName);
74
137
 
75
- const storeHandle = objectStore.transaction.__storeHandles[objectStore.name];
138
+ const storeHandle = /** @type {import('./IDBTransaction.js').IDBTransactionFull} */ (
139
+ objectStore.transaction
140
+ ).__storeHandles[objectStore.name];
76
141
  const oldIndexHandle = storeHandle.__indexHandles[oldName];
77
142
  oldIndexHandle.__name = newName; // Fix old references
78
143
  storeHandle.__indexHandles[newName] = oldIndexHandle; // Ensure new reference accessible
@@ -82,24 +147,37 @@ IDBIndex.__createInstance = function (store, indexProperties) {
82
147
  ['key', 'BLOB ' + (objectStore.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY')],
83
148
  ['value', 'BLOB']
84
149
  ].concat(
150
+ // @ts-expect-error Has numeric indexes instead of iterator
85
151
  [...objectStore.indexNames]
86
152
  .filter((indexName) => indexName !== newName)
87
153
  .map((indexName) => [util.escapeIndexNameForSQL(indexName), 'BLOB'])
88
154
  );
89
155
 
90
- me.__renameIndex(objectStore, oldName, newName, colInfoToPreserveArr, function (tx, success) {
91
- IDBIndexAlias.__updateIndexList(store, tx, function (store) {
92
- delete storeHandle.__pendingName;
93
- success(store);
94
- });
95
- });
156
+ me.__renameIndex(
157
+ objectStore, oldName, newName, colInfoToPreserveArr,
158
+ function (tx, success) {
159
+ IDBIndexAlias.__updateIndexList(store, tx, function (store) {
160
+ delete storeHandle.__pendingName;
161
+ success(store);
162
+ });
163
+ }
164
+ );
96
165
  }
97
166
  });
98
167
  }
99
168
  IDBIndex.prototype = IDBIndexAlias.prototype;
169
+
170
+ // @ts-expect-error It's ok
100
171
  return new IDBIndex();
101
172
  };
102
173
 
174
+ /**
175
+ *
176
+ * @param {IDBIndexFull} index
177
+ * @param {string} [msg]
178
+ * @throws {DOMException}
179
+ * @returns {void}
180
+ */
103
181
  IDBIndex.__invalidStateIfDeleted = function (index, msg) {
104
182
  if (index.__deleted || index.__pendingDelete || (
105
183
  index.__pendingCreate && index.objectStore.transaction && index.objectStore.transaction.__errored
@@ -110,10 +188,9 @@ IDBIndex.__invalidStateIfDeleted = function (index, msg) {
110
188
 
111
189
  /**
112
190
  * Clones an IDBIndex instance for a different IDBObjectStore instance.
113
- * @param {IDBIndex} index
114
- * @param {IDBObjectStore} store
115
- * @protected
116
- * @returns {IDBIndex}
191
+ * @param {IDBIndexFull} index
192
+ * @param {import('./IDBObjectStore.js').IDBObjectStoreFull} store
193
+ * @returns {IDBIndexFull}
117
194
  */
118
195
  IDBIndex.__clone = function (index, store) {
119
196
  const idx = IDBIndex.__createInstance(store, {
@@ -124,7 +201,11 @@ IDBIndex.__clone = function (index, store) {
124
201
  unique: index.unique
125
202
  }
126
203
  });
127
- ['__pendingCreate', '__pendingDelete', '__deleted', '__originalName', '__recreated'].forEach((p) => {
204
+ /** @type {const} */ ([
205
+ '__pendingCreate', '__pendingDelete', '__deleted',
206
+ '__originalName', '__recreated'
207
+ ]).forEach((p) => {
208
+ // @ts-expect-error Why is this type "never"?
128
209
  idx[p] = index[p];
129
210
  });
130
211
  return idx;
@@ -132,10 +213,9 @@ IDBIndex.__clone = function (index, store) {
132
213
 
133
214
  /**
134
215
  * Creates a new index on an object store.
135
- * @param {IDBObjectStore} store
136
- * @param {IDBIndex} index
216
+ * @param {import('./IDBObjectStore.js').IDBObjectStoreFull} store
217
+ * @param {IDBIndexFull} index
137
218
  * @returns {void}
138
- * @protected
139
219
  */
140
220
  IDBIndex.__createIndex = function (store, index) {
141
221
  const indexName = index.name;
@@ -160,33 +240,55 @@ IDBIndex.__createIndex = function (store, index) {
160
240
 
161
241
  // Create the index in WebSQL
162
242
  const {transaction} = store;
163
- transaction.__addNonRequestToTransactionQueue(function createIndex (tx, args, success, failure) {
243
+ /** @type {import('./IDBTransaction.js').IDBTransactionFull} */ (
244
+ transaction
245
+ ).__addNonRequestToTransactionQueue(function createIndex (tx, args, success, failure) {
164
246
  const columnExists = idx && (idx.__deleted || idx.__recreated); // This check must occur here rather than earlier as properties may not have been set yet otherwise
247
+
248
+ /** @type {{[key: string]: boolean}} */
165
249
  let indexValues = {};
166
250
 
251
+ /**
252
+ * @param {SQLTransaction} tx
253
+ * @param {SQLError} err
254
+ * @returns {void}
255
+ */
167
256
  function error (tx, err) {
168
257
  failure(createDOMException('UnknownError', 'Could not create index "' + indexName + '"' + err.code + '::' + err.message, err));
169
258
  }
170
259
 
260
+ /**
261
+ * @param {SQLTransaction} tx
262
+ * @returns {void}
263
+ */
171
264
  function applyIndex (tx) {
172
265
  // Update the object store's index list
173
266
  IDBIndex.__updateIndexList(store, tx, function () {
174
267
  // Add index entries for all existing records
175
268
  tx.executeSql('SELECT "key", "value" FROM ' + util.escapeStoreNameForSQL(storeName), [], function (tx, data) {
176
- CFG.DEBUG && console.log('Adding existing ' + storeName + ' records to the ' + indexName + ' index');
269
+ if (CFG.DEBUG) { console.log('Adding existing ' + storeName + ' records to the ' + indexName + ' index'); }
177
270
  addIndexEntry(0);
178
271
 
272
+ /**
273
+ * @param {Integer} i
274
+ * @returns {void}
275
+ */
179
276
  function addIndexEntry (i) {
180
277
  if (i < data.rows.length) {
181
278
  try {
182
279
  const value = Sca.decode(util.unescapeSQLiteResponse(data.rows.item(i).value));
183
- let indexKey = Key.extractKeyValueDecodedFromValueUsingKeyPath(value, index.keyPath, index.multiEntry); // Todo: Do we need this stricter error checking?
184
- if (indexKey.invalid || indexKey.failure) { // Todo: Do we need invalid checks and should we instead treat these as being duplicates?
280
+ const indexKey = Key.extractKeyValueDecodedFromValueUsingKeyPath(value, index.keyPath, index.multiEntry); // Todo: Do we need this stricter error checking?
281
+ if (
282
+ ('invalid' in indexKey && indexKey.invalid) ||
283
+ ('failure' in indexKey && indexKey.failure)
284
+ ) { // Todo: Do we need invalid checks and should we instead treat these as being duplicates?
185
285
  throw new Error('Go to catch; ignore bad indexKey');
186
286
  }
187
- indexKey = Key.encode(indexKey.value, index.multiEntry);
287
+ const indexKeyStr = /** @type {string} */ (
288
+ Key.encode(indexKey.value, index.multiEntry)
289
+ );
188
290
  if (index.unique) {
189
- if (indexValues[indexKey]) {
291
+ if (indexValues[indexKeyStr]) {
190
292
  indexValues = {};
191
293
  failure(createDOMException(
192
294
  'ConstraintError',
@@ -194,16 +296,17 @@ IDBIndex.__createIndex = function (store, index) {
194
296
  ));
195
297
  return;
196
298
  }
197
- indexValues[indexKey] = true;
299
+ indexValues[indexKeyStr] = true;
198
300
  }
199
301
 
200
302
  tx.executeSql(
201
303
  'UPDATE ' + util.escapeStoreNameForSQL(storeName) + ' SET ' +
202
304
  util.escapeIndexNameForSQL(indexName) + ' = ? WHERE "key" = ?',
203
- [util.escapeSQLiteStatement(indexKey), data.rows.item(i).key],
204
- function (tx, data) {
305
+ [util.escapeSQLiteStatement(indexKeyStr), data.rows.item(i).key],
306
+ function () {
205
307
  addIndexEntry(i + 1);
206
- }, error
308
+ },
309
+ /** @type {SQLStatementErrorCallback} */ (error)
207
310
  );
208
311
  } catch (e) {
209
312
  // Not a valid value to insert into index, so just continue
@@ -222,13 +325,17 @@ IDBIndex.__createIndex = function (store, index) {
222
325
  success(store);
223
326
  }
224
327
  }
225
- }, error);
226
- }, error);
328
+ }, /** @type {SQLStatementErrorCallback} */ (error));
329
+ }, /** @type {SQLStatementErrorCallback} */ (error));
227
330
  }
228
331
 
229
332
  const escapedStoreNameSQL = util.escapeStoreNameForSQL(storeName);
230
333
  const escapedIndexNameSQL = util.escapeIndexNameForSQL(index.name);
231
334
 
335
+ /**
336
+ * @param {SQLTransaction} tx
337
+ * @returns {void}
338
+ */
232
339
  function addIndexSQL (tx) {
233
340
  if (!CFG.useSQLiteIndexes) {
234
341
  applyIndex(tx);
@@ -244,7 +351,7 @@ IDBIndex.__createIndex = function (store, index) {
244
351
  '" ON ' + escapedStoreNameSQL + '(' + escapedIndexNameSQL + ')',
245
352
  [],
246
353
  applyIndex,
247
- error
354
+ /** @type {SQLStatementErrorCallback} */ (error)
248
355
  );
249
356
  }
250
357
 
@@ -255,17 +362,18 @@ IDBIndex.__createIndex = function (store, index) {
255
362
  } else {
256
363
  // For a new index, add a new column to the object store, then apply the index
257
364
  const sql = ['ALTER TABLE', escapedStoreNameSQL, 'ADD', escapedIndexNameSQL, 'BLOB'].join(' ');
258
- CFG.DEBUG && console.log(sql);
259
- tx.executeSql(sql, [], addIndexSQL, error);
365
+ if (CFG.DEBUG) { console.log(sql); }
366
+ tx.executeSql(
367
+ sql, [], addIndexSQL, /** @type {SQLStatementErrorCallback} */ (error)
368
+ );
260
369
  }
261
- }, undefined, store);
370
+ });
262
371
  };
263
372
 
264
373
  /**
265
374
  * Deletes an index from an object store.
266
- * @param {IDBObjectStore} store
267
- * @param {IDBIndex} index
268
- * @protected
375
+ * @param {import('./IDBObjectStore.js').IDBObjectStoreFull} store
376
+ * @param {IDBIndexFull} index
269
377
  * @returns {void}
270
378
  */
271
379
  IDBIndex.__deleteIndex = function (store, index) {
@@ -280,11 +388,21 @@ IDBIndex.__deleteIndex = function (store, index) {
280
388
 
281
389
  // Remove the index in WebSQL
282
390
  const {transaction} = store;
283
- transaction.__addNonRequestToTransactionQueue(function deleteIndex (tx, args, success, failure) {
391
+ /** @type {import('./IDBTransaction.js').IDBTransactionFull} */ (
392
+ transaction
393
+ ).__addNonRequestToTransactionQueue(function deleteIndex (tx, args, success, failure) {
394
+ /**
395
+ * @param {SQLTransaction} tx
396
+ * @param {SQLError} err
397
+ * @returns {void}
398
+ */
284
399
  function error (tx, err) {
285
400
  failure(createDOMException('UnknownError', 'Could not delete index "' + index.name + '"', err));
286
401
  }
287
402
 
403
+ /**
404
+ * @returns {void}
405
+ */
288
406
  function finishDeleteIndex () {
289
407
  // Update the object store's index list
290
408
  IDBIndex.__updateIndexList(store, tx, function (store) {
@@ -296,7 +414,7 @@ IDBIndex.__deleteIndex = function (store, index) {
296
414
  delete indexHandle.__pendingDelete;
297
415
  }
298
416
  success(store);
299
- }, error);
417
+ }, /** @type {SQLStatementErrorCallback} */ (error));
300
418
  }
301
419
 
302
420
  if (!CFG.useSQLiteIndexes) {
@@ -311,24 +429,31 @@ IDBIndex.__deleteIndex = function (store, index) {
311
429
  ),
312
430
  [],
313
431
  finishDeleteIndex,
314
- error
432
+ /** @type {SQLStatementErrorCallback} */ (error)
315
433
  );
316
- }, undefined, store);
434
+ });
317
435
  };
318
436
 
437
+ /**
438
+ * @typedef {{[key: string]: IDBIndexProperties}} IndexList
439
+ */
440
+
319
441
  /**
320
442
  * Updates index list for the given object store.
321
- * @param {IDBObjectStore} store
322
- * @param {object} tx
323
- * @param {function} success
324
- * @param {function} failure
443
+ * @param {import('./IDBObjectStore.js').IDBObjectStoreFull} store
444
+ * @param {SQLTransaction} tx
445
+ * @param {(store: IDBObjectStore) => void} success
446
+ * @param {(
447
+ * tx: SQLTransaction,
448
+ * err: SQLError
449
+ * ) => boolean} [failure]
325
450
  * @returns {void}
326
451
  */
327
452
  IDBIndex.__updateIndexList = function (store, tx, success, failure) {
453
+ /** @type {IndexList} **/
328
454
  const indexList = {};
329
455
  for (let i = 0; i < store.indexNames.length; i++) {
330
456
  const idx = store.__indexes[store.indexNames[i]];
331
- /** @type {IDBIndexProperties} **/
332
457
  indexList[idx.name] = {
333
458
  columnName: idx.name,
334
459
  keyPath: idx.keyPath,
@@ -336,24 +461,28 @@ IDBIndex.__updateIndexList = function (store, tx, success, failure) {
336
461
  unique: idx.unique,
337
462
  multiEntry: idx.multiEntry
338
463
  },
339
- deleted: Boolean(idx.deleted)
464
+ deleted: Boolean(idx.__deleted)
340
465
  };
341
466
  }
342
467
 
343
- CFG.DEBUG && console.log('Updating the index list for ' + store.__currentName, indexList);
468
+ if (CFG.DEBUG) { console.log('Updating the index list for ' + store.__currentName, indexList); }
344
469
  tx.executeSql('UPDATE __sys__ SET "indexList" = ? WHERE "name" = ?', [JSON.stringify(indexList), util.escapeSQLiteStatement(store.__currentName)], function () {
345
470
  success(store);
346
- }, failure);
471
+ }, /** @type {SQLStatementErrorCallback} */ (failure));
347
472
  };
348
473
 
474
+ /**
475
+ * @typedef {any|IDBKeyRange} Query
476
+ */
477
+
349
478
  /**
350
479
  * Retrieves index data for the given key.
351
- * @param {*|IDBKeyRange} range
352
- * @param {string} opType
480
+ * @param {Query} range
481
+ * @param {"value"|"key"|"count"} opType
353
482
  * @param {boolean} nullDisallowed
354
- * @param {number} count
355
- * @returns {IDBRequest}
356
- * @private
483
+ * @param {number} [count]
484
+ * @this {IDBIndexFull}
485
+ * @returns {import('./IDBRequest.js').IDBRequestFull}
357
486
  */
358
487
  IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed, count) {
359
488
  const me = this;
@@ -373,20 +502,24 @@ IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed, c
373
502
  }
374
503
 
375
504
  const fetchArgs = buildFetchIndexDataSQL(nullDisallowed, me, range, opType, false);
376
- return me.objectStore.transaction.__addToTransactionQueue(function (...args) {
377
- executeFetchIndexData(count, ...fetchArgs, ...args);
505
+ return /** @type {import('./IDBTransaction.js').IDBTransactionFull} */ (
506
+ me.objectStore.transaction
507
+ ).__addToTransactionQueue(function (...args) {
508
+ executeFetchIndexData(
509
+ count,
510
+ ...fetchArgs,
511
+ // @ts-expect-error It's ok
512
+ ...args
513
+ );
378
514
  }, undefined, me);
379
515
  };
380
516
 
381
- /* eslint-disable jsdoc/check-param-names */
382
517
  /**
383
518
  * Opens a cursor over the given key range.
384
- * @param {*|IDBKeyRange} query
385
- * @param {string} direction
386
- * @returns {IDBRequest}
519
+ * @this {IDBIndexFull}
520
+ * @returns {import('./IDBRequest.js').IDBRequestFull}
387
521
  */
388
522
  IDBIndex.prototype.openCursor = function (/* query, direction */) {
389
- /* eslint-enable jsdoc/check-param-names */
390
523
  const me = this;
391
524
  // eslint-disable-next-line prefer-rest-params
392
525
  const [query, direction] = arguments;
@@ -395,15 +528,12 @@ IDBIndex.prototype.openCursor = function (/* query, direction */) {
395
528
  return cursor.__request;
396
529
  };
397
530
 
398
- /* eslint-disable jsdoc/check-param-names */
399
531
  /**
400
532
  * Opens a cursor over the given key range. The cursor only includes key values, not data.
401
- * @param {*|IDBKeyRange} query
402
- * @param {string} direction
403
- * @returns {IDBRequest}
533
+ * @this {IDBIndexFull}
534
+ * @returns {import('./IDBRequest.js').IDBRequestFull}
404
535
  */
405
536
  IDBIndex.prototype.openKeyCursor = function (/* query, direction */) {
406
- /* eslint-enable jsdoc/check-param-names */
407
537
  const me = this;
408
538
  // eslint-disable-next-line prefer-rest-params
409
539
  const [query, direction] = arguments;
@@ -412,6 +542,13 @@ IDBIndex.prototype.openKeyCursor = function (/* query, direction */) {
412
542
  return cursor.__request;
413
543
  };
414
544
 
545
+ /**
546
+ *
547
+ * @param {Query} query
548
+ * @throws {TypeError}
549
+ * @this {IDBIndexFull}
550
+ * @returns {import('./IDBRequest.js').IDBRequestFull}
551
+ */
415
552
  IDBIndex.prototype.get = function (query) {
416
553
  if (!arguments.length) { // Per https://heycam.github.io/webidl/
417
554
  throw new TypeError('A parameter was missing for `IDBIndex.get`.');
@@ -419,6 +556,13 @@ IDBIndex.prototype.get = function (query) {
419
556
  return this.__fetchIndexData(query, 'value', true);
420
557
  };
421
558
 
559
+ /**
560
+ *
561
+ * @param {Query} query
562
+ * @throws {TypeError}
563
+ * @this {IDBIndexFull}
564
+ * @returns {import('./IDBRequest.js').IDBRequestFull}
565
+ */
422
566
  IDBIndex.prototype.getKey = function (query) {
423
567
  if (!arguments.length) { // Per https://heycam.github.io/webidl/
424
568
  throw new TypeError('A parameter was missing for `IDBIndex.getKey`.');
@@ -426,18 +570,30 @@ IDBIndex.prototype.getKey = function (query) {
426
570
  return this.__fetchIndexData(query, 'key', true);
427
571
  };
428
572
 
573
+ /**
574
+ * @this {IDBIndexFull}
575
+ * @returns {import('./IDBRequest.js').IDBRequestFull}
576
+ */
429
577
  IDBIndex.prototype.getAll = function (/* query, count */) {
430
578
  // eslint-disable-next-line prefer-rest-params
431
579
  const [query, count] = arguments;
432
580
  return this.__fetchIndexData(query, 'value', false, count);
433
581
  };
434
582
 
583
+ /**
584
+ * @this {IDBIndexFull}
585
+ * @returns {import('./IDBRequest.js').IDBRequestFull}
586
+ */
435
587
  IDBIndex.prototype.getAllKeys = function (/* query, count */) {
436
588
  // eslint-disable-next-line prefer-rest-params
437
589
  const [query, count] = arguments;
438
590
  return this.__fetchIndexData(query, 'key', false, count);
439
591
  };
440
592
 
593
+ /**
594
+ * @this {IDBIndexFull}
595
+ * @returns {import('./IDBRequest.js').IDBRequestFull}
596
+ */
441
597
  IDBIndex.prototype.count = function (/* query */) {
442
598
  const me = this;
443
599
  // eslint-disable-next-line prefer-rest-params
@@ -454,6 +610,19 @@ IDBIndex.prototype.count = function (/* query */) {
454
610
  return me.__fetchIndexData(query, 'count', false);
455
611
  };
456
612
 
613
+ /**
614
+ *
615
+ * @param {import('./IDBObjectStore.js').IDBObjectStoreFull} store
616
+ * @param {string} oldName
617
+ * @param {string} newName
618
+ * @param {string[][]} colInfoToPreserveArr
619
+ * @param {null|((
620
+ * tx: SQLTransaction,
621
+ * success: ((store: IDBObjectStore) => void)
622
+ * ) => void)} cb
623
+ * @this {IDBIndexFull}
624
+ * @returns {void}
625
+ */
457
626
  IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToPreserveArr = [], cb = null) {
458
627
  const newNameType = 'BLOB';
459
628
  const storeName = store.__currentName;
@@ -467,10 +636,20 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
467
636
 
468
637
  // We could adapt the approach at http://stackoverflow.com/a/8430746/271577
469
638
  // to make the approach reusable without passing column names, but it is a bit fragile
470
- store.transaction.__addNonRequestToTransactionQueue(function renameIndex (tx, args, success, error) {
639
+ /** @type {import('./IDBTransaction.js').IDBTransactionFull} */ (
640
+ store.transaction
641
+ ).__addNonRequestToTransactionQueue(function renameIndex (tx, args, success, error) {
642
+ /**
643
+ * @param {SQLTransaction} tx
644
+ * @param {SQLError} err
645
+ * @returns {void}
646
+ */
471
647
  function sqlError (tx, err) {
472
648
  error(err);
473
649
  }
650
+ /**
651
+ * @returns {void}
652
+ */
474
653
  function finish () {
475
654
  if (cb) {
476
655
  cb(tx, success);
@@ -483,19 +662,19 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
483
662
  // This approach has the advantage of auto-deleting indexes via the DROP TABLE
484
663
  const sql = 'CREATE TABLE ' + escapedTmpStoreNameSQL +
485
664
  '(' + listColInfoToPreserve + escapedNewIndexNameSQL + ' ' + newNameType + ')';
486
- CFG.DEBUG && console.log(sql);
665
+ if (CFG.DEBUG) { console.log(sql); }
487
666
  tx.executeSql(sql, [], function () {
488
667
  const sql = 'INSERT INTO ' + escapedTmpStoreNameSQL + '(' +
489
668
  listColsToPreserve + escapedNewIndexNameSQL +
490
669
  ') SELECT ' + listColsToPreserve + util.escapeIndexNameForSQL(oldName) + ' FROM ' + escapedStoreNameSQL;
491
- CFG.DEBUG && console.log(sql);
670
+ if (CFG.DEBUG) { console.log(sql); }
492
671
  tx.executeSql(sql, [], function () {
493
672
  const sql = 'DROP TABLE ' + escapedStoreNameSQL;
494
- CFG.DEBUG && console.log(sql);
673
+ if (CFG.DEBUG) { console.log(sql); }
495
674
  tx.executeSql(sql, [], function () {
496
675
  const sql = 'ALTER TABLE ' + escapedTmpStoreNameSQL + ' RENAME TO ' + escapedStoreNameSQL;
497
- CFG.DEBUG && console.log(sql);
498
- tx.executeSql(sql, [], function (tx, data) {
676
+ if (CFG.DEBUG) { console.log(sql); }
677
+ tx.executeSql(sql, [], function (tx) {
499
678
  if (!CFG.useSQLiteIndexes) {
500
679
  finish();
501
680
  return;
@@ -507,14 +686,20 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
507
686
  escapedStoreNameSQL.slice(1, -1) + '^5' + escapedIndexNameSQL.slice(1, -1)
508
687
  );
509
688
  // const sql = 'DROP INDEX IF EXISTS ' + escapedIndexToRecreate;
510
- // CFG.DEBUG && console.log(sql);
689
+ // if (CFG.DEBUG) { console.log(sql); }
511
690
  // tx.executeSql(sql, [], function () {
512
691
  const sql = 'CREATE INDEX ' +
513
692
  escapedIndexToRecreate + ' ON ' + escapedStoreNameSQL + '(' + escapedIndexNameSQL + ')';
514
- CFG.DEBUG && console.log(sql);
515
- tx.executeSql(sql, [], resolve, function (tx, err) {
516
- reject(err);
517
- });
693
+ if (CFG.DEBUG) { console.log(sql); }
694
+ tx.executeSql(
695
+ sql,
696
+ [],
697
+ resolve,
698
+ /** @type {SQLStatementErrorCallback} */
699
+ (function (tx, err) {
700
+ reject(err);
701
+ })
702
+ );
518
703
  // }, function (tx, err) {
519
704
  // reject(err);
520
705
  // });
@@ -524,32 +709,56 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
524
709
  const escapedIndexToRecreate = util.sqlQuote('sk_' + escapedStoreNameSQL.slice(1, -1));
525
710
  // Chrome erring here if not dropped first; Node does not
526
711
  const sql = 'DROP INDEX IF EXISTS ' + escapedIndexToRecreate;
527
- CFG.DEBUG && console.log(sql);
528
- tx.executeSql(sql, [], function () {
529
- const sql = 'CREATE INDEX ' + escapedIndexToRecreate +
530
- ' ON ' + escapedStoreNameSQL + '("key")';
531
- CFG.DEBUG && console.log(sql);
532
- tx.executeSql(sql, [], resolve, function (tx, err) {
712
+ if (CFG.DEBUG) { console.log(sql); }
713
+ tx.executeSql(
714
+ sql, [], function () {
715
+ const sql = 'CREATE INDEX ' + escapedIndexToRecreate +
716
+ ' ON ' + escapedStoreNameSQL + '("key")';
717
+ if (CFG.DEBUG) { console.log(sql); }
718
+ tx.executeSql(
719
+ sql, [], resolve,
720
+ /** @type {SQLStatementErrorCallback} */
721
+ (function (tx, err) {
722
+ reject(err);
723
+ })
724
+ );
725
+ },
726
+ /** @type {SQLStatementErrorCallback} */
727
+ (function (tx, err) {
533
728
  reject(err);
534
- });
535
- }, function (tx, err) {
536
- reject(err);
537
- });
729
+ })
730
+ );
538
731
  })
539
732
  );
540
- SyncPromise.all(indexCreations).then(finish, error).catch((err) => {
733
+ SyncPromise.all(indexCreations).then(
734
+ finish,
735
+ /** @type {(reason: any) => PromiseLike<never>} */
736
+ (error)
737
+ ).catch((err) => {
541
738
  console.log('Index rename error');
542
739
  throw err;
543
740
  });
544
- }, sqlError);
545
- }, sqlError);
546
- }, sqlError);
547
- }, sqlError);
741
+ }, /** @type {SQLStatementErrorCallback} */ (sqlError));
742
+ }, /** @type {SQLStatementErrorCallback} */ (sqlError));
743
+ }, /** @type {SQLStatementErrorCallback} */ (sqlError));
744
+ }, /** @type {SQLStatementErrorCallback} */ (sqlError));
548
745
  });
549
746
  };
550
747
 
748
+ /**
749
+ * @typedef {any} AnyValue
750
+ */
751
+
551
752
  Object.defineProperty(IDBIndex, Symbol.hasInstance, {
552
- value: (obj) => util.isObj(obj) && typeof obj.openCursor === 'function' && typeof obj.multiEntry === 'boolean'
753
+ /**
754
+ * @param {AnyValue} obj
755
+ * @returns {boolean}
756
+ */
757
+ value: (obj) => util.isObj(obj) &&
758
+ 'openCursor' in obj &&
759
+ typeof obj.openCursor === 'function' &&
760
+ 'multiEntry' in obj &&
761
+ typeof obj.multiEntry === 'boolean'
553
762
  });
554
763
 
555
764
  util.defineReadonlyOuterInterface(IDBIndex.prototype, readonlyProperties);
@@ -561,26 +770,61 @@ Object.defineProperty(IDBIndex, 'prototype', {
561
770
  writable: false
562
771
  });
563
772
 
564
- function executeFetchIndexData (count, unboundedDisallowed, index, hasKey, range, opType, multiChecks, sql, sqlValues, tx, args, success, error) {
773
+ /**
774
+ * @param {number|null} count
775
+ * @param {boolean} unboundedDisallowed
776
+ * @param {IDBIndexFull} index
777
+ * @param {boolean} hasKey
778
+ * @param {import('./Key.js').Value|import('./Key.js').Key} range
779
+ * @param {"value"|"key"|"count"} opType
780
+ * @param {boolean} multiChecks
781
+ * @param {string[]} sql
782
+ * @param {string[]} sqlValues
783
+ * @param {SQLTransaction} tx
784
+ * @param {null|undefined} args
785
+ * @param {(result: number|undefined|[]|AnyValue|AnyValue[]) => void} success
786
+ * @param {(tx: SQLTransaction, err: SQLError) => void} error
787
+ * @returns {void}
788
+ */
789
+ function executeFetchIndexData (
790
+ count, unboundedDisallowed, index, hasKey, range, opType,
791
+ multiChecks, sql, sqlValues, tx, args, success, error
792
+ ) {
565
793
  if (unboundedDisallowed) {
566
794
  count = 1;
567
795
  }
568
796
  if (count) {
569
- sql.push('LIMIT', count);
797
+ sql.push('LIMIT', String(count));
570
798
  }
571
799
  const isCount = opType === 'count';
572
- CFG.DEBUG && console.log('Trying to fetch data for Index', sql.join(' '), sqlValues);
800
+ if (CFG.DEBUG) { console.log('Trying to fetch data for Index', sql.join(' '), sqlValues); }
573
801
  tx.executeSql(sql.join(' '), sqlValues, function (tx, data) {
574
802
  const records = [];
575
803
  let recordCount = 0;
576
804
  const decode = isCount
577
805
  ? () => { /* */ }
578
806
  : (opType === 'key'
579
- ? (record) => {
807
+ // eslint-disable-next-line @stylistic/operator-linebreak -- JSDoc
808
+ ?
809
+ /**
810
+ * @param {{
811
+ * key: string
812
+ * }} record
813
+ * @returns {import('./Key.js').ValueType|undefined}
814
+ */
815
+ (record) => {
580
816
  // Key.convertValueToKey(record.key); // Already validated before storage
581
817
  return Key.decode(util.unescapeSQLiteResponse(record.key));
582
818
  }
583
- : (record) => { // when opType is value
819
+ // eslint-disable-next-line @stylistic/operator-linebreak -- JSDoc
820
+ :
821
+ /**
822
+ * @param {{
823
+ * value: string
824
+ * }} record
825
+ * @returns {AnyValue}
826
+ */
827
+ (record) => { // when opType is value
584
828
  return Sca.decode(util.unescapeSQLiteResponse(record.value));
585
829
  });
586
830
  if (index.multiEntry) {
@@ -588,11 +832,23 @@ function executeFetchIndexData (count, unboundedDisallowed, index, hasKey, range
588
832
  const encodedKey = Key.encode(range, index.multiEntry);
589
833
  for (let i = 0; i < data.rows.length; i++) {
590
834
  const row = data.rows.item(i);
591
- const rowKey = Key.decode(row[escapedIndexNameForKeyCol]);
835
+ const rowKey = /** @type {import('./Key.js').ValueTypeArray} */ (
836
+ Key.decode(row[escapedIndexNameForKeyCol])
837
+ );
592
838
  let record;
593
839
  if (hasKey && (
594
- (multiChecks && range.some((check) => rowKey.includes(check))) || // More precise than our SQL
595
- Key.isMultiEntryMatch(encodedKey, row[escapedIndexNameForKeyCol])
840
+ (multiChecks && range.some(
841
+ /**
842
+ * @param {string} check
843
+ * @returns {boolean}
844
+ */
845
+ (check) => rowKey.includes(check)
846
+ )) || // More precise than our SQL
847
+ Key.isMultiEntryMatch(
848
+ /** @type {string} */
849
+ (encodedKey),
850
+ row[escapedIndexNameForKeyCol]
851
+ )
596
852
  )) {
597
853
  recordCount++;
598
854
  record = row;
@@ -625,10 +881,29 @@ function executeFetchIndexData (count, unboundedDisallowed, index, hasKey, range
625
881
  } else {
626
882
  success(unboundedDisallowed ? records[0] : records);
627
883
  }
628
- }, error);
884
+ }, /** @type {SQLStatementErrorCallback} */ (error));
629
885
  }
630
886
 
631
- function buildFetchIndexDataSQL (nullDisallowed, index, range, opType, multiChecks) {
887
+ /**
888
+ * @param {boolean} nullDisallowed
889
+ * @param {IDBIndexFull} index
890
+ * @param {import('./Key.js').Value|import('./Key.js').Key} range
891
+ * @param {"value"|"key"|"count"} opType
892
+ * @param {boolean} multiChecks
893
+ * @returns {[
894
+ * nullDisallowed: boolean,
895
+ * index: IDBIndexFull,
896
+ * hasRange: boolean,
897
+ * range: import('./Key.js').Value|import('./Key.js').Key,
898
+ * opType: "value"|"key"|"count",
899
+ * multiChecks: boolean,
900
+ * sql: string[],
901
+ * sqlValues: string[]
902
+ * ]}
903
+ */
904
+ function buildFetchIndexDataSQL (
905
+ nullDisallowed, index, range, opType, multiChecks
906
+ ) {
632
907
  const hasRange = nullDisallowed || !util.isNullish(range);
633
908
  const col = opType === 'count' ? 'key' : opType; // It doesn't matter which column we use for 'count' as long as it is valid
634
909
  const sql = [
@@ -638,19 +913,27 @@ function buildFetchIndexDataSQL (nullDisallowed, index, range, opType, multiChec
638
913
  'FROM', util.escapeStoreNameForSQL(index.objectStore.__currentName),
639
914
  'WHERE', util.escapeIndexNameForSQL(index.name), 'NOT NULL'
640
915
  ];
916
+
917
+ /** @type {string[]} */
641
918
  const sqlValues = [];
642
919
  if (hasRange) {
643
920
  if (multiChecks) {
644
921
  sql.push('AND (');
645
- range.forEach((innerKey, i) => {
646
- if (i > 0) sql.push('OR');
922
+ /** @type {import('./Key.js').KeyPathArray} */ (
923
+ range
924
+ ).forEach((innerKey, i) => {
925
+ if (i > 0) { sql.push('OR'); }
647
926
  sql.push(util.escapeIndexNameForSQL(index.name), "LIKE ? ESCAPE '^' ");
648
- sqlValues.push('%' + util.sqlLIKEEscape(Key.encode(innerKey, index.multiEntry)) + '%');
927
+ sqlValues.push('%' + util.sqlLIKEEscape(
928
+ /** @type {string} */ (Key.encode(innerKey, index.multiEntry))
929
+ ) + '%');
649
930
  });
650
931
  sql.push(')');
651
932
  } else if (index.multiEntry) {
652
933
  sql.push('AND', util.escapeIndexNameForSQL(index.name), "LIKE ? ESCAPE '^'");
653
- sqlValues.push('%' + util.sqlLIKEEscape(Key.encode(range, index.multiEntry)) + '%');
934
+ sqlValues.push('%' + util.sqlLIKEEscape(
935
+ /** @type {string} */ (Key.encode(range, index.multiEntry))
936
+ ) + '%');
654
937
  } else {
655
938
  const convertedRange = convertValueToKeyRange(range, nullDisallowed);
656
939
  setSQLForKeyRange(convertedRange, util.escapeIndexNameForSQL(index.name), sql, sqlValues, true, false);