@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.
- 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/force-update/force-update.client.test.ts +69 -23
- package/src/clients/force-update/force-update.client.ts +42 -59
- package/src/clients/identity/identity.client.test.ts +22 -14
- 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,171 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Identity
|
|
3
|
+
description: User and device identification with the Teardown SDK.
|
|
4
|
+
icon: User
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The Identity client manages user sessions, device identification, and authentication state.
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
The SDK automatically identifies devices on initialization. You can optionally associate users with devices by calling `identify()` with user information.
|
|
12
|
+
|
|
13
|
+
## Session Structure
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
interface Session {
|
|
17
|
+
session_id: string; // Unique session identifier
|
|
18
|
+
device_id: string; // Stable device identifier
|
|
19
|
+
user_id: string; // User or persona identifier
|
|
20
|
+
token: string; // Authentication token
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Basic Usage
|
|
25
|
+
|
|
26
|
+
### Identify a User
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
const { core } = useTeardown();
|
|
30
|
+
|
|
31
|
+
const handleLogin = async () => {
|
|
32
|
+
const result = await core.identity.identify({
|
|
33
|
+
user_id: 'user-123',
|
|
34
|
+
email: 'user@example.com',
|
|
35
|
+
name: 'John Doe',
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
if (result.success) {
|
|
39
|
+
console.log('Identified:', result.data.session_id);
|
|
40
|
+
} else {
|
|
41
|
+
console.error('Failed:', result.error);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Get Current Session
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
// Imperative
|
|
50
|
+
const session = core.identity.getSessionState();
|
|
51
|
+
|
|
52
|
+
// Reactive (hook)
|
|
53
|
+
const session = useSession();
|
|
54
|
+
|
|
55
|
+
if (session) {
|
|
56
|
+
console.log('Device:', session.device_id);
|
|
57
|
+
console.log('User:', session.user_id);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Reset Identity
|
|
62
|
+
|
|
63
|
+
Clear the current session and device association:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
core.identity.reset();
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Refresh Session
|
|
70
|
+
|
|
71
|
+
Re-identify to refresh session data (only works if already identified):
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
const result = await core.identity.refresh();
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Identity State
|
|
78
|
+
|
|
79
|
+
The identity client maintains a state machine:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
type IdentifyState =
|
|
83
|
+
| { type: 'unidentified' }
|
|
84
|
+
| { type: 'identifying' }
|
|
85
|
+
| { type: 'identified'; session: Session; version_info: VersionInfo };
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Subscribe to State Changes
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
const unsubscribe = core.identity.onIdentifyStateChange((state) => {
|
|
92
|
+
switch (state.type) {
|
|
93
|
+
case 'unidentified':
|
|
94
|
+
// Show login screen
|
|
95
|
+
break;
|
|
96
|
+
case 'identifying':
|
|
97
|
+
// Show loading
|
|
98
|
+
break;
|
|
99
|
+
case 'identified':
|
|
100
|
+
// Navigate to app
|
|
101
|
+
console.log('Session:', state.session);
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Cleanup
|
|
107
|
+
unsubscribe();
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Persona Object
|
|
111
|
+
|
|
112
|
+
When identifying, you can provide optional user information:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
interface Persona {
|
|
116
|
+
user_id?: string; // Your system's user ID
|
|
117
|
+
email?: string; // User email
|
|
118
|
+
name?: string; // Display name
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
All fields are optional. If no persona is provided, the device is identified anonymously.
|
|
123
|
+
|
|
124
|
+
## Device ID
|
|
125
|
+
|
|
126
|
+
The SDK generates a stable device ID that persists across app sessions:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
const deviceId = await core.device.getDeviceId();
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The device ID is:
|
|
133
|
+
- Generated once per device
|
|
134
|
+
- Persisted in storage
|
|
135
|
+
- Used for all API calls
|
|
136
|
+
- Stable across app updates
|
|
137
|
+
|
|
138
|
+
## Version Info
|
|
139
|
+
|
|
140
|
+
The identify response includes version information used for force updates:
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
if (state.type === 'identified') {
|
|
144
|
+
const status = state.version_info.status;
|
|
145
|
+
// 'UP_TO_DATE' | 'UPDATE_AVAILABLE' | 'UPDATE_RECOMMENDED' | 'UPDATE_REQUIRED' | 'DISABLED'
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Error Handling
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
const result = await core.identity.identify({ user_id: '123' });
|
|
153
|
+
|
|
154
|
+
if (!result.success) {
|
|
155
|
+
switch (result.error) {
|
|
156
|
+
case 'Network error':
|
|
157
|
+
// Handle offline
|
|
158
|
+
break;
|
|
159
|
+
default:
|
|
160
|
+
// Handle other errors
|
|
161
|
+
console.error(result.error);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Best Practices
|
|
167
|
+
|
|
168
|
+
1. **Call identify on login** - Associate users with their devices
|
|
169
|
+
2. **Call reset on logout** - Clear session data
|
|
170
|
+
3. **Handle offline** - The SDK caches session data for offline use
|
|
171
|
+
4. **Use useSession hook** - For reactive UI updates
|
package/docs/index.mdx
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: React Native SDK
|
|
3
|
+
description: Comprehensive SDK for device identity, force updates, logging, and analytics in React Native and Expo applications.
|
|
4
|
+
icon: Smartphone
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The Teardown React Native SDK provides everything you need to manage device identity, force app updates, and collect analytics in your mobile applications.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Device & User Identity** - Unique device fingerprinting and user session management
|
|
12
|
+
- **Force Updates** - Automatic version checking with optional, recommended, or required update flows
|
|
13
|
+
- **Device Information** - Comprehensive device, OS, and app information collection
|
|
14
|
+
- **Storage** - Namespaced persistent storage with platform adapters
|
|
15
|
+
- **Logging** - Structured logging system with configurable log levels
|
|
16
|
+
- **Type Safety** - Full TypeScript support with Zod runtime validation
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
bun add @teardown/react-native
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { TeardownCore, TeardownProvider } from '@teardown/react-native';
|
|
26
|
+
import { ExpoDeviceAdapter } from '@teardown/react-native/adapters/expo';
|
|
27
|
+
import { MMKVStorageAdapter } from '@teardown/react-native/adapters/mmkv';
|
|
28
|
+
|
|
29
|
+
const teardown = new TeardownCore({
|
|
30
|
+
org_id: 'your-org-id',
|
|
31
|
+
project_id: 'your-project-id',
|
|
32
|
+
api_key: 'your-api-key',
|
|
33
|
+
storageAdapter: new MMKVStorageAdapter(),
|
|
34
|
+
deviceAdapter: new ExpoDeviceAdapter(),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export default function App() {
|
|
38
|
+
return (
|
|
39
|
+
<TeardownProvider core={teardown}>
|
|
40
|
+
<YourApp />
|
|
41
|
+
</TeardownProvider>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Platform Support
|
|
47
|
+
|
|
48
|
+
| Platform | Device Adapter | Storage Adapter |
|
|
49
|
+
|----------|---------------|-----------------|
|
|
50
|
+
| Expo | `ExpoDeviceAdapter` | `MMKVStorageAdapter` or `AsyncStorageAdapter` |
|
|
51
|
+
| React Native CLI | `DeviceInfoAdapter` | `MMKVStorageAdapter` or `AsyncStorageAdapter` |
|
|
52
|
+
|
|
53
|
+
## Documentation
|
|
54
|
+
|
|
55
|
+
- [Getting Started](/docs/react-native/getting-started) - Installation and setup
|
|
56
|
+
- [Core Concepts](/docs/react-native/core-concepts) - Architecture overview
|
|
57
|
+
- [Identity](/docs/react-native/identity) - User and device identification
|
|
58
|
+
- [Force Updates](/docs/react-native/force-updates) - Version management
|
|
59
|
+
- [Storage Adapters](/docs/react-native/adapters/storage) - Persistent storage adapters
|
|
60
|
+
- [API Reference](/docs/react-native/api-reference) - Complete API documentation
|
|
61
|
+
- [Hooks Reference](/docs/react-native/hooks-reference) - React hooks
|
package/docs/logging.mdx
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Logging
|
|
3
|
+
description: Configure structured logging in the Teardown SDK.
|
|
4
|
+
icon: FileText
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The SDK includes a structured logging system for debugging and monitoring.
|
|
8
|
+
|
|
9
|
+
## Log Levels
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
type LogLevel = 'none' | 'error' | 'warn' | 'info' | 'verbose';
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
| Level | Priority | Description |
|
|
16
|
+
|-------|----------|-------------|
|
|
17
|
+
| `none` | 0 | No logging |
|
|
18
|
+
| `error` | 1 | Only errors |
|
|
19
|
+
| `warn` | 2 | Errors and warnings |
|
|
20
|
+
| `info` | 3 | General information |
|
|
21
|
+
| `verbose` | 4 | Detailed debug output |
|
|
22
|
+
|
|
23
|
+
## Setting Log Level
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
const teardown = new TeardownCore({
|
|
27
|
+
// ...options
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Set log level (default is 'verbose' during development)
|
|
31
|
+
teardown.setLogLevel('verbose');
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Log Output
|
|
35
|
+
|
|
36
|
+
Each client logs with a prefix for easy filtering:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
[Teardown:TeardownCore] TeardownCore initialized
|
|
40
|
+
[Teardown:IdentityClient] Identifying user with persona: John
|
|
41
|
+
[Teardown:ForceUpdateClient] Version status: up_to_date
|
|
42
|
+
[Teardown:DeviceClient] Device ID: 550e8400-e29b-41d4...
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Log Methods
|
|
46
|
+
|
|
47
|
+
The internal `Logger` class provides these methods:
|
|
48
|
+
|
|
49
|
+
| Method | Level Required | Console Method |
|
|
50
|
+
|--------|---------------|----------------|
|
|
51
|
+
| `error()` | error | `console.error` |
|
|
52
|
+
| `warn()` | warn | `console.warn` |
|
|
53
|
+
| `info()` | info | `console.log` |
|
|
54
|
+
| `debug()` | verbose | `console.debug` |
|
|
55
|
+
| `trace()` | verbose | `console.trace` |
|
|
56
|
+
|
|
57
|
+
### Debug Variants
|
|
58
|
+
|
|
59
|
+
Additional debug methods for categorized output:
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
logger.debugError('Something went wrong', { error }); // Error: [prefix] ...
|
|
63
|
+
logger.debugWarn('Warning message'); // Warning: [prefix] ...
|
|
64
|
+
logger.debugInfo('Info message'); // Info: [prefix] ...
|
|
65
|
+
logger.debugVerbose('Verbose details'); // Verbose: [prefix] ...
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Production Logging
|
|
69
|
+
|
|
70
|
+
For production builds, set log level to `none` or `error`:
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
const teardown = new TeardownCore({ /* ... */ });
|
|
74
|
+
|
|
75
|
+
if (__DEV__) {
|
|
76
|
+
teardown.setLogLevel('verbose');
|
|
77
|
+
} else {
|
|
78
|
+
teardown.setLogLevel('error');
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Filtering Logs
|
|
83
|
+
|
|
84
|
+
Use the `[Teardown:` prefix to filter SDK logs in your console:
|
|
85
|
+
|
|
86
|
+
**React Native Debugger:**
|
|
87
|
+
```
|
|
88
|
+
Filter: [Teardown:
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Xcode Console:**
|
|
92
|
+
```
|
|
93
|
+
[Teardown:
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Android Logcat:**
|
|
97
|
+
```bash
|
|
98
|
+
adb logcat | grep "\[Teardown:"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Internal Architecture
|
|
102
|
+
|
|
103
|
+
The logging system consists of two classes:
|
|
104
|
+
|
|
105
|
+
### LoggingClient
|
|
106
|
+
|
|
107
|
+
Central log level management:
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
class LoggingClient {
|
|
111
|
+
setLogLevel(level: LogLevel): void;
|
|
112
|
+
getLogLevel(): LogLevel;
|
|
113
|
+
shouldLog(level: LogLevel): boolean;
|
|
114
|
+
createLogger(options: { name: string }): Logger;
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Logger
|
|
119
|
+
|
|
120
|
+
Individual logger instance with bound console methods:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
class Logger {
|
|
124
|
+
get prefix(): string; // [Teardown:ClientName]
|
|
125
|
+
info(message: string, ...args: unknown[]): void;
|
|
126
|
+
error(message: string, ...args: unknown[]): void;
|
|
127
|
+
warn(message: string, ...args: unknown[]): void;
|
|
128
|
+
debug(message: string, ...args: unknown[]): void;
|
|
129
|
+
trace(message: string, ...args: unknown[]): void;
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Best Practices
|
|
134
|
+
|
|
135
|
+
1. **Use `verbose` in development** - See all SDK activity
|
|
136
|
+
2. **Use `error` in production** - Minimize noise, catch issues
|
|
137
|
+
3. **Filter by prefix** - Isolate SDK logs from app logs
|
|
138
|
+
4. **Check log level first** - Avoid expensive string operations:
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
if (core.logging.shouldLog('verbose')) {
|
|
142
|
+
console.log('Complex debug:', JSON.stringify(largeObject));
|
|
143
|
+
}
|
|
144
|
+
```
|
package/docs/meta.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teardown/react-native",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.27",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"private": false,
|
|
5
6
|
"publishConfig": {
|
|
6
7
|
"access": "public"
|
|
@@ -13,69 +14,77 @@
|
|
|
13
14
|
"module": "./src/exports/index.ts",
|
|
14
15
|
"types": "./src/exports/index.ts",
|
|
15
16
|
"exports": {
|
|
17
|
+
"./package.json": "./package.json",
|
|
16
18
|
".": {
|
|
17
19
|
"types": "./src/exports/index.ts",
|
|
18
20
|
"import": "./src/exports/index.ts",
|
|
19
21
|
"default": "./src/exports/index.ts"
|
|
20
22
|
},
|
|
21
|
-
"./adapters
|
|
22
|
-
"types": "./src/exports/adapters
|
|
23
|
-
"import": "./src/exports/adapters
|
|
24
|
-
"default": "./src/exports/adapters
|
|
23
|
+
"./adapters/*": {
|
|
24
|
+
"types": "./src/exports/adapters/*.ts",
|
|
25
|
+
"import": "./src/exports/adapters/*.ts",
|
|
26
|
+
"default": "./src/exports/adapters/*.ts"
|
|
25
27
|
},
|
|
26
|
-
"./
|
|
27
|
-
"types": "./src/exports/
|
|
28
|
-
"import": "./src/exports/
|
|
29
|
-
"default": "./src/exports/
|
|
28
|
+
"./expo": {
|
|
29
|
+
"types": "./src/exports/expo.ts",
|
|
30
|
+
"import": "./src/exports/expo.ts",
|
|
31
|
+
"default": "./src/exports/expo.ts"
|
|
30
32
|
},
|
|
31
|
-
"./
|
|
32
|
-
"types": "./src/exports/
|
|
33
|
-
"import": "./src/exports/
|
|
34
|
-
"default": "./src/exports/
|
|
33
|
+
"./firebase": {
|
|
34
|
+
"types": "./src/exports/firebase.ts",
|
|
35
|
+
"import": "./src/exports/firebase.ts",
|
|
36
|
+
"default": "./src/exports/firebase.ts"
|
|
35
37
|
},
|
|
36
|
-
"./
|
|
37
|
-
"types": "./src/exports/
|
|
38
|
-
"import": "./src/exports/
|
|
39
|
-
"default": "./src/exports/
|
|
38
|
+
"./wix": {
|
|
39
|
+
"types": "./src/exports/wix.ts",
|
|
40
|
+
"import": "./src/exports/wix.ts",
|
|
41
|
+
"default": "./src/exports/wix.ts"
|
|
40
42
|
}
|
|
41
43
|
},
|
|
42
44
|
"scripts": {
|
|
43
45
|
"build": "tsc --project ./tsconfig.json",
|
|
44
46
|
"dev": "bun run build && tsc --watch --project ./tsconfig.json",
|
|
45
47
|
"typecheck": "tsc --noEmit --project ./tsconfig.json",
|
|
46
|
-
"lint": "biome lint --write",
|
|
47
|
-
"fmt": "biome format --write",
|
|
48
|
+
"lint": "bun x biome lint --write ./src",
|
|
49
|
+
"fmt": "bun x biome format --write ./src",
|
|
50
|
+
"check": "bun x biome check ./src",
|
|
48
51
|
"test": "bun test",
|
|
49
|
-
"prepublishOnly": "bun run build"
|
|
50
|
-
"nuke": "cd ../../ && bun run nuke"
|
|
52
|
+
"prepublishOnly": "bun run build"
|
|
51
53
|
},
|
|
52
54
|
"dependencies": {
|
|
53
|
-
"@teardown/ingest-api": "0.
|
|
54
|
-
"@teardown/schemas": "0.
|
|
55
|
-
"@teardown/types": "0.
|
|
55
|
+
"@teardown/ingest-api": "2.0.26",
|
|
56
|
+
"@teardown/schemas": "2.0.26",
|
|
57
|
+
"@teardown/types": "2.0.26",
|
|
56
58
|
"eventemitter3": "^5.0.1",
|
|
57
59
|
"react-native-get-random-values": "^2.0.0",
|
|
58
60
|
"uuid": "^13.0.0",
|
|
59
|
-
"zod": "
|
|
61
|
+
"zod": "4.2.1"
|
|
60
62
|
},
|
|
61
63
|
"devDependencies": {
|
|
62
|
-
"@
|
|
63
|
-
"@
|
|
64
|
-
"@
|
|
65
|
-
"@
|
|
66
|
-
"@types/
|
|
64
|
+
"@biomejs/biome": "2.3.10",
|
|
65
|
+
"@elysiajs/eden": "1.4.5",
|
|
66
|
+
"@react-native-firebase/messaging": "*",
|
|
67
|
+
"@teardown/tsconfig": "2.0.26",
|
|
68
|
+
"@types/bun": "1.3.5",
|
|
69
|
+
"@types/react": "~19.1.0",
|
|
70
|
+
"@types/uuid": "^11.0.0",
|
|
71
|
+
"react": "19.1.0",
|
|
72
|
+
"react-native": "0.81.5",
|
|
73
|
+
"react-native-notifications": "*"
|
|
67
74
|
},
|
|
68
75
|
"peerDependencies": {
|
|
69
|
-
"@react-native-async-storage/async-storage": "
|
|
76
|
+
"@react-native-async-storage/async-storage": "^1.21 || ^2.0",
|
|
70
77
|
"expo-application": "~7",
|
|
71
78
|
"expo-device": "~8",
|
|
72
79
|
"expo-notifications": "~0.32",
|
|
73
80
|
"expo-secure-store": "~15",
|
|
74
81
|
"expo-updates": "~29",
|
|
82
|
+
"@react-native-firebase/messaging": "*",
|
|
75
83
|
"react": "~19",
|
|
76
84
|
"react-native": "~0.81",
|
|
77
85
|
"react-native-device-info": "~15",
|
|
78
86
|
"react-native-mmkv": "^4",
|
|
87
|
+
"react-native-notifications": "*",
|
|
79
88
|
"typescript": "~5"
|
|
80
89
|
},
|
|
81
90
|
"peerDependenciesMeta": {
|
|
@@ -105,6 +114,15 @@
|
|
|
105
114
|
},
|
|
106
115
|
"expo-secure-store": {
|
|
107
116
|
"optional": true
|
|
117
|
+
},
|
|
118
|
+
"expo-updates": {
|
|
119
|
+
"optional": true
|
|
120
|
+
},
|
|
121
|
+
"@react-native-firebase/messaging": {
|
|
122
|
+
"optional": true
|
|
123
|
+
},
|
|
124
|
+
"react-native-notifications": {
|
|
125
|
+
"optional": true
|
|
108
126
|
}
|
|
109
127
|
}
|
|
110
128
|
}
|
package/src/clients/api/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "./api.client";
|
|
1
|
+
export * from "./api.client";
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ApplicationInfo,
|
|
3
|
-
HardwareInfo,
|
|
4
|
-
NotificationsInfo,
|
|
5
|
-
OSInfo,
|
|
6
|
-
} from "@teardown/schemas";
|
|
1
|
+
import type { ApplicationInfo, HardwareInfo, NotificationsInfo, OSInfo } from "@teardown/schemas";
|
|
7
2
|
import * as Application from "expo-application";
|
|
8
3
|
import * as Device from "expo-device";
|
|
9
4
|
import { Platform } from "react-native";
|
|
@@ -15,76 +10,72 @@ import { DeviceInfoAdapter } from "./device.adpater-interface";
|
|
|
15
10
|
* Maps expo-device DeviceType to a string representation
|
|
16
11
|
*/
|
|
17
12
|
function mapDeviceType(deviceType: Device.DeviceType | null): string {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
13
|
+
switch (deviceType) {
|
|
14
|
+
case Device.DeviceType.PHONE:
|
|
15
|
+
return "phone";
|
|
16
|
+
case Device.DeviceType.TABLET:
|
|
17
|
+
return "tablet";
|
|
18
|
+
case Device.DeviceType.DESKTOP:
|
|
19
|
+
return "desktop";
|
|
20
|
+
case Device.DeviceType.TV:
|
|
21
|
+
return "tv";
|
|
22
|
+
default:
|
|
23
|
+
return "unknown";
|
|
24
|
+
}
|
|
30
25
|
}
|
|
31
26
|
|
|
32
27
|
/**
|
|
33
28
|
* Maps React Native Platform.OS to DevicePlatformEnum
|
|
34
29
|
*/
|
|
35
30
|
function mapPlatform(platform: typeof Platform.OS): DevicePlatformEnum {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
31
|
+
switch (platform) {
|
|
32
|
+
case "ios":
|
|
33
|
+
return DevicePlatformEnum.IOS;
|
|
34
|
+
case "android":
|
|
35
|
+
return DevicePlatformEnum.ANDROID;
|
|
36
|
+
case "web":
|
|
37
|
+
return DevicePlatformEnum.WEB;
|
|
38
|
+
case "macos":
|
|
39
|
+
return DevicePlatformEnum.MACOS;
|
|
40
|
+
case "windows":
|
|
41
|
+
return DevicePlatformEnum.WINDOWS;
|
|
42
|
+
default:
|
|
43
|
+
return DevicePlatformEnum.UNKNOWN;
|
|
44
|
+
}
|
|
50
45
|
}
|
|
51
46
|
|
|
52
47
|
export class ExpoDeviceAdapter extends DeviceInfoAdapter {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
),
|
|
60
|
-
};
|
|
61
|
-
}
|
|
48
|
+
get applicationInfo(): ApplicationInfo {
|
|
49
|
+
return {
|
|
50
|
+
version: Application.nativeApplicationVersion ?? "0.0.0",
|
|
51
|
+
build_number: Number.parseInt(Application.nativeBuildVersion ?? "0", 10),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
62
54
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
55
|
+
get hardwareInfo(): HardwareInfo {
|
|
56
|
+
return {
|
|
57
|
+
device_name: Device.deviceName ?? "Unknown Device",
|
|
58
|
+
device_brand: Device.brand ?? "Unknown Brand",
|
|
59
|
+
device_type: mapDeviceType(Device.deviceType),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
70
62
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
get notificationsInfo(): NotificationsInfo {
|
|
80
|
-
return {
|
|
81
|
-
push: {
|
|
82
|
-
enabled: false,
|
|
83
|
-
granted: false,
|
|
84
|
-
token: null,
|
|
85
|
-
platform: NotificationPlatformEnum.EXPO,
|
|
86
|
-
},
|
|
87
|
-
};
|
|
88
|
-
}
|
|
63
|
+
get osInfo(): OSInfo {
|
|
64
|
+
return {
|
|
65
|
+
platform: mapPlatform(Platform.OS),
|
|
66
|
+
name: Device.osName ?? Platform.OS,
|
|
67
|
+
version: Device.osVersion ?? "0.0.0",
|
|
68
|
+
};
|
|
69
|
+
}
|
|
89
70
|
|
|
71
|
+
get notificationsInfo(): NotificationsInfo {
|
|
72
|
+
return {
|
|
73
|
+
push: {
|
|
74
|
+
enabled: false,
|
|
75
|
+
granted: false,
|
|
76
|
+
token: null,
|
|
77
|
+
platform: NotificationPlatformEnum.EXPO,
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
90
81
|
}
|