@bubblsdk/react-native-sdk 3.0.0

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.
@@ -0,0 +1,83 @@
1
+ #import <React/RCTBridgeModule.h>
2
+ #import <React/RCTEventEmitter.h>
3
+
4
+ @interface RCT_EXTERN_MODULE(BubblSdk, RCTEventEmitter)
5
+
6
+ RCT_EXTERN_METHOD(boot:(NSDictionary *)config
7
+ resolver:(RCTPromiseResolveBlock)resolve
8
+ rejecter:(RCTPromiseRejectBlock)reject)
9
+ RCT_EXTERN_METHOD(shutdown:(RCTPromiseResolveBlock)resolve
10
+ rejecter:(RCTPromiseRejectBlock)reject)
11
+ RCT_EXTERN_METHOD(startLocationTracking:(RCTPromiseResolveBlock)resolve
12
+ rejecter:(RCTPromiseRejectBlock)reject)
13
+ RCT_EXTERN_METHOD(stopLocationTracking:(RCTPromiseResolveBlock)resolve
14
+ rejecter:(RCTPromiseRejectBlock)reject)
15
+ RCT_EXTERN_METHOD(refresh:(RCTPromiseResolveBlock)resolve
16
+ rejecter:(RCTPromiseRejectBlock)reject)
17
+ RCT_EXTERN_METHOD(refreshGeofence:(double)latitude
18
+ longitude:(double)longitude
19
+ resolver:(RCTPromiseResolveBlock)resolve
20
+ rejecter:(RCTPromiseRejectBlock)reject)
21
+ RCT_EXTERN_METHOD(handleLocationUpdate:(double)latitude
22
+ longitude:(double)longitude
23
+ resolver:(RCTPromiseResolveBlock)resolve
24
+ rejecter:(RCTPromiseRejectBlock)reject)
25
+ RCT_EXTERN_METHOD(refreshPush:(RCTPromiseResolveBlock)resolve
26
+ rejecter:(RCTPromiseRejectBlock)reject)
27
+ RCT_EXTERN_METHOD(getConfiguration:(RCTPromiseResolveBlock)resolve
28
+ rejecter:(RCTPromiseRejectBlock)reject)
29
+ RCT_EXTERN_METHOD(getPrivacyText:(RCTPromiseResolveBlock)resolve
30
+ rejecter:(RCTPromiseRejectBlock)reject)
31
+ RCT_EXTERN_METHOD(updateSegments:(NSArray *)tags
32
+ resolver:(RCTPromiseResolveBlock)resolve
33
+ rejecter:(RCTPromiseRejectBlock)reject)
34
+ RCT_EXTERN_METHOD(setCorrelationId:(NSString *)value
35
+ resolver:(RCTPromiseResolveBlock)resolve
36
+ rejecter:(RCTPromiseRejectBlock)reject)
37
+ RCT_EXTERN_METHOD(clearCorrelationId:(RCTPromiseResolveBlock)resolve
38
+ rejecter:(RCTPromiseRejectBlock)reject)
39
+ RCT_EXTERN_METHOD(setDefaultNotificationModalEnabled:(BOOL)enabled
40
+ resolver:(RCTPromiseResolveBlock)resolve
41
+ rejecter:(RCTPromiseRejectBlock)reject)
42
+ RCT_EXTERN_METHOD(registerPushToken:(NSString *)token
43
+ resolver:(RCTPromiseResolveBlock)resolve
44
+ rejecter:(RCTPromiseRejectBlock)reject)
45
+ RCT_EXTERN_METHOD(handleFirebasePayload:(NSDictionary *)payload
46
+ resolver:(RCTPromiseResolveBlock)resolve
47
+ rejecter:(RCTPromiseRejectBlock)reject)
48
+ RCT_EXTERN_METHOD(showNotification:(NSDictionary *)payload
49
+ resolver:(RCTPromiseResolveBlock)resolve
50
+ rejecter:(RCTPromiseRejectBlock)reject)
51
+ RCT_EXTERN_METHOD(handleNotificationPayload:(NSDictionary *)payload
52
+ resolver:(RCTPromiseResolveBlock)resolve
53
+ rejecter:(RCTPromiseRejectBlock)reject)
54
+ RCT_EXTERN_METHOD(handleNotificationOpen:(NSDictionary *)payload
55
+ action:(NSString *)action
56
+ resolver:(RCTPromiseResolveBlock)resolve
57
+ rejecter:(RCTPromiseRejectBlock)reject)
58
+ RCT_EXTERN_METHOD(openNotificationModal:(NSDictionary *)payload
59
+ action:(NSString *)action
60
+ resolver:(RCTPromiseResolveBlock)resolve
61
+ rejecter:(RCTPromiseRejectBlock)reject)
62
+ RCT_EXTERN_METHOD(handleNotificationCta:(NSDictionary *)payload
63
+ action:(NSString *)action
64
+ resolver:(RCTPromiseResolveBlock)resolve
65
+ rejecter:(RCTPromiseRejectBlock)reject)
66
+ RCT_EXTERN_METHOD(handleNotificationMediaViewed:(NSDictionary *)payload
67
+ resolver:(RCTPromiseResolveBlock)resolve
68
+ rejecter:(RCTPromiseRejectBlock)reject)
69
+ RCT_EXTERN_METHOD(handleNotificationSurveyRequested:(NSDictionary *)payload
70
+ resolver:(RCTPromiseResolveBlock)resolve
71
+ rejecter:(RCTPromiseRejectBlock)reject)
72
+ RCT_EXTERN_METHOD(track:(NSDictionary *)event
73
+ resolver:(RCTPromiseResolveBlock)resolve
74
+ rejecter:(RCTPromiseRejectBlock)reject)
75
+ RCT_EXTERN_METHOD(submitSurveyResponse:(NSDictionary *)response
76
+ resolver:(RCTPromiseResolveBlock)resolve
77
+ rejecter:(RCTPromiseRejectBlock)reject)
78
+ RCT_EXTERN_METHOD(flush:(RCTPromiseResolveBlock)resolve
79
+ rejecter:(RCTPromiseRejectBlock)reject)
80
+ RCT_EXTERN_METHOD(diagnostics:(RCTPromiseResolveBlock)resolve
81
+ rejecter:(RCTPromiseRejectBlock)reject)
82
+
83
+ @end
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@bubblsdk/react-native-sdk",
3
+ "version": "3.0.0",
4
+ "description": "React Native wrapper for Bubbl SDK v3 native Android and iOS cores.",
5
+ "main": "src/index.ts",
6
+ "module": "src/index.ts",
7
+ "types": "src/index.ts",
8
+ "react-native": "src/index.ts",
9
+ "source": "src/index.ts",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://devops.bubbl.tech/bubbl/renewed-sdk.git",
13
+ "directory": "react-native"
14
+ },
15
+ "license": "SEE LICENSE IN LICENSE",
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "scripts": {
20
+ "build": "node ../scripts/validate-wrapper-surfaces.mjs --react-native",
21
+ "test": "node ../scripts/validate-wrapper-surfaces.mjs --react-native",
22
+ "typecheck": "node ../scripts/validate-wrapper-surfaces.mjs --react-native"
23
+ },
24
+ "files": [
25
+ "android/build.gradle",
26
+ "android/src",
27
+ "ios/BubblSdk.swift",
28
+ "ios/BubblSdkBridge.m",
29
+ "src",
30
+ "BubblReactNativeSdk.podspec",
31
+ "react-native.config.js",
32
+ "README.md",
33
+ "CHANGELOG.md",
34
+ "LICENSE"
35
+ ],
36
+ "peerDependencies": {
37
+ "react": "*",
38
+ "react-native": ">=0.76"
39
+ },
40
+ "codegenConfig": {
41
+ "name": "BubblSdkSpec",
42
+ "type": "modules",
43
+ "jsSrcsDir": "src/specs",
44
+ "android": {
45
+ "javaPackageName": "tech.bubbl.reactnative"
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ dependency: {
3
+ platforms: {
4
+ android: {
5
+ sourceDir: './android',
6
+ packageImportPath: 'import tech.bubbl.reactnative.BubblSdkPackage;',
7
+ packageInstance: 'new BubblSdkPackage()',
8
+ },
9
+ },
10
+ },
11
+ };
package/src/index.ts ADDED
@@ -0,0 +1,292 @@
1
+ import {
2
+ NativeEventEmitter,
3
+ NativeModules,
4
+ type EmitterSubscription,
5
+ } from 'react-native';
6
+ import NativeBubblSdk from './specs/NativeBubblSdk';
7
+
8
+ export type BubblEnvironment = 'development' | 'nightly' | 'staging' | 'production';
9
+ export type BubblLogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug';
10
+ export type BubblNotificationRenderingMode = 'sdkDefault' | 'hostRendered' | 'eventOnly';
11
+ export type BubblNotificationSource = 'firebase' | 'apns' | 'runtime' | 'geofence' | 'manual';
12
+
13
+ export type BubblConfig = {
14
+ apiKey: string;
15
+ environment?: BubblEnvironment;
16
+ runtimeBaseUrl?: string | null;
17
+ transmissionBaseUrl?: string | null;
18
+ ingestBaseUrl?: string | null;
19
+ segments?: string[];
20
+ correlationId?: string | null;
21
+ defaultDistanceMeters?: number;
22
+ refreshIntervalSeconds?: number;
23
+ enablePushHandling?: boolean;
24
+ enableLocationTracking?: boolean;
25
+ notificationRenderingMode?: BubblNotificationRenderingMode;
26
+ enableDefaultNotificationModal?: boolean;
27
+ enableDefaultSurveyUi?: boolean;
28
+ logLevel?: BubblLogLevel;
29
+ };
30
+
31
+ export type BubblBootResult = {
32
+ ready: boolean;
33
+ fromCache: boolean;
34
+ deviceRegistered: boolean;
35
+ requiresPermission: string[];
36
+ warnings: string[];
37
+ };
38
+
39
+ export type BubblLocation = {
40
+ latitude: number;
41
+ longitude: number;
42
+ };
43
+
44
+ export type BubblGeofenceTransitionType = 'enter' | 'exit';
45
+
46
+ export type BubblGeofenceTransition = {
47
+ type: BubblGeofenceTransitionType;
48
+ campaignId?: string | null;
49
+ locationId?: string | null;
50
+ location: BubblLocation;
51
+ };
52
+
53
+ export type BubblGeofenceVertex = BubblLocation;
54
+
55
+ export type BubblGeofencePolygon = {
56
+ campaignId?: string | null;
57
+ campaignName?: string | null;
58
+ locationId?: string | null;
59
+ vertices: BubblGeofenceVertex[];
60
+ };
61
+
62
+ export type BubblGeofenceCircle = {
63
+ campaignId?: string | null;
64
+ campaignName?: string | null;
65
+ locationId?: string | null;
66
+ center: BubblGeofenceVertex;
67
+ radius: number;
68
+ };
69
+
70
+ export type BubblGeofenceSnapshot = {
71
+ stats: {
72
+ campaignsTotal: number;
73
+ polygonsTotal: number;
74
+ };
75
+ polygons: BubblGeofencePolygon[];
76
+ circles: BubblGeofenceCircle[];
77
+ };
78
+
79
+ export type BubblTrackEvent = {
80
+ type: string;
81
+ activity: string;
82
+ locationId?: string | null;
83
+ curatedNotificationId?: string | null;
84
+ latitude?: number | null;
85
+ longitude?: number | null;
86
+ };
87
+
88
+ export type BubblSurveyAnswer = {
89
+ questionId: string;
90
+ type: string;
91
+ value?: string | null;
92
+ choiceIds?: string[];
93
+ };
94
+
95
+ export type BubblSurveyResponse = {
96
+ curatedNotificationId: string;
97
+ locationId?: string | null;
98
+ answers: BubblSurveyAnswer[];
99
+ };
100
+
101
+ export type BubblNotificationPayload = {
102
+ id: string;
103
+ title: string;
104
+ body: string;
105
+ source?: BubblNotificationSource;
106
+ locationId?: string | null;
107
+ curatedNotificationId?: string | null;
108
+ correlationId?: string | null;
109
+ media?: BubblNotificationMedia | null;
110
+ cta?: BubblNotificationCta | null;
111
+ survey?: BubblNotificationSurvey | null;
112
+ raw?: Record<string, string>;
113
+ };
114
+
115
+ export type BubblNotificationMedia = {
116
+ url: string;
117
+ type?: string | null;
118
+ altText?: string | null;
119
+ };
120
+
121
+ export type BubblNotificationCta = {
122
+ label: string;
123
+ url?: string | null;
124
+ action?: string | null;
125
+ };
126
+
127
+ export type BubblNotificationSurvey = {
128
+ questions?: BubblSurveyQuestion[];
129
+ };
130
+
131
+ export type BubblSurveyQuestion = {
132
+ id: string;
133
+ title: string;
134
+ type: string;
135
+ choices?: BubblSurveyChoice[];
136
+ };
137
+
138
+ export type BubblSurveyChoice = {
139
+ id: string;
140
+ label: string;
141
+ };
142
+
143
+ export type BubblNotificationDisplayResult = {
144
+ displayed: boolean;
145
+ reason?: string | null;
146
+ };
147
+
148
+ export type BubblDiagnostics = {
149
+ sdkVersion: string;
150
+ platform: 'react-native';
151
+ booted: boolean;
152
+ pendingIngestCount: number;
153
+ pushTokenSuffix?: string | null;
154
+ };
155
+
156
+ export type BubblEvent =
157
+ | { type: 'ready' }
158
+ | { type: 'diagnostic'; diagnostics: BubblDiagnostics }
159
+ | { type: 'notificationReceived'; payload: BubblNotificationPayload }
160
+ | { type: 'notificationDisplayed'; payload: BubblNotificationPayload }
161
+ | { type: 'notificationTapped'; payload: BubblNotificationPayload; action?: string | null }
162
+ | { type: 'notificationCtaTapped'; payload: BubblNotificationPayload; action?: string | null }
163
+ | { type: 'notificationMediaViewed'; payload: BubblNotificationPayload }
164
+ | { type: 'notificationSurveyRequested'; payload: BubblNotificationPayload }
165
+ | { type: 'locationUpdated'; location: BubblLocation }
166
+ | { type: 'geofenceSnapshot'; snapshot: BubblGeofenceSnapshot }
167
+ | { type: 'geofenceEntered'; transition: BubblGeofenceTransition }
168
+ | { type: 'geofenceExited'; transition: BubblGeofenceTransition }
169
+ | { type: 'error'; code: string; message: string };
170
+
171
+ export type BubblEventSubscription = Pick<EmitterSubscription, 'remove'>;
172
+
173
+ const EVENT_NAME = 'BubblSdkEvent';
174
+
175
+ type NativeBubblSdkShape = NonNullable<typeof NativeBubblSdk>;
176
+
177
+ function nativeModule(): NativeBubblSdkShape {
178
+ const module = NativeBubblSdk ?? NativeModules.BubblSdk;
179
+ if (!module) {
180
+ throw new Error('BubblSdk native module is not linked.');
181
+ }
182
+
183
+ return module as NativeBubblSdkShape;
184
+ }
185
+
186
+ function eventEmitter(): NativeEventEmitter {
187
+ return new NativeEventEmitter(NativeModules.BubblSdk ?? (NativeBubblSdk as object | null));
188
+ }
189
+
190
+ function validateApiKey(config: BubblConfig): void {
191
+ if (!config.apiKey?.trim()) {
192
+ throw new Error('apiKey is required');
193
+ }
194
+ }
195
+
196
+ export const Bubbl = {
197
+ async boot(config: BubblConfig): Promise<BubblBootResult> {
198
+ validateApiKey(config);
199
+ return nativeModule().boot(config) as Promise<BubblBootResult>;
200
+ },
201
+ async shutdown(): Promise<void> {
202
+ return nativeModule().shutdown();
203
+ },
204
+ async startLocationTracking(): Promise<void> {
205
+ return nativeModule().startLocationTracking();
206
+ },
207
+ async stopLocationTracking(): Promise<void> {
208
+ return nativeModule().stopLocationTracking();
209
+ },
210
+ async refresh(): Promise<void> {
211
+ return nativeModule().refresh();
212
+ },
213
+ async refreshGeofence(location: BubblLocation): Promise<void> {
214
+ return nativeModule().refreshGeofence(location.latitude, location.longitude);
215
+ },
216
+ async handleLocationUpdate(location: BubblLocation): Promise<void> {
217
+ return nativeModule().handleLocationUpdate(location.latitude, location.longitude);
218
+ },
219
+ async refreshPush(): Promise<void> {
220
+ return nativeModule().refreshPush();
221
+ },
222
+ async getConfiguration(): Promise<Record<string, unknown> | null> {
223
+ return nativeModule().getConfiguration() as Promise<Record<string, unknown> | null>;
224
+ },
225
+ async getPrivacyText(): Promise<string> {
226
+ return nativeModule().getPrivacyText();
227
+ },
228
+ async updateSegments(tags: string[]): Promise<void> {
229
+ return nativeModule().updateSegments(tags);
230
+ },
231
+ async setCorrelationId(value: string): Promise<void> {
232
+ return nativeModule().setCorrelationId(value);
233
+ },
234
+ async clearCorrelationId(): Promise<void> {
235
+ return nativeModule().clearCorrelationId();
236
+ },
237
+ async setDefaultNotificationModalEnabled(enabled: boolean): Promise<void> {
238
+ return nativeModule().setDefaultNotificationModalEnabled(enabled);
239
+ },
240
+ async disableDefaultNotificationModal(): Promise<void> {
241
+ return nativeModule().setDefaultNotificationModalEnabled(false);
242
+ },
243
+ async enableDefaultNotificationModal(): Promise<void> {
244
+ return nativeModule().setDefaultNotificationModalEnabled(true);
245
+ },
246
+ async registerPushToken(token: string): Promise<void> {
247
+ return nativeModule().registerPushToken(token);
248
+ },
249
+ async handleFirebasePayload(payload: Record<string, string>): Promise<BubblNotificationPayload | null> {
250
+ return nativeModule().handleFirebasePayload(payload) as Promise<BubblNotificationPayload | null>;
251
+ },
252
+ async showNotification(payload: BubblNotificationPayload): Promise<BubblNotificationDisplayResult> {
253
+ return nativeModule().showNotification(payload) as Promise<BubblNotificationDisplayResult>;
254
+ },
255
+ async handleNotificationPayload(payload: BubblNotificationPayload): Promise<BubblNotificationDisplayResult> {
256
+ return nativeModule().handleNotificationPayload(payload) as Promise<BubblNotificationDisplayResult>;
257
+ },
258
+ async handleNotificationOpen(payload: BubblNotificationPayload, action?: string | null): Promise<void> {
259
+ return nativeModule().handleNotificationOpen(payload, action);
260
+ },
261
+ async openNotificationModal(payload: BubblNotificationPayload, action?: string | null): Promise<boolean> {
262
+ return nativeModule().openNotificationModal(payload, action);
263
+ },
264
+ async handleNotificationCta(payload: BubblNotificationPayload, action?: string | null): Promise<void> {
265
+ return nativeModule().handleNotificationCta(payload, action);
266
+ },
267
+ async handleNotificationMediaViewed(payload: BubblNotificationPayload): Promise<void> {
268
+ return nativeModule().handleNotificationMediaViewed(payload);
269
+ },
270
+ async handleNotificationSurveyRequested(payload: BubblNotificationPayload): Promise<void> {
271
+ return nativeModule().handleNotificationSurveyRequested(payload);
272
+ },
273
+ async track(event: BubblTrackEvent): Promise<void> {
274
+ return nativeModule().track(event);
275
+ },
276
+ async submitSurveyResponse(response: BubblSurveyResponse): Promise<void> {
277
+ return nativeModule().submitSurveyResponse(response);
278
+ },
279
+ async flush(): Promise<{ pendingCount: number }> {
280
+ return nativeModule().flush() as Promise<{ pendingCount: number }>;
281
+ },
282
+ async diagnostics(): Promise<BubblDiagnostics> {
283
+ return nativeModule().diagnostics() as Promise<BubblDiagnostics>;
284
+ },
285
+ events: {
286
+ addListener(listener: (event: BubblEvent) => void): BubblEventSubscription {
287
+ return eventEmitter().addListener(EVENT_NAME, listener);
288
+ },
289
+ },
290
+ };
291
+
292
+ export default Bubbl;
@@ -0,0 +1,52 @@
1
+ import type { TurboModule } from 'react-native';
2
+ import { TurboModuleRegistry } from 'react-native';
3
+
4
+ export type BubblBootOptions = {
5
+ apiKey: string;
6
+ environment?: string;
7
+ runtimeBaseUrl?: string | null;
8
+ transmissionBaseUrl?: string | null;
9
+ ingestBaseUrl?: string | null;
10
+ segments?: string[];
11
+ correlationId?: string | null;
12
+ defaultDistanceMeters?: number;
13
+ refreshIntervalSeconds?: number;
14
+ enablePushHandling?: boolean;
15
+ enableLocationTracking?: boolean;
16
+ notificationRenderingMode?: string;
17
+ enableDefaultNotificationModal?: boolean;
18
+ enableDefaultSurveyUi?: boolean;
19
+ logLevel?: string;
20
+ };
21
+
22
+ export interface Spec extends TurboModule {
23
+ boot(config: BubblBootOptions): Promise<Object>;
24
+ shutdown(): Promise<void>;
25
+ startLocationTracking(): Promise<void>;
26
+ stopLocationTracking(): Promise<void>;
27
+ refresh(): Promise<void>;
28
+ refreshGeofence(latitude: number, longitude: number): Promise<void>;
29
+ handleLocationUpdate(latitude: number, longitude: number): Promise<void>;
30
+ refreshPush(): Promise<void>;
31
+ getConfiguration(): Promise<Object | null>;
32
+ getPrivacyText(): Promise<string>;
33
+ updateSegments(tags: string[]): Promise<void>;
34
+ setCorrelationId(value: string): Promise<void>;
35
+ clearCorrelationId(): Promise<void>;
36
+ setDefaultNotificationModalEnabled(enabled: boolean): Promise<void>;
37
+ registerPushToken(token: string): Promise<void>;
38
+ handleFirebasePayload(payload: Object): Promise<Object | null>;
39
+ showNotification(payload: Object): Promise<Object>;
40
+ handleNotificationPayload(payload: Object): Promise<Object>;
41
+ handleNotificationOpen(payload: Object, action?: string | null): Promise<void>;
42
+ openNotificationModal(payload: Object, action?: string | null): Promise<boolean>;
43
+ handleNotificationCta(payload: Object, action?: string | null): Promise<void>;
44
+ handleNotificationMediaViewed(payload: Object): Promise<void>;
45
+ handleNotificationSurveyRequested(payload: Object): Promise<void>;
46
+ track(event: Object): Promise<void>;
47
+ submitSurveyResponse(response: Object): Promise<void>;
48
+ flush(): Promise<Object>;
49
+ diagnostics(): Promise<Object>;
50
+ }
51
+
52
+ export default TurboModuleRegistry.get<Spec>('BubblSdk');