@teardown/react-native 2.0.4 → 2.0.10
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 +104 -34
- package/package.json +18 -9
- package/src/clients/api/api.client.ts +1 -1
- package/src/clients/device/adapters/device-info.adapter.ts +36 -0
- package/src/clients/device/adapters/device.adpater-interface.ts +23 -0
- package/src/clients/device/adapters/expo.adapter.ts +2 -36
- package/src/clients/force-update/force-update.client.test.ts +7 -7
- package/src/clients/force-update/force-update.client.ts +30 -6
- package/src/clients/identity/identity.client.test.ts +20 -20
- package/src/clients/identity/identity.client.ts +5 -6
- package/src/clients/storage/adapters/async-storage.adapter.ts +18 -20
- package/src/clients/storage/adapters/storage.adpater-interface.ts +1 -1
- package/src/clients/storage/storage.client.ts +17 -1
- package/src/exports/adapters/device-info.ts +1 -0
- package/src/teardown.core.ts +3 -1
- package/docs/01-getting-started.mdx +0 -147
- package/docs/02-core-concepts.mdx +0 -188
- package/docs/03-identity.mdx +0 -301
- package/docs/04-force-updates.mdx +0 -339
- package/docs/05-device-info.mdx +0 -324
- package/docs/06-logging.mdx +0 -345
- package/docs/06-storage.mdx +0 -349
- package/docs/07-api-reference.mdx +0 -472
- package/docs/07-logging.mdx +0 -345
- package/docs/08-api-reference.mdx +0 -472
- package/docs/08-hooks-reference.mdx +0 -476
- package/docs/09-advanced.mdx +0 -563
- package/docs/09-hooks-reference.mdx +0 -476
- package/docs/10-advanced.mdx +0 -563
package/docs/05-device-info.mdx
DELETED
|
@@ -1,324 +0,0 @@
|
|
|
1
|
-
# Device Information
|
|
2
|
-
|
|
3
|
-
Collect comprehensive device, OS, and app information with the DeviceClient.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
The DeviceClient provides:
|
|
8
|
-
- Unique device identification
|
|
9
|
-
- Comprehensive device information
|
|
10
|
-
- Platform-specific adapters
|
|
11
|
-
- Automatic device fingerprinting
|
|
12
|
-
|
|
13
|
-
## Device Adapters
|
|
14
|
-
|
|
15
|
-
The SDK uses adapters to collect device information across different platforms.
|
|
16
|
-
|
|
17
|
-
### Expo Adapter
|
|
18
|
-
|
|
19
|
-
For Expo applications:
|
|
20
|
-
|
|
21
|
-
```typescript
|
|
22
|
-
import { TeardownCore } from '@teardown/react-native';
|
|
23
|
-
import { ExpoDeviceAdapter } from '@teardown/react-native/expo';
|
|
24
|
-
|
|
25
|
-
const teardown = new TeardownCore({
|
|
26
|
-
// ... other options
|
|
27
|
-
deviceAdapter: new ExpoDeviceAdapter(),
|
|
28
|
-
});
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
Required dependencies:
|
|
32
|
-
```bash
|
|
33
|
-
bun add expo-application expo-device expo-updates
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### React Native Adapter
|
|
37
|
-
|
|
38
|
-
For React Native CLI applications:
|
|
39
|
-
|
|
40
|
-
```typescript
|
|
41
|
-
import { TeardownCore } from '@teardown/react-native';
|
|
42
|
-
import { ReactNativeDeviceAdapter } from '@teardown/react-native/device-info';
|
|
43
|
-
|
|
44
|
-
const teardown = new TeardownCore({
|
|
45
|
-
// ... other options
|
|
46
|
-
deviceAdapter: new ReactNativeDeviceAdapter(),
|
|
47
|
-
});
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Required dependencies:
|
|
51
|
-
```bash
|
|
52
|
-
bun add react-native-device-info
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Device ID
|
|
56
|
-
|
|
57
|
-
Every device gets a unique, persistent identifier.
|
|
58
|
-
|
|
59
|
-
### Getting Device ID
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
import { useTeardown } from '@teardown/react-native';
|
|
63
|
-
|
|
64
|
-
function MyComponent() {
|
|
65
|
-
const { core } = useTeardown();
|
|
66
|
-
|
|
67
|
-
const getDeviceId = async () => {
|
|
68
|
-
const deviceId = await core.device.getDeviceId();
|
|
69
|
-
console.log('Device ID:', deviceId);
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### How It Works
|
|
75
|
-
|
|
76
|
-
1. On first launch, a random UUID is generated
|
|
77
|
-
2. ID is persisted in namespaced storage
|
|
78
|
-
3. Same ID is used for all subsequent sessions
|
|
79
|
-
4. Survives app updates and reinstalls (depending on storage)
|
|
80
|
-
|
|
81
|
-
## Device Information
|
|
82
|
-
|
|
83
|
-
### Getting Device Info
|
|
84
|
-
|
|
85
|
-
```typescript
|
|
86
|
-
const deviceInfo = await core.device.getDeviceInfo();
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### DeviceInfo Object
|
|
90
|
-
|
|
91
|
-
```typescript
|
|
92
|
-
type DeviceInfo = {
|
|
93
|
-
// App Information
|
|
94
|
-
app_version: string; // e.g., "1.0.0"
|
|
95
|
-
app_build: string; // e.g., "100"
|
|
96
|
-
app_bundle_id: string; // e.g., "com.company.app"
|
|
97
|
-
|
|
98
|
-
// Device Information
|
|
99
|
-
device_platform: DevicePlatformEnum; // IOS, ANDROID, WEB, etc.
|
|
100
|
-
device_os_version: string; // e.g., "17.0"
|
|
101
|
-
device_model: string; // e.g., "iPhone 14 Pro"
|
|
102
|
-
device_manufacturer: string; // e.g., "Apple"
|
|
103
|
-
|
|
104
|
-
// Update Information (Expo only)
|
|
105
|
-
update?: {
|
|
106
|
-
update_id: string;
|
|
107
|
-
channel: string;
|
|
108
|
-
created_at: string;
|
|
109
|
-
runtime_version: string;
|
|
110
|
-
} | null;
|
|
111
|
-
}
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
## Platform Enums
|
|
115
|
-
|
|
116
|
-
### DevicePlatformEnum
|
|
117
|
-
|
|
118
|
-
```typescript
|
|
119
|
-
enum DevicePlatformEnum {
|
|
120
|
-
IOS = "IOS",
|
|
121
|
-
ANDROID = "ANDROID",
|
|
122
|
-
WEB = "WEB",
|
|
123
|
-
WINDOWS = "WINDOWS",
|
|
124
|
-
MACOS = "MACOS",
|
|
125
|
-
LINUX = "LINUX",
|
|
126
|
-
PHONE = "PHONE",
|
|
127
|
-
TABLET = "TABLET",
|
|
128
|
-
DESKTOP = "DESKTOP",
|
|
129
|
-
CONSOLE = "CONSOLE",
|
|
130
|
-
TV = "TV",
|
|
131
|
-
WEARABLE = "WEARABLE",
|
|
132
|
-
GAME_CONSOLE = "GAME_CONSOLE",
|
|
133
|
-
VR = "VR",
|
|
134
|
-
UNKNOWN = "UNKNOWN",
|
|
135
|
-
OTHER = "OTHER",
|
|
136
|
-
}
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
## Creating Custom Adapters
|
|
140
|
-
|
|
141
|
-
You can create custom device adapters for specific platforms or needs.
|
|
142
|
-
|
|
143
|
-
### Adapter Interface
|
|
144
|
-
|
|
145
|
-
```typescript
|
|
146
|
-
interface DeviceInfoAdapter {
|
|
147
|
-
getDeviceInfo(): Promise<DeviceInfo>;
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
### Example: Custom Web Adapter
|
|
152
|
-
|
|
153
|
-
```typescript
|
|
154
|
-
class WebDeviceAdapter implements DeviceInfoAdapter {
|
|
155
|
-
async getDeviceInfo(): Promise<DeviceInfo> {
|
|
156
|
-
return {
|
|
157
|
-
app_version: '1.0.0',
|
|
158
|
-
app_build: '1',
|
|
159
|
-
app_bundle_id: 'com.yourapp.web',
|
|
160
|
-
device_platform: DevicePlatformEnum.WEB,
|
|
161
|
-
device_os_version: navigator.userAgent,
|
|
162
|
-
device_model: 'Web Browser',
|
|
163
|
-
device_manufacturer: this.getBrowserName(),
|
|
164
|
-
update: null,
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
private getBrowserName(): string {
|
|
169
|
-
const ua = navigator.userAgent;
|
|
170
|
-
if (ua.includes('Chrome')) return 'Chrome';
|
|
171
|
-
if (ua.includes('Firefox')) return 'Firefox';
|
|
172
|
-
if (ua.includes('Safari')) return 'Safari';
|
|
173
|
-
return 'Unknown';
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Use it
|
|
178
|
-
const teardown = new TeardownCore({
|
|
179
|
-
deviceAdapter: new WebDeviceAdapter(),
|
|
180
|
-
// ...
|
|
181
|
-
});
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
## Expo Update Information
|
|
185
|
-
|
|
186
|
-
When using Expo with OTA updates, the SDK automatically includes update information:
|
|
187
|
-
|
|
188
|
-
```typescript
|
|
189
|
-
{
|
|
190
|
-
update: {
|
|
191
|
-
update_id: "abc123",
|
|
192
|
-
channel: "production",
|
|
193
|
-
created_at: "2024-01-01T00:00:00Z",
|
|
194
|
-
runtime_version: "1.0.0",
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
This helps track which OTA update version users are running.
|
|
200
|
-
|
|
201
|
-
## Usage in Identification
|
|
202
|
-
|
|
203
|
-
Device information is automatically sent during identification:
|
|
204
|
-
|
|
205
|
-
```typescript
|
|
206
|
-
await core.identity.identify({
|
|
207
|
-
user_id: 'user-123',
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
// Automatically includes:
|
|
211
|
-
// - Device ID
|
|
212
|
-
// - Device platform
|
|
213
|
-
// - OS version
|
|
214
|
-
// - App version
|
|
215
|
-
// - Device model
|
|
216
|
-
// - Manufacturer
|
|
217
|
-
// - Update info (if Expo)
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
This data is visible in your Teardown dashboard for analytics and debugging.
|
|
221
|
-
|
|
222
|
-
## Platform Detection Examples
|
|
223
|
-
|
|
224
|
-
### Check if iOS
|
|
225
|
-
|
|
226
|
-
```typescript
|
|
227
|
-
const deviceInfo = await core.device.getDeviceInfo();
|
|
228
|
-
const isIOS = deviceInfo.device_platform === DevicePlatformEnum.IOS;
|
|
229
|
-
|
|
230
|
-
if (isIOS) {
|
|
231
|
-
// iOS-specific logic
|
|
232
|
-
}
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
### Check Version
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
const deviceInfo = await core.device.getDeviceInfo();
|
|
239
|
-
const version = deviceInfo.app_version;
|
|
240
|
-
|
|
241
|
-
if (compareVersions(version, '2.0.0') < 0) {
|
|
242
|
-
// Running version older than 2.0.0
|
|
243
|
-
}
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
### Check if Tablet
|
|
247
|
-
|
|
248
|
-
```typescript
|
|
249
|
-
const deviceInfo = await core.device.getDeviceInfo();
|
|
250
|
-
const isTablet = deviceInfo.device_platform === DevicePlatformEnum.TABLET;
|
|
251
|
-
|
|
252
|
-
if (isTablet) {
|
|
253
|
-
// Show tablet-optimized UI
|
|
254
|
-
}
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
## Storage
|
|
258
|
-
|
|
259
|
-
Device ID is stored in namespaced storage:
|
|
260
|
-
|
|
261
|
-
```
|
|
262
|
-
Key: teardown:v1:device:deviceId
|
|
263
|
-
Value: "uuid-generated-on-first-launch"
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
## Best Practices
|
|
267
|
-
|
|
268
|
-
### 1. Cache Device Info If Needed Frequently
|
|
269
|
-
|
|
270
|
-
```typescript
|
|
271
|
-
// ❌ Bad - fetches every render
|
|
272
|
-
function MyComponent() {
|
|
273
|
-
const deviceInfo = await core.device.getDeviceInfo();
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// ✅ Good - fetch once and cache
|
|
277
|
-
function MyComponent() {
|
|
278
|
-
const [deviceInfo, setDeviceInfo] = useState(null);
|
|
279
|
-
|
|
280
|
-
useEffect(() => {
|
|
281
|
-
core.device.getDeviceInfo().then(setDeviceInfo);
|
|
282
|
-
}, []);
|
|
283
|
-
}
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
### 2. Use Platform-Specific Code When Needed
|
|
287
|
-
|
|
288
|
-
```typescript
|
|
289
|
-
const deviceInfo = await core.device.getDeviceInfo();
|
|
290
|
-
|
|
291
|
-
if (deviceInfo.device_platform === DevicePlatformEnum.IOS) {
|
|
292
|
-
// iOS-specific behavior
|
|
293
|
-
} else if (deviceInfo.device_platform === DevicePlatformEnum.ANDROID) {
|
|
294
|
-
// Android-specific behavior
|
|
295
|
-
}
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
### 3. Don't Manually Generate Device IDs
|
|
299
|
-
|
|
300
|
-
```typescript
|
|
301
|
-
// ❌ Bad - inconsistent with SDK
|
|
302
|
-
const myDeviceId = uuid.v4();
|
|
303
|
-
|
|
304
|
-
// ✅ Good - use SDK's device ID
|
|
305
|
-
const deviceId = await core.device.getDeviceId();
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
## Privacy Considerations
|
|
309
|
-
|
|
310
|
-
The SDK collects:
|
|
311
|
-
- ✅ Device model and OS (for compatibility)
|
|
312
|
-
- ✅ App version (for update management)
|
|
313
|
-
- ✅ Generated device ID (for analytics)
|
|
314
|
-
- ❌ No personal information
|
|
315
|
-
- ❌ No advertising IDs
|
|
316
|
-
- ❌ No contacts or photos
|
|
317
|
-
|
|
318
|
-
Device ID is randomly generated and not tied to hardware identifiers.
|
|
319
|
-
|
|
320
|
-
## Next Steps
|
|
321
|
-
|
|
322
|
-
- [Storage](./06-storage.mdx)
|
|
323
|
-
- [Logging](./06-logging.mdx)
|
|
324
|
-
- [API Reference](./07-api-reference.mdx)
|
package/docs/06-logging.mdx
DELETED
|
@@ -1,345 +0,0 @@
|
|
|
1
|
-
# Logging
|
|
2
|
-
|
|
3
|
-
Structured logging system with configurable log levels.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
The LoggingClient provides:
|
|
8
|
-
- Configurable log levels
|
|
9
|
-
- Named loggers for each client
|
|
10
|
-
- Console binding preservation
|
|
11
|
-
- Debug mode support
|
|
12
|
-
|
|
13
|
-
## Log Levels
|
|
14
|
-
|
|
15
|
-
```typescript
|
|
16
|
-
type LogLevel =
|
|
17
|
-
| "none" // No logging
|
|
18
|
-
| "error" // Only errors
|
|
19
|
-
| "warn" // Errors and warnings
|
|
20
|
-
| "info" // Errors, warnings, and info
|
|
21
|
-
| "verbose" // Everything including debug
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
### Level Priority
|
|
25
|
-
|
|
26
|
-
```
|
|
27
|
-
none < error < warn < info < verbose
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
When you set a level, all lower-priority levels are also shown:
|
|
31
|
-
- `error`: Shows only errors
|
|
32
|
-
- `warn`: Shows errors + warnings
|
|
33
|
-
- `info`: Shows errors + warnings + info
|
|
34
|
-
- `verbose`: Shows everything (errors + warnings + info + debug)
|
|
35
|
-
|
|
36
|
-
## Setting Log Level
|
|
37
|
-
|
|
38
|
-
### On Initialization
|
|
39
|
-
|
|
40
|
-
```typescript
|
|
41
|
-
const teardown = new TeardownCore({
|
|
42
|
-
// ... other options
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// Set log level after initialization
|
|
46
|
-
teardown.setLogLevel('verbose');
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### During Runtime
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
import { useTeardown } from '@teardown/react-native';
|
|
53
|
-
|
|
54
|
-
function DebugPanel() {
|
|
55
|
-
const { core } = useTeardown();
|
|
56
|
-
|
|
57
|
-
const enableDebugMode = () => {
|
|
58
|
-
core.setLogLevel('verbose');
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const disableLogging = () => {
|
|
62
|
-
core.setLogLevel('none');
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
return (
|
|
66
|
-
<View>
|
|
67
|
-
<Button title="Enable Debug" onPress={enableDebugMode} />
|
|
68
|
-
<Button title="Disable Logs" onPress={disableLogging} />
|
|
69
|
-
</View>
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Log Output Format
|
|
75
|
-
|
|
76
|
-
All logs are prefixed with the client name:
|
|
77
|
-
|
|
78
|
-
```
|
|
79
|
-
[Teardown:TeardownCore] Shutting down TeardownCore
|
|
80
|
-
[Teardown:IdentityClient] Identify state: unidentified -> identifying
|
|
81
|
-
[Teardown:IdentityClient] Identify state: identifying -> identified
|
|
82
|
-
[Teardown:ForceUpdateClient] Version status changing: initializing -> checking
|
|
83
|
-
[Teardown:ForceUpdateClient] Checking version status on foreground
|
|
84
|
-
[Teardown:DeviceClient] Getting device ID
|
|
85
|
-
[Teardown:StorageClient] Creating storage for teardown:v1:identity
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Logger Methods
|
|
89
|
-
|
|
90
|
-
Each client has a logger with these methods:
|
|
91
|
-
|
|
92
|
-
```typescript
|
|
93
|
-
logger.info(message, ...args) // Info level
|
|
94
|
-
logger.warn(message, ...args) // Warning level
|
|
95
|
-
logger.error(message, ...args) // Error level
|
|
96
|
-
logger.debug(message, ...args) // Debug level (verbose)
|
|
97
|
-
logger.trace(message, ...args) // Stack trace (verbose)
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
## Internal Logging
|
|
101
|
-
|
|
102
|
-
The SDK logs these events:
|
|
103
|
-
|
|
104
|
-
### TeardownCore
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
[Teardown:TeardownCore] Error initializing TeardownCore { error }
|
|
108
|
-
[Teardown:TeardownCore] Shutting down TeardownCore
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### IdentityClient
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
[Teardown:IdentityClient] Identify state: unidentified -> identifying
|
|
115
|
-
[Teardown:IdentityClient] Identify state: identifying -> identified
|
|
116
|
-
[Teardown:IdentityClient] 422 Error identifying user { ... }
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
### ForceUpdateClient
|
|
120
|
-
|
|
121
|
-
```typescript
|
|
122
|
-
[Teardown:ForceUpdateClient] Version status changing: initializing -> up_to_date
|
|
123
|
-
[Teardown:ForceUpdateClient] Checking version status on foreground
|
|
124
|
-
[Teardown:ForceUpdateClient] Skipping version check - not identified
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### DeviceClient
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
[Teardown:DeviceClient] Getting device ID
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### StorageClient
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
[Teardown:StorageClient] Creating storage for teardown:v1:identity
|
|
137
|
-
[Teardown:StorageClient] Storage already exists for teardown:v1:identity
|
|
138
|
-
[Teardown:StorageClient] Returning existing storage for teardown:v1:identity
|
|
139
|
-
[Teardown:StorageClient] Clearing storage for teardown:v1:identity
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
## Console Binding
|
|
143
|
-
|
|
144
|
-
The logger preserves console call sites for better debugging:
|
|
145
|
-
|
|
146
|
-
```typescript
|
|
147
|
-
// Bound console methods preserve original call site
|
|
148
|
-
private boundConsole = {
|
|
149
|
-
log: console.log.bind(console),
|
|
150
|
-
error: console.error.bind(console),
|
|
151
|
-
debug: console.debug.bind(console),
|
|
152
|
-
warn: console.warn.bind(console),
|
|
153
|
-
trace: console.trace.bind(console),
|
|
154
|
-
};
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
This means clicking log messages in DevTools takes you to the original SDK code, not the logger wrapper.
|
|
158
|
-
|
|
159
|
-
## Creating Custom Loggers
|
|
160
|
-
|
|
161
|
-
While not typically needed, you can create custom loggers:
|
|
162
|
-
|
|
163
|
-
```typescript
|
|
164
|
-
import { LoggingClient } from '@teardown/react-native';
|
|
165
|
-
|
|
166
|
-
const logging = new LoggingClient({ logLevel: 'info' });
|
|
167
|
-
const logger = logging.createLogger({ name: 'MyFeature' });
|
|
168
|
-
|
|
169
|
-
logger.info('Feature initialized');
|
|
170
|
-
logger.error('Something went wrong');
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
## Conditional Logging
|
|
174
|
-
|
|
175
|
-
The SDK checks log level before logging:
|
|
176
|
-
|
|
177
|
-
```typescript
|
|
178
|
-
// Only logs if current level >= info
|
|
179
|
-
if (this.loggingClient.shouldLog('info')) {
|
|
180
|
-
logger.info('Message');
|
|
181
|
-
}
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
This prevents unnecessary string concatenation and formatting in production.
|
|
185
|
-
|
|
186
|
-
## Best Practices
|
|
187
|
-
|
|
188
|
-
### 1. Use 'none' in Production
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
// ✅ Good - no logs in production
|
|
192
|
-
const logLevel = __DEV__ ? 'verbose' : 'none';
|
|
193
|
-
teardown.setLogLevel(logLevel);
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### 2. Use 'verbose' for Debugging
|
|
197
|
-
|
|
198
|
-
```typescript
|
|
199
|
-
// ✅ Good - detailed logs during development
|
|
200
|
-
if (__DEV__) {
|
|
201
|
-
teardown.setLogLevel('verbose');
|
|
202
|
-
}
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
### 3. Enable Logging for Support
|
|
206
|
-
|
|
207
|
-
```typescript
|
|
208
|
-
// ✅ Good - user can enable logs for support
|
|
209
|
-
function Settings() {
|
|
210
|
-
const { core } = useTeardown();
|
|
211
|
-
const [debugMode, setDebugMode] = useState(false);
|
|
212
|
-
|
|
213
|
-
const toggleDebug = () => {
|
|
214
|
-
const newMode = !debugMode;
|
|
215
|
-
setDebugMode(newMode);
|
|
216
|
-
core.setLogLevel(newMode ? 'verbose' : 'none');
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
return <Switch value={debugMode} onValueChange={toggleDebug} />;
|
|
220
|
-
}
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
### 4. Don't Rely on Logs for Logic
|
|
224
|
-
|
|
225
|
-
```typescript
|
|
226
|
-
// ❌ Bad - logs may be disabled
|
|
227
|
-
logger.info('User identified');
|
|
228
|
-
// ... rely on this log
|
|
229
|
-
|
|
230
|
-
// ✅ Good - use state/events
|
|
231
|
-
const result = await identify();
|
|
232
|
-
if (result.success) {
|
|
233
|
-
// ... use result, not logs
|
|
234
|
-
}
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
## Log Level Examples
|
|
238
|
-
|
|
239
|
-
### Development
|
|
240
|
-
|
|
241
|
-
```typescript
|
|
242
|
-
// See everything
|
|
243
|
-
teardown.setLogLevel('verbose');
|
|
244
|
-
|
|
245
|
-
// Output:
|
|
246
|
-
// [Teardown:IdentityClient] Getting device ID
|
|
247
|
-
// [Teardown:IdentityClient] Identify state: unidentified -> identifying
|
|
248
|
-
// [Teardown:StorageClient] Creating storage for teardown:v1:identity
|
|
249
|
-
// etc.
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
### Debugging Issues
|
|
253
|
-
|
|
254
|
-
```typescript
|
|
255
|
-
// See important events
|
|
256
|
-
teardown.setLogLevel('info');
|
|
257
|
-
|
|
258
|
-
// Output:
|
|
259
|
-
// [Teardown:IdentityClient] Identify state: unidentified -> identifying
|
|
260
|
-
// [Teardown:ForceUpdateClient] Version status changing: initializing -> up_to_date
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
### Production
|
|
264
|
-
|
|
265
|
-
```typescript
|
|
266
|
-
// See only errors
|
|
267
|
-
teardown.setLogLevel('error');
|
|
268
|
-
|
|
269
|
-
// Output:
|
|
270
|
-
// [Teardown:TeardownCore] Error initializing TeardownCore { error }
|
|
271
|
-
// [Teardown:IdentityClient] 422 Error identifying user { ... }
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
### Disabled
|
|
275
|
-
|
|
276
|
-
```typescript
|
|
277
|
-
// No logs
|
|
278
|
-
teardown.setLogLevel('none');
|
|
279
|
-
|
|
280
|
-
// Output:
|
|
281
|
-
// (nothing)
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
## Environment-Based Configuration
|
|
285
|
-
|
|
286
|
-
```typescript
|
|
287
|
-
const LOG_LEVEL: LogLevel =
|
|
288
|
-
process.env.NODE_ENV === 'development' ? 'verbose' :
|
|
289
|
-
process.env.NODE_ENV === 'staging' ? 'info' :
|
|
290
|
-
'error';
|
|
291
|
-
|
|
292
|
-
teardown.setLogLevel(LOG_LEVEL);
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
## Debugging Tips
|
|
296
|
-
|
|
297
|
-
### 1. Enable Verbose Logging
|
|
298
|
-
|
|
299
|
-
```typescript
|
|
300
|
-
teardown.setLogLevel('verbose');
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
### 2. Filter by Client
|
|
304
|
-
|
|
305
|
-
Search DevTools console for specific client:
|
|
306
|
-
```
|
|
307
|
-
[Teardown:IdentityClient]
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
### 3. Track State Transitions
|
|
311
|
-
|
|
312
|
-
Look for state change logs:
|
|
313
|
-
```
|
|
314
|
-
Identify state: unidentified -> identifying
|
|
315
|
-
Version status changing: checking -> up_to_date
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
### 4. Check Error Details
|
|
319
|
-
|
|
320
|
-
Errors include full context:
|
|
321
|
-
```typescript
|
|
322
|
-
logger.error('Error initializing', { error, context });
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
## Performance
|
|
326
|
-
|
|
327
|
-
Logging is optimized for production:
|
|
328
|
-
|
|
329
|
-
```typescript
|
|
330
|
-
// ✅ Good - check happens before string operations
|
|
331
|
-
if (this.shouldLog('verbose')) {
|
|
332
|
-
logger.debug(`Expensive operation: ${JSON.stringify(bigObject)}`);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// ❌ Bad - string created even if logging disabled
|
|
336
|
-
logger.debug(`Expensive operation: ${JSON.stringify(bigObject)}`);
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
The SDK uses the first pattern internally.
|
|
340
|
-
|
|
341
|
-
## Next Steps
|
|
342
|
-
|
|
343
|
-
- [API Reference](./07-api-reference.mdx)
|
|
344
|
-
- [Hooks Reference](./08-hooks-reference.mdx)
|
|
345
|
-
- [Advanced Usage](./09-advanced.mdx)
|