@clix-so/react-native-sdk 0.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.
- package/LICENSE +27 -0
- package/README.md +345 -0
- package/lib/module/core/Clix.js +217 -0
- package/lib/module/core/Clix.js.map +1 -0
- package/lib/module/core/ClixConfig.js +4 -0
- package/lib/module/core/ClixConfig.js.map +1 -0
- package/lib/module/core/ClixInitCoordinator.js +58 -0
- package/lib/module/core/ClixInitCoordinator.js.map +1 -0
- package/lib/module/core/ClixVersion.js +17 -0
- package/lib/module/core/ClixVersion.js.map +1 -0
- package/lib/module/index.js +7 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/models/ClixDevice.js +51 -0
- package/lib/module/models/ClixDevice.js.map +1 -0
- package/lib/module/models/ClixPushNotificationPayload.js +21 -0
- package/lib/module/models/ClixPushNotificationPayload.js.map +1 -0
- package/lib/module/models/ClixUserProperty.js +44 -0
- package/lib/module/models/ClixUserProperty.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/services/ClixAPIClient.js +172 -0
- package/lib/module/services/ClixAPIClient.js.map +1 -0
- package/lib/module/services/DeviceAPIService.js +112 -0
- package/lib/module/services/DeviceAPIService.js.map +1 -0
- package/lib/module/services/DeviceService.js +157 -0
- package/lib/module/services/DeviceService.js.map +1 -0
- package/lib/module/services/EventAPIService.js +36 -0
- package/lib/module/services/EventAPIService.js.map +1 -0
- package/lib/module/services/EventService.js +29 -0
- package/lib/module/services/EventService.js.map +1 -0
- package/lib/module/services/NotificationService.js +549 -0
- package/lib/module/services/NotificationService.js.map +1 -0
- package/lib/module/services/StorageService.js +76 -0
- package/lib/module/services/StorageService.js.map +1 -0
- package/lib/module/services/TokenService.js +71 -0
- package/lib/module/services/TokenService.js.map +1 -0
- package/lib/module/utils/ClixError.js +63 -0
- package/lib/module/utils/ClixError.js.map +1 -0
- package/lib/module/utils/UUID.js +28 -0
- package/lib/module/utils/UUID.js.map +1 -0
- package/lib/module/utils/logging/ClixLogger.js +55 -0
- package/lib/module/utils/logging/ClixLogger.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/core/Clix.d.ts +67 -0
- package/lib/typescript/src/core/Clix.d.ts.map +1 -0
- package/lib/typescript/src/core/ClixConfig.d.ts +9 -0
- package/lib/typescript/src/core/ClixConfig.d.ts.map +1 -0
- package/lib/typescript/src/core/ClixInitCoordinator.d.ts +16 -0
- package/lib/typescript/src/core/ClixInitCoordinator.d.ts.map +1 -0
- package/lib/typescript/src/core/ClixVersion.d.ts +6 -0
- package/lib/typescript/src/core/ClixVersion.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +5 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/models/ClixDevice.d.ts +42 -0
- package/lib/typescript/src/models/ClixDevice.d.ts.map +1 -0
- package/lib/typescript/src/models/ClixPushNotificationPayload.d.ts +23 -0
- package/lib/typescript/src/models/ClixPushNotificationPayload.d.ts.map +1 -0
- package/lib/typescript/src/models/ClixUserProperty.d.ts +19 -0
- package/lib/typescript/src/models/ClixUserProperty.d.ts.map +1 -0
- package/lib/typescript/src/services/ClixAPIClient.d.ts +35 -0
- package/lib/typescript/src/services/ClixAPIClient.d.ts.map +1 -0
- package/lib/typescript/src/services/DeviceAPIService.d.ts +13 -0
- package/lib/typescript/src/services/DeviceAPIService.d.ts.map +1 -0
- package/lib/typescript/src/services/DeviceService.d.ts +20 -0
- package/lib/typescript/src/services/DeviceService.d.ts.map +1 -0
- package/lib/typescript/src/services/EventAPIService.d.ts +7 -0
- package/lib/typescript/src/services/EventAPIService.d.ts.map +1 -0
- package/lib/typescript/src/services/EventService.d.ts +9 -0
- package/lib/typescript/src/services/EventService.d.ts.map +1 -0
- package/lib/typescript/src/services/NotificationService.d.ts +56 -0
- package/lib/typescript/src/services/NotificationService.d.ts.map +1 -0
- package/lib/typescript/src/services/StorageService.d.ts +10 -0
- package/lib/typescript/src/services/StorageService.d.ts.map +1 -0
- package/lib/typescript/src/services/TokenService.d.ts +15 -0
- package/lib/typescript/src/services/TokenService.d.ts.map +1 -0
- package/lib/typescript/src/utils/ClixError.d.ts +41 -0
- package/lib/typescript/src/utils/ClixError.d.ts.map +1 -0
- package/lib/typescript/src/utils/UUID.d.ts +14 -0
- package/lib/typescript/src/utils/UUID.d.ts.map +1 -0
- package/lib/typescript/src/utils/logging/ClixLogger.d.ts +18 -0
- package/lib/typescript/src/utils/logging/ClixLogger.d.ts.map +1 -0
- package/package.json +151 -0
- package/src/core/Clix.ts +256 -0
- package/src/core/ClixConfig.ts +9 -0
- package/src/core/ClixInitCoordinator.ts +65 -0
- package/src/core/ClixVersion.ts +17 -0
- package/src/index.ts +5 -0
- package/src/models/ClixDevice.ts +88 -0
- package/src/models/ClixPushNotificationPayload.ts +38 -0
- package/src/models/ClixUserProperty.ts +58 -0
- package/src/services/ClixAPIClient.ts +248 -0
- package/src/services/DeviceAPIService.ts +187 -0
- package/src/services/DeviceService.ts +204 -0
- package/src/services/EventAPIService.ts +48 -0
- package/src/services/EventService.ts +45 -0
- package/src/services/NotificationService.ts +730 -0
- package/src/services/StorageService.ts +84 -0
- package/src/services/TokenService.ts +84 -0
- package/src/utils/ClixError.ts +78 -0
- package/src/utils/UUID.ts +29 -0
- package/src/utils/logging/ClixLogger.ts +61 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import messaging from '@react-native-firebase/messaging';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
import DeviceInfo from 'react-native-device-info';
|
|
4
|
+
import { ClixVersion } from '../core/ClixVersion';
|
|
5
|
+
import { ClixDevice } from '../models/ClixDevice';
|
|
6
|
+
import { ClixUserProperty } from '../models/ClixUserProperty';
|
|
7
|
+
import { ClixError } from '../utils/ClixError';
|
|
8
|
+
import { ClixLogger } from '../utils/logging/ClixLogger';
|
|
9
|
+
import { UUID } from '../utils/UUID';
|
|
10
|
+
import { DeviceAPIService } from './DeviceAPIService';
|
|
11
|
+
import { StorageService } from './StorageService';
|
|
12
|
+
import { TokenService } from './TokenService';
|
|
13
|
+
|
|
14
|
+
export class DeviceService {
|
|
15
|
+
private static readonly DEVICE_ID_KEY = 'clix_device_id';
|
|
16
|
+
|
|
17
|
+
constructor(
|
|
18
|
+
private readonly storageService: StorageService,
|
|
19
|
+
private readonly tokenService: TokenService,
|
|
20
|
+
private readonly deviceAPIService: DeviceAPIService
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
async getCurrentDeviceId(): Promise<string> {
|
|
24
|
+
const existingId = await this.storageService.get<string>(
|
|
25
|
+
DeviceService.DEVICE_ID_KEY
|
|
26
|
+
);
|
|
27
|
+
if (existingId) {
|
|
28
|
+
return existingId;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const newId = UUID.generate();
|
|
32
|
+
await this.storageService.set(DeviceService.DEVICE_ID_KEY, newId);
|
|
33
|
+
return newId;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async setProjectUserId(projectUserId: string): Promise<void> {
|
|
37
|
+
try {
|
|
38
|
+
const deviceId = await this.getCurrentDeviceId();
|
|
39
|
+
await this.deviceAPIService.setProjectUserId(deviceId, projectUserId);
|
|
40
|
+
ClixLogger.debug(`Project user ID set: ${projectUserId}`);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
ClixLogger.error('Failed to set project user ID', error);
|
|
43
|
+
throw ClixError.unknownError({
|
|
44
|
+
reason: `Failed to set project user ID: ${error}`,
|
|
45
|
+
cause: error,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async removeProjectUserId(): Promise<void> {
|
|
51
|
+
try {
|
|
52
|
+
const deviceId = await this.getCurrentDeviceId();
|
|
53
|
+
await this.deviceAPIService.removeProjectUserId(deviceId);
|
|
54
|
+
ClixLogger.debug('Project user ID removed');
|
|
55
|
+
} catch (error) {
|
|
56
|
+
ClixLogger.error('Failed to remove project user ID', error);
|
|
57
|
+
throw ClixError.unknownError({
|
|
58
|
+
reason: `Failed to remove project user ID: ${error}`,
|
|
59
|
+
cause: error,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async updateUserProperties(properties: Record<string, any>): Promise<void> {
|
|
65
|
+
try {
|
|
66
|
+
const userProperties = Object.entries(properties).map(([key, value]) =>
|
|
67
|
+
ClixUserProperty.of(key, value)
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const deviceId = await this.getCurrentDeviceId();
|
|
71
|
+
await this.deviceAPIService.upsertUserProperties(
|
|
72
|
+
deviceId,
|
|
73
|
+
userProperties
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
ClixLogger.debug(
|
|
77
|
+
`User properties updated: ${Object.keys(properties).join(', ')}`
|
|
78
|
+
);
|
|
79
|
+
} catch (error) {
|
|
80
|
+
ClixLogger.error('Failed to update user properties', error);
|
|
81
|
+
throw ClixError.unknownError({
|
|
82
|
+
reason: `Failed to update user properties: ${error}`,
|
|
83
|
+
cause: error,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async removeUserProperties(names: string[]): Promise<void> {
|
|
89
|
+
try {
|
|
90
|
+
const deviceId = await this.getCurrentDeviceId();
|
|
91
|
+
await this.deviceAPIService.removeUserProperties(deviceId, names);
|
|
92
|
+
|
|
93
|
+
ClixLogger.debug(`User properties removed: ${names.join(', ')}`);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
ClixLogger.error('Failed to remove user properties', error);
|
|
96
|
+
throw ClixError.unknownError({
|
|
97
|
+
reason: `Failed to remove user properties: ${error}`,
|
|
98
|
+
cause: error,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async upsertToken(token: string, tokenType: string = 'FCM'): Promise<void> {
|
|
104
|
+
try {
|
|
105
|
+
await this.tokenService.saveToken(token);
|
|
106
|
+
|
|
107
|
+
const deviceId = await this.getCurrentDeviceId();
|
|
108
|
+
const device = await this.createDevice(deviceId, token);
|
|
109
|
+
|
|
110
|
+
await this.deviceAPIService.registerDevice(device);
|
|
111
|
+
|
|
112
|
+
ClixLogger.debug(`Token upserted: ${tokenType}`);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
ClixLogger.error('Failed to upsert token', error);
|
|
115
|
+
|
|
116
|
+
// Don't throw for token upsert failures during initialization
|
|
117
|
+
// This allows the SDK to continue initializing even if token registration fails
|
|
118
|
+
if (
|
|
119
|
+
error instanceof Error &&
|
|
120
|
+
error.message.includes('crypto.getRandomValues')
|
|
121
|
+
) {
|
|
122
|
+
ClixLogger.warn(
|
|
123
|
+
'Token upsert failed due to crypto polyfill issue, will retry later'
|
|
124
|
+
);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
throw ClixError.unknownError({
|
|
129
|
+
reason: `Failed to upsert token: ${error}`,
|
|
130
|
+
cause: error,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private async getPushPermissionStatus(): Promise<boolean> {
|
|
136
|
+
try {
|
|
137
|
+
// First check stored permission status
|
|
138
|
+
const storedStatus = await this.storageService.get<string>(
|
|
139
|
+
'notification_permission_status'
|
|
140
|
+
);
|
|
141
|
+
if (storedStatus === 'authorized' || storedStatus === 'provisional') {
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// If no stored status, check current Firebase messaging permission
|
|
146
|
+
const authStatus = await messaging().hasPermission();
|
|
147
|
+
const isGranted =
|
|
148
|
+
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
|
|
149
|
+
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
|
|
150
|
+
|
|
151
|
+
ClixLogger.debug(
|
|
152
|
+
`Push permission status: ${isGranted ? 'granted' : 'denied'}`
|
|
153
|
+
);
|
|
154
|
+
return isGranted;
|
|
155
|
+
} catch (error) {
|
|
156
|
+
ClixLogger.warn(
|
|
157
|
+
'Failed to get push permission status, defaulting to false',
|
|
158
|
+
error
|
|
159
|
+
);
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async createDevice(deviceId: string, token?: string): Promise<ClixDevice> {
|
|
165
|
+
const platform = DeviceInfo.getSystemName();
|
|
166
|
+
const osName = DeviceInfo.getSystemName();
|
|
167
|
+
const osVersion = DeviceInfo.getSystemVersion();
|
|
168
|
+
const manufacturer = await DeviceInfo.getManufacturer();
|
|
169
|
+
const model = DeviceInfo.getModel();
|
|
170
|
+
const appName = DeviceInfo.getApplicationName();
|
|
171
|
+
const appVersion = DeviceInfo.getVersion();
|
|
172
|
+
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
173
|
+
const locale = Intl.DateTimeFormat().resolvedOptions().locale || 'en-US';
|
|
174
|
+
const localeLanguage = locale.split('-')[0] || 'en';
|
|
175
|
+
const localeRegion = locale.split('-')[1] || 'US';
|
|
176
|
+
let adId: string | undefined;
|
|
177
|
+
const isPushPermissionGranted = await this.getPushPermissionStatus();
|
|
178
|
+
const sdkVersion = await ClixVersion.getVersion();
|
|
179
|
+
|
|
180
|
+
return new ClixDevice({
|
|
181
|
+
id: deviceId,
|
|
182
|
+
platform,
|
|
183
|
+
model,
|
|
184
|
+
manufacturer,
|
|
185
|
+
osName,
|
|
186
|
+
osVersion,
|
|
187
|
+
localeRegion,
|
|
188
|
+
localeLanguage,
|
|
189
|
+
timezone,
|
|
190
|
+
appName,
|
|
191
|
+
appVersion,
|
|
192
|
+
sdkType: 'react-native',
|
|
193
|
+
sdkVersion,
|
|
194
|
+
adId,
|
|
195
|
+
isPushPermissionGranted,
|
|
196
|
+
pushToken: token,
|
|
197
|
+
pushTokenType: token
|
|
198
|
+
? Platform.OS === 'ios'
|
|
199
|
+
? 'APNS'
|
|
200
|
+
: 'FCM'
|
|
201
|
+
: undefined,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ClixLogger } from '../utils/logging/ClixLogger';
|
|
2
|
+
import { ClixAPIClient } from './ClixAPIClient';
|
|
3
|
+
|
|
4
|
+
export class EventAPIService {
|
|
5
|
+
constructor(private readonly apiClient: ClixAPIClient) {}
|
|
6
|
+
|
|
7
|
+
async trackEvent(
|
|
8
|
+
deviceId: string,
|
|
9
|
+
name: string,
|
|
10
|
+
properties: Record<string, any>,
|
|
11
|
+
messageId?: string
|
|
12
|
+
): Promise<void> {
|
|
13
|
+
try {
|
|
14
|
+
ClixLogger.debug(`Tracking event: ${name} for device: ${deviceId}`);
|
|
15
|
+
|
|
16
|
+
const eventRequestBody = {
|
|
17
|
+
device_id: deviceId,
|
|
18
|
+
name: name,
|
|
19
|
+
event_property: {
|
|
20
|
+
custom_properties: properties,
|
|
21
|
+
...(messageId && { message_id: messageId }),
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const response = await this.apiClient.post('/events', {
|
|
26
|
+
body: {
|
|
27
|
+
events: [eventRequestBody],
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (response.status < 200 || response.status >= 300) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
`HTTP ${response.status}: ${JSON.stringify(response.data)}`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
ClixLogger.debug(
|
|
38
|
+
`Event tracked successfully: ${name} for device: ${deviceId}`
|
|
39
|
+
);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
ClixLogger.error(
|
|
42
|
+
`Failed to track event: ${name} for device: ${deviceId}`,
|
|
43
|
+
error
|
|
44
|
+
);
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ClixLogger } from '../utils/logging/ClixLogger';
|
|
2
|
+
import { DeviceService } from './DeviceService';
|
|
3
|
+
import { EventAPIService } from './EventAPIService';
|
|
4
|
+
|
|
5
|
+
export class EventService {
|
|
6
|
+
constructor(
|
|
7
|
+
private readonly eventAPIService: EventAPIService,
|
|
8
|
+
private readonly deviceService: DeviceService
|
|
9
|
+
) {}
|
|
10
|
+
|
|
11
|
+
async trackEvent(
|
|
12
|
+
name: string,
|
|
13
|
+
properties?: Record<string, any>,
|
|
14
|
+
messageId?: string
|
|
15
|
+
): Promise<void> {
|
|
16
|
+
try {
|
|
17
|
+
ClixLogger.debug(`Tracking event: ${name}`);
|
|
18
|
+
|
|
19
|
+
const deviceId = await this.deviceService.getCurrentDeviceId();
|
|
20
|
+
|
|
21
|
+
const cleanProperties: Record<string, any> = {};
|
|
22
|
+
if (properties) {
|
|
23
|
+
Object.entries(properties).forEach(([key, value]) => {
|
|
24
|
+
if (value !== null && value !== undefined) {
|
|
25
|
+
cleanProperties[key] = value;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
await this.eventAPIService.trackEvent(
|
|
31
|
+
deviceId,
|
|
32
|
+
name,
|
|
33
|
+
cleanProperties,
|
|
34
|
+
messageId
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
ClixLogger.debug(`Event tracked successfully: ${name}`);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
ClixLogger.error(
|
|
40
|
+
`Failed to track event '${name}': ${error}. Make sure Clix.initialize() has been called.`
|
|
41
|
+
);
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|