@effect/platform-browser 4.0.0-beta.8 → 4.0.0-beta.81

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