@teardown/react-native 2.0.23 → 2.0.27

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 (61) hide show
  1. package/docs/adapters/device/basic.mdx +59 -0
  2. package/docs/adapters/device/device-info.mdx +76 -0
  3. package/docs/adapters/device/expo.mdx +61 -0
  4. package/docs/adapters/device/index.mdx +102 -0
  5. package/docs/adapters/device/meta.json +4 -0
  6. package/docs/adapters/index.mdx +96 -0
  7. package/docs/adapters/meta.json +4 -0
  8. package/docs/adapters/notifications/expo.mdx +127 -0
  9. package/docs/adapters/notifications/firebase.mdx +142 -0
  10. package/docs/adapters/notifications/index.mdx +100 -0
  11. package/docs/adapters/notifications/meta.json +4 -0
  12. package/docs/adapters/notifications/wix.mdx +140 -0
  13. package/docs/adapters/storage/async-storage.mdx +95 -0
  14. package/docs/adapters/storage/index.mdx +93 -0
  15. package/docs/adapters/storage/meta.json +4 -0
  16. package/docs/adapters/storage/mmkv.mdx +86 -0
  17. package/docs/advanced.mdx +280 -0
  18. package/docs/api-reference.mdx +241 -0
  19. package/docs/core-concepts.mdx +158 -0
  20. package/docs/force-updates.mdx +185 -0
  21. package/docs/getting-started.mdx +156 -0
  22. package/docs/hooks-reference.mdx +232 -0
  23. package/docs/identity.mdx +171 -0
  24. package/docs/index.mdx +61 -0
  25. package/docs/logging.mdx +144 -0
  26. package/docs/meta.json +14 -0
  27. package/package.json +49 -31
  28. package/src/clients/api/index.ts +1 -1
  29. package/src/clients/device/adapters/basic.adapter.ts +57 -66
  30. package/src/clients/device/adapters/device-info.adapter.ts +21 -28
  31. package/src/clients/device/adapters/device.adpater-interface.ts +1 -8
  32. package/src/clients/device/adapters/expo.adapter.ts +33 -40
  33. package/src/clients/device/device.client.test.ts +20 -35
  34. package/src/clients/device/device.client.ts +0 -3
  35. package/src/clients/force-update/force-update.client.test.ts +69 -23
  36. package/src/clients/force-update/force-update.client.ts +42 -59
  37. package/src/clients/identity/identity.client.test.ts +22 -14
  38. package/src/clients/identity/identity.client.ts +1 -1
  39. package/src/clients/identity/index.ts +1 -1
  40. package/src/clients/logging/index.ts +1 -1
  41. package/src/clients/notifications/adapters/expo-notifications.adapter.ts +105 -0
  42. package/src/clients/notifications/adapters/firebase-messaging.adapter.ts +87 -0
  43. package/src/clients/notifications/adapters/notifications.adapter-interface.ts +112 -0
  44. package/src/clients/notifications/adapters/wix-notifications.adapter.ts +183 -0
  45. package/src/clients/notifications/index.ts +2 -0
  46. package/src/clients/notifications/notifications.client.ts +214 -3
  47. package/src/clients/storage/adapters/async-storage.adapter.ts +2 -6
  48. package/src/clients/storage/adapters/storage-adapters.test.ts +2 -7
  49. package/src/clients/storage/adapters/storage.adpater-interface.ts +1 -5
  50. package/src/clients/utils/index.ts +1 -1
  51. package/src/clients/utils/utils.client.ts +1 -1
  52. package/src/exports/adapters/async-storage.ts +1 -1
  53. package/src/exports/adapters/expo.ts +1 -1
  54. package/src/exports/expo.ts +2 -0
  55. package/src/exports/firebase.ts +1 -0
  56. package/src/exports/index.ts +6 -9
  57. package/src/exports/wix.ts +1 -0
  58. package/src/hooks/use-force-update.ts +31 -34
  59. package/src/index.ts +1 -0
  60. package/src/teardown.core.ts +0 -2
  61. package/src/.DS_Store +0 -0
@@ -0,0 +1,280 @@
1
+ ---
2
+ title: Advanced Usage
3
+ description: Advanced patterns and configurations for the Teardown SDK.
4
+ icon: Wrench
5
+ ---
6
+
7
+ ## Multiple Environments
8
+
9
+ Configure different credentials per environment:
10
+
11
+ ```typescript
12
+ const getConfig = () => {
13
+ if (__DEV__) {
14
+ return {
15
+ org_id: 'dev-org-id',
16
+ project_id: 'dev-project-id',
17
+ api_key: 'dev-api-key',
18
+ };
19
+ }
20
+ return {
21
+ org_id: 'prod-org-id',
22
+ project_id: 'prod-project-id',
23
+ api_key: 'prod-api-key',
24
+ };
25
+ };
26
+
27
+ export const teardown = new TeardownCore({
28
+ ...getConfig(),
29
+ storageAdapter: new MMKVStorageAdapter(),
30
+ deviceAdapter: new ExpoDeviceAdapter(),
31
+ });
32
+ ```
33
+
34
+ ## Disable Force Update Checking
35
+
36
+ For debugging or testing:
37
+
38
+ ```typescript
39
+ const teardown = new TeardownCore({
40
+ // ...
41
+ forceUpdate: {
42
+ checkIntervalMs: -1, // Disable automatic checking
43
+ },
44
+ });
45
+ ```
46
+
47
+ ## Custom Version Check Interval
48
+
49
+ Check more or less frequently:
50
+
51
+ ```typescript
52
+ const teardown = new TeardownCore({
53
+ // ...
54
+ forceUpdate: {
55
+ checkIntervalMs: 60_000, // Check every minute
56
+ checkOnForeground: true,
57
+ },
58
+ });
59
+ ```
60
+
61
+ ## Manual Version Checking
62
+
63
+ Trigger version check programmatically:
64
+
65
+ ```typescript
66
+ const { core } = useTeardown();
67
+
68
+ const checkForUpdates = async () => {
69
+ const result = await core.identity.refresh();
70
+ if (result.success) {
71
+ // Version status will update via subscription
72
+ console.log('Version checked');
73
+ }
74
+ };
75
+ ```
76
+
77
+ ## Offline Support
78
+
79
+ The SDK handles offline scenarios gracefully:
80
+
81
+ 1. **Cached session** - Identity state persists across restarts
82
+ 2. **Cached version status** - Last known status is preserved
83
+ 3. **Retry on foreground** - Re-checks when connectivity restored
84
+
85
+ ```typescript
86
+ const session = useSession();
87
+
88
+ // Works offline - returns cached session
89
+ if (session) {
90
+ console.log('User:', session.user_id);
91
+ }
92
+ ```
93
+
94
+ ## Pre-warming
95
+
96
+ Initialize SDK before app is fully loaded:
97
+
98
+ ```typescript
99
+ // In app entry point (before React renders)
100
+ import { teardown } from './lib/teardown';
101
+
102
+ // SDK starts initializing immediately
103
+ // By the time UI renders, it may already be ready
104
+ ```
105
+
106
+ ## Error Boundaries
107
+
108
+ Handle SDK errors gracefully:
109
+
110
+ ```tsx
111
+ import { ErrorBoundary } from 'react-error-boundary';
112
+
113
+ function App() {
114
+ return (
115
+ <ErrorBoundary fallback={<ErrorScreen />}>
116
+ <TeardownProvider core={teardown}>
117
+ <MainApp />
118
+ </TeardownProvider>
119
+ </ErrorBoundary>
120
+ );
121
+ }
122
+ ```
123
+
124
+ ## Testing
125
+
126
+ ### Mock the SDK
127
+
128
+ ```typescript
129
+ // __mocks__/@teardown/react-native.ts
130
+ export const TeardownProvider = ({ children }) => children;
131
+
132
+ export const useTeardown = () => ({
133
+ core: {
134
+ identity: {
135
+ identify: jest.fn().mockResolvedValue({ success: true, data: mockSession }),
136
+ reset: jest.fn(),
137
+ getSessionState: () => mockSession,
138
+ },
139
+ forceUpdate: {
140
+ getVersionStatus: () => ({ type: 'up_to_date' }),
141
+ },
142
+ },
143
+ });
144
+
145
+ export const useSession = () => mockSession;
146
+ export const useForceUpdate = () => ({
147
+ versionStatus: { type: 'up_to_date' },
148
+ isUpdateRequired: false,
149
+ isUpdateRecommended: false,
150
+ isUpdateAvailable: false,
151
+ });
152
+ ```
153
+
154
+ ### Test Components
155
+
156
+ ```typescript
157
+ import { render } from '@testing-library/react-native';
158
+
159
+ test('shows login when not identified', () => {
160
+ jest.spyOn(hooks, 'useSession').mockReturnValue(null);
161
+
162
+ const { getByText } = render(<App />);
163
+ expect(getByText('Login')).toBeTruthy();
164
+ });
165
+ ```
166
+
167
+ ## Debugging
168
+
169
+ ### Enable Verbose Logging
170
+
171
+ ```typescript
172
+ teardown.setLogLevel('verbose');
173
+ ```
174
+
175
+ ### Inspect State
176
+
177
+ ```typescript
178
+ const { core } = useTeardown();
179
+
180
+ console.log('Identity state:', core.identity.getIdentifyState());
181
+ console.log('Version status:', core.forceUpdate.getVersionStatus());
182
+ console.log('Device ID:', await core.device.getDeviceId());
183
+ ```
184
+
185
+ ### Clear All Data
186
+
187
+ For debugging or logout:
188
+
189
+ ```typescript
190
+ core.identity.reset();
191
+ // This clears session data and device association
192
+ ```
193
+
194
+ ## Performance
195
+
196
+ ### Minimize Re-renders
197
+
198
+ Use specific hooks instead of broad subscriptions:
199
+
200
+ ```tsx
201
+ // Good - only re-renders on session change
202
+ const session = useSession();
203
+
204
+ // Avoid - accessing core gives no reactivity
205
+ const { core } = useTeardown();
206
+ const session = core.identity.getSessionState(); // Not reactive!
207
+ ```
208
+
209
+ ### Lazy Initialization
210
+
211
+ Defer SDK init until needed:
212
+
213
+ ```typescript
214
+ let teardownInstance: TeardownCore | null = null;
215
+
216
+ export const getTeardown = () => {
217
+ if (!teardownInstance) {
218
+ teardownInstance = new TeardownCore({ /* ... */ });
219
+ }
220
+ return teardownInstance;
221
+ };
222
+ ```
223
+
224
+ ## Cleanup
225
+
226
+ Properly cleanup on app shutdown:
227
+
228
+ ```typescript
229
+ import { AppState } from 'react-native';
230
+
231
+ useEffect(() => {
232
+ const subscription = AppState.addEventListener('change', (state) => {
233
+ if (state === 'background') {
234
+ // SDK persists state automatically, no action needed
235
+ }
236
+ });
237
+
238
+ return () => {
239
+ subscription.remove();
240
+ teardown.shutdown();
241
+ };
242
+ }, []);
243
+ ```
244
+
245
+ ## TypeScript
246
+
247
+ ### Strict Types
248
+
249
+ All SDK types are exported:
250
+
251
+ ```typescript
252
+ import type {
253
+ TeardownCore,
254
+ TeardownCoreOptions,
255
+ Session,
256
+ IdentifyState,
257
+ VersionStatus,
258
+ Persona,
259
+ AsyncResult,
260
+ } from '@teardown/react-native';
261
+ ```
262
+
263
+ ### Type Guards
264
+
265
+ ```typescript
266
+ function handleIdentifyState(state: IdentifyState) {
267
+ switch (state.type) {
268
+ case 'unidentified':
269
+ // state is UnidentifiedSessionState
270
+ break;
271
+ case 'identifying':
272
+ // state is IdentifyingSessionState
273
+ break;
274
+ case 'identified':
275
+ // state is IdentifiedSessionState
276
+ console.log(state.session.user_id);
277
+ break;
278
+ }
279
+ }
280
+ ```
@@ -0,0 +1,241 @@
1
+ ---
2
+ title: API Reference
3
+ description: Complete API reference for the Teardown React Native SDK.
4
+ icon: Code
5
+ ---
6
+
7
+ ## TeardownCore
8
+
9
+ The main SDK class that orchestrates all clients.
10
+
11
+ ### Constructor
12
+
13
+ ```typescript
14
+ new TeardownCore(options: TeardownCoreOptions)
15
+ ```
16
+
17
+ ### TeardownCoreOptions
18
+
19
+ | Property | Type | Required | Description |
20
+ |----------|------|----------|-------------|
21
+ | `org_id` | `string` | Yes | Organization ID from dashboard |
22
+ | `project_id` | `string` | Yes | Project ID from dashboard |
23
+ | `api_key` | `string` | Yes | API key from dashboard |
24
+ | `storageAdapter` | `StorageAdapter` | Yes | Storage adapter instance |
25
+ | `deviceAdapter` | `DeviceInfoAdapter` | Yes | Device info adapter instance |
26
+ | `forceUpdate` | `ForceUpdateClientOptions` | No | Force update configuration |
27
+
28
+ ### Methods
29
+
30
+ | Method | Returns | Description |
31
+ |--------|---------|-------------|
32
+ | `setLogLevel(level)` | `void` | Set logging verbosity |
33
+ | `shutdown()` | `void` | Cleanup SDK resources |
34
+
35
+ ### Properties
36
+
37
+ | Property | Type | Description |
38
+ |----------|------|-------------|
39
+ | `api` | `ApiClient` | Backend API client |
40
+ | `device` | `DeviceClient` | Device information client |
41
+ | `identity` | `IdentityClient` | Identity management client |
42
+ | `forceUpdate` | `ForceUpdateClient` | Version checking client |
43
+
44
+ ---
45
+
46
+ ## IdentityClient
47
+
48
+ Manages user and device identification.
49
+
50
+ ### Methods
51
+
52
+ | Method | Returns | Description |
53
+ |--------|---------|-------------|
54
+ | `identify(persona?)` | `AsyncResult<IdentityUser>` | Identify user/device |
55
+ | `refresh()` | `AsyncResult<IdentityUser>` | Re-identify current user |
56
+ | `reset()` | `void` | Clear session data |
57
+ | `getIdentifyState()` | `IdentifyState` | Get current state |
58
+ | `getSessionState()` | `Session \| null` | Get current session |
59
+ | `onIdentifyStateChange(listener)` | `() => void` | Subscribe to state changes |
60
+ | `shutdown()` | `void` | Cleanup listeners |
61
+
62
+ ### Persona
63
+
64
+ ```typescript
65
+ interface Persona {
66
+ user_id?: string;
67
+ email?: string;
68
+ name?: string;
69
+ }
70
+ ```
71
+
72
+ ### Session
73
+
74
+ ```typescript
75
+ interface Session {
76
+ session_id: string;
77
+ device_id: string;
78
+ user_id: string;
79
+ token: string;
80
+ }
81
+ ```
82
+
83
+ ### IdentifyState
84
+
85
+ ```typescript
86
+ type IdentifyState =
87
+ | { type: 'unidentified' }
88
+ | { type: 'identifying' }
89
+ | { type: 'identified'; session: Session; version_info: VersionInfo };
90
+ ```
91
+
92
+ ---
93
+
94
+ ## ForceUpdateClient
95
+
96
+ Manages version checking and force updates.
97
+
98
+ ### Methods
99
+
100
+ | Method | Returns | Description |
101
+ |--------|---------|-------------|
102
+ | `getVersionStatus()` | `VersionStatus` | Get current version status |
103
+ | `onVersionStatusChange(listener)` | `() => void` | Subscribe to status changes |
104
+ | `shutdown()` | `void` | Cleanup listeners |
105
+
106
+ ### ForceUpdateClientOptions
107
+
108
+ | Property | Type | Default | Description |
109
+ |----------|------|---------|-------------|
110
+ | `checkIntervalMs` | `number` | `300000` | Min time between checks. `0` = every foreground, `-1` = disabled |
111
+ | `checkOnForeground` | `boolean` | `true` | Check when app foregrounds |
112
+ | `identifyAnonymousDevice` | `boolean` | `false` | Check when not identified |
113
+
114
+ ### VersionStatus
115
+
116
+ ```typescript
117
+ type VersionStatus =
118
+ | { type: 'initializing' }
119
+ | { type: 'checking' }
120
+ | { type: 'up_to_date' }
121
+ | { type: 'update_available' }
122
+ | { type: 'update_recommended' }
123
+ | { type: 'update_required' }
124
+ | { type: 'disabled' };
125
+ ```
126
+
127
+ ---
128
+
129
+ ## DeviceClient
130
+
131
+ Collects device information.
132
+
133
+ ### Methods
134
+
135
+ | Method | Returns | Description |
136
+ |--------|---------|-------------|
137
+ | `getDeviceId()` | `Promise<string>` | Get stable device UUID |
138
+ | `getDeviceInfo()` | `Promise<DeviceInfo>` | Get full device info |
139
+
140
+ ### DeviceInfo
141
+
142
+ ```typescript
143
+ interface DeviceInfo {
144
+ timestamp: string;
145
+ os: OSInfo;
146
+ hardware: HardwareInfo;
147
+ application: ApplicationInfo;
148
+ }
149
+ ```
150
+
151
+ ---
152
+
153
+ ## StorageAdapter
154
+
155
+ Abstract class for storage implementations.
156
+
157
+ ### Methods
158
+
159
+ | Method | Returns | Description |
160
+ |--------|---------|-------------|
161
+ | `createStorage(key)` | `SupportedStorage` | Create namespaced storage |
162
+
163
+ ### SupportedStorage
164
+
165
+ ```typescript
166
+ interface SupportedStorage {
167
+ preload(): void;
168
+ getItem(key: string): string | null;
169
+ setItem(key: string, value: string): void;
170
+ removeItem(key: string): void;
171
+ clear(): void;
172
+ keys(): string[];
173
+ }
174
+ ```
175
+
176
+ ---
177
+
178
+ ## DeviceInfoAdapter
179
+
180
+ Interface for device information adapters.
181
+
182
+ ### Properties
183
+
184
+ | Property | Type | Description |
185
+ |----------|------|-------------|
186
+ | `applicationInfo` | `ApplicationInfo` | App version info |
187
+ | `hardwareInfo` | `HardwareInfo` | Device hardware info |
188
+ | `osInfo` | `OSInfo` | Operating system info |
189
+
190
+ ### ApplicationInfo
191
+
192
+ ```typescript
193
+ interface ApplicationInfo {
194
+ version: string;
195
+ buildNumber: string;
196
+ bundleId: string;
197
+ }
198
+ ```
199
+
200
+ ### HardwareInfo
201
+
202
+ ```typescript
203
+ interface HardwareInfo {
204
+ deviceName: string;
205
+ brand: string;
206
+ deviceType: string;
207
+ }
208
+ ```
209
+
210
+ ### OSInfo
211
+
212
+ ```typescript
213
+ interface OSInfo {
214
+ osName: string;
215
+ osVersion: string;
216
+ }
217
+ ```
218
+
219
+ ---
220
+
221
+ ## AsyncResult
222
+
223
+ Type-safe result type for async operations.
224
+
225
+ ```typescript
226
+ type AsyncResult<T> =
227
+ | { success: true; data: T }
228
+ | { success: false; error: string };
229
+ ```
230
+
231
+ ### Usage
232
+
233
+ ```typescript
234
+ const result = await core.identity.identify({ user_id: '123' });
235
+
236
+ if (result.success) {
237
+ console.log(result.data.session_id);
238
+ } else {
239
+ console.error(result.error);
240
+ }
241
+ ```
@@ -0,0 +1,158 @@
1
+ ---
2
+ title: Core Concepts
3
+ description: Understand the architecture and design principles of the Teardown React Native SDK.
4
+ icon: Lightbulb
5
+ ---
6
+
7
+ ## Architecture Overview
8
+
9
+ The Teardown SDK is built around a central `TeardownCore` class that orchestrates multiple specialized clients:
10
+
11
+ ```
12
+ TeardownCore
13
+ ├── IdentityClient # User/device identification
14
+ ├── ForceUpdateClient # Version checking
15
+ ├── DeviceClient # Device information
16
+ ├── StorageClient # Persistent storage
17
+ ├── ApiClient # Backend communication
18
+ └── LoggingClient # Structured logging
19
+ ```
20
+
21
+ ## Initialization Flow
22
+
23
+ When you create a `TeardownCore` instance, the following happens:
24
+
25
+ 1. **Storage Hydration** - Storage adapters load persisted state
26
+ 2. **Identity Initialization** - Loads cached session, then identifies with backend
27
+ 3. **Force Update Setup** - Subscribes to identity events for version checking
28
+ 4. **Ready State** - SDK is fully operational
29
+
30
+ ```typescript
31
+ const teardown = new TeardownCore({
32
+ org_id: 'your-org-id',
33
+ project_id: 'your-project-id',
34
+ api_key: 'your-api-key',
35
+ storageAdapter: new MMKVStorageAdapter(),
36
+ deviceAdapter: new ExpoDeviceAdapter(),
37
+ });
38
+ // Initialization happens automatically in the background
39
+ ```
40
+
41
+ ## State Management
42
+
43
+ The SDK uses an event-driven architecture with discriminated unions for type-safe state:
44
+
45
+ ### Identity State
46
+
47
+ ```typescript
48
+ type IdentifyState =
49
+ | { type: 'unidentified' }
50
+ | { type: 'identifying' }
51
+ | { type: 'identified'; session: Session; version_info: VersionInfo };
52
+ ```
53
+
54
+ ### Version Status
55
+
56
+ ```typescript
57
+ type VersionStatus =
58
+ | { type: 'initializing' }
59
+ | { type: 'checking' }
60
+ | { type: 'up_to_date' }
61
+ | { type: 'update_available' }
62
+ | { type: 'update_recommended' }
63
+ | { type: 'update_required' }
64
+ | { type: 'disabled' };
65
+ ```
66
+
67
+ ## Adapter Pattern
68
+
69
+ The SDK uses adapters to abstract platform-specific functionality:
70
+
71
+ ### Storage Adapters
72
+
73
+ Handle persistent data storage with a consistent interface:
74
+
75
+ ```typescript
76
+ interface SupportedStorage {
77
+ preload(): void;
78
+ getItem(key: string): string | null;
79
+ setItem(key: string, value: string): void;
80
+ removeItem(key: string): void;
81
+ clear(): void;
82
+ keys(): string[];
83
+ }
84
+ ```
85
+
86
+ ### Device Adapters
87
+
88
+ Provide device and app information:
89
+
90
+ ```typescript
91
+ interface DeviceInfoAdapter {
92
+ applicationInfo: ApplicationInfo; // version, buildNumber, bundleId
93
+ hardwareInfo: HardwareInfo; // deviceName, brand, deviceType
94
+ osInfo: OSInfo; // osName, osVersion
95
+ }
96
+ ```
97
+
98
+ ## React Integration
99
+
100
+ The SDK provides React primitives for seamless integration:
101
+
102
+ ### TeardownProvider
103
+
104
+ Context provider that makes the SDK available throughout your app:
105
+
106
+ ```tsx
107
+ <TeardownProvider core={teardown}>
108
+ <App />
109
+ </TeardownProvider>
110
+ ```
111
+
112
+ ### Hooks
113
+
114
+ Reactive hooks that subscribe to SDK state changes:
115
+
116
+ - `useTeardown()` - Access the core instance
117
+ - `useSession()` - Get current session (reactive)
118
+ - `useForceUpdate()` - Get version status (reactive)
119
+
120
+ ## Persistence
121
+
122
+ The SDK automatically persists:
123
+
124
+ - **Session data** - Device ID, user ID, token
125
+ - **Version status** - Last known update state
126
+ - **Device ID** - Stable device identifier
127
+
128
+ State is restored on app restart, providing offline-first functionality.
129
+
130
+ ## Error Handling
131
+
132
+ All async operations return `AsyncResult` for type-safe error handling:
133
+
134
+ ```typescript
135
+ type AsyncResult<T> =
136
+ | { success: true; data: T }
137
+ | { success: false; error: string };
138
+
139
+ const result = await core.identity.identify({ user_id: '123' });
140
+ if (result.success) {
141
+ console.log(result.data.session_id);
142
+ } else {
143
+ console.error(result.error);
144
+ }
145
+ ```
146
+
147
+ ## Logging
148
+
149
+ The SDK includes a structured logging system with configurable levels:
150
+
151
+ ```typescript
152
+ teardown.setLogLevel('verbose'); // none | error | warn | info | verbose
153
+ ```
154
+
155
+ Each client logs with a prefix for easy filtering:
156
+ - `[Teardown:IdentityClient]`
157
+ - `[Teardown:ForceUpdateClient]`
158
+ - `[Teardown:DeviceClient]`