@effect/platform-browser 4.0.0-beta.7 → 4.0.0-beta.70

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 (91) hide show
  1. package/dist/BrowserCrypto.d.ts +23 -0
  2. package/dist/BrowserCrypto.d.ts.map +1 -0
  3. package/dist/BrowserCrypto.js +61 -0
  4. package/dist/BrowserCrypto.js.map +1 -0
  5. package/dist/BrowserHttpClient.d.ts +32 -16
  6. package/dist/BrowserHttpClient.d.ts.map +1 -1
  7. package/dist/BrowserHttpClient.js +66 -18
  8. package/dist/BrowserHttpClient.js.map +1 -1
  9. package/dist/BrowserKeyValueStore.d.ts +17 -14
  10. package/dist/BrowserKeyValueStore.d.ts.map +1 -1
  11. package/dist/BrowserKeyValueStore.js +130 -10
  12. package/dist/BrowserKeyValueStore.js.map +1 -1
  13. package/dist/BrowserPersistence.d.ts +21 -0
  14. package/dist/BrowserPersistence.d.ts.map +1 -0
  15. package/dist/BrowserPersistence.js +188 -0
  16. package/dist/BrowserPersistence.js.map +1 -0
  17. package/dist/BrowserRuntime.d.ts +31 -4
  18. package/dist/BrowserRuntime.d.ts.map +1 -1
  19. package/dist/BrowserRuntime.js +3 -1
  20. package/dist/BrowserRuntime.js.map +1 -1
  21. package/dist/BrowserSocket.d.ts +31 -6
  22. package/dist/BrowserSocket.d.ts.map +1 -1
  23. package/dist/BrowserSocket.js +31 -6
  24. package/dist/BrowserSocket.js.map +1 -1
  25. package/dist/BrowserStream.d.ts +33 -5
  26. package/dist/BrowserStream.d.ts.map +1 -1
  27. package/dist/BrowserStream.js +33 -5
  28. package/dist/BrowserStream.js.map +1 -1
  29. package/dist/BrowserWorker.d.ts +8 -4
  30. package/dist/BrowserWorker.d.ts.map +1 -1
  31. package/dist/BrowserWorker.js +30 -6
  32. package/dist/BrowserWorker.js.map +1 -1
  33. package/dist/BrowserWorkerRunner.d.ts +12 -6
  34. package/dist/BrowserWorkerRunner.d.ts.map +1 -1
  35. package/dist/BrowserWorkerRunner.js +34 -10
  36. package/dist/BrowserWorkerRunner.js.map +1 -1
  37. package/dist/Clipboard.d.ts +40 -13
  38. package/dist/Clipboard.d.ts.map +1 -1
  39. package/dist/Clipboard.js +33 -11
  40. package/dist/Clipboard.js.map +1 -1
  41. package/dist/Geolocation.d.ts +58 -24
  42. package/dist/Geolocation.d.ts.map +1 -1
  43. package/dist/Geolocation.js +46 -16
  44. package/dist/Geolocation.js.map +1 -1
  45. package/dist/IndexedDb.d.ts +77 -0
  46. package/dist/IndexedDb.d.ts.map +1 -0
  47. package/dist/IndexedDb.js +87 -0
  48. package/dist/IndexedDb.js.map +1 -0
  49. package/dist/IndexedDbDatabase.d.ts +150 -0
  50. package/dist/IndexedDbDatabase.d.ts.map +1 -0
  51. package/dist/IndexedDbDatabase.js +324 -0
  52. package/dist/IndexedDbDatabase.js.map +1 -0
  53. package/dist/IndexedDbQueryBuilder.d.ts +430 -0
  54. package/dist/IndexedDbQueryBuilder.d.ts.map +1 -0
  55. package/dist/IndexedDbQueryBuilder.js +927 -0
  56. package/dist/IndexedDbQueryBuilder.js.map +1 -0
  57. package/dist/IndexedDbTable.d.ts +153 -0
  58. package/dist/IndexedDbTable.d.ts.map +1 -0
  59. package/dist/IndexedDbTable.js +58 -0
  60. package/dist/IndexedDbTable.js.map +1 -0
  61. package/dist/IndexedDbVersion.d.ts +80 -0
  62. package/dist/IndexedDbVersion.d.ts.map +1 -0
  63. package/dist/IndexedDbVersion.js +25 -0
  64. package/dist/IndexedDbVersion.js.map +1 -0
  65. package/dist/Permissions.d.ts +45 -15
  66. package/dist/Permissions.d.ts.map +1 -1
  67. package/dist/Permissions.js +35 -10
  68. package/dist/Permissions.js.map +1 -1
  69. package/dist/index.d.ts +357 -10
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +357 -10
  72. package/dist/index.js.map +1 -1
  73. package/package.json +4 -3
  74. package/src/BrowserCrypto.ts +71 -0
  75. package/src/BrowserHttpClient.ts +76 -24
  76. package/src/BrowserKeyValueStore.ts +146 -12
  77. package/src/BrowserPersistence.ts +319 -0
  78. package/src/BrowserRuntime.ts +31 -4
  79. package/src/BrowserSocket.ts +31 -6
  80. package/src/BrowserStream.ts +33 -5
  81. package/src/BrowserWorker.ts +30 -6
  82. package/src/BrowserWorkerRunner.ts +34 -10
  83. package/src/Clipboard.ts +37 -13
  84. package/src/Geolocation.ts +54 -20
  85. package/src/IndexedDb.ts +115 -0
  86. package/src/IndexedDbDatabase.ts +645 -0
  87. package/src/IndexedDbQueryBuilder.ts +2040 -0
  88. package/src/IndexedDbTable.ts +247 -0
  89. package/src/IndexedDbVersion.ts +119 -0
  90. package/src/Permissions.ts +40 -13
  91. package/src/index.ts +364 -10
@@ -0,0 +1,927 @@
1
+ import * as Cause from "effect/Cause";
2
+ import * as Context from "effect/Context";
3
+ import * as Data from "effect/Data";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Effectable from "effect/Effectable";
6
+ import * as Fiber from "effect/Fiber";
7
+ import { BaseProto } from "effect/Inspectable";
8
+ import * as Option from "effect/Option";
9
+ import * as Pipeable from "effect/Pipeable";
10
+ import * as References from "effect/References";
11
+ import * as Schema from "effect/Schema";
12
+ import * as SchemaIssue from "effect/SchemaIssue";
13
+ import * as SchemaParser from "effect/SchemaParser";
14
+ import * as Stream from "effect/Stream";
15
+ import * as Utils from "effect/Utils";
16
+ const ErrorTypeId = "~@effect/platform-browser/IndexedDbQueryBuilder/IndexedDbQueryError";
17
+ const CommonProto = {
18
+ [Symbol.iterator]() {
19
+ return new Utils.SingleShotGen(this);
20
+ },
21
+ ...Pipeable.Prototype,
22
+ ...BaseProto,
23
+ toJSON() {
24
+ return {
25
+ _id: "IndexedDbQueryBuilder"
26
+ };
27
+ }
28
+ };
29
+ /**
30
+ * Tagged error for IndexedDB query operations, carrying a query error reason and the original cause.
31
+ *
32
+ * @category errors
33
+ * @since 4.0.0
34
+ */
35
+ export class IndexedDbQueryError extends /*#__PURE__*/Data.TaggedError("IndexedDbQueryError") {
36
+ /**
37
+ * Marks this value as an IndexedDB query builder error for runtime guards.
38
+ *
39
+ * @since 4.0.0
40
+ */
41
+ [ErrorTypeId] = ErrorTypeId;
42
+ message = this.reason;
43
+ }
44
+ /**
45
+ * Service tag for the active `IDBTransaction` used to share a transaction across IndexedDB query effects.
46
+ *
47
+ * @category models
48
+ * @since 4.0.0
49
+ */
50
+ export class IndexedDbTransaction extends /*#__PURE__*/Context.Service()("@effect/platform-browser/IndexedDbQueryBuilder/IndexedDbTransaction") {}
51
+ const applyDelete = query => Effect.callback(resume => {
52
+ const database = query.delete.from.database;
53
+ const IDBKeyRange = query.delete.from.IDBKeyRange;
54
+ const transaction = getOrCreateTransaction(database.current, [query.delete.from.table.tableName], "readwrite", {
55
+ durability: query.delete.from.table.durability
56
+ });
57
+ const objectStore = transaction.objectStore(query.delete.from.table.tableName);
58
+ const predicate = query.predicate;
59
+ let keyRange = undefined;
60
+ if (query.only !== undefined) {
61
+ keyRange = IDBKeyRange.only(query.only);
62
+ } else if (query.lowerBound !== undefined && query.upperBound !== undefined) {
63
+ keyRange = IDBKeyRange.bound(query.lowerBound, query.upperBound, query.excludeLowerBound, query.excludeUpperBound);
64
+ } else if (query.lowerBound !== undefined) {
65
+ keyRange = IDBKeyRange.lowerBound(query.lowerBound, query.excludeLowerBound);
66
+ } else if (query.upperBound !== undefined) {
67
+ keyRange = IDBKeyRange.upperBound(query.upperBound, query.excludeUpperBound);
68
+ }
69
+ let request;
70
+ if (query.limitValue !== undefined || predicate) {
71
+ const cursorRequest = objectStore.openCursor();
72
+ let count = 0;
73
+ cursorRequest.onerror = () => {
74
+ resume(Effect.fail(new IndexedDbQueryError({
75
+ reason: "TransactionError",
76
+ cause: cursorRequest.error
77
+ })));
78
+ };
79
+ cursorRequest.onsuccess = () => {
80
+ const cursor = cursorRequest.result;
81
+ if (cursor === null) {
82
+ return resume(Effect.void);
83
+ }
84
+ if (predicate === undefined || predicate(cursor.value)) {
85
+ const deleteRequest = cursor.delete();
86
+ deleteRequest.onerror = () => {
87
+ resume(Effect.fail(new IndexedDbQueryError({
88
+ reason: "TransactionError",
89
+ cause: deleteRequest.error
90
+ })));
91
+ };
92
+ count += 1;
93
+ }
94
+ if (query.limitValue === undefined || count < query.limitValue) {
95
+ return cursor.continue();
96
+ }
97
+ resume(Effect.void);
98
+ };
99
+ } else if (keyRange !== undefined) {
100
+ request = objectStore.delete(keyRange);
101
+ request.onerror = event => {
102
+ resume(Effect.fail(new IndexedDbQueryError({
103
+ reason: "TransactionError",
104
+ cause: event
105
+ })));
106
+ };
107
+ request.onsuccess = () => {
108
+ resume(Effect.succeed(request.result));
109
+ };
110
+ } else {
111
+ resume(Effect.die(new Error("No key range provided for delete operation")));
112
+ }
113
+ });
114
+ const getReadonlyObjectStore = query => {
115
+ const database = query.from.database;
116
+ const IDBKeyRange = query.from.IDBKeyRange;
117
+ const transaction = getOrCreateTransaction(database.current, [query.from.table.tableName], "readonly", {
118
+ durability: query.from.table.durability
119
+ });
120
+ const objectStore = transaction.objectStore(query.from.table.tableName);
121
+ let keyRange = undefined;
122
+ let store;
123
+ if (query.only !== undefined) {
124
+ keyRange = IDBKeyRange.only(query.only);
125
+ } else if (query.lowerBound !== undefined && query.upperBound !== undefined) {
126
+ keyRange = IDBKeyRange.bound(query.lowerBound, query.upperBound, query.excludeLowerBound, query.excludeUpperBound);
127
+ } else if (query.lowerBound !== undefined) {
128
+ keyRange = IDBKeyRange.lowerBound(query.lowerBound, query.excludeLowerBound);
129
+ } else if (query.upperBound !== undefined) {
130
+ keyRange = IDBKeyRange.upperBound(query.upperBound, query.excludeUpperBound);
131
+ }
132
+ if (query.index !== undefined) {
133
+ store = objectStore.index(query.index);
134
+ } else {
135
+ store = objectStore;
136
+ }
137
+ return {
138
+ store,
139
+ keyRange
140
+ };
141
+ };
142
+ const applySelect = /*#__PURE__*/Effect.fnUntraced(function* (query) {
143
+ const keyPath = query.from.table.keyPath;
144
+ const predicate = query.predicate;
145
+ const data = predicate || keyPath === undefined || query.offsetValue !== undefined ? yield* Effect.callback(resume => {
146
+ const {
147
+ keyRange,
148
+ store
149
+ } = getReadonlyObjectStore(query);
150
+ const cursorRequest = store.openCursor(keyRange, query.reverseValue ? "prev" : "next");
151
+ const results = [];
152
+ let count = 0;
153
+ let offsetApplied = false;
154
+ cursorRequest.onerror = () => {
155
+ resume(Effect.fail(new IndexedDbQueryError({
156
+ reason: "TransactionError",
157
+ cause: cursorRequest.error
158
+ })));
159
+ };
160
+ cursorRequest.onsuccess = () => {
161
+ const cursor = cursorRequest.result;
162
+ if (cursor === null) {
163
+ return resume(Effect.succeed(results));
164
+ }
165
+ if (query.offsetValue && !offsetApplied) {
166
+ offsetApplied = true;
167
+ return cursor.advance(query.offsetValue);
168
+ }
169
+ if (predicate === undefined || predicate(cursor.value)) {
170
+ results.push(keyPath === undefined ? {
171
+ ...cursor.value,
172
+ key: cursor.key
173
+ } : cursor.value);
174
+ count += 1;
175
+ }
176
+ if (query.limitValue === undefined || count < query.limitValue) {
177
+ return cursor.continue();
178
+ }
179
+ resume(Effect.succeed(results));
180
+ };
181
+ }) : yield* Effect.callback(resume => {
182
+ const {
183
+ keyRange,
184
+ store
185
+ } = getReadonlyObjectStore(query);
186
+ const request = store.getAll(keyRange, query.limitValue);
187
+ request.onerror = event => {
188
+ resume(Effect.fail(new IndexedDbQueryError({
189
+ reason: "TransactionError",
190
+ cause: event
191
+ })));
192
+ };
193
+ request.onsuccess = () => {
194
+ if (query.reverseValue) {
195
+ request.result.reverse();
196
+ }
197
+ resume(Effect.succeed(request.result));
198
+ };
199
+ });
200
+ const tableSchema = query.from.table.arraySchema;
201
+ return yield* Schema.decodeUnknownEffect(tableSchema)(data).pipe(Effect.mapError(error => new IndexedDbQueryError({
202
+ reason: "DecodeError",
203
+ cause: error
204
+ })));
205
+ });
206
+ const applyFirst = /*#__PURE__*/Effect.fnUntraced(function* (query) {
207
+ const keyPath = query.select.from.table.keyPath;
208
+ const data = yield* Effect.callback(resume => {
209
+ const {
210
+ keyRange,
211
+ store
212
+ } = getReadonlyObjectStore(query.select);
213
+ if (keyRange !== undefined) {
214
+ const request = store.get(keyRange);
215
+ request.onerror = event => {
216
+ resume(Effect.fail(new IndexedDbQueryError({
217
+ reason: "TransactionError",
218
+ cause: event
219
+ })));
220
+ };
221
+ request.onsuccess = () => {
222
+ resume(Effect.succeed(request.result));
223
+ };
224
+ } else {
225
+ const request = store.openCursor();
226
+ request.onerror = event => {
227
+ resume(Effect.fail(new IndexedDbQueryError({
228
+ reason: "TransactionError",
229
+ cause: event
230
+ })));
231
+ };
232
+ request.onsuccess = () => {
233
+ const value = request.result?.value;
234
+ const key = request.result?.key;
235
+ if (value === undefined) {
236
+ resume(Effect.fail(new Cause.NoSuchElementError(`No such element in table ${query.select.from.table.tableName}`)));
237
+ } else {
238
+ resume(Effect.succeed(keyPath === undefined ? {
239
+ ...value,
240
+ key
241
+ } : value));
242
+ }
243
+ };
244
+ }
245
+ });
246
+ return yield* Schema.decodeUnknownEffect(query.select.from.table.readSchema)(data).pipe(Effect.mapError(error => new IndexedDbQueryError({
247
+ reason: "DecodeError",
248
+ cause: error
249
+ })));
250
+ });
251
+ const applyModify = /*#__PURE__*/Effect.fnUntraced(function* ({
252
+ query,
253
+ value
254
+ }) {
255
+ const autoIncrement = query.from.table.autoIncrement;
256
+ const keyPath = query.from.table.keyPath;
257
+ const table = query.from.table;
258
+ const schema = autoIncrement && value[keyPath] === undefined ? table.autoincrementSchema : table.tableSchema;
259
+ const encodedValue = yield* schema.makeEffect(value).pipe(Effect.flatMap(Schema.encodeUnknownEffect(schema)), Effect.mapError(error => new IndexedDbQueryError({
260
+ reason: "EncodeError",
261
+ cause: error
262
+ })));
263
+ return yield* Effect.callback(resume => {
264
+ const database = query.from.database;
265
+ const transaction = getOrCreateTransaction(database.current, [query.from.table.tableName], "readwrite", {
266
+ durability: query.from.table.durability
267
+ });
268
+ const objectStore = transaction.objectStore(query.from.table.tableName);
269
+ let request;
270
+ if (query.operation === "add") {
271
+ request = objectStore.add(encodedValue, keyPath === undefined ? value["key"] : undefined);
272
+ } else if (query.operation === "put") {
273
+ request = objectStore.put(encodedValue, keyPath === undefined ? value["key"] : undefined);
274
+ } else {
275
+ return resume(Effect.die(new Error("Invalid modify operation")));
276
+ }
277
+ request.onerror = event => {
278
+ resume(Effect.fail(new IndexedDbQueryError({
279
+ reason: "TransactionError",
280
+ cause: event
281
+ })));
282
+ };
283
+ request.onsuccess = () => {
284
+ resume(Effect.succeed(request.result));
285
+ };
286
+ });
287
+ });
288
+ const applyModifyAll = /*#__PURE__*/Effect.fnUntraced(function* ({
289
+ query,
290
+ values
291
+ }) {
292
+ const autoIncrement = query.from.table.autoIncrement;
293
+ const keyPath = query.from.table.keyPath;
294
+ const schema = query.from.table.tableSchema;
295
+ const encodedValues = new Array(values.length);
296
+ const makeValue = SchemaParser.makeEffect(schema);
297
+ const encodeValue = SchemaParser.encodeUnknownEffect(schema);
298
+ const makeValueAutoincrement = SchemaParser.makeEffect(query.from.table.autoincrementSchema);
299
+ const encodeValueAutoincrement = SchemaParser.encodeUnknownEffect(query.from.table.autoincrementSchema);
300
+ for (let i = 0; i < values.length; i++) {
301
+ const value = values[i];
302
+ if (autoIncrement && value[keyPath] === undefined) {
303
+ encodedValues[i] = yield* encodeValueAutoincrement(yield* makeValueAutoincrement(value));
304
+ } else {
305
+ encodedValues[i] = yield* encodeValue(yield* makeValue(value));
306
+ }
307
+ }
308
+ return yield* Effect.callback(resume => {
309
+ if (encodedValues.length === 0) {
310
+ return resume(Effect.succeed([]));
311
+ }
312
+ const database = query.from.database;
313
+ const transaction = getOrCreateTransaction(database.current, [query.from.table.tableName], "readwrite", {
314
+ durability: query.from.table.durability
315
+ });
316
+ const objectStore = transaction.objectStore(query.from.table.tableName);
317
+ const results = new Array(encodedValues.length);
318
+ let remaining = encodedValues.length;
319
+ if (query.operation === "add") {
320
+ for (let i = 0; i < encodedValues.length; i++) {
321
+ const request = objectStore.add(encodedValues[i], keyPath === undefined ? values[i]["key"] : undefined);
322
+ request.onerror = () => {
323
+ resume(Effect.fail(new IndexedDbQueryError({
324
+ reason: "TransactionError",
325
+ cause: request.error
326
+ })));
327
+ };
328
+ request.onsuccess = () => {
329
+ results[i] = request.result;
330
+ remaining -= 1;
331
+ if (remaining === 0) {
332
+ resume(Effect.succeed(results));
333
+ }
334
+ };
335
+ }
336
+ } else if (query.operation === "put") {
337
+ for (let i = 0; i < encodedValues.length; i++) {
338
+ const request = objectStore.put(encodedValues[i], keyPath === undefined ? values[i]["key"] : undefined);
339
+ request.onerror = () => {
340
+ resume(Effect.fail(new IndexedDbQueryError({
341
+ reason: "TransactionError",
342
+ cause: request.error
343
+ })));
344
+ };
345
+ request.onsuccess = () => {
346
+ results[i] = request.result;
347
+ remaining -= 1;
348
+ if (remaining === 0) {
349
+ resume(Effect.succeed(results));
350
+ }
351
+ };
352
+ }
353
+ } else {
354
+ return resume(Effect.die(new Error("Invalid modify all operation")));
355
+ }
356
+ objectStore.transaction.onerror = () => {
357
+ resume(Effect.fail(new IndexedDbQueryError({
358
+ reason: "TransactionError",
359
+ cause: objectStore.transaction.error
360
+ })));
361
+ };
362
+ });
363
+ }, /*#__PURE__*/Effect.catchIf(SchemaIssue.isIssue, issue => Effect.fail(new IndexedDbQueryError({
364
+ reason: "EncodeError",
365
+ cause: new Schema.SchemaError(issue)
366
+ }))));
367
+ const applyClear = options => Effect.callback(resume => {
368
+ const database = options.database;
369
+ const transaction = getOrCreateTransaction(database, [options.table.tableName], "readwrite", {
370
+ durability: options.table.durability
371
+ });
372
+ const objectStore = transaction.objectStore(options.table.tableName);
373
+ const request = objectStore.clear();
374
+ request.onerror = event => {
375
+ resume(Effect.fail(new IndexedDbQueryError({
376
+ reason: "TransactionError",
377
+ cause: event
378
+ })));
379
+ };
380
+ request.onsuccess = () => {
381
+ resume(Effect.void);
382
+ };
383
+ });
384
+ const applyClearAll = options => Effect.callback(resume => {
385
+ const database = options.database;
386
+ const tables = database.objectStoreNames;
387
+ const transaction = getOrCreateTransaction(database, [...tables], "readwrite");
388
+ for (let t = 0; t < tables.length; t++) {
389
+ const objectStore = transaction.objectStore(tables[t]);
390
+ const request = objectStore.clear();
391
+ request.onerror = () => {
392
+ resume(Effect.fail(new IndexedDbQueryError({
393
+ reason: "TransactionError",
394
+ cause: request.error
395
+ })));
396
+ };
397
+ }
398
+ transaction.onerror = () => {
399
+ resume(Effect.fail(new IndexedDbQueryError({
400
+ reason: "TransactionError",
401
+ cause: transaction.error
402
+ })));
403
+ };
404
+ transaction.oncomplete = () => {
405
+ resume(Effect.void);
406
+ };
407
+ });
408
+ const getCount = query => Effect.callback(resume => {
409
+ const {
410
+ keyRange,
411
+ store
412
+ } = getReadonlyObjectStore(query);
413
+ const request = store.count(keyRange);
414
+ request.onerror = event => {
415
+ resume(Effect.fail(new IndexedDbQueryError({
416
+ reason: "TransactionError",
417
+ cause: event
418
+ })));
419
+ };
420
+ request.onsuccess = () => {
421
+ resume(Effect.succeed(request.result));
422
+ };
423
+ });
424
+ const FromProto = {
425
+ ...CommonProto,
426
+ select(index) {
427
+ let select = this.selectCache.get(index);
428
+ if (select === undefined) {
429
+ select = makeSelect({
430
+ from: this,
431
+ index
432
+ });
433
+ this.selectCache.set(index, select);
434
+ }
435
+ return select;
436
+ },
437
+ count(index) {
438
+ let count = this.countCache.get(index);
439
+ if (count === undefined) {
440
+ count = makeCount({
441
+ from: this,
442
+ index
443
+ });
444
+ this.countCache.set(index, count);
445
+ }
446
+ return count;
447
+ },
448
+ delete(index) {
449
+ let cached = this.deleteCache.get(index);
450
+ if (cached === undefined) {
451
+ cached = makeDeletePartial({
452
+ from: this,
453
+ index
454
+ });
455
+ this.deleteCache.set(index, cached);
456
+ }
457
+ return cached;
458
+ },
459
+ insert(value) {
460
+ return makeModify({
461
+ from: this,
462
+ value,
463
+ operation: "add"
464
+ });
465
+ },
466
+ upsert(value) {
467
+ return makeModify({
468
+ from: this,
469
+ value,
470
+ operation: "put"
471
+ });
472
+ },
473
+ insertAll(values) {
474
+ return makeModifyAll({
475
+ from: this,
476
+ values,
477
+ operation: "add"
478
+ });
479
+ },
480
+ upsertAll(values) {
481
+ return makeModifyAll({
482
+ from: this,
483
+ values,
484
+ operation: "put"
485
+ });
486
+ },
487
+ get clear() {
488
+ const self = this;
489
+ return applyClear({
490
+ database: self.database.current,
491
+ table: self.table
492
+ });
493
+ }
494
+ };
495
+ const makeFrom = options => {
496
+ const self = Object.create(FromProto);
497
+ self.table = options.table;
498
+ self.database = options.database;
499
+ self.IDBKeyRange = options.IDBKeyRange;
500
+ self.reactivity = options.reactivity;
501
+ self.selectCache = new Map();
502
+ self.countCache = new Map();
503
+ self.deleteCache = new Map();
504
+ return self;
505
+ };
506
+ const DeletePartialProto = {
507
+ ...CommonProto,
508
+ limit(limit) {
509
+ return makeDelete({
510
+ delete: this,
511
+ limitValue: limit
512
+ });
513
+ },
514
+ equals(value) {
515
+ return makeDelete({
516
+ delete: this,
517
+ only: value
518
+ });
519
+ },
520
+ gte(value) {
521
+ return makeDelete({
522
+ delete: this,
523
+ lowerBound: value,
524
+ excludeLowerBound: false
525
+ });
526
+ },
527
+ lte(value) {
528
+ return makeDelete({
529
+ delete: this,
530
+ upperBound: value,
531
+ excludeUpperBound: false
532
+ });
533
+ },
534
+ gt(value) {
535
+ return makeDelete({
536
+ delete: this,
537
+ lowerBound: value,
538
+ excludeLowerBound: true
539
+ });
540
+ },
541
+ lt(value) {
542
+ return makeDelete({
543
+ delete: this,
544
+ upperBound: value,
545
+ excludeUpperBound: true
546
+ });
547
+ },
548
+ between(lowerBound, upperBound, queryOptions) {
549
+ return makeDelete({
550
+ delete: this,
551
+ lowerBound,
552
+ upperBound,
553
+ excludeLowerBound: queryOptions?.excludeLowerBound ?? false,
554
+ excludeUpperBound: queryOptions?.excludeUpperBound ?? false
555
+ });
556
+ }
557
+ };
558
+ const makeDeletePartial = options => {
559
+ const self = Object.create(DeletePartialProto);
560
+ self.from = options.from;
561
+ self.index = options.index;
562
+ return self;
563
+ };
564
+ const DeleteProto = {
565
+ ...CommonProto,
566
+ ... /*#__PURE__*/Effectable.Prototype({
567
+ label: "IndexedDbQuery.Delete",
568
+ evaluate() {
569
+ return applyDelete(this);
570
+ }
571
+ }),
572
+ limit(limit) {
573
+ return makeDelete({
574
+ ...this,
575
+ limitValue: limit
576
+ });
577
+ },
578
+ filter(filter) {
579
+ const prev = this.predicate;
580
+ return makeDelete({
581
+ delete: this.delete,
582
+ predicate: prev ? item => prev(item) && filter(item) : filter
583
+ });
584
+ },
585
+ invalidate(keys) {
586
+ keys ??= this.only !== undefined ? {
587
+ [this.delete.from.table.tableName]: [this.only]
588
+ } : [this.delete.from.table.tableName];
589
+ return this.delete.from.reactivity.mutation(keys, this);
590
+ }
591
+ };
592
+ const makeDelete = options => {
593
+ const self = Object.create(DeleteProto);
594
+ self.delete = options.delete;
595
+ self.limitValue = options.limitValue;
596
+ self.only = options.only;
597
+ self.lowerBound = options.lowerBound;
598
+ self.upperBound = options.upperBound;
599
+ self.excludeLowerBound = options.excludeLowerBound ?? false;
600
+ self.excludeUpperBound = options.excludeUpperBound ?? false;
601
+ self.predicate = options.predicate;
602
+ return self;
603
+ };
604
+ const CountProto = {
605
+ ...CommonProto,
606
+ ... /*#__PURE__*/Effectable.Prototype({
607
+ label: "IndexedDbQuery.Count",
608
+ evaluate() {
609
+ return getCount(this);
610
+ }
611
+ }),
612
+ equals(value) {
613
+ return makeCount({
614
+ from: this.from,
615
+ index: this.index,
616
+ only: value
617
+ });
618
+ },
619
+ gte(value) {
620
+ return makeCount({
621
+ from: this.from,
622
+ index: this.index,
623
+ lowerBound: value,
624
+ excludeLowerBound: false
625
+ });
626
+ },
627
+ lte(value) {
628
+ return makeCount({
629
+ from: this.from,
630
+ index: this.index,
631
+ upperBound: value,
632
+ excludeUpperBound: false
633
+ });
634
+ },
635
+ gt(value) {
636
+ return makeCount({
637
+ from: this.from,
638
+ index: this.index,
639
+ lowerBound: value,
640
+ excludeLowerBound: true
641
+ });
642
+ },
643
+ lt(value) {
644
+ return makeCount({
645
+ from: this.from,
646
+ index: this.index,
647
+ upperBound: value,
648
+ excludeUpperBound: true
649
+ });
650
+ },
651
+ between(lowerBound, upperBound, queryOptions) {
652
+ return makeCount({
653
+ from: this.from,
654
+ index: this.index,
655
+ lowerBound,
656
+ upperBound,
657
+ excludeLowerBound: queryOptions?.excludeLowerBound ?? false,
658
+ excludeUpperBound: queryOptions?.excludeUpperBound ?? false
659
+ });
660
+ }
661
+ };
662
+ const makeCount = options => {
663
+ const self = Object.create(CountProto);
664
+ self.from = options.from;
665
+ self.index = options.index;
666
+ self.only = options.only;
667
+ self.lowerBound = options.lowerBound;
668
+ self.upperBound = options.upperBound;
669
+ self.excludeLowerBound = options.excludeLowerBound;
670
+ self.excludeUpperBound = options.excludeUpperBound;
671
+ return self;
672
+ };
673
+ const SelectProto = {
674
+ ...CommonProto,
675
+ ... /*#__PURE__*/Effectable.Prototype({
676
+ label: "IndexedDbQuery.Select",
677
+ evaluate() {
678
+ return applySelect(this);
679
+ }
680
+ }),
681
+ limit(limit) {
682
+ return makeSelect({
683
+ ...this,
684
+ limitValue: limit
685
+ });
686
+ },
687
+ offset(offset) {
688
+ return makeSelect({
689
+ ...this,
690
+ offsetValue: offset
691
+ });
692
+ },
693
+ equals(value) {
694
+ return makeSelect({
695
+ ...this,
696
+ only: value
697
+ });
698
+ },
699
+ gte(value) {
700
+ return makeSelect({
701
+ ...this,
702
+ lowerBound: value,
703
+ excludeLowerBound: false
704
+ });
705
+ },
706
+ lte(value) {
707
+ return makeSelect({
708
+ ...this,
709
+ upperBound: value,
710
+ excludeUpperBound: false
711
+ });
712
+ },
713
+ gt(value) {
714
+ return makeSelect({
715
+ ...this,
716
+ lowerBound: value,
717
+ excludeLowerBound: true
718
+ });
719
+ },
720
+ lt(value) {
721
+ return makeSelect({
722
+ ...this,
723
+ upperBound: value,
724
+ excludeUpperBound: true
725
+ });
726
+ },
727
+ between(lowerBound, upperBound, queryOptions) {
728
+ return makeSelect({
729
+ ...this,
730
+ lowerBound,
731
+ upperBound,
732
+ excludeLowerBound: queryOptions?.excludeLowerBound ?? false,
733
+ excludeUpperBound: queryOptions?.excludeUpperBound ?? false
734
+ });
735
+ },
736
+ reverse() {
737
+ return makeSelect({
738
+ ...this,
739
+ reverseValue: true
740
+ });
741
+ },
742
+ first() {
743
+ return makeFirst({
744
+ select: this
745
+ });
746
+ },
747
+ filter(filter) {
748
+ const prev = this.predicate;
749
+ return makeSelect({
750
+ ...this,
751
+ predicate: prev ? item => prev(item) && filter(item) : filter
752
+ });
753
+ },
754
+ stream(options) {
755
+ const limit = this.limitValue;
756
+ const chunkSize = Math.min(options?.chunkSize ?? 100, limit ?? Number.MAX_SAFE_INTEGER);
757
+ const initial = this.limit(chunkSize);
758
+ return Stream.suspend(() => {
759
+ let total = 0;
760
+ return Stream.paginate(initial, select => Effect.map(applySelect(select), data => {
761
+ total += data.length;
762
+ select.offsetValue = total;
763
+ const reachedLimit = limit && total >= limit;
764
+ const isPartial = data.length < chunkSize;
765
+ return [data, isPartial || reachedLimit ? Option.none() : Option.some(select)];
766
+ }));
767
+ });
768
+ },
769
+ reactive(keys) {
770
+ keys ??= [this.from.table.tableName];
771
+ return this.from.reactivity.stream(keys, this);
772
+ },
773
+ reactiveQueue(keys) {
774
+ keys ??= [this.from.table.tableName];
775
+ return this.from.reactivity.query(keys, this);
776
+ }
777
+ };
778
+ const makeSelect = options => {
779
+ const self = Object.create(SelectProto);
780
+ self.from = options.from;
781
+ self.index = options.index;
782
+ self.only = options.only;
783
+ self.limitValue = options.limitValue;
784
+ self.offsetValue = options.offsetValue;
785
+ self.reverseValue = options.reverseValue;
786
+ self.lowerBound = options.lowerBound;
787
+ self.upperBound = options.upperBound;
788
+ self.excludeLowerBound = options.excludeLowerBound;
789
+ self.excludeUpperBound = options.excludeUpperBound;
790
+ self.predicate = options.predicate;
791
+ return self;
792
+ };
793
+ const FirstProto = {
794
+ ...CommonProto,
795
+ ... /*#__PURE__*/Effectable.Prototype({
796
+ label: "IndexedDbQuery.First",
797
+ evaluate() {
798
+ return applyFirst(this);
799
+ }
800
+ }),
801
+ reactive(keys) {
802
+ keys ??= this.select.only !== undefined ? [`${this.select.from.table.tableName}:${String(this.select.only)}`] : [this.select.from.table.tableName];
803
+ return this.select.from.reactivity.stream(keys, this);
804
+ },
805
+ reactiveQueue(keys) {
806
+ keys ??= this.select.only !== undefined ? [`${this.select.from.table.tableName}:${this.select.only}`] : [this.select.from.table.tableName];
807
+ return this.select.from.reactivity.query(keys, this);
808
+ }
809
+ };
810
+ const makeFirst = options => {
811
+ const self = Object.create(FirstProto);
812
+ self.select = options.select;
813
+ return self;
814
+ };
815
+ const ModifyProto = {
816
+ ...CommonProto,
817
+ ... /*#__PURE__*/Effectable.Prototype({
818
+ label: "IndexedDbQuery.Modify",
819
+ evaluate() {
820
+ return applyModify({
821
+ query: this,
822
+ value: this.value
823
+ });
824
+ }
825
+ }),
826
+ invalidate(keys) {
827
+ const keyPath = this.from.table.keyPath;
828
+ keys ??= typeof keyPath === "string" && this.value[keyPath] !== undefined ? {
829
+ [this.from.table.tableName]: [this.value[keyPath]]
830
+ } : [this.from.table.tableName];
831
+ return this.from.reactivity.mutation(keys, this);
832
+ }
833
+ };
834
+ const makeModify = options => {
835
+ const self = Object.create(ModifyProto);
836
+ self.from = options.from;
837
+ self.value = options.value;
838
+ self.operation = options.operation;
839
+ return self;
840
+ };
841
+ const ModifyAllProto = {
842
+ ...CommonProto,
843
+ ... /*#__PURE__*/Effectable.Prototype({
844
+ label: "IndexedDbQuery.ModifyAll",
845
+ evaluate() {
846
+ return applyModifyAll({
847
+ query: this,
848
+ values: this.values
849
+ });
850
+ }
851
+ }),
852
+ invalidate(keys) {
853
+ keys ??= [this.from.table.tableName];
854
+ return this.from.reactivity.mutation(keys, this);
855
+ }
856
+ };
857
+ const makeModifyAll = options => {
858
+ const self = Object.create(ModifyAllProto);
859
+ self.from = options.from;
860
+ self.values = options.values;
861
+ self.operation = options.operation;
862
+ return self;
863
+ };
864
+ const QueryBuilderProto = {
865
+ ...CommonProto,
866
+ use(f) {
867
+ return Effect.try({
868
+ try: () => f(this.database.current),
869
+ catch: error => new IndexedDbQueryError({
870
+ reason: "UnknownError",
871
+ cause: error
872
+ })
873
+ });
874
+ },
875
+ from(table) {
876
+ let cached = this.fromCache.get(table);
877
+ if (cached === undefined) {
878
+ cached = makeFrom({
879
+ database: this.database,
880
+ IDBKeyRange: this.IDBKeyRange,
881
+ table: this.tables.get(table),
882
+ reactivity: this.reactivity
883
+ });
884
+ this.fromCache.set(table, cached);
885
+ }
886
+ return cached;
887
+ },
888
+ get clearAll() {
889
+ const self = this;
890
+ return applyClearAll({
891
+ database: self.database.current
892
+ });
893
+ },
894
+ withTransaction(options) {
895
+ return effect => Effect.suspend(() => {
896
+ const transaction = this.database.current.transaction(options.tables, options.mode, options);
897
+ return Effect.provideService(effect, IndexedDbTransaction, transaction);
898
+ }).pipe(
899
+ // To prevent async gaps between transaction queries
900
+ Effect.provideService(References.PreventSchedulerYield, true));
901
+ }
902
+ };
903
+ /**
904
+ * Creates an `IndexedDbQueryBuilder` from an open database reference, key-range constructor, table map, and reactivity service.
905
+ *
906
+ * @category constructors
907
+ * @since 4.0.0
908
+ */
909
+ export const make = ({
910
+ IDBKeyRange,
911
+ database,
912
+ tables,
913
+ reactivity
914
+ }) => {
915
+ const self = Object.create(QueryBuilderProto);
916
+ self.tables = tables;
917
+ self.database = database;
918
+ self.reactivity = reactivity;
919
+ self.IDBKeyRange = IDBKeyRange;
920
+ self.fromCache = new Map();
921
+ return self;
922
+ };
923
+ const getOrCreateTransaction = (database, tables, mode, options) => {
924
+ const fiber = Fiber.getCurrent();
925
+ return Context.getOrUndefined(fiber.context, IndexedDbTransaction) ?? database.transaction(tables, mode, options);
926
+ };
927
+ //# sourceMappingURL=IndexedDbQueryBuilder.js.map