@effect/platform-browser 4.0.0-beta.66 → 4.0.0-beta.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/dist/BrowserCrypto.d.ts +23 -0
  2. package/dist/BrowserCrypto.d.ts.map +1 -0
  3. package/dist/BrowserCrypto.js +61 -0
  4. package/dist/BrowserCrypto.js.map +1 -0
  5. package/dist/BrowserHttpClient.d.ts +23 -13
  6. package/dist/BrowserHttpClient.d.ts.map +1 -1
  7. package/dist/BrowserHttpClient.js +49 -12
  8. package/dist/BrowserHttpClient.js.map +1 -1
  9. package/dist/BrowserKeyValueStore.d.ts +15 -8
  10. package/dist/BrowserKeyValueStore.d.ts.map +1 -1
  11. package/dist/BrowserKeyValueStore.js +128 -4
  12. package/dist/BrowserKeyValueStore.js.map +1 -1
  13. package/dist/BrowserPersistence.d.ts +6 -2
  14. package/dist/BrowserPersistence.d.ts.map +1 -1
  15. package/dist/BrowserPersistence.js +6 -2
  16. package/dist/BrowserPersistence.js.map +1 -1
  17. package/dist/BrowserRuntime.d.ts +31 -4
  18. package/dist/BrowserRuntime.d.ts.map +1 -1
  19. package/dist/BrowserRuntime.js +3 -1
  20. package/dist/BrowserRuntime.js.map +1 -1
  21. package/dist/BrowserSocket.d.ts +31 -6
  22. package/dist/BrowserSocket.d.ts.map +1 -1
  23. package/dist/BrowserSocket.js +31 -6
  24. package/dist/BrowserSocket.js.map +1 -1
  25. package/dist/BrowserStream.d.ts +25 -3
  26. package/dist/BrowserStream.d.ts.map +1 -1
  27. package/dist/BrowserStream.js +25 -3
  28. package/dist/BrowserStream.js.map +1 -1
  29. package/dist/BrowserWorker.d.ts +8 -4
  30. package/dist/BrowserWorker.d.ts.map +1 -1
  31. package/dist/BrowserWorker.js +29 -5
  32. package/dist/BrowserWorker.js.map +1 -1
  33. package/dist/BrowserWorkerRunner.d.ts +12 -6
  34. package/dist/BrowserWorkerRunner.d.ts.map +1 -1
  35. package/dist/BrowserWorkerRunner.js +31 -7
  36. package/dist/BrowserWorkerRunner.js.map +1 -1
  37. package/dist/Clipboard.d.ts +35 -11
  38. package/dist/Clipboard.d.ts.map +1 -1
  39. package/dist/Clipboard.js +31 -9
  40. package/dist/Clipboard.js.map +1 -1
  41. package/dist/Geolocation.d.ts +52 -18
  42. package/dist/Geolocation.d.ts.map +1 -1
  43. package/dist/Geolocation.js +44 -14
  44. package/dist/Geolocation.js.map +1 -1
  45. package/dist/IndexedDb.d.ts +38 -11
  46. package/dist/IndexedDb.d.ts.map +1 -1
  47. package/dist/IndexedDb.js +35 -13
  48. package/dist/IndexedDb.js.map +1 -1
  49. package/dist/IndexedDbDatabase.d.ts +57 -10
  50. package/dist/IndexedDbDatabase.d.ts.map +1 -1
  51. package/dist/IndexedDbDatabase.js +36 -3
  52. package/dist/IndexedDbDatabase.js.map +1 -1
  53. package/dist/IndexedDbQueryBuilder.d.ts +102 -28
  54. package/dist/IndexedDbQueryBuilder.d.ts.map +1 -1
  55. package/dist/IndexedDbQueryBuilder.js +56 -26
  56. package/dist/IndexedDbQueryBuilder.js.map +1 -1
  57. package/dist/IndexedDbTable.d.ts +57 -13
  58. package/dist/IndexedDbTable.d.ts.map +1 -1
  59. package/dist/IndexedDbTable.js +21 -1
  60. package/dist/IndexedDbTable.js.map +1 -1
  61. package/dist/IndexedDbVersion.d.ts +37 -7
  62. package/dist/IndexedDbVersion.d.ts.map +1 -1
  63. package/dist/IndexedDbVersion.js +3 -1
  64. package/dist/IndexedDbVersion.js.map +1 -1
  65. package/dist/Permissions.d.ts +38 -11
  66. package/dist/Permissions.d.ts.map +1 -1
  67. package/dist/Permissions.js +33 -8
  68. package/dist/Permissions.js.map +1 -1
  69. package/dist/index.d.ts +334 -11
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +334 -11
  72. package/dist/index.js.map +1 -1
  73. package/package.json +3 -3
  74. package/src/BrowserCrypto.ts +71 -0
  75. package/src/BrowserHttpClient.ts +53 -14
  76. package/src/BrowserKeyValueStore.ts +144 -6
  77. package/src/BrowserPersistence.ts +19 -3
  78. package/src/BrowserRuntime.ts +31 -4
  79. package/src/BrowserSocket.ts +31 -6
  80. package/src/BrowserStream.ts +25 -3
  81. package/src/BrowserWorker.ts +29 -5
  82. package/src/BrowserWorkerRunner.ts +31 -7
  83. package/src/Clipboard.ts +35 -11
  84. package/src/Geolocation.ts +52 -18
  85. package/src/IndexedDb.ts +39 -21
  86. package/src/IndexedDbDatabase.ts +57 -10
  87. package/src/IndexedDbQueryBuilder.ts +171 -58
  88. package/src/IndexedDbTable.ts +57 -13
  89. package/src/IndexedDbVersion.ts +37 -7
  90. package/src/Permissions.ts +38 -11
  91. package/src/index.ts +335 -11
@@ -1,7 +1,34 @@
1
1
  /**
2
+ * Builds effectful, schema-aware queries for typed browser IndexedDB versions.
3
+ *
4
+ * An `IndexedDbQueryBuilder` is created from an open database and a version's
5
+ * table descriptors, then exposes `from(tableName)` as the entry point for
6
+ * table operations. The resulting query objects can select, count, delete,
7
+ * insert, upsert, clear tables, stream paged reads, react to invalidations, and
8
+ * run multiple effects in a shared `IDBTransaction` with `withTransaction`.
9
+ *
10
+ * Use this module for local browser persistence such as caches, offline-first
11
+ * state, background queues, drafts, and other client-side data where writes
12
+ * should be encoded through `Schema` and reads should be decoded before they
13
+ * reach application code.
14
+ *
15
+ * Index and range helpers are thinly typed wrappers around IndexedDB object
16
+ * stores, indexes, `IDBKeyRange`, and cursors. Index names must be declared on
17
+ * the table and created during migrations; without an index, queries use the
18
+ * object store key path. Range values are encoded IndexedDB key values, and
19
+ * compound key paths must follow the declared key order. Filters, offsets,
20
+ * reverse reads, out-of-line keys, and limited deletes require cursor-based
21
+ * scans, while simpler selects can use `getAll`.
22
+ *
23
+ * Table schema details affect runtime behavior: auto-increment writes may omit
24
+ * the generated numeric key, stores without a key path require an out-of-line
25
+ * `key` for writes and add that `key` back to selected rows, and schema
26
+ * mismatches surface as `EncodeError` or `DecodeError` query failures.
27
+ *
2
28
  * @since 4.0.0
3
29
  */
4
30
  import type { NonEmptyReadonlyArray } from "effect/Array"
31
+ import * as Cause from "effect/Cause"
5
32
  import * as Context from "effect/Context"
6
33
  import * as Data from "effect/Data"
7
34
  import * as Effect from "effect/Effect"
@@ -43,19 +70,22 @@ const CommonProto = {
43
70
  }
44
71
 
45
72
  /**
46
- * @since 4.0.0
73
+ * String union describing IndexedDB query failure categories such as decoding, encoding, and transaction errors.
74
+ *
47
75
  * @category errors
76
+ * @since 4.0.0
48
77
  */
49
78
  export type ErrorReason =
50
- | "NotFoundError"
51
79
  | "UnknownError"
52
80
  | "DecodeError"
53
81
  | "EncodeError"
54
82
  | "TransactionError"
55
83
 
56
84
  /**
57
- * @since 4.0.0
85
+ * Tagged error for IndexedDB query operations, carrying a query error reason and the original cause.
86
+ *
58
87
  * @category errors
88
+ * @since 4.0.0
59
89
  */
60
90
  export class IndexedDbQueryError extends Data.TaggedError(
61
91
  "IndexedDbQueryError"
@@ -64,6 +94,8 @@ export class IndexedDbQueryError extends Data.TaggedError(
64
94
  cause: unknown
65
95
  }> {
66
96
  /**
97
+ * Marks this value as an IndexedDB query builder error for runtime guards.
98
+ *
67
99
  * @since 4.0.0
68
100
  */
69
101
  readonly [ErrorTypeId]: typeof ErrorTypeId = ErrorTypeId
@@ -72,8 +104,10 @@ export class IndexedDbQueryError extends Data.TaggedError(
72
104
  }
73
105
 
74
106
  /**
75
- * @since 4.0.0
107
+ * Typed query builder for an IndexedDB version, with helpers for table queries, database access, clearing data, and running effects in a shared transaction.
108
+ *
76
109
  * @category models
110
+ * @since 4.0.0
77
111
  */
78
112
  export interface IndexedDbQueryBuilder<
79
113
  Source extends IndexedDbVersion.AnyWithProps
@@ -96,6 +130,9 @@ export interface IndexedDbQueryBuilder<
96
130
  table: Name
97
131
  ) => IndexedDbQuery.From<IndexedDbVersion.TableWithName<Source, Name>>
98
132
 
133
+ /** @internal */
134
+ readonly fromCache: Map<string, IndexedDbQuery.From<IndexedDbVersion.TableWithName<Source, any>>>
135
+
99
136
  readonly clearAll: Effect.Effect<void, IndexedDbQueryError>
100
137
 
101
138
  readonly withTransaction: <
@@ -111,29 +148,36 @@ export interface IndexedDbQueryBuilder<
111
148
  }
112
149
 
113
150
  /**
114
- * @since 4.0.0
151
+ * Valid key-path type for a table schema, using encoded fields whose values are IndexedDB-valid keys.
152
+ *
115
153
  * @category models
154
+ * @since 4.0.0
116
155
  */
117
156
  export type KeyPath<TableSchema extends IndexedDbTable.AnySchemaStruct> =
118
157
  | IndexedDbValidKeys<TableSchema>
119
158
  | NonEmptyReadonlyArray<IndexedDbValidKeys<TableSchema>>
120
159
 
121
160
  /**
122
- * @since 4.0.0
161
+ * Valid numeric key-path type for a table schema, used for auto-increment key paths.
162
+ *
123
163
  * @category models
164
+ * @since 4.0.0
124
165
  */
125
166
  export type KeyPathNumber<TableSchema extends IndexedDbTable.AnySchemaStruct> =
126
167
  | IndexedDbValidNumberKeys<TableSchema>
127
168
  | NonEmptyReadonlyArray<IndexedDbValidNumberKeys<TableSchema>>
128
169
 
129
170
  /**
171
+ * Namespace containing the typed IndexedDB query model interfaces and helper types.
172
+ *
130
173
  * @since 4.0.0
131
- * @category models
132
174
  */
133
175
  export declare namespace IndexedDbQuery {
134
176
  /**
135
- * @since 4.0.0
177
+ * Decoded row type returned by select queries, adding a `key` field when the table does not define a key path.
178
+ *
136
179
  * @category models
180
+ * @since 4.0.0
137
181
  */
138
182
  export type SelectType<
139
183
  Table extends IndexedDbTable.AnyWithProps
@@ -143,8 +187,10 @@ export declare namespace IndexedDbQuery {
143
187
  IndexedDbTable.TableSchema<Table>["Type"]
144
188
 
145
189
  /**
146
- * @since 4.0.0
190
+ * Input type for insert and upsert operations, adjusted for auto-increment keys and out-of-line keys.
191
+ *
147
192
  * @category models
193
+ * @since 4.0.0
148
194
  */
149
195
  export type ModifyType<
150
196
  Table extends IndexedDbTable.AnyWithProps
@@ -175,8 +221,10 @@ export declare namespace IndexedDbQuery {
175
221
  : {})
176
222
 
177
223
  /**
178
- * @since 4.0.0
224
+ * Value type accepted by `equals` comparisons for a table key path or index.
225
+ *
179
226
  * @category models
227
+ * @since 4.0.0
180
228
  */
181
229
  export type EqualsType<
182
230
  Table extends IndexedDbTable.AnyWithProps,
@@ -187,8 +235,10 @@ export declare namespace IndexedDbQuery {
187
235
  : { [I in keyof KeyPath]: KeyPath[I] extends keyof Type ? Type[KeyPath[I]] | [] : never }
188
236
 
189
237
  /**
190
- * @since 4.0.0
238
+ * Value type accepted by range comparisons for a table key path or index, including partial tuples for compound indexes.
239
+ *
191
240
  * @category models
241
+ * @since 4.0.0
192
242
  */
193
243
  export type ExtractIndexType<
194
244
  Table extends IndexedDbTable.AnyWithProps,
@@ -204,14 +254,18 @@ export declare namespace IndexedDbQuery {
204
254
  never
205
255
 
206
256
  /**
207
- * @since 4.0.0
257
+ * Mutation input type for insert and upsert operations, including any required key fields.
258
+ *
208
259
  * @category models
260
+ * @since 4.0.0
209
261
  */
210
262
  export type ModifyWithKey<Table extends IndexedDbTable.AnyWithProps> = ModifyType<Table>
211
263
 
212
264
  /**
213
- * @since 4.0.0
265
+ * Query entry point for a table, exposing clear, select, count, delete, insert, and upsert operations.
266
+ *
214
267
  * @category models
268
+ * @since 4.0.0
215
269
  */
216
270
  export interface From<Table extends IndexedDbTable.AnyWithProps> {
217
271
  readonly table: Table
@@ -228,6 +282,12 @@ export declare namespace IndexedDbQuery {
228
282
  (): Select<Table, never>
229
283
  }
230
284
 
285
+ /** @internal */
286
+ readonly selectCache: Map<
287
+ string | undefined,
288
+ IndexedDbQuery.Select<any, never>
289
+ >
290
+
231
291
  readonly count: {
232
292
  <Index extends IndexedDbDatabase.IndexFromTable<Table>>(
233
293
  index: Index
@@ -235,6 +295,12 @@ export declare namespace IndexedDbQuery {
235
295
  (): Count<Table, never>
236
296
  }
237
297
 
298
+ /** @internal */
299
+ readonly countCache: Map<
300
+ string | undefined,
301
+ IndexedDbQuery.Count<any, never>
302
+ >
303
+
238
304
  readonly delete: {
239
305
  <Index extends IndexedDbDatabase.IndexFromTable<Table>>(
240
306
  index: Index
@@ -242,6 +308,12 @@ export declare namespace IndexedDbQuery {
242
308
  (): DeletePartial<Table, never>
243
309
  }
244
310
 
311
+ /** @internal */
312
+ readonly deleteCache: Map<
313
+ string | undefined,
314
+ IndexedDbQuery.DeletePartial<any, never>
315
+ >
316
+
245
317
  readonly insert: (value: ModifyWithKey<Table>) => Modify<Table>
246
318
  readonly insertAll: (
247
319
  values: Array<ModifyWithKey<Table>>
@@ -253,8 +325,10 @@ export declare namespace IndexedDbQuery {
253
325
  }
254
326
 
255
327
  /**
256
- * @since 4.0.0
328
+ * Effect model for clearing all rows from a table.
329
+ *
257
330
  * @category models
331
+ * @since 4.0.0
258
332
  */
259
333
  export interface Clear<
260
334
  Table extends IndexedDbTable.AnyWithProps
@@ -265,8 +339,10 @@ export declare namespace IndexedDbQuery {
265
339
  type ComparisonKeys = "equals" | "gte" | "lte" | "gt" | "lt" | "between"
266
340
 
267
341
  /**
268
- * @since 4.0.0
342
+ * Effect model for counting table rows, optionally constrained by an index and key-range comparisons.
343
+ *
269
344
  * @category models
345
+ * @since 4.0.0
270
346
  */
271
347
  export interface Count<
272
348
  Table extends IndexedDbTable.AnyWithProps,
@@ -308,8 +384,10 @@ export declare namespace IndexedDbQuery {
308
384
  }
309
385
 
310
386
  /**
311
- * @since 4.0.0
387
+ * Intermediate delete builder used to choose a key range or limit before producing an executable delete query.
388
+ *
312
389
  * @category models
390
+ * @since 4.0.0
313
391
  */
314
392
  export interface DeletePartial<
315
393
  Table extends IndexedDbTable.AnyWithProps,
@@ -356,8 +434,10 @@ export declare namespace IndexedDbQuery {
356
434
  > = Omit<Delete<Table, Index, ExcludedKeys>, ExcludedKeys>
357
435
 
358
436
  /**
359
- * @since 4.0.0
437
+ * Effect model for deleting rows from a table, with optional key-range, limit, filter, and reactivity invalidation helpers.
438
+ *
360
439
  * @category models
440
+ * @since 4.0.0
361
441
  */
362
442
  export interface Delete<
363
443
  Table extends IndexedDbTable.AnyWithProps,
@@ -399,8 +479,10 @@ export declare namespace IndexedDbQuery {
399
479
  > = Omit<Select<Table, Index, ExcludedKeys>, ExcludedKeys>
400
480
 
401
481
  /**
402
- * @since 4.0.0
482
+ * Effect model for selecting rows from a table, with chainable range, paging, filtering, streaming, and reactive query helpers.
483
+ *
403
484
  * @category models
485
+ * @since 4.0.0
404
486
  */
405
487
  export interface Select<
406
488
  Table extends IndexedDbTable.AnyWithProps,
@@ -502,8 +584,10 @@ export declare namespace IndexedDbQuery {
502
584
  }
503
585
 
504
586
  /**
505
- * @since 4.0.0
587
+ * Effect model for selecting the first matching row, failing with `NoSuchElementError` when no row is found.
588
+ *
506
589
  * @category models
590
+ * @since 4.0.0
507
591
  */
508
592
  export interface First<
509
593
  Table extends IndexedDbTable.AnyWithProps,
@@ -511,7 +595,7 @@ export declare namespace IndexedDbQuery {
511
595
  > extends
512
596
  Effect.Effect<
513
597
  SelectType<Table>,
514
- IndexedDbQueryError,
598
+ IndexedDbQueryError | Cause.NoSuchElementError,
515
599
  IndexedDbTable.Context<Table>
516
600
  >
517
601
  {
@@ -526,7 +610,7 @@ export declare namespace IndexedDbQuery {
526
610
  keys?: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>> | undefined
527
611
  ) => Stream.Stream<
528
612
  SelectType<Table>,
529
- IndexedDbQueryError,
613
+ IndexedDbQueryError | Cause.NoSuchElementError,
530
614
  IndexedDbTable.Context<Table>
531
615
  >
532
616
 
@@ -538,15 +622,17 @@ export declare namespace IndexedDbQuery {
538
622
  readonly reactiveQueue: (
539
623
  keys: ReadonlyArray<unknown> | Record.ReadonlyRecord<string, ReadonlyArray<unknown>>
540
624
  ) => Effect.Effect<
541
- Queue.Dequeue<SelectType<Table>, IndexedDbQueryError>,
625
+ Queue.Dequeue<SelectType<Table>, IndexedDbQueryError | Cause.NoSuchElementError>,
542
626
  never,
543
627
  Scope.Scope | IndexedDbTable.Context<Table>
544
628
  >
545
629
  }
546
630
 
547
631
  /**
548
- * @since 4.0.0
632
+ * Effect model for a select query filtered by one or more predicates over encoded table rows.
633
+ *
549
634
  * @category models
635
+ * @since 4.0.0
550
636
  */
551
637
  export interface Filter<
552
638
  Table extends IndexedDbTable.AnyWithProps,
@@ -566,8 +652,10 @@ export declare namespace IndexedDbQuery {
566
652
  }
567
653
 
568
654
  /**
569
- * @since 4.0.0
655
+ * Effect model for inserting or upserting one row, returning the resulting IndexedDB key and supporting reactivity invalidation.
656
+ *
570
657
  * @category models
658
+ * @since 4.0.0
571
659
  */
572
660
  export interface Modify<
573
661
  Table extends IndexedDbTable.AnyWithProps
@@ -593,8 +681,10 @@ export declare namespace IndexedDbQuery {
593
681
  }
594
682
 
595
683
  /**
596
- * @since 4.0.0
684
+ * Effect model for inserting or upserting multiple rows, returning the resulting IndexedDB keys and supporting reactivity invalidation.
685
+ *
597
686
  * @category models
687
+ * @since 4.0.0
598
688
  */
599
689
  export interface ModifyAll<
600
690
  Table extends IndexedDbTable.AnyWithProps
@@ -621,8 +711,10 @@ export declare namespace IndexedDbQuery {
621
711
  }
622
712
 
623
713
  /**
624
- * @since 4.0.0
714
+ * Service tag for the active `IDBTransaction` used to share a transaction across IndexedDB query effects.
715
+ *
625
716
  * @category models
717
+ * @since 4.0.0
626
718
  */
627
719
  export class IndexedDbTransaction extends Context.Service<IndexedDbTransaction, globalThis.IDBTransaction>()(
628
720
  "@effect/platform-browser/IndexedDbQueryBuilder/IndexedDbTransaction"
@@ -885,7 +977,7 @@ const applyFirst = Effect.fnUntraced(function*(
885
977
  ) {
886
978
  const keyPath = query.select.from.table.keyPath
887
979
 
888
- const data = yield* Effect.callback<any, IndexedDbQueryError>((resume) => {
980
+ const data = yield* Effect.callback<any, IndexedDbQueryError | Cause.NoSuchElementError>((resume) => {
889
981
  const { keyRange, store } = getReadonlyObjectStore(query.select)
890
982
 
891
983
  if (keyRange !== undefined) {
@@ -925,12 +1017,7 @@ const applyFirst = Effect.fnUntraced(function*(
925
1017
 
926
1018
  if (value === undefined) {
927
1019
  resume(
928
- Effect.fail(
929
- new IndexedDbQueryError({
930
- reason: "NotFoundError",
931
- cause: request.error
932
- })
933
- )
1020
+ Effect.fail(new Cause.NoSuchElementError(`No such element in table ${query.select.from.table.tableName}`))
934
1021
  )
935
1022
  } else {
936
1023
  resume(
@@ -964,15 +1051,11 @@ const applyModify = Effect.fnUntraced(function*({
964
1051
  const autoIncrement = query.from.table.autoIncrement as boolean
965
1052
  const keyPath = query.from.table.keyPath
966
1053
  const table = query.from.table
967
- const schema = autoIncrement && value[keyPath] === undefined
1054
+ const schema: Schema.Top = autoIncrement && value[keyPath] === undefined
968
1055
  ? table.autoincrementSchema
969
1056
  : table.tableSchema
970
1057
 
971
- const encodedValue = yield* SchemaParser.makeEffect(
972
- autoIncrement && value[keyPath] === undefined
973
- ? table.autoincrementSchema
974
- : table.tableSchema
975
- )(value).pipe(
1058
+ const encodedValue = yield* schema.makeEffect(value).pipe(
976
1059
  Effect.flatMap(Schema.encodeUnknownEffect(schema)),
977
1060
  Effect.mapError(
978
1061
  (error) =>
@@ -1229,34 +1312,52 @@ const FromProto: Omit<
1229
1312
  | "IDBKeyRange"
1230
1313
  | "transaction"
1231
1314
  | "reactivity"
1315
+ | "selectCache"
1316
+ | "countCache"
1317
+ | "deleteCache"
1232
1318
  > = {
1233
1319
  ...CommonProto,
1234
1320
  select<Index extends IndexedDbDatabase.IndexFromTable<any>>(
1235
1321
  this: IndexedDbQuery.From<any>,
1236
1322
  index?: Index
1237
1323
  ) {
1238
- return makeSelect({
1239
- from: this,
1240
- index
1241
- }) as any
1324
+ let select = this.selectCache.get(index)
1325
+ if (select === undefined) {
1326
+ select = makeSelect({
1327
+ from: this,
1328
+ index
1329
+ })
1330
+ this.selectCache.set(index, select)
1331
+ }
1332
+ return select
1242
1333
  },
1243
1334
  count<Index extends IndexedDbDatabase.IndexFromTable<any>>(
1244
1335
  this: IndexedDbQuery.From<any>,
1245
1336
  index?: Index
1246
1337
  ) {
1247
- return makeCount({
1248
- from: this,
1249
- index
1250
- }) as any
1338
+ let count = this.countCache.get(index)
1339
+ if (count === undefined) {
1340
+ count = makeCount({
1341
+ from: this,
1342
+ index
1343
+ })
1344
+ this.countCache.set(index, count)
1345
+ }
1346
+ return count
1251
1347
  },
1252
1348
  delete<Index extends IndexedDbDatabase.IndexFromTable<any>>(
1253
1349
  this: IndexedDbQuery.From<any>,
1254
1350
  index?: Index
1255
1351
  ) {
1256
- return makeDeletePartial({
1257
- from: this,
1258
- index
1259
- }) as any
1352
+ let cached = this.deleteCache.get(index)
1353
+ if (cached === undefined) {
1354
+ cached = makeDeletePartial({
1355
+ from: this,
1356
+ index
1357
+ })
1358
+ this.deleteCache.set(index, cached)
1359
+ }
1360
+ return cached
1260
1361
  },
1261
1362
  insert(this: IndexedDbQuery.From<any>, value: any) {
1262
1363
  return makeModify({ from: this, value, operation: "add" })
@@ -1292,6 +1393,9 @@ const makeFrom = <
1292
1393
  self.database = options.database
1293
1394
  self.IDBKeyRange = options.IDBKeyRange
1294
1395
  self.reactivity = options.reactivity
1396
+ self.selectCache = new Map()
1397
+ self.countCache = new Map()
1398
+ self.deleteCache = new Map()
1295
1399
  return self
1296
1400
  }
1297
1401
 
@@ -1825,6 +1929,7 @@ const makeModifyAll = <
1825
1929
 
1826
1930
  const QueryBuilderProto: Omit<
1827
1931
  IndexedDbQueryBuilder<any>,
1932
+ | "fromCache"
1828
1933
  | "tables"
1829
1934
  | "database"
1830
1935
  | "IDBKeyRange"
@@ -1843,12 +1948,17 @@ const QueryBuilderProto: Omit<
1843
1948
  })
1844
1949
  },
1845
1950
  from(this: IndexedDbQueryBuilder<any>, table: any) {
1846
- return makeFrom({
1847
- database: this.database,
1848
- IDBKeyRange: this.IDBKeyRange,
1849
- table: this.tables.get(table)!,
1850
- reactivity: this.reactivity
1851
- }) as any
1951
+ let cached = this.fromCache.get(table)
1952
+ if (cached === undefined) {
1953
+ cached = makeFrom({
1954
+ database: this.database,
1955
+ IDBKeyRange: this.IDBKeyRange,
1956
+ table: this.tables.get(table)!,
1957
+ reactivity: this.reactivity
1958
+ })
1959
+ this.fromCache.set(table, cached)
1960
+ }
1961
+ return cached as any
1852
1962
  },
1853
1963
  get clearAll() {
1854
1964
  const self = this as IndexedDbQueryBuilder<any>
@@ -1871,8 +1981,10 @@ const QueryBuilderProto: Omit<
1871
1981
  }
1872
1982
 
1873
1983
  /**
1874
- * @since 4.0.0
1984
+ * Creates an `IndexedDbQueryBuilder` from an open database reference, key-range constructor, table map, and reactivity service.
1985
+ *
1875
1986
  * @category constructors
1987
+ * @since 4.0.0
1876
1988
  */
1877
1989
  export const make = <Source extends IndexedDbVersion.AnyWithProps>({
1878
1990
  IDBKeyRange,
@@ -1890,6 +2002,7 @@ export const make = <Source extends IndexedDbVersion.AnyWithProps>({
1890
2002
  self.database = database
1891
2003
  self.reactivity = reactivity
1892
2004
  self.IDBKeyRange = IDBKeyRange
2005
+ self.fromCache = new Map()
1893
2006
  return self
1894
2007
  }
1895
2008
 
@@ -1,4 +1,22 @@
1
1
  /**
2
+ * Defines typed table descriptors for the browser IndexedDB integration.
3
+ *
4
+ * An `IndexedDbTable` records the object store name, row schema, primary key
5
+ * path, indexes, auto-increment behavior, and transaction durability used by
6
+ * database versions, migrations, and typed queries. These descriptors are
7
+ * useful for local caches, offline-first application state, background queues,
8
+ * drafts, and other browser-persisted data that should be validated through
9
+ * `Schema`.
10
+ *
11
+ * Key paths and index paths must reference encoded schema fields whose values
12
+ * are valid IndexedDB keys, and compound paths are represented as readonly
13
+ * arrays. Tables without a key path use an out-of-line `key` that is added to
14
+ * reads and required for writes, so the row schema itself cannot define a
15
+ * `key` field. Auto-increment tables require a numeric key path; when that key
16
+ * is omitted on write, the module uses a derived schema without the generated
17
+ * key. Declaring indexes here types query builder index selection, but the
18
+ * indexes still need to be created during database migrations.
19
+ *
2
20
  * @since 4.0.0
3
21
  */
4
22
  import { type Pipeable, pipeArguments } from "effect/Pipeable"
@@ -11,8 +29,10 @@ import type * as IndexedDbQueryBuilder from "./IndexedDbQueryBuilder.ts"
11
29
  const TypeId = "~@effect/platform-browser/IndexedDbTable"
12
30
 
13
31
  /**
14
- * @since 4.0.0
32
+ * Typed IndexedDB table definition containing its name, schema, key path, indexes, auto-increment setting, and transaction durability.
33
+ *
15
34
  * @category interface
35
+ * @since 4.0.0
16
36
  */
17
37
  export interface IndexedDbTable<
18
38
  out Name extends string,
@@ -38,16 +58,20 @@ export interface IndexedDbTable<
38
58
  }
39
59
 
40
60
  /**
41
- * @since 4.0.0
61
+ * Schema constraint for table schemas that expose struct fields.
62
+ *
42
63
  * @category models
64
+ * @since 4.0.0
43
65
  */
44
66
  export type AnySchemaStruct = Schema.Top & {
45
67
  readonly fields: Schema.Struct.Fields
46
68
  }
47
69
 
48
70
  /**
49
- * @since 4.0.0
71
+ * Type-erased shape of an `IndexedDbTable` used when table type parameters are not needed.
72
+ *
50
73
  * @category models
74
+ * @since 4.0.0
51
75
  */
52
76
  export interface Any {
53
77
  readonly [TypeId]: typeof TypeId
@@ -62,8 +86,10 @@ export interface Any {
62
86
  }
63
87
 
64
88
  /**
65
- * @since 4.0.0
89
+ * Type-erased `IndexedDbTable` retaining the table interface properties with broad type parameters.
90
+ *
66
91
  * @category models
92
+ * @since 4.0.0
67
93
  */
68
94
  export type AnyWithProps = IndexedDbTable<
69
95
  string,
@@ -74,50 +100,66 @@ export type AnyWithProps = IndexedDbTable<
74
100
  >
75
101
 
76
102
  /**
77
- * @since 4.0.0
103
+ * Extracts the table name type from an `IndexedDbTable`.
104
+ *
78
105
  * @category models
106
+ * @since 4.0.0
79
107
  */
80
108
  export type TableName<Table extends Any> = Table["tableName"]
81
109
  /**
82
- * @since 4.0.0
110
+ * Extracts the key-path type from an `IndexedDbTable`.
111
+ *
83
112
  * @category models
113
+ * @since 4.0.0
84
114
  */
85
115
  export type KeyPath<Table extends Any> = Table["keyPath"]
86
116
 
87
117
  /**
88
- * @since 4.0.0
118
+ * Extracts the auto-increment flag type from an `IndexedDbTable`.
119
+ *
89
120
  * @category models
121
+ * @since 4.0.0
90
122
  */
91
123
  export type AutoIncrement<Table extends Any> = Table["autoIncrement"]
92
124
 
93
125
  /**
94
- * @since 4.0.0
126
+ * Extracts the schema type from an `IndexedDbTable`.
127
+ *
95
128
  * @category models
129
+ * @since 4.0.0
96
130
  */
97
131
  export type TableSchema<Table extends Any> = Table["tableSchema"]
98
132
  /**
99
- * @since 4.0.0
133
+ * Extracts the decoding or encoding service requirements needed by an `IndexedDbTable` schema.
134
+ *
100
135
  * @category models
136
+ * @since 4.0.0
101
137
  */
102
138
  export type Context<Table extends Any> =
103
139
  | Table["tableSchema"]["DecodingServices"]
104
140
  | Table["tableSchema"]["EncodingServices"]
105
141
 
106
142
  /**
107
- * @since 4.0.0
143
+ * Extracts the encoded row type from an `IndexedDbTable` schema.
144
+ *
108
145
  * @category models
146
+ * @since 4.0.0
109
147
  */
110
148
  export type Encoded<Table extends Any> = Table["tableSchema"]["Encoded"]
111
149
 
112
150
  /**
113
- * @since 4.0.0
151
+ * Extracts the index definition map from an `IndexedDbTable`.
152
+ *
114
153
  * @category models
154
+ * @since 4.0.0
115
155
  */
116
156
  export type Indexes<Table extends Any> = Table["indexes"]
117
157
 
118
158
  /**
119
- * @since 4.0.0
159
+ * Selects the table with the given name from a union of `IndexedDbTable` types.
160
+ *
120
161
  * @category models
162
+ * @since 4.0.0
121
163
  */
122
164
  export type WithName<Table extends Any, TableName extends string> = Extract<
123
165
  Table,
@@ -132,8 +174,10 @@ const Proto = {
132
174
  }
133
175
 
134
176
  /**
135
- * @since 4.0.0
177
+ * Creates a typed IndexedDB table definition from its name, schema, optional key path, indexes, auto-increment flag, and durability.
178
+ *
136
179
  * @category constructors
180
+ * @since 4.0.0
137
181
  */
138
182
  export const make = <
139
183
  const Name extends string,