@effect/platform-browser 4.0.0-beta.6 → 4.0.0-beta.60

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