@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.
Files changed (87) hide show
  1. package/README.md +89 -7
  2. package/docs/01-getting-started.mdx +147 -0
  3. package/docs/02-core-concepts.mdx +188 -0
  4. package/docs/03-identity.mdx +301 -0
  5. package/docs/04-force-updates.mdx +339 -0
  6. package/docs/05-device-info.mdx +324 -0
  7. package/docs/06-logging.mdx +345 -0
  8. package/docs/06-storage.mdx +349 -0
  9. package/docs/07-api-reference.mdx +472 -0
  10. package/docs/07-logging.mdx +345 -0
  11. package/docs/08-api-reference.mdx +472 -0
  12. package/docs/08-hooks-reference.mdx +476 -0
  13. package/docs/09-advanced.mdx +563 -0
  14. package/docs/09-hooks-reference.mdx +476 -0
  15. package/docs/10-advanced.mdx +563 -0
  16. package/package.json +65 -47
  17. package/src/clients/api/api.client.ts +80 -0
  18. package/src/clients/api/index.ts +1 -0
  19. package/src/clients/device/device.adpater-interface.ts +57 -0
  20. package/src/clients/device/device.client.test.ts +190 -0
  21. package/src/clients/device/device.client.ts +69 -0
  22. package/src/clients/device/expo-adapter.ts +90 -0
  23. package/src/clients/device/index.ts +4 -0
  24. package/src/clients/force-update/force-update.client.test.ts +295 -0
  25. package/src/clients/force-update/force-update.client.ts +224 -0
  26. package/src/clients/force-update/index.ts +1 -0
  27. package/src/clients/identity/identity.client.test.ts +454 -0
  28. package/src/clients/identity/identity.client.ts +255 -0
  29. package/src/clients/identity/index.ts +1 -0
  30. package/src/clients/logging/index.ts +1 -0
  31. package/src/clients/logging/logging.client.ts +92 -0
  32. package/src/clients/notifications/notifications.client.ts +10 -0
  33. package/src/clients/storage/index.ts +1 -0
  34. package/src/clients/storage/mmkv-adapter.ts +23 -0
  35. package/src/clients/storage/storage.client.ts +75 -0
  36. package/src/clients/utils/index.ts +1 -0
  37. package/src/clients/utils/utils.client.ts +75 -0
  38. package/src/components/ui/button.tsx +0 -0
  39. package/src/components/ui/input.tsx +0 -0
  40. package/src/contexts/index.ts +1 -0
  41. package/src/contexts/teardown.context.ts +17 -0
  42. package/src/exports/expo.ts +1 -0
  43. package/src/exports/index.ts +16 -0
  44. package/src/exports/mmkv.ts +1 -0
  45. package/src/hooks/use-force-update.ts +38 -0
  46. package/src/hooks/use-session.ts +26 -0
  47. package/src/providers/teardown.provider.tsx +28 -0
  48. package/src/teardown.core.ts +76 -0
  49. package/dist/components/index.d.ts +0 -1
  50. package/dist/components/index.js +0 -3
  51. package/dist/components/index.js.map +0 -1
  52. package/dist/components/teardown-logo.d.ts +0 -4
  53. package/dist/components/teardown-logo.js +0 -35
  54. package/dist/components/teardown-logo.js.map +0 -1
  55. package/dist/containers/index.d.ts +0 -1
  56. package/dist/containers/index.js +0 -18
  57. package/dist/containers/index.js.map +0 -1
  58. package/dist/containers/teardown.container.d.ts +0 -8
  59. package/dist/containers/teardown.container.js +0 -26
  60. package/dist/containers/teardown.container.js.map +0 -1
  61. package/dist/index.d.ts +0 -2
  62. package/dist/index.js +0 -22
  63. package/dist/index.js.map +0 -1
  64. package/dist/plugins/http.plugin.d.ts +0 -23
  65. package/dist/plugins/http.plugin.js +0 -145
  66. package/dist/plugins/http.plugin.js.map +0 -1
  67. package/dist/plugins/index.d.ts +0 -2
  68. package/dist/plugins/index.js +0 -20
  69. package/dist/plugins/index.js.map +0 -1
  70. package/dist/plugins/logging.plugin.d.ts +0 -9
  71. package/dist/plugins/logging.plugin.js +0 -36
  72. package/dist/plugins/logging.plugin.js.map +0 -1
  73. package/dist/plugins/websocket.plugin.d.ts +0 -1
  74. package/dist/plugins/websocket.plugin.js +0 -108
  75. package/dist/plugins/websocket.plugin.js.map +0 -1
  76. package/dist/services/index.d.ts +0 -1
  77. package/dist/services/index.js +0 -18
  78. package/dist/services/index.js.map +0 -1
  79. package/dist/services/teardown.service.d.ts +0 -10
  80. package/dist/services/teardown.service.js +0 -22
  81. package/dist/services/teardown.service.js.map +0 -1
  82. package/dist/teardown.client.d.ts +0 -41
  83. package/dist/teardown.client.js +0 -60
  84. package/dist/teardown.client.js.map +0 -1
  85. package/dist/utils/log.d.ts +0 -5
  86. package/dist/utils/log.js +0 -9
  87. package/dist/utils/log.js.map +0 -1
@@ -0,0 +1,476 @@
1
+ # Hooks Reference
2
+
3
+ React hooks for accessing Teardown SDK functionality.
4
+
5
+ ## useTeardown
6
+
7
+ Access the TeardownCore instance.
8
+
9
+ ### Usage
10
+
11
+ ```typescript
12
+ import { useTeardown } from '@teardown/react-native';
13
+
14
+ function MyComponent() {
15
+ const { core } = useTeardown();
16
+
17
+ return <Button onPress={() => core.identity.reset()} />;
18
+ }
19
+ ```
20
+
21
+ ### Return Value
22
+
23
+ ```typescript
24
+ type UseTeardownResult = {
25
+ core: TeardownCore;
26
+ }
27
+ ```
28
+
29
+ ### When to Use
30
+
31
+ - Accessing clients directly
32
+ - Calling SDK methods
33
+ - Setting configuration
34
+
35
+ ### Example: Manual Identification
36
+
37
+ ```typescript
38
+ function LoginButton() {
39
+ const { core } = useTeardown();
40
+
41
+ const handleLogin = async () => {
42
+ const result = await core.identity.identify({
43
+ user_id: 'user-123',
44
+ email: 'user@example.com',
45
+ });
46
+
47
+ if (result.success) {
48
+ console.log('Logged in:', result.data.session_id);
49
+ }
50
+ };
51
+
52
+ return <Button onPress={handleLogin} title="Login" />;
53
+ }
54
+ ```
55
+
56
+ ### Example: Enable Debug Logging
57
+
58
+ ```typescript
59
+ function DebugToggle() {
60
+ const { core } = useTeardown();
61
+ const [enabled, setEnabled] = useState(false);
62
+
63
+ const toggle = () => {
64
+ const newValue = !enabled;
65
+ setEnabled(newValue);
66
+ core.setLogLevel(newValue ? 'verbose' : 'none');
67
+ };
68
+
69
+ return <Switch value={enabled} onValueChange={toggle} />;
70
+ }
71
+ ```
72
+
73
+ ---
74
+
75
+ ## useSession
76
+
77
+ Get current user session with automatic updates.
78
+
79
+ ### Usage
80
+
81
+ ```typescript
82
+ import { useSession } from '@teardown/react-native';
83
+
84
+ function UserProfile() {
85
+ const session = useSession();
86
+
87
+ if (!session) {
88
+ return <LoginPrompt />;
89
+ }
90
+
91
+ return <Text>Session: {session.session_id}</Text>;
92
+ }
93
+ ```
94
+
95
+ ### Return Value
96
+
97
+ ```typescript
98
+ type UseSessionResult = Session | null
99
+
100
+ type Session = {
101
+ session_id: string;
102
+ device_id: string;
103
+ persona_id: string;
104
+ token: string;
105
+ }
106
+ ```
107
+
108
+ Returns `null` when:
109
+ - User is not identified
110
+ - Identity state is "unidentified" or "identifying"
111
+
112
+ Returns `Session` when:
113
+ - Identity state is "identified"
114
+
115
+ ### Reactivity
116
+
117
+ The hook automatically re-renders when:
118
+ - User is identified
119
+ - User is logged out
120
+ - Session is refreshed
121
+
122
+ ### Example: Conditional Rendering
123
+
124
+ ```typescript
125
+ function App() {
126
+ const session = useSession();
127
+
128
+ if (!session) {
129
+ return <LoginScreen />;
130
+ }
131
+
132
+ return <MainApp session={session} />;
133
+ }
134
+ ```
135
+
136
+ ### Example: Display Session Info
137
+
138
+ ```typescript
139
+ function SessionInfo() {
140
+ const session = useSession();
141
+
142
+ return (
143
+ <View>
144
+ <Text>Session ID: {session?.session_id ?? 'Not logged in'}</Text>
145
+ <Text>Device ID: {session?.device_id ?? 'Unknown'}</Text>
146
+ <Text>Persona ID: {session?.persona_id ?? 'Anonymous'}</Text>
147
+ </View>
148
+ );
149
+ }
150
+ ```
151
+
152
+ ### Example: Protected Route
153
+
154
+ ```typescript
155
+ function ProtectedScreen() {
156
+ const session = useSession();
157
+ const navigation = useNavigation();
158
+
159
+ useEffect(() => {
160
+ if (!session) {
161
+ navigation.navigate('Login');
162
+ }
163
+ }, [session]);
164
+
165
+ if (!session) {
166
+ return <ActivityIndicator />;
167
+ }
168
+
169
+ return <SecureContent />;
170
+ }
171
+ ```
172
+
173
+ ---
174
+
175
+ ## useForceUpdate
176
+
177
+ Get version update status with automatic updates.
178
+
179
+ ### Usage
180
+
181
+ ```typescript
182
+ import { useForceUpdate } from '@teardown/react-native';
183
+
184
+ function UpdateBanner() {
185
+ const { versionStatus, isUpdateRequired, isUpdateAvailable } = useForceUpdate();
186
+
187
+ if (isUpdateRequired) {
188
+ return <UpdateRequiredScreen />;
189
+ }
190
+
191
+ return null;
192
+ }
193
+ ```
194
+
195
+ ### Return Value
196
+
197
+ ```typescript
198
+ type UseForceUpdateResult = {
199
+ versionStatus: VersionStatus;
200
+ isUpdateAvailable: boolean;
201
+ isUpdateRequired: boolean;
202
+ }
203
+
204
+ type VersionStatus =
205
+ | { type: "initializing" }
206
+ | { type: "checking" }
207
+ | { type: "up_to_date" }
208
+ | { type: "update_available" }
209
+ | { type: "update_recommended" }
210
+ | { type: "update_required" }
211
+ | { type: "disabled" }
212
+ ```
213
+
214
+ ### Fields
215
+
216
+ #### `versionStatus`
217
+
218
+ Current version status object with discriminated union type.
219
+
220
+ #### `isUpdateAvailable`
221
+
222
+ Boolean indicating if any update exists (available, recommended, or required).
223
+
224
+ ```typescript
225
+ isUpdateAvailable =
226
+ versionStatus.type === "update_available" ||
227
+ versionStatus.type === "update_recommended" ||
228
+ versionStatus.type === "update_required"
229
+ ```
230
+
231
+ #### `isUpdateRequired`
232
+
233
+ Boolean indicating if update is mandatory.
234
+
235
+ ```typescript
236
+ isUpdateRequired = versionStatus.type === "update_required"
237
+ ```
238
+
239
+ ### Reactivity
240
+
241
+ The hook automatically re-renders when:
242
+ - Version status changes
243
+ - App returns to foreground
244
+ - User is identified/re-identified
245
+
246
+ ### Example: Update Required Modal
247
+
248
+ ```typescript
249
+ function UpdateRequiredModal() {
250
+ const { isUpdateRequired } = useForceUpdate();
251
+
252
+ if (!isUpdateRequired) return null;
253
+
254
+ return (
255
+ <Modal visible={true} animationType="slide">
256
+ <View style={styles.container}>
257
+ <Text>Update Required</Text>
258
+ <Text>Please update to continue</Text>
259
+ <Button
260
+ title="Update Now"
261
+ onPress={() => Linking.openURL(STORE_URL)}
262
+ />
263
+ </View>
264
+ </Modal>
265
+ );
266
+ }
267
+ ```
268
+
269
+ ### Example: Optional Update Banner
270
+
271
+ ```typescript
272
+ function UpdateBanner() {
273
+ const { isUpdateAvailable, isUpdateRequired } = useForceUpdate();
274
+ const [dismissed, setDismissed] = useState(false);
275
+
276
+ // Don't show if required (use modal instead) or dismissed
277
+ if (isUpdateRequired || !isUpdateAvailable || dismissed) {
278
+ return null;
279
+ }
280
+
281
+ return (
282
+ <View style={styles.banner}>
283
+ <Text>New version available</Text>
284
+ <Button title="Update" onPress={() => Linking.openURL(STORE_URL)} />
285
+ <Button title="Later" onPress={() => setDismissed(true)} />
286
+ </View>
287
+ );
288
+ }
289
+ ```
290
+
291
+ ### Example: Status-Based UI
292
+
293
+ ```typescript
294
+ function VersionStatusIndicator() {
295
+ const { versionStatus } = useForceUpdate();
296
+
297
+ switch (versionStatus.type) {
298
+ case 'checking':
299
+ return <ActivityIndicator />;
300
+ case 'update_required':
301
+ return <Badge color="red">Update Required</Badge>;
302
+ case 'update_recommended':
303
+ return <Badge color="orange">Update Recommended</Badge>;
304
+ case 'update_available':
305
+ return <Badge color="blue">Update Available</Badge>;
306
+ case 'up_to_date':
307
+ return <Badge color="green">Up to Date</Badge>;
308
+ default:
309
+ return null;
310
+ }
311
+ }
312
+ ```
313
+
314
+ ### Example: Full Screen Takeover
315
+
316
+ ```typescript
317
+ function FullscreenTakeover() {
318
+ const { isUpdateRequired } = useForceUpdate();
319
+
320
+ if (!isUpdateRequired) return null;
321
+
322
+ return (
323
+ <Modal
324
+ visible={true}
325
+ animationType="fade"
326
+ presentationStyle="overFullScreen"
327
+ >
328
+ <SafeAreaView style={styles.container}>
329
+ <Image source={appIcon} />
330
+ <Text style={styles.title}>Update Required</Text>
331
+ <Text style={styles.body}>
332
+ A new version of the app is required to continue.
333
+ </Text>
334
+ <Button
335
+ title="Update Now"
336
+ onPress={() => Linking.openURL(STORE_URL)}
337
+ />
338
+ </SafeAreaView>
339
+ </Modal>
340
+ );
341
+ }
342
+
343
+ // In root layout
344
+ <TeardownProvider core={teardown}>
345
+ <App />
346
+ <FullscreenTakeover />
347
+ </TeardownProvider>
348
+ ```
349
+
350
+ ---
351
+
352
+ ## Hook Patterns
353
+
354
+ ### Combining Hooks
355
+
356
+ ```typescript
357
+ function AppShell() {
358
+ const session = useSession();
359
+ const { isUpdateRequired } = useForceUpdate();
360
+
361
+ if (isUpdateRequired) {
362
+ return <UpdateRequiredScreen />;
363
+ }
364
+
365
+ if (!session) {
366
+ return <LoginScreen />;
367
+ }
368
+
369
+ return <MainApp />;
370
+ }
371
+ ```
372
+
373
+ ### Custom Hooks
374
+
375
+ ```typescript
376
+ function useIsAuthenticated(): boolean {
377
+ const session = useSession();
378
+ return session !== null;
379
+ }
380
+
381
+ function useRequireAuth() {
382
+ const session = useSession();
383
+ const navigation = useNavigation();
384
+
385
+ useEffect(() => {
386
+ if (!session) {
387
+ navigation.navigate('Login');
388
+ }
389
+ }, [session, navigation]);
390
+
391
+ return session;
392
+ }
393
+ ```
394
+
395
+ ### Memoization
396
+
397
+ ```typescript
398
+ function UserDashboard() {
399
+ const session = useSession();
400
+
401
+ const personaId = useMemo(() => {
402
+ return session?.persona_id ?? 'anonymous';
403
+ }, [session]);
404
+
405
+ return <Dashboard personaId={personaId} />;
406
+ }
407
+ ```
408
+
409
+ ---
410
+
411
+ ## Best Practices
412
+
413
+ ### 1. Use Hooks for Reactive UI
414
+
415
+ ```typescript
416
+ // ✅ Good - automatic updates
417
+ const session = useSession();
418
+
419
+ // ❌ Bad - manual subscription
420
+ const [session, setSession] = useState(null);
421
+ useEffect(() => {
422
+ const unsubscribe = core.identity.onIdentifyStateChange(/* ... */);
423
+ return unsubscribe;
424
+ }, []);
425
+ ```
426
+
427
+ ### 2. Handle Null States
428
+
429
+ ```typescript
430
+ // ✅ Good - null check
431
+ const session = useSession();
432
+ if (!session) return <LoginPrompt />;
433
+
434
+ // ❌ Bad - assumes session exists
435
+ const session = useSession();
436
+ return <Text>{session.session_id}</Text>; // Can crash!
437
+ ```
438
+
439
+ ### 3. Combine Conditions Properly
440
+
441
+ ```typescript
442
+ // ✅ Good - correct priority
443
+ if (isUpdateRequired) return <UpdateModal />;
444
+ if (!session) return <LoginScreen />;
445
+ return <App />;
446
+
447
+ // ❌ Bad - wrong priority
448
+ if (!session) return <LoginScreen />;
449
+ if (isUpdateRequired) return <UpdateModal />; // Never shown!
450
+ ```
451
+
452
+ ### 4. Don't Call Hooks Conditionally
453
+
454
+ ```typescript
455
+ // ✅ Good - hooks at top level
456
+ function MyComponent() {
457
+ const session = useSession();
458
+
459
+ if (!session) return null;
460
+ return <Content />;
461
+ }
462
+
463
+ // ❌ Bad - conditional hook
464
+ function MyComponent() {
465
+ if (someCondition) {
466
+ const session = useSession(); // Error!
467
+ }
468
+ }
469
+ ```
470
+
471
+ ---
472
+
473
+ ## Next Steps
474
+
475
+ - [Advanced Usage](./09-advanced.mdx)
476
+ - [API Reference](./07-api-reference.mdx)