rampkit-expo-dev 0.0.19 → 0.0.22

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,419 @@
1
+ "use strict";
2
+ /**
3
+ * RampKit Event Manager
4
+ * Handles event tracking for the /app-user-events endpoint
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.EventManager = exports.eventManager = void 0;
41
+ const Crypto = __importStar(require("expo-crypto"));
42
+ const constants_1 = require("./constants");
43
+ /**
44
+ * Generate a UUID v4 using expo-crypto
45
+ */
46
+ async function generateEventId() {
47
+ try {
48
+ const bytes = (await Crypto.getRandomBytesAsync(16));
49
+ bytes[6] = (bytes[6] & 0x0f) | 0x40;
50
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
51
+ const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0"));
52
+ return (hex[0] +
53
+ hex[1] +
54
+ hex[2] +
55
+ hex[3] +
56
+ "-" +
57
+ hex[4] +
58
+ hex[5] +
59
+ "-" +
60
+ hex[6] +
61
+ hex[7] +
62
+ "-" +
63
+ hex[8] +
64
+ hex[9] +
65
+ "-" +
66
+ hex[10] +
67
+ hex[11] +
68
+ hex[12] +
69
+ hex[13] +
70
+ hex[14] +
71
+ hex[15]);
72
+ }
73
+ catch (_a) {
74
+ // Fallback using Math.random
75
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
76
+ const r = (Math.random() * 16) | 0;
77
+ const v = c === "x" ? r : (r & 0x3) | 0x8;
78
+ return v.toString(16);
79
+ });
80
+ }
81
+ }
82
+ /**
83
+ * Synchronous UUID generator for when async is not practical
84
+ */
85
+ function generateEventIdSync() {
86
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
87
+ const r = (Math.random() * 16) | 0;
88
+ const v = c === "x" ? r : (r & 0x3) | 0x8;
89
+ return v.toString(16);
90
+ });
91
+ }
92
+ class EventManager {
93
+ constructor() {
94
+ this.appId = null;
95
+ this.appUserId = null;
96
+ this.sessionId = null;
97
+ this.device = null;
98
+ this.baseContext = {};
99
+ // Current context tracking
100
+ this.currentScreenName = null;
101
+ this.currentFlowId = null;
102
+ this.currentVariantId = null;
103
+ this.currentPaywallId = null;
104
+ this.currentPlacement = null;
105
+ // Onboarding tracking
106
+ this.onboardingStartTime = null;
107
+ this.currentOnboardingId = null;
108
+ // Initialization state
109
+ this.initialized = false;
110
+ }
111
+ static get instance() {
112
+ if (!this._instance) {
113
+ this._instance = new EventManager();
114
+ }
115
+ return this._instance;
116
+ }
117
+ /**
118
+ * Initialize the event manager with device info
119
+ */
120
+ initialize(appId, deviceInfo) {
121
+ this.appId = appId;
122
+ this.appUserId = deviceInfo.appUserId;
123
+ this.sessionId = deviceInfo.appSessionId;
124
+ this.device = {
125
+ platform: deviceInfo.platform,
126
+ platformVersion: deviceInfo.platformVersion,
127
+ deviceModel: deviceInfo.deviceModel,
128
+ sdkVersion: deviceInfo.sdkVersion,
129
+ appVersion: deviceInfo.appVersion,
130
+ buildNumber: deviceInfo.buildNumber,
131
+ };
132
+ this.baseContext = {
133
+ locale: deviceInfo.deviceLocale,
134
+ regionCode: deviceInfo.regionCode,
135
+ };
136
+ this.initialized = true;
137
+ console.log("[RampKit] EventManager: Initialized");
138
+ }
139
+ /**
140
+ * Check if the event manager is initialized
141
+ */
142
+ isInitialized() {
143
+ return this.initialized;
144
+ }
145
+ /**
146
+ * Set current screen context
147
+ */
148
+ setCurrentScreen(screenName) {
149
+ this.currentScreenName = screenName;
150
+ }
151
+ /**
152
+ * Set current flow context (e.g., onboarding flow ID)
153
+ */
154
+ setCurrentFlow(flowId, variantId) {
155
+ this.currentFlowId = flowId;
156
+ if (variantId !== undefined) {
157
+ this.currentVariantId = variantId;
158
+ }
159
+ }
160
+ /**
161
+ * Set current paywall context
162
+ */
163
+ setCurrentPaywall(paywallId, placement) {
164
+ this.currentPaywallId = paywallId;
165
+ if (placement !== undefined) {
166
+ this.currentPlacement = placement;
167
+ }
168
+ }
169
+ /**
170
+ * Start onboarding tracking
171
+ */
172
+ startOnboardingTracking(onboardingId) {
173
+ this.currentOnboardingId = onboardingId;
174
+ this.onboardingStartTime = new Date();
175
+ this.currentFlowId = onboardingId;
176
+ }
177
+ /**
178
+ * Get onboarding duration in seconds
179
+ */
180
+ getOnboardingDurationSeconds() {
181
+ if (!this.onboardingStartTime)
182
+ return 0;
183
+ return Math.floor((Date.now() - this.onboardingStartTime.getTime()) / 1000);
184
+ }
185
+ /**
186
+ * End onboarding tracking
187
+ */
188
+ endOnboardingTracking() {
189
+ this.currentOnboardingId = null;
190
+ this.onboardingStartTime = null;
191
+ this.currentFlowId = null;
192
+ }
193
+ /**
194
+ * Get current onboarding ID
195
+ */
196
+ getCurrentOnboardingId() {
197
+ return this.currentOnboardingId;
198
+ }
199
+ /**
200
+ * Track an event
201
+ */
202
+ async track(eventName, properties = {}, contextOverrides) {
203
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
204
+ if (!this.initialized || !this.appId || !this.appUserId || !this.sessionId || !this.device) {
205
+ console.warn("[RampKit] EventManager: Not initialized, skipping event:", eventName);
206
+ return;
207
+ }
208
+ const eventId = generateEventIdSync();
209
+ const occurredAt = new Date().toISOString();
210
+ const context = {
211
+ screenName: (_a = contextOverrides === null || contextOverrides === void 0 ? void 0 : contextOverrides.screenName) !== null && _a !== void 0 ? _a : this.currentScreenName,
212
+ flowId: (_b = contextOverrides === null || contextOverrides === void 0 ? void 0 : contextOverrides.flowId) !== null && _b !== void 0 ? _b : this.currentFlowId,
213
+ variantId: (_c = contextOverrides === null || contextOverrides === void 0 ? void 0 : contextOverrides.variantId) !== null && _c !== void 0 ? _c : this.currentVariantId,
214
+ paywallId: (_d = contextOverrides === null || contextOverrides === void 0 ? void 0 : contextOverrides.paywallId) !== null && _d !== void 0 ? _d : this.currentPaywallId,
215
+ locale: (_f = (_e = contextOverrides === null || contextOverrides === void 0 ? void 0 : contextOverrides.locale) !== null && _e !== void 0 ? _e : this.baseContext.locale) !== null && _f !== void 0 ? _f : null,
216
+ regionCode: (_h = (_g = contextOverrides === null || contextOverrides === void 0 ? void 0 : contextOverrides.regionCode) !== null && _g !== void 0 ? _g : this.baseContext.regionCode) !== null && _h !== void 0 ? _h : null,
217
+ placement: (_j = contextOverrides === null || contextOverrides === void 0 ? void 0 : contextOverrides.placement) !== null && _j !== void 0 ? _j : this.currentPlacement,
218
+ };
219
+ const event = {
220
+ appId: this.appId,
221
+ appUserId: this.appUserId,
222
+ eventId,
223
+ eventName,
224
+ sessionId: this.sessionId,
225
+ occurredAt,
226
+ device: this.device,
227
+ context,
228
+ properties,
229
+ };
230
+ // Fire and forget - don't await
231
+ this.sendEvent(event);
232
+ }
233
+ /**
234
+ * Send event to backend (fire and forget)
235
+ */
236
+ async sendEvent(event) {
237
+ try {
238
+ const url = `${constants_1.ENDPOINTS.BASE_URL}${constants_1.ENDPOINTS.APP_USER_EVENTS}`;
239
+ const response = await fetch(url, {
240
+ method: "POST",
241
+ headers: {
242
+ "Content-Type": "application/json",
243
+ apikey: constants_1.SUPABASE_ANON_KEY,
244
+ Authorization: `Bearer ${constants_1.SUPABASE_ANON_KEY}`,
245
+ },
246
+ body: JSON.stringify(event),
247
+ });
248
+ if (!response.ok) {
249
+ console.warn("[RampKit] EventManager: Failed to send event:", event.eventName, response.status);
250
+ }
251
+ else {
252
+ console.log("[RampKit] EventManager: Event sent:", event.eventName);
253
+ }
254
+ }
255
+ catch (error) {
256
+ console.warn("[RampKit] EventManager: Error sending event:", event.eventName, error);
257
+ }
258
+ }
259
+ // ============================================================================
260
+ // Convenience methods for specific event types
261
+ // ============================================================================
262
+ /**
263
+ * Track app session started
264
+ */
265
+ trackAppSessionStarted(isFirstLaunch, launchCount) {
266
+ this.track("app_session_started", { isFirstLaunch, launchCount });
267
+ }
268
+ /**
269
+ * Track app backgrounded
270
+ */
271
+ trackAppBackgrounded(sessionDurationSeconds) {
272
+ this.track("app_backgrounded", { sessionDurationSeconds });
273
+ }
274
+ /**
275
+ * Track app foregrounded
276
+ */
277
+ trackAppForegrounded() {
278
+ this.track("app_foregrounded", {});
279
+ }
280
+ /**
281
+ * Track screen view
282
+ */
283
+ trackScreenView(screenName, referrer) {
284
+ this.setCurrentScreen(screenName);
285
+ this.track("screen_view", { screenName, referrer });
286
+ }
287
+ /**
288
+ * Track CTA tap
289
+ */
290
+ trackCtaTap(buttonId, buttonText) {
291
+ this.track("cta_tap", { buttonId, buttonText });
292
+ }
293
+ /**
294
+ * Track onboarding started
295
+ */
296
+ trackOnboardingStarted(onboardingId, totalSteps) {
297
+ this.startOnboardingTracking(onboardingId);
298
+ this.track("onboarding_started", { onboardingId, totalSteps });
299
+ }
300
+ /**
301
+ * Track onboarding screen viewed
302
+ */
303
+ trackOnboardingScreenViewed(screenName, screenIndex, totalScreens, onboardingId) {
304
+ this.setCurrentScreen(screenName);
305
+ this.track("onboarding_screen_viewed", {
306
+ onboardingId: onboardingId || this.currentOnboardingId,
307
+ screenName,
308
+ screenIndex,
309
+ totalScreens,
310
+ });
311
+ }
312
+ /**
313
+ * Track onboarding question answered
314
+ */
315
+ trackOnboardingQuestionAnswered(questionId, answer, questionText, onboardingId) {
316
+ this.track("onboarding_question_answered", {
317
+ onboardingId: onboardingId || this.currentOnboardingId,
318
+ questionId,
319
+ answer,
320
+ questionText,
321
+ });
322
+ }
323
+ /**
324
+ * Track onboarding completed
325
+ */
326
+ trackOnboardingCompleted(completedSteps, totalSteps, onboardingId) {
327
+ const timeToCompleteSeconds = this.getOnboardingDurationSeconds();
328
+ this.track("onboarding_completed", {
329
+ onboardingId: onboardingId || this.currentOnboardingId,
330
+ timeToCompleteSeconds,
331
+ completedSteps,
332
+ totalSteps,
333
+ });
334
+ this.endOnboardingTracking();
335
+ }
336
+ /**
337
+ * Track onboarding abandoned
338
+ */
339
+ trackOnboardingAbandoned(reason, lastScreenName, onboardingId) {
340
+ const timeSpentSeconds = this.getOnboardingDurationSeconds();
341
+ this.track("onboarding_abandoned", {
342
+ onboardingId: onboardingId || this.currentOnboardingId,
343
+ reason,
344
+ lastScreenName,
345
+ timeSpentSeconds,
346
+ });
347
+ this.endOnboardingTracking();
348
+ }
349
+ /**
350
+ * Track notification prompt shown
351
+ */
352
+ trackNotificationsPromptShown() {
353
+ this.track("notifications_prompt_shown", {});
354
+ }
355
+ /**
356
+ * Track notification response
357
+ */
358
+ trackNotificationsResponse(status) {
359
+ this.track("notifications_response", { status });
360
+ }
361
+ /**
362
+ * Track paywall shown
363
+ */
364
+ trackPaywallShown(paywallId, placement, products) {
365
+ this.setCurrentPaywall(paywallId, placement);
366
+ this.track("paywall_shown", { paywallId, placement, products }, { paywallId, placement });
367
+ }
368
+ /**
369
+ * Track paywall primary action tap
370
+ */
371
+ trackPaywallPrimaryActionTap(paywallId, productId) {
372
+ this.track("paywall_primary_action_tap", { paywallId, productId }, { paywallId });
373
+ }
374
+ /**
375
+ * Track paywall closed
376
+ */
377
+ trackPaywallClosed(paywallId, reason) {
378
+ this.track("paywall_closed", { paywallId, reason }, { paywallId });
379
+ this.setCurrentPaywall(null);
380
+ }
381
+ /**
382
+ * Track purchase started
383
+ */
384
+ trackPurchaseStarted(productId, amount, currency) {
385
+ this.track("purchase_started", { productId, amount, currency });
386
+ }
387
+ /**
388
+ * Track purchase completed
389
+ */
390
+ trackPurchaseCompleted(properties) {
391
+ this.track("purchase_completed", properties);
392
+ }
393
+ /**
394
+ * Track purchase failed
395
+ */
396
+ trackPurchaseFailed(productId, errorCode, errorMessage) {
397
+ this.track("purchase_failed", { productId, errorCode, errorMessage });
398
+ }
399
+ /**
400
+ * Reset the event manager (e.g., on logout)
401
+ */
402
+ reset() {
403
+ this.appId = null;
404
+ this.appUserId = null;
405
+ this.sessionId = null;
406
+ this.device = null;
407
+ this.baseContext = {};
408
+ this.currentScreenName = null;
409
+ this.currentFlowId = null;
410
+ this.currentVariantId = null;
411
+ this.currentPaywallId = null;
412
+ this.currentPlacement = null;
413
+ this.onboardingStartTime = null;
414
+ this.currentOnboardingId = null;
415
+ this.initialized = false;
416
+ }
417
+ }
418
+ exports.EventManager = EventManager;
419
+ exports.eventManager = EventManager.instance;
@@ -1,27 +1,109 @@
1
+ /**
2
+ * RampKit Core SDK
3
+ * Main SDK class for RampKit Expo integration
4
+ */
5
+ import { DeviceInfo, RampKitConfig, EventContext } from "./types";
1
6
  export declare class RampKitCore {
2
7
  private static _instance;
3
8
  private config;
4
9
  private onboardingData;
5
10
  private userId;
6
11
  private appId;
12
+ private deviceInfo;
7
13
  private onOnboardingFinished?;
8
14
  private onShowPaywall?;
9
- private static readonly MANIFEST_BASE_URL;
15
+ private appStateSubscription;
16
+ private lastAppState;
17
+ private initialized;
10
18
  static get instance(): RampKitCore;
11
- init(config: {
12
- appId: string;
13
- apiKey?: string;
14
- environment?: string;
15
- autoShowOnboarding?: boolean;
16
- onOnboardingFinished?: (payload?: any) => void;
17
- onShowPaywall?: (payload?: any) => void;
18
- showPaywall?: (payload?: any) => void;
19
- }): Promise<void>;
19
+ /**
20
+ * Initialize the RampKit SDK
21
+ */
22
+ init(config: RampKitConfig): Promise<void>;
23
+ /**
24
+ * Send user/device data to the /app-users endpoint
25
+ */
26
+ private sendUserDataToBackend;
27
+ /**
28
+ * Setup app state listener for background/foreground tracking
29
+ */
30
+ private setupAppStateListener;
31
+ /**
32
+ * Get the onboarding data
33
+ */
20
34
  getOnboardingData(): any;
35
+ /**
36
+ * Get the user ID
37
+ */
21
38
  getUserId(): string | null;
39
+ /**
40
+ * Get the device info
41
+ */
42
+ getDeviceInfo(): DeviceInfo | null;
43
+ /**
44
+ * Check if SDK is initialized
45
+ */
46
+ isInitialized(): boolean;
47
+ /**
48
+ * Show the onboarding overlay
49
+ */
22
50
  showOnboarding(opts?: {
23
51
  onShowPaywall?: (payload?: any) => void;
24
52
  showPaywall?: (payload?: any) => void;
25
53
  }): void;
54
+ /**
55
+ * Close the onboarding overlay
56
+ */
26
57
  closeOnboarding(): void;
58
+ /**
59
+ * Track a custom event
60
+ */
61
+ trackEvent(eventName: string, properties?: Record<string, any>, context?: Partial<EventContext>): void;
62
+ /**
63
+ * Track a screen view
64
+ */
65
+ trackScreenView(screenName: string, referrer?: string): void;
66
+ /**
67
+ * Track a CTA tap
68
+ */
69
+ trackCtaTap(buttonId: string, buttonText?: string): void;
70
+ /**
71
+ * Track paywall shown
72
+ */
73
+ trackPaywallShown(paywallId: string, placement?: string, products?: Array<{
74
+ productId: string;
75
+ price?: number;
76
+ currency?: string;
77
+ }>): void;
78
+ /**
79
+ * Track paywall primary action tap
80
+ */
81
+ trackPaywallPrimaryActionTap(paywallId: string, productId?: string): void;
82
+ /**
83
+ * Track paywall closed
84
+ */
85
+ trackPaywallClosed(paywallId: string, reason: "dismissed" | "purchased" | "backgrounded"): void;
86
+ /**
87
+ * Track purchase started
88
+ */
89
+ trackPurchaseStarted(productId: string, amount?: number, currency?: string): void;
90
+ /**
91
+ * Track purchase completed
92
+ */
93
+ trackPurchaseCompleted(properties: {
94
+ productId: string;
95
+ amount: number;
96
+ currency: string;
97
+ transactionId: string;
98
+ originalTransactionId?: string;
99
+ purchaseDate?: string;
100
+ }): void;
101
+ /**
102
+ * Track purchase failed
103
+ */
104
+ trackPurchaseFailed(productId: string, errorCode: string, errorMessage: string): void;
105
+ /**
106
+ * Cleanup SDK resources
107
+ */
108
+ cleanup(): void;
27
109
  }