@effect/platform-browser 4.0.0-beta.43 → 4.0.0-beta.44

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 (44) hide show
  1. package/dist/BrowserHttpClient.d.ts +3 -3
  2. package/dist/BrowserHttpClient.d.ts.map +1 -1
  3. package/dist/BrowserHttpClient.js +5 -5
  4. package/dist/BrowserHttpClient.js.map +1 -1
  5. package/dist/BrowserWorkerRunner.js +1 -1
  6. package/dist/BrowserWorkerRunner.js.map +1 -1
  7. package/dist/Clipboard.d.ts +5 -2
  8. package/dist/Clipboard.d.ts.map +1 -1
  9. package/dist/Clipboard.js +2 -2
  10. package/dist/Clipboard.js.map +1 -1
  11. package/dist/Geolocation.d.ts +2 -2
  12. package/dist/Geolocation.d.ts.map +1 -1
  13. package/dist/Geolocation.js +2 -2
  14. package/dist/Geolocation.js.map +1 -1
  15. package/dist/IndexedDb.d.ts +3 -3
  16. package/dist/IndexedDb.d.ts.map +1 -1
  17. package/dist/IndexedDb.js +2 -2
  18. package/dist/IndexedDb.js.map +1 -1
  19. package/dist/IndexedDbDatabase.d.ts +8 -3
  20. package/dist/IndexedDbDatabase.d.ts.map +1 -1
  21. package/dist/IndexedDbDatabase.js +38 -16
  22. package/dist/IndexedDbDatabase.js.map +1 -1
  23. package/dist/IndexedDbQueryBuilder.d.ts +115 -57
  24. package/dist/IndexedDbQueryBuilder.d.ts.map +1 -1
  25. package/dist/IndexedDbQueryBuilder.js +114 -107
  26. package/dist/IndexedDbQueryBuilder.js.map +1 -1
  27. package/dist/IndexedDbTable.d.ts +2 -3
  28. package/dist/IndexedDbTable.d.ts.map +1 -1
  29. package/dist/IndexedDbTable.js +5 -3
  30. package/dist/IndexedDbTable.js.map +1 -1
  31. package/dist/Permissions.d.ts +5 -2
  32. package/dist/Permissions.d.ts.map +1 -1
  33. package/dist/Permissions.js +2 -2
  34. package/dist/Permissions.js.map +1 -1
  35. package/package.json +3 -3
  36. package/src/BrowserHttpClient.ts +6 -6
  37. package/src/BrowserWorkerRunner.ts +1 -1
  38. package/src/Clipboard.ts +2 -2
  39. package/src/Geolocation.ts +2 -2
  40. package/src/IndexedDb.ts +2 -2
  41. package/src/IndexedDbDatabase.ts +174 -141
  42. package/src/IndexedDbQueryBuilder.ts +322 -327
  43. package/src/IndexedDbTable.ts +8 -10
  44. package/src/Permissions.ts +2 -2
@@ -2,18 +2,23 @@
2
2
  * @since 4.0.0
3
3
  */
4
4
  import type { NonEmptyReadonlyArray } from "effect/Array"
5
+ import * as Context from "effect/Context"
5
6
  import * as Data from "effect/Data"
6
7
  import * as Effect from "effect/Effect"
8
+ import * as Fiber from "effect/Fiber"
7
9
  import type { Inspectable } from "effect/Inspectable"
8
10
  import { BaseProto } from "effect/Inspectable"
11
+ import type * as MutableRef from "effect/MutableRef"
12
+ import * as Option from "effect/Option"
9
13
  import * as Pipeable from "effect/Pipeable"
10
14
  import type * as Queue from "effect/Queue"
11
15
  import type * as Record from "effect/Record"
16
+ import * as References from "effect/References"
12
17
  import * as Schema from "effect/Schema"
13
18
  import * as SchemaIssue from "effect/SchemaIssue"
14
19
  import * as SchemaParser from "effect/SchemaParser"
15
20
  import type * as Scope from "effect/Scope"
16
- import type * as Stream from "effect/Stream"
21
+ import * as Stream from "effect/Stream"
17
22
  import type * as Reactivity from "effect/unstable/reactivity/Reactivity"
18
23
  import * as Utils from "effect/Utils"
19
24
  import type * as IndexedDb from "./IndexedDb.ts"
@@ -73,13 +78,13 @@ export interface IndexedDbQueryBuilder<
73
78
  Source extends IndexedDbVersion.AnyWithProps
74
79
  > extends Pipeable.Pipeable, Inspectable {
75
80
  readonly tables: ReadonlyMap<string, IndexedDbVersion.Tables<Source>>
76
- readonly database: globalThis.IDBDatabase
81
+ readonly database: MutableRef.MutableRef<globalThis.IDBDatabase>
77
82
  readonly reactivity: Reactivity.Reactivity["Service"]
78
83
  readonly IDBKeyRange: typeof globalThis.IDBKeyRange
79
84
  readonly IDBTransaction: globalThis.IDBTransaction | undefined
80
85
 
81
86
  readonly use: <A = unknown>(
82
- f: (database: globalThis.IDBDatabase) => Promise<A>
87
+ f: (database: globalThis.IDBDatabase) => A
83
88
  ) => Effect.Effect<A, IndexedDbQueryError>
84
89
 
85
90
  readonly from: <
@@ -92,27 +97,16 @@ export interface IndexedDbQueryBuilder<
92
97
 
93
98
  readonly clearAll: Effect.Effect<void, IndexedDbQueryError>
94
99
 
95
- readonly transaction: <
100
+ readonly withTransaction: <
96
101
  Tables extends NonEmptyReadonlyArray<
97
102
  IndexedDbTable.TableName<IndexedDbVersion.Tables<Source>>
98
103
  >,
99
- Mode extends "readonly" | "readwrite",
100
- E,
101
- R
102
- >(
103
- tables: Tables,
104
- mode: Mode,
105
- callback: (api: {
106
- readonly from: <Name extends Tables[number]>(
107
- table: Name
108
- ) => Mode extends "readwrite" ? IndexedDbQuery.From<IndexedDbVersion.TableWithName<Source, Name>>
109
- : Omit<
110
- IndexedDbQuery.From<IndexedDbVersion.TableWithName<Source, Name>>,
111
- "insert" | "insertAll" | "upsert" | "upsertAll" | "clear" | "delete"
112
- >
113
- }) => Effect.Effect<void, E, R>,
114
- options?: globalThis.IDBTransactionOptions
115
- ) => Effect.Effect<void, never, R>
104
+ Mode extends "readonly" | "readwrite"
105
+ >(options: {
106
+ readonly tables: Tables
107
+ readonly mode: Mode
108
+ readonly durability?: IDBTransactionDurability
109
+ }) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, IndexedDbTransaction>>
116
110
  }
117
111
 
118
112
  /**
@@ -140,7 +134,7 @@ export declare namespace IndexedDbQuery {
140
134
  * @since 4.0.0
141
135
  * @category models
142
136
  */
143
- export type SourceTableSelectSchemaType<
137
+ export type SelectType<
144
138
  Table extends IndexedDbTable.AnyWithProps
145
139
  > = [IndexedDbTable.KeyPath<Table>] extends [undefined] ? IndexedDbTable.TableSchema<Table>["Type"] & {
146
140
  readonly key: (typeof IndexedDb.IDBValidKey)["Type"]
@@ -151,7 +145,7 @@ export declare namespace IndexedDbQuery {
151
145
  * @since 4.0.0
152
146
  * @category models
153
147
  */
154
- export type SourceTableModifySchemaType<
148
+ export type ModifyType<
155
149
  Table extends IndexedDbTable.AnyWithProps
156
150
  > =
157
151
  & (IndexedDbTable.AutoIncrement<Table> extends true ?
@@ -179,25 +173,40 @@ export declare namespace IndexedDbQuery {
179
173
  }
180
174
  : {})
181
175
 
176
+ /**
177
+ * @since 4.0.0
178
+ * @category models
179
+ */
180
+ export type EqualsType<
181
+ Table extends IndexedDbTable.AnyWithProps,
182
+ Index extends keyof Table["indexes"],
183
+ KeyPath = [Index] extends [never] ? Table["keyPath"] : Table["indexes"][Index],
184
+ Type = Table["tableSchema"]["Encoded"]
185
+ > = KeyPath extends keyof Type ? Type[KeyPath]
186
+ : { [I in keyof KeyPath]: KeyPath[I] extends keyof Type ? Type[KeyPath[I]] | [] : never }
187
+
182
188
  /**
183
189
  * @since 4.0.0
184
190
  * @category models
185
191
  */
186
192
  export type ExtractIndexType<
187
193
  Table extends IndexedDbTable.AnyWithProps,
188
- Index extends IndexedDbDatabase.IndexFromTable<Table>
189
- > = [Index] extends [never] ? Schema.Schema.Type<
190
- IndexedDbTable.TableSchema<Table>
191
- >[IndexedDbTable.KeyPath<Table>]
192
- : Schema.Schema.Type<
193
- IndexedDbTable.TableSchema<Table>
194
- >[IndexedDbTable.Indexes<Table>[Index]]
194
+ Index extends keyof Table["indexes"],
195
+ KeyPath = [Index] extends [never] ? Table["keyPath"] : Table["indexes"][Index],
196
+ Type = Table["tableSchema"]["Encoded"]
197
+ > = KeyPath extends keyof Type ? Type[KeyPath]
198
+ : KeyPath extends readonly [infer K, ...infer Rest] ? K extends keyof Type ? [
199
+ Type[K],
200
+ ...{ [P in keyof Rest]?: Rest[P] extends keyof Type ? Type[Rest[P]] | [] : never }
201
+ ] :
202
+ never :
203
+ never
195
204
 
196
205
  /**
197
206
  * @since 4.0.0
198
207
  * @category models
199
208
  */
200
- export type ModifyWithKey<Table extends IndexedDbTable.AnyWithProps> = SourceTableModifySchemaType<Table>
209
+ export type ModifyWithKey<Table extends IndexedDbTable.AnyWithProps> = ModifyType<Table>
201
210
 
202
211
  /**
203
212
  * @since 4.0.0
@@ -205,9 +214,8 @@ export declare namespace IndexedDbQuery {
205
214
  */
206
215
  export interface From<Table extends IndexedDbTable.AnyWithProps> {
207
216
  readonly table: Table
208
- readonly database: globalThis.IDBDatabase
217
+ readonly database: MutableRef.MutableRef<globalThis.IDBDatabase>
209
218
  readonly IDBKeyRange: typeof globalThis.IDBKeyRange
210
- readonly transaction?: globalThis.IDBTransaction
211
219
  readonly reactivity: Reactivity.Reactivity["Service"]
212
220
 
213
221
  readonly clear: Effect.Effect<void, IndexedDbQueryError>
@@ -253,6 +261,8 @@ export declare namespace IndexedDbQuery {
253
261
  readonly from: From<Table>
254
262
  }
255
263
 
264
+ type ComparisonKeys = "equals" | "gte" | "lte" | "gt" | "lt" | "between"
265
+
256
266
  /**
257
267
  * @since 4.0.0
258
268
  * @category models
@@ -268,51 +278,32 @@ export declare namespace IndexedDbQuery {
268
278
  readonly upperBound?: ExtractIndexType<Table, Index>
269
279
  readonly excludeLowerBound?: boolean
270
280
  readonly excludeUpperBound?: boolean
271
- readonly limitValue?: number | undefined
272
281
 
273
282
  readonly equals: (
274
- value: ExtractIndexType<Table, Index>
275
- ) => Omit<
276
- Count<Table, Index>,
277
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
278
- >
283
+ value: EqualsType<Table, Index>
284
+ ) => Omit<Count<Table, Index>, ComparisonKeys>
279
285
 
280
286
  readonly gte: (
281
287
  value: ExtractIndexType<Table, Index>
282
- ) => Omit<
283
- Count<Table, Index>,
284
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
285
- >
288
+ ) => Omit<Count<Table, Index>, ComparisonKeys>
286
289
 
287
290
  readonly lte: (
288
291
  value: ExtractIndexType<Table, Index>
289
- ) => Omit<
290
- Count<Table, Index>,
291
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
292
- >
292
+ ) => Omit<Count<Table, Index>, ComparisonKeys>
293
293
 
294
294
  readonly gt: (
295
295
  value: ExtractIndexType<Table, Index>
296
- ) => Omit<
297
- Count<Table, Index>,
298
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
299
- >
296
+ ) => Omit<Count<Table, Index>, ComparisonKeys>
300
297
 
301
298
  readonly lt: (
302
299
  value: ExtractIndexType<Table, Index>
303
- ) => Omit<
304
- Count<Table, Index>,
305
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
306
- >
300
+ ) => Omit<Count<Table, Index>, ComparisonKeys>
307
301
 
308
302
  readonly between: (
309
303
  lowerBound: ExtractIndexType<Table, Index>,
310
304
  upperBound: ExtractIndexType<Table, Index>,
311
305
  options?: { excludeLowerBound?: boolean; excludeUpperBound?: boolean }
312
- ) => Omit<
313
- Count<Table, Index>,
314
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
315
- >
306
+ ) => Omit<Count<Table, Index>, ComparisonKeys>
316
307
  }
317
308
 
318
309
  /**
@@ -327,64 +318,50 @@ export declare namespace IndexedDbQuery {
327
318
  readonly index?: Index
328
319
 
329
320
  readonly equals: (
330
- value: ExtractIndexType<Table, Index>
331
- ) => Omit<
332
- Delete<Table, Index>,
333
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
334
- >
321
+ value: EqualsType<Table, Index>
322
+ ) => Delete<Table, Index>
335
323
 
336
324
  readonly gte: (
337
325
  value: ExtractIndexType<Table, Index>
338
- ) => Omit<
339
- Delete<Table, Index>,
340
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
341
- >
326
+ ) => Delete<Table, Index>
342
327
 
343
328
  readonly lte: (
344
329
  value: ExtractIndexType<Table, Index>
345
- ) => Omit<
346
- Delete<Table, Index>,
347
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
348
- >
330
+ ) => Delete<Table, Index>
349
331
 
350
332
  readonly gt: (
351
333
  value: ExtractIndexType<Table, Index>
352
- ) => Omit<
353
- Delete<Table, Index>,
354
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
355
- >
334
+ ) => Delete<Table, Index>
356
335
 
357
336
  readonly lt: (
358
337
  value: ExtractIndexType<Table, Index>
359
- ) => Omit<
360
- Delete<Table, Index>,
361
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
362
- >
338
+ ) => Delete<Table, Index>
363
339
 
364
340
  readonly between: (
365
341
  lowerBound: ExtractIndexType<Table, Index>,
366
342
  upperBound: ExtractIndexType<Table, Index>,
367
343
  options?: { excludeLowerBound?: boolean; excludeUpperBound?: boolean }
368
- ) => Omit<
369
- Delete<Table, Index>,
370
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
371
- >
344
+ ) => Delete<Table, Index>
372
345
 
373
346
  readonly limit: (
374
347
  limit: number
375
- ) => Omit<
376
- Delete<Table, Index>,
377
- "limit" | "equals" | "gte" | "lte" | "gt" | "lt" | "between"
378
- >
348
+ ) => DeleteWithout<Table, Index, "limit">
379
349
  }
380
350
 
351
+ type DeleteWithout<
352
+ Table extends IndexedDbTable.AnyWithProps,
353
+ Index extends IndexedDbDatabase.IndexFromTable<Table>,
354
+ ExcludedKeys extends string
355
+ > = Omit<Delete<Table, Index, ExcludedKeys>, ExcludedKeys>
356
+
381
357
  /**
382
358
  * @since 4.0.0
383
359
  * @category models
384
360
  */
385
361
  export interface Delete<
386
362
  Table extends IndexedDbTable.AnyWithProps,
387
- Index extends IndexedDbDatabase.IndexFromTable<Table>
363
+ Index extends IndexedDbDatabase.IndexFromTable<Table>,
364
+ ExcludedKeys extends string = never
388
365
  > extends Pipeable.Pipeable, Effect.YieldableClass<void, IndexedDbQueryError> {
389
366
  readonly delete: DeletePartial<Table, Index>
390
367
  readonly index?: Index
@@ -396,77 +373,42 @@ export declare namespace IndexedDbQuery {
396
373
  readonly excludeUpperBound?: boolean
397
374
  readonly predicate?: (item: IndexedDbTable.Encoded<Table>) => boolean
398
375
 
399
- readonly equals: (
400
- value: ExtractIndexType<Table, Index>
401
- ) => Omit<
402
- Delete<Table, Index>,
403
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
404
- >
405
-
406
- readonly gte: (
407
- value: ExtractIndexType<Table, Index>
408
- ) => Omit<
409
- Delete<Table, Index>,
410
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
411
- >
412
-
413
- readonly lte: (
414
- value: ExtractIndexType<Table, Index>
415
- ) => Omit<
416
- Delete<Table, Index>,
417
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
418
- >
419
-
420
- readonly gt: (
421
- value: ExtractIndexType<Table, Index>
422
- ) => Omit<
423
- Delete<Table, Index>,
424
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
425
- >
426
-
427
- readonly lt: (
428
- value: ExtractIndexType<Table, Index>
429
- ) => Omit<
430
- Delete<Table, Index>,
431
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
432
- >
433
-
434
- readonly between: (
435
- lowerBound: ExtractIndexType<Table, Index>,
436
- upperBound: ExtractIndexType<Table, Index>,
437
- options?: { excludeLowerBound?: boolean; excludeUpperBound?: boolean }
438
- ) => Omit<
439
- Delete<Table, Index>,
440
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
441
- >
442
-
443
376
  readonly limit: (
444
377
  limit: number
445
- ) => Omit<
446
- Delete<Table, Index>,
447
- "limit" | "equals" | "gte" | "lte" | "gt" | "lt" | "between"
448
- >
378
+ ) => DeleteWithout<Table, Index, ExcludedKeys | "limit">
449
379
 
450
380
  readonly filter: (
451
381
  f: (value: IndexedDbTable.Encoded<Table>) => boolean
452
- ) => Delete<Table, Index>
382
+ ) => DeleteWithout<Table, Index, ExcludedKeys>
453
383
 
384
+ /**
385
+ * Invalidate any queries using Reactivity service with the provided keys.
386
+ *
387
+ * Defaults to using the table name as a key if no keys are provided.
388
+ */
454
389
  readonly invalidate: (
455
- keys: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>>
390
+ keys?: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
456
391
  ) => Effect.Effect<void, IndexedDbQueryError, IndexedDbTable.Context<Table>>
457
392
  }
458
393
 
394
+ type SelectWithout<
395
+ Table extends IndexedDbTable.AnyWithProps,
396
+ Index extends IndexedDbDatabase.IndexFromTable<Table>,
397
+ ExcludedKeys extends string
398
+ > = Omit<Select<Table, Index, ExcludedKeys>, ExcludedKeys>
399
+
459
400
  /**
460
401
  * @since 4.0.0
461
402
  * @category models
462
403
  */
463
404
  export interface Select<
464
405
  Table extends IndexedDbTable.AnyWithProps,
465
- Index extends IndexedDbDatabase.IndexFromTable<Table>
406
+ Index extends IndexedDbDatabase.IndexFromTable<Table>,
407
+ ExcludedKeys extends string = never
466
408
  > extends
467
409
  Pipeable.Pipeable,
468
410
  Effect.YieldableClass<
469
- Array<SourceTableSelectSchemaType<Table>>,
411
+ Array<SelectType<Table>>,
470
412
  IndexedDbQueryError,
471
413
  IndexedDbTable.Context<Table>
472
414
  >
@@ -474,6 +416,8 @@ export declare namespace IndexedDbQuery {
474
416
  readonly from: From<Table>
475
417
  readonly index?: Index
476
418
  readonly limitValue?: number
419
+ readonly offsetValue?: number
420
+ readonly reverseValue?: boolean
477
421
  readonly only?: ExtractIndexType<Table, Index>
478
422
  readonly lowerBound?: ExtractIndexType<Table, Index>
479
423
  readonly upperBound?: ExtractIndexType<Table, Index>
@@ -482,73 +426,76 @@ export declare namespace IndexedDbQuery {
482
426
  readonly predicate?: (item: IndexedDbTable.Encoded<Table>) => boolean
483
427
 
484
428
  readonly equals: (
485
- value: ExtractIndexType<Table, Index>
486
- ) => Omit<
487
- Select<Table, Index>,
488
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
489
- >
429
+ value: EqualsType<Table, Index>
430
+ ) => SelectWithout<Table, Index, ExcludedKeys | ComparisonKeys>
490
431
 
491
432
  readonly gte: (
492
433
  value: ExtractIndexType<Table, Index>
493
- ) => Omit<
494
- Select<Table, Index>,
495
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
496
- >
434
+ ) => SelectWithout<Table, Index, ExcludedKeys | ComparisonKeys>
497
435
 
498
436
  readonly lte: (
499
437
  value: ExtractIndexType<Table, Index>
500
- ) => Omit<
501
- Select<Table, Index>,
502
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
503
- >
438
+ ) => SelectWithout<Table, Index, ExcludedKeys | ComparisonKeys>
504
439
 
505
440
  readonly gt: (
506
441
  value: ExtractIndexType<Table, Index>
507
- ) => Omit<
508
- Select<Table, Index>,
509
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
510
- >
442
+ ) => SelectWithout<Table, Index, ExcludedKeys | ComparisonKeys>
511
443
 
512
444
  readonly lt: (
513
445
  value: ExtractIndexType<Table, Index>
514
- ) => Omit<
515
- Select<Table, Index>,
516
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
517
- >
446
+ ) => SelectWithout<Table, Index, ExcludedKeys | ComparisonKeys>
518
447
 
519
448
  readonly between: (
520
449
  lowerBound: ExtractIndexType<Table, Index>,
521
450
  upperBound: ExtractIndexType<Table, Index>,
522
451
  options?: { excludeLowerBound?: boolean; excludeUpperBound?: boolean }
523
- ) => Omit<
524
- Select<Table, Index>,
525
- "equals" | "gte" | "lte" | "gt" | "lt" | "between"
526
- >
452
+ ) => SelectWithout<Table, Index, ExcludedKeys | ComparisonKeys>
527
453
 
528
454
  readonly limit: (
529
455
  limit: number
530
- ) => Omit<
531
- Select<Table, Index>,
532
- "limit" | "equals" | "gte" | "lte" | "gt" | "lt" | "between" | "first"
533
- >
456
+ ) => SelectWithout<Table, Index, ExcludedKeys | "limit" | "first">
457
+
458
+ readonly offset: (
459
+ offset: number
460
+ ) => SelectWithout<Table, Index, ExcludedKeys | "offset" | "first">
461
+
462
+ readonly reverse: () => SelectWithout<Table, Index, ExcludedKeys | "reverse" | "first">
534
463
 
535
464
  readonly filter: (
536
465
  f: (value: IndexedDbTable.Encoded<Table>) => boolean
537
- ) => Select<Table, Index>
466
+ ) => SelectWithout<Table, Index, ExcludedKeys | "first">
538
467
 
539
468
  readonly first: () => First<Table, Index>
540
469
 
470
+ /**
471
+ * Stream the selected data.
472
+ *
473
+ * Defaults to a chunk size of 100.
474
+ */
475
+ readonly stream: (options?: {
476
+ readonly chunkSize?: number | undefined
477
+ }) => Stream.Stream<
478
+ SelectType<Table>,
479
+ IndexedDbQueryError,
480
+ IndexedDbTable.Context<Table>
481
+ >
482
+
483
+ /**
484
+ * Use the Reactivity service to react to changes to the selected data.
485
+ *
486
+ * By default it uses the table name as a key.
487
+ */
541
488
  readonly reactive: (
542
- keys: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>>
489
+ keys?: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
543
490
  ) => Stream.Stream<
544
- Array<SourceTableSelectSchemaType<Table>>,
491
+ Array<SelectType<Table>>,
545
492
  IndexedDbQueryError,
546
493
  IndexedDbTable.Context<Table>
547
494
  >
548
495
  readonly reactiveQueue: (
549
- keys: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>>
496
+ keys?: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
550
497
  ) => Effect.Effect<
551
- Queue.Dequeue<Array<SourceTableSelectSchemaType<Table>>, IndexedDbQueryError>,
498
+ Queue.Dequeue<Array<SelectType<Table>>, IndexedDbQueryError>,
552
499
  never,
553
500
  Scope.Scope | IndexedDbTable.Context<Table>
554
501
  >
@@ -564,12 +511,38 @@ export declare namespace IndexedDbQuery {
564
511
  > extends
565
512
  Pipeable.Pipeable,
566
513
  Effect.YieldableClass<
567
- SourceTableSelectSchemaType<Table>,
514
+ SelectType<Table>,
568
515
  IndexedDbQueryError,
569
516
  IndexedDbTable.Context<Table>
570
517
  >
571
518
  {
572
519
  readonly select: Select<Table, Index>
520
+
521
+ /**
522
+ * Use the Reactivity service to react to changes to the selected data.
523
+ *
524
+ * By default it uses the table name as a key.
525
+ */
526
+ readonly reactive: (
527
+ keys?: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
528
+ ) => Stream.Stream<
529
+ SelectType<Table>,
530
+ IndexedDbQueryError,
531
+ IndexedDbTable.Context<Table>
532
+ >
533
+
534
+ /**
535
+ * Use the Reactivity service to react to changes to the selected data.
536
+ *
537
+ * By default it uses the table name as a key.
538
+ */
539
+ readonly reactiveQueue: (
540
+ keys: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>>
541
+ ) => Effect.Effect<
542
+ Queue.Dequeue<SelectType<Table>, IndexedDbQueryError>,
543
+ never,
544
+ Scope.Scope | IndexedDbTable.Context<Table>
545
+ >
573
546
  }
574
547
 
575
548
  /**
@@ -582,7 +555,7 @@ export declare namespace IndexedDbQuery {
582
555
  > extends
583
556
  Pipeable.Pipeable,
584
557
  Effect.YieldableClass<
585
- Array<SourceTableSelectSchemaType<Table>>,
558
+ Array<SelectType<Table>>,
586
559
  IndexedDbQueryError,
587
560
  IndexedDbTable.Context<Table>
588
561
  >
@@ -611,8 +584,14 @@ export declare namespace IndexedDbQuery {
611
584
  readonly operation: "add" | "put"
612
585
  readonly from: From<Table>
613
586
  readonly value: ModifyWithKey<Table>
587
+
588
+ /**
589
+ * Invalidate any queries using Reactivity service with the provided keys.
590
+ *
591
+ * Defaults to using the table name as a key if no keys are provided.
592
+ */
614
593
  readonly invalidate: (
615
- keys: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>>
594
+ keys?: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
616
595
  ) => Effect.Effect<globalThis.IDBValidKey, IndexedDbQueryError, IndexedDbTable.Context<Table>>
617
596
  }
618
597
 
@@ -633,12 +612,26 @@ export declare namespace IndexedDbQuery {
633
612
  readonly operation: "add" | "put"
634
613
  readonly from: From<Table>
635
614
  readonly values: Array<ModifyWithKey<Table>>
615
+
616
+ /**
617
+ * Invalidate any queries using Reactivity service with the provided keys.
618
+ *
619
+ * Defaults to using the table name as a key if no keys are provided.
620
+ */
636
621
  readonly invalidate: (
637
- keys: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>>
638
- ) => Effect.Effect<Array<globalThis.IDBValidKey>, IndexedDbQueryError, IndexedDbTable.Context<Table>>
622
+ keys?: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
623
+ ) => Effect.Effect<globalThis.IDBValidKey, IndexedDbQueryError, IndexedDbTable.Context<Table>>
639
624
  }
640
625
  }
641
626
 
627
+ /**
628
+ * @since 4.0.0
629
+ * @category models
630
+ */
631
+ export class IndexedDbTransaction extends Context.Service<IndexedDbTransaction, globalThis.IDBTransaction>()(
632
+ "@effect/platform-browser/IndexedDbQueryBuilder/IndexedDbTransaction"
633
+ ) {}
634
+
642
635
  // -----------------------------------------------------------------------------
643
636
  // internal
644
637
  // -----------------------------------------------------------------------------
@@ -661,8 +654,9 @@ const applyDelete = (query: IndexedDbQuery.Delete<any, never>) =>
661
654
  Effect.callback<any, IndexedDbQueryError>((resume) => {
662
655
  const database = query.delete.from.database
663
656
  const IDBKeyRange = query.delete.from.IDBKeyRange
664
- let transaction = query.delete.from.transaction
665
- transaction ??= database.transaction([query.delete.from.table.tableName], "readwrite")
657
+ const transaction = getOrCreateTransaction(database.current, [query.delete.from.table.tableName], "readwrite", {
658
+ durability: query.delete.from.table.durability
659
+ })
666
660
  const objectStore = transaction.objectStore(query.delete.from.table.tableName)
667
661
  const predicate = query.predicate
668
662
 
@@ -765,7 +759,9 @@ const getReadonlyObjectStore = (
765
759
  ) => {
766
760
  const database = query.from.database
767
761
  const IDBKeyRange = query.from.IDBKeyRange
768
- const transaction = query.from.transaction ?? database.transaction([query.from.table.tableName], "readonly")
762
+ const transaction = getOrCreateTransaction(database.current, [query.from.table.tableName], "readonly", {
763
+ durability: query.from.table.durability
764
+ })
769
765
  const objectStore = transaction.objectStore(query.from.table.tableName)
770
766
 
771
767
  let keyRange: globalThis.IDBKeyRange | undefined = undefined
@@ -801,19 +797,20 @@ const getReadonlyObjectStore = (
801
797
  return { store, keyRange }
802
798
  }
803
799
 
804
- const getSelect = Effect.fnUntraced(function*(
805
- query: IndexedDbQuery.Select<any, never>
806
- ) {
800
+ const applySelect = Effect.fnUntraced(function*(
801
+ query: IndexedDbQuery.Select<any, never, any>
802
+ ): Effect.fn.Return<Array<any>, IndexedDbQueryError, unknown> {
807
803
  const keyPath = query.from.table.keyPath
808
804
  const predicate = query.predicate
809
805
 
810
- const data = predicate || keyPath === undefined ?
811
- yield* Effect.callback<any, IndexedDbQueryError>((resume) => {
806
+ const data = predicate || keyPath === undefined || query.offsetValue !== undefined ?
807
+ yield* Effect.callback<Array<any>, IndexedDbQueryError>((resume) => {
812
808
  const { keyRange, store } = getReadonlyObjectStore(query)
813
809
 
814
- const cursorRequest = store.openCursor(keyRange)
810
+ const cursorRequest = store.openCursor(keyRange, query.reverseValue ? "prev" : "next")
815
811
  const results: Array<any> = []
816
812
  let count = 0
813
+ let offsetApplied = false
817
814
 
818
815
  cursorRequest.onerror = () => {
819
816
  resume(
@@ -832,6 +829,11 @@ const getSelect = Effect.fnUntraced(function*(
832
829
  return resume(Effect.succeed(results))
833
830
  }
834
831
 
832
+ if (query.offsetValue && !offsetApplied) {
833
+ offsetApplied = true
834
+ return cursor.advance(query.offsetValue)
835
+ }
836
+
835
837
  if (predicate === undefined || predicate(cursor.value)) {
836
838
  results.push(
837
839
  keyPath === undefined
@@ -848,7 +850,7 @@ const getSelect = Effect.fnUntraced(function*(
848
850
  resume(Effect.succeed(results))
849
851
  }
850
852
  }) :
851
- yield* Effect.callback<any, IndexedDbQueryError>((resume) => {
853
+ yield* Effect.callback<Array<any>, IndexedDbQueryError>((resume) => {
852
854
  const { keyRange, store } = getReadonlyObjectStore(query)
853
855
  const request = store.getAll(keyRange, query.limitValue)
854
856
  request.onerror = (event) => {
@@ -862,6 +864,9 @@ const getSelect = Effect.fnUntraced(function*(
862
864
  )
863
865
  }
864
866
  request.onsuccess = () => {
867
+ if (query.reverseValue) {
868
+ request.result.reverse()
869
+ }
865
870
  resume(Effect.succeed(request.result))
866
871
  }
867
872
  })
@@ -876,7 +881,7 @@ const getSelect = Effect.fnUntraced(function*(
876
881
  cause: error
877
882
  })
878
883
  )
879
- )
884
+ ) as Effect.Effect<Array<any>, IndexedDbQueryError, unknown>
880
885
  })
881
886
 
882
887
  const getFirst = Effect.fnUntraced(function*(
@@ -984,7 +989,9 @@ const applyModify = Effect.fnUntraced(function*({
984
989
 
985
990
  return yield* Effect.callback<any, IndexedDbQueryError>((resume) => {
986
991
  const database = query.from.database
987
- const transaction = query.from.transaction ?? database.transaction([query.from.table.tableName], "readwrite")
992
+ const transaction = getOrCreateTransaction(database.current, [query.from.table.tableName], "readwrite", {
993
+ durability: query.from.table.durability
994
+ })
988
995
  const objectStore = transaction.objectStore(query.from.table.tableName)
989
996
 
990
997
  let request: globalThis.IDBRequest<IDBValidKey>
@@ -1051,11 +1058,10 @@ const applyModifyAll = Effect.fnUntraced(
1051
1058
  IndexedDbQueryError
1052
1059
  >((resume) => {
1053
1060
  const database = query.from.database
1054
- const transaction = query.from.transaction
1055
- const objectStore = (
1056
- transaction ??
1057
- database.transaction([query.from.table.tableName], "readwrite")
1058
- ).objectStore(query.from.table.tableName)
1061
+ const transaction = getOrCreateTransaction(database.current, [query.from.table.tableName], "readwrite", {
1062
+ durability: query.from.table.durability
1063
+ })
1064
+ const objectStore = transaction.objectStore(query.from.table.tableName)
1059
1065
 
1060
1066
  const results: Array<globalThis.IDBValidKey> = []
1061
1067
 
@@ -1131,13 +1137,14 @@ const applyModifyAll = Effect.fnUntraced(
1131
1137
 
1132
1138
  const applyClear = (options: {
1133
1139
  readonly database: globalThis.IDBDatabase
1134
- readonly transaction: globalThis.IDBTransaction | undefined
1135
- readonly table: string
1140
+ readonly table: IndexedDbTable.AnyWithProps
1136
1141
  }) =>
1137
1142
  Effect.callback<void, IndexedDbQueryError>((resume) => {
1138
1143
  const database = options.database
1139
- const transaction = options.transaction ?? database.transaction([options.table], "readwrite")
1140
- const objectStore = transaction.objectStore(options.table)
1144
+ const transaction = getOrCreateTransaction(database, [options.table.tableName], "readwrite", {
1145
+ durability: options.table.durability
1146
+ })
1147
+ const objectStore = transaction.objectStore(options.table.tableName)
1141
1148
 
1142
1149
  const request = objectStore.clear()
1143
1150
 
@@ -1159,12 +1166,11 @@ const applyClear = (options: {
1159
1166
 
1160
1167
  const applyClearAll = (options: {
1161
1168
  readonly database: globalThis.IDBDatabase
1162
- readonly transaction: globalThis.IDBTransaction | undefined
1163
1169
  }) =>
1164
1170
  Effect.callback<void, IndexedDbQueryError>((resume) => {
1165
1171
  const database = options.database
1166
1172
  const tables = database.objectStoreNames
1167
- const transaction = options.transaction ?? database.transaction([...tables], "readwrite")
1173
+ const transaction = getOrCreateTransaction(database, [...tables], "readwrite")
1168
1174
 
1169
1175
  for (let t = 0; t < tables.length; t++) {
1170
1176
  const objectStore = transaction.objectStore(tables[t])
@@ -1271,9 +1277,8 @@ const FromProto: Omit<
1271
1277
  get clear() {
1272
1278
  const self = this as IndexedDbQuery.From<any>
1273
1279
  return applyClear({
1274
- database: self.database,
1275
- transaction: self.transaction,
1276
- table: self.table.tableName
1280
+ database: self.database.current,
1281
+ table: self.table
1277
1282
  })
1278
1283
  }
1279
1284
  }
@@ -1282,16 +1287,14 @@ const makeFrom = <
1282
1287
  const Table extends IndexedDbTable.AnyWithProps
1283
1288
  >(options: {
1284
1289
  readonly table: Table
1285
- readonly database: globalThis.IDBDatabase
1290
+ readonly database: MutableRef.MutableRef<globalThis.IDBDatabase>
1286
1291
  readonly IDBKeyRange: typeof globalThis.IDBKeyRange
1287
- readonly transaction: globalThis.IDBTransaction | undefined
1288
1292
  readonly reactivity: Reactivity.Reactivity["Service"]
1289
1293
  }): IndexedDbQuery.From<Table> => {
1290
1294
  const self = Object.create(FromProto)
1291
1295
  self.table = options.table
1292
1296
  self.database = options.database
1293
1297
  self.IDBKeyRange = options.IDBKeyRange
1294
- self.transaction = options.transaction
1295
1298
  self.reactivity = options.reactivity
1296
1299
  return self
1297
1300
  }
@@ -1388,69 +1391,10 @@ const DeleteProto: Omit<
1388
1391
  },
1389
1392
  limit(this: IndexedDbQuery.Delete<any, never>, limit: number) {
1390
1393
  return makeDelete({
1391
- delete: this.delete,
1392
- only: this.only,
1393
- lowerBound: this.lowerBound,
1394
- upperBound: this.upperBound,
1395
- excludeLowerBound: this.excludeLowerBound ?? false,
1396
- excludeUpperBound: this.excludeUpperBound ?? false,
1394
+ ...this,
1397
1395
  limitValue: limit
1398
1396
  })
1399
1397
  },
1400
- equals(this: IndexedDbQuery.Delete<any, never>, value: IndexedDbQuery.ExtractIndexType<any, never>) {
1401
- return makeDelete({
1402
- delete: this.delete,
1403
- only: value,
1404
- limitValue: this.limitValue
1405
- })
1406
- },
1407
- gte(this: IndexedDbQuery.Delete<any, never>, value: IndexedDbQuery.ExtractIndexType<any, never>) {
1408
- return makeDelete({
1409
- delete: this.delete,
1410
- lowerBound: value,
1411
- excludeLowerBound: false,
1412
- limitValue: this.limitValue
1413
- })
1414
- },
1415
- lte(this: IndexedDbQuery.Delete<any, never>, value: IndexedDbQuery.ExtractIndexType<any, never>) {
1416
- return makeDelete({
1417
- delete: this.delete,
1418
- upperBound: value,
1419
- excludeUpperBound: false,
1420
- limitValue: this.limitValue
1421
- })
1422
- },
1423
- gt(this: IndexedDbQuery.Delete<any, never>, value: IndexedDbQuery.ExtractIndexType<any, never>) {
1424
- return makeDelete({
1425
- delete: this.delete,
1426
- lowerBound: value,
1427
- excludeLowerBound: true,
1428
- limitValue: this.limitValue
1429
- })
1430
- },
1431
- lt(this: IndexedDbQuery.Delete<any, never>, value: IndexedDbQuery.ExtractIndexType<any, never>) {
1432
- return makeDelete({
1433
- delete: this.delete,
1434
- upperBound: value,
1435
- excludeUpperBound: true,
1436
- limitValue: this.limitValue
1437
- })
1438
- },
1439
- between(
1440
- this: IndexedDbQuery.Delete<any, never>,
1441
- lowerBound: IndexedDbQuery.ExtractIndexType<any, never>,
1442
- upperBound: IndexedDbQuery.ExtractIndexType<any, never>,
1443
- queryOptions?: { excludeLowerBound?: boolean; excludeUpperBound?: boolean }
1444
- ) {
1445
- return makeDelete({
1446
- delete: this.delete,
1447
- lowerBound,
1448
- upperBound,
1449
- excludeLowerBound: queryOptions?.excludeLowerBound ?? false,
1450
- excludeUpperBound: queryOptions?.excludeUpperBound ?? false,
1451
- limitValue: this.limitValue
1452
- })
1453
- },
1454
1398
  filter(this: IndexedDbQuery.Delete<any, never>, filter: (value: IndexedDbTable.Encoded<any>) => boolean) {
1455
1399
  const prev = this.predicate
1456
1400
  return makeDelete({
@@ -1460,8 +1404,11 @@ const DeleteProto: Omit<
1460
1404
  },
1461
1405
  invalidate(
1462
1406
  this: IndexedDbQuery.Delete<any, never>,
1463
- keys: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>>
1407
+ keys?: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
1464
1408
  ) {
1409
+ keys ??= this.only !== undefined
1410
+ ? { [this.delete.from.table.tableName]: [this.only] }
1411
+ : [this.delete.from.table.tableName]
1465
1412
  return this.delete.from.reactivity.mutation(keys, this.asEffect())
1466
1413
  }
1467
1414
  }
@@ -1489,8 +1436,8 @@ const makeDelete = <
1489
1436
  self.only = options.only
1490
1437
  self.lowerBound = options.lowerBound
1491
1438
  self.upperBound = options.upperBound
1492
- self.excludeLowerBound = options.excludeLowerBound
1493
- self.excludeUpperBound = options.excludeUpperBound
1439
+ self.excludeLowerBound = options.excludeLowerBound ?? false
1440
+ self.excludeUpperBound = options.excludeUpperBound ?? false
1494
1441
  self.predicate = options.predicate
1495
1442
  return self
1496
1443
  }
@@ -1513,8 +1460,7 @@ const CountProto: Omit<
1513
1460
  return makeCount({
1514
1461
  from: this.from,
1515
1462
  index: this.index,
1516
- only: value,
1517
- limitValue: this.limitValue
1463
+ only: value
1518
1464
  })
1519
1465
  },
1520
1466
  gte(this: IndexedDbQuery.Count<any, never>, value: IndexedDbQuery.ExtractIndexType<any, never>) {
@@ -1522,8 +1468,7 @@ const CountProto: Omit<
1522
1468
  from: this.from,
1523
1469
  index: this.index,
1524
1470
  lowerBound: value,
1525
- excludeLowerBound: false,
1526
- limitValue: this.limitValue
1471
+ excludeLowerBound: false
1527
1472
  })
1528
1473
  },
1529
1474
  lte(this: IndexedDbQuery.Count<any, never>, value: IndexedDbQuery.ExtractIndexType<any, never>) {
@@ -1531,8 +1476,7 @@ const CountProto: Omit<
1531
1476
  from: this.from,
1532
1477
  index: this.index,
1533
1478
  upperBound: value,
1534
- excludeUpperBound: false,
1535
- limitValue: this.limitValue
1479
+ excludeUpperBound: false
1536
1480
  })
1537
1481
  },
1538
1482
  gt(this: IndexedDbQuery.Count<any, never>, value: IndexedDbQuery.ExtractIndexType<any, never>) {
@@ -1540,8 +1484,7 @@ const CountProto: Omit<
1540
1484
  from: this.from,
1541
1485
  index: this.index,
1542
1486
  lowerBound: value,
1543
- excludeLowerBound: true,
1544
- limitValue: this.limitValue
1487
+ excludeLowerBound: true
1545
1488
  })
1546
1489
  },
1547
1490
  lt(this: IndexedDbQuery.Count<any, never>, value: IndexedDbQuery.ExtractIndexType<any, never>) {
@@ -1549,8 +1492,7 @@ const CountProto: Omit<
1549
1492
  from: this.from,
1550
1493
  index: this.index,
1551
1494
  upperBound: value,
1552
- excludeUpperBound: true,
1553
- limitValue: this.limitValue
1495
+ excludeUpperBound: true
1554
1496
  })
1555
1497
  },
1556
1498
  between(
@@ -1565,8 +1507,7 @@ const CountProto: Omit<
1565
1507
  lowerBound,
1566
1508
  upperBound,
1567
1509
  excludeLowerBound: queryOptions?.excludeLowerBound ?? false,
1568
- excludeUpperBound: queryOptions?.excludeUpperBound ?? false,
1569
- limitValue: this.limitValue
1510
+ excludeUpperBound: queryOptions?.excludeUpperBound ?? false
1570
1511
  })
1571
1512
  }
1572
1513
  }
@@ -1577,7 +1518,6 @@ const makeCount = <
1577
1518
  >(options: {
1578
1519
  readonly from: IndexedDbQuery.From<Table>
1579
1520
  readonly index: Index | undefined
1580
- readonly limitValue?: number | undefined
1581
1521
  readonly only?: IndexedDbQuery.ExtractIndexType<Table, Index> | undefined
1582
1522
  readonly lowerBound?:
1583
1523
  | IndexedDbQuery.ExtractIndexType<Table, Index>
@@ -1592,7 +1532,6 @@ const makeCount = <
1592
1532
  self.from = options.from
1593
1533
  self.index = options.index
1594
1534
  self.only = options.only
1595
- self.limitValue = options.limitValue
1596
1535
  self.lowerBound = options.lowerBound
1597
1536
  self.upperBound = options.upperBound
1598
1537
  self.excludeLowerBound = options.excludeLowerBound
@@ -1605,6 +1544,7 @@ const SelectProto: Omit<
1605
1544
  | "from"
1606
1545
  | "index"
1607
1546
  | "limitValue"
1547
+ | "reverseValue"
1608
1548
  | "only"
1609
1549
  | "lowerBound"
1610
1550
  | "upperBound"
@@ -1618,6 +1558,12 @@ const SelectProto: Omit<
1618
1558
  limitValue: limit
1619
1559
  })
1620
1560
  },
1561
+ offset(this: IndexedDbQuery.Select<any, never>, offset: number) {
1562
+ return makeSelect({
1563
+ ...this,
1564
+ offsetValue: offset
1565
+ })
1566
+ },
1621
1567
  equals(this: IndexedDbQuery.Select<any, never>, value: IndexedDbQuery.ExtractIndexType<any, never>) {
1622
1568
  return makeSelect({
1623
1569
  ...this,
@@ -1666,6 +1612,12 @@ const SelectProto: Omit<
1666
1612
  excludeUpperBound: queryOptions?.excludeUpperBound ?? false
1667
1613
  })
1668
1614
  },
1615
+ reverse(this: IndexedDbQuery.Select<any, never>) {
1616
+ return makeSelect({
1617
+ ...this,
1618
+ reverseValue: true
1619
+ })
1620
+ },
1669
1621
  first(this: IndexedDbQuery.Select<any, never>) {
1670
1622
  return makeFirst({ select: this })
1671
1623
  },
@@ -1677,18 +1629,41 @@ const SelectProto: Omit<
1677
1629
  })
1678
1630
  },
1679
1631
  asEffect(this: IndexedDbQuery.Select<any, never>) {
1680
- return getSelect(this) as any
1632
+ return applySelect(this) as any
1633
+ },
1634
+ stream(this: IndexedDbQuery.Select<any, never>, options?: {
1635
+ readonly chunkSize?: number | undefined
1636
+ }) {
1637
+ const limit = this.limitValue
1638
+ const chunkSize = Math.min(options?.chunkSize ?? 100, limit ?? Number.MAX_SAFE_INTEGER)
1639
+ const initial = this.limit(chunkSize)
1640
+ return Stream.suspend(() => {
1641
+ let total = 0
1642
+ return Stream.paginate(initial, (select) =>
1643
+ Effect.map(
1644
+ applySelect(select as any),
1645
+ (data) => {
1646
+ total += data.length
1647
+ ;(select as any).offsetValue = total
1648
+ const reachedLimit = limit && total >= limit
1649
+ const isPartial = data.length < chunkSize
1650
+ return [data, isPartial || reachedLimit ? Option.none() : Option.some(select)] as const
1651
+ }
1652
+ ))
1653
+ })
1681
1654
  },
1682
1655
  reactive(
1683
1656
  this: IndexedDbQuery.Select<any, never>,
1684
- keys: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>>
1657
+ keys?: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
1685
1658
  ) {
1659
+ keys ??= [this.from.table.tableName]
1686
1660
  return this.from.reactivity.stream(keys, this.asEffect())
1687
1661
  },
1688
1662
  reactiveQueue(
1689
1663
  this: IndexedDbQuery.Select<any, never>,
1690
- keys: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>>
1664
+ keys?: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
1691
1665
  ) {
1666
+ keys ??= [this.from.table.tableName]
1692
1667
  return this.from.reactivity.query(keys, this.asEffect())
1693
1668
  }
1694
1669
  }
@@ -1700,6 +1675,8 @@ const makeSelect = <
1700
1675
  readonly from: IndexedDbQuery.From<Table>
1701
1676
  readonly index?: Index | undefined
1702
1677
  readonly limitValue?: number | undefined
1678
+ readonly offsetValue?: number | undefined
1679
+ readonly reverseValue?: boolean | undefined
1703
1680
  readonly only?: IndexedDbQuery.ExtractIndexType<Table, Index> | undefined
1704
1681
  readonly lowerBound?:
1705
1682
  | IndexedDbQuery.ExtractIndexType<Table, Index>
@@ -1716,6 +1693,8 @@ const makeSelect = <
1716
1693
  self.index = options.index
1717
1694
  self.only = options.only
1718
1695
  self.limitValue = options.limitValue
1696
+ self.offsetValue = options.offsetValue
1697
+ self.reverseValue = options.reverseValue
1719
1698
  self.lowerBound = options.lowerBound
1720
1699
  self.upperBound = options.upperBound
1721
1700
  self.excludeLowerBound = options.excludeLowerBound
@@ -1731,6 +1710,24 @@ const FirstProto: Omit<
1731
1710
  ...CommonProto,
1732
1711
  asEffect(this: IndexedDbQuery.First<any, never>) {
1733
1712
  return getFirst(this) as any
1713
+ },
1714
+ reactive(
1715
+ this: IndexedDbQuery.First<any, never>,
1716
+ keys?: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
1717
+ ) {
1718
+ keys ??= this.select.only !== undefined
1719
+ ? [`${this.select.from.table.tableName}:${String(this.select.only)}`]
1720
+ : [this.select.from.table.tableName]
1721
+ return this.select.from.reactivity.stream(keys, this.asEffect())
1722
+ },
1723
+ reactiveQueue(
1724
+ this: IndexedDbQuery.First<any, never>,
1725
+ keys?: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
1726
+ ) {
1727
+ keys ??= this.select.only !== undefined
1728
+ ? [`${this.select.from.table.tableName}:${this.select.only}`]
1729
+ : [this.select.from.table.tableName]
1730
+ return this.select.from.reactivity.query(keys, this.asEffect())
1734
1731
  }
1735
1732
  }
1736
1733
 
@@ -1757,8 +1754,12 @@ const ModifyProto: Omit<
1757
1754
  },
1758
1755
  invalidate(
1759
1756
  this: IndexedDbQuery.Modify<any>,
1760
- keys: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>>
1757
+ keys?: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
1761
1758
  ) {
1759
+ const keyPath = this.from.table.keyPath
1760
+ keys ??= typeof keyPath === "string" && this.value[keyPath] !== undefined
1761
+ ? { [this.from.table.tableName]: [this.value[keyPath]] }
1762
+ : [this.from.table.tableName]
1762
1763
  return this.from.reactivity.mutation(keys, this.asEffect())
1763
1764
  }
1764
1765
  }
@@ -1787,8 +1788,9 @@ const ModifyAllProto: Omit<
1787
1788
  },
1788
1789
  invalidate(
1789
1790
  this: IndexedDbQuery.ModifyAll<any>,
1790
- keys: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>>
1791
+ keys?: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
1791
1792
  ) {
1793
+ keys ??= [this.from.table.tableName]
1792
1794
  return this.from.reactivity.mutation(keys, this.asEffect())
1793
1795
  }
1794
1796
  }
@@ -1816,9 +1818,9 @@ const QueryBuilderProto: Omit<
1816
1818
  | "reactivity"
1817
1819
  > = {
1818
1820
  ...CommonProto,
1819
- use(this: IndexedDbQueryBuilder<any>, f: (database: globalThis.IDBDatabase) => Promise<any>) {
1820
- return Effect.tryPromise({
1821
- try: () => f(this.database),
1821
+ use(this: IndexedDbQueryBuilder<any>, f: (database: globalThis.IDBDatabase) => any) {
1822
+ return Effect.try({
1823
+ try: () => f(this.database.current),
1822
1824
  catch: (error) =>
1823
1825
  new IndexedDbQueryError({
1824
1826
  reason: "UnknownError",
@@ -1831,41 +1833,27 @@ const QueryBuilderProto: Omit<
1831
1833
  database: this.database,
1832
1834
  IDBKeyRange: this.IDBKeyRange,
1833
1835
  table: this.tables.get(table)!,
1834
- transaction: this.IDBTransaction,
1835
1836
  reactivity: this.reactivity
1836
1837
  }) as any
1837
1838
  },
1838
1839
  get clearAll() {
1839
1840
  const self = this as IndexedDbQueryBuilder<any>
1840
- return applyClearAll({ database: self.database, transaction: self.IDBTransaction })
1841
+ return applyClearAll({ database: self.database.current })
1841
1842
  },
1842
- transaction: Effect.fnUntraced(function*<E, R>(
1843
- this: IndexedDbQueryBuilder<any>,
1844
- transactionTables: Array<
1845
- IndexedDbTable.TableName<IndexedDbVersion.Tables<any>>
1846
- >,
1847
- mode: globalThis.IDBTransactionMode,
1848
- callback: (api: {
1849
- readonly from: <
1850
- Name extends IndexedDbTable.TableName<IndexedDbVersion.Tables<any>>
1851
- >(
1852
- table: Name
1853
- ) => IndexedDbQuery.From<IndexedDbVersion.TableWithName<any, Name>>
1854
- }) => Effect.Effect<void, E, R>,
1855
- options?: globalThis.IDBTransactionOptions
1856
- ) {
1857
- const transaction = this.database.transaction(transactionTables, mode, options)
1858
- return yield* callback({
1859
- from: (table) =>
1860
- makeFrom({
1861
- database: this.database,
1862
- IDBKeyRange: this.IDBKeyRange,
1863
- table: this.tables.get(table) as any,
1864
- transaction,
1865
- reactivity: this.reactivity
1866
- })
1867
- })
1868
- }) as any
1843
+ withTransaction(this: IndexedDbQueryBuilder<any>, options: {
1844
+ readonly tables: NonEmptyReadonlyArray<any>
1845
+ readonly mode: globalThis.IDBTransactionMode
1846
+ readonly durability?: IDBTransactionDurability
1847
+ }) {
1848
+ return (effect) =>
1849
+ Effect.suspend(() => {
1850
+ const transaction = this.database.current.transaction(options.tables, options.mode, options)
1851
+ return Effect.provideService(effect, IndexedDbTransaction, transaction)
1852
+ }).pipe(
1853
+ // To prevent async gaps between transaction queries
1854
+ Effect.provideService(References.PreventSchedulerYield, true)
1855
+ )
1856
+ }
1869
1857
  }
1870
1858
 
1871
1859
  /**
@@ -1876,13 +1864,11 @@ export const make = <Source extends IndexedDbVersion.AnyWithProps>({
1876
1864
  IDBKeyRange,
1877
1865
  database,
1878
1866
  tables,
1879
- transaction,
1880
1867
  reactivity
1881
1868
  }: {
1882
- readonly database: globalThis.IDBDatabase
1869
+ readonly database: MutableRef.MutableRef<globalThis.IDBDatabase>
1883
1870
  readonly IDBKeyRange: typeof globalThis.IDBKeyRange
1884
1871
  readonly tables: ReadonlyMap<string, IndexedDbVersion.Tables<Source>>
1885
- readonly transaction: globalThis.IDBTransaction | undefined
1886
1872
  readonly reactivity: Reactivity.Reactivity["Service"]
1887
1873
  }): IndexedDbQueryBuilder<Source> => {
1888
1874
  const self = Object.create(QueryBuilderProto)
@@ -1890,6 +1876,15 @@ export const make = <Source extends IndexedDbVersion.AnyWithProps>({
1890
1876
  self.database = database
1891
1877
  self.reactivity = reactivity
1892
1878
  self.IDBKeyRange = IDBKeyRange
1893
- self.IDBTransaction = transaction
1894
1879
  return self
1895
1880
  }
1881
+
1882
+ const getOrCreateTransaction = (
1883
+ database: globalThis.IDBDatabase,
1884
+ tables: ReadonlyArray<string>,
1885
+ mode: globalThis.IDBTransactionMode,
1886
+ options?: IDBTransactionOptions
1887
+ ) => {
1888
+ const fiber = Fiber.getCurrent()!
1889
+ return Context.getOrUndefined(fiber.context, IndexedDbTransaction) ?? database.transaction(tables, mode, options)
1890
+ }