@effect/platform-browser 4.0.0-beta.7 → 4.0.0-beta.70
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.
- package/dist/BrowserCrypto.d.ts +23 -0
- package/dist/BrowserCrypto.d.ts.map +1 -0
- package/dist/BrowserCrypto.js +61 -0
- package/dist/BrowserCrypto.js.map +1 -0
- package/dist/BrowserHttpClient.d.ts +32 -16
- package/dist/BrowserHttpClient.d.ts.map +1 -1
- package/dist/BrowserHttpClient.js +66 -18
- package/dist/BrowserHttpClient.js.map +1 -1
- package/dist/BrowserKeyValueStore.d.ts +17 -14
- package/dist/BrowserKeyValueStore.d.ts.map +1 -1
- package/dist/BrowserKeyValueStore.js +130 -10
- package/dist/BrowserKeyValueStore.js.map +1 -1
- package/dist/BrowserPersistence.d.ts +21 -0
- package/dist/BrowserPersistence.d.ts.map +1 -0
- package/dist/BrowserPersistence.js +188 -0
- package/dist/BrowserPersistence.js.map +1 -0
- package/dist/BrowserRuntime.d.ts +31 -4
- package/dist/BrowserRuntime.d.ts.map +1 -1
- package/dist/BrowserRuntime.js +3 -1
- package/dist/BrowserRuntime.js.map +1 -1
- package/dist/BrowserSocket.d.ts +31 -6
- package/dist/BrowserSocket.d.ts.map +1 -1
- package/dist/BrowserSocket.js +31 -6
- package/dist/BrowserSocket.js.map +1 -1
- package/dist/BrowserStream.d.ts +33 -5
- package/dist/BrowserStream.d.ts.map +1 -1
- package/dist/BrowserStream.js +33 -5
- package/dist/BrowserStream.js.map +1 -1
- package/dist/BrowserWorker.d.ts +8 -4
- package/dist/BrowserWorker.d.ts.map +1 -1
- package/dist/BrowserWorker.js +30 -6
- package/dist/BrowserWorker.js.map +1 -1
- package/dist/BrowserWorkerRunner.d.ts +12 -6
- package/dist/BrowserWorkerRunner.d.ts.map +1 -1
- package/dist/BrowserWorkerRunner.js +34 -10
- package/dist/BrowserWorkerRunner.js.map +1 -1
- package/dist/Clipboard.d.ts +40 -13
- package/dist/Clipboard.d.ts.map +1 -1
- package/dist/Clipboard.js +33 -11
- package/dist/Clipboard.js.map +1 -1
- package/dist/Geolocation.d.ts +58 -24
- package/dist/Geolocation.d.ts.map +1 -1
- package/dist/Geolocation.js +46 -16
- package/dist/Geolocation.js.map +1 -1
- package/dist/IndexedDb.d.ts +77 -0
- package/dist/IndexedDb.d.ts.map +1 -0
- package/dist/IndexedDb.js +87 -0
- package/dist/IndexedDb.js.map +1 -0
- package/dist/IndexedDbDatabase.d.ts +150 -0
- package/dist/IndexedDbDatabase.d.ts.map +1 -0
- package/dist/IndexedDbDatabase.js +324 -0
- package/dist/IndexedDbDatabase.js.map +1 -0
- package/dist/IndexedDbQueryBuilder.d.ts +430 -0
- package/dist/IndexedDbQueryBuilder.d.ts.map +1 -0
- package/dist/IndexedDbQueryBuilder.js +927 -0
- package/dist/IndexedDbQueryBuilder.js.map +1 -0
- package/dist/IndexedDbTable.d.ts +153 -0
- package/dist/IndexedDbTable.d.ts.map +1 -0
- package/dist/IndexedDbTable.js +58 -0
- package/dist/IndexedDbTable.js.map +1 -0
- package/dist/IndexedDbVersion.d.ts +80 -0
- package/dist/IndexedDbVersion.d.ts.map +1 -0
- package/dist/IndexedDbVersion.js +25 -0
- package/dist/IndexedDbVersion.js.map +1 -0
- package/dist/Permissions.d.ts +45 -15
- package/dist/Permissions.d.ts.map +1 -1
- package/dist/Permissions.js +35 -10
- package/dist/Permissions.js.map +1 -1
- package/dist/index.d.ts +357 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +357 -10
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/BrowserCrypto.ts +71 -0
- package/src/BrowserHttpClient.ts +76 -24
- package/src/BrowserKeyValueStore.ts +146 -12
- package/src/BrowserPersistence.ts +319 -0
- package/src/BrowserRuntime.ts +31 -4
- package/src/BrowserSocket.ts +31 -6
- package/src/BrowserStream.ts +33 -5
- package/src/BrowserWorker.ts +30 -6
- package/src/BrowserWorkerRunner.ts +34 -10
- package/src/Clipboard.ts +37 -13
- package/src/Geolocation.ts +54 -20
- package/src/IndexedDb.ts +115 -0
- package/src/IndexedDbDatabase.ts +645 -0
- package/src/IndexedDbQueryBuilder.ts +2040 -0
- package/src/IndexedDbTable.ts +247 -0
- package/src/IndexedDbVersion.ts +119 -0
- package/src/Permissions.ts +40 -13
- package/src/index.ts +364 -10
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser IndexedDB primitives and key schemas for Effect applications.
|
|
3
|
+
*
|
|
4
|
+
* This module is the low-level bridge used by the platform-browser IndexedDB
|
|
5
|
+
* integration. It provides an `IndexedDb` service around the browser
|
|
6
|
+
* `indexedDB` factory and `IDBKeyRange` constructor, a `layerWindow` layer for
|
|
7
|
+
* wiring those primitives from `window`, and schemas for the key shapes accepted
|
|
8
|
+
* by IndexedDB object stores and indexes.
|
|
9
|
+
*
|
|
10
|
+
* Use it when building typed local persistence for browser caches,
|
|
11
|
+
* offline-first state, background queues, drafts, or other client-side data
|
|
12
|
+
* that should be validated before it reaches IndexedDB. Higher-level database,
|
|
13
|
+
* version, table, and query modules build on these primitives for migrations
|
|
14
|
+
* and typed transactions.
|
|
15
|
+
*
|
|
16
|
+
* IndexedDB still follows the browser rules: schema changes happen only during
|
|
17
|
+
* version upgrades, upgrades may be blocked by other open tabs or connections,
|
|
18
|
+
* and reads or writes must run in transactions scoped to the object stores they
|
|
19
|
+
* touch. The `layerWindow` constructor should be used only where browser
|
|
20
|
+
* globals are available, and code that also runs during SSR or in restricted
|
|
21
|
+
* browser contexts should account for `indexedDB` or `IDBKeyRange` being
|
|
22
|
+
* missing.
|
|
23
|
+
*
|
|
24
|
+
* @since 4.0.0
|
|
25
|
+
*/
|
|
26
|
+
import * as Context from "effect/Context";
|
|
27
|
+
import * as Layer from "effect/Layer";
|
|
28
|
+
import * as Schema from "effect/Schema";
|
|
29
|
+
declare const TypeId = "~@effect/platform-browser/IndexedDb";
|
|
30
|
+
/**
|
|
31
|
+
* Service interface that provides the browser `indexedDB` factory and `IDBKeyRange` constructor.
|
|
32
|
+
*
|
|
33
|
+
* @category models
|
|
34
|
+
* @since 4.0.0
|
|
35
|
+
*/
|
|
36
|
+
export interface IndexedDb {
|
|
37
|
+
readonly [TypeId]: typeof TypeId;
|
|
38
|
+
readonly indexedDB: globalThis.IDBFactory;
|
|
39
|
+
readonly IDBKeyRange: typeof globalThis.IDBKeyRange;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Service tag for browser IndexedDB primitives.
|
|
43
|
+
*
|
|
44
|
+
* @category tag
|
|
45
|
+
* @since 4.0.0
|
|
46
|
+
*/
|
|
47
|
+
export declare const IndexedDb: Context.Service<IndexedDb, IndexedDb>;
|
|
48
|
+
/**
|
|
49
|
+
* Schema for IndexedDB keys: strings, non-NaN numbers, valid dates, buffer sources, or arrays of those flat key values.
|
|
50
|
+
*
|
|
51
|
+
* @category schemas
|
|
52
|
+
* @since 4.0.0
|
|
53
|
+
*/
|
|
54
|
+
export declare const IDBValidKey: Schema.Union<readonly [Schema.Union<readonly [Schema.String, Schema.Number, Schema.DateValid, Schema.declare<BufferSource, unknown>]>, Schema.$Array<Schema.Union<readonly [Schema.String, Schema.Number, Schema.DateValid, Schema.declare<BufferSource, unknown>]>>]>;
|
|
55
|
+
/**
|
|
56
|
+
* Schema for auto-incremented IndexedDB keys, accepting integers from 1 through `2 ** 53`.
|
|
57
|
+
*
|
|
58
|
+
* @category schemas
|
|
59
|
+
* @since 4.0.0
|
|
60
|
+
*/
|
|
61
|
+
export declare const AutoIncrement: Schema.Int;
|
|
62
|
+
/**
|
|
63
|
+
* Creates an `IndexedDb` service from an `IDBFactory` and `IDBKeyRange` constructor.
|
|
64
|
+
*
|
|
65
|
+
* @category constructors
|
|
66
|
+
* @since 4.0.0
|
|
67
|
+
*/
|
|
68
|
+
export declare const make: (impl: Omit<IndexedDb, typeof TypeId>) => IndexedDb;
|
|
69
|
+
/**
|
|
70
|
+
* Layer that provides `IndexedDb` from `window.indexedDB` and `window.IDBKeyRange`, failing with a config error when they are unavailable.
|
|
71
|
+
*
|
|
72
|
+
* @category constructors
|
|
73
|
+
* @since 4.0.0
|
|
74
|
+
*/
|
|
75
|
+
export declare const layerWindow: Layer.Layer<IndexedDb>;
|
|
76
|
+
export {};
|
|
77
|
+
//# sourceMappingURL=IndexedDb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IndexedDb.d.ts","sourceRoot":"","sources":["../src/IndexedDb.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AAEzC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,QAAA,MAAM,MAAM,wCAAwC,CAAA;AAEpD;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,MAAM,CAAA;IAChC,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,UAAU,CAAA;IACzC,QAAQ,CAAC,WAAW,EAAE,OAAO,UAAU,CAAC,WAAW,CAAA;CACpD;AAED;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAiD,CAAA;AAc7G;;;;;GAKG;AACH,eAAO,MAAM,WAAW,wQAAuD,CAAA;AAE/E;;;;;GAKG;AACH,eAAO,MAAM,aAAa,YAMxB,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,MAAM,IAAI,CAAC,SAAS,EAAE,OAAO,MAAM,CAAC,KAAG,SAAwD,CAAA;AAEpH;;;;;GAKG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,CAc9C,CAAA"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser IndexedDB primitives and key schemas for Effect applications.
|
|
3
|
+
*
|
|
4
|
+
* This module is the low-level bridge used by the platform-browser IndexedDB
|
|
5
|
+
* integration. It provides an `IndexedDb` service around the browser
|
|
6
|
+
* `indexedDB` factory and `IDBKeyRange` constructor, a `layerWindow` layer for
|
|
7
|
+
* wiring those primitives from `window`, and schemas for the key shapes accepted
|
|
8
|
+
* by IndexedDB object stores and indexes.
|
|
9
|
+
*
|
|
10
|
+
* Use it when building typed local persistence for browser caches,
|
|
11
|
+
* offline-first state, background queues, drafts, or other client-side data
|
|
12
|
+
* that should be validated before it reaches IndexedDB. Higher-level database,
|
|
13
|
+
* version, table, and query modules build on these primitives for migrations
|
|
14
|
+
* and typed transactions.
|
|
15
|
+
*
|
|
16
|
+
* IndexedDB still follows the browser rules: schema changes happen only during
|
|
17
|
+
* version upgrades, upgrades may be blocked by other open tabs or connections,
|
|
18
|
+
* and reads or writes must run in transactions scoped to the object stores they
|
|
19
|
+
* touch. The `layerWindow` constructor should be used only where browser
|
|
20
|
+
* globals are available, and code that also runs during SSR or in restricted
|
|
21
|
+
* browser contexts should account for `indexedDB` or `IDBKeyRange` being
|
|
22
|
+
* missing.
|
|
23
|
+
*
|
|
24
|
+
* @since 4.0.0
|
|
25
|
+
*/
|
|
26
|
+
import * as Context from "effect/Context";
|
|
27
|
+
import * as Effect from "effect/Effect";
|
|
28
|
+
import * as Layer from "effect/Layer";
|
|
29
|
+
import * as Schema from "effect/Schema";
|
|
30
|
+
const TypeId = "~@effect/platform-browser/IndexedDb";
|
|
31
|
+
/**
|
|
32
|
+
* Service tag for browser IndexedDB primitives.
|
|
33
|
+
*
|
|
34
|
+
* @category tag
|
|
35
|
+
* @since 4.0.0
|
|
36
|
+
*/
|
|
37
|
+
export const IndexedDb = /*#__PURE__*/Context.Service(TypeId);
|
|
38
|
+
/** @internal */
|
|
39
|
+
const IDBFlatKey = /*#__PURE__*/Schema.Union([Schema.String, /*#__PURE__*/Schema.Number.check(/*#__PURE__*/Schema.makeFilter(input => !Number.isNaN(input))), Schema.DateValid, /*#__PURE__*/Schema.declare(input => input instanceof ArrayBuffer || ArrayBuffer.isView(input) && input.buffer instanceof ArrayBuffer)]);
|
|
40
|
+
/**
|
|
41
|
+
* Schema for IndexedDB keys: strings, non-NaN numbers, valid dates, buffer sources, or arrays of those flat key values.
|
|
42
|
+
*
|
|
43
|
+
* @category schemas
|
|
44
|
+
* @since 4.0.0
|
|
45
|
+
*/
|
|
46
|
+
export const IDBValidKey = /*#__PURE__*/Schema.Union([IDBFlatKey, /*#__PURE__*/Schema.Array(IDBFlatKey)]);
|
|
47
|
+
/**
|
|
48
|
+
* Schema for auto-incremented IndexedDB keys, accepting integers from 1 through `2 ** 53`.
|
|
49
|
+
*
|
|
50
|
+
* @category schemas
|
|
51
|
+
* @since 4.0.0
|
|
52
|
+
*/
|
|
53
|
+
export const AutoIncrement = /*#__PURE__*/Schema.Int.check(Schema.isBetween({
|
|
54
|
+
minimum: 1,
|
|
55
|
+
maximum: 2 ** 53
|
|
56
|
+
})).annotate({
|
|
57
|
+
identifier: "AutoIncrement",
|
|
58
|
+
title: "autoIncrement",
|
|
59
|
+
description: "Defines a valid autoIncrement key path for the IndexedDb table"
|
|
60
|
+
});
|
|
61
|
+
/**
|
|
62
|
+
* Creates an `IndexedDb` service from an `IDBFactory` and `IDBKeyRange` constructor.
|
|
63
|
+
*
|
|
64
|
+
* @category constructors
|
|
65
|
+
* @since 4.0.0
|
|
66
|
+
*/
|
|
67
|
+
export const make = impl => IndexedDb.of({
|
|
68
|
+
[TypeId]: TypeId,
|
|
69
|
+
...impl
|
|
70
|
+
});
|
|
71
|
+
/**
|
|
72
|
+
* Layer that provides `IndexedDb` from `window.indexedDB` and `window.IDBKeyRange`, failing with a config error when they are unavailable.
|
|
73
|
+
*
|
|
74
|
+
* @category constructors
|
|
75
|
+
* @since 4.0.0
|
|
76
|
+
*/
|
|
77
|
+
export const layerWindow = /*#__PURE__*/Layer.effect(IndexedDb, /*#__PURE__*/Effect.suspend(() => {
|
|
78
|
+
if (window.indexedDB && window.IDBKeyRange) {
|
|
79
|
+
return Effect.succeed(make({
|
|
80
|
+
indexedDB: window.indexedDB,
|
|
81
|
+
IDBKeyRange: window.IDBKeyRange
|
|
82
|
+
}));
|
|
83
|
+
} else {
|
|
84
|
+
return Effect.die(new Error("window.indexedDB is not available"));
|
|
85
|
+
}
|
|
86
|
+
}));
|
|
87
|
+
//# sourceMappingURL=IndexedDb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IndexedDb.js","names":["Context","Effect","Layer","Schema","TypeId","IndexedDb","Service","IDBFlatKey","Union","String","Number","check","makeFilter","input","isNaN","DateValid","declare","ArrayBuffer","isView","buffer","IDBValidKey","Array","AutoIncrement","Int","isBetween","minimum","maximum","annotate","identifier","title","description","make","impl","of","layerWindow","effect","suspend","window","indexedDB","IDBKeyRange","succeed","die","Error"],"sources":["../src/IndexedDb.ts"],"sourcesContent":[null],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,OAAO,KAAKA,OAAO,MAAM,gBAAgB;AACzC,OAAO,KAAKC,MAAM,MAAM,eAAe;AACvC,OAAO,KAAKC,KAAK,MAAM,cAAc;AACrC,OAAO,KAAKC,MAAM,MAAM,eAAe;AAEvC,MAAMC,MAAM,GAAG,qCAAqC;AAcpD;;;;;;AAMA,OAAO,MAAMC,SAAS,gBAA0CL,OAAO,CAACM,OAAO,CAAuBF,MAAM,CAAC;AAE7G;AACA,MAAMG,UAAU,gBAAGJ,MAAM,CAACK,KAAK,CAAC,CAC9BL,MAAM,CAACM,MAAM,eACbN,MAAM,CAACO,MAAM,CAACC,KAAK,cAACR,MAAM,CAACS,UAAU,CAAEC,KAAK,IAAK,CAACH,MAAM,CAACI,KAAK,CAACD,KAAK,CAAC,CAAC,CAAC,EACvEV,MAAM,CAACY,SAAS,eAChBZ,MAAM,CAACa,OAAO,CACXH,KAAK,IACJA,KAAK,YAAYI,WAAW,IAC3BA,WAAW,CAACC,MAAM,CAACL,KAAK,CAAC,IAAIA,KAAK,CAACM,MAAM,YAAYF,WAAY,CACrE,CACF,CAAC;AAEF;;;;;;AAMA,OAAO,MAAMG,WAAW,gBAAGjB,MAAM,CAACK,KAAK,CAAC,CAACD,UAAU,eAAEJ,MAAM,CAACkB,KAAK,CAACd,UAAU,CAAC,CAAC,CAAC;AAE/E;;;;;;AAMA,OAAO,MAAMe,aAAa,gBAAGnB,MAAM,CAACoB,GAAG,CAACZ,KAAK,CAC3CR,MAAM,CAACqB,SAAS,CAAC;EAAEC,OAAO,EAAE,CAAC;EAAEC,OAAO,EAAE,CAAC,IAAI;AAAE,CAAE,CAAC,CACnD,CAACC,QAAQ,CAAC;EACTC,UAAU,EAAE,eAAe;EAC3BC,KAAK,EAAE,eAAe;EACtBC,WAAW,EAAE;CACd,CAAC;AAEF;;;;;;AAMA,OAAO,MAAMC,IAAI,GAAIC,IAAoC,IAAgB3B,SAAS,CAAC4B,EAAE,CAAC;EAAE,CAAC7B,MAAM,GAAGA,MAAM;EAAE,GAAG4B;AAAI,CAAE,CAAC;AAEpH;;;;;;AAMA,OAAO,MAAME,WAAW,gBAA2BhC,KAAK,CAACiC,MAAM,CAC7D9B,SAAS,eACTJ,MAAM,CAACmC,OAAO,CAAC,MAAK;EAClB,IAAIC,MAAM,CAACC,SAAS,IAAID,MAAM,CAACE,WAAW,EAAE;IAC1C,OAAOtC,MAAM,CAACuC,OAAO,CACnBT,IAAI,CAAC;MACHO,SAAS,EAAED,MAAM,CAACC,SAAS;MAC3BC,WAAW,EAAEF,MAAM,CAACE;KACrB,CAAC,CACH;EACH,CAAC,MAAM;IACL,OAAOtC,MAAM,CAACwC,GAAG,CAAC,IAAIC,KAAK,CAAC,mCAAmC,CAAC,CAAC;EACnE;AACF,CAAC,CAAC,CACH","ignoreList":[]}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds and opens typed IndexedDB databases from versioned schema migrations.
|
|
3
|
+
*
|
|
4
|
+
* This module turns an `IndexedDbVersion` migration chain into an
|
|
5
|
+
* `IndexedDbDatabase` layer. The layer opens the browser database, runs any
|
|
6
|
+
* pending upgrade migrations, provides a query builder for the current schema,
|
|
7
|
+
* and exposes a `rebuild` effect that deletes and reopens the database. It is
|
|
8
|
+
* the database-level companion to the table, version, and query builder
|
|
9
|
+
* modules.
|
|
10
|
+
*
|
|
11
|
+
* Use it for browser-local persistence such as offline-first application
|
|
12
|
+
* state, cached server data, background queues, drafts, and other client-side
|
|
13
|
+
* stores that need typed reads and writes backed by IndexedDB transactions.
|
|
14
|
+
*
|
|
15
|
+
* IndexedDB schema changes can only happen inside upgrade transactions, so
|
|
16
|
+
* every call to `make` or `.add` represents the next browser database version
|
|
17
|
+
* and only migrations after the existing browser version are run. Table and
|
|
18
|
+
* index definitions type the migration and query APIs, but object stores and
|
|
19
|
+
* indexes still need to be created or removed explicitly with the migration
|
|
20
|
+
* transaction helpers. Include the complete target table set in each version,
|
|
21
|
+
* create indexes before querying them, and treat key path or auto-increment
|
|
22
|
+
* changes as store migrations that copy data into a replacement object store.
|
|
23
|
+
* Upgrades can be blocked by other open connections, and all migration reads,
|
|
24
|
+
* writes, store changes, and index changes share the single upgrade
|
|
25
|
+
* transaction supplied by the browser.
|
|
26
|
+
*
|
|
27
|
+
* @since 4.0.0
|
|
28
|
+
*/
|
|
29
|
+
import * as Context from "effect/Context";
|
|
30
|
+
import * as Effect from "effect/Effect";
|
|
31
|
+
import * as Layer from "effect/Layer";
|
|
32
|
+
import * as MutableRef from "effect/MutableRef";
|
|
33
|
+
import * as Reactivity from "effect/unstable/reactivity/Reactivity";
|
|
34
|
+
import * as IndexedDb from "./IndexedDb.ts";
|
|
35
|
+
import * as IndexedDbQueryBuilder from "./IndexedDbQueryBuilder.ts";
|
|
36
|
+
import type * as IndexedDbTable from "./IndexedDbTable.ts";
|
|
37
|
+
import type * as IndexedDbVersion from "./IndexedDbVersion.ts";
|
|
38
|
+
declare const ErrorTypeId = "~@effect/platform-browser/IndexedDbDatabase/IndexedDbDatabaseError";
|
|
39
|
+
/**
|
|
40
|
+
* String union describing the failure categories for IndexedDB database opening, migration, and schema operations.
|
|
41
|
+
*
|
|
42
|
+
* @category errors
|
|
43
|
+
* @since 4.0.0
|
|
44
|
+
*/
|
|
45
|
+
export type ErrorReason = "TransactionError" | "MissingTable" | "OpenError" | "UpgradeError" | "Aborted" | "Blocked" | "MissingIndex";
|
|
46
|
+
declare const IndexedDbDatabaseError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
47
|
+
readonly _tag: "IndexedDbDatabaseError";
|
|
48
|
+
} & Readonly<A>;
|
|
49
|
+
/**
|
|
50
|
+
* Tagged error for IndexedDB database operations, carrying a database error reason and the original cause.
|
|
51
|
+
*
|
|
52
|
+
* @category errors
|
|
53
|
+
* @since 4.0.0
|
|
54
|
+
*/
|
|
55
|
+
export declare class IndexedDbDatabaseError extends IndexedDbDatabaseError_base<{
|
|
56
|
+
reason: ErrorReason;
|
|
57
|
+
cause: unknown;
|
|
58
|
+
}> {
|
|
59
|
+
/**
|
|
60
|
+
* Marks this value as an IndexedDB database error for runtime guards.
|
|
61
|
+
*
|
|
62
|
+
* @since 4.0.0
|
|
63
|
+
*/
|
|
64
|
+
readonly [ErrorTypeId]: typeof ErrorTypeId;
|
|
65
|
+
readonly message: ErrorReason;
|
|
66
|
+
}
|
|
67
|
+
declare const IndexedDbDatabase_base: Context.ServiceClass<IndexedDbDatabase, "~@effect/platform-browser/IndexedDbDatabase", {
|
|
68
|
+
readonly database: MutableRef.MutableRef<globalThis.IDBDatabase>;
|
|
69
|
+
readonly IDBKeyRange: typeof globalThis.IDBKeyRange;
|
|
70
|
+
readonly reactivity: Reactivity.Reactivity["Service"];
|
|
71
|
+
readonly rebuild: Effect.Effect<void, IndexedDbDatabaseError>;
|
|
72
|
+
}>;
|
|
73
|
+
/**
|
|
74
|
+
* Service tag for an open IndexedDB database, its `IDBKeyRange` constructor, reactivity service, and rebuild effect.
|
|
75
|
+
*
|
|
76
|
+
* @category models
|
|
77
|
+
* @since 4.0.0
|
|
78
|
+
*/
|
|
79
|
+
export declare class IndexedDbDatabase extends IndexedDbDatabase_base {
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Describes an IndexedDB schema version and its migrations, and acts as an effect that yields a query builder for the target version.
|
|
83
|
+
*
|
|
84
|
+
* @category models
|
|
85
|
+
* @since 4.0.0
|
|
86
|
+
*/
|
|
87
|
+
export interface IndexedDbSchema<in out FromVersion extends IndexedDbVersion.AnyWithProps, in out ToVersion extends IndexedDbVersion.AnyWithProps, out Error = never> extends Effect.Effect<IndexedDbQueryBuilder.IndexedDbQueryBuilder<ToVersion>, never, IndexedDbDatabase> {
|
|
88
|
+
new (_: never): {};
|
|
89
|
+
readonly previous: [FromVersion] extends [never] ? undefined : IndexedDbSchema<never, FromVersion, Error>;
|
|
90
|
+
readonly fromVersion: FromVersion;
|
|
91
|
+
readonly version: ToVersion;
|
|
92
|
+
readonly migrate: [FromVersion] extends [never] ? (query: Transaction<ToVersion>) => Effect.Effect<void, Error> : (fromQuery: Transaction<FromVersion>, toQuery: Transaction<ToVersion>) => Effect.Effect<void, Error>;
|
|
93
|
+
readonly add: <Version extends IndexedDbVersion.AnyWithProps, MigrationError>(version: Version, migrate: (fromQuery: Transaction<ToVersion>, toQuery: Transaction<Version>) => Effect.Effect<void, MigrationError>) => IndexedDbSchema<ToVersion, Version, MigrationError | Error>;
|
|
94
|
+
readonly getQueryBuilder: Effect.Effect<IndexedDbQueryBuilder.IndexedDbQueryBuilder<ToVersion>, never, IndexedDbDatabase>;
|
|
95
|
+
readonly layer: (databaseName: string) => Layer.Layer<IndexedDbDatabase, IndexedDbDatabaseError, IndexedDb.IndexedDb>;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Query builder available during a database migration, extended with object-store and index management helpers for the active `IDBTransaction`.
|
|
99
|
+
*
|
|
100
|
+
* @category models
|
|
101
|
+
* @since 4.0.0
|
|
102
|
+
*/
|
|
103
|
+
export interface Transaction<Source extends IndexedDbVersion.AnyWithProps = never> extends Omit<IndexedDbQueryBuilder.IndexedDbQueryBuilder<Source>, "transaction"> {
|
|
104
|
+
readonly transaction: globalThis.IDBTransaction;
|
|
105
|
+
readonly createObjectStore: <A extends IndexedDbTable.TableName<IndexedDbVersion.Tables<Source>>>(table: A) => Effect.Effect<globalThis.IDBObjectStore, IndexedDbDatabaseError>;
|
|
106
|
+
readonly deleteObjectStore: <A extends IndexedDbTable.TableName<IndexedDbVersion.Tables<Source>>>(table: A) => Effect.Effect<void, IndexedDbDatabaseError>;
|
|
107
|
+
readonly createIndex: <Name extends IndexedDbTable.TableName<IndexedDbVersion.Tables<Source>>>(table: Name, indexName: IndexFromTableName<Source, Name>, options?: IDBIndexParameters) => Effect.Effect<globalThis.IDBIndex, IndexedDbDatabaseError>;
|
|
108
|
+
readonly deleteIndex: <Name extends IndexedDbTable.TableName<IndexedDbVersion.Tables<Source>>>(table: Name, indexName: IndexFromTableName<Source, Name>) => Effect.Effect<void, IndexedDbDatabaseError>;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Extracts the string-literal index names defined by an `IndexedDbTable`.
|
|
112
|
+
*
|
|
113
|
+
* @category models
|
|
114
|
+
* @since 4.0.0
|
|
115
|
+
*/
|
|
116
|
+
export type IndexFromTable<Table extends IndexedDbTable.AnyWithProps> = IsStringLiteral<Extract<keyof IndexedDbTable.Indexes<Table>, string>> extends true ? Extract<keyof IndexedDbTable.Indexes<Table>, string> : never;
|
|
117
|
+
/**
|
|
118
|
+
* Extracts the valid index names for a table name within an IndexedDB version.
|
|
119
|
+
*
|
|
120
|
+
* @category models
|
|
121
|
+
* @since 4.0.0
|
|
122
|
+
*/
|
|
123
|
+
export type IndexFromTableName<Version extends IndexedDbVersion.AnyWithProps, Table extends string> = IndexFromTable<IndexedDbTable.WithName<IndexedDbVersion.Tables<Version>, Table>>;
|
|
124
|
+
/**
|
|
125
|
+
* Type-erased IndexedDB schema shape used when traversing schema migration chains.
|
|
126
|
+
*
|
|
127
|
+
* @category models
|
|
128
|
+
* @since 4.0.0
|
|
129
|
+
*/
|
|
130
|
+
export interface Any {
|
|
131
|
+
readonly previous?: Any | undefined;
|
|
132
|
+
readonly layer: (databaseName: string) => Layer.Layer<IndexedDbDatabase, IndexedDbDatabaseError, IndexedDb.IndexedDb>;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Type-erased `IndexedDbSchema` covering any source version, target version, and migration error type.
|
|
136
|
+
*
|
|
137
|
+
* @category models
|
|
138
|
+
* @since 4.0.0
|
|
139
|
+
*/
|
|
140
|
+
export type AnySchema = IndexedDbSchema<IndexedDbVersion.AnyWithProps, IndexedDbVersion.AnyWithProps, any>;
|
|
141
|
+
/**
|
|
142
|
+
* Creates the initial `IndexedDbSchema` from a version and an initialization migration run during database upgrade.
|
|
143
|
+
*
|
|
144
|
+
* @category constructors
|
|
145
|
+
* @since 4.0.0
|
|
146
|
+
*/
|
|
147
|
+
export declare const make: <InitialVersion extends IndexedDbVersion.AnyWithProps, Error>(initialVersion: InitialVersion, init: (toQuery: Transaction<InitialVersion>) => Effect.Effect<void, Error>) => IndexedDbSchema<never, InitialVersion, Error>;
|
|
148
|
+
type IsStringLiteral<T> = T extends string ? string extends T ? false : true : false;
|
|
149
|
+
export {};
|
|
150
|
+
//# sourceMappingURL=IndexedDbDatabase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IndexedDbDatabase.d.ts","sourceRoot":"","sources":["../src/IndexedDbDatabase.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds and opens typed IndexedDB databases from versioned schema migrations.
|
|
3
|
+
*
|
|
4
|
+
* This module turns an `IndexedDbVersion` migration chain into an
|
|
5
|
+
* `IndexedDbDatabase` layer. The layer opens the browser database, runs any
|
|
6
|
+
* pending upgrade migrations, provides a query builder for the current schema,
|
|
7
|
+
* and exposes a `rebuild` effect that deletes and reopens the database. It is
|
|
8
|
+
* the database-level companion to the table, version, and query builder
|
|
9
|
+
* modules.
|
|
10
|
+
*
|
|
11
|
+
* Use it for browser-local persistence such as offline-first application
|
|
12
|
+
* state, cached server data, background queues, drafts, and other client-side
|
|
13
|
+
* stores that need typed reads and writes backed by IndexedDB transactions.
|
|
14
|
+
*
|
|
15
|
+
* IndexedDB schema changes can only happen inside upgrade transactions, so
|
|
16
|
+
* every call to `make` or `.add` represents the next browser database version
|
|
17
|
+
* and only migrations after the existing browser version are run. Table and
|
|
18
|
+
* index definitions type the migration and query APIs, but object stores and
|
|
19
|
+
* indexes still need to be created or removed explicitly with the migration
|
|
20
|
+
* transaction helpers. Include the complete target table set in each version,
|
|
21
|
+
* create indexes before querying them, and treat key path or auto-increment
|
|
22
|
+
* changes as store migrations that copy data into a replacement object store.
|
|
23
|
+
* Upgrades can be blocked by other open connections, and all migration reads,
|
|
24
|
+
* writes, store changes, and index changes share the single upgrade
|
|
25
|
+
* transaction supplied by the browser.
|
|
26
|
+
*
|
|
27
|
+
* @since 4.0.0
|
|
28
|
+
*/
|
|
29
|
+
import * as Context from "effect/Context";
|
|
30
|
+
import * as Data from "effect/Data";
|
|
31
|
+
import * as Effect from "effect/Effect";
|
|
32
|
+
import * as Effectable from "effect/Effectable";
|
|
33
|
+
import * as Fiber from "effect/Fiber";
|
|
34
|
+
import * as Layer from "effect/Layer";
|
|
35
|
+
import * as MutableRef from "effect/MutableRef";
|
|
36
|
+
import * as Semaphore from "effect/Semaphore";
|
|
37
|
+
import * as Reactivity from "effect/unstable/reactivity/Reactivity";
|
|
38
|
+
import * as IndexedDb from "./IndexedDb.js";
|
|
39
|
+
import * as IndexedDbQueryBuilder from "./IndexedDbQueryBuilder.js";
|
|
40
|
+
const TypeId = "~@effect/platform-browser/IndexedDbDatabase";
|
|
41
|
+
const ErrorTypeId = "~@effect/platform-browser/IndexedDbDatabase/IndexedDbDatabaseError";
|
|
42
|
+
const SchemaProto = {
|
|
43
|
+
[TypeId]: {
|
|
44
|
+
_A: _ => _
|
|
45
|
+
},
|
|
46
|
+
... /*#__PURE__*/Effectable.Prototype({
|
|
47
|
+
label: "IndexedDbSchema",
|
|
48
|
+
evaluate() {
|
|
49
|
+
return this.getQueryBuilder;
|
|
50
|
+
}
|
|
51
|
+
}),
|
|
52
|
+
get getQueryBuilder() {
|
|
53
|
+
const self = this;
|
|
54
|
+
return IndexedDbDatabase.useSync(({
|
|
55
|
+
database,
|
|
56
|
+
IDBKeyRange,
|
|
57
|
+
reactivity
|
|
58
|
+
}) => IndexedDbQueryBuilder.make({
|
|
59
|
+
database,
|
|
60
|
+
IDBKeyRange,
|
|
61
|
+
tables: self.version.tables,
|
|
62
|
+
reactivity
|
|
63
|
+
}));
|
|
64
|
+
},
|
|
65
|
+
add(version, migrate) {
|
|
66
|
+
return makeMigration({
|
|
67
|
+
fromVersion: this.version,
|
|
68
|
+
version,
|
|
69
|
+
migrate,
|
|
70
|
+
previous: this
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
layer(databaseName) {
|
|
74
|
+
return layer(databaseName, this);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Tagged error for IndexedDB database operations, carrying a database error reason and the original cause.
|
|
79
|
+
*
|
|
80
|
+
* @category errors
|
|
81
|
+
* @since 4.0.0
|
|
82
|
+
*/
|
|
83
|
+
export class IndexedDbDatabaseError extends /*#__PURE__*/Data.TaggedError("IndexedDbDatabaseError") {
|
|
84
|
+
/**
|
|
85
|
+
* Marks this value as an IndexedDB database error for runtime guards.
|
|
86
|
+
*
|
|
87
|
+
* @since 4.0.0
|
|
88
|
+
*/
|
|
89
|
+
[ErrorTypeId] = ErrorTypeId;
|
|
90
|
+
message = this.reason;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Service tag for an open IndexedDB database, its `IDBKeyRange` constructor, reactivity service, and rebuild effect.
|
|
94
|
+
*
|
|
95
|
+
* @category models
|
|
96
|
+
* @since 4.0.0
|
|
97
|
+
*/
|
|
98
|
+
export class IndexedDbDatabase extends /*#__PURE__*/Context.Service()(TypeId) {}
|
|
99
|
+
/**
|
|
100
|
+
* Creates the initial `IndexedDbSchema` from a version and an initialization migration run during database upgrade.
|
|
101
|
+
*
|
|
102
|
+
* @category constructors
|
|
103
|
+
* @since 4.0.0
|
|
104
|
+
*/
|
|
105
|
+
export const make = (initialVersion, init) => {
|
|
106
|
+
// oxlint-disable-next-line typescript/no-extraneous-class
|
|
107
|
+
function Initial() {}
|
|
108
|
+
Object.setPrototypeOf(Initial, SchemaProto);
|
|
109
|
+
Initial.version = initialVersion;
|
|
110
|
+
Initial.migrate = init;
|
|
111
|
+
return Initial;
|
|
112
|
+
};
|
|
113
|
+
const makeMigration = options => {
|
|
114
|
+
// oxlint-disable-next-line typescript/no-extraneous-class
|
|
115
|
+
function Migration() {}
|
|
116
|
+
Object.setPrototypeOf(Migration, SchemaProto);
|
|
117
|
+
Migration.previous = options.previous;
|
|
118
|
+
Migration.fromVersion = options.fromVersion;
|
|
119
|
+
Migration.version = options.version;
|
|
120
|
+
Migration.migrate = options.migrate;
|
|
121
|
+
return Migration;
|
|
122
|
+
};
|
|
123
|
+
const layer = (databaseName, migration) => Layer.effect(IndexedDbDatabase, Effect.gen(function* () {
|
|
124
|
+
const {
|
|
125
|
+
IDBKeyRange,
|
|
126
|
+
indexedDB
|
|
127
|
+
} = yield* IndexedDb.IndexedDb;
|
|
128
|
+
const reactivity = yield* Reactivity.Reactivity;
|
|
129
|
+
const context = yield* Effect.context();
|
|
130
|
+
const runForkWith = Effect.runForkWith(context);
|
|
131
|
+
let oldVersion = 0;
|
|
132
|
+
const migrations = [];
|
|
133
|
+
let current = migration;
|
|
134
|
+
while (current) {
|
|
135
|
+
migrations.unshift(current);
|
|
136
|
+
current = current.previous;
|
|
137
|
+
}
|
|
138
|
+
const version = migrations.length;
|
|
139
|
+
const database = MutableRef.make(null);
|
|
140
|
+
const open = Effect.callback(resume => {
|
|
141
|
+
const request = indexedDB.open(databaseName, version);
|
|
142
|
+
request.onblocked = event => {
|
|
143
|
+
resume(Effect.fail(new IndexedDbDatabaseError({
|
|
144
|
+
reason: "Blocked",
|
|
145
|
+
cause: event
|
|
146
|
+
})));
|
|
147
|
+
};
|
|
148
|
+
request.onerror = event => {
|
|
149
|
+
const idbRequest = event.target;
|
|
150
|
+
resume(Effect.fail(new IndexedDbDatabaseError({
|
|
151
|
+
reason: "OpenError",
|
|
152
|
+
cause: idbRequest.error
|
|
153
|
+
})));
|
|
154
|
+
};
|
|
155
|
+
let fiber;
|
|
156
|
+
request.onupgradeneeded = event => {
|
|
157
|
+
const idbRequest = event.target;
|
|
158
|
+
const db = idbRequest.result;
|
|
159
|
+
const transaction = idbRequest.transaction;
|
|
160
|
+
oldVersion = event.oldVersion;
|
|
161
|
+
MutableRef.set(database, db);
|
|
162
|
+
if (transaction === null) {
|
|
163
|
+
return resume(Effect.fail(new IndexedDbDatabaseError({
|
|
164
|
+
reason: "TransactionError",
|
|
165
|
+
cause: null
|
|
166
|
+
})));
|
|
167
|
+
}
|
|
168
|
+
transaction.onabort = event => {
|
|
169
|
+
resume(Effect.fail(new IndexedDbDatabaseError({
|
|
170
|
+
reason: "Aborted",
|
|
171
|
+
cause: event
|
|
172
|
+
})));
|
|
173
|
+
};
|
|
174
|
+
transaction.onerror = event => {
|
|
175
|
+
resume(Effect.fail(new IndexedDbDatabaseError({
|
|
176
|
+
reason: "TransactionError",
|
|
177
|
+
cause: event
|
|
178
|
+
})));
|
|
179
|
+
};
|
|
180
|
+
const effect = Effect.forEach(migrations.slice(oldVersion), untypedMigration => {
|
|
181
|
+
if (untypedMigration.previous === undefined) {
|
|
182
|
+
const migration = untypedMigration;
|
|
183
|
+
const api = makeTransactionProto({
|
|
184
|
+
database,
|
|
185
|
+
IDBKeyRange,
|
|
186
|
+
tables: migration.version.tables,
|
|
187
|
+
transaction,
|
|
188
|
+
reactivity
|
|
189
|
+
});
|
|
190
|
+
return migration.migrate(api);
|
|
191
|
+
} else if (untypedMigration.previous) {
|
|
192
|
+
const migration = untypedMigration;
|
|
193
|
+
const fromApi = makeTransactionProto({
|
|
194
|
+
database,
|
|
195
|
+
IDBKeyRange,
|
|
196
|
+
tables: migration.fromVersion.tables,
|
|
197
|
+
transaction,
|
|
198
|
+
reactivity
|
|
199
|
+
});
|
|
200
|
+
const toApi = makeTransactionProto({
|
|
201
|
+
database,
|
|
202
|
+
IDBKeyRange,
|
|
203
|
+
tables: migration.version.tables,
|
|
204
|
+
transaction,
|
|
205
|
+
reactivity
|
|
206
|
+
});
|
|
207
|
+
return migration.migrate(fromApi, toApi);
|
|
208
|
+
}
|
|
209
|
+
return Effect.die(new Error("Invalid migration"));
|
|
210
|
+
}, {
|
|
211
|
+
discard: true
|
|
212
|
+
}).pipe(Effect.mapError(cause => new IndexedDbDatabaseError({
|
|
213
|
+
reason: "UpgradeError",
|
|
214
|
+
cause
|
|
215
|
+
})), Effect.provideService(IndexedDbQueryBuilder.IndexedDbTransaction, transaction));
|
|
216
|
+
fiber = runForkWith(effect);
|
|
217
|
+
fiber.currentDispatcher.flush();
|
|
218
|
+
};
|
|
219
|
+
request.onsuccess = event => {
|
|
220
|
+
const idbRequest = event.target;
|
|
221
|
+
const db = idbRequest.result;
|
|
222
|
+
MutableRef.set(database, db);
|
|
223
|
+
if (fiber) {
|
|
224
|
+
// ensure migration errors are propagated
|
|
225
|
+
resume(Effect.asVoid(Fiber.join(fiber)));
|
|
226
|
+
} else {
|
|
227
|
+
resume(Effect.void);
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
});
|
|
231
|
+
yield* Effect.addFinalizer(() => {
|
|
232
|
+
database.current?.close();
|
|
233
|
+
return Effect.void;
|
|
234
|
+
});
|
|
235
|
+
yield* open;
|
|
236
|
+
const rebuildLock = Semaphore.makeUnsafe(1).withPermit;
|
|
237
|
+
const rebuild = Effect.callback(resume => {
|
|
238
|
+
database.current?.close();
|
|
239
|
+
const request = indexedDB.deleteDatabase(databaseName);
|
|
240
|
+
request.onerror = _ => {
|
|
241
|
+
resume(Effect.fail(new IndexedDbDatabaseError({
|
|
242
|
+
reason: "OpenError",
|
|
243
|
+
cause: request.error
|
|
244
|
+
})));
|
|
245
|
+
};
|
|
246
|
+
request.onsuccess = () => {
|
|
247
|
+
resume(Effect.void);
|
|
248
|
+
};
|
|
249
|
+
}).pipe(Effect.flatMap(() => open), rebuildLock);
|
|
250
|
+
return IndexedDbDatabase.of({
|
|
251
|
+
database,
|
|
252
|
+
IDBKeyRange,
|
|
253
|
+
rebuild,
|
|
254
|
+
reactivity
|
|
255
|
+
});
|
|
256
|
+
})).pipe(Layer.provide(Reactivity.layer));
|
|
257
|
+
const makeTransactionProto = ({
|
|
258
|
+
IDBKeyRange,
|
|
259
|
+
database,
|
|
260
|
+
tables,
|
|
261
|
+
transaction,
|
|
262
|
+
reactivity
|
|
263
|
+
}) => {
|
|
264
|
+
const migration = IndexedDbQueryBuilder.make({
|
|
265
|
+
database,
|
|
266
|
+
IDBKeyRange,
|
|
267
|
+
tables,
|
|
268
|
+
reactivity
|
|
269
|
+
});
|
|
270
|
+
migration.transaction = transaction;
|
|
271
|
+
migration.createObjectStore = Effect.fnUntraced(function* (table) {
|
|
272
|
+
const createTable = yield* Effect.fromNullishOr(tables.get(table)).pipe(Effect.mapError(cause => new IndexedDbDatabaseError({
|
|
273
|
+
reason: "MissingTable",
|
|
274
|
+
cause
|
|
275
|
+
})));
|
|
276
|
+
return yield* Effect.try({
|
|
277
|
+
try: () => database.current.createObjectStore(createTable.tableName, {
|
|
278
|
+
keyPath: createTable.keyPath,
|
|
279
|
+
autoIncrement: createTable.autoIncrement
|
|
280
|
+
}),
|
|
281
|
+
catch: cause => new IndexedDbDatabaseError({
|
|
282
|
+
reason: "TransactionError",
|
|
283
|
+
cause
|
|
284
|
+
})
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
migration.deleteObjectStore = Effect.fnUntraced(function* (table) {
|
|
288
|
+
const createTable = yield* Effect.fromNullishOr(tables.get(table)).pipe(Effect.mapError(cause => new IndexedDbDatabaseError({
|
|
289
|
+
reason: "MissingTable",
|
|
290
|
+
cause
|
|
291
|
+
})));
|
|
292
|
+
return yield* Effect.try({
|
|
293
|
+
try: () => database.current.deleteObjectStore(createTable.tableName),
|
|
294
|
+
catch: cause => new IndexedDbDatabaseError({
|
|
295
|
+
reason: "TransactionError",
|
|
296
|
+
cause
|
|
297
|
+
})
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
migration.createIndex = Effect.fnUntraced(function* (table, indexName, options) {
|
|
301
|
+
const store = transaction.objectStore(table);
|
|
302
|
+
const sourceTable = tables.get(table);
|
|
303
|
+
const keyPath = yield* Effect.fromNullishOr(sourceTable.indexes[indexName]).pipe(Effect.mapError(cause => new IndexedDbDatabaseError({
|
|
304
|
+
reason: "MissingIndex",
|
|
305
|
+
cause
|
|
306
|
+
})));
|
|
307
|
+
return yield* Effect.try({
|
|
308
|
+
try: () => store.createIndex(indexName, keyPath, options),
|
|
309
|
+
catch: cause => new IndexedDbDatabaseError({
|
|
310
|
+
reason: "TransactionError",
|
|
311
|
+
cause
|
|
312
|
+
})
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
migration.deleteIndex = (table, indexName) => Effect.try({
|
|
316
|
+
try: () => transaction.objectStore(table).deleteIndex(indexName),
|
|
317
|
+
catch: cause => new IndexedDbDatabaseError({
|
|
318
|
+
reason: "TransactionError",
|
|
319
|
+
cause
|
|
320
|
+
})
|
|
321
|
+
});
|
|
322
|
+
return migration;
|
|
323
|
+
};
|
|
324
|
+
//# sourceMappingURL=IndexedDbDatabase.js.map
|