@switchlabs/verify-ai-react-native 1.1.2 → 2.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.
package/README.md CHANGED
@@ -4,18 +4,20 @@ React Native SDK for Verify AI photo verification.
4
4
 
5
5
  ## Install
6
6
 
7
- Expo-managed apps:
7
+ Core SDK (client, hooks, types):
8
8
 
9
9
  ```bash
10
- npx expo install @switchlabs/verify-ai-react-native expo-camera expo-image-manipulator @react-native-async-storage/async-storage
10
+ npm install @switchlabs/verify-ai-react-native
11
11
  ```
12
12
 
13
- React Native CLI:
13
+ With built-in camera scanner:
14
14
 
15
15
  ```bash
16
- npm install @switchlabs/verify-ai-react-native expo-camera expo-image-manipulator @react-native-async-storage/async-storage
16
+ npm install @switchlabs/verify-ai-react-native expo-camera expo-image-manipulator
17
17
  ```
18
18
 
19
+ For offline queue support, also install `@react-native-async-storage/async-storage`.
20
+
19
21
  If you want on-device inference, also install `expo-file-system`,
20
22
  `react-native-fast-tflite`, and configure `react-native-fast-tflite` for the
21
23
  delegates you plan to use.
@@ -44,18 +46,18 @@ function ParkingScreen() {
44
46
 
45
47
  ## Scanner Component
46
48
 
49
+ The scanner is exported from a separate subpath to avoid pulling in `expo-camera` for consumers that only need the client.
50
+
47
51
  ```tsx
48
- import { useVerifyAI, VerifyAIScanner } from '@switchlabs/verify-ai-react-native';
52
+ import { useVerifyAI } from '@switchlabs/verify-ai-react-native';
53
+ import { VerifyAIScanner } from '@switchlabs/verify-ai-react-native/scanner';
49
54
 
50
55
  function ScannerScreen() {
51
- const { verifyMultipart } = useVerifyAI({
52
- apiKey: 'vai_your_api_key',
53
- enableOnDeviceML: true,
54
- });
56
+ const { verify } = useVerifyAI({ apiKey: 'vai_your_api_key' });
55
57
  return (
56
58
  <VerifyAIScanner
57
- onCapture={(imageUri) =>
58
- verifyMultipart({ imageUri, policy: 'scooter_parking' })
59
+ onCapture={(base64) =>
60
+ verify({ image: base64, policy: 'scooter_parking' })
59
61
  }
60
62
  onResult={(result) => console.log(result.is_compliant ? 'PASS' : 'FAIL')}
61
63
  />
@@ -63,12 +65,10 @@ function ScannerScreen() {
63
65
  }
64
66
  ```
65
67
 
66
- `verifyMultipart()` is the recommended path for live camera captures. The
67
- built-in offline queue currently replays base64 `verify()` requests only; raw
68
- multipart uploads are not persisted automatically.
69
-
70
68
  ## Offline Mode
71
69
 
70
+ Requires `@react-native-async-storage/async-storage` to be installed.
71
+
72
72
  Set `offlineMode: true` to queue transient failures (network, timeout, 429, 5xx) and retry later.
73
73
 
74
74
  ```tsx
@@ -38,9 +38,6 @@ export declare class VerifyAIClient {
38
38
  * Submit a photo for AI verification using multipart/form-data.
39
39
  * Streams the image directly from disk — avoids base64 encoding overhead.
40
40
  *
41
- * **Breaking change:** `onCapture` prop on `VerifyAIScanner` now receives
42
- * an image URI instead of a base64 string.
43
- *
44
41
  * @param request - Multipart request with file URI and policy
45
42
  * @param options - Optional verify options (e.g. idempotency key)
46
43
  * @returns The verification result with compliance status and feedback
@@ -1,6 +1,24 @@
1
1
  import { TelemetryReporter } from '../telemetry/TelemetryReporter';
2
+ import { SDK_VERSION } from '../version';
2
3
  const DEFAULT_BASE_URL = 'https://verify.switchlabs.dev/api/v1';
3
4
  const DEFAULT_TIMEOUT = 30000;
5
+ const VEHICLE_TYPE_LABELS = {
6
+ scooter: 'Scooter',
7
+ 'e-bike': 'E-Bike',
8
+ ebike: 'E-Bike',
9
+ bike: 'Bike',
10
+ moped: 'Moped',
11
+ car: 'Car',
12
+ };
13
+ /** Auto-inject sdkVersion and vehicleTypeLabel into metadata. */
14
+ function enrichMetadata(metadata) {
15
+ const enriched = { ...metadata, sdkVersion: SDK_VERSION };
16
+ const vehicleType = enriched.vehicleType;
17
+ if (typeof vehicleType === 'string' && !enriched.vehicleTypeLabel) {
18
+ enriched.vehicleTypeLabel = VEHICLE_TYPE_LABELS[vehicleType.toLowerCase()] || vehicleType;
19
+ }
20
+ return enriched;
21
+ }
4
22
  export class VerifyAIClient {
5
23
  constructor(config) {
6
24
  if (!config.apiKey) {
@@ -142,19 +160,17 @@ export class VerifyAIClient {
142
160
  if (options?.idempotencyKey) {
143
161
  headers['Idempotency-Key'] = options.idempotencyKey;
144
162
  }
163
+ const enrichedRequest = { ...request, metadata: enrichMetadata(request.metadata) };
145
164
  return this.request('/verify', {
146
165
  method: 'POST',
147
166
  headers,
148
- body: JSON.stringify(request),
167
+ body: JSON.stringify(enrichedRequest),
149
168
  });
150
169
  }
151
170
  /**
152
171
  * Submit a photo for AI verification using multipart/form-data.
153
172
  * Streams the image directly from disk — avoids base64 encoding overhead.
154
173
  *
155
- * **Breaking change:** `onCapture` prop on `VerifyAIScanner` now receives
156
- * an image URI instead of a base64 string.
157
- *
158
174
  * @param request - Multipart request with file URI and policy
159
175
  * @param options - Optional verify options (e.g. idempotency key)
160
176
  * @returns The verification result with compliance status and feedback
@@ -168,9 +184,7 @@ export class VerifyAIClient {
168
184
  name: 'photo.jpg',
169
185
  });
170
186
  formData.append('policy', request.policy);
171
- if (request.metadata) {
172
- formData.append('metadata', JSON.stringify(request.metadata));
173
- }
187
+ formData.append('metadata', JSON.stringify(enrichMetadata(request.metadata)));
174
188
  if (request.provider) {
175
189
  formData.append('provider', request.provider);
176
190
  }
package/lib/index.d.ts CHANGED
@@ -1,8 +1,6 @@
1
1
  export { VerifyAIClient, VerifyAIRequestError } from './client';
2
2
  export { useVerifyAI } from './hooks/useVerifyAI';
3
3
  export type { UseVerifyAIReturn, UseVerifyAIConfig } from './hooks/useVerifyAI';
4
- export { VerifyAIScanner } from './components/VerifyAIScanner';
5
- export type { VerifyAIScannerProps } from './components/VerifyAIScanner';
6
4
  export { TelemetryReporter } from './telemetry/TelemetryReporter';
7
5
  export { TelemetryContext } from './telemetry/TelemetryContext';
8
6
  export { OfflineQueue } from './storage/offlineQueue';
package/lib/index.js CHANGED
@@ -2,8 +2,6 @@
2
2
  export { VerifyAIClient, VerifyAIRequestError } from './client';
3
3
  // Hooks
4
4
  export { useVerifyAI } from './hooks/useVerifyAI';
5
- // Components
6
- export { VerifyAIScanner } from './components/VerifyAIScanner';
7
5
  // Telemetry
8
6
  export { TelemetryReporter } from './telemetry/TelemetryReporter';
9
7
  export { TelemetryContext } from './telemetry/TelemetryContext';
@@ -0,0 +1,2 @@
1
+ export { VerifyAIScanner } from './components/VerifyAIScanner';
2
+ export type { VerifyAIScannerProps } from './components/VerifyAIScanner';
package/lib/scanner.js ADDED
@@ -0,0 +1 @@
1
+ export { VerifyAIScanner } from './components/VerifyAIScanner';
@@ -1,5 +1,12 @@
1
- import AsyncStorage from '@react-native-async-storage/async-storage';
2
1
  import { VerifyAIRequestError } from '../client';
2
+ let _storage = null;
3
+ async function getStorage() {
4
+ if (!_storage) {
5
+ const mod = await import('@react-native-async-storage/async-storage');
6
+ _storage = mod.default;
7
+ }
8
+ return _storage;
9
+ }
3
10
  const MANIFEST_KEY = '@verifyai/queue_manifest';
4
11
  const ITEM_PREFIX = '@verifyai/queue_item_';
5
12
  const LEGACY_KEY = '@verifyai/offline_queue';
@@ -17,13 +24,13 @@ export class OfflineQueue {
17
24
  if (this.migrated)
18
25
  return;
19
26
  this.migrated = true;
20
- const legacy = await AsyncStorage.getItem(LEGACY_KEY);
27
+ const legacy = await (await getStorage()).getItem(LEGACY_KEY);
21
28
  if (!legacy)
22
29
  return;
23
30
  try {
24
31
  const items = JSON.parse(legacy);
25
32
  if (!Array.isArray(items) || items.length === 0) {
26
- await AsyncStorage.removeItem(LEGACY_KEY);
33
+ await (await getStorage()).removeItem(LEGACY_KEY);
27
34
  return;
28
35
  }
29
36
  const ids = [];
@@ -32,24 +39,25 @@ export class OfflineQueue {
32
39
  ids.push(item.id);
33
40
  pairs.push([`${ITEM_PREFIX}${item.id}`, JSON.stringify(item)]);
34
41
  }
35
- await AsyncStorage.multiSet([
42
+ const storage = await getStorage();
43
+ await storage.multiSet([
36
44
  [MANIFEST_KEY, JSON.stringify(ids)],
37
45
  ...pairs,
38
46
  ]);
39
- await AsyncStorage.removeItem(LEGACY_KEY);
47
+ await storage.removeItem(LEGACY_KEY);
40
48
  }
41
49
  catch {
42
50
  // If migration fails, remove corrupt legacy data
43
- await AsyncStorage.removeItem(LEGACY_KEY);
51
+ await (await getStorage()).removeItem(LEGACY_KEY);
44
52
  }
45
53
  }
46
54
  async getManifest() {
47
55
  await this.migrateIfNeeded();
48
- const raw = await AsyncStorage.getItem(MANIFEST_KEY);
56
+ const raw = await (await getStorage()).getItem(MANIFEST_KEY);
49
57
  return raw ? JSON.parse(raw) : [];
50
58
  }
51
59
  async setManifest(ids) {
52
- await AsyncStorage.setItem(MANIFEST_KEY, JSON.stringify(ids));
60
+ await (await getStorage()).setItem(MANIFEST_KEY, JSON.stringify(ids));
53
61
  }
54
62
  /**
55
63
  * Add a verification request to the offline queue.
@@ -64,7 +72,7 @@ export class OfflineQueue {
64
72
  };
65
73
  const ids = await this.getManifest();
66
74
  ids.push(item.id);
67
- await AsyncStorage.setItem(`${ITEM_PREFIX}${item.id}`, JSON.stringify(item));
75
+ await (await getStorage()).setItem(`${ITEM_PREFIX}${item.id}`, JSON.stringify(item));
68
76
  await this.setManifest(ids);
69
77
  return item.id;
70
78
  }
@@ -76,7 +84,7 @@ export class OfflineQueue {
76
84
  if (ids.length === 0)
77
85
  return [];
78
86
  const keys = ids.map((id) => `${ITEM_PREFIX}${id}`);
79
- const pairs = await AsyncStorage.multiGet(keys);
87
+ const pairs = await (await getStorage()).multiGet(keys);
80
88
  const items = [];
81
89
  for (const [, value] of pairs) {
82
90
  if (value) {
@@ -104,7 +112,7 @@ export class OfflineQueue {
104
112
  const ids = await this.getManifest();
105
113
  const filtered = ids.filter((i) => i !== id);
106
114
  await this.setManifest(filtered);
107
- await AsyncStorage.removeItem(`${ITEM_PREFIX}${id}`);
115
+ await (await getStorage()).removeItem(`${ITEM_PREFIX}${id}`);
108
116
  }
109
117
  /**
110
118
  * Clear all items from the queue.
@@ -113,10 +121,10 @@ export class OfflineQueue {
113
121
  const ids = await this.getManifest();
114
122
  if (ids.length > 0) {
115
123
  const keys = ids.map((id) => `${ITEM_PREFIX}${id}`);
116
- await AsyncStorage.multiRemove([MANIFEST_KEY, ...keys]);
124
+ await (await getStorage()).multiRemove([MANIFEST_KEY, ...keys]);
117
125
  }
118
126
  else {
119
- await AsyncStorage.removeItem(MANIFEST_KEY);
127
+ await (await getStorage()).removeItem(MANIFEST_KEY);
120
128
  }
121
129
  }
122
130
  /**
@@ -140,7 +148,7 @@ export class OfflineQueue {
140
148
  try {
141
149
  const ids = await this.getManifest();
142
150
  for (const id of ids) {
143
- const raw = await AsyncStorage.getItem(`${ITEM_PREFIX}${id}`);
151
+ const raw = await (await getStorage()).getItem(`${ITEM_PREFIX}${id}`);
144
152
  if (!raw)
145
153
  continue;
146
154
  let item;
@@ -149,13 +157,13 @@ export class OfflineQueue {
149
157
  }
150
158
  catch {
151
159
  // Remove corrupt item
152
- await AsyncStorage.removeItem(`${ITEM_PREFIX}${id}`);
160
+ await (await getStorage()).removeItem(`${ITEM_PREFIX}${id}`);
153
161
  continue;
154
162
  }
155
163
  try {
156
164
  const result = await this.client.verify(item.request, { idempotencyKey: item.id });
157
165
  processed++;
158
- await AsyncStorage.removeItem(`${ITEM_PREFIX}${id}`);
166
+ await (await getStorage()).removeItem(`${ITEM_PREFIX}${id}`);
159
167
  onResult?.(item.id, result);
160
168
  }
161
169
  catch (err) {
@@ -163,12 +171,12 @@ export class OfflineQueue {
163
171
  const shouldRetry = !requestError || requestError.isRetryable;
164
172
  item.retryCount++;
165
173
  if (shouldRetry && item.retryCount < maxRetries) {
166
- await AsyncStorage.setItem(`${ITEM_PREFIX}${id}`, JSON.stringify(item));
174
+ await (await getStorage()).setItem(`${ITEM_PREFIX}${id}`, JSON.stringify(item));
167
175
  remainingIds.push(id);
168
176
  }
169
177
  else {
170
178
  failed++;
171
- await AsyncStorage.removeItem(`${ITEM_PREFIX}${id}`);
179
+ await (await getStorage()).removeItem(`${ITEM_PREFIX}${id}`);
172
180
  }
173
181
  }
174
182
  }
package/lib/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "1.1.1";
1
+ export declare const SDK_VERSION = "2.1.0";
package/lib/version.js CHANGED
@@ -1 +1 @@
1
- export const SDK_VERSION = '1.1.1';
1
+ export const SDK_VERSION = '2.1.0';
package/package.json CHANGED
@@ -1,9 +1,19 @@
1
1
  {
2
2
  "name": "@switchlabs/verify-ai-react-native",
3
- "version": "1.1.2",
3
+ "version": "2.1.0",
4
4
  "description": "React Native SDK for Verify AI - photo verification with AI vision processing",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./lib/index.d.ts",
10
+ "default": "./lib/index.js"
11
+ },
12
+ "./scanner": {
13
+ "types": "./lib/scanner.d.ts",
14
+ "default": "./lib/scanner.js"
15
+ }
16
+ },
7
17
  "files": [
8
18
  "src",
9
19
  "lib"
@@ -10,10 +10,30 @@ import type {
10
10
  PolicyConfigResponse,
11
11
  } from '../types';
12
12
  import { TelemetryReporter } from '../telemetry/TelemetryReporter';
13
+ import { SDK_VERSION } from '../version';
13
14
 
14
15
  const DEFAULT_BASE_URL = 'https://verify.switchlabs.dev/api/v1';
15
16
  const DEFAULT_TIMEOUT = 30000;
16
17
 
18
+ const VEHICLE_TYPE_LABELS: Record<string, string> = {
19
+ scooter: 'Scooter',
20
+ 'e-bike': 'E-Bike',
21
+ ebike: 'E-Bike',
22
+ bike: 'Bike',
23
+ moped: 'Moped',
24
+ car: 'Car',
25
+ };
26
+
27
+ /** Auto-inject sdkVersion and vehicleTypeLabel into metadata. */
28
+ function enrichMetadata(metadata?: Record<string, unknown>): Record<string, unknown> {
29
+ const enriched: Record<string, unknown> = { ...metadata, sdkVersion: SDK_VERSION };
30
+ const vehicleType = enriched.vehicleType;
31
+ if (typeof vehicleType === 'string' && !enriched.vehicleTypeLabel) {
32
+ enriched.vehicleTypeLabel = VEHICLE_TYPE_LABELS[vehicleType.toLowerCase()] || vehicleType;
33
+ }
34
+ return enriched;
35
+ }
36
+
17
37
  interface RequestContext {
18
38
  path: string;
19
39
  url: string;
@@ -204,10 +224,11 @@ export class VerifyAIClient {
204
224
  if (options?.idempotencyKey) {
205
225
  headers['Idempotency-Key'] = options.idempotencyKey;
206
226
  }
227
+ const enrichedRequest = { ...request, metadata: enrichMetadata(request.metadata) };
207
228
  return this.request<VerificationResult>('/verify', {
208
229
  method: 'POST',
209
230
  headers,
210
- body: JSON.stringify(request),
231
+ body: JSON.stringify(enrichedRequest),
211
232
  });
212
233
  }
213
234
 
@@ -215,9 +236,6 @@ export class VerifyAIClient {
215
236
  * Submit a photo for AI verification using multipart/form-data.
216
237
  * Streams the image directly from disk — avoids base64 encoding overhead.
217
238
  *
218
- * **Breaking change:** `onCapture` prop on `VerifyAIScanner` now receives
219
- * an image URI instead of a base64 string.
220
- *
221
239
  * @param request - Multipart request with file URI and policy
222
240
  * @param options - Optional verify options (e.g. idempotency key)
223
241
  * @returns The verification result with compliance status and feedback
@@ -231,9 +249,7 @@ export class VerifyAIClient {
231
249
  name: 'photo.jpg',
232
250
  } as unknown as Blob);
233
251
  formData.append('policy', request.policy);
234
- if (request.metadata) {
235
- formData.append('metadata', JSON.stringify(request.metadata));
236
- }
252
+ formData.append('metadata', JSON.stringify(enrichMetadata(request.metadata)));
237
253
  if (request.provider) {
238
254
  formData.append('provider', request.provider);
239
255
  }
package/src/index.ts CHANGED
@@ -5,10 +5,6 @@ export { VerifyAIClient, VerifyAIRequestError } from './client';
5
5
  export { useVerifyAI } from './hooks/useVerifyAI';
6
6
  export type { UseVerifyAIReturn, UseVerifyAIConfig } from './hooks/useVerifyAI';
7
7
 
8
- // Components
9
- export { VerifyAIScanner } from './components/VerifyAIScanner';
10
- export type { VerifyAIScannerProps } from './components/VerifyAIScanner';
11
-
12
8
  // Telemetry
13
9
  export { TelemetryReporter } from './telemetry/TelemetryReporter';
14
10
  export { TelemetryContext } from './telemetry/TelemetryContext';
package/src/scanner.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { VerifyAIScanner } from './components/VerifyAIScanner';
2
+ export type { VerifyAIScannerProps } from './components/VerifyAIScanner';
@@ -1,7 +1,15 @@
1
- import AsyncStorage from '@react-native-async-storage/async-storage';
2
1
  import type { VerificationRequest, VerificationResult, QueueItem } from '../types';
3
2
  import { VerifyAIClient, VerifyAIRequestError } from '../client';
4
3
 
4
+ let _storage: typeof import('@react-native-async-storage/async-storage').default | null = null;
5
+ async function getStorage() {
6
+ if (!_storage) {
7
+ const mod = await import('@react-native-async-storage/async-storage');
8
+ _storage = mod.default;
9
+ }
10
+ return _storage;
11
+ }
12
+
5
13
  const MANIFEST_KEY = '@verifyai/queue_manifest';
6
14
  const ITEM_PREFIX = '@verifyai/queue_item_';
7
15
  const LEGACY_KEY = '@verifyai/offline_queue';
@@ -23,13 +31,13 @@ export class OfflineQueue {
23
31
  if (this.migrated) return;
24
32
  this.migrated = true;
25
33
 
26
- const legacy = await AsyncStorage.getItem(LEGACY_KEY);
34
+ const legacy = await (await getStorage()).getItem(LEGACY_KEY);
27
35
  if (!legacy) return;
28
36
 
29
37
  try {
30
38
  const items: QueueItem[] = JSON.parse(legacy);
31
39
  if (!Array.isArray(items) || items.length === 0) {
32
- await AsyncStorage.removeItem(LEGACY_KEY);
40
+ await (await getStorage()).removeItem(LEGACY_KEY);
33
41
  return;
34
42
  }
35
43
 
@@ -40,25 +48,26 @@ export class OfflineQueue {
40
48
  pairs.push([`${ITEM_PREFIX}${item.id}`, JSON.stringify(item)]);
41
49
  }
42
50
 
43
- await AsyncStorage.multiSet([
51
+ const storage = await getStorage();
52
+ await storage.multiSet([
44
53
  [MANIFEST_KEY, JSON.stringify(ids)],
45
54
  ...pairs,
46
55
  ]);
47
- await AsyncStorage.removeItem(LEGACY_KEY);
56
+ await storage.removeItem(LEGACY_KEY);
48
57
  } catch {
49
58
  // If migration fails, remove corrupt legacy data
50
- await AsyncStorage.removeItem(LEGACY_KEY);
59
+ await (await getStorage()).removeItem(LEGACY_KEY);
51
60
  }
52
61
  }
53
62
 
54
63
  private async getManifest(): Promise<string[]> {
55
64
  await this.migrateIfNeeded();
56
- const raw = await AsyncStorage.getItem(MANIFEST_KEY);
65
+ const raw = await (await getStorage()).getItem(MANIFEST_KEY);
57
66
  return raw ? JSON.parse(raw) : [];
58
67
  }
59
68
 
60
69
  private async setManifest(ids: string[]): Promise<void> {
61
- await AsyncStorage.setItem(MANIFEST_KEY, JSON.stringify(ids));
70
+ await (await getStorage()).setItem(MANIFEST_KEY, JSON.stringify(ids));
62
71
  }
63
72
 
64
73
  /**
@@ -76,7 +85,7 @@ export class OfflineQueue {
76
85
  const ids = await this.getManifest();
77
86
  ids.push(item.id);
78
87
 
79
- await AsyncStorage.setItem(`${ITEM_PREFIX}${item.id}`, JSON.stringify(item));
88
+ await (await getStorage()).setItem(`${ITEM_PREFIX}${item.id}`, JSON.stringify(item));
80
89
  await this.setManifest(ids);
81
90
  return item.id;
82
91
  }
@@ -89,7 +98,7 @@ export class OfflineQueue {
89
98
  if (ids.length === 0) return [];
90
99
 
91
100
  const keys = ids.map((id) => `${ITEM_PREFIX}${id}`);
92
- const pairs = await AsyncStorage.multiGet(keys);
101
+ const pairs = await (await getStorage()).multiGet(keys);
93
102
 
94
103
  const items: QueueItem[] = [];
95
104
  for (const [, value] of pairs) {
@@ -119,7 +128,7 @@ export class OfflineQueue {
119
128
  const ids = await this.getManifest();
120
129
  const filtered = ids.filter((i) => i !== id);
121
130
  await this.setManifest(filtered);
122
- await AsyncStorage.removeItem(`${ITEM_PREFIX}${id}`);
131
+ await (await getStorage()).removeItem(`${ITEM_PREFIX}${id}`);
123
132
  }
124
133
 
125
134
  /**
@@ -129,9 +138,9 @@ export class OfflineQueue {
129
138
  const ids = await this.getManifest();
130
139
  if (ids.length > 0) {
131
140
  const keys = ids.map((id) => `${ITEM_PREFIX}${id}`);
132
- await AsyncStorage.multiRemove([MANIFEST_KEY, ...keys]);
141
+ await (await getStorage()).multiRemove([MANIFEST_KEY, ...keys]);
133
142
  } else {
134
- await AsyncStorage.removeItem(MANIFEST_KEY);
143
+ await (await getStorage()).removeItem(MANIFEST_KEY);
135
144
  }
136
145
  }
137
146
 
@@ -162,7 +171,7 @@ export class OfflineQueue {
162
171
  const ids = await this.getManifest();
163
172
 
164
173
  for (const id of ids) {
165
- const raw = await AsyncStorage.getItem(`${ITEM_PREFIX}${id}`);
174
+ const raw = await (await getStorage()).getItem(`${ITEM_PREFIX}${id}`);
166
175
  if (!raw) continue;
167
176
 
168
177
  let item: QueueItem;
@@ -170,14 +179,14 @@ export class OfflineQueue {
170
179
  item = JSON.parse(raw);
171
180
  } catch {
172
181
  // Remove corrupt item
173
- await AsyncStorage.removeItem(`${ITEM_PREFIX}${id}`);
182
+ await (await getStorage()).removeItem(`${ITEM_PREFIX}${id}`);
174
183
  continue;
175
184
  }
176
185
 
177
186
  try {
178
187
  const result = await this.client.verify(item.request, { idempotencyKey: item.id });
179
188
  processed++;
180
- await AsyncStorage.removeItem(`${ITEM_PREFIX}${id}`);
189
+ await (await getStorage()).removeItem(`${ITEM_PREFIX}${id}`);
181
190
  onResult?.(item.id, result);
182
191
  } catch (err) {
183
192
  const requestError = err instanceof VerifyAIRequestError ? err : null;
@@ -185,11 +194,11 @@ export class OfflineQueue {
185
194
 
186
195
  item.retryCount++;
187
196
  if (shouldRetry && item.retryCount < maxRetries) {
188
- await AsyncStorage.setItem(`${ITEM_PREFIX}${id}`, JSON.stringify(item));
197
+ await (await getStorage()).setItem(`${ITEM_PREFIX}${id}`, JSON.stringify(item));
189
198
  remainingIds.push(id);
190
199
  } else {
191
200
  failed++;
192
- await AsyncStorage.removeItem(`${ITEM_PREFIX}${id}`);
201
+ await (await getStorage()).removeItem(`${ITEM_PREFIX}${id}`);
193
202
  }
194
203
  }
195
204
  }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const SDK_VERSION = '1.1.1';
1
+ export const SDK_VERSION = '2.1.0';