@teardown/react-native 2.0.24 → 2.0.28
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/docs/adapters/device/basic.mdx +59 -0
- package/docs/adapters/device/device-info.mdx +76 -0
- package/docs/adapters/device/expo.mdx +61 -0
- package/docs/adapters/device/index.mdx +102 -0
- package/docs/adapters/device/meta.json +4 -0
- package/docs/adapters/index.mdx +96 -0
- package/docs/adapters/meta.json +4 -0
- package/docs/adapters/notifications/expo.mdx +127 -0
- package/docs/adapters/notifications/firebase.mdx +142 -0
- package/docs/adapters/notifications/index.mdx +100 -0
- package/docs/adapters/notifications/meta.json +4 -0
- package/docs/adapters/notifications/wix.mdx +140 -0
- package/docs/adapters/storage/async-storage.mdx +95 -0
- package/docs/adapters/storage/index.mdx +93 -0
- package/docs/adapters/storage/meta.json +4 -0
- package/docs/adapters/storage/mmkv.mdx +86 -0
- package/docs/advanced.mdx +280 -0
- package/docs/api-reference.mdx +241 -0
- package/docs/core-concepts.mdx +158 -0
- package/docs/force-updates.mdx +185 -0
- package/docs/getting-started.mdx +156 -0
- package/docs/hooks-reference.mdx +232 -0
- package/docs/identity.mdx +171 -0
- package/docs/index.mdx +61 -0
- package/docs/logging.mdx +144 -0
- package/docs/meta.json +14 -0
- package/package.json +49 -31
- package/src/clients/api/index.ts +1 -1
- package/src/clients/device/adapters/basic.adapter.ts +57 -66
- package/src/clients/device/adapters/device-info.adapter.ts +21 -28
- package/src/clients/device/adapters/device.adpater-interface.ts +1 -8
- package/src/clients/device/adapters/expo.adapter.ts +33 -40
- package/src/clients/device/device.client.test.ts +20 -35
- package/src/clients/device/device.client.ts +0 -3
- package/src/clients/identity/identity.client.test.ts +8 -8
- package/src/clients/identity/identity.client.ts +1 -1
- package/src/clients/identity/index.ts +1 -1
- package/src/clients/logging/index.ts +1 -1
- package/src/clients/notifications/adapters/expo-notifications.adapter.ts +105 -0
- package/src/clients/notifications/adapters/firebase-messaging.adapter.ts +87 -0
- package/src/clients/notifications/adapters/notifications.adapter-interface.ts +112 -0
- package/src/clients/notifications/adapters/wix-notifications.adapter.ts +183 -0
- package/src/clients/notifications/index.ts +2 -0
- package/src/clients/notifications/notifications.client.ts +214 -3
- package/src/clients/storage/adapters/async-storage.adapter.ts +2 -6
- package/src/clients/storage/adapters/storage-adapters.test.ts +2 -7
- package/src/clients/storage/adapters/storage.adpater-interface.ts +1 -5
- package/src/clients/utils/index.ts +1 -1
- package/src/clients/utils/utils.client.ts +1 -1
- package/src/exports/adapters/async-storage.ts +1 -1
- package/src/exports/adapters/expo.ts +1 -1
- package/src/exports/expo.ts +2 -0
- package/src/exports/firebase.ts +1 -0
- package/src/exports/index.ts +6 -9
- package/src/exports/wix.ts +1 -0
- package/src/hooks/use-force-update.ts +31 -34
- package/src/index.ts +1 -0
- package/src/teardown.core.ts +0 -2
- 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]`
|