@teardown/react-native 1.2.39 → 2.0.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.
- package/README.md +89 -7
- package/docs/01-getting-started.mdx +147 -0
- package/docs/02-core-concepts.mdx +188 -0
- package/docs/03-identity.mdx +301 -0
- package/docs/04-force-updates.mdx +339 -0
- package/docs/05-device-info.mdx +324 -0
- package/docs/06-logging.mdx +345 -0
- package/docs/06-storage.mdx +349 -0
- package/docs/07-api-reference.mdx +472 -0
- package/docs/07-logging.mdx +345 -0
- package/docs/08-api-reference.mdx +472 -0
- package/docs/08-hooks-reference.mdx +476 -0
- package/docs/09-advanced.mdx +563 -0
- package/docs/09-hooks-reference.mdx +476 -0
- package/docs/10-advanced.mdx +563 -0
- package/package.json +65 -47
- package/src/clients/api/api.client.ts +80 -0
- package/src/clients/api/index.ts +1 -0
- package/src/clients/device/device.adpater-interface.ts +57 -0
- package/src/clients/device/device.client.test.ts +190 -0
- package/src/clients/device/device.client.ts +69 -0
- package/src/clients/device/expo-adapter.ts +90 -0
- package/src/clients/device/index.ts +4 -0
- package/src/clients/force-update/force-update.client.test.ts +295 -0
- package/src/clients/force-update/force-update.client.ts +224 -0
- package/src/clients/force-update/index.ts +1 -0
- package/src/clients/identity/identity.client.test.ts +454 -0
- package/src/clients/identity/identity.client.ts +255 -0
- package/src/clients/identity/index.ts +1 -0
- package/src/clients/logging/index.ts +1 -0
- package/src/clients/logging/logging.client.ts +92 -0
- package/src/clients/notifications/notifications.client.ts +10 -0
- package/src/clients/storage/index.ts +1 -0
- package/src/clients/storage/mmkv-adapter.ts +23 -0
- package/src/clients/storage/storage.client.ts +75 -0
- package/src/clients/utils/index.ts +1 -0
- package/src/clients/utils/utils.client.ts +75 -0
- package/src/components/ui/button.tsx +0 -0
- package/src/components/ui/input.tsx +0 -0
- package/src/contexts/index.ts +1 -0
- package/src/contexts/teardown.context.ts +17 -0
- package/src/exports/expo.ts +1 -0
- package/src/exports/index.ts +16 -0
- package/src/exports/mmkv.ts +1 -0
- package/src/hooks/use-force-update.ts +38 -0
- package/src/hooks/use-session.ts +26 -0
- package/src/providers/teardown.provider.tsx +28 -0
- package/src/teardown.core.ts +76 -0
- package/dist/components/index.d.ts +0 -1
- package/dist/components/index.js +0 -3
- package/dist/components/index.js.map +0 -1
- package/dist/components/teardown-logo.d.ts +0 -4
- package/dist/components/teardown-logo.js +0 -35
- package/dist/components/teardown-logo.js.map +0 -1
- package/dist/containers/index.d.ts +0 -1
- package/dist/containers/index.js +0 -18
- package/dist/containers/index.js.map +0 -1
- package/dist/containers/teardown.container.d.ts +0 -8
- package/dist/containers/teardown.container.js +0 -26
- package/dist/containers/teardown.container.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -22
- package/dist/index.js.map +0 -1
- package/dist/plugins/http.plugin.d.ts +0 -23
- package/dist/plugins/http.plugin.js +0 -145
- package/dist/plugins/http.plugin.js.map +0 -1
- package/dist/plugins/index.d.ts +0 -2
- package/dist/plugins/index.js +0 -20
- package/dist/plugins/index.js.map +0 -1
- package/dist/plugins/logging.plugin.d.ts +0 -9
- package/dist/plugins/logging.plugin.js +0 -36
- package/dist/plugins/logging.plugin.js.map +0 -1
- package/dist/plugins/websocket.plugin.d.ts +0 -1
- package/dist/plugins/websocket.plugin.js +0 -108
- package/dist/plugins/websocket.plugin.js.map +0 -1
- package/dist/services/index.d.ts +0 -1
- package/dist/services/index.js +0 -18
- package/dist/services/index.js.map +0 -1
- package/dist/services/teardown.service.d.ts +0 -10
- package/dist/services/teardown.service.js +0 -22
- package/dist/services/teardown.service.js.map +0 -1
- package/dist/teardown.client.d.ts +0 -41
- package/dist/teardown.client.js +0 -60
- package/dist/teardown.client.js.map +0 -1
- package/dist/utils/log.d.ts +0 -5
- package/dist/utils/log.js +0 -9
- package/dist/utils/log.js.map +0 -1
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
# Storage
|
|
2
|
+
|
|
3
|
+
Persistent, namespaced storage with platform adapters.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The StorageClient provides:
|
|
8
|
+
- Namespaced key-value storage
|
|
9
|
+
- Platform-agnostic interface
|
|
10
|
+
- Multiple storage adapters
|
|
11
|
+
- Automatic cleanup
|
|
12
|
+
|
|
13
|
+
## Storage Adapters
|
|
14
|
+
|
|
15
|
+
### MMKV Adapter (Recommended)
|
|
16
|
+
|
|
17
|
+
Fast, encrypted storage using react-native-mmkv:
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { TeardownCore } from '@teardown/react-native';
|
|
21
|
+
import { createMMKVStorageFactory } from '@teardown/react-native/mmkv';
|
|
22
|
+
|
|
23
|
+
const teardown = new TeardownCore({
|
|
24
|
+
// ... other options
|
|
25
|
+
storageFactory: createMMKVStorageFactory(),
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Install dependency:
|
|
30
|
+
```bash
|
|
31
|
+
bun add react-native-mmkv
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Benefits:
|
|
35
|
+
- ⚡ Extremely fast (synchronous)
|
|
36
|
+
- 🔒 Encrypted by default
|
|
37
|
+
- 📦 Small bundle size
|
|
38
|
+
- 💾 Persistent across app restarts
|
|
39
|
+
|
|
40
|
+
### Custom Storage Adapter
|
|
41
|
+
|
|
42
|
+
Create your own storage adapter:
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import type { SupportedStorage } from '@teardown/react-native';
|
|
46
|
+
|
|
47
|
+
function createCustomStorageFactory() {
|
|
48
|
+
return (storageKey: string): SupportedStorage => {
|
|
49
|
+
// Your storage implementation
|
|
50
|
+
return {
|
|
51
|
+
preload: () => {
|
|
52
|
+
// Load data into memory if needed
|
|
53
|
+
},
|
|
54
|
+
getItem: (key: string) => {
|
|
55
|
+
// Return value or null
|
|
56
|
+
return localStorage.getItem(`${storageKey}:${key}`);
|
|
57
|
+
},
|
|
58
|
+
setItem: (key: string, value: string) => {
|
|
59
|
+
// Store value
|
|
60
|
+
localStorage.setItem(`${storageKey}:${key}`, value);
|
|
61
|
+
},
|
|
62
|
+
removeItem: (key: string) => {
|
|
63
|
+
// Remove value
|
|
64
|
+
localStorage.removeItem(`${storageKey}:${key}`);
|
|
65
|
+
},
|
|
66
|
+
clear: () => {
|
|
67
|
+
// Clear all keys for this namespace
|
|
68
|
+
},
|
|
69
|
+
keys: () => {
|
|
70
|
+
// Return all keys
|
|
71
|
+
return Object.keys(localStorage);
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Storage Interface
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
type SupportedStorage = {
|
|
82
|
+
preload: () => void;
|
|
83
|
+
getItem: (key: string) => string | null;
|
|
84
|
+
setItem: (key: string, value: string) => void;
|
|
85
|
+
removeItem: (key: string) => void;
|
|
86
|
+
clear: () => void;
|
|
87
|
+
keys: () => string[];
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Namespacing
|
|
92
|
+
|
|
93
|
+
Storage is automatically namespaced to prevent key collisions:
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
// Internal storage keys are prefixed
|
|
97
|
+
teardown:v1:identity:IDENTIFY_STATE
|
|
98
|
+
teardown:v1:device:deviceId
|
|
99
|
+
teardown:v1:version:VERSION_STATUS
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
This prevents conflicts with:
|
|
103
|
+
- Your app's storage
|
|
104
|
+
- Other libraries
|
|
105
|
+
- Multiple Teardown instances
|
|
106
|
+
|
|
107
|
+
## How It Works
|
|
108
|
+
|
|
109
|
+
### 1. Storage Factory
|
|
110
|
+
|
|
111
|
+
The storage factory creates namespaced storage instances:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// You provide the factory
|
|
115
|
+
storageFactory: createMMKVStorageFactory()
|
|
116
|
+
|
|
117
|
+
// SDK calls it for each client
|
|
118
|
+
const identityStorage = storage.createStorage('identity');
|
|
119
|
+
const deviceStorage = storage.createStorage('device');
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 2. Client Storage
|
|
123
|
+
|
|
124
|
+
Each client gets its own namespaced storage:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
class IdentityClient {
|
|
128
|
+
constructor(storage: StorageClient) {
|
|
129
|
+
// Creates "teardown:v1:identity" namespace
|
|
130
|
+
this.storage = storage.createStorage('identity');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
saveSession(session: Session) {
|
|
134
|
+
// Actually saves to "teardown:v1:identity:IDENTIFY_STATE"
|
|
135
|
+
this.storage.setItem('IDENTIFY_STATE', JSON.stringify(session));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 3. Automatic Persistence
|
|
141
|
+
|
|
142
|
+
The SDK automatically persists critical state:
|
|
143
|
+
|
|
144
|
+
- Identity state (session data)
|
|
145
|
+
- Version status
|
|
146
|
+
- Device ID
|
|
147
|
+
|
|
148
|
+
## Internal Storage Keys
|
|
149
|
+
|
|
150
|
+
The SDK uses these storage keys internally:
|
|
151
|
+
|
|
152
|
+
| Client | Key | Data |
|
|
153
|
+
|--------|-----|------|
|
|
154
|
+
| Identity | `IDENTIFY_STATE` | User session and identity state |
|
|
155
|
+
| Device | `deviceId` | Generated device UUID |
|
|
156
|
+
| ForceUpdate | `VERSION_STATUS` | Current version status |
|
|
157
|
+
|
|
158
|
+
## Creating Storage Instances
|
|
159
|
+
|
|
160
|
+
You typically don't create storage instances directly - clients do it internally:
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
// Internal SDK code
|
|
164
|
+
class MyClient {
|
|
165
|
+
constructor(storage: StorageClient) {
|
|
166
|
+
this.storage = storage.createStorage('my-namespace');
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
If you need custom storage:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import { useTeardown } from '@teardown/react-native';
|
|
175
|
+
|
|
176
|
+
function MyComponent() {
|
|
177
|
+
const { core } = useTeardown();
|
|
178
|
+
|
|
179
|
+
// Access internal storage (not recommended)
|
|
180
|
+
// Better to use your own storage solution for app data
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Data Format
|
|
185
|
+
|
|
186
|
+
All data is stored as JSON strings:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// Stored
|
|
190
|
+
storage.setItem('key', JSON.stringify({ foo: 'bar' }));
|
|
191
|
+
|
|
192
|
+
// Retrieved
|
|
193
|
+
const data = JSON.parse(storage.getItem('key'));
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Cleanup
|
|
197
|
+
|
|
198
|
+
Storage is automatically cleaned up on SDK shutdown:
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
// Happens automatically when TeardownProvider unmounts
|
|
202
|
+
core.shutdown();
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
This clears all namespaced storage instances.
|
|
206
|
+
|
|
207
|
+
## Best Practices
|
|
208
|
+
|
|
209
|
+
### 1. Use MMKV for Production
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
// ✅ Recommended - fast and encrypted
|
|
213
|
+
storageFactory: createMMKVStorageFactory()
|
|
214
|
+
|
|
215
|
+
// ⚠️ Avoid in production - slow and unencrypted
|
|
216
|
+
storageFactory: createAsyncStorageFactory()
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### 2. Don't Access Internal Storage Directly
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
// ❌ Bad - bypasses SDK abstractions
|
|
223
|
+
MMKV.set('teardown:v1:identity:IDENTIFY_STATE', '...');
|
|
224
|
+
|
|
225
|
+
// ✅ Good - use SDK methods
|
|
226
|
+
await core.identity.identify({...});
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### 3. Use Your Own Storage for App Data
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
// ❌ Bad - mixing SDK and app data
|
|
233
|
+
core.storage.setItem('user-preferences', '...');
|
|
234
|
+
|
|
235
|
+
// ✅ Good - separate storage for app
|
|
236
|
+
import { MMKV } from 'react-native-mmkv';
|
|
237
|
+
const appStorage = new MMKV({ id: 'app-storage' });
|
|
238
|
+
appStorage.set('user-preferences', '...');
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### 4. Handle Storage Errors
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
// Storage operations can throw
|
|
245
|
+
try {
|
|
246
|
+
const value = storage.getItem('key');
|
|
247
|
+
} catch (error) {
|
|
248
|
+
console.error('Storage error:', error);
|
|
249
|
+
// Handle error (fallback, retry, etc.)
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Migrations
|
|
254
|
+
|
|
255
|
+
If you need to migrate storage data:
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
function migrateStorage() {
|
|
259
|
+
const oldKey = 'old-app:session';
|
|
260
|
+
const newKey = 'teardown:v1:identity:IDENTIFY_STATE';
|
|
261
|
+
|
|
262
|
+
const oldData = localStorage.getItem(oldKey);
|
|
263
|
+
if (oldData) {
|
|
264
|
+
// Transform data if needed
|
|
265
|
+
const newData = transformData(oldData);
|
|
266
|
+
localStorage.setItem(newKey, newData);
|
|
267
|
+
localStorage.removeItem(oldKey);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Run before initializing Teardown
|
|
272
|
+
migrateStorage();
|
|
273
|
+
const teardown = new TeardownCore({...});
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Storage Size
|
|
277
|
+
|
|
278
|
+
The SDK stores minimal data:
|
|
279
|
+
|
|
280
|
+
- Identity state: ~500 bytes
|
|
281
|
+
- Device ID: ~36 bytes (UUID)
|
|
282
|
+
- Version status: ~50 bytes
|
|
283
|
+
|
|
284
|
+
Total: Less than 1KB for all SDK data.
|
|
285
|
+
|
|
286
|
+
## Encryption
|
|
287
|
+
|
|
288
|
+
### MMKV
|
|
289
|
+
|
|
290
|
+
MMKV encrypts data by default:
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
// Already encrypted
|
|
294
|
+
storageFactory: createMMKVStorageFactory()
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Custom Encryption
|
|
298
|
+
|
|
299
|
+
For custom adapters, implement encryption:
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
import CryptoJS from 'crypto-js';
|
|
303
|
+
|
|
304
|
+
function createEncryptedStorage(encryptionKey: string) {
|
|
305
|
+
return (namespace: string) => ({
|
|
306
|
+
getItem: (key: string) => {
|
|
307
|
+
const encrypted = localStorage.getItem(`${namespace}:${key}`);
|
|
308
|
+
if (!encrypted) return null;
|
|
309
|
+
return CryptoJS.AES.decrypt(encrypted, encryptionKey).toString();
|
|
310
|
+
},
|
|
311
|
+
setItem: (key: string, value: string) => {
|
|
312
|
+
const encrypted = CryptoJS.AES.encrypt(value, encryptionKey).toString();
|
|
313
|
+
localStorage.setItem(`${namespace}:${key}`, encrypted);
|
|
314
|
+
},
|
|
315
|
+
// ... other methods
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Testing
|
|
321
|
+
|
|
322
|
+
Mock storage for testing:
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
function createMockStorageFactory() {
|
|
326
|
+
const store = new Map<string, string>();
|
|
327
|
+
|
|
328
|
+
return (namespace: string) => ({
|
|
329
|
+
preload: () => {},
|
|
330
|
+
getItem: (key: string) => store.get(`${namespace}:${key}`) ?? null,
|
|
331
|
+
setItem: (key: string, value: string) => store.set(`${namespace}:${key}`, value),
|
|
332
|
+
removeItem: (key: string) => store.delete(`${namespace}:${key}`),
|
|
333
|
+
clear: () => store.clear(),
|
|
334
|
+
keys: () => Array.from(store.keys()),
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Use in tests
|
|
339
|
+
const teardown = new TeardownCore({
|
|
340
|
+
storageFactory: createMockStorageFactory(),
|
|
341
|
+
// ...
|
|
342
|
+
});
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Next Steps
|
|
346
|
+
|
|
347
|
+
- [Logging](./06-logging.mdx)
|
|
348
|
+
- [API Reference](./07-api-reference.mdx)
|
|
349
|
+
- [Advanced Usage](./09-advanced.mdx)
|