@plq/use-persisted-state 1.4.0 → 1.4.2
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/README.md +14 -0
- package/lib/create-async-persisted-state.d.ts.map +1 -1
- package/lib/create-async-persisted-state.js +67 -38
- package/lib/create-async-persisted-state.js.map +1 -1
- package/lib/create-persisted-state.d.ts.map +1 -1
- package/lib/create-persisted-state.js +48 -17
- package/lib/create-persisted-state.js.map +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/storages/chrome-storage.d.ts.map +1 -1
- package/lib/storages/chrome-storage.js +6 -15
- package/lib/storages/chrome-storage.js.map +1 -1
- package/lib/storages/local-storage.d.ts.map +1 -1
- package/lib/storages/local-storage.js +1 -2
- package/lib/storages/local-storage.js.map +1 -1
- package/lib/storages/session-storage.d.ts.map +1 -1
- package/lib/storages/session-storage.js +1 -2
- package/lib/storages/session-storage.js.map +1 -1
- package/lib/utils/change-notifier.d.ts +1 -8
- package/lib/utils/change-notifier.d.ts.map +1 -1
- package/lib/utils/change-notifier.js +1 -10
- package/lib/utils/change-notifier.js.map +1 -1
- package/lib/utils/create-web-storage.d.ts +1 -8
- package/lib/utils/create-web-storage.d.ts.map +1 -1
- package/lib/utils/create-web-storage.js +5 -17
- package/lib/utils/create-web-storage.js.map +1 -1
- package/lib/utils/extension-storage.d.ts +2 -12
- package/lib/utils/extension-storage.d.ts.map +1 -1
- package/lib/utils/extension-storage.js +3 -14
- package/lib/utils/extension-storage.js.map +1 -1
- package/lib/utils/get-new-item.d.ts +2 -1
- package/lib/utils/get-new-item.d.ts.map +1 -1
- package/lib/utils/get-new-item.js +13 -7
- package/lib/utils/get-new-item.js.map +1 -1
- package/lib/utils/get-persisted-value.d.ts +1 -7
- package/lib/utils/get-persisted-value.d.ts.map +1 -1
- package/lib/utils/get-persisted-value.js +3 -13
- package/lib/utils/get-persisted-value.js.map +1 -1
- package/lib/utils/is-async-storage.d.ts +1 -7
- package/lib/utils/is-async-storage.d.ts.map +1 -1
- package/lib/utils/is-async-storage.js +6 -25
- package/lib/utils/is-async-storage.js.map +1 -1
- package/lib/utils/storage-event-router.d.ts +1 -5
- package/lib/utils/storage-event-router.d.ts.map +1 -1
- package/lib/utils/storage-event-router.js +3 -14
- package/lib/utils/storage-event-router.js.map +1 -1
- package/lib/utils/use-storage-handler.d.ts +3 -1
- package/lib/utils/use-storage-handler.d.ts.map +1 -1
- package/lib/utils/use-storage-handler.js +28 -46
- package/lib/utils/use-storage-handler.js.map +1 -1
- package/package.json +1 -1
- package/src/create-async-persisted-state.ts +42 -40
- package/src/create-persisted-state.ts +15 -17
- package/src/index.ts +1 -4
- package/src/storages/chrome-storage.ts +6 -18
- package/src/storages/local-storage.ts +1 -2
- package/src/storages/session-storage.ts +1 -2
- package/src/utils/change-notifier.ts +1 -10
- package/src/utils/create-web-storage.ts +5 -17
- package/src/utils/extension-storage.ts +3 -14
- package/src/utils/get-new-item.ts +18 -9
- package/src/utils/get-persisted-value.ts +3 -13
- package/src/utils/is-async-storage.ts +6 -26
- package/src/utils/storage-event-router.ts +3 -14
- package/src/utils/use-storage-handler.ts +33 -58
package/README.md
CHANGED
|
@@ -225,6 +225,20 @@ persisted_state_hook:example → {"count":0}
|
|
|
225
225
|
|
|
226
226
|
Storage backends only ever see serialized strings. Anything you persist ends up unencrypted in the underlying storage — do not store secrets or sensitive data (see [SECURITY.md](https://github.com/Akurganow/use-persisted-state/blob/main/SECURITY.md)).
|
|
227
227
|
|
|
228
|
+
### An entry the library cannot read
|
|
229
|
+
|
|
230
|
+
A write replaces the factory's whole entry, so there is nothing safe to store when the entry already
|
|
231
|
+
there is a string that will not parse, or parses to something that is not an object — another
|
|
232
|
+
library writing under the same key, or a write cut short. The setter reports the failure on
|
|
233
|
+
`console.error`, keeps the value you set in memory and writes nothing, leaving every other hook's
|
|
234
|
+
key exactly where it is. The factory's `clear` removes the entry and lets writing resume.
|
|
235
|
+
|
|
236
|
+
This reaches as far as the adapter reports. Web storage holds only strings, so anything under the
|
|
237
|
+
key comes back and is checked. Extension storage holds arbitrary JSON, and the bundled adapters
|
|
238
|
+
report a non-string value as absent — the library then reads the entry as empty and its next write
|
|
239
|
+
**replaces that value**. Storing your own data under a `persisted_state_hook:` key in extension
|
|
240
|
+
storage is not safe, whatever its type.
|
|
241
|
+
|
|
228
242
|
### Values JSON cannot carry
|
|
229
243
|
|
|
230
244
|
A few values do not survive `JSON.stringify`. This follows from the format rather than from a choice
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-async-persisted-state.d.ts","sourceRoot":"","sources":["../src/create-async-persisted-state.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,eAAe,CAAA;AAEtE,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,CAAC,SAAS,YAAY,EACtE,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,CAAC,GACT,CAAC,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"create-async-persisted-state.d.ts","sourceRoot":"","sources":["../src/create-async-persisted-state.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,eAAe,CAAA;AAEtE,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,CAAC,SAAS,YAAY,EACtE,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,CAAC,GACT,CAAC,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAuGvC"}
|
|
@@ -1,64 +1,98 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
5
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
39
|
exports.default = createAsyncPersistedState;
|
|
7
40
|
const react_1 = require("react");
|
|
8
|
-
const use_storage_handler_1 =
|
|
41
|
+
const use_storage_handler_1 = __importStar(require("./utils/use-storage-handler"));
|
|
9
42
|
const get_new_value_1 = __importDefault(require("./utils/get-new-value"));
|
|
10
43
|
const get_new_item_1 = __importDefault(require("./utils/get-new-item"));
|
|
11
44
|
const get_persisted_value_1 = __importDefault(require("./utils/get-persisted-value"));
|
|
12
45
|
function createAsyncPersistedState(storageKey, storage) {
|
|
13
46
|
const safeStorageKey = `persisted_state_hook:${storageKey}`;
|
|
47
|
+
// Storing is read-merge-write on one shared entry, so overlapping writers would drop each other's keys.
|
|
48
|
+
let entryWrites = Promise.resolve();
|
|
14
49
|
const clear = () => {
|
|
15
|
-
|
|
50
|
+
// In the same chain as writes, or a queued write lands after the removal and restores what was cleared.
|
|
51
|
+
const removal = entryWrites.then(() => storage.remove(safeStorageKey));
|
|
52
|
+
entryWrites = removal.catch(() => undefined);
|
|
53
|
+
return removal;
|
|
54
|
+
};
|
|
55
|
+
const commitEntry = (key, newValue, pendingOwnWrites) => {
|
|
56
|
+
const write = entryWrites.then(async () => {
|
|
57
|
+
const persistedItem = await storage.get(safeStorageKey);
|
|
58
|
+
let newItem;
|
|
59
|
+
try {
|
|
60
|
+
newItem = (0, get_new_item_1.default)(key, persistedItem[safeStorageKey], newValue);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// A write replaces the whole entry, so an unreadable one is skipped rather than rebuilt without other keys.
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
(0, use_storage_handler_1.recordOwnWrite)(pendingOwnWrites, newItem);
|
|
67
|
+
await storage.set({ [safeStorageKey]: newItem });
|
|
68
|
+
});
|
|
69
|
+
// The chain must outlive a failed write; the rejection still reaches the caller through `write`.
|
|
70
|
+
entryWrites = write.catch(() => undefined);
|
|
71
|
+
return write;
|
|
16
72
|
};
|
|
17
73
|
const usePersistedState = (key, initialValue) => {
|
|
18
74
|
const [state, setState] = (0, react_1.useState)(initialValue);
|
|
19
|
-
//
|
|
20
|
-
// not against the one captured by the render that created it. Reading the
|
|
21
|
-
// render closure collapses updates batched into a single event.
|
|
75
|
+
// Updater functions must resolve against the last applied value, not the render closure's.
|
|
22
76
|
const latestValue = (0, react_1.useRef)(state);
|
|
23
|
-
//
|
|
24
|
-
// the caller set one must not revert it, and no signal local to the load can
|
|
25
|
-
// answer this: the write it loses to happens outside the load entirely.
|
|
77
|
+
// A load that settles after the caller set a value must not revert it.
|
|
26
78
|
const hasAppliedValue = (0, react_1.useRef)(false);
|
|
27
79
|
const applyValue = (0, react_1.useCallback)((value) => {
|
|
28
80
|
latestValue.current = value;
|
|
29
81
|
hasAppliedValue.current = true;
|
|
30
82
|
setState(value);
|
|
31
83
|
}, []);
|
|
32
|
-
|
|
33
|
-
const pendingOwnWrite = (0, react_1.useRef)(null);
|
|
84
|
+
const pendingOwnWrites = (0, react_1.useRef)([]);
|
|
34
85
|
const setPersistedState = (0, react_1.useCallback)(async (newState) => {
|
|
35
86
|
const newValue = (0, get_new_value_1.default)(newState, latestValue.current);
|
|
36
87
|
applyValue(newValue);
|
|
37
|
-
|
|
38
|
-
const newItem = (0, get_new_item_1.default)(key, persistedItem[safeStorageKey], newValue);
|
|
39
|
-
// Recorded before the write, because the backend may report it before the
|
|
40
|
-
// promise settles.
|
|
41
|
-
pendingOwnWrite.current = newItem;
|
|
42
|
-
await storage.set({ [safeStorageKey]: newItem });
|
|
88
|
+
await commitEntry(key, newValue, pendingOwnWrites);
|
|
43
89
|
}, [key, applyValue]);
|
|
44
|
-
//
|
|
45
|
-
// first render. Later identities of an inline object must not reload, or the
|
|
46
|
-
// effect re-runs on every render and never settles.
|
|
90
|
+
// The first render's initial value: reloading on a later identity would re-run the effect forever.
|
|
47
91
|
const mountInitialValue = (0, react_1.useRef)(initialValue);
|
|
48
|
-
// Subscribed before the load
|
|
49
|
-
|
|
50
|
-
// between the read and the subscription in which a write belongs to neither
|
|
51
|
-
// and is lost. Reading last covers everything written before the subscription
|
|
52
|
-
// began, and the listener covers everything after.
|
|
53
|
-
(0, use_storage_handler_1.default)(key, safeStorageKey, applyValue, storage, initialValue, pendingOwnWrite);
|
|
92
|
+
// Subscribed before the load: effects run in declaration order, and reading first would lose writes in between.
|
|
93
|
+
(0, use_storage_handler_1.default)(key, safeStorageKey, applyValue, storage, initialValue, pendingOwnWrites);
|
|
54
94
|
(0, react_1.useEffect)(() => {
|
|
55
|
-
//
|
|
56
|
-
// is still the current one, which only the closure it belongs to can answer,
|
|
57
|
-
// and whether a value has been applied meanwhile, which outlives it. A load
|
|
58
|
-
// abandoned by a key change would otherwise read the flag its successor had
|
|
59
|
-
// just set, apply the previous key's value and shut the successor out. The
|
|
60
|
-
// second question is also what makes subscribing first safe: a value the
|
|
61
|
-
// listener delivers while the load is in flight is not overwritten by it.
|
|
95
|
+
// Separate from `hasAppliedValue`: only this closure knows whether its own load is still current.
|
|
62
96
|
let isCancelled = false;
|
|
63
97
|
hasAppliedValue.current = false;
|
|
64
98
|
const loadPersistedValue = async () => {
|
|
@@ -69,12 +103,7 @@ function createAsyncPersistedState(storageKey, storage) {
|
|
|
69
103
|
applyValue((0, get_persisted_value_1.default)(key, mountInitialValue.current, persist[safeStorageKey]));
|
|
70
104
|
}
|
|
71
105
|
catch (err) {
|
|
72
|
-
//
|
|
73
|
-
// extension context. Nothing awaits this load, so an unclaimed
|
|
74
|
-
// rejection terminates the process on Node 15+ and surfaces as an
|
|
75
|
-
// uncaught error in the browser. The initial value is already in
|
|
76
|
-
// state, so the mount stands on it and the failure is reported rather
|
|
77
|
-
// than swallowed, as the synchronous path reports its own.
|
|
106
|
+
// Nothing awaits this load, so an unclaimed rejection would surface as an uncaught error.
|
|
78
107
|
console.error("use-persisted-state: Can't read value from storage", err);
|
|
79
108
|
}
|
|
80
109
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-async-persisted-state.js","sourceRoot":"","sources":["../src/create-async-persisted-state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create-async-persisted-state.js","sourceRoot":"","sources":["../src/create-async-persisted-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-persisted-state.d.ts","sourceRoot":"","sources":["../src/create-persisted-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,eAAe,CAAA;AAOtE,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,cAAc,EAAE,MAAM,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"create-persisted-state.d.ts","sourceRoot":"","sources":["../src/create-persisted-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,eAAe,CAAA;AAOtE,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,cAAc,EAAE,MAAM,IAAI,CAAC,CA8D/G"}
|
|
@@ -1,11 +1,44 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
5
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
39
|
exports.default = createPersistedState;
|
|
7
40
|
const react_1 = require("react");
|
|
8
|
-
const use_storage_handler_1 =
|
|
41
|
+
const use_storage_handler_1 = __importStar(require("./utils/use-storage-handler"));
|
|
9
42
|
const get_new_value_1 = __importDefault(require("./utils/get-new-value"));
|
|
10
43
|
const get_new_item_1 = __importDefault(require("./utils/get-new-item"));
|
|
11
44
|
const get_persisted_value_1 = __importDefault(require("./utils/get-persisted-value"));
|
|
@@ -16,39 +49,37 @@ function createPersistedState(storageKey, storage) {
|
|
|
16
49
|
};
|
|
17
50
|
const readPersisted = (key, initialValue) => (0, get_persisted_value_1.default)(key, initialValue, storage.get(safeStorageKey)[safeStorageKey]);
|
|
18
51
|
const usePersistedState = (key, initialValue) => {
|
|
19
|
-
//
|
|
20
|
-
// the hook runs on every render of every consuming component, so a re-read is
|
|
21
|
-
// only warranted when the key it is asked for actually changes.
|
|
52
|
+
// Read through the initializer: the hook runs on every render, so storage stays out of the render path.
|
|
22
53
|
const [state, setState] = (0, react_1.useState)(() => readPersisted(key, initialValue));
|
|
23
|
-
//
|
|
24
|
-
// not against the one captured by the render that created it. Reading the
|
|
25
|
-
// render closure collapses updates batched into a single event.
|
|
54
|
+
// Updater functions must resolve against the last applied value, not the render closure's.
|
|
26
55
|
const latestValue = (0, react_1.useRef)(state);
|
|
27
56
|
const applyValue = (0, react_1.useCallback)((value) => {
|
|
28
57
|
latestValue.current = value;
|
|
29
58
|
setState(value);
|
|
30
59
|
}, []);
|
|
31
|
-
// A
|
|
32
|
-
// anything can be written, or the next update stores the previous key's value
|
|
33
|
-
// under the new key and destroys what was there. Adjusting during render ties
|
|
34
|
-
// the re-read to the change itself, where an effect would cost a read and a
|
|
35
|
-
// second render on every mount as well.
|
|
60
|
+
// A new key must be read before anything is written, or the next update stores the old key's value under it.
|
|
36
61
|
const renderedKey = (0, react_1.useRef)(key);
|
|
37
62
|
if (renderedKey.current !== key) {
|
|
38
63
|
renderedKey.current = key;
|
|
39
64
|
applyValue(readPersisted(key, initialValue));
|
|
40
65
|
}
|
|
41
|
-
|
|
42
|
-
const pendingOwnWrite = (0, react_1.useRef)(null);
|
|
66
|
+
const pendingOwnWrites = (0, react_1.useRef)([]);
|
|
43
67
|
const setPersistedState = (0, react_1.useCallback)((newState) => {
|
|
44
68
|
const newValue = (0, get_new_value_1.default)(newState, latestValue.current);
|
|
45
69
|
applyValue(newValue);
|
|
46
70
|
const persistedItem = storage.get(safeStorageKey)[safeStorageKey];
|
|
47
|
-
|
|
48
|
-
|
|
71
|
+
let newItem;
|
|
72
|
+
try {
|
|
73
|
+
newItem = (0, get_new_item_1.default)(key, persistedItem, newValue);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// A write replaces the whole entry, so an unreadable one is skipped rather than rebuilt without other keys.
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
(0, use_storage_handler_1.recordOwnWrite)(pendingOwnWrites, newItem);
|
|
49
80
|
storage.set({ [safeStorageKey]: newItem });
|
|
50
81
|
}, [key, applyValue]);
|
|
51
|
-
(0, use_storage_handler_1.default)(key, safeStorageKey, applyValue, storage, initialValue,
|
|
82
|
+
(0, use_storage_handler_1.default)(key, safeStorageKey, applyValue, storage, initialValue, pendingOwnWrites);
|
|
52
83
|
return [state, setPersistedState];
|
|
53
84
|
};
|
|
54
85
|
return [usePersistedState, clear];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-persisted-state.js","sourceRoot":"","sources":["../src/create-persisted-state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create-persisted-state.js","sourceRoot":"","sources":["../src/create-persisted-state.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,uCA8DC;AAxED,iCAAqD;AAKrD,mFAA+E;AAC/E,0EAA+C;AAC/C,wEAA6C;AAC7C,sFAA2D;AAE3D,SAAwB,oBAAoB,CAAC,UAAkB,EAAE,OAAgB;IAC/E,MAAM,cAAc,GAAG,wBAAwB,UAAU,EAAE,CAAA;IAC3D,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;IAChC,CAAC,CAAA;IAED,MAAM,aAAa,GAAG,CAAI,GAAW,EAAE,YAAe,EAAK,EAAE,CAC3D,IAAA,6BAAiB,EAAI,GAAG,EAAE,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,cAAc,CAAC,CAAC,CAAA;IAEtF,MAAM,iBAAiB,GAAG,CAAI,GAAW,EAAE,YAAe,EAAwB,EAAE;QAClF,wGAAwG;QACxG,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAI,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAA;QAE7E,2FAA2F;QAC3F,MAAM,WAAW,GAAG,IAAA,cAAM,EAAC,KAAK,CAAC,CAAA;QAEjC,MAAM,UAAU,GAAG,IAAA,mBAAW,EAAC,CAAC,KAAQ,EAAQ,EAAE;YAChD,WAAW,CAAC,OAAO,GAAG,KAAK,CAAA;YAE3B,QAAQ,CAAC,KAAK,CAAC,CAAA;QACjB,CAAC,EAAE,EAAE,CAAC,CAAA;QAEN,6GAA6G;QAC7G,MAAM,WAAW,GAAG,IAAA,cAAM,EAAC,GAAG,CAAC,CAAA;QAE/B,IAAI,WAAW,CAAC,OAAO,KAAK,GAAG,EAAE,CAAC;YAChC,WAAW,CAAC,OAAO,GAAG,GAAG,CAAA;YAEzB,UAAU,CAAC,aAAa,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAA;QAC9C,CAAC;QAED,MAAM,gBAAgB,GAAG,IAAA,cAAM,EAAW,EAAE,CAAC,CAAA;QAE7C,MAAM,iBAAiB,GAAG,IAAA,mBAAW,EACnC,CAAC,QAAiC,EAAQ,EAAE;YAC1C,MAAM,QAAQ,GAAG,IAAA,uBAAW,EAAI,QAAQ,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;YAE9D,UAAU,CAAC,QAAQ,CAAC,CAAA;YAEpB,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,cAAc,CAAC,CAAA;YACjE,IAAI,OAAe,CAAA;YAEnB,IAAI,CAAC;gBACH,OAAO,GAAG,IAAA,sBAAU,EAAI,GAAG,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAA;YACvD,CAAC;YAAC,MAAM,CAAC;gBACP,4GAA4G;gBAC5G,OAAM;YACR,CAAC;YAED,IAAA,oCAAc,EAAC,gBAAgB,EAAE,OAAO,CAAC,CAAA;YAEzC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;QAC5C,CAAC,EACD,CAAC,GAAG,EAAE,UAAU,CAAC,CAClB,CAAA;QAED,IAAA,6BAAiB,EAAI,GAAG,EAAE,cAAc,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,gBAAgB,CAAC,CAAA;QAE9F,OAAO,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAA;IACnC,CAAC,CAAA;IAED,OAAO,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAA;AACnC,CAAC"}
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAEnD,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,CAAC,SAAS,OAAO,GAAG,YAAY,EAC3E,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,GACT,CAAC,cAAc,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAM9C;AAED,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,gCAAgC,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAEnD,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,CAAC,SAAS,OAAO,GAAG,YAAY,EAC3E,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,GACT,CAAC,cAAc,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAM9C;AAED,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,gCAAgC,CAAA;AAGrF,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AACvH,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chrome-storage.d.ts","sourceRoot":"","sources":["../../src/storages/chrome-storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"chrome-storage.d.ts","sourceRoot":"","sources":["../../src/storages/chrome-storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAmBrD,QAAA,MAAM,KAAK,cAA+C,CAAA;AAC1D,QAAA,MAAM,IAAI,cAA6C,CAAA;AACvD,QAAA,MAAM,OAAO,cAAmD,CAAA;AAEhE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA"}
|
|
@@ -6,22 +6,13 @@ const registry = (0, extension_storage_1.createListenerRegistry)();
|
|
|
6
6
|
chrome.storage.onChanged.addListener((changes, area) => {
|
|
7
7
|
registry.fire((0, extension_storage_1.toStorageChanges)(changes), area);
|
|
8
8
|
});
|
|
9
|
-
//
|
|
9
|
+
// Passing no callback selects the promise form; the callback form leaves failures in `runtime.lastError`.
|
|
10
|
+
// Called through `storage`: a torn-off `StorageArea` method throws `Illegal invocation`, unlike firefox's.
|
|
11
|
+
// `get` stays `async` so asking whether this storage is asynchronous costs no round trip to the extension.
|
|
10
12
|
const createStorage = (storage, area) => ({
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
get: async (keys) => new Promise(resolve => {
|
|
15
|
-
storage.get(keys, items => {
|
|
16
|
-
resolve((0, extension_storage_1.toStoredItems)(items));
|
|
17
|
-
});
|
|
18
|
-
}),
|
|
19
|
-
set: items => new Promise(resolve => {
|
|
20
|
-
storage.set(items, resolve);
|
|
21
|
-
}),
|
|
22
|
-
remove: keys => new Promise(resolve => {
|
|
23
|
-
storage.remove(keys, resolve);
|
|
24
|
-
}),
|
|
13
|
+
get: async (keys) => (0, extension_storage_1.toStoredItems)(await storage.get(keys)),
|
|
14
|
+
set: items => storage.set(items),
|
|
15
|
+
remove: keys => storage.remove(keys),
|
|
25
16
|
onChanged: registry.createOnChanged(area),
|
|
26
17
|
});
|
|
27
18
|
const local = createStorage(chrome.storage.local, 'local');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chrome-storage.js","sourceRoot":"","sources":["../../src/storages/chrome-storage.ts"],"names":[],"mappings":";;;AACA,kEAA+G;AAE/G,MAAM,QAAQ,GAAG,IAAA,0CAAsB,GAAE,CAAA;AAEzC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;IACrD,QAAQ,CAAC,IAAI,CAAC,IAAA,oCAAgB,EAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAA;AAChD,CAAC,CAAC,CAAA;AAEF,
|
|
1
|
+
{"version":3,"file":"chrome-storage.js","sourceRoot":"","sources":["../../src/storages/chrome-storage.ts"],"names":[],"mappings":";;;AACA,kEAA+G;AAE/G,MAAM,QAAQ,GAAG,IAAA,0CAAsB,GAAE,CAAA;AAEzC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;IACrD,QAAQ,CAAC,IAAI,CAAC,IAAA,oCAAgB,EAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAA;AAChD,CAAC,CAAC,CAAA;AAEF,0GAA0G;AAC1G,2GAA2G;AAC3G,2GAA2G;AAC3G,MAAM,aAAa,GAAG,CAAC,OAAmC,EAAE,IAAU,EAAgB,EAAE,CAAC,CAAC;IACxF,GAAG,EAAE,KAAK,EAAC,IAAI,EAAC,EAAE,CAAC,IAAA,iCAAa,EAAC,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACzD,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;IAChC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;IACpC,SAAS,EAAE,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC;CAC1C,CAAC,CAAA;AAEF,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;AAIjD,sBAAK;AAHd,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AAGvC,oBAAI;AAFpB,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;AAE1C,0BAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-storage.d.ts","sourceRoot":"","sources":["../../src/storages/local-storage.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"local-storage.d.ts","sourceRoot":"","sources":["../../src/storages/local-storage.ts"],"names":[],"mappings":";AAGA,wBAA4F"}
|
|
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const create_web_storage_1 = __importDefault(require("../utils/create-web-storage"));
|
|
7
|
-
// The typeof guard keeps this import from throwing on server runtimes
|
|
8
|
-
// where the browser storage globals are not defined.
|
|
7
|
+
// The typeof guard keeps this import from throwing on server runtimes, where the global is not defined.
|
|
9
8
|
exports.default = (0, create_web_storage_1.default)(typeof localStorage !== 'undefined' ? localStorage : undefined);
|
|
10
9
|
//# sourceMappingURL=local-storage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-storage.js","sourceRoot":"","sources":["../../src/storages/local-storage.ts"],"names":[],"mappings":";;;;;AAAA,qFAAuD;AAEvD,
|
|
1
|
+
{"version":3,"file":"local-storage.js","sourceRoot":"","sources":["../../src/storages/local-storage.ts"],"names":[],"mappings":";;;;;AAAA,qFAAuD;AAEvD,wGAAwG;AACxG,kBAAe,IAAA,4BAAa,EAAC,OAAO,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-storage.d.ts","sourceRoot":"","sources":["../../src/storages/session-storage.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"session-storage.d.ts","sourceRoot":"","sources":["../../src/storages/session-storage.ts"],"names":[],"mappings":";AAGA,wBAAgG"}
|
|
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const create_web_storage_1 = __importDefault(require("../utils/create-web-storage"));
|
|
7
|
-
// The typeof guard keeps this import from throwing on server runtimes
|
|
8
|
-
// where the browser storage globals are not defined.
|
|
7
|
+
// The typeof guard keeps this import from throwing on server runtimes, where the global is not defined.
|
|
9
8
|
exports.default = (0, create_web_storage_1.default)(typeof sessionStorage !== 'undefined' ? sessionStorage : undefined);
|
|
10
9
|
//# sourceMappingURL=session-storage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-storage.js","sourceRoot":"","sources":["../../src/storages/session-storage.ts"],"names":[],"mappings":";;;;;AAAA,qFAAuD;AAEvD,
|
|
1
|
+
{"version":3,"file":"session-storage.js","sourceRoot":"","sources":["../../src/storages/session-storage.ts"],"names":[],"mappings":";;;;;AAAA,qFAAuD;AAEvD,wGAAwG;AACxG,kBAAe,IAAA,4BAAa,EAAC,OAAO,cAAc,KAAK,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA"}
|
|
@@ -6,13 +6,6 @@ export interface ChangeNotifier {
|
|
|
6
6
|
hasListeners(): boolean;
|
|
7
7
|
onChanged: StorageChangeEvent;
|
|
8
8
|
}
|
|
9
|
-
/**
|
|
10
|
-
* Holds the subscribers of a single change source. Each adapter — and, for the
|
|
11
|
-
* extension backends, each storage area — owns one, so a change never reaches
|
|
12
|
-
* listeners that subscribed elsewhere.
|
|
13
|
-
*
|
|
14
|
-
* Routing a backend's events to the right notifier stays with the adapter: the
|
|
15
|
-
* extensions demultiplex one event by area name, the DOM one by storage object.
|
|
16
|
-
*/
|
|
9
|
+
/** Holds the subscribers of a single change source, so a change never reaches listeners that subscribed elsewhere. */
|
|
17
10
|
export declare function createChangeNotifier(): ChangeNotifier;
|
|
18
11
|
//# sourceMappingURL=change-notifier.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"change-notifier.d.ts","sourceRoot":"","sources":["../../src/utils/change-notifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAyB,MAAM,mBAAmB,CAAA;AAEjG,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,OAAO,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAA;KAAE,GAAG,IAAI,CAAA;IACrD,YAAY,IAAI,OAAO,CAAA;IACvB,SAAS,EAAE,kBAAkB,CAAA;CAC9B;AAED
|
|
1
|
+
{"version":3,"file":"change-notifier.d.ts","sourceRoot":"","sources":["../../src/utils/change-notifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAyB,MAAM,mBAAmB,CAAA;AAEjG,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,OAAO,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAA;KAAE,GAAG,IAAI,CAAA;IACrD,YAAY,IAAI,OAAO,CAAA;IACvB,SAAS,EAAE,kBAAkB,CAAA;CAC9B;AAED,sHAAsH;AACtH,wBAAgB,oBAAoB,IAAI,cAAc,CAwBrD"}
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createChangeNotifier = createChangeNotifier;
|
|
4
|
-
/**
|
|
5
|
-
* Holds the subscribers of a single change source. Each adapter — and, for the
|
|
6
|
-
* extension backends, each storage area — owns one, so a change never reaches
|
|
7
|
-
* listeners that subscribed elsewhere.
|
|
8
|
-
*
|
|
9
|
-
* Routing a backend's events to the right notifier stays with the adapter: the
|
|
10
|
-
* extensions demultiplex one event by area name, the DOM one by storage object.
|
|
11
|
-
*/
|
|
4
|
+
/** Holds the subscribers of a single change source, so a change never reaches listeners that subscribed elsewhere. */
|
|
12
5
|
function createChangeNotifier() {
|
|
13
6
|
const listeners = new Set();
|
|
14
7
|
return {
|
|
@@ -17,8 +10,6 @@ function createChangeNotifier() {
|
|
|
17
10
|
listener(changes);
|
|
18
11
|
}
|
|
19
12
|
},
|
|
20
|
-
// Lets an adapter release a shared resource once nobody is listening; the
|
|
21
|
-
// set behind onChanged stays the only count, so the two cannot drift.
|
|
22
13
|
hasListeners() {
|
|
23
14
|
return listeners.size > 0;
|
|
24
15
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"change-notifier.js","sourceRoot":"","sources":["../../src/utils/change-notifier.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"change-notifier.js","sourceRoot":"","sources":["../../src/utils/change-notifier.ts"],"names":[],"mappings":";;AASA,oDAwBC;AAzBD,sHAAsH;AACtH,SAAgB,oBAAoB;IAClC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAyB,CAAA;IAElD,OAAO;QACL,IAAI,CAAC,OAAO;YACV,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,QAAQ,CAAC,OAAO,CAAC,CAAA;YACnB,CAAC;QACH,CAAC;QACD,YAAY;YACV,OAAO,SAAS,CAAC,IAAI,GAAG,CAAC,CAAA;QAC3B,CAAC;QACD,SAAS,EAAE;YACT,WAAW,CAAC,QAAQ;gBAClB,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YACzB,CAAC;YACD,cAAc,CAAC,QAAQ;gBACrB,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;YAC5B,CAAC;YACD,WAAW,CAAC,QAAQ;gBAClB,OAAO,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YAChC,CAAC;SACF;KACF,CAAA;AACH,CAAC"}
|
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import type { Storage } from '../@types/storage';
|
|
2
|
-
/**
|
|
3
|
-
* Adapts a Web Storage area to the library's `Storage` contract.
|
|
4
|
-
*
|
|
5
|
-
* Pass `undefined` where the global is missing, as it is on a server: the
|
|
6
|
-
* adapter then reads back nothing and **silently discards every write**, so a
|
|
7
|
-
* consumer keeps its initial value instead of the import throwing. Listeners
|
|
8
|
-
* are still accepted and reported, they simply never fire.
|
|
9
|
-
*/
|
|
2
|
+
/** Adapts a Web Storage area. With `undefined`, as on a server, it reads back nothing and discards every write. */
|
|
10
3
|
declare const _default: (storage: globalThis.Storage | undefined) => Storage;
|
|
11
4
|
export default _default;
|
|
12
5
|
//# sourceMappingURL=create-web-storage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-web-storage.d.ts","sourceRoot":"","sources":["../../src/utils/create-web-storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAqC,MAAM,mBAAmB,CAAA;AAQnF
|
|
1
|
+
{"version":3,"file":"create-web-storage.d.ts","sourceRoot":"","sources":["../../src/utils/create-web-storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAqC,MAAM,mBAAmB,CAAA;AAQnF,mHAAmH;yBACnG,SAAS,UAAU,CAAC,OAAO,GAAG,SAAS,KAAG,OAAO;AAAjE,wBAgFC"}
|
|
@@ -5,20 +5,11 @@ const storage_event_router_1 = require("./storage-event-router");
|
|
|
5
5
|
function toKeyList(keys) {
|
|
6
6
|
return Array.isArray(keys) ? keys : [keys];
|
|
7
7
|
}
|
|
8
|
-
/**
|
|
9
|
-
* Adapts a Web Storage area to the library's `Storage` contract.
|
|
10
|
-
*
|
|
11
|
-
* Pass `undefined` where the global is missing, as it is on a server: the
|
|
12
|
-
* adapter then reads back nothing and **silently discards every write**, so a
|
|
13
|
-
* consumer keeps its initial value instead of the import throwing. Listeners
|
|
14
|
-
* are still accepted and reported, they simply never fire.
|
|
15
|
-
*/
|
|
8
|
+
/** Adapts a Web Storage area. With `undefined`, as on a server, it reads back nothing and discards every write. */
|
|
16
9
|
exports.default = (storage) => {
|
|
17
|
-
// Per
|
|
18
|
-
// share listeners, or a write to one area notifies subscribers of the other.
|
|
10
|
+
// Per instance: the localStorage and sessionStorage adapters must not share listeners.
|
|
19
11
|
const notifier = (0, change_notifier_1.createChangeNotifier)();
|
|
20
|
-
// Only a missing global is inert
|
|
21
|
-
// on first use instead of swallowing their writes.
|
|
12
|
+
// Only a missing global is inert; anything else a caller passes has to fail on first use.
|
|
22
13
|
if (storage === undefined) {
|
|
23
14
|
return {
|
|
24
15
|
get: () => ({}),
|
|
@@ -28,9 +19,7 @@ exports.default = (storage) => {
|
|
|
28
19
|
};
|
|
29
20
|
}
|
|
30
21
|
const route = { storage, fire: notifier.fire };
|
|
31
|
-
// The DOM subscription is shared and reference counted
|
|
32
|
-
// with its first listener and lets go with its last, so factory calls nobody
|
|
33
|
-
// listens to leave nothing attached to the global object.
|
|
22
|
+
// The DOM subscription is shared and reference counted, so adapters nobody listens to attach nothing.
|
|
34
23
|
const onChanged = {
|
|
35
24
|
addListener(listener) {
|
|
36
25
|
notifier.onChanged.addListener(listener);
|
|
@@ -50,8 +39,7 @@ exports.default = (storage) => {
|
|
|
50
39
|
const result = {};
|
|
51
40
|
for (const key of toKeyList(keys)) {
|
|
52
41
|
const item = storage.getItem(key);
|
|
53
|
-
// `null` is the only answer
|
|
54
|
-
// value the caller stored, and reporting it as a missing key loses it.
|
|
42
|
+
// `null` is the only answer meaning absence; an empty string is a value the caller stored.
|
|
55
43
|
if (item !== null)
|
|
56
44
|
result[key] = item;
|
|
57
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-web-storage.js","sourceRoot":"","sources":["../../src/utils/create-web-storage.ts"],"names":[],"mappings":";;AACA,uDAAwD;AACxD,iEAAsF;AAEtF,SAAS,SAAS,CAAC,IAAuB;IACxC,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;AAC5C,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"create-web-storage.js","sourceRoot":"","sources":["../../src/utils/create-web-storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import type { StorageChange, StorageChangeEvent } from '../@types/storage';
|
|
2
2
|
declare const TRACKED_AREAS: readonly ["local", "sync", "managed"];
|
|
3
3
|
export type Area = (typeof TRACKED_AREAS)[number];
|
|
4
|
-
/**
|
|
5
|
-
* Extension storage holds arbitrary JSON, while this library only ever writes
|
|
6
|
-
* serialized strings. Anything else under a key belongs to other code and is
|
|
7
|
-
* reported as absent — which is what effectively happened before, once such a
|
|
8
|
-
* value reached `JSON.parse` and the hook fell back to its initial value.
|
|
9
|
-
*/
|
|
4
|
+
/** Extension storage holds arbitrary JSON; this library writes only strings, so anything else reads as absent. */
|
|
10
5
|
export declare function toStoredValue(value: unknown): string | null | undefined;
|
|
11
6
|
export declare function toStorageChanges(changes: {
|
|
12
7
|
[key: string]: {
|
|
@@ -27,12 +22,7 @@ export interface ListenerRegistry {
|
|
|
27
22
|
}, area: string): void;
|
|
28
23
|
createOnChanged(area: Area): StorageChangeEvent;
|
|
29
24
|
}
|
|
30
|
-
/**
|
|
31
|
-
* Demultiplexes an extension's single `onChanged` event, which names the area
|
|
32
|
-
* that changed, to one notifier per area. Each adapter owns its own registry,
|
|
33
|
-
* so a change in one browser's storage never reaches listeners registered on
|
|
34
|
-
* another's.
|
|
35
|
-
*/
|
|
25
|
+
/** Demultiplexes an extension's single `onChanged` event to one notifier per area, one registry per adapter. */
|
|
36
26
|
export declare function createListenerRegistry(): ListenerRegistry;
|
|
37
27
|
export {};
|
|
38
28
|
//# sourceMappingURL=extension-storage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension-storage.d.ts","sourceRoot":"","sources":["../../src/utils/extension-storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAG1E,QAAA,MAAM,aAAa,uCAAwC,CAAA;AAE3D,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"extension-storage.d.ts","sourceRoot":"","sources":["../../src/utils/extension-storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAG1E,QAAA,MAAM,aAAa,uCAAwC,CAAA;AAE3D,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAOjD,kHAAkH;AAClH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAIvE;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,GAAG;IACxG,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAA;CAC7B,CAWA;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAQ1F;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,OAAO,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAA;KAAE,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnE,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,kBAAkB,CAAA;CAChD;AAED,gHAAgH;AAChH,wBAAgB,sBAAsB,IAAI,gBAAgB,CAiBzD"}
|
|
@@ -6,17 +6,11 @@ exports.toStoredItems = toStoredItems;
|
|
|
6
6
|
exports.createListenerRegistry = createListenerRegistry;
|
|
7
7
|
const change_notifier_1 = require("./change-notifier");
|
|
8
8
|
const TRACKED_AREAS = ['local', 'sync', 'managed'];
|
|
9
|
-
// Both browsers also report `session
|
|
10
|
-
// expose. Dispatching one would read an undefined notifier and throw.
|
|
9
|
+
// Both browsers also report `session`, an area this library does not expose; dispatching one would throw.
|
|
11
10
|
function isTrackedArea(area) {
|
|
12
11
|
return TRACKED_AREAS.includes(area);
|
|
13
12
|
}
|
|
14
|
-
/**
|
|
15
|
-
* Extension storage holds arbitrary JSON, while this library only ever writes
|
|
16
|
-
* serialized strings. Anything else under a key belongs to other code and is
|
|
17
|
-
* reported as absent — which is what effectively happened before, once such a
|
|
18
|
-
* value reached `JSON.parse` and the hook fell back to its initial value.
|
|
19
|
-
*/
|
|
13
|
+
/** Extension storage holds arbitrary JSON; this library writes only strings, so anything else reads as absent. */
|
|
20
14
|
function toStoredValue(value) {
|
|
21
15
|
if (value === undefined)
|
|
22
16
|
return;
|
|
@@ -40,12 +34,7 @@ function toStoredItems(items) {
|
|
|
40
34
|
}
|
|
41
35
|
return result;
|
|
42
36
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Demultiplexes an extension's single `onChanged` event, which names the area
|
|
45
|
-
* that changed, to one notifier per area. Each adapter owns its own registry,
|
|
46
|
-
* so a change in one browser's storage never reaches listeners registered on
|
|
47
|
-
* another's.
|
|
48
|
-
*/
|
|
37
|
+
/** Demultiplexes an extension's single `onChanged` event to one notifier per area, one registry per adapter. */
|
|
49
38
|
function createListenerRegistry() {
|
|
50
39
|
const notifiers = {
|
|
51
40
|
local: (0, change_notifier_1.createChangeNotifier)(),
|