@ahoo-wang/fetcher-storage 2.8.6 → 2.9.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.
package/README.md CHANGED
@@ -8,18 +8,18 @@
8
8
  [![npm bundle size](https://img.shields.io/bundlephobia/minzip/%40ahoo-wang%2Ffetcher-storage)](https://www.npmjs.com/package/@ahoo-wang/fetcher-storage)
9
9
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/Ahoo-Wang/fetcher)
10
10
 
11
- A lightweight, cross-environment storage library with change event listening capabilities. Provides consistent API for
12
- browser localStorage/sessionStorage and in-memory storage with change notifications.
11
+ A lightweight, cross-environment storage library with key-based storage and automatic environment detection. Provides
12
+ consistent API for browser localStorage and in-memory storage with change notifications.
13
13
 
14
14
  ## Features
15
15
 
16
16
  - 🌐 Cross-environment support (Browser & Node.js)
17
17
  - 📦 Ultra-lightweight (~1KB gzip)
18
18
  - 🔔 Storage change event listening
19
- - 🔄 Automatic environment detection
20
- - 🛠️ Key-based storage with caching
19
+ - 🔄 Automatic environment detection with fallback
20
+ - 🛠️ Key-based storage with caching and serialization
21
21
  - 🔧 Custom serialization support
22
- - 📝 TypeScript support
22
+ - 📝 Full TypeScript support
23
23
 
24
24
  ## Installation
25
25
 
@@ -29,25 +29,20 @@ npm install @ahoo-wang/fetcher-storage
29
29
 
30
30
  ## Usage
31
31
 
32
- ### Basic Usage
32
+ ### Environment Detection and Storage Selection
33
33
 
34
34
  ```typescript
35
- import { createListenableStorage } from '@ahoo-wang/fetcher-storage';
35
+ import { getStorage, isBrowser } from '@ahoo-wang/fetcher-storage';
36
36
 
37
- // Automatically selects the appropriate storage implementation
38
- const storage = createListenableStorage();
37
+ // Check if running in browser
38
+ console.log('Is browser:', isBrowser());
39
39
 
40
- // Use like regular Storage API
40
+ // Get appropriate storage for current environment
41
+ const storage = getStorage(); // localStorage in browser, InMemoryStorage in Node.js
42
+
43
+ // Use like standard Storage API
41
44
  storage.setItem('key', 'value');
42
45
  const value = storage.getItem('key');
43
-
44
- // Listen for storage changes
45
- const removeListener = storage.addListener(event => {
46
- console.log('Storage changed:', event);
47
- });
48
-
49
- // Remove listener when no longer needed
50
- removeListener();
51
46
  ```
52
47
 
53
48
  ### Key-based Storage with Caching
@@ -55,19 +50,22 @@ removeListener();
55
50
  ```typescript
56
51
  import { KeyStorage } from '@ahoo-wang/fetcher-storage';
57
52
 
58
- // Create a storage for a specific key
53
+ // Create typed storage for a specific key
59
54
  const userStorage = new KeyStorage<{ name: string; age: number }>({
60
55
  key: 'user',
61
56
  });
62
57
 
63
- // Set and get values
58
+ // Set and get values with automatic caching
64
59
  userStorage.set({ name: 'John', age: 30 });
65
60
  const user = userStorage.get(); // {name: 'John', age: 30}
66
61
 
67
62
  // Listen for changes to this specific key
68
63
  const removeListener = userStorage.addListener(event => {
69
- console.log('User changed:', event.newValue);
64
+ console.log('User changed:', event.newValue, 'from:', event.oldValue);
70
65
  });
66
+
67
+ // Clean up when done
68
+ removeListener();
71
69
  ```
72
70
 
73
71
  ### Custom Serialization
@@ -75,58 +73,115 @@ const removeListener = userStorage.addListener(event => {
75
73
  ```typescript
76
74
  import { KeyStorage, JsonSerializer } from '@ahoo-wang/fetcher-storage';
77
75
 
76
+ // Use JSON serialization (default)
78
77
  const jsonStorage = new KeyStorage<any>({
79
78
  key: 'data',
80
79
  serializer: new JsonSerializer(),
81
80
  });
82
81
 
83
- jsonStorage.set({ message: 'Hello World' });
84
- const data = jsonStorage.get(); // {message: 'Hello World'}
82
+ jsonStorage.set({ message: 'Hello World', timestamp: Date.now() });
83
+ const data = jsonStorage.get(); // {message: 'Hello World', timestamp: 1234567890}
85
84
  ```
86
85
 
87
- ### Environment-specific Storage
86
+ ### In-Memory Storage
88
87
 
89
88
  ```typescript
90
- import {
91
- BrowserListenableStorage,
92
- InMemoryListenableStorage,
93
- } from '@ahoo-wang/fetcher-storage';
89
+ import { InMemoryStorage } from '@ahoo-wang/fetcher-storage';
90
+
91
+ // Create in-memory storage (works in any environment)
92
+ const memoryStorage = new InMemoryStorage();
93
+
94
+ // Use like standard Storage API
95
+ memoryStorage.setItem('temp', 'data');
96
+ console.log(memoryStorage.getItem('temp')); // 'data'
97
+ console.log(memoryStorage.length); // 1
98
+ ```
94
99
 
95
- // Browser storage (wraps localStorage or sessionStorage)
96
- const browserStorage = new BrowserListenableStorage(localStorage);
100
+ ### Advanced Configuration
97
101
 
98
- // In-memory storage (works in any environment)
99
- const memoryStorage = new InMemoryListenableStorage();
102
+ ```typescript
103
+ import { KeyStorage } from '@ahoo-wang/fetcher-storage';
104
+
105
+ // Custom storage and event bus
106
+ const customStorage = new KeyStorage<string>({
107
+ key: 'custom',
108
+ storage: new InMemoryStorage(), // Use in-memory instead of localStorage
109
+ // eventBus: customEventBus, // Custom event bus for notifications
110
+ });
100
111
  ```
101
112
 
102
- ## API
113
+ ## API Reference
103
114
 
104
- ### createListenableStorage()
115
+ ### Environment Utilities
105
116
 
106
- Factory function that automatically returns the appropriate storage implementation based on the environment:
117
+ #### `isBrowser(): boolean`
107
118
 
108
- - Browser environment: `BrowserListenableStorage` wrapping `localStorage`
109
- - Non-browser environment: `InMemoryListenableStorage`
119
+ Checks if the current environment is a browser.
110
120
 
111
- ### ListenableStorage
121
+ #### `getStorage(): Storage`
112
122
 
113
- Extends the native `Storage` interface with event listening capabilities:
123
+ Returns the appropriate storage implementation:
114
124
 
115
- - `addListener(listener: StorageListener): RemoveStorageListener`
116
- - All standard `Storage` methods (`getItem`, `setItem`, `removeItem`, etc.)
125
+ - Browser: `window.localStorage` (with availability check)
126
+ - Non-browser: `InMemoryStorage` instance
117
127
 
118
128
  ### KeyStorage
119
129
 
120
- A storage wrapper for managing a single value associated with a specific key:
130
+ A storage wrapper for managing typed values with caching and change notifications.
131
+
132
+ ```typescript
133
+ new KeyStorage<T>(options
134
+ :
135
+ KeyStorageOptions<T>
136
+ )
137
+ ```
138
+
139
+ #### Options
121
140
 
122
- - Automatic caching with cache invalidation
123
- - Key-specific event listening
124
- - Custom serialization support
141
+ - `key: string` - Storage key
142
+ - `serializer?: Serializer<string, T>` - Custom serializer (default: JsonSerializer)
143
+ - `storage?: Storage` - Custom storage (default: getStorage())
144
+ - `eventBus?: TypedEventBus<StorageEvent<T>>` - Custom event bus
145
+
146
+ #### Methods
147
+
148
+ - `get(): T | null` - Get cached value
149
+ - `set(value: T): void` - Set value with caching and notification
150
+ - `remove(): void` - Remove value and clear cache
151
+ - `addListener(handler: EventHandler<StorageEvent<T>>): RemoveStorageListener` - Add change listener
152
+
153
+ ### InMemoryStorage
154
+
155
+ In-memory implementation of the Storage interface.
156
+
157
+ ```typescript
158
+ new InMemoryStorage();
159
+ ```
160
+
161
+ Implements all standard Storage methods with Map-based storage.
125
162
 
126
163
  ### Serializers
127
164
 
128
- - `JsonSerializer`: Serializes values to/from JSON strings
129
- - `IdentitySerializer`: Passes values through without modification
165
+ #### `JsonSerializer`
166
+
167
+ Serializes values to/from JSON strings.
168
+
169
+ #### `typedIdentitySerializer<T>()`
170
+
171
+ Identity serializer that passes values through unchanged.
172
+
173
+ ## TypeScript Support
174
+
175
+ Full TypeScript support with generics and type inference:
176
+
177
+ ```typescript
178
+ // Typed storage
179
+ const userStorage = new KeyStorage<User>({ key: 'user' });
180
+
181
+ // Type-safe operations
182
+ userStorage.set({ id: 1, name: 'John' });
183
+ const user = userStorage.get(); // User | null
184
+ ```
130
185
 
131
186
  ## License
132
187
 
package/README.zh-CN.md CHANGED
@@ -8,17 +8,17 @@
8
8
  [![npm bundle size](https://img.shields.io/bundlephobia/minzip/%40ahoo-wang%2Ffetcher-storage)](https://www.npmjs.com/package/@ahoo-wang/fetcher-storage)
9
9
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/Ahoo-Wang/fetcher)
10
10
 
11
- 一个轻量级的跨环境存储库,具有变更事件监听功能。为浏览器 localStorage/sessionStorage 和内存存储提供一致的 API,并支持变更通知。
11
+ 一个轻量级的跨环境存储库,具有基于键的存储和自动环境检测功能。为浏览器 localStorage 和内存存储提供一致的 API,并支持变更通知。
12
12
 
13
13
  ## 特性
14
14
 
15
15
  - 🌐 跨环境支持(浏览器和 Node.js)
16
16
  - 📦 超轻量级(~1KB gzip)
17
17
  - 🔔 存储变更事件监听
18
- - 🔄 自动环境检测
19
- - 🛠️ 基于键的存储和缓存
18
+ - 🔄 自动环境检测和降级处理
19
+ - 🛠️ 基于键的存储、缓存和序列化
20
20
  - 🔧 自定义序列化支持
21
- - 📝 TypeScript 支持
21
+ - 📝 完整的 TypeScript 支持
22
22
 
23
23
  ## 安装
24
24
 
@@ -28,25 +28,20 @@ npm install @ahoo-wang/fetcher-storage
28
28
 
29
29
  ## 使用方法
30
30
 
31
- ### 基本用法
31
+ ### 环境检测和存储选择
32
32
 
33
33
  ```typescript
34
- import { createListenableStorage } from '@ahoo-wang/fetcher-storage';
34
+ import { getStorage, isBrowser } from '@ahoo-wang/fetcher-storage';
35
35
 
36
- // 自动选择合适的存储实现
37
- const storage = createListenableStorage();
36
+ // 检查是否在浏览器环境中运行
37
+ console.log('是否为浏览器:', isBrowser());
38
38
 
39
- // 像使用常规 Storage API 一样使用
39
+ // 获取当前环境的合适存储
40
+ const storage = getStorage(); // 浏览器中使用 localStorage,Node.js 中使用 InMemoryStorage
41
+
42
+ // 像标准 Storage API 一样使用
40
43
  storage.setItem('key', 'value');
41
44
  const value = storage.getItem('key');
42
-
43
- // 监听存储变更
44
- const removeListener = storage.addListener(event => {
45
- console.log('存储变更:', event);
46
- });
47
-
48
- // 不再需要时移除监听器
49
- removeListener();
50
45
  ```
51
46
 
52
47
  ### 基于键的存储和缓存
@@ -54,19 +49,22 @@ removeListener();
54
49
  ```typescript
55
50
  import { KeyStorage } from '@ahoo-wang/fetcher-storage';
56
51
 
57
- // 为特定键创建存储
52
+ // 为特定键创建类型化的存储
58
53
  const userStorage = new KeyStorage<{ name: string; age: number }>({
59
54
  key: 'user',
60
55
  });
61
56
 
62
- // 设置和获取值
57
+ // 设置和获取值,自动缓存
63
58
  userStorage.set({ name: 'John', age: 30 });
64
59
  const user = userStorage.get(); // {name: 'John', age: 30}
65
60
 
66
61
  // 监听此特定键的变更
67
62
  const removeListener = userStorage.addListener(event => {
68
- console.log('用户变更:', event.newValue);
63
+ console.log('用户变更:', event.newValue, '来自:', event.oldValue);
69
64
  });
65
+
66
+ // 使用完毕后清理
67
+ removeListener();
70
68
  ```
71
69
 
72
70
  ### 自定义序列化
@@ -74,58 +72,112 @@ const removeListener = userStorage.addListener(event => {
74
72
  ```typescript
75
73
  import { KeyStorage, JsonSerializer } from '@ahoo-wang/fetcher-storage';
76
74
 
75
+ // 使用 JSON 序列化(默认)
77
76
  const jsonStorage = new KeyStorage<any>({
78
77
  key: 'data',
79
78
  serializer: new JsonSerializer(),
80
79
  });
81
80
 
82
- jsonStorage.set({ message: 'Hello World' });
83
- const data = jsonStorage.get(); // {message: 'Hello World'}
81
+ jsonStorage.set({ message: 'Hello World', timestamp: Date.now() });
82
+ const data = jsonStorage.get(); // {message: 'Hello World', timestamp: 1234567890}
84
83
  ```
85
84
 
86
- ### 环境特定的存储
85
+ ### 内存存储
87
86
 
88
87
  ```typescript
89
- import {
90
- BrowserListenableStorage,
91
- InMemoryListenableStorage,
92
- } from '@ahoo-wang/fetcher-storage';
88
+ import { InMemoryStorage } from '@ahoo-wang/fetcher-storage';
93
89
 
94
- // 浏览器存储(包装 localStorage 或 sessionStorage)
95
- const browserStorage = new BrowserListenableStorage(localStorage);
90
+ // 创建内存存储(在任何环境中都能工作)
91
+ const memoryStorage = new InMemoryStorage();
96
92
 
97
- // 内存存储(在任何环境中都能工作)
98
- const memoryStorage = new InMemoryListenableStorage();
93
+ // 像标准 Storage API 一样使用
94
+ memoryStorage.setItem('temp', 'data');
95
+ console.log(memoryStorage.getItem('temp')); // 'data'
96
+ console.log(memoryStorage.length); // 1
99
97
  ```
100
98
 
101
- ## API
99
+ ### 高级配置
102
100
 
103
- ### createListenableStorage()
101
+ ```typescript
102
+ import { KeyStorage, InMemoryStorage } from '@ahoo-wang/fetcher-storage';
104
103
 
105
- 工厂函数,根据环境自动返回合适的存储实现:
104
+ // 自定义存储和事件总线
105
+ const customStorage = new KeyStorage<string>({
106
+ key: 'custom',
107
+ storage: new InMemoryStorage(), // 使用内存存储而不是 localStorage
108
+ // eventBus: customEventBus, // 自定义事件总线用于通知
109
+ });
110
+ ```
111
+
112
+ ## API 参考
113
+
114
+ ### 环境工具
115
+
116
+ #### `isBrowser(): boolean`
106
117
 
107
- - 浏览器环境:包装 localStorage 的 `BrowserListenableStorage`
108
- - 非浏览器环境:`InMemoryListenableStorage`
118
+ 检查当前环境是否为浏览器。
109
119
 
110
- ### ListenableStorage
120
+ #### `getStorage(): Storage`
111
121
 
112
- 扩展了原生 `Storage` 接口,增加了事件监听功能:
122
+ 返回合适的存储实现:
113
123
 
114
- - `addListener(listener: StorageListener): RemoveStorageListener`
115
- - 所有标准 `Storage` 方法(`getItem`、`setItem`、`removeItem` 等)
124
+ - 浏览器:`window.localStorage`(带可用性检查)
125
+ - 非浏览器:`InMemoryStorage` 实例
116
126
 
117
127
  ### KeyStorage
118
128
 
119
- 用于管理与特定键关联的单个值的存储包装器:
129
+ 用于管理类型化值、缓存和变更通知的存储包装器。
130
+
131
+ ```typescript
132
+ new KeyStorage<T>(options: KeyStorageOptions<T>)
133
+ ```
134
+
135
+ #### 选项
120
136
 
121
- - 自动缓存和缓存失效
122
- - 键特定的事件监听
123
- - 自定义序列化支持
137
+ - `key: string` - 存储键
138
+ - `serializer?: Serializer<string, T>` - 自定义序列化器(默认:JsonSerializer)
139
+ - `storage?: Storage` - 自定义存储(默认:getStorage())
140
+ - `eventBus?: TypedEventBus<StorageEvent<T>>` - 自定义事件总线
141
+
142
+ #### 方法
143
+
144
+ - `get(): T | null` - 获取缓存的值
145
+ - `set(value: T): void` - 设置值并缓存和通知
146
+ - `remove(): void` - 移除值并清除缓存
147
+ - `addListener(handler: EventHandler<StorageEvent<T>>): RemoveStorageListener` - 添加变更监听器
148
+
149
+ ### InMemoryStorage
150
+
151
+ Storage 接口的内存实现。
152
+
153
+ ```typescript
154
+ new InMemoryStorage();
155
+ ```
156
+
157
+ 使用 Map 实现所有标准 Storage 方法。
124
158
 
125
159
  ### 序列化器
126
160
 
127
- - `JsonSerializer`:将值序列化为 JSON 字符串
128
- - `IdentitySerializer`:不进行修改直接传递值
161
+ #### `JsonSerializer`
162
+
163
+ 将值序列化为 JSON 字符串。
164
+
165
+ #### `typedIdentitySerializer<T>()`
166
+
167
+ 恒等序列化器,直接传递值而不修改。
168
+
169
+ ## TypeScript 支持
170
+
171
+ 完整的 TypeScript 支持,包括泛型和类型推断:
172
+
173
+ ```typescript
174
+ // 类型化存储
175
+ const userStorage = new KeyStorage<User>({ key: 'user' });
176
+
177
+ // 类型安全操作
178
+ userStorage.set({ id: 1, name: 'John' });
179
+ const user = userStorage.get(); // User | null
180
+ ```
129
181
 
130
182
  ## 许可证
131
183
 
package/dist/env.d.ts CHANGED
@@ -1,2 +1,12 @@
1
+ /**
2
+ * Checks if the current environment is a browser.
3
+ * @returns True if running in a browser environment, false otherwise
4
+ */
1
5
  export declare function isBrowser(): boolean;
6
+ /**
7
+ * Gets the appropriate storage implementation based on the environment.
8
+ * Returns localStorage in browser environments if available, InMemoryStorage otherwise.
9
+ * @returns A Storage-compatible object
10
+ */
11
+ export declare const getStorage: () => Storage;
2
12
  //# sourceMappingURL=env.d.ts.map
package/dist/env.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAaA,wBAAgB,SAAS,IAAI,OAAO,CAEnC"}
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAeA;;;GAGG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,QAAO,OAK7B,CAAC"}
@@ -1,11 +1,5 @@
1
- import { ListenableStorage, RemoveStorageListener, StorageListener } from './listenableStorage';
2
- /**
3
- * An in-memory implementation of ListenableStorage that works in any environment.
4
- * This implementation stores data in a Map and manually fires storage events when data changes.
5
- */
6
- export declare class InMemoryListenableStorage implements ListenableStorage {
1
+ export declare class InMemoryStorage implements Storage {
7
2
  private readonly store;
8
- private readonly listeners;
9
3
  /**
10
4
  * Gets the number of items stored in the storage.
11
5
  */
@@ -37,16 +31,5 @@ export declare class InMemoryListenableStorage implements ListenableStorage {
37
31
  * @param value - The value to set
38
32
  */
39
33
  setItem(key: string, value: string): void;
40
- /**
41
- * Adds a listener for storage changes.
42
- * @param listener - The listener function to be called when storage changes
43
- * @returns A function that can be called to remove the listener
44
- */
45
- addListener(listener: StorageListener): RemoveStorageListener;
46
- /**
47
- * Notifies all listeners of a storage change by creating and dispatching a StorageEvent.
48
- * @param eventInit - The initialization object for the StorageEvent
49
- */
50
- private notifyListeners;
51
34
  }
52
- //# sourceMappingURL=inMemoryListenableStorage.d.ts.map
35
+ //# sourceMappingURL=inMemoryStorage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inMemoryStorage.d.ts","sourceRoot":"","sources":["../src/inMemoryStorage.ts"],"names":[],"mappings":"AAaA,qBAAa,eAAgB,YAAW,OAAO;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IAExD;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;;;OAIG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKnC;;;;OAIG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKjC;;;OAGG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI7B;;;;OAIG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;CAG1C"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,5 @@
1
1
  export * from './env';
2
- export * from './listenableStorage';
3
- export * from './browserListenableStorage';
4
- export * from './inMemoryListenableStorage';
5
2
  export * from './keyStorage';
3
+ export * from './inMemoryStorage';
6
4
  export * from './serializer';
7
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,OAAO,CAAC;AACtB,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,OAAO,CAAC;AACtB,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC"}