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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/BrowserHttpClient.d.ts +3 -3
  2. package/dist/BrowserHttpClient.d.ts.map +1 -1
  3. package/dist/BrowserHttpClient.js +11 -6
  4. package/dist/BrowserHttpClient.js.map +1 -1
  5. package/dist/BrowserPersistence.d.ts +17 -0
  6. package/dist/BrowserPersistence.d.ts.map +1 -0
  7. package/dist/BrowserPersistence.js +184 -0
  8. package/dist/BrowserPersistence.js.map +1 -0
  9. package/dist/BrowserWorkerRunner.js +1 -1
  10. package/dist/BrowserWorkerRunner.js.map +1 -1
  11. package/dist/Clipboard.d.ts +6 -3
  12. package/dist/Clipboard.d.ts.map +1 -1
  13. package/dist/Clipboard.js +2 -2
  14. package/dist/Clipboard.js.map +1 -1
  15. package/dist/Geolocation.d.ts +6 -6
  16. package/dist/Geolocation.d.ts.map +1 -1
  17. package/dist/Geolocation.js +2 -2
  18. package/dist/Geolocation.js.map +1 -1
  19. package/dist/IndexedDb.d.ts +50 -0
  20. package/dist/IndexedDb.d.ts.map +1 -0
  21. package/dist/IndexedDb.js +65 -0
  22. package/dist/IndexedDb.js.map +1 -0
  23. package/dist/IndexedDbDatabase.d.ts +103 -0
  24. package/dist/IndexedDbDatabase.d.ts.map +1 -0
  25. package/dist/IndexedDbDatabase.js +291 -0
  26. package/dist/IndexedDbDatabase.js.map +1 -0
  27. package/dist/IndexedDbQueryBuilder.d.ts +342 -0
  28. package/dist/IndexedDbQueryBuilder.d.ts.map +1 -0
  29. package/dist/IndexedDbQueryBuilder.js +888 -0
  30. package/dist/IndexedDbQueryBuilder.js.map +1 -0
  31. package/dist/IndexedDbTable.d.ts +109 -0
  32. package/dist/IndexedDbTable.d.ts.map +1 -0
  33. package/dist/IndexedDbTable.js +38 -0
  34. package/dist/IndexedDbTable.js.map +1 -0
  35. package/dist/IndexedDbVersion.d.ts +50 -0
  36. package/dist/IndexedDbVersion.d.ts.map +1 -0
  37. package/dist/IndexedDbVersion.js +23 -0
  38. package/dist/IndexedDbVersion.js.map +1 -0
  39. package/dist/Permissions.d.ts +8 -5
  40. package/dist/Permissions.d.ts.map +1 -1
  41. package/dist/Permissions.js +2 -2
  42. package/dist/Permissions.js.map +1 -1
  43. package/dist/index.d.ts +24 -0
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +24 -0
  46. package/dist/index.js.map +1 -1
  47. package/package.json +4 -3
  48. package/src/BrowserHttpClient.ts +17 -10
  49. package/src/BrowserPersistence.ts +303 -0
  50. package/src/BrowserWorkerRunner.ts +1 -1
  51. package/src/Clipboard.ts +2 -2
  52. package/src/Geolocation.ts +2 -2
  53. package/src/IndexedDb.ts +97 -0
  54. package/src/IndexedDbDatabase.ts +598 -0
  55. package/src/IndexedDbQueryBuilder.ts +1904 -0
  56. package/src/IndexedDbTable.ts +203 -0
  57. package/src/IndexedDbVersion.ts +89 -0
  58. package/src/Permissions.ts +2 -2
  59. package/src/index.ts +30 -0
@@ -0,0 +1,598 @@
1
+ /**
2
+ * @since 4.0.0
3
+ */
4
+ import * as Context from "effect/Context"
5
+ import * as Data from "effect/Data"
6
+ import * as Effect from "effect/Effect"
7
+ import * as Effectable from "effect/Effectable"
8
+ import * as Fiber from "effect/Fiber"
9
+ import * as Layer from "effect/Layer"
10
+ import * as MutableRef from "effect/MutableRef"
11
+ import * as Semaphore from "effect/Semaphore"
12
+ import * as Reactivity from "effect/unstable/reactivity/Reactivity"
13
+ import * as IndexedDb from "./IndexedDb.ts"
14
+ import * as IndexedDbQueryBuilder from "./IndexedDbQueryBuilder.ts"
15
+ import type * as IndexedDbTable from "./IndexedDbTable.ts"
16
+ import type * as IndexedDbVersion from "./IndexedDbVersion.ts"
17
+
18
+ const TypeId = "~@effect/platform-browser/IndexedDbDatabase"
19
+ const ErrorTypeId = "~@effect/platform-browser/IndexedDbDatabase/IndexedDbDatabaseError"
20
+
21
+ const SchemaProto = {
22
+ [TypeId]: {
23
+ _A: (_: never) => _
24
+ },
25
+ ...Effectable.Prototype<IndexedDbSchema<any, any, any>>({
26
+ label: "IndexedDbSchema",
27
+ evaluate() {
28
+ return this.getQueryBuilder
29
+ }
30
+ }),
31
+ get getQueryBuilder() {
32
+ const self = this as unknown as IndexedDbSchema<any, any, any>
33
+ return IndexedDbDatabase.useSync(({ database, IDBKeyRange, reactivity }) =>
34
+ IndexedDbQueryBuilder.make({
35
+ database,
36
+ IDBKeyRange,
37
+ tables: self.version.tables,
38
+ reactivity
39
+ })
40
+ )
41
+ },
42
+ add<Version extends IndexedDbVersion.AnyWithProps>(
43
+ this: IndexedDbSchema<any, any, any>,
44
+ version: Version,
45
+ migrate: (
46
+ fromQuery: Transaction<any>,
47
+ toQuery: Transaction<Version>
48
+ ) => Effect.Effect<void, Error>
49
+ ) {
50
+ return makeMigration({
51
+ fromVersion: this.version,
52
+ version,
53
+ migrate,
54
+ previous: this
55
+ })
56
+ },
57
+ layer(this: IndexedDbSchema<any, any, any>, databaseName: string) {
58
+ return layer(databaseName, this)
59
+ }
60
+ }
61
+
62
+ /**
63
+ * @since 4.0.0
64
+ * @category errors
65
+ */
66
+ export type ErrorReason =
67
+ | "TransactionError"
68
+ | "MissingTable"
69
+ | "OpenError"
70
+ | "UpgradeError"
71
+ | "Aborted"
72
+ | "Blocked"
73
+ | "MissingIndex"
74
+
75
+ /**
76
+ * @since 4.0.0
77
+ * @category errors
78
+ */
79
+ export class IndexedDbDatabaseError extends Data.TaggedError(
80
+ "IndexedDbDatabaseError"
81
+ )<{
82
+ reason: ErrorReason
83
+ cause: unknown
84
+ }> {
85
+ /**
86
+ * @since 4.0.0
87
+ */
88
+ readonly [ErrorTypeId]: typeof ErrorTypeId = ErrorTypeId
89
+ override readonly message = this.reason
90
+ }
91
+
92
+ /**
93
+ * @since 4.0.0
94
+ * @category models
95
+ */
96
+ export class IndexedDbDatabase extends Context.Service<
97
+ IndexedDbDatabase,
98
+ {
99
+ readonly database: MutableRef.MutableRef<globalThis.IDBDatabase>
100
+ readonly IDBKeyRange: typeof globalThis.IDBKeyRange
101
+ readonly reactivity: Reactivity.Reactivity["Service"]
102
+ readonly rebuild: Effect.Effect<void, IndexedDbDatabaseError>
103
+ }
104
+ >()(TypeId) {}
105
+
106
+ /**
107
+ * @since 4.0.0
108
+ * @category models
109
+ */
110
+ export interface IndexedDbSchema<
111
+ in out FromVersion extends IndexedDbVersion.AnyWithProps,
112
+ in out ToVersion extends IndexedDbVersion.AnyWithProps,
113
+ out Error = never
114
+ > extends
115
+ Effect.Effect<
116
+ IndexedDbQueryBuilder.IndexedDbQueryBuilder<ToVersion>,
117
+ never,
118
+ IndexedDbDatabase
119
+ >
120
+ {
121
+ new(_: never): {}
122
+
123
+ readonly previous: [FromVersion] extends [never] ? undefined
124
+ : IndexedDbSchema<never, FromVersion, Error>
125
+ readonly fromVersion: FromVersion
126
+ readonly version: ToVersion
127
+
128
+ readonly migrate: [FromVersion] extends [never] ? (query: Transaction<ToVersion>) => Effect.Effect<void, Error>
129
+ : (
130
+ fromQuery: Transaction<FromVersion>,
131
+ toQuery: Transaction<ToVersion>
132
+ ) => Effect.Effect<void, Error>
133
+
134
+ readonly add: <Version extends IndexedDbVersion.AnyWithProps, MigrationError>(
135
+ version: Version,
136
+ migrate: (
137
+ fromQuery: Transaction<ToVersion>,
138
+ toQuery: Transaction<Version>
139
+ ) => Effect.Effect<void, MigrationError>
140
+ ) => IndexedDbSchema<ToVersion, Version, MigrationError | Error>
141
+
142
+ readonly getQueryBuilder: Effect.Effect<
143
+ IndexedDbQueryBuilder.IndexedDbQueryBuilder<ToVersion>,
144
+ never,
145
+ IndexedDbDatabase
146
+ >
147
+
148
+ readonly layer: (
149
+ databaseName: string
150
+ ) => Layer.Layer<
151
+ IndexedDbDatabase,
152
+ IndexedDbDatabaseError,
153
+ IndexedDb.IndexedDb
154
+ >
155
+ }
156
+
157
+ /**
158
+ * @since 4.0.0
159
+ * @category models
160
+ */
161
+ export interface Transaction<
162
+ Source extends IndexedDbVersion.AnyWithProps = never
163
+ > extends Omit<IndexedDbQueryBuilder.IndexedDbQueryBuilder<Source>, "transaction"> {
164
+ readonly transaction: globalThis.IDBTransaction
165
+
166
+ readonly createObjectStore: <
167
+ A extends IndexedDbTable.TableName<IndexedDbVersion.Tables<Source>>
168
+ >(
169
+ table: A
170
+ ) => Effect.Effect<globalThis.IDBObjectStore, IndexedDbDatabaseError>
171
+
172
+ readonly deleteObjectStore: <
173
+ A extends IndexedDbTable.TableName<IndexedDbVersion.Tables<Source>>
174
+ >(
175
+ table: A
176
+ ) => Effect.Effect<void, IndexedDbDatabaseError>
177
+
178
+ readonly createIndex: <
179
+ Name extends IndexedDbTable.TableName<IndexedDbVersion.Tables<Source>>
180
+ >(
181
+ table: Name,
182
+ indexName: IndexFromTableName<Source, Name>,
183
+ options?: IDBIndexParameters
184
+ ) => Effect.Effect<globalThis.IDBIndex, IndexedDbDatabaseError>
185
+
186
+ readonly deleteIndex: <
187
+ Name extends IndexedDbTable.TableName<IndexedDbVersion.Tables<Source>>
188
+ >(
189
+ table: Name,
190
+ indexName: IndexFromTableName<Source, Name>
191
+ ) => Effect.Effect<void, IndexedDbDatabaseError>
192
+ }
193
+
194
+ /**
195
+ * @since 4.0.0
196
+ * @category models
197
+ */
198
+ export type IndexFromTable<Table extends IndexedDbTable.AnyWithProps> = IsStringLiteral<
199
+ Extract<keyof IndexedDbTable.Indexes<Table>, string>
200
+ > extends true ? Extract<keyof IndexedDbTable.Indexes<Table>, string>
201
+ : never
202
+
203
+ /**
204
+ * @since 4.0.0
205
+ * @category models
206
+ */
207
+ export type IndexFromTableName<
208
+ Version extends IndexedDbVersion.AnyWithProps,
209
+ Table extends string
210
+ > = IndexFromTable<
211
+ IndexedDbTable.WithName<IndexedDbVersion.Tables<Version>, Table>
212
+ >
213
+
214
+ /**
215
+ * @since 4.0.0
216
+ * @category models
217
+ */
218
+ export interface Any {
219
+ readonly previous?: Any | undefined
220
+ readonly layer: (
221
+ databaseName: string
222
+ ) => Layer.Layer<
223
+ IndexedDbDatabase,
224
+ IndexedDbDatabaseError,
225
+ IndexedDb.IndexedDb
226
+ >
227
+ }
228
+
229
+ /**
230
+ * @since 4.0.0
231
+ * @category models
232
+ */
233
+ export type AnySchema = IndexedDbSchema<
234
+ IndexedDbVersion.AnyWithProps,
235
+ IndexedDbVersion.AnyWithProps,
236
+ any
237
+ >
238
+
239
+ /**
240
+ * @since 4.0.0
241
+ * @category constructors
242
+ */
243
+ export const make = <
244
+ InitialVersion extends IndexedDbVersion.AnyWithProps,
245
+ Error
246
+ >(
247
+ initialVersion: InitialVersion,
248
+ init: (toQuery: Transaction<InitialVersion>) => Effect.Effect<void, Error>
249
+ ): IndexedDbSchema<never, InitialVersion, Error> => {
250
+ // oxlint-disable-next-line typescript/no-extraneous-class
251
+ function Initial() {}
252
+ Object.setPrototypeOf(Initial, SchemaProto)
253
+ ;(Initial as any).version = initialVersion
254
+ ;(Initial as any).migrate = init
255
+ return Initial as any
256
+ }
257
+
258
+ const makeMigration = <
259
+ FromVersion extends IndexedDbVersion.AnyWithProps,
260
+ ToVersion extends IndexedDbVersion.AnyWithProps,
261
+ Error
262
+ >(options: {
263
+ readonly previous:
264
+ | IndexedDbSchema<FromVersion, ToVersion, Error>
265
+ | IndexedDbSchema<never, FromVersion, Error>
266
+ readonly fromVersion: FromVersion
267
+ readonly version: ToVersion
268
+ readonly migrate: (
269
+ fromQuery: Transaction<FromVersion>,
270
+ toQuery: Transaction<ToVersion>
271
+ ) => Effect.Effect<void, Error>
272
+ }): IndexedDbSchema<FromVersion, ToVersion, Error> => {
273
+ // oxlint-disable-next-line typescript/no-extraneous-class
274
+ function Migration() {}
275
+ Object.setPrototypeOf(Migration, SchemaProto)
276
+ ;(Migration as any).previous = options.previous
277
+ ;(Migration as any).fromVersion = options.fromVersion
278
+ ;(Migration as any).version = options.version
279
+ ;(Migration as any).migrate = options.migrate
280
+
281
+ return Migration as any
282
+ }
283
+
284
+ const layer = <DatabaseName extends string>(
285
+ databaseName: DatabaseName,
286
+ migration: Any
287
+ ) =>
288
+ Layer.effect(
289
+ IndexedDbDatabase,
290
+ Effect.gen(function*() {
291
+ const { IDBKeyRange, indexedDB } = yield* IndexedDb.IndexedDb
292
+ const reactivity = yield* Reactivity.Reactivity
293
+ const context = yield* Effect.context()
294
+ const runForkWith = Effect.runForkWith(context)
295
+
296
+ let oldVersion = 0
297
+ const migrations: Array<Any> = []
298
+ let current = migration
299
+ while (current) {
300
+ migrations.unshift(current)
301
+ current = (current as unknown as AnySchema).previous as any
302
+ }
303
+
304
+ const version = migrations.length
305
+ const database = MutableRef.make<globalThis.IDBDatabase>(null as any)
306
+
307
+ const open = Effect.callback<
308
+ void,
309
+ IndexedDbDatabaseError
310
+ >((resume) => {
311
+ const request = indexedDB.open(databaseName, version)
312
+
313
+ request.onblocked = (event) => {
314
+ resume(
315
+ Effect.fail(
316
+ new IndexedDbDatabaseError({
317
+ reason: "Blocked",
318
+ cause: event
319
+ })
320
+ )
321
+ )
322
+ }
323
+
324
+ request.onerror = (event) => {
325
+ const idbRequest = event.target as IDBRequest<IDBDatabase>
326
+
327
+ resume(
328
+ Effect.fail(
329
+ new IndexedDbDatabaseError({
330
+ reason: "OpenError",
331
+ cause: idbRequest.error
332
+ })
333
+ )
334
+ )
335
+ }
336
+
337
+ let fiber: Fiber.Fiber<void, IndexedDbDatabaseError> | undefined
338
+ request.onupgradeneeded = (event) => {
339
+ const idbRequest = event.target as IDBRequest<IDBDatabase>
340
+ const db = idbRequest.result
341
+ const transaction = idbRequest.transaction
342
+ oldVersion = event.oldVersion
343
+
344
+ MutableRef.set(database, db)
345
+
346
+ if (transaction === null) {
347
+ return resume(
348
+ Effect.fail(
349
+ new IndexedDbDatabaseError({
350
+ reason: "TransactionError",
351
+ cause: null
352
+ })
353
+ )
354
+ )
355
+ }
356
+
357
+ transaction.onabort = (event) => {
358
+ resume(
359
+ Effect.fail(
360
+ new IndexedDbDatabaseError({
361
+ reason: "Aborted",
362
+ cause: event
363
+ })
364
+ )
365
+ )
366
+ }
367
+
368
+ transaction.onerror = (event) => {
369
+ resume(
370
+ Effect.fail(
371
+ new IndexedDbDatabaseError({
372
+ reason: "TransactionError",
373
+ cause: event
374
+ })
375
+ )
376
+ )
377
+ }
378
+
379
+ const effect = Effect.forEach(
380
+ migrations.slice(oldVersion),
381
+ (untypedMigration) => {
382
+ if (untypedMigration.previous === undefined) {
383
+ const migration = untypedMigration as any as AnySchema
384
+ const api = makeTransactionProto({
385
+ database,
386
+ IDBKeyRange,
387
+ tables: migration.version.tables,
388
+ transaction,
389
+ reactivity
390
+ })
391
+ return (migration as any).migrate(api) as Effect.Effect<
392
+ void,
393
+ IndexedDbDatabaseError
394
+ >
395
+ } else if (untypedMigration.previous) {
396
+ const migration = untypedMigration as any as AnySchema
397
+ const fromApi = makeTransactionProto({
398
+ database,
399
+ IDBKeyRange,
400
+ tables: migration.fromVersion.tables,
401
+ transaction,
402
+ reactivity
403
+ })
404
+ const toApi = makeTransactionProto({
405
+ database,
406
+ IDBKeyRange,
407
+ tables: migration.version.tables,
408
+ transaction,
409
+ reactivity
410
+ })
411
+ return migration.migrate(fromApi, toApi) as Effect.Effect<
412
+ void,
413
+ IndexedDbDatabaseError
414
+ >
415
+ }
416
+
417
+ return Effect.die(new Error("Invalid migration"))
418
+ },
419
+ { discard: true }
420
+ ).pipe(
421
+ Effect.mapError(
422
+ (cause) =>
423
+ new IndexedDbDatabaseError({
424
+ reason: "UpgradeError",
425
+ cause
426
+ })
427
+ ),
428
+ Effect.provideService(IndexedDbQueryBuilder.IndexedDbTransaction, transaction)
429
+ )
430
+ fiber = runForkWith(effect)
431
+ fiber.currentDispatcher.flush()
432
+ }
433
+
434
+ request.onsuccess = (event) => {
435
+ const idbRequest = event.target as IDBRequest<IDBDatabase>
436
+ const db = idbRequest.result
437
+ MutableRef.set(database, db)
438
+ if (fiber) {
439
+ // ensure migration errors are propagated
440
+ resume(Effect.asVoid(Fiber.join(fiber)))
441
+ } else {
442
+ resume(Effect.void)
443
+ }
444
+ }
445
+ })
446
+
447
+ yield* Effect.addFinalizer(() => {
448
+ database.current?.close()
449
+ return Effect.void
450
+ })
451
+ yield* open
452
+
453
+ const rebuildLock = Semaphore.makeUnsafe(1).withPermit
454
+ const rebuild = Effect.callback<void, IndexedDbDatabaseError>((resume) => {
455
+ database.current?.close()
456
+ const request = indexedDB.deleteDatabase(databaseName)
457
+ request.onerror = (_) => {
458
+ resume(
459
+ Effect.fail(
460
+ new IndexedDbDatabaseError({
461
+ reason: "OpenError",
462
+ cause: request.error
463
+ })
464
+ )
465
+ )
466
+ }
467
+ request.onsuccess = () => {
468
+ resume(Effect.void)
469
+ }
470
+ }).pipe(
471
+ Effect.flatMap(() => open),
472
+ rebuildLock
473
+ )
474
+
475
+ return IndexedDbDatabase.of({ database, IDBKeyRange, rebuild, reactivity })
476
+ })
477
+ ).pipe(
478
+ Layer.provide(Reactivity.layer)
479
+ )
480
+
481
+ // -----------------------------------------------------------------------------
482
+ // Internal
483
+ // -----------------------------------------------------------------------------
484
+
485
+ type IsStringLiteral<T> = T extends string ? string extends T ? false
486
+ : true
487
+ : false
488
+
489
+ const makeTransactionProto = <Source extends IndexedDbVersion.AnyWithProps>({
490
+ IDBKeyRange,
491
+ database,
492
+ tables,
493
+ transaction,
494
+ reactivity
495
+ }: {
496
+ readonly database: MutableRef.MutableRef<globalThis.IDBDatabase>
497
+ readonly IDBKeyRange: typeof globalThis.IDBKeyRange
498
+ readonly tables: ReadonlyMap<string, IndexedDbVersion.Tables<Source>>
499
+ readonly transaction: globalThis.IDBTransaction
500
+ readonly reactivity: Reactivity.Reactivity["Service"]
501
+ }): Transaction<Source> => {
502
+ const migration = IndexedDbQueryBuilder.make({
503
+ database,
504
+ IDBKeyRange,
505
+ tables,
506
+ reactivity
507
+ }) as any
508
+
509
+ migration.transaction = transaction
510
+
511
+ migration.createObjectStore = Effect.fnUntraced(function*(table: string) {
512
+ const createTable = yield* Effect.fromNullishOr(tables.get(table)).pipe(
513
+ Effect.mapError(
514
+ (cause) =>
515
+ new IndexedDbDatabaseError({
516
+ reason: "MissingTable",
517
+ cause
518
+ })
519
+ )
520
+ )
521
+
522
+ return yield* Effect.try({
523
+ try: () =>
524
+ database.current.createObjectStore(createTable.tableName, {
525
+ keyPath: createTable.keyPath,
526
+ autoIncrement: createTable.autoIncrement
527
+ }),
528
+ catch: (cause) =>
529
+ new IndexedDbDatabaseError({
530
+ reason: "TransactionError",
531
+ cause
532
+ })
533
+ })
534
+ })
535
+
536
+ migration.deleteObjectStore = Effect.fnUntraced(function*(table: string) {
537
+ const createTable = yield* Effect.fromNullishOr(tables.get(table)).pipe(
538
+ Effect.mapError(
539
+ (cause) =>
540
+ new IndexedDbDatabaseError({
541
+ reason: "MissingTable",
542
+ cause
543
+ })
544
+ )
545
+ )
546
+
547
+ return yield* Effect.try({
548
+ try: () => database.current.deleteObjectStore(createTable.tableName),
549
+ catch: (cause) =>
550
+ new IndexedDbDatabaseError({
551
+ reason: "TransactionError",
552
+ cause
553
+ })
554
+ })
555
+ })
556
+
557
+ migration.createIndex = Effect.fnUntraced(function*(
558
+ table: string,
559
+ indexName: string,
560
+ options?: IDBIndexParameters
561
+ ) {
562
+ const store = transaction.objectStore(table)
563
+ const sourceTable = tables.get(table)!
564
+
565
+ const keyPath = yield* Effect.fromNullishOr(
566
+ sourceTable.indexes[indexName]
567
+ ).pipe(
568
+ Effect.mapError(
569
+ (cause) =>
570
+ new IndexedDbDatabaseError({
571
+ reason: "MissingIndex",
572
+ cause
573
+ })
574
+ )
575
+ )
576
+
577
+ return yield* Effect.try({
578
+ try: () => store.createIndex(indexName, keyPath, options),
579
+ catch: (cause) =>
580
+ new IndexedDbDatabaseError({
581
+ reason: "TransactionError",
582
+ cause
583
+ })
584
+ })
585
+ })
586
+
587
+ migration.deleteIndex = (table: string, indexName: string) =>
588
+ Effect.try({
589
+ try: () => transaction.objectStore(table).deleteIndex(indexName),
590
+ catch: (cause) =>
591
+ new IndexedDbDatabaseError({
592
+ reason: "TransactionError",
593
+ cause
594
+ })
595
+ })
596
+
597
+ return migration
598
+ }