@signaldb/indexeddb 2.0.0-beta.6 → 2.0.0-beta.7
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/base/core/src/AsyncDataAdapter.d.ts +64 -0
- package/dist/base/core/src/AutoFetchDataAdapter.d.ts +112 -0
- package/dist/base/core/src/Collection/Cursor.d.ts +113 -0
- package/dist/base/core/src/Collection/Observer.d.ts +64 -0
- package/dist/base/core/src/Collection/index.d.ts +294 -0
- package/dist/base/core/src/Collection/types.d.ts +28 -0
- package/dist/base/core/src/DataAdapter.d.ts +35 -0
- package/dist/base/core/src/DefaultDataAdapter.d.ts +35 -0
- package/dist/base/core/src/WorkerDataAdapter.d.ts +25 -0
- package/dist/base/core/src/WorkerDataAdapterHost.d.ts +62 -0
- package/dist/base/core/src/createIndex.d.ts +7 -0
- package/dist/base/core/src/createIndexProvider.d.ts +8 -0
- package/dist/base/core/src/createReactivityAdapter.d.ts +8 -0
- package/dist/base/core/src/createStorageAdapter.d.ts +9 -0
- package/dist/base/core/src/getIndexInfo.d.ts +39 -0
- package/dist/base/core/src/index.d.ts +22 -0
- package/dist/base/core/src/types/Dependency.d.ts +4 -0
- package/dist/base/core/src/types/IndexProvider.d.ts +26 -0
- package/dist/base/core/src/types/Modifier.d.ts +46 -0
- package/dist/base/core/src/types/ReactivityAdapter.d.ts +6 -0
- package/dist/base/core/src/types/Selector.d.ts +46 -0
- package/dist/base/core/src/types/Signal.d.ts +4 -0
- package/dist/base/core/src/types/StorageAdapter.d.ts +20 -0
- package/dist/base/core/src/utils/EventEmitter.d.ts +71 -0
- package/dist/base/core/src/utils/batchOnNextTick.d.ts +16 -0
- package/dist/base/core/src/utils/compact.d.ts +9 -0
- package/dist/base/core/src/utils/createSignal.d.ts +14 -0
- package/dist/base/core/src/utils/deepClone.d.ts +17 -0
- package/dist/base/core/src/utils/get.d.ts +9 -0
- package/dist/base/core/src/utils/getMatchingKeys.d.ts +19 -0
- package/dist/base/core/src/utils/intersection.d.ts +9 -0
- package/dist/base/core/src/utils/isEqual.d.ts +14 -0
- package/dist/base/core/src/utils/isFieldExpression.d.ts +11 -0
- package/dist/base/core/src/utils/match.d.ts +12 -0
- package/dist/base/core/src/utils/modify.d.ts +14 -0
- package/dist/base/core/src/utils/project.d.ts +15 -0
- package/dist/base/core/src/utils/queryId.d.ts +9 -0
- package/dist/base/core/src/utils/randomId.d.ts +7 -0
- package/dist/base/core/src/utils/reactiveOrAsync.d.ts +59 -0
- package/dist/base/core/src/utils/serializeValue.d.ts +12 -0
- package/dist/base/core/src/utils/set.d.ts +13 -0
- package/dist/base/core/src/utils/sortItems.d.ts +12 -0
- package/dist/base/core/src/utils/uniqueBy.d.ts +10 -0
- package/dist/index.mjs +119 -132
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +2 -2
- package/dist/index.umd.js.map +1 -1
- package/package.json +2 -2
- /package/dist/{index.d.ts → storage-adapters/indexeddb/src/index.d.ts} +0 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compares two values for deep equality.
|
|
3
|
+
* @param a - The first value to compare.
|
|
4
|
+
* @param b - The second value to compare.
|
|
5
|
+
* @returns - Returns `true` if the two values are deeply equal, otherwise `false`.
|
|
6
|
+
* @example
|
|
7
|
+
* isEqual({ a: 1 }, { a: 1 }); // true
|
|
8
|
+
* isEqual([1, 2], [1, 2]); // true
|
|
9
|
+
* isEqual(new Date(0), new Date(0)); // true
|
|
10
|
+
* isEqual(/abc/, /abc/); // true
|
|
11
|
+
* isEqual({ a: 1 }, { a: 2 }); // false
|
|
12
|
+
* isEqual(null, null); // true
|
|
13
|
+
*/
|
|
14
|
+
export default function isEqual<T, K>(a: T, b: K): boolean;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FieldExpression } from '../types/Selector';
|
|
2
|
+
/**
|
|
3
|
+
* Determines whether a given object is a valid field expression.
|
|
4
|
+
* A field expression is an object containing query operators supported by MongoDB-style queries.
|
|
5
|
+
* @template T - The type of the field expression.
|
|
6
|
+
* @param expression - The object to test.
|
|
7
|
+
* @returns A boolean indicating whether the object is a valid field expression.
|
|
8
|
+
* - `true` if the object contains only recognized query operators.
|
|
9
|
+
* - `false` otherwise.
|
|
10
|
+
*/
|
|
11
|
+
export default function isFieldExpression<T>(expression: any): expression is FieldExpression<T>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type Selector from '../types/Selector';
|
|
2
|
+
type BaseItem = Record<string, any>;
|
|
3
|
+
/**
|
|
4
|
+
* Tests whether a given item matches a specified selector.
|
|
5
|
+
* Uses the `mingo` library to evaluate the query.
|
|
6
|
+
* @template T - The type of the item being tested.
|
|
7
|
+
* @param item - The item to test against the selector.
|
|
8
|
+
* @param selector - The query selector used to match the item.
|
|
9
|
+
* @returns A boolean indicating whether the item matches the selector.
|
|
10
|
+
*/
|
|
11
|
+
export default function match<T extends BaseItem = BaseItem>(item: T, selector: Selector<T>): boolean;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type Modifier from '../types/Modifier';
|
|
2
|
+
/**
|
|
3
|
+
* Applies a modifier to an object and returns a new modified object.
|
|
4
|
+
* @template T - The type of the object to be modified.
|
|
5
|
+
* @param item - The object to be modified.
|
|
6
|
+
* @param modifier - The modifier to apply. This can be any transformation logic.
|
|
7
|
+
* @returns - Returns a new object with the modifications applied.
|
|
8
|
+
* @example
|
|
9
|
+
* const item = { a: 1, b: 2 }
|
|
10
|
+
* const modifier = { $set: { b: 3, c: 4 } }
|
|
11
|
+
* const result = modify(item, modifier)
|
|
12
|
+
* // result: { a: 1, b: 3, c: 4 }
|
|
13
|
+
*/
|
|
14
|
+
export default function modify<T extends Record<string, any>>(item: T, modifier: Modifier): T;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Projects the fields of an object based on a specified fields configuration.
|
|
3
|
+
* Supports inclusion (`1`) and exclusion (`0`) of specific fields. Creates a new object
|
|
4
|
+
* with the desired fields included or excluded, based on the configuration.
|
|
5
|
+
* @template T - The type of the object being projected.
|
|
6
|
+
* @param item - The original object to project fields from.
|
|
7
|
+
* @param fields - An object defining the fields to include (`1`) or exclude (`0`).
|
|
8
|
+
* - Keys are the field names, and values are either `1` (include) or `0` (exclude).
|
|
9
|
+
* @returns A new object with the specified fields included or excluded.
|
|
10
|
+
* - If all fields are set to `0`, the excluded fields are removed from the result.
|
|
11
|
+
* - If fields are set to `1`, only the included fields are retained.
|
|
12
|
+
*/
|
|
13
|
+
export default function project<T extends Record<string, any>>(item: T, fields: {
|
|
14
|
+
[P in keyof T]?: 0 | 1;
|
|
15
|
+
} & Record<string, 0 | 1>): T;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { QueryOptions } from '../DataAdapter';
|
|
2
|
+
import type Selector from '../types/Selector';
|
|
3
|
+
/**
|
|
4
|
+
* Generates a unique identifier for a query based on its selector and options.
|
|
5
|
+
* @param selector - The selector object.
|
|
6
|
+
* @param options - The query options object (optional).
|
|
7
|
+
* @returns A unique identifier string for the query.
|
|
8
|
+
*/
|
|
9
|
+
export default function queryId(selector: Selector<any>, options?: QueryOptions<any>): string;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export type MaybePromise<T> = T | Promise<T>;
|
|
2
|
+
/**
|
|
3
|
+
* Options that control execution mode (and potential future mode-specific behavior).
|
|
4
|
+
* Keep this minimal; you can extend it later (e.g. signal, timeoutMs, debugLabel).
|
|
5
|
+
*/
|
|
6
|
+
export type ModeOptions = {
|
|
7
|
+
async?: boolean;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* A generator helper that makes TypeScript infer the “synchronous value type” for maybe-async expressions.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* const doc = yield* unwrap(Collection.findOne(...))
|
|
14
|
+
* const list = yield* unwrap(Collection.find(...).fetch())
|
|
15
|
+
*
|
|
16
|
+
* Runtime note:
|
|
17
|
+
* This does not “unwrap” Promises by itself. It yields the value/Promise to the runner and returns the
|
|
18
|
+
* value that the runner feeds back via `.next(...)`.
|
|
19
|
+
* @param value The value (or Promise of a value) to yield to the runner.
|
|
20
|
+
* @returns A generator that yields `value` and resolves to the runner-supplied unwrapped `T`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function unwrap<T>(value: MaybePromise<T>): Generator<MaybePromise<T>, T, T>;
|
|
23
|
+
/**
|
|
24
|
+
* Generator shape used by the factory.
|
|
25
|
+
*
|
|
26
|
+
* `TThis` is the type of `this` inside the generator.
|
|
27
|
+
* `Args` are the method parameters (excluding the mode flag).
|
|
28
|
+
* `TReturn` is the final return value of the workflow.
|
|
29
|
+
* `TNext` is the type that is yielded/awaited and fed back via `.next(...)`.
|
|
30
|
+
*
|
|
31
|
+
* Note:
|
|
32
|
+
* - For best inference at yield sites, prefer `yield* unwrap(expr)` for maybe-async expressions.
|
|
33
|
+
*/
|
|
34
|
+
export type ReactiveOrAsyncGen<TThis, Arguments extends any[], TReturn, TNext> = (this: TThis, a: boolean, ...args: Arguments) => Generator<MaybePromise<TNext>, TReturn, TNext>;
|
|
35
|
+
/**
|
|
36
|
+
* The method type produced from the generator signature.
|
|
37
|
+
* Adds overloads so that `{ async: true }` yields a `Promise<...>` return type.
|
|
38
|
+
*/
|
|
39
|
+
export type ReactiveOrAsyncMethod<TThis, P extends any[], R, N> = {
|
|
40
|
+
(this: TThis, ...args: P): R;
|
|
41
|
+
(this: TThis, ...args: [...P, ModeOptions?]): MaybePromise<R>;
|
|
42
|
+
(this: TThis, ...args: [...P, {
|
|
43
|
+
async: true;
|
|
44
|
+
}]): Promise<R>;
|
|
45
|
+
} & {
|
|
46
|
+
/** Exposes the underlying generator for composition via `yield* method.generator.call(this, a, ...)` */
|
|
47
|
+
generator: (this: TThis, a: boolean, ...args: P) => Generator<MaybePromise<N>, R, N>;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Factory that turns a generator workflow into a callable method that can run in sync (reactive) or async mode.
|
|
51
|
+
*
|
|
52
|
+
* Call style:
|
|
53
|
+
* fn(a, b) -> sync/reactive return
|
|
54
|
+
* await fn(a, b, { async: true }) -> async return
|
|
55
|
+
* @param gen Generator workflow. Receives `(a)` which indicates async mode and should `yield`/`yield* unwrap(...)`
|
|
56
|
+
* any values that may be Promises.
|
|
57
|
+
* @returns A callable method with overloads plus a `.generator` property for composition.
|
|
58
|
+
*/
|
|
59
|
+
export default function reactiveOrAsync<TThis, P extends any[], R, N>(gen: (this: TThis, a: boolean, ...args: P) => Generator<MaybePromise<N>, R, N>): ReactiveOrAsyncMethod<TThis, P, R, N>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serializes a value into a string representation.
|
|
3
|
+
* Handles various types, including strings, numbers, booleans, dates, and objects.
|
|
4
|
+
* Falls back to JSON stringification for unsupported types.
|
|
5
|
+
* @param value - The value to serialize.
|
|
6
|
+
* - Strings are returned as-is.
|
|
7
|
+
* - Numbers and booleans are converted to their string representation.
|
|
8
|
+
* - Dates are converted to ISO string format.
|
|
9
|
+
* - Other values are stringified using `JSON.stringify`.
|
|
10
|
+
* @returns A string representation of the value.
|
|
11
|
+
*/
|
|
12
|
+
export default function serializeValue(value: any): string | null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sets a value at a specified path within an object. Creates nested structures
|
|
3
|
+
* (arrays or objects) as needed to set the value at the correct location. Supports
|
|
4
|
+
* deleting the key if the value is `undefined` and the `deleteIfUndefined` flag is set to `true`.
|
|
5
|
+
* @template T - The type of the object to modify.
|
|
6
|
+
* @template K - The type of the value to set.
|
|
7
|
+
* @param object - The object to modify. The object is mutated directly.
|
|
8
|
+
* @param path - The path (dot or bracket notation) where the value should be set.
|
|
9
|
+
* @param value - The value to set at the specified path.
|
|
10
|
+
* @param deleteIfUndefined - A boolean indicating whether to delete the key if the value is `undefined` (default: `false`).
|
|
11
|
+
* @returns The modified object.
|
|
12
|
+
*/
|
|
13
|
+
export default function set<T extends object, K>(object: T, path: string, value: K, deleteIfUndefined?: boolean): T;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sorts an array of items based on multiple fields and their specified sort order.
|
|
3
|
+
* Uses the `fast-sort` library for efficient sorting.
|
|
4
|
+
* @template T - The type of the items in the array.
|
|
5
|
+
* @param items - The array of items to be sorted.
|
|
6
|
+
* @param sortFields - An object defining the sort order for each field.
|
|
7
|
+
* - Keys are the field names, and values are either `1` (ascending) or `-1` (descending).
|
|
8
|
+
* @returns A new array of items sorted based on the specified fields and their order.
|
|
9
|
+
*/
|
|
10
|
+
export default function sortItems<T extends Record<string, any>>(items: T[], sortFields: {
|
|
11
|
+
[P in keyof T]?: -1 | 1;
|
|
12
|
+
} & Record<string, -1 | 1>): T[];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filters an array to ensure unique values based on a specified key or transformation function.
|
|
3
|
+
* @template T - The type of the elements in the array.
|
|
4
|
+
* @param array - The array to filter for unique values.
|
|
5
|
+
* @param fn - A key or transformation function to determine uniqueness.
|
|
6
|
+
* - If a key is provided, it will use the corresponding property of each element for uniqueness.
|
|
7
|
+
* - If a function is provided, it will use the return value of the function applied to each element for uniqueness.
|
|
8
|
+
* @returns A new array containing only unique elements based on the specified key or transformation.
|
|
9
|
+
*/
|
|
10
|
+
export default function uniqueBy<T>(array: T[], fn: keyof T | ((item: T) => any)): T[];
|
package/dist/index.mjs
CHANGED
|
@@ -1,135 +1,122 @@
|
|
|
1
|
-
import { createStorageAdapter as
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
]), u;
|
|
1
|
+
import { createStorageAdapter as e } from "@signaldb/core";
|
|
2
|
+
//#region src/index.ts
|
|
3
|
+
async function t(e, t, n) {
|
|
4
|
+
let r = indexedDB.open(e, t), i = new Promise((e, t) => {
|
|
5
|
+
r.addEventListener("success", () => e()), r.addEventListener("error", () => t(Error(r.error?.message || "Database error"))), r.addEventListener("upgradeneeded", (i) => {
|
|
6
|
+
let a = r.result, o = r.transaction;
|
|
7
|
+
if (n) {
|
|
8
|
+
n(a, o, i.oldVersion, i.newVersion ?? null).then(() => e()).catch(
|
|
9
|
+
/* istanbul ignore next -- @preserve */
|
|
10
|
+
(e) => {
|
|
11
|
+
t(e);
|
|
12
|
+
}
|
|
13
|
+
);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
/* istanbul ignore next -- @preserve */
|
|
17
|
+
e();
|
|
18
|
+
});
|
|
19
|
+
}), a = new Promise((e, t) => {
|
|
20
|
+
r.addEventListener("success", () => e(r.result)), r.addEventListener("error", () => t(Error(r.error?.message || "Database error")));
|
|
21
|
+
});
|
|
22
|
+
return await Promise.all([a, i]), a;
|
|
24
23
|
}
|
|
25
|
-
function
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return h(d, c);
|
|
53
|
-
};
|
|
24
|
+
function n(e) {
|
|
25
|
+
let n = t(e.databaseName || "signaldb", e.version, async (t, n) => {
|
|
26
|
+
e.onUpgrade && await e.onUpgrade(t, n, t.version, e.version);
|
|
27
|
+
let r = /* @__PURE__ */ new Set();
|
|
28
|
+
for (let n = 0; n < t.objectStoreNames.length; n += 1) {
|
|
29
|
+
let i = t.objectStoreNames.item(n);
|
|
30
|
+
!i || i in e.schema || r.add(i);
|
|
31
|
+
}
|
|
32
|
+
r.forEach((e) => {
|
|
33
|
+
t.objectStoreNames.contains(e) && t.deleteObjectStore(e);
|
|
34
|
+
});
|
|
35
|
+
for (let [r, i] of Object.entries(e.schema)) {
|
|
36
|
+
let e = t.objectStoreNames.contains(r) ? n.objectStore(r) : t.createObjectStore(r, { keyPath: "id" }), a = /* @__PURE__ */ new Set();
|
|
37
|
+
for (let t = 0; t < e.indexNames.length; t += 1) {
|
|
38
|
+
let n = e.indexNames.item(t);
|
|
39
|
+
!n || i.includes(n) || a.add(n);
|
|
40
|
+
}
|
|
41
|
+
a.forEach((t) => {
|
|
42
|
+
e.indexNames.contains(t) && e.deleteIndex(t);
|
|
43
|
+
}), i.forEach((t) => {
|
|
44
|
+
t !== "id" && (e.indexNames.contains(t) || e.createIndex(t, t, { unique: !1 }));
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
return function(e) {
|
|
49
|
+
return r(e, n);
|
|
50
|
+
};
|
|
54
51
|
}
|
|
55
|
-
function
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
})));
|
|
122
|
-
},
|
|
123
|
-
removeAll: async () => {
|
|
124
|
-
const e = await c(!0);
|
|
125
|
-
return new Promise((r, t) => {
|
|
126
|
-
const a = e.clear();
|
|
127
|
-
a.addEventListener("success", () => r()), a.addEventListener("error", () => t(new Error(a.error?.message || "Error clearing items")));
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
});
|
|
52
|
+
function r(t, n) {
|
|
53
|
+
let r = async (e = !1) => {
|
|
54
|
+
let r = await n;
|
|
55
|
+
if (!r) throw Error("Database not initialized");
|
|
56
|
+
return r.transaction(t, e ? "readwrite" : "readonly").objectStore(t);
|
|
57
|
+
}, i = async (e) => {
|
|
58
|
+
let t = await r();
|
|
59
|
+
if (!t.indexNames.contains(e)) throw Error(`Index on field "${e}" does not exist`);
|
|
60
|
+
return new Promise((n, r) => {
|
|
61
|
+
let i = t.index(e), a = /* @__PURE__ */ new Map(), o = i.openCursor();
|
|
62
|
+
o.addEventListener("success", () => {
|
|
63
|
+
let e = o.result;
|
|
64
|
+
if (e) {
|
|
65
|
+
let t = e.key, n = e.value.id;
|
|
66
|
+
a.has(t) || a.set(t, /* @__PURE__ */ new Set()), a.get(t)?.add(n), e.continue();
|
|
67
|
+
} else n(a);
|
|
68
|
+
}), o.addEventListener("error", () => r(Error(o.error?.message || "Error reading index")));
|
|
69
|
+
});
|
|
70
|
+
}, a = async (e) => {
|
|
71
|
+
let t = await r(!0);
|
|
72
|
+
return new Promise((n, r) => {
|
|
73
|
+
let i = t.get(e);
|
|
74
|
+
i.addEventListener("success", () => n(i.result || null)), i.addEventListener("error", () => r(Error(i.error?.message || "Error fetching item")));
|
|
75
|
+
});
|
|
76
|
+
}, o = async (e) => {
|
|
77
|
+
let t = await r(!0);
|
|
78
|
+
await Promise.all(e.map((e) => new Promise((n, r) => {
|
|
79
|
+
let i = t.put(e);
|
|
80
|
+
i.addEventListener("success", () => n()), i.addEventListener("error", () => r(Error(i.error?.message || "Error inserting or replacing item")));
|
|
81
|
+
})));
|
|
82
|
+
};
|
|
83
|
+
return e({
|
|
84
|
+
setup: async () => {
|
|
85
|
+
if (!(await n).objectStoreNames.contains(t)) throw Error(`Object store "${t}" does not exist in database. Make sure to define it in the schema when initializing the adapter.`);
|
|
86
|
+
},
|
|
87
|
+
teardown: async () => {
|
|
88
|
+
(await n).close();
|
|
89
|
+
},
|
|
90
|
+
readAll: async () => {
|
|
91
|
+
let e = await r();
|
|
92
|
+
return new Promise((t, n) => {
|
|
93
|
+
let r = e.getAll();
|
|
94
|
+
r.addEventListener("success", () => t(r.result)), r.addEventListener("error", () => n(Error(r.error?.message || "Error fetching items")));
|
|
95
|
+
});
|
|
96
|
+
},
|
|
97
|
+
readIds: async (e) => (await Promise.all(e.map((e) => a(e)))).filter((e) => e !== null),
|
|
98
|
+
createIndex: async () => {},
|
|
99
|
+
dropIndex: async () => {},
|
|
100
|
+
readIndex: i,
|
|
101
|
+
insert: (e) => o(e),
|
|
102
|
+
replace: (e) => o(e),
|
|
103
|
+
remove: async (e) => {
|
|
104
|
+
let t = await r(!0);
|
|
105
|
+
await Promise.all(e.map(async (e) => new Promise((n, r) => {
|
|
106
|
+
let i = t.delete(e.id);
|
|
107
|
+
i.addEventListener("success", () => n()), i.addEventListener("error", () => r(Error(i.error?.message || "Error removing item")));
|
|
108
|
+
})));
|
|
109
|
+
},
|
|
110
|
+
removeAll: async () => {
|
|
111
|
+
let e = await r(!0);
|
|
112
|
+
return new Promise((t, n) => {
|
|
113
|
+
let r = e.clear();
|
|
114
|
+
r.addEventListener("success", () => t()), r.addEventListener("error", () => n(Error(r.error?.message || "Error clearing items")));
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
});
|
|
131
118
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
//# sourceMappingURL=index.mjs.map
|
|
119
|
+
//#endregion
|
|
120
|
+
export { n as default };
|
|
121
|
+
|
|
122
|
+
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":["import { createStorageAdapter } from '@signaldb/core';\n/**\n * Opens the IndexedDB database and creates the object store if it doesn't exist.\n * @param databaseName - The name of the database.\n * @param version - The version of the database.\n * @param onUpgrade - Optional callback for handling database upgrades.\n * @returns A promise that resolves with the opened database.\n */\nasync function openDatabase(databaseName, version, onUpgrade) {\n const request = indexedDB.open(databaseName, version);\n const upgradePromise = new Promise((resolve, reject) => {\n request.addEventListener('success', () => resolve());\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Database error')));\n request.addEventListener('upgradeneeded', (event) => {\n const database = request.result;\n const tx = request.transaction;\n if (onUpgrade) {\n onUpgrade(database, tx, event.oldVersion, event.newVersion ?? null)\n .then(() => resolve())\n .catch(\n /* istanbul ignore next -- @preserve */\n (error) => {\n reject(error);\n });\n return;\n }\n // No custom upgrade logic provided, resolve immediately\n /* istanbul ignore next -- @preserve */\n resolve();\n });\n });\n const databasePromise = new Promise((resolve, reject) => {\n request.addEventListener('success', () => resolve(request.result));\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Database error')));\n });\n await Promise.all([\n databasePromise,\n upgradePromise,\n ]);\n return databasePromise;\n}\n/**\n * Prepares an IndexedDB storage adapter for SignalDB with the specified options.\n * @param options - Configuration options for the IndexedDB adapter.\n * @param options.databaseName - The name of the IndexedDB database. Defaults to 'signaldb'.\n * @param options.version - The version of the database schema.\n * @param options.schema - An object defining the schema of the database, where keys are store names and values are arrays of index names.\n * @param options.onUpgrade - Optional callback for handling database upgrades.\n * @returns A function that takes a store name and returns a SignalDB storage adapter for that store.\n */\nexport default function prepareIndexedDB(options) {\n const databaseName = options.databaseName || 'signaldb';\n const databasePromise = openDatabase(databaseName, options.version, async (database, tx) => {\n if (options.onUpgrade) {\n await options.onUpgrade(database, tx, database.version, options.version);\n }\n const storesToDelete = new Set();\n for (let i = 0; i < database.objectStoreNames.length; i += 1) {\n const storeName = database.objectStoreNames.item(i);\n if (!storeName || storeName in options.schema)\n continue;\n storesToDelete.add(storeName);\n }\n // Delete stores that are not in the new schema\n storesToDelete.forEach((storeName) => {\n if (!database.objectStoreNames.contains(storeName))\n return;\n database.deleteObjectStore(storeName);\n });\n // Create or update stores as per the new schema\n for (const [storeName, indexes] of Object.entries(options.schema)) {\n const store = database.objectStoreNames.contains(storeName)\n ? tx.objectStore(storeName)\n : database.createObjectStore(storeName, {\n keyPath: 'id',\n });\n const indexesToDrop = new Set();\n for (let i = 0; i < store.indexNames.length; i += 1) {\n const indexName = store.indexNames.item(i);\n if (!indexName || indexes.includes(indexName))\n continue;\n indexesToDrop.add(indexName);\n }\n // Drop indexes that are not in the new schema\n indexesToDrop.forEach((indexName) => {\n if (!store.indexNames.contains(indexName))\n return;\n store.deleteIndex(indexName);\n });\n // Create indexes as per the new schema\n indexes.forEach((index) => {\n if (index === 'id')\n return;\n if (store.indexNames.contains(index))\n return;\n store.createIndex(index, index, { unique: false });\n });\n }\n });\n return function indexedDBAdapter(storeName) {\n return createIndexedDBAdapter(storeName, databasePromise);\n };\n}\n/**\n * Creates a storage adapter for managing a SignalDB collection using IndexedDB.\n * This adapter reads and writes data to an IndexedDB object store, with customizable serialization and deserialization.\n * @template T - The type of the items in the collection.\n * @template I - The type of the unique identifier for the items.\n * @param storeName - A unique name for the collection, used as the database name.\n * @param databasePromise - A promise that resolves to an opened IndexedDB database.\n * @returns A SignalDB storage adapter for managing data in IndexedDB.\n */\nfunction createIndexedDBAdapter(storeName, databasePromise) {\n const getStore = async (writeAccess = false) => {\n const database = await databasePromise;\n if (!database)\n throw new Error('Database not initialized');\n const transaction = database.transaction(storeName, writeAccess ? 'readwrite' : 'readonly');\n const store = transaction.objectStore(storeName);\n return store;\n };\n const readIndex = async (field) => {\n const store = await getStore();\n if (!store.indexNames.contains(field)) {\n throw new Error(`Index on field \"${field}\" does not exist`);\n }\n return new Promise((resolve, reject) => {\n const index = store.index(field);\n const result = new Map();\n const request = index.openCursor();\n request.addEventListener('success', () => {\n const cursor = request.result;\n if (cursor) {\n const key = cursor.key;\n const id = cursor.value.id;\n if (!result.has(key)) {\n result.set(key, new Set());\n }\n result.get(key)?.add(id);\n cursor.continue();\n }\n else {\n resolve(result);\n }\n });\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error reading index')));\n });\n };\n const getById = async (id) => {\n const store = await getStore(true);\n return new Promise((resolve, reject) => {\n const request = store.get(id);\n request.addEventListener('success', () => resolve(request.result || null));\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching item')));\n });\n };\n const insertOrReplace = async (items) => {\n const store = await getStore(true);\n await Promise.all(items.map(item => new Promise((resolve, reject) => {\n const request = store.put(item);\n request.addEventListener('success', () => resolve());\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error inserting or replacing item')));\n })));\n };\n return createStorageAdapter({\n // lifecycle methods\n setup: async () => {\n const database = await databasePromise;\n if (database.objectStoreNames.contains(storeName))\n return;\n throw new Error(`Object store \"${storeName}\" does not exist in database. Make sure to define it in the schema when initializing the adapter.`);\n },\n teardown: async () => {\n const database = await databasePromise;\n database.close();\n },\n // data retrieval methods\n readAll: async () => {\n const store = await getStore();\n return new Promise((resolve, reject) => {\n const request = store.getAll();\n request.addEventListener('success', () => resolve(request.result));\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching items')));\n });\n },\n readIds: async (ids) => {\n const results = await Promise.all(ids.map(id => getById(id)));\n return results.filter(item => item !== null);\n },\n // index methods\n createIndex: async () => {\n /* noop */\n },\n dropIndex: async () => {\n /* noop */\n },\n readIndex,\n // data manipulation methods\n insert: items => insertOrReplace(items),\n replace: items => insertOrReplace(items),\n remove: async (itemsToRemove) => {\n const store = await getStore(true);\n await Promise.all(itemsToRemove.map(async (item) => new Promise((resolve, reject) => {\n const request = store.delete(item.id);\n request.addEventListener('success', () => resolve());\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error removing item')));\n })));\n },\n removeAll: async () => {\n const store = await getStore(true);\n return new Promise((resolve, reject) => {\n const request = store.clear();\n request.addEventListener('success', () => resolve());\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error clearing items')));\n });\n },\n });\n}\n"],"names":["openDatabase","databaseName","version","onUpgrade","request","upgradePromise","resolve","reject","event","database","tx","error","databasePromise","prepareIndexedDB","options","storesToDelete","i","storeName","indexes","store","indexesToDrop","indexName","index","createIndexedDBAdapter","getStore","writeAccess","readIndex","field","result","cursor","key","id","getById","insertOrReplace","items","item","createStorageAdapter","ids","itemsToRemove"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { createStorageAdapter } from '@signaldb/core'\n\n/**\n * Opens the IndexedDB database and creates the object store if it doesn't exist.\n * @param databaseName - The name of the database.\n * @param version - The version of the database.\n * @param onUpgrade - Optional callback for handling database upgrades.\n * @returns A promise that resolves with the opened database.\n */\nasync function openDatabase(\n databaseName: string,\n version: number,\n onUpgrade?: (\n database: IDBDatabase,\n transaction: IDBTransaction,\n oldVersion: number,\n newVersion: number | null,\n ) => Promise<void>,\n): Promise<IDBDatabase> {\n const request = indexedDB.open(databaseName, version)\n const upgradePromise = new Promise<void>((resolve, reject) => {\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Database error')))\n request.addEventListener('upgradeneeded', (event) => {\n const database = request.result\n const tx = request.transaction as IDBTransaction\n if (onUpgrade) {\n onUpgrade(\n database,\n tx,\n event.oldVersion,\n event.newVersion ?? null,\n )\n .then(() => resolve())\n .catch(\n /* istanbul ignore next -- @preserve */\n (error) => {\n reject(error as Error)\n },\n )\n return\n }\n\n // No custom upgrade logic provided, resolve immediately\n /* istanbul ignore next -- @preserve */\n resolve()\n })\n })\n const databasePromise = new Promise<IDBDatabase>((resolve, reject) => {\n request.addEventListener('success', () => resolve(request.result))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Database error')))\n })\n await Promise.all([\n databasePromise,\n upgradePromise,\n ])\n return databasePromise\n}\n\nexport type IndexedDBOptions = {\n databaseName?: string,\n version: number,\n schema: Record<string, string[]>,\n onUpgrade?: (\n database: IDBDatabase,\n transaction: IDBTransaction,\n oldVersion: number,\n newVersion: number | null,\n ) => Promise<void>,\n}\n\n/**\n * Prepares an IndexedDB storage adapter for SignalDB with the specified options.\n * @param options - Configuration options for the IndexedDB adapter.\n * @param options.databaseName - The name of the IndexedDB database. Defaults to 'signaldb'.\n * @param options.version - The version of the database schema.\n * @param options.schema - An object defining the schema of the database, where keys are store names and values are arrays of index names.\n * @param options.onUpgrade - Optional callback for handling database upgrades.\n * @returns A function that takes a store name and returns a SignalDB storage adapter for that store.\n */\nexport default function prepareIndexedDB(options: IndexedDBOptions) {\n const databaseName = options.databaseName || 'signaldb'\n const databasePromise = openDatabase(\n databaseName,\n options.version,\n async (database, tx) => {\n if (options.onUpgrade) {\n await options.onUpgrade(database, tx, database.version, options.version)\n }\n\n const storesToDelete = new Set<string>()\n for (let i = 0; i < database.objectStoreNames.length; i += 1) {\n const storeName = database.objectStoreNames.item(i)\n if (!storeName || storeName in options.schema) continue\n storesToDelete.add(storeName)\n }\n\n // Delete stores that are not in the new schema\n storesToDelete.forEach((storeName) => {\n if (!database.objectStoreNames.contains(storeName)) return\n database.deleteObjectStore(storeName)\n })\n\n // Create or update stores as per the new schema\n for (const [storeName, indexes] of Object.entries(options.schema)) {\n const store = database.objectStoreNames.contains(storeName)\n ? tx.objectStore(storeName)\n : database.createObjectStore(storeName, {\n keyPath: 'id',\n })\n\n const indexesToDrop = new Set<string>()\n for (let i = 0; i < store.indexNames.length; i += 1) {\n const indexName = store.indexNames.item(i)\n if (!indexName || indexes.includes(indexName)) continue\n indexesToDrop.add(indexName)\n }\n\n // Drop indexes that are not in the new schema\n indexesToDrop.forEach((indexName) => {\n if (!store.indexNames.contains(indexName)) return\n store.deleteIndex(indexName)\n })\n\n // Create indexes as per the new schema\n indexes.forEach((index) => {\n if (index === 'id') return\n if (store.indexNames.contains(index)) return\n store.createIndex(index, index, { unique: false })\n })\n }\n },\n )\n\n return function indexedDBAdapter<\n T extends { id: I } & Record<string, any>,\n I extends IDBValidKey,\n >(storeName: string) {\n return createIndexedDBAdapter<T, I>(storeName, databasePromise)\n }\n}\n\n/**\n * Creates a storage adapter for managing a SignalDB collection using IndexedDB.\n * This adapter reads and writes data to an IndexedDB object store, with customizable serialization and deserialization.\n * @template T - The type of the items in the collection.\n * @template I - The type of the unique identifier for the items.\n * @param storeName - A unique name for the collection, used as the database name.\n * @param databasePromise - A promise that resolves to an opened IndexedDB database.\n * @returns A SignalDB storage adapter for managing data in IndexedDB.\n */\nfunction createIndexedDBAdapter<\n T extends { id: I } & Record<string, any>,\n I extends IDBValidKey,\n>(storeName: string, databasePromise: Promise<IDBDatabase>) {\n const getStore = async (writeAccess = false) => {\n const database = await databasePromise\n if (!database) throw new Error('Database not initialized')\n const transaction = database.transaction(storeName, writeAccess ? 'readwrite' : 'readonly')\n const store = transaction.objectStore(storeName)\n return store\n }\n\n const readIndex = async (field: string) => {\n const store = await getStore()\n if (!store.indexNames.contains(field)) {\n throw new Error(`Index on field \"${field}\" does not exist`)\n }\n return new Promise<Map<any, Set<I>>>((resolve, reject) => {\n const index = store.index(field)\n const result = new Map<any, Set<I>>()\n const request = index.openCursor()\n request.addEventListener('success', () => {\n const cursor = request.result\n if (cursor) {\n const key = cursor.key as T[keyof T & string]\n const id = (cursor.value as T).id\n if (!result.has(key)) {\n result.set(key, new Set())\n }\n result.get(key)?.add(id)\n cursor.continue()\n } else {\n resolve(result)\n }\n })\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error reading index')))\n })\n }\n\n const getById = async (id: I) => {\n const store = await getStore(true)\n return new Promise<T | null>((resolve, reject) => {\n const request = store.get(id)\n request.addEventListener('success', () => resolve(request.result as T || null))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching item')))\n })\n }\n\n const insertOrReplace = async (items: T[]) => {\n const store = await getStore(true)\n await Promise.all(items.map(item => new Promise<void>((resolve, reject) => {\n const request = store.put(item)\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error inserting or replacing item')))\n })))\n }\n\n return createStorageAdapter<T, I>({\n // lifecycle methods\n setup: async () => {\n const database = await databasePromise\n if (database.objectStoreNames.contains(storeName)) return\n throw new Error(`Object store \"${storeName}\" does not exist in database. Make sure to define it in the schema when initializing the adapter.`)\n },\n teardown: async () => {\n const database = await databasePromise\n database.close()\n },\n\n // data retrieval methods\n readAll: async () => {\n const store = await getStore()\n return new Promise<T[]>((resolve, reject) => {\n const request = store.getAll()\n request.addEventListener('success', () => resolve(request.result as T[]))\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error fetching items')))\n })\n },\n readIds: async (ids) => {\n const results = await Promise.all(ids.map(id => getById(id)))\n return results.filter(item => item !== null)\n },\n\n // index methods\n createIndex: async () => {\n /* noop */\n },\n dropIndex: async () => {\n /* noop */\n },\n readIndex,\n\n // data manipulation methods\n insert: items => insertOrReplace(items),\n replace: items => insertOrReplace(items),\n remove: async (itemsToRemove) => {\n const store = await getStore(true)\n await Promise.all(itemsToRemove.map(async item => new Promise<void>((resolve, reject) => {\n const request = store.delete(item.id)\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error removing item')))\n })))\n },\n removeAll: async () => {\n const store = await getStore(true)\n return new Promise<void>((resolve, reject) => {\n const request = store.clear()\n request.addEventListener('success', () => resolve())\n request.addEventListener('error', () => reject(new Error(request.error?.message || 'Error clearing items')))\n })\n },\n })\n}\n"],"mappings":"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"}
|
package/dist/index.umd.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(
|
|
2
|
-
//# sourceMappingURL=index.umd.js.map
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?module.exports=t(require("@signaldb/core")):typeof define==`function`&&define.amd?define([`@signaldb/core`],t):(e=typeof globalThis<`u`?globalThis:e||self,e.SignalDB=t(e._signaldb_core))})(this,function(e){async function t(e,t,n){let r=indexedDB.open(e,t),i=new Promise((e,t)=>{r.addEventListener(`success`,()=>e()),r.addEventListener(`error`,()=>t(Error(r.error?.message||`Database error`))),r.addEventListener(`upgradeneeded`,i=>{let a=r.result,o=r.transaction;if(n){n(a,o,i.oldVersion,i.newVersion??null).then(()=>e()).catch(e=>{t(e)});return}e()})}),a=new Promise((e,t)=>{r.addEventListener(`success`,()=>e(r.result)),r.addEventListener(`error`,()=>t(Error(r.error?.message||`Database error`)))});return await Promise.all([a,i]),a}function n(e){let n=t(e.databaseName||`signaldb`,e.version,async(t,n)=>{e.onUpgrade&&await e.onUpgrade(t,n,t.version,e.version);let r=new Set;for(let n=0;n<t.objectStoreNames.length;n+=1){let i=t.objectStoreNames.item(n);!i||i in e.schema||r.add(i)}r.forEach(e=>{t.objectStoreNames.contains(e)&&t.deleteObjectStore(e)});for(let[r,i]of Object.entries(e.schema)){let e=t.objectStoreNames.contains(r)?n.objectStore(r):t.createObjectStore(r,{keyPath:`id`}),a=new Set;for(let t=0;t<e.indexNames.length;t+=1){let n=e.indexNames.item(t);!n||i.includes(n)||a.add(n)}a.forEach(t=>{e.indexNames.contains(t)&&e.deleteIndex(t)}),i.forEach(t=>{t!==`id`&&(e.indexNames.contains(t)||e.createIndex(t,t,{unique:!1}))})}});return function(e){return r(e,n)}}function r(t,n){let r=async(e=!1)=>{let r=await n;if(!r)throw Error(`Database not initialized`);return r.transaction(t,e?`readwrite`:`readonly`).objectStore(t)},i=async e=>{let t=await r();if(!t.indexNames.contains(e))throw Error(`Index on field "${e}" does not exist`);return new Promise((n,r)=>{let i=t.index(e),a=new Map,o=i.openCursor();o.addEventListener(`success`,()=>{let e=o.result;if(e){let t=e.key,n=e.value.id;a.has(t)||a.set(t,new Set),a.get(t)?.add(n),e.continue()}else n(a)}),o.addEventListener(`error`,()=>r(Error(o.error?.message||`Error reading index`)))})},a=async e=>{let t=await r(!0);return new Promise((n,r)=>{let i=t.get(e);i.addEventListener(`success`,()=>n(i.result||null)),i.addEventListener(`error`,()=>r(Error(i.error?.message||`Error fetching item`)))})},o=async e=>{let t=await r(!0);await Promise.all(e.map(e=>new Promise((n,r)=>{let i=t.put(e);i.addEventListener(`success`,()=>n()),i.addEventListener(`error`,()=>r(Error(i.error?.message||`Error inserting or replacing item`)))})))};return(0,e.createStorageAdapter)({setup:async()=>{if(!(await n).objectStoreNames.contains(t))throw Error(`Object store "${t}" does not exist in database. Make sure to define it in the schema when initializing the adapter.`)},teardown:async()=>{(await n).close()},readAll:async()=>{let e=await r();return new Promise((t,n)=>{let r=e.getAll();r.addEventListener(`success`,()=>t(r.result)),r.addEventListener(`error`,()=>n(Error(r.error?.message||`Error fetching items`)))})},readIds:async e=>(await Promise.all(e.map(e=>a(e)))).filter(e=>e!==null),createIndex:async()=>{},dropIndex:async()=>{},readIndex:i,insert:e=>o(e),replace:e=>o(e),remove:async e=>{let t=await r(!0);await Promise.all(e.map(async e=>new Promise((n,r)=>{let i=t.delete(e.id);i.addEventListener(`success`,()=>n()),i.addEventListener(`error`,()=>r(Error(i.error?.message||`Error removing item`)))})))},removeAll:async()=>{let e=await r(!0);return new Promise((t,n)=>{let r=e.clear();r.addEventListener(`success`,()=>t()),r.addEventListener(`error`,()=>n(Error(r.error?.message||`Error clearing items`)))})}})}return n});
|
|
2
|
+
//# sourceMappingURL=index.umd.js.map
|