webext-storage 3.0.0 → 3.1.0

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.
@@ -18,6 +18,10 @@ Return = Base | undefined> {
18
18
  remove(secondaryKey: string): Promise<void>;
19
19
  /** @deprecated Only here to match the Map API; use `remove` instead */
20
20
  delete(secondaryKey: string): Promise<void>;
21
+ keys(): Promise<string[]>;
22
+ clear(): Promise<void>;
23
+ entries(): AsyncIterableIterator<[string, Exclude<Return, undefined>]>;
24
+ [Symbol.asyncIterator](): AsyncIterableIterator<[string, Exclude<Return, undefined>]>;
21
25
  onChanged(callback: (key: string, value: Exclude<Return, undefined>) => void, signal?: AbortSignal): void;
22
26
  private getRawStorageKey;
23
27
  private getSecondaryStorageKey;
@@ -26,7 +26,7 @@ export class StorageItemMap {
26
26
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Assumes the user never uses the Storage API directly for this key
27
27
  return this.defaultValue;
28
28
  }
29
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-type-assertion -- Assumes the user never uses the Storage API directly for this key
29
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Assumes the user never uses the Storage API directly for this key
30
30
  return result[rawStorageKey];
31
31
  }
32
32
  async set(secondaryKey, value) {
@@ -47,6 +47,28 @@ export class StorageItemMap {
47
47
  async delete(secondaryKey) {
48
48
  return this.remove(secondaryKey);
49
49
  }
50
+ async keys() {
51
+ const rawKeys = await this.#getRawKeys();
52
+ return rawKeys.map(key => key.slice(this.prefix.length));
53
+ }
54
+ async clear() {
55
+ const rawKeys = await this.#getRawKeys();
56
+ if (rawKeys.length > 0) {
57
+ await this.#storage.remove(rawKeys);
58
+ }
59
+ }
60
+ async *entries() {
61
+ const secondaryKeys = await this.keys();
62
+ for (const secondaryKey of secondaryKeys) {
63
+ // eslint-disable-next-line no-await-in-loop -- Intentionally fetching one value at a time to avoid loading all storage at once
64
+ const value = await this.get(secondaryKey);
65
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Key exists in storage, get() will return the stored value
66
+ yield [secondaryKey, value];
67
+ }
68
+ }
69
+ [Symbol.asyncIterator]() {
70
+ return this.entries();
71
+ }
50
72
  onChanged(callback, signal) {
51
73
  assertChromeStorageAvailable();
52
74
  const changeHandler = (changes, area) => {
@@ -56,7 +78,7 @@ export class StorageItemMap {
56
78
  for (const rawKey of Object.keys(changes)) {
57
79
  const secondaryKey = this.getSecondaryStorageKey(rawKey);
58
80
  if (secondaryKey && hasStorageValueChanged(changes[rawKey])) {
59
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-type-assertion -- Assumes the user never uses the Storage API directly
81
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Assumes the user never uses the Storage API directly
60
82
  callback(secondaryKey, changes[rawKey].newValue);
61
83
  }
62
84
  }
@@ -74,4 +96,8 @@ export class StorageItemMap {
74
96
  getSecondaryStorageKey(rawKey) {
75
97
  return rawKey.startsWith(this.prefix) && rawKey.slice(this.prefix.length);
76
98
  }
99
+ async #getRawKeys() {
100
+ const allKeys = await this.#storage.getKeys();
101
+ return allKeys.filter(key => key.startsWith(this.prefix));
102
+ }
77
103
  }
@@ -19,7 +19,7 @@ export class StorageItem {
19
19
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Assumes the user never uses the Storage API directly
20
20
  return this.defaultValue;
21
21
  }
22
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-type-assertion -- Assumes the user never uses the Storage API directly
22
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Assumes the user never uses the Storage API directly
23
23
  return result[this.key];
24
24
  }
25
25
  async set(value) {
@@ -44,7 +44,7 @@ export class StorageItem {
44
44
  const changeHandler = (changes, area) => {
45
45
  const changedItem = changes[this.key];
46
46
  if (area === this.area && changedItem && hasStorageValueChanged(changedItem)) {
47
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-type-assertion -- Assumes the user never uses the Storage API directly
47
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Assumes the user never uses the Storage API directly
48
48
  callback(changedItem.newValue);
49
49
  }
50
50
  };
@@ -6,7 +6,6 @@ export function assertChromeStorageAvailable() {
6
6
  // Workaround for https://github.com/w3c/webextensions/issues/511
7
7
  // Firefox fires onChanged even when set() is called with the same value
8
8
  export function hasStorageValueChanged(change) {
9
- // eslint-disable-next-line n/no-unsupported-features/node-builtins -- browser extension context, not Node.js
10
9
  return !globalThis.navigator?.userAgent.includes('Firefox')
11
10
  || JSON.stringify(change.newValue) !== JSON.stringify(change.oldValue);
12
11
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webext-storage",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "description": "A more usable typed storage API for Web Extensions",
5
5
  "keywords": [
6
6
  "browser",