@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,324 @@
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)
@@ -0,0 +1,345 @@
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)