@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.
Files changed (100) hide show
  1. package/LICENSE +27 -0
  2. package/README.md +345 -0
  3. package/lib/module/core/Clix.js +217 -0
  4. package/lib/module/core/Clix.js.map +1 -0
  5. package/lib/module/core/ClixConfig.js +4 -0
  6. package/lib/module/core/ClixConfig.js.map +1 -0
  7. package/lib/module/core/ClixInitCoordinator.js +58 -0
  8. package/lib/module/core/ClixInitCoordinator.js.map +1 -0
  9. package/lib/module/core/ClixVersion.js +17 -0
  10. package/lib/module/core/ClixVersion.js.map +1 -0
  11. package/lib/module/index.js +7 -0
  12. package/lib/module/index.js.map +1 -0
  13. package/lib/module/models/ClixDevice.js +51 -0
  14. package/lib/module/models/ClixDevice.js.map +1 -0
  15. package/lib/module/models/ClixPushNotificationPayload.js +21 -0
  16. package/lib/module/models/ClixPushNotificationPayload.js.map +1 -0
  17. package/lib/module/models/ClixUserProperty.js +44 -0
  18. package/lib/module/models/ClixUserProperty.js.map +1 -0
  19. package/lib/module/package.json +1 -0
  20. package/lib/module/services/ClixAPIClient.js +172 -0
  21. package/lib/module/services/ClixAPIClient.js.map +1 -0
  22. package/lib/module/services/DeviceAPIService.js +112 -0
  23. package/lib/module/services/DeviceAPIService.js.map +1 -0
  24. package/lib/module/services/DeviceService.js +157 -0
  25. package/lib/module/services/DeviceService.js.map +1 -0
  26. package/lib/module/services/EventAPIService.js +36 -0
  27. package/lib/module/services/EventAPIService.js.map +1 -0
  28. package/lib/module/services/EventService.js +29 -0
  29. package/lib/module/services/EventService.js.map +1 -0
  30. package/lib/module/services/NotificationService.js +549 -0
  31. package/lib/module/services/NotificationService.js.map +1 -0
  32. package/lib/module/services/StorageService.js +76 -0
  33. package/lib/module/services/StorageService.js.map +1 -0
  34. package/lib/module/services/TokenService.js +71 -0
  35. package/lib/module/services/TokenService.js.map +1 -0
  36. package/lib/module/utils/ClixError.js +63 -0
  37. package/lib/module/utils/ClixError.js.map +1 -0
  38. package/lib/module/utils/UUID.js +28 -0
  39. package/lib/module/utils/UUID.js.map +1 -0
  40. package/lib/module/utils/logging/ClixLogger.js +55 -0
  41. package/lib/module/utils/logging/ClixLogger.js.map +1 -0
  42. package/lib/typescript/package.json +1 -0
  43. package/lib/typescript/src/core/Clix.d.ts +67 -0
  44. package/lib/typescript/src/core/Clix.d.ts.map +1 -0
  45. package/lib/typescript/src/core/ClixConfig.d.ts +9 -0
  46. package/lib/typescript/src/core/ClixConfig.d.ts.map +1 -0
  47. package/lib/typescript/src/core/ClixInitCoordinator.d.ts +16 -0
  48. package/lib/typescript/src/core/ClixInitCoordinator.d.ts.map +1 -0
  49. package/lib/typescript/src/core/ClixVersion.d.ts +6 -0
  50. package/lib/typescript/src/core/ClixVersion.d.ts.map +1 -0
  51. package/lib/typescript/src/index.d.ts +5 -0
  52. package/lib/typescript/src/index.d.ts.map +1 -0
  53. package/lib/typescript/src/models/ClixDevice.d.ts +42 -0
  54. package/lib/typescript/src/models/ClixDevice.d.ts.map +1 -0
  55. package/lib/typescript/src/models/ClixPushNotificationPayload.d.ts +23 -0
  56. package/lib/typescript/src/models/ClixPushNotificationPayload.d.ts.map +1 -0
  57. package/lib/typescript/src/models/ClixUserProperty.d.ts +19 -0
  58. package/lib/typescript/src/models/ClixUserProperty.d.ts.map +1 -0
  59. package/lib/typescript/src/services/ClixAPIClient.d.ts +35 -0
  60. package/lib/typescript/src/services/ClixAPIClient.d.ts.map +1 -0
  61. package/lib/typescript/src/services/DeviceAPIService.d.ts +13 -0
  62. package/lib/typescript/src/services/DeviceAPIService.d.ts.map +1 -0
  63. package/lib/typescript/src/services/DeviceService.d.ts +20 -0
  64. package/lib/typescript/src/services/DeviceService.d.ts.map +1 -0
  65. package/lib/typescript/src/services/EventAPIService.d.ts +7 -0
  66. package/lib/typescript/src/services/EventAPIService.d.ts.map +1 -0
  67. package/lib/typescript/src/services/EventService.d.ts +9 -0
  68. package/lib/typescript/src/services/EventService.d.ts.map +1 -0
  69. package/lib/typescript/src/services/NotificationService.d.ts +56 -0
  70. package/lib/typescript/src/services/NotificationService.d.ts.map +1 -0
  71. package/lib/typescript/src/services/StorageService.d.ts +10 -0
  72. package/lib/typescript/src/services/StorageService.d.ts.map +1 -0
  73. package/lib/typescript/src/services/TokenService.d.ts +15 -0
  74. package/lib/typescript/src/services/TokenService.d.ts.map +1 -0
  75. package/lib/typescript/src/utils/ClixError.d.ts +41 -0
  76. package/lib/typescript/src/utils/ClixError.d.ts.map +1 -0
  77. package/lib/typescript/src/utils/UUID.d.ts +14 -0
  78. package/lib/typescript/src/utils/UUID.d.ts.map +1 -0
  79. package/lib/typescript/src/utils/logging/ClixLogger.d.ts +18 -0
  80. package/lib/typescript/src/utils/logging/ClixLogger.d.ts.map +1 -0
  81. package/package.json +151 -0
  82. package/src/core/Clix.ts +256 -0
  83. package/src/core/ClixConfig.ts +9 -0
  84. package/src/core/ClixInitCoordinator.ts +65 -0
  85. package/src/core/ClixVersion.ts +17 -0
  86. package/src/index.ts +5 -0
  87. package/src/models/ClixDevice.ts +88 -0
  88. package/src/models/ClixPushNotificationPayload.ts +38 -0
  89. package/src/models/ClixUserProperty.ts +58 -0
  90. package/src/services/ClixAPIClient.ts +248 -0
  91. package/src/services/DeviceAPIService.ts +187 -0
  92. package/src/services/DeviceService.ts +204 -0
  93. package/src/services/EventAPIService.ts +48 -0
  94. package/src/services/EventService.ts +45 -0
  95. package/src/services/NotificationService.ts +730 -0
  96. package/src/services/StorageService.ts +84 -0
  97. package/src/services/TokenService.ts +84 -0
  98. package/src/utils/ClixError.ts +78 -0
  99. package/src/utils/UUID.ts +29 -0
  100. 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
+ }