@ahoo-wang/fetcher-cosec 3.0.5 → 3.0.8

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
@@ -126,9 +126,15 @@ const fetcher = new Fetcher({
126
126
  baseURL: 'https://api.example.com',
127
127
  });
128
128
 
129
- // Create CoSec configurer with minimal required configuration
129
+ // Create CoSec configurer with flexible configuration
130
130
  const configurer = new CoSecConfigurer({
131
131
  appId: 'your-app-id',
132
+
133
+ // Optional: Custom storage implementations
134
+ tokenStorage: new TokenStorage(),
135
+ deviceIdStorage: new DeviceIdStorage(),
136
+
137
+ // Optional: Token refresher (enables authentication interceptors)
132
138
  tokenRefresher: {
133
139
  refresh: async token => {
134
140
  // Implement your token refresh logic
@@ -149,6 +155,7 @@ const configurer = new CoSecConfigurer({
149
155
  };
150
156
  },
151
157
  },
158
+
152
159
  // Optional: Custom error handlers (only add interceptors if provided)
153
160
  onUnauthorized: exchange => {
154
161
  console.error('Unauthorized access:', exchange.request.url);
@@ -159,7 +166,7 @@ const configurer = new CoSecConfigurer({
159
166
  console.error('Forbidden access:', exchange.request.url);
160
167
  // Show permission error
161
168
  alert('You do not have permission to access this resource');
162
- }
169
+ },
163
170
  });
164
171
 
165
172
  // Apply all CoSec interceptors with one call
@@ -171,9 +178,10 @@ const response = await fetcher.get('/protected-endpoint');
171
178
 
172
179
  ### Benefits of CoSecConfigurer
173
180
 
174
- - ✅ **One-line setup**: `configurer.applyTo(fetcher)` configures everything
175
- - ✅ **Minimal configuration**: Only `appId` and `tokenRefresher` are required
176
- - ✅ **Sensible defaults**: Automatic error handling and parameter names
181
+ - ✅ **Flexible configuration**: Support for full auth setup or minimal CoSec headers only
182
+ - ✅ **Custom storage**: Optional custom TokenStorage and DeviceIdStorage implementations
183
+ - ✅ **Conditional interceptors**: Authentication interceptors only added when tokenRefresher is provided
184
+ - ✅ **Error handler control**: Choose which error interceptors to add based on your needs
177
185
  - ✅ **Type-safe**: Full TypeScript support with intelligent defaults
178
186
  - ✅ **Backward compatible**: Original manual setup still works
179
187
 
@@ -235,6 +243,12 @@ The recommended way to configure CoSec authentication. Provides a simplified API
235
243
  ```typescript
236
244
  const configurer = new CoSecConfigurer({
237
245
  appId: 'your-app-id',
246
+
247
+ // Optional: Custom storage implementations
248
+ tokenStorage: new TokenStorage('custom-prefix'),
249
+ deviceIdStorage: new DeviceIdStorage('custom-prefix'),
250
+
251
+ // Optional: Token refresher (enables auth interceptors)
238
252
  tokenRefresher: {
239
253
  refresh: async token => {
240
254
  // Your token refresh implementation
@@ -244,6 +258,7 @@ const configurer = new CoSecConfigurer({
244
258
  };
245
259
  },
246
260
  },
261
+
247
262
  // Optional error handlers (interceptors only added if provided)
248
263
  onUnauthorized: exchange => {
249
264
  /* handle 401 */
@@ -251,21 +266,27 @@ const configurer = new CoSecConfigurer({
251
266
  onForbidden: async exchange => {
252
267
  /* handle 403 */
253
268
  },
254
- tenantId: 'tenantId', // default: 'tenantId'
255
- ownerId: 'ownerId', // default: 'ownerId'
256
269
  });
257
270
 
258
271
  configurer.applyTo(fetcher);
259
272
  ```
260
273
 
261
- **Automatically Configured Interceptors:**
274
+ **Conditionally Configured Interceptors:**
275
+
276
+ Always added:
277
+
278
+ - `CoSecRequestInterceptor` - Adds CoSec headers (appId, deviceId, requestId)
279
+ - `ResourceAttributionRequestInterceptor` - Adds tenant/owner path parameters
280
+
281
+ Only when `tokenRefresher` is provided:
282
+
283
+ - `AuthorizationRequestInterceptor` - Adds Bearer token authentication
284
+ - `AuthorizationResponseInterceptor` - Handles token refresh on 401 responses
285
+
286
+ Only when corresponding handlers are provided:
262
287
 
263
- - `CoSecRequestInterceptor` - Adds CoSec headers
264
- - `AuthorizationRequestInterceptor` - Adds Bearer token
265
- - `ResourceAttributionRequestInterceptor` - Adds tenant/owner parameters
266
- - `AuthorizationResponseInterceptor` - Handles token refresh
267
- - `UnauthorizedErrorInterceptor` - Handles 401 errors
268
- - `ForbiddenErrorInterceptor` - Handles 403 errors
288
+ - `UnauthorizedErrorInterceptor` - Handles 401 unauthorized errors
289
+ - `ForbiddenErrorInterceptor` - Handles 403 forbidden errors
269
290
 
270
291
  #### AuthorizationRequestInterceptor
271
292
 
package/README.zh-CN.md CHANGED
@@ -126,9 +126,15 @@ const fetcher = new Fetcher({
126
126
  baseURL: 'https://api.example.com',
127
127
  });
128
128
 
129
- // 使用最少的必需配置创建 CoSec 配置器
129
+ // 使用灵活的配置创建 CoSec 配置器
130
130
  const configurer = new CoSecConfigurer({
131
131
  appId: 'your-app-id',
132
+
133
+ // 可选:自定义存储实现
134
+ tokenStorage: new TokenStorage(),
135
+ deviceIdStorage: new DeviceIdStorage(),
136
+
137
+ // 可选:令牌刷新器(启用认证拦截器)
132
138
  tokenRefresher: {
133
139
  refresh: async token => {
134
140
  // 实现您的令牌刷新逻辑
@@ -149,6 +155,7 @@ const configurer = new CoSecConfigurer({
149
155
  };
150
156
  },
151
157
  },
158
+
152
159
  // 可选:自定义错误处理器(仅在提供时才添加拦截器)
153
160
  onUnauthorized: exchange => {
154
161
  console.error('未授权访问:', exchange.request.url);
@@ -159,7 +166,7 @@ const configurer = new CoSecConfigurer({
159
166
  console.error('禁止访问:', exchange.request.url);
160
167
  // 显示权限错误
161
168
  alert('您没有权限访问此资源');
162
- }
169
+ },
163
170
  });
164
171
 
165
172
  // 使用一次调用应用所有 CoSec 拦截器
@@ -171,9 +178,10 @@ const response = await fetcher.get('/protected-endpoint');
171
178
 
172
179
  ### CoSecConfigurer 的优势
173
180
 
174
- - ✅ **一行设置**:`configurer.applyTo(fetcher)` 配置一切
175
- - ✅ **最小配置**:仅需要 `appId``tokenRefresher`
176
- - ✅ **合理的默认值**:自动错误处理和参数名称
181
+ - ✅ **灵活配置**:支持完整认证设置或仅最小的 CoSec 头部
182
+ - ✅ **自定义存储**:可选的自定义 TokenStorageDeviceIdStorage 实现
183
+ - ✅ **条件拦截器**:仅在提供 tokenRefresher 时才添加认证拦截器
184
+ - ✅ **错误处理器控制**:根据需要选择添加哪些错误拦截器
177
185
  - ✅ **类型安全**:完整的 TypeScript 支持和智能默认值
178
186
  - ✅ **向后兼容**:原始手动设置仍然有效
179
187
 
@@ -235,6 +243,12 @@ interface JwtTokenManagerCapable {
235
243
  ```typescript
236
244
  const configurer = new CoSecConfigurer({
237
245
  appId: 'your-app-id',
246
+
247
+ // 可选:自定义存储实现
248
+ tokenStorage: new TokenStorage('custom-prefix'),
249
+ deviceIdStorage: new DeviceIdStorage('custom-prefix'),
250
+
251
+ // 可选:令牌刷新器(启用认证拦截器)
238
252
  tokenRefresher: {
239
253
  refresh: async token => {
240
254
  // 您的令牌刷新实现
@@ -244,6 +258,7 @@ const configurer = new CoSecConfigurer({
244
258
  };
245
259
  },
246
260
  },
261
+
247
262
  // 可选错误处理器(仅在提供时才添加拦截器)
248
263
  onUnauthorized: exchange => {
249
264
  /* 处理 401 */
@@ -251,21 +266,27 @@ const configurer = new CoSecConfigurer({
251
266
  onForbidden: async exchange => {
252
267
  /* 处理 403 */
253
268
  },
254
- tenantId: 'tenantId', // 默认: 'tenantId'
255
- ownerId: 'ownerId', // 默认: 'ownerId'
256
269
  });
257
270
 
258
271
  configurer.applyTo(fetcher);
259
272
  ```
260
273
 
261
- **自动配置的拦截器:**
274
+ **条件配置的拦截器:**
275
+
276
+ 始终添加:
277
+
278
+ - `CoSecRequestInterceptor` - 添加 CoSec 头部(appId、deviceId、requestId)
279
+ - `ResourceAttributionRequestInterceptor` - 添加租户/所有者路径参数
280
+
281
+ 仅在提供 `tokenRefresher` 时添加:
282
+
283
+ - `AuthorizationRequestInterceptor` - 添加 Bearer 令牌认证
284
+ - `AuthorizationResponseInterceptor` - 处理 401 响应时的令牌刷新
285
+
286
+ 仅在提供相应处理器时添加:
262
287
 
263
- - `CoSecRequestInterceptor` - 添加 CoSec 头部
264
- - `AuthorizationRequestInterceptor` - 添加 Bearer 令牌
265
- - `ResourceAttributionRequestInterceptor` - 添加租户/所有者参数
266
- - `AuthorizationResponseInterceptor` - 处理令牌刷新
267
- - `UnauthorizedErrorInterceptor` - 处理 401 错误
268
- - `ForbiddenErrorInterceptor` - 处理 403 错误
288
+ - `UnauthorizedErrorInterceptor` - 处理 401 未授权错误
289
+ - `ForbiddenErrorInterceptor` - 处理 403 禁止错误
269
290
 
270
291
  #### AuthorizationRequestInterceptor
271
292
 
@@ -3,24 +3,38 @@ import { DeviceIdStorage } from './deviceIdStorage';
3
3
  import { JwtTokenManager } from './jwtTokenManager';
4
4
  import { TokenRefresher } from './tokenRefresher';
5
5
  import { TokenStorage } from './tokenStorage';
6
+ import { AppIdCapable, DeviceIdStorageCapable } from './types';
6
7
  /**
7
8
  * Simplified configuration interface for CoSec setup.
8
- * Only requires the essential configuration, with sensible defaults for everything else.
9
+ * Provides flexible configuration with sensible defaults for optional components.
9
10
  */
10
- export interface CoSecConfig {
11
+ export interface CoSecConfig extends AppIdCapable, Partial<DeviceIdStorageCapable> {
11
12
  /**
12
13
  * Application ID to be sent in the CoSec-App-Id header.
13
14
  * This is required for identifying your application in the CoSec system.
14
15
  */
15
16
  appId: string;
17
+ /**
18
+ * Custom token storage implementation.
19
+ * If not provided, a default TokenStorage instance will be created.
20
+ * Useful for custom storage backends or testing scenarios.
21
+ */
22
+ tokenStorage?: TokenStorage;
23
+ /**
24
+ * Custom device ID storage implementation.
25
+ * If not provided, a default DeviceIdStorage instance will be created.
26
+ * Useful for custom device identification strategies or testing scenarios.
27
+ */
28
+ deviceIdStorage?: DeviceIdStorage;
16
29
  /**
17
30
  * Token refresher implementation for handling expired tokens.
18
- * This is required to enable automatic token refresh functionality.
31
+ * If not provided, authentication interceptors will not be added.
32
+ * This enables CoSec configuration without full JWT authentication.
19
33
  */
20
- tokenRefresher: TokenRefresher;
34
+ tokenRefresher?: TokenRefresher;
21
35
  /**
22
36
  * Callback function invoked when an unauthorized (401) response is detected.
23
- * If not provided, defaults to throwing an error.
37
+ * If not provided, 401 errors will not be intercepted.
24
38
  */
25
39
  onUnauthorized?: (exchange: FetchExchange) => Promise<void> | void;
26
40
  /**
@@ -30,19 +44,24 @@ export interface CoSecConfig {
30
44
  onForbidden?: (exchange: FetchExchange) => Promise<void>;
31
45
  }
32
46
  /**
33
- * CoSecConfigurer provides a simplified way to configure all CoSec interceptors
47
+ * CoSecConfigurer provides a flexible way to configure CoSec interceptors
34
48
  * and dependencies with a single configuration object.
35
49
  *
36
- * This class automatically creates all necessary dependencies (TokenStorage, DeviceIdStorage,
37
- * JwtTokenManager) and configures all CoSec interceptors with sensible defaults.
50
+ * This class implements FetcherConfigurer and supports both full authentication
51
+ * setups and minimal CoSec header injection. It conditionally creates dependencies
52
+ * based on the provided configuration, allowing for different levels of integration.
53
+ *
54
+ * @implements {FetcherConfigurer}
38
55
  *
39
56
  * @example
57
+ * Full authentication setup with custom storage:
40
58
  * ```typescript
41
59
  * const configurer = new CoSecConfigurer({
42
60
  * appId: 'my-app-001',
61
+ * tokenStorage: new CustomTokenStorage(),
62
+ * deviceIdStorage: new CustomDeviceStorage(),
43
63
  * tokenRefresher: {
44
64
  * refresh: async (token: CompositeToken) => {
45
- * // Your token refresh logic here
46
65
  * const response = await fetch('/api/auth/refresh', {
47
66
  * method: 'POST',
48
67
  * body: JSON.stringify({ refreshToken: token.refreshToken }),
@@ -54,6 +73,19 @@ export interface CoSecConfig {
54
73
  * };
55
74
  * },
56
75
  * },
76
+ * onUnauthorized: (exchange) => redirectToLogin(),
77
+ * onForbidden: (exchange) => showPermissionError(),
78
+ * });
79
+ *
80
+ * configurer.applyTo(fetcher);
81
+ * ```
82
+ *
83
+ * @example
84
+ * Minimal setup with only CoSec headers (no authentication):
85
+ * ```typescript
86
+ * const configurer = new CoSecConfigurer({
87
+ * appId: 'my-app-001',
88
+ * // No tokenRefresher provided - authentication interceptors won't be added
57
89
  * });
58
90
  *
59
91
  * configurer.applyTo(fetcher);
@@ -61,27 +93,77 @@ export interface CoSecConfig {
61
93
  */
62
94
  export declare class CoSecConfigurer implements FetcherConfigurer {
63
95
  readonly config: CoSecConfig;
96
+ /**
97
+ * Token storage instance, either provided in config or auto-created.
98
+ */
64
99
  readonly tokenStorage: TokenStorage;
100
+ /**
101
+ * Device ID storage instance, either provided in config or auto-created.
102
+ */
65
103
  readonly deviceIdStorage: DeviceIdStorage;
66
- readonly tokenManager: JwtTokenManager;
104
+ /**
105
+ * JWT token manager instance, only created if tokenRefresher is provided.
106
+ * When undefined, authentication interceptors will not be added.
107
+ */
108
+ readonly tokenManager?: JwtTokenManager;
67
109
  /**
68
110
  * Creates a new CoSecConfigurer instance with the provided configuration.
69
111
  *
70
- * @param config - Simplified CoSec configuration
112
+ * This constructor conditionally creates dependencies based on the configuration:
113
+ * - TokenStorage and DeviceIdStorage are always created (using defaults if not provided)
114
+ * - JwtTokenManager is only created if tokenRefresher is provided
115
+ *
116
+ * @param config - CoSec configuration object
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * // Full setup with all dependencies
121
+ * const configurer = new CoSecConfigurer({
122
+ * appId: 'my-app',
123
+ * tokenRefresher: myTokenRefresher,
124
+ * });
125
+ *
126
+ * // Minimal setup with custom storage
127
+ * const configurer = new CoSecConfigurer({
128
+ * appId: 'my-app',
129
+ * tokenStorage: customStorage,
130
+ * deviceIdStorage: customDeviceStorage,
131
+ * });
132
+ * ```
71
133
  */
72
134
  constructor(config: CoSecConfig);
73
135
  /**
74
- * Applies all CoSec interceptors to the provided Fetcher instance.
136
+ * Applies CoSec interceptors to the provided Fetcher instance.
75
137
  *
76
- * This method configures the following interceptors in the correct order:
138
+ * This method conditionally configures interceptors based on the provided configuration:
139
+ *
140
+ * Always added:
77
141
  * 1. CoSecRequestInterceptor - Adds CoSec headers (appId, deviceId, requestId)
78
- * 2. AuthorizationRequestInterceptor - Adds Authorization header with Bearer token
79
- * 3. ResourceAttributionRequestInterceptor - Adds tenant/owner path parameters
80
- * 4. AuthorizationResponseInterceptor - Handles 401 responses with token refresh
81
- * 5. UnauthorizedErrorInterceptor - Handles unauthorized errors
82
- * 6. ForbiddenErrorInterceptor - Handles forbidden errors
142
+ * 2. ResourceAttributionRequestInterceptor - Adds tenant/owner path parameters
143
+ *
144
+ * Only when `tokenRefresher` is provided:
145
+ * 3. AuthorizationRequestInterceptor - Adds Bearer token authentication
146
+ * 4. AuthorizationResponseInterceptor - Handles token refresh on 401 responses
147
+ *
148
+ * Only when corresponding handlers are provided:
149
+ * 5. UnauthorizedErrorInterceptor - Handles 401 unauthorized errors
150
+ * 6. ForbiddenErrorInterceptor - Handles 403 forbidden errors
83
151
  *
84
152
  * @param fetcher - The Fetcher instance to configure
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * const fetcher = new Fetcher({ baseURL: '/api' });
157
+ * const configurer = new CoSecConfigurer({
158
+ * appId: 'my-app',
159
+ * tokenRefresher: myTokenRefresher,
160
+ * onUnauthorized: handle401,
161
+ * onForbidden: handle403,
162
+ * });
163
+ *
164
+ * configurer.applyTo(fetcher);
165
+ * // Now fetcher has all CoSec interceptors configured
166
+ * ```
85
167
  */
86
168
  applyTo(fetcher: Fetcher): void;
87
169
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cosecConfigurer.d.ts","sourceRoot":"","sources":["../src/cosecConfigurer.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAI/E,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,cAAc,EAAE,cAAc,CAAC;IAE/B;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAEnE;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,eAAgB,YAAW,iBAAiB;aAU3B,MAAM,EAAE,WAAW;IAT/C,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC;IAEvC;;;;OAIG;gBACyB,MAAM,EAAE,WAAW;IAY/C;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CA0ChC"}
1
+ {"version":3,"file":"cosecConfigurer.d.ts","sourceRoot":"","sources":["../src/cosecConfigurer.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAI/E,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAE/D;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,YAAY,EAAE,OAAO,CAAC,sBAAsB,CAAC;IAChF;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAE5B;;;;OAIG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;IAElC;;;;OAIG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAEnE;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,qBAAa,eAAgB,YAAW,iBAAiB;aA0C3B,MAAM,EAAE,WAAW;IAzC/C;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IAEpC;;OAEG;IACH,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAE1C;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,eAAe,CAAC;IAExC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;gBACyB,MAAM,EAAE,WAAW;IAc/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CA0ChC"}
@@ -1,12 +1,12 @@
1
1
  import { KeyStorage, KeyStorageOptions } from '@ahoo-wang/fetcher-storage';
2
2
  export declare const DEFAULT_COSEC_DEVICE_ID_KEY = "cosec-device-id";
3
- export interface DeviceIdStorageOptions extends KeyStorageOptions<string> {
3
+ export interface DeviceIdStorageOptions extends Partial<KeyStorageOptions<string>> {
4
4
  }
5
5
  /**
6
6
  * Storage class for managing device identifiers.
7
7
  */
8
8
  export declare class DeviceIdStorage extends KeyStorage<string> {
9
- constructor(options?: DeviceIdStorageOptions);
9
+ constructor({ key, eventBus, ...reset }?: DeviceIdStorageOptions);
10
10
  /**
11
11
  * Generate a new device ID.
12
12
  *
@@ -1 +1 @@
1
- {"version":3,"file":"deviceIdStorage.d.ts","sourceRoot":"","sources":["../src/deviceIdStorage.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,UAAU,EAAE,iBAAiB,EAC9B,MAAM,4BAA4B,CAAC;AAGpC,eAAO,MAAM,2BAA2B,oBAAoB,CAAC;AAG7D,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB,CAAC,MAAM,CAAC;CACxE;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,UAAU,CAAC,MAAM,CAAC;gBACzC,OAAO,GAAE,sBAGpB;IAID;;;;OAIG;IACH,gBAAgB,IAAI,MAAM;IAI1B;;;;OAIG;IACH,WAAW,IAAI,MAAM;CAWtB"}
1
+ {"version":3,"file":"deviceIdStorage.d.ts","sourceRoot":"","sources":["../src/deviceIdStorage.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,UAAU,EAAE,iBAAiB,EAC9B,MAAM,4BAA4B,CAAC;AAGpC,eAAO,MAAM,2BAA2B,oBAAoB,CAAC;AAG7D,MAAM,WAAW,sBAAuB,SAAQ,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;CACjF;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,UAAU,CAAC,MAAM,CAAC;gBACzC,EACE,GAAiC,EACjC,QAAyG,EACzG,GAAG,KAAK,EACT,GAAE,sBAA2B;IAI1C;;;;OAIG;IACH,gBAAgB,IAAI,MAAM;IAI1B;;;;OAIG;IACH,WAAW,IAAI,MAAM;CAWtB"}