webext-storage 1.1.0 → 1.2.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.
@@ -3,13 +3,13 @@ export type StorageItemOptions<T> = {
3
3
  area?: chrome.storage.AreaName;
4
4
  defaultValue?: T;
5
5
  };
6
- export declare class StorageItem<Base, InferredBase extends (Base | undefined) = Base | undefined, Return = InferredBase extends undefined ? Base | undefined : InferredBase> {
6
+ export declare class StorageItem<Base, Default = Base | undefined, Return = Default extends undefined ? Base : Default> {
7
7
  readonly key: string;
8
8
  readonly area: chrome.storage.AreaName;
9
- readonly defaultValue?: InferredBase;
10
- constructor(key: string, { area, defaultValue, }?: StorageItemOptions<NonNullable<InferredBase>>);
11
- get(): Promise<Return>;
12
- set(value: NonNullable<InferredBase>): Promise<void>;
13
- remove(): Promise<void>;
14
- onChange(callback: (value: NonNullable<InferredBase>) => void, signal?: AbortSignal): void;
9
+ readonly defaultValue?: Default;
10
+ constructor(key: string, { area, defaultValue, }?: StorageItemOptions<NonNullable<Default>>);
11
+ get: () => Promise<Return>;
12
+ set: (value: NonNullable<Default>) => Promise<void>;
13
+ remove: () => Promise<void>;
14
+ onChange(callback: (value: NonNullable<Default>) => void, signal?: AbortSignal): void;
15
15
  }
@@ -8,20 +8,20 @@ export class StorageItem {
8
8
  this.area = area;
9
9
  this.defaultValue = defaultValue;
10
10
  }
11
- async get() {
11
+ get = async () => {
12
12
  const result = await chromeP.storage[this.area].get(this.key);
13
13
  if (!Object.hasOwn(result, this.key)) {
14
14
  return this.defaultValue;
15
15
  }
16
16
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- Assumes the user never uses the Storage API directly
17
17
  return result[this.key];
18
- }
19
- async set(value) {
18
+ };
19
+ set = async (value) => {
20
20
  await chromeP.storage[this.area].set({ [this.key]: value });
21
- }
22
- async remove() {
21
+ };
22
+ remove = async () => {
23
23
  await chromeP.storage[this.area].remove(this.key);
24
- }
24
+ };
25
25
  onChange(callback, signal) {
26
26
  const changeHandler = (changes, area) => {
27
27
  const changedItem = changes[this.key];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webext-storage",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "A more usable typed storage API for Web Extensions",
5
5
  "keywords": [
6
6
  "browser",
package/readme.md CHANGED
@@ -12,6 +12,36 @@
12
12
 
13
13
  **Sponsored by [PixieBrix](https://www.pixiebrix.com)** :tada:
14
14
 
15
+ `chrome.storage.local.get()` is very inconvenient to use and it does not provide type safety. This module provides a better API:
16
+
17
+ ```ts
18
+ // Before
19
+ const storage = await chrome.storage.local.get('user-options');
20
+ const value = storage['user-options']; // The type is `any`
21
+ await chrome.storage.local.set({['user-options']: {color: 'red'}}); // Not type-checked
22
+ chrome.storage.onChanged.addListener((storageArea, change) => {
23
+ if (storageArea === 'local' && change['user-options']) { // Repetitive
24
+ console.log('New options', change['user-options'].newValue)
25
+ }
26
+ });
27
+
28
+ // After
29
+ const options = new StorageItem<Record<string, string>>('user-options');
30
+ const value = await options.get(); // The type is `Record<string, string> | undefined`
31
+ await options.set({color: 'red'}) // Type-checked
32
+ options.onChange(newValue => {
33
+ console.log('New options', newValue)
34
+ });
35
+ ```
36
+
37
+ Why this is better:
38
+
39
+ - The storage item is defined in a single place, including its storageArea, its types and default value
40
+ - `get` only is only `.get()` instead of the awkward post-get object access that
41
+ - Every `get` and `set` operation is type-safe
42
+ - If you provide a `defaultValue`, the return type will not be ` | undefined`
43
+ - The `onChange` example speaks for itself
44
+
15
45
  ## Install
16
46
 
17
47
  ```sh
@@ -48,7 +78,7 @@ username.onChange(newName => {
48
78
 
49
79
  ## Related
50
80
 
51
- - [webext-storage-cache](https://github.com/fregante/webext-storage-cache) - Detects where the current browser extension code is being run.
81
+ - [webext-storage-cache](https://github.com/fregante/webext-storage-cache) - Cache values in your Web Extension and clear them on expiration.
52
82
  - [webext-tools](https://github.com/fregante/webext-tools) - Utility functions for Web Extensions.
53
83
  - [webext-content-scripts](https://github.com/fregante/webext-content-scripts) - Utility functions to inject content scripts in WebExtensions.
54
84
  - [webext-base-css](https://github.com/fregante/webext-base-css) - Extremely minimal stylesheet/setup for Web Extensions’ options pages (also dark mode)