@speckle/objectloader2 2.25.9 → 2.26.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 (92) hide show
  1. package/dist/commonjs/core/interfaces.d.ts +4 -6
  2. package/dist/commonjs/core/interfaces.d.ts.map +1 -1
  3. package/dist/commonjs/core/objectLoader2.js +2 -2
  4. package/dist/commonjs/core/objectLoader2.js.map +1 -1
  5. package/dist/commonjs/core/objectLoader2Factory.d.ts.map +1 -1
  6. package/dist/commonjs/core/objectLoader2Factory.js +4 -3
  7. package/dist/commonjs/core/objectLoader2Factory.js.map +1 -1
  8. package/dist/commonjs/core/stages/cacheWriter.js +1 -1
  9. package/dist/commonjs/core/stages/cacheWriter.js.map +1 -1
  10. package/dist/commonjs/core/stages/indexedDatabase.d.ts +20 -6
  11. package/dist/commonjs/core/stages/indexedDatabase.d.ts.map +1 -1
  12. package/dist/commonjs/core/stages/indexedDatabase.js +138 -19
  13. package/dist/commonjs/core/stages/indexedDatabase.js.map +1 -1
  14. package/dist/commonjs/core/stages/memory/memoryDatabase.d.ts +2 -4
  15. package/dist/commonjs/core/stages/memory/memoryDatabase.d.ts.map +1 -1
  16. package/dist/commonjs/core/stages/memory/memoryDatabase.js +3 -3
  17. package/dist/commonjs/core/stages/memory/memoryDatabase.js.map +1 -1
  18. package/dist/commonjs/core/stages/memory/memoryDownloader.d.ts +1 -1
  19. package/dist/commonjs/core/stages/memory/memoryDownloader.d.ts.map +1 -1
  20. package/dist/commonjs/core/stages/memory/memoryDownloader.js +1 -1
  21. package/dist/commonjs/core/stages/memory/memoryDownloader.js.map +1 -1
  22. package/dist/commonjs/core/stages/serverDownloader.d.ts +3 -2
  23. package/dist/commonjs/core/stages/serverDownloader.d.ts.map +1 -1
  24. package/dist/commonjs/core/stages/serverDownloader.js +12 -19
  25. package/dist/commonjs/core/stages/serverDownloader.js.map +1 -1
  26. package/dist/commonjs/queues/keyedQueue.test.d.ts +2 -0
  27. package/dist/commonjs/queues/keyedQueue.test.d.ts.map +1 -0
  28. package/dist/commonjs/queues/keyedQueue.test.js +118 -0
  29. package/dist/commonjs/queues/keyedQueue.test.js.map +1 -0
  30. package/dist/esm/core/interfaces.d.ts +4 -6
  31. package/dist/esm/core/interfaces.d.ts.map +1 -1
  32. package/dist/esm/core/objectLoader2.js +2 -2
  33. package/dist/esm/core/objectLoader2.js.map +1 -1
  34. package/dist/esm/core/objectLoader2Factory.d.ts.map +1 -1
  35. package/dist/esm/core/objectLoader2Factory.js +3 -2
  36. package/dist/esm/core/objectLoader2Factory.js.map +1 -1
  37. package/dist/esm/core/stages/cacheWriter.js +1 -1
  38. package/dist/esm/core/stages/cacheWriter.js.map +1 -1
  39. package/dist/esm/core/stages/indexedDatabase.d.ts +20 -6
  40. package/dist/esm/core/stages/indexedDatabase.d.ts.map +1 -1
  41. package/dist/esm/core/stages/indexedDatabase.js +140 -22
  42. package/dist/esm/core/stages/indexedDatabase.js.map +1 -1
  43. package/dist/esm/core/stages/memory/memoryDatabase.d.ts +2 -4
  44. package/dist/esm/core/stages/memory/memoryDatabase.d.ts.map +1 -1
  45. package/dist/esm/core/stages/memory/memoryDatabase.js +3 -3
  46. package/dist/esm/core/stages/memory/memoryDatabase.js.map +1 -1
  47. package/dist/esm/core/stages/memory/memoryDownloader.d.ts +1 -1
  48. package/dist/esm/core/stages/memory/memoryDownloader.d.ts.map +1 -1
  49. package/dist/esm/core/stages/memory/memoryDownloader.js +1 -1
  50. package/dist/esm/core/stages/memory/memoryDownloader.js.map +1 -1
  51. package/dist/esm/core/stages/serverDownloader.d.ts +3 -2
  52. package/dist/esm/core/stages/serverDownloader.d.ts.map +1 -1
  53. package/dist/esm/core/stages/serverDownloader.js +12 -19
  54. package/dist/esm/core/stages/serverDownloader.js.map +1 -1
  55. package/dist/esm/queues/keyedQueue.test.d.ts +2 -0
  56. package/dist/esm/queues/keyedQueue.test.d.ts.map +1 -0
  57. package/dist/esm/queues/keyedQueue.test.js +113 -0
  58. package/dist/esm/queues/keyedQueue.test.js.map +1 -0
  59. package/package.json +2 -2
  60. package/src/core/interfaces.ts +4 -4
  61. package/src/core/objectLoader2.spec.ts +1 -1
  62. package/src/core/objectLoader2.ts +2 -2
  63. package/src/core/objectLoader2Factory.ts +3 -2
  64. package/src/core/stages/cacheWriter.spec.ts +4 -4
  65. package/src/core/stages/cacheWriter.ts +1 -1
  66. package/src/core/stages/indexedDatabase.spec.ts +6 -6
  67. package/src/core/stages/indexedDatabase.ts +154 -25
  68. package/src/core/stages/memory/memoryDatabase.spec.ts +6 -6
  69. package/src/core/stages/memory/memoryDatabase.ts +3 -3
  70. package/src/core/stages/memory/memoryDownloader.spec.ts +2 -2
  71. package/src/core/stages/memory/memoryDownloader.ts +1 -1
  72. package/src/core/stages/serverDownloader.spec.ts +20 -12
  73. package/src/core/stages/serverDownloader.ts +18 -24
  74. package/src/queues/keyedQueue.test.ts +146 -0
  75. package/dist/commonjs/core/stages/ItemStore.d.ts +0 -37
  76. package/dist/commonjs/core/stages/ItemStore.d.ts.map +0 -1
  77. package/dist/commonjs/core/stages/ItemStore.js +0 -167
  78. package/dist/commonjs/core/stages/ItemStore.js.map +0 -1
  79. package/dist/commonjs/queues/batchedPool.d.ts +0 -13
  80. package/dist/commonjs/queues/batchedPool.d.ts.map +0 -1
  81. package/dist/commonjs/queues/batchedPool.js +0 -45
  82. package/dist/commonjs/queues/batchedPool.js.map +0 -1
  83. package/dist/esm/core/stages/ItemStore.d.ts +0 -37
  84. package/dist/esm/core/stages/ItemStore.d.ts.map +0 -1
  85. package/dist/esm/core/stages/ItemStore.js +0 -163
  86. package/dist/esm/core/stages/ItemStore.js.map +0 -1
  87. package/dist/esm/queues/batchedPool.d.ts +0 -13
  88. package/dist/esm/queues/batchedPool.d.ts.map +0 -1
  89. package/dist/esm/queues/batchedPool.js +0 -42
  90. package/dist/esm/queues/batchedPool.js.map +0 -1
  91. package/src/core/stages/ItemStore.ts +0 -196
  92. package/src/queues/batchedPool.ts +0 -58
@@ -1,37 +0,0 @@
1
- import { Item } from '../../types/types.js';
2
- /**
3
- * A wrapper class for IndexedDB to simplify common database operations.
4
- */
5
- export interface ItemStoreOptions {
6
- indexedDB?: IDBFactory;
7
- keyRange?: {
8
- bound: Function;
9
- lowerBound: Function;
10
- upperBound: Function;
11
- };
12
- }
13
- export declare class ItemStore {
14
- #private;
15
- constructor(options: ItemStoreOptions, dbName: string, storeName: string);
16
- /**
17
- * Initializes the database connection and creates the object store if needed.
18
- * This must be called before any other database operations.
19
- */
20
- init(): Promise<void>;
21
- /**
22
- * Inserts or updates an array of items in a single transaction.
23
- * @param data The array of items to insert.
24
- */
25
- bulkInsert(data: Item[]): Promise<void>;
26
- /**
27
- * Retrieves an array of items from the object store based on their IDs.
28
- * @param ids The array of IDs to retrieve.
29
- */
30
- bulkGet(ids: string[]): Promise<(Item | undefined)[]>;
31
- /**
32
- * Retrieves all items from the object store.
33
- */
34
- getAll(): Promise<Item[]>;
35
- close(): void;
36
- }
37
- //# sourceMappingURL=ItemStore.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ItemStore.d.ts","sourceRoot":"","sources":["../../../../src/core/stages/ItemStore.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAE3C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,UAAU,CAAA;IACtB,QAAQ,CAAC,EAAE;QACT,KAAK,EAAE,QAAQ,CAAA;QACf,UAAU,EAAE,QAAQ,CAAA;QACpB,UAAU,EAAE,QAAQ,CAAA;KACrB,CAAA;CACF;AACD,qBAAa,SAAS;;gBAOR,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAMxE;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAwE3B;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBvC;;;OAGG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;IAmCrD;;OAEG;IACH,MAAM,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAezB,KAAK,IAAI,IAAI;CAKd"}
@@ -1,163 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-base-to-string */
2
- /* eslint-disable @typescript-eslint/prefer-promise-reject-errors */
3
- /* eslint-disable @typescript-eslint/no-explicit-any */
4
- /* eslint-disable @typescript-eslint/no-unsafe-function-type */
5
- import { isSafari } from '@speckle/shared';
6
- export class ItemStore {
7
- #options;
8
- #db = undefined;
9
- #dbName;
10
- #storeName;
11
- constructor(options, dbName, storeName) {
12
- this.#options = options;
13
- this.#dbName = dbName;
14
- this.#storeName = storeName;
15
- }
16
- /**
17
- * Initializes the database connection and creates the object store if needed.
18
- * This must be called before any other database operations.
19
- */
20
- async init() {
21
- if (this.#db)
22
- return;
23
- await this.#safariFix();
24
- return this.#openDatabase();
25
- }
26
- /**
27
- * Opens the database, and if there's an error, deletes the database and tries again.
28
- */
29
- async #openDatabase() {
30
- const idb = this.#options.indexedDB ?? indexedDB;
31
- return new Promise((resolve, reject) => {
32
- const request = idb.open(this.#dbName, 1);
33
- request.onerror = () => {
34
- console.warn(`Failed to open database: ${this.#dbName}, deleting and trying again`);
35
- // Delete the database and try again
36
- const deleteRequest = idb.deleteDatabase(this.#dbName);
37
- deleteRequest.onsuccess = () => {
38
- // Try opening again after deletion
39
- void this.#openDatabase().then(resolve).catch(reject);
40
- };
41
- deleteRequest.onerror = () => {
42
- reject(`Failed to delete and reopen database: ${this.#dbName}`);
43
- };
44
- };
45
- request.onupgradeneeded = (event) => {
46
- const db = event.target.result;
47
- if (db.objectStoreNames.contains(this.#storeName)) {
48
- db.deleteObjectStore(this.#storeName);
49
- }
50
- db.createObjectStore(this.#storeName, { keyPath: 'baseId' });
51
- };
52
- request.onsuccess = (event) => {
53
- this.#db = event.target.result;
54
- resolve();
55
- };
56
- });
57
- }
58
- #getDB() {
59
- if (!this.#db) {
60
- throw new Error('Database not initialized. Call init() first.');
61
- }
62
- return this.#db;
63
- }
64
- /**
65
- * Fixes a Safari bug where IndexedDB requests get lost and never resolve - invoke before you use IndexedDB
66
- * @link Credits and more info: https://github.com/jakearchibald/safari-14-idb-fix
67
- */
68
- async #safariFix() {
69
- // No point putting other browsers or older versions of Safari through this mess.
70
- if (!isSafari() || !this.#options.indexedDB?.databases)
71
- return Promise.resolve();
72
- let intervalId;
73
- return new Promise((resolve) => {
74
- const tryIdb = () => this.#options.indexedDB?.databases().finally(resolve);
75
- intervalId = setInterval(() => {
76
- void tryIdb();
77
- }, 100);
78
- void tryIdb();
79
- }).finally(() => clearInterval(intervalId));
80
- }
81
- /**
82
- * Inserts or updates an array of items in a single transaction.
83
- * @param data The array of items to insert.
84
- */
85
- bulkInsert(data) {
86
- return new Promise((resolve, reject) => {
87
- try {
88
- const transaction = this.#getDB().transaction(this.#storeName, 'readwrite', {
89
- durability: 'relaxed'
90
- });
91
- const store = transaction.objectStore(this.#storeName);
92
- transaction.onerror = () => {
93
- reject(`Transaction error: ${transaction.error}`);
94
- };
95
- transaction.oncomplete = () => {
96
- resolve();
97
- };
98
- data.forEach((item) => store.put(item));
99
- }
100
- catch (error) {
101
- reject(error);
102
- }
103
- });
104
- }
105
- /**
106
- * Retrieves an array of items from the object store based on their IDs.
107
- * @param ids The array of IDs to retrieve.
108
- */
109
- bulkGet(ids) {
110
- return new Promise((resolve, reject) => {
111
- if (ids.length === 0) {
112
- return resolve([]);
113
- }
114
- try {
115
- const transaction = this.#getDB().transaction(this.#storeName, 'readonly', {
116
- durability: 'relaxed'
117
- });
118
- const store = transaction.objectStore(this.#storeName);
119
- const promises = [];
120
- for (const id of ids) {
121
- promises.push(new Promise((resolveGet, rejectGet) => {
122
- const request = store.get(id);
123
- request.onerror = () => rejectGet(`Request error for id ${id}: ${request.error}`);
124
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
125
- request.onsuccess = () => resolveGet(request.result);
126
- }));
127
- }
128
- Promise.all(promises)
129
- .then((results) => {
130
- resolve(results);
131
- })
132
- .catch(reject);
133
- }
134
- catch (error) {
135
- reject(error);
136
- }
137
- });
138
- }
139
- /**
140
- * Retrieves all items from the object store.
141
- */
142
- getAll() {
143
- return new Promise((resolve, reject) => {
144
- try {
145
- const transaction = this.#getDB().transaction(this.#storeName, 'readonly');
146
- const store = transaction.objectStore(this.#storeName);
147
- const request = store.getAll();
148
- request.onerror = () => reject(`Request error: ${request.error}`);
149
- request.onsuccess = () => resolve(request.result);
150
- }
151
- catch (error) {
152
- reject(error);
153
- }
154
- });
155
- }
156
- close() {
157
- if (!this.#db)
158
- return;
159
- this.#db.close();
160
- this.#db = undefined;
161
- }
162
- }
163
- //# sourceMappingURL=ItemStore.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ItemStore.js","sourceRoot":"","sources":["../../../../src/core/stages/ItemStore.ts"],"names":[],"mappings":"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"}
@@ -1,13 +0,0 @@
1
- import Queue from './queue.js';
2
- export default class BatchedPool<T> implements Queue<T> {
3
- #private;
4
- constructor(params: {
5
- concurrencyAndSizes: number[];
6
- maxWaitTime?: number;
7
- processFunction: (batch: T[]) => Promise<void>;
8
- });
9
- add(item: T): void;
10
- getBatch(batchSize: number): T[];
11
- disposeAsync(): Promise<void>;
12
- }
13
- //# sourceMappingURL=batchedPool.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"batchedPool.d.ts","sourceRoot":"","sources":["../../../src/queues/batchedPool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAA;AAE9B,MAAM,CAAC,OAAO,OAAO,WAAW,CAAC,CAAC,CAAE,YAAW,KAAK,CAAC,CAAC,CAAC;;gBAUzC,MAAM,EAAE;QAClB,mBAAmB,EAAE,MAAM,EAAE,CAAA;QAC7B,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,eAAe,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KAC/C;IAOD,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAIlB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,CAAC,EAAE;IAc1B,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CAgBpC"}
@@ -1,42 +0,0 @@
1
- export default class BatchedPool {
2
- #queue = [];
3
- #concurrencyAndSizes;
4
- #processFunction;
5
- #baseInterval;
6
- #processingLoop;
7
- #disposed = false;
8
- constructor(params) {
9
- this.#concurrencyAndSizes = params.concurrencyAndSizes;
10
- this.#baseInterval = Math.min(params.maxWaitTime ?? 200, 200); // Initial batch time (ms)
11
- this.#processFunction = params.processFunction;
12
- this.#processingLoop = this.#loop();
13
- }
14
- add(item) {
15
- this.#queue.push(item);
16
- }
17
- getBatch(batchSize) {
18
- return this.#queue.splice(0, Math.min(batchSize, this.#queue.length));
19
- }
20
- async #runWorker(batchSize) {
21
- while (!this.#disposed || this.#queue.length > 0) {
22
- if (this.#queue.length > 0) {
23
- const batch = this.getBatch(batchSize);
24
- await this.#processFunction(batch);
25
- }
26
- await this.#delay(this.#baseInterval);
27
- }
28
- }
29
- async disposeAsync() {
30
- this.#disposed = true;
31
- await this.#processingLoop;
32
- }
33
- async #loop() {
34
- // Initialize workers
35
- const workers = Array.from(this.#concurrencyAndSizes, (batchSize) => this.#runWorker(batchSize));
36
- await Promise.all(workers);
37
- }
38
- #delay(ms) {
39
- return new Promise((resolve) => setTimeout(resolve, ms));
40
- }
41
- }
42
- //# sourceMappingURL=batchedPool.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"batchedPool.js","sourceRoot":"","sources":["../../../src/queues/batchedPool.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,OAAO,WAAW;IAC9B,MAAM,GAAQ,EAAE,CAAA;IAChB,oBAAoB,CAAU;IAC9B,gBAAgB,CAA+B;IAE/C,aAAa,CAAQ;IAErB,eAAe,CAAe;IAC9B,SAAS,GAAG,KAAK,CAAA;IAEjB,YAAY,MAIX;QACC,IAAI,CAAC,oBAAoB,GAAG,MAAM,CAAC,mBAAmB,CAAA;QACtD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,GAAG,EAAE,GAAG,CAAC,CAAA,CAAC,0BAA0B;QACxF,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,eAAe,CAAA;QAC9C,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,KAAK,EAAE,CAAA;IACrC,CAAC;IAED,GAAG,CAAC,IAAO;QACT,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACxB,CAAC;IAED,QAAQ,CAAC,SAAiB;QACxB,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;IACvE,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,SAAiB;QAChC,OAAO,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjD,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;gBACtC,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAA;YACpC,CAAC;YACD,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QACvC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;QACrB,MAAM,IAAI,CAAC,eAAe,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,qBAAqB;QACrB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC,SAAiB,EAAE,EAAE,CAC1E,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAC3B,CAAA;QACD,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAC5B,CAAC;IAED,MAAM,CAAC,EAAU;QACf,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;IAC1D,CAAC;CACF"}
@@ -1,196 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-base-to-string */
2
- /* eslint-disable @typescript-eslint/prefer-promise-reject-errors */
3
- /* eslint-disable @typescript-eslint/no-explicit-any */
4
- /* eslint-disable @typescript-eslint/no-unsafe-function-type */
5
- import { isSafari } from '@speckle/shared'
6
- import { Item } from '../../types/types.js'
7
-
8
- /**
9
- * A wrapper class for IndexedDB to simplify common database operations.
10
- */
11
- export interface ItemStoreOptions {
12
- indexedDB?: IDBFactory
13
- keyRange?: {
14
- bound: Function
15
- lowerBound: Function
16
- upperBound: Function
17
- }
18
- }
19
- export class ItemStore {
20
- #options: ItemStoreOptions
21
-
22
- #db: IDBDatabase | undefined = undefined
23
- readonly #dbName: string
24
- readonly #storeName: string
25
-
26
- constructor(options: ItemStoreOptions, dbName: string, storeName: string) {
27
- this.#options = options
28
- this.#dbName = dbName
29
- this.#storeName = storeName
30
- }
31
-
32
- /**
33
- * Initializes the database connection and creates the object store if needed.
34
- * This must be called before any other database operations.
35
- */
36
- async init(): Promise<void> {
37
- if (this.#db) return
38
- await this.#safariFix()
39
- return this.#openDatabase()
40
- }
41
-
42
- /**
43
- * Opens the database, and if there's an error, deletes the database and tries again.
44
- */
45
- async #openDatabase(): Promise<void> {
46
- const idb = this.#options.indexedDB ?? indexedDB
47
-
48
- return new Promise((resolve, reject) => {
49
- const request = idb.open(this.#dbName, 1)
50
-
51
- request.onerror = (): any => {
52
- console.warn(
53
- `Failed to open database: ${this.#dbName}, deleting and trying again`
54
- )
55
- // Delete the database and try again
56
- const deleteRequest = idb.deleteDatabase(this.#dbName)
57
- deleteRequest.onsuccess = (): any => {
58
- // Try opening again after deletion
59
- void this.#openDatabase().then(resolve).catch(reject)
60
- }
61
- deleteRequest.onerror = (): any => {
62
- reject(`Failed to delete and reopen database: ${this.#dbName}`)
63
- }
64
- }
65
-
66
- request.onupgradeneeded = (event): any => {
67
- const db = (event.target as IDBOpenDBRequest).result
68
- if (db.objectStoreNames.contains(this.#storeName)) {
69
- db.deleteObjectStore(this.#storeName)
70
- }
71
- db.createObjectStore(this.#storeName, { keyPath: 'baseId' })
72
- }
73
-
74
- request.onsuccess = (event): any => {
75
- this.#db = (event.target as IDBOpenDBRequest).result
76
- resolve()
77
- }
78
- })
79
- }
80
-
81
- #getDB(): IDBDatabase {
82
- if (!this.#db) {
83
- throw new Error('Database not initialized. Call init() first.')
84
- }
85
- return this.#db
86
- }
87
-
88
- /**
89
- * Fixes a Safari bug where IndexedDB requests get lost and never resolve - invoke before you use IndexedDB
90
- * @link Credits and more info: https://github.com/jakearchibald/safari-14-idb-fix
91
- */
92
- async #safariFix(): Promise<void> {
93
- // No point putting other browsers or older versions of Safari through this mess.
94
- if (!isSafari() || !this.#options.indexedDB?.databases) return Promise.resolve()
95
-
96
- let intervalId: ReturnType<typeof setInterval>
97
-
98
- return new Promise<void>((resolve: () => void) => {
99
- const tryIdb = (): Promise<IDBDatabaseInfo[]> | undefined =>
100
- this.#options.indexedDB?.databases().finally(resolve)
101
- intervalId = setInterval(() => {
102
- void tryIdb()
103
- }, 100)
104
- void tryIdb()
105
- }).finally(() => clearInterval(intervalId))
106
- }
107
-
108
- /**
109
- * Inserts or updates an array of items in a single transaction.
110
- * @param data The array of items to insert.
111
- */
112
- bulkInsert(data: Item[]): Promise<void> {
113
- return new Promise((resolve, reject) => {
114
- try {
115
- const transaction = this.#getDB().transaction(this.#storeName, 'readwrite', {
116
- durability: 'relaxed'
117
- })
118
- const store = transaction.objectStore(this.#storeName)
119
-
120
- transaction.onerror = (): any => {
121
- reject(`Transaction error: ${transaction.error}`)
122
- }
123
- transaction.oncomplete = (): any => {
124
- resolve()
125
- }
126
-
127
- data.forEach((item) => store.put(item))
128
- } catch (error) {
129
- reject(error)
130
- }
131
- })
132
- }
133
-
134
- /**
135
- * Retrieves an array of items from the object store based on their IDs.
136
- * @param ids The array of IDs to retrieve.
137
- */
138
- bulkGet(ids: string[]): Promise<(Item | undefined)[]> {
139
- return new Promise((resolve, reject) => {
140
- if (ids.length === 0) {
141
- return resolve([])
142
- }
143
- try {
144
- const transaction = this.#getDB().transaction(this.#storeName, 'readonly', {
145
- durability: 'relaxed'
146
- })
147
- const store = transaction.objectStore(this.#storeName)
148
- const promises: Promise<Item | undefined>[] = []
149
-
150
- for (const id of ids) {
151
- promises.push(
152
- new Promise((resolveGet, rejectGet) => {
153
- const request = store.get(id)
154
- request.onerror = (): void =>
155
- rejectGet(`Request error for id ${id}: ${request.error}`)
156
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
157
- request.onsuccess = (): void => resolveGet(request.result)
158
- })
159
- )
160
- }
161
-
162
- Promise.all(promises)
163
- .then((results) => {
164
- resolve(results)
165
- })
166
- .catch(reject)
167
- } catch (error) {
168
- reject(error)
169
- }
170
- })
171
- }
172
-
173
- /**
174
- * Retrieves all items from the object store.
175
- */
176
- getAll(): Promise<Item[]> {
177
- return new Promise((resolve, reject) => {
178
- try {
179
- const transaction = this.#getDB().transaction(this.#storeName, 'readonly')
180
- const store = transaction.objectStore(this.#storeName)
181
- const request = store.getAll()
182
-
183
- request.onerror = (): any => reject(`Request error: ${request.error}`)
184
- request.onsuccess = (): any => resolve(request.result)
185
- } catch (error) {
186
- reject(error)
187
- }
188
- })
189
- }
190
-
191
- close(): void {
192
- if (!this.#db) return
193
- this.#db.close()
194
- this.#db = undefined
195
- }
196
- }
@@ -1,58 +0,0 @@
1
- import Queue from './queue.js'
2
-
3
- export default class BatchedPool<T> implements Queue<T> {
4
- #queue: T[] = []
5
- #concurrencyAndSizes: number[]
6
- #processFunction: (batch: T[]) => Promise<void>
7
-
8
- #baseInterval: number
9
-
10
- #processingLoop: Promise<void>
11
- #disposed = false
12
-
13
- constructor(params: {
14
- concurrencyAndSizes: number[]
15
- maxWaitTime?: number
16
- processFunction: (batch: T[]) => Promise<void>
17
- }) {
18
- this.#concurrencyAndSizes = params.concurrencyAndSizes
19
- this.#baseInterval = Math.min(params.maxWaitTime ?? 200, 200) // Initial batch time (ms)
20
- this.#processFunction = params.processFunction
21
- this.#processingLoop = this.#loop()
22
- }
23
-
24
- add(item: T): void {
25
- this.#queue.push(item)
26
- }
27
-
28
- getBatch(batchSize: number): T[] {
29
- return this.#queue.splice(0, Math.min(batchSize, this.#queue.length))
30
- }
31
-
32
- async #runWorker(batchSize: number): Promise<void> {
33
- while (!this.#disposed || this.#queue.length > 0) {
34
- if (this.#queue.length > 0) {
35
- const batch = this.getBatch(batchSize)
36
- await this.#processFunction(batch)
37
- }
38
- await this.#delay(this.#baseInterval)
39
- }
40
- }
41
-
42
- async disposeAsync(): Promise<void> {
43
- this.#disposed = true
44
- await this.#processingLoop
45
- }
46
-
47
- async #loop(): Promise<void> {
48
- // Initialize workers
49
- const workers = Array.from(this.#concurrencyAndSizes, (batchSize: number) =>
50
- this.#runWorker(batchSize)
51
- )
52
- await Promise.all(workers)
53
- }
54
-
55
- #delay(ms: number): Promise<void> {
56
- return new Promise((resolve) => setTimeout(resolve, ms))
57
- }
58
- }