@yaasl/core 0.13.1 → 0.14.0-alpha.1
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/@types/effects/index.d.ts +1 -0
- package/dist/@types/effects/indexed-db.d.ts +5 -3
- package/dist/@types/effects/session-storage.d.ts +0 -1
- package/dist/@types/effects/sync.d.ts +5 -0
- package/dist/@types/utils/idb-store.d.ts +2 -1
- package/dist/cjs/base/create-atom.js +5 -0
- package/dist/cjs/effects/index.js +3 -1
- package/dist/cjs/effects/indexed-db.js +19 -42
- package/dist/cjs/effects/session-storage.js +0 -1
- package/dist/cjs/effects/sync.js +54 -0
- package/dist/cjs/utils/idb-store.js +5 -0
- package/dist/cjs/utils/queue.js +2 -1
- package/dist/esm/base/create-atom.js +6 -1
- package/dist/esm/effects/index.js +1 -0
- package/dist/esm/effects/indexed-db.js +18 -41
- package/dist/esm/effects/session-storage.js +0 -1
- package/dist/esm/effects/sync.js +52 -0
- package/dist/esm/utils/idb-store.js +5 -0
- package/dist/esm/utils/queue.js +2 -1
- package/package.json +1 -1
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
export interface IndexedDbOptions {
|
|
2
2
|
/** Use your own store key. Will be `atom.name` by default. */
|
|
3
3
|
key?: string;
|
|
4
|
-
/** Disable the synchronization of values over browser tabs */
|
|
5
|
-
noTabSync?: boolean;
|
|
6
4
|
}
|
|
7
5
|
/** Middleware to save and load atom values to an indexedDb.
|
|
8
6
|
*
|
|
9
7
|
* Will use one database and store for all atoms with your `CONFIG.name`
|
|
10
8
|
* as name or `yaasl` if not set.
|
|
11
9
|
*
|
|
10
|
+
* Should be used in combination with the `sync` effect, to ensure value integrity.
|
|
11
|
+
*
|
|
12
12
|
* @param {IndexedDbOptions | undefined} options
|
|
13
13
|
* @param options.key Use your own store key. Will be `atom.name` by default.
|
|
14
14
|
*
|
|
15
15
|
* @returns The effect to be used on atoms.
|
|
16
16
|
**/
|
|
17
|
-
export declare const indexedDb: (...[optionsArg]: [] | [undefined] | [IndexedDbOptions]) => import("./create-effect").EffectAtomCallback<IndexedDbOptions | undefined, unknown
|
|
17
|
+
export declare const indexedDb: ((...[optionsArg]: [] | [undefined] | [IndexedDbOptions]) => import("./create-effect").EffectAtomCallback<IndexedDbOptions | undefined, unknown>) & {
|
|
18
|
+
getAllKeys: () => Promise<string[]>;
|
|
19
|
+
};
|
|
@@ -15,7 +15,6 @@ export interface SessionStorageOptions {
|
|
|
15
15
|
* @param {SessionStorageOptions | undefined} options
|
|
16
16
|
* @param options.key Use your own key for the session storage.
|
|
17
17
|
* Will be "{config-name}/{atom-name}" by default.
|
|
18
|
-
* @param options.noTabSync Disable the synchronization of values over browser tabs.
|
|
19
18
|
* @param options.parser Custom functions to stringify and parse values. Defaults to JSON.stringify and JSON.parse. Use this when handling complex datatypes like Maps or Sets.
|
|
20
19
|
*
|
|
21
20
|
* @returns The effect to be used on atoms.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
export declare class IdbStore<T> {
|
|
1
|
+
export declare class IdbStore<T = unknown> {
|
|
2
2
|
private name;
|
|
3
3
|
private database?;
|
|
4
4
|
constructor(name: string);
|
|
5
5
|
private getStore;
|
|
6
|
+
getAllKeys(): Promise<string[]>;
|
|
6
7
|
get(key: string): Promise<T | undefined>;
|
|
7
8
|
set(key: string, value: T): Promise<IDBValidKey | undefined>;
|
|
8
9
|
delete(key: string): Promise<undefined>;
|
|
@@ -46,6 +46,11 @@ class Atom extends stateful_1.Stateful {
|
|
|
46
46
|
* new value based off the previous value.
|
|
47
47
|
*/
|
|
48
48
|
set(next) {
|
|
49
|
+
if (this.didInit !== true) {
|
|
50
|
+
throw new Error((0, utils_1.consoleMessage)("Tried to set a value during initialization. " +
|
|
51
|
+
"You are probably using an async effect. " +
|
|
52
|
+
"Use `await atom.didInit` to wait for the initialization process to be finished.", { scope: this.name }));
|
|
53
|
+
}
|
|
49
54
|
const oldState = this.get();
|
|
50
55
|
const newState = (0, utils_1.updater)(next, oldState);
|
|
51
56
|
if (oldState === newState)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createMigrationStep = exports.migration = exports.expiration = exports.indexedDb = exports.sessionStorage = exports.localStorage = exports.autoSort = exports.createEffect = void 0;
|
|
3
|
+
exports.sync = exports.createMigrationStep = exports.migration = exports.expiration = exports.indexedDb = exports.sessionStorage = exports.localStorage = exports.autoSort = exports.createEffect = void 0;
|
|
4
4
|
var create_effect_1 = require("./create-effect");
|
|
5
5
|
Object.defineProperty(exports, "createEffect", { enumerable: true, get: function () { return create_effect_1.createEffect; } });
|
|
6
6
|
var auto_sort_1 = require("./auto-sort");
|
|
@@ -16,3 +16,5 @@ Object.defineProperty(exports, "expiration", { enumerable: true, get: function (
|
|
|
16
16
|
var migration_1 = require("./migration");
|
|
17
17
|
Object.defineProperty(exports, "migration", { enumerable: true, get: function () { return migration_1.migration; } });
|
|
18
18
|
Object.defineProperty(exports, "createMigrationStep", { enumerable: true, get: function () { return migration_1.createMigrationStep; } });
|
|
19
|
+
var sync_1 = require("./sync");
|
|
20
|
+
Object.defineProperty(exports, "sync", { enumerable: true, get: function () { return sync_1.sync; } });
|
|
@@ -12,61 +12,34 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.indexedDb = void 0;
|
|
13
13
|
const create_effect_1 = require("./create-effect");
|
|
14
14
|
const base_1 = require("../base");
|
|
15
|
-
const get_scoped_key_1 = require("../utils/get-scoped-key");
|
|
16
15
|
const idb_store_1 = require("../utils/idb-store");
|
|
17
16
|
let atomDb = null;
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
changeTrigger = null;
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
changeTrigger = "sync";
|
|
28
|
-
onTabSync();
|
|
29
|
-
};
|
|
30
|
-
return {
|
|
31
|
-
pushSync: () => {
|
|
32
|
-
if (changeTrigger === "sync") {
|
|
33
|
-
changeTrigger = null;
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
changeTrigger = "self";
|
|
37
|
-
channel.postMessage("sync");
|
|
38
|
-
},
|
|
39
|
-
};
|
|
17
|
+
const getAtomDb = () => {
|
|
18
|
+
var _a;
|
|
19
|
+
if (!atomDb) {
|
|
20
|
+
atomDb = new idb_store_1.IdbStore((_a = base_1.CONFIG.name) !== null && _a !== void 0 ? _a : "yaasl");
|
|
21
|
+
}
|
|
22
|
+
return atomDb;
|
|
40
23
|
};
|
|
41
24
|
/** Middleware to save and load atom values to an indexedDb.
|
|
42
25
|
*
|
|
43
26
|
* Will use one database and store for all atoms with your `CONFIG.name`
|
|
44
27
|
* as name or `yaasl` if not set.
|
|
45
28
|
*
|
|
29
|
+
* Should be used in combination with the `sync` effect, to ensure value integrity.
|
|
30
|
+
*
|
|
46
31
|
* @param {IndexedDbOptions | undefined} options
|
|
47
32
|
* @param options.key Use your own store key. Will be `atom.name` by default.
|
|
48
33
|
*
|
|
49
34
|
* @returns The effect to be used on atoms.
|
|
50
35
|
**/
|
|
51
|
-
exports.indexedDb = (0, create_effect_1.createEffect)(({ atom, options }) => {
|
|
36
|
+
exports.indexedDb = Object.assign((0, create_effect_1.createEffect)(({ atom, options }) => {
|
|
52
37
|
var _a;
|
|
53
38
|
const key = (_a = options === null || options === void 0 ? void 0 : options.key) !== null && _a !== void 0 ? _a : atom.name;
|
|
54
|
-
const { pushSync } = (options === null || options === void 0 ? void 0 : options.noTabSync)
|
|
55
|
-
? {}
|
|
56
|
-
: createSync(key, () => {
|
|
57
|
-
void (atomDb === null || atomDb === void 0 ? void 0 : atomDb.get(key).then(value => {
|
|
58
|
-
if (!value)
|
|
59
|
-
return;
|
|
60
|
-
atom.set(value);
|
|
61
|
-
}));
|
|
62
|
-
});
|
|
63
39
|
return {
|
|
64
40
|
sort: "pre",
|
|
65
41
|
init: (_a) => __awaiter(void 0, [_a], void 0, function* ({ atom, set }) {
|
|
66
|
-
|
|
67
|
-
if (!atomDb) {
|
|
68
|
-
atomDb = new idb_store_1.IdbStore((_b = base_1.CONFIG.name) !== null && _b !== void 0 ? _b : "yaasl");
|
|
69
|
-
}
|
|
42
|
+
const atomDb = getAtomDb();
|
|
70
43
|
const existing = yield atomDb.get(key);
|
|
71
44
|
if (existing != null) {
|
|
72
45
|
set(existing);
|
|
@@ -76,11 +49,15 @@ exports.indexedDb = (0, create_effect_1.createEffect)(({ atom, options }) => {
|
|
|
76
49
|
}
|
|
77
50
|
}),
|
|
78
51
|
set: ({ value, atom }) => {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
52
|
+
// Don't wait for promises since this would cause lag
|
|
53
|
+
if (value === atom.defaultValue) {
|
|
54
|
+
void (atomDb === null || atomDb === void 0 ? void 0 : atomDb.delete(key));
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
void (atomDb === null || atomDb === void 0 ? void 0 : atomDb.set(key, value));
|
|
58
|
+
}
|
|
84
59
|
},
|
|
85
60
|
};
|
|
61
|
+
}), {
|
|
62
|
+
getAllKeys: () => getAtomDb().getAllKeys(),
|
|
86
63
|
});
|
|
@@ -10,7 +10,6 @@ const string_storage_1 = require("../utils/string-storage");
|
|
|
10
10
|
* @param {SessionStorageOptions | undefined} options
|
|
11
11
|
* @param options.key Use your own key for the session storage.
|
|
12
12
|
* Will be "{config-name}/{atom-name}" by default.
|
|
13
|
-
* @param options.noTabSync Disable the synchronization of values over browser tabs.
|
|
14
13
|
* @param options.parser Custom functions to stringify and parse values. Defaults to JSON.stringify and JSON.parse. Use this when handling complex datatypes like Maps or Sets.
|
|
15
14
|
*
|
|
16
15
|
* @returns The effect to be used on atoms.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sync = void 0;
|
|
4
|
+
const utils_1 = require("@yaasl/utils");
|
|
5
|
+
const create_effect_1 = require("./create-effect");
|
|
6
|
+
const base_1 = require("../base");
|
|
7
|
+
const getId = () => { var _a, _b; return (_b = (_a = (0, utils_1.getWindow)()) === null || _a === void 0 ? void 0 : _a.crypto.randomUUID()) !== null && _b !== void 0 ? _b : Math.random().toString(36).slice(2, 10); };
|
|
8
|
+
const getChannelName = (key) => ["yaasl", "sync-channel", base_1.CONFIG.name, key].filter(Boolean).join("/");
|
|
9
|
+
class SyncChannel {
|
|
10
|
+
constructor(key) {
|
|
11
|
+
this.listeners = new Set();
|
|
12
|
+
this.channel = new BroadcastChannel(getChannelName(key));
|
|
13
|
+
this.channel.onmessage = event => {
|
|
14
|
+
const { id, data } = event.data;
|
|
15
|
+
if (id === SyncChannel.id)
|
|
16
|
+
return;
|
|
17
|
+
this.listeners.forEach(listener => listener(data));
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
push(data) {
|
|
21
|
+
this.channel.postMessage({
|
|
22
|
+
id: SyncChannel.id,
|
|
23
|
+
data,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
subscribe(listener) {
|
|
27
|
+
this.listeners.add(listener);
|
|
28
|
+
return () => this.listeners.delete(listener);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
SyncChannel.id = getId();
|
|
32
|
+
/** Effect to synchronize the atoms value over tabs.
|
|
33
|
+
*
|
|
34
|
+
* @returns The effect to be used on atoms.
|
|
35
|
+
**/
|
|
36
|
+
exports.sync = (0, create_effect_1.createEffect)(({ atom }) => {
|
|
37
|
+
const channel = new SyncChannel(atom.name);
|
|
38
|
+
let skip = false;
|
|
39
|
+
return {
|
|
40
|
+
didInit: () => {
|
|
41
|
+
channel.subscribe(data => {
|
|
42
|
+
atom.set(data);
|
|
43
|
+
skip = true;
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
set: ({ value }) => {
|
|
47
|
+
if (skip) {
|
|
48
|
+
skip = false;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
channel.push(value);
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
});
|
|
@@ -37,6 +37,11 @@ class IdbStore {
|
|
|
37
37
|
return database === null || database === void 0 ? void 0 : database.transaction(this.name, mode).objectStore(this.name);
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
|
+
getAllKeys() {
|
|
41
|
+
return this.getStore("readonly").then(store => !store
|
|
42
|
+
? []
|
|
43
|
+
: promisifyRequest(store.getAllKeys()).then(keys => keys.map(String)));
|
|
44
|
+
}
|
|
40
45
|
get(key) {
|
|
41
46
|
return __awaiter(this, void 0, void 0, function* () {
|
|
42
47
|
return this.getStore("readonly").then(store => !store ? undefined : promisifyRequest(store.get(key)));
|
package/dist/cjs/utils/queue.js
CHANGED
|
@@ -15,7 +15,8 @@ class Queue {
|
|
|
15
15
|
const init = this.last ? this.last.then(() => prev) : new utils_1.Thenable(prev);
|
|
16
16
|
const result = this.queue.reduce((result, next) => result.then(prev => next(prev)), init);
|
|
17
17
|
this.queue = [];
|
|
18
|
-
this.last = result
|
|
18
|
+
this.last = result;
|
|
19
|
+
result.then(value => {
|
|
19
20
|
if (this.last === result) {
|
|
20
21
|
this.last = null;
|
|
21
22
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { updater, Thenable, toVoid } from "@yaasl/utils";
|
|
1
|
+
import { updater, Thenable, toVoid, consoleMessage, } from "@yaasl/utils";
|
|
2
2
|
import { CONFIG } from "./config";
|
|
3
3
|
import { Stateful } from "./stateful";
|
|
4
4
|
import { EffectDispatcher } from "../effects/effect-dispatcher";
|
|
@@ -48,6 +48,11 @@ export class Atom extends Stateful {
|
|
|
48
48
|
* new value based off the previous value.
|
|
49
49
|
*/
|
|
50
50
|
set(next) {
|
|
51
|
+
if (this.didInit !== true) {
|
|
52
|
+
throw new Error(consoleMessage("Tried to set a value during initialization. " +
|
|
53
|
+
"You are probably using an async effect. " +
|
|
54
|
+
"Use `await atom.didInit` to wait for the initialization process to be finished.", { scope: this.name }));
|
|
55
|
+
}
|
|
51
56
|
const oldState = this.get();
|
|
52
57
|
const newState = updater(next, oldState);
|
|
53
58
|
if (oldState === newState)
|
|
@@ -1,58 +1,31 @@
|
|
|
1
1
|
import { createEffect } from "./create-effect";
|
|
2
2
|
import { CONFIG } from "../base";
|
|
3
|
-
import { getScopedKey } from "../utils/get-scoped-key";
|
|
4
3
|
import { IdbStore } from "../utils/idb-store";
|
|
5
4
|
let atomDb = null;
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if (changeTrigger === "self") {
|
|
12
|
-
changeTrigger = null;
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
changeTrigger = "sync";
|
|
16
|
-
onTabSync();
|
|
17
|
-
};
|
|
18
|
-
return {
|
|
19
|
-
pushSync: () => {
|
|
20
|
-
if (changeTrigger === "sync") {
|
|
21
|
-
changeTrigger = null;
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
changeTrigger = "self";
|
|
25
|
-
channel.postMessage("sync");
|
|
26
|
-
},
|
|
27
|
-
};
|
|
5
|
+
const getAtomDb = () => {
|
|
6
|
+
if (!atomDb) {
|
|
7
|
+
atomDb = new IdbStore(CONFIG.name ?? "yaasl");
|
|
8
|
+
}
|
|
9
|
+
return atomDb;
|
|
28
10
|
};
|
|
29
11
|
/** Middleware to save and load atom values to an indexedDb.
|
|
30
12
|
*
|
|
31
13
|
* Will use one database and store for all atoms with your `CONFIG.name`
|
|
32
14
|
* as name or `yaasl` if not set.
|
|
33
15
|
*
|
|
16
|
+
* Should be used in combination with the `sync` effect, to ensure value integrity.
|
|
17
|
+
*
|
|
34
18
|
* @param {IndexedDbOptions | undefined} options
|
|
35
19
|
* @param options.key Use your own store key. Will be `atom.name` by default.
|
|
36
20
|
*
|
|
37
21
|
* @returns The effect to be used on atoms.
|
|
38
22
|
**/
|
|
39
|
-
export const indexedDb = createEffect(({ atom, options }) => {
|
|
23
|
+
export const indexedDb = Object.assign(createEffect(({ atom, options }) => {
|
|
40
24
|
const key = options?.key ?? atom.name;
|
|
41
|
-
const { pushSync } = options?.noTabSync
|
|
42
|
-
? {}
|
|
43
|
-
: createSync(key, () => {
|
|
44
|
-
void atomDb?.get(key).then(value => {
|
|
45
|
-
if (!value)
|
|
46
|
-
return;
|
|
47
|
-
atom.set(value);
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
25
|
return {
|
|
51
26
|
sort: "pre",
|
|
52
27
|
init: async ({ atom, set }) => {
|
|
53
|
-
|
|
54
|
-
atomDb = new IdbStore(CONFIG.name ?? "yaasl");
|
|
55
|
-
}
|
|
28
|
+
const atomDb = getAtomDb();
|
|
56
29
|
const existing = await atomDb.get(key);
|
|
57
30
|
if (existing != null) {
|
|
58
31
|
set(existing);
|
|
@@ -62,11 +35,15 @@ export const indexedDb = createEffect(({ atom, options }) => {
|
|
|
62
35
|
}
|
|
63
36
|
},
|
|
64
37
|
set: ({ value, atom }) => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
38
|
+
// Don't wait for promises since this would cause lag
|
|
39
|
+
if (value === atom.defaultValue) {
|
|
40
|
+
void atomDb?.delete(key);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
void atomDb?.set(key, value);
|
|
44
|
+
}
|
|
70
45
|
},
|
|
71
46
|
};
|
|
47
|
+
}), {
|
|
48
|
+
getAllKeys: () => getAtomDb().getAllKeys(),
|
|
72
49
|
});
|
|
@@ -7,7 +7,6 @@ import { StringStorage } from "../utils/string-storage";
|
|
|
7
7
|
* @param {SessionStorageOptions | undefined} options
|
|
8
8
|
* @param options.key Use your own key for the session storage.
|
|
9
9
|
* Will be "{config-name}/{atom-name}" by default.
|
|
10
|
-
* @param options.noTabSync Disable the synchronization of values over browser tabs.
|
|
11
10
|
* @param options.parser Custom functions to stringify and parse values. Defaults to JSON.stringify and JSON.parse. Use this when handling complex datatypes like Maps or Sets.
|
|
12
11
|
*
|
|
13
12
|
* @returns The effect to be used on atoms.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { getWindow } from "@yaasl/utils";
|
|
2
|
+
import { createEffect } from "./create-effect";
|
|
3
|
+
import { CONFIG } from "../base";
|
|
4
|
+
const getId = () => getWindow()?.crypto.randomUUID() ?? Math.random().toString(36).slice(2, 10);
|
|
5
|
+
const getChannelName = (key) => ["yaasl", "sync-channel", CONFIG.name, key].filter(Boolean).join("/");
|
|
6
|
+
class SyncChannel {
|
|
7
|
+
static id = getId();
|
|
8
|
+
channel;
|
|
9
|
+
listeners = new Set();
|
|
10
|
+
constructor(key) {
|
|
11
|
+
this.channel = new BroadcastChannel(getChannelName(key));
|
|
12
|
+
this.channel.onmessage = event => {
|
|
13
|
+
const { id, data } = event.data;
|
|
14
|
+
if (id === SyncChannel.id)
|
|
15
|
+
return;
|
|
16
|
+
this.listeners.forEach(listener => listener(data));
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
push(data) {
|
|
20
|
+
this.channel.postMessage({
|
|
21
|
+
id: SyncChannel.id,
|
|
22
|
+
data,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
subscribe(listener) {
|
|
26
|
+
this.listeners.add(listener);
|
|
27
|
+
return () => this.listeners.delete(listener);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Effect to synchronize the atoms value over tabs.
|
|
31
|
+
*
|
|
32
|
+
* @returns The effect to be used on atoms.
|
|
33
|
+
**/
|
|
34
|
+
export const sync = createEffect(({ atom }) => {
|
|
35
|
+
const channel = new SyncChannel(atom.name);
|
|
36
|
+
let skip = false;
|
|
37
|
+
return {
|
|
38
|
+
didInit: () => {
|
|
39
|
+
channel.subscribe(data => {
|
|
40
|
+
atom.set(data);
|
|
41
|
+
skip = true;
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
set: ({ value }) => {
|
|
45
|
+
if (skip) {
|
|
46
|
+
skip = false;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
channel.push(value);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
});
|
|
@@ -24,6 +24,11 @@ export class IdbStore {
|
|
|
24
24
|
const database = await this.database;
|
|
25
25
|
return database?.transaction(this.name, mode).objectStore(this.name);
|
|
26
26
|
}
|
|
27
|
+
getAllKeys() {
|
|
28
|
+
return this.getStore("readonly").then(store => !store
|
|
29
|
+
? []
|
|
30
|
+
: promisifyRequest(store.getAllKeys()).then(keys => keys.map(String)));
|
|
31
|
+
}
|
|
27
32
|
async get(key) {
|
|
28
33
|
return this.getStore("readonly").then(store => !store ? undefined : promisifyRequest(store.get(key)));
|
|
29
34
|
}
|
package/dist/esm/utils/queue.js
CHANGED
|
@@ -10,7 +10,8 @@ export class Queue {
|
|
|
10
10
|
const init = this.last ? this.last.then(() => prev) : new Thenable(prev);
|
|
11
11
|
const result = this.queue.reduce((result, next) => result.then(prev => next(prev)), init);
|
|
12
12
|
this.queue = [];
|
|
13
|
-
this.last = result
|
|
13
|
+
this.last = result;
|
|
14
|
+
result.then(value => {
|
|
14
15
|
if (this.last === result) {
|
|
15
16
|
this.last = null;
|
|
16
17
|
}
|