rampkit-expo-dev 0.0.70 → 0.0.71

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.
@@ -19,6 +19,7 @@ interface RampKitNativeModule {
19
19
  startTransactionObserver(appId: string): Promise<TransactionObserverResult>;
20
20
  stopTransactionObserver(): Promise<void>;
21
21
  clearTrackedTransactions(): Promise<number>;
22
+ recheckEntitlements(): Promise<EntitlementCheckResult>;
22
23
  trackPurchaseCompleted(productId: string, transactionId?: string, originalTransactionId?: string): Promise<void>;
23
24
  trackPurchaseFromProduct(productId: string): Promise<void>;
24
25
  }
@@ -100,6 +101,28 @@ export interface SentEventResult {
100
101
  currency?: string;
101
102
  environment?: string;
102
103
  }
104
+ export interface TrackedTransactionDetail {
105
+ productId: string;
106
+ transactionId: string;
107
+ originalTransactionId: string;
108
+ purchaseDate: string;
109
+ expirationDate?: string;
110
+ environment?: string;
111
+ status: "already_sent" | "skipped";
112
+ reason?: string;
113
+ }
114
+ export interface EntitlementCheckResult {
115
+ totalFound: number;
116
+ alreadyTracked: number;
117
+ newPurchases: number;
118
+ productIds: string[];
119
+ newProductIds: string[];
120
+ sentEvents?: SentEventResult[];
121
+ skippedReasons?: TrackedTransactionDetail[];
122
+ alreadyTrackedDetails?: TrackedTransactionDetail[];
123
+ trackedIdsCount: number;
124
+ error?: string;
125
+ }
103
126
  export interface TransactionObserverResult {
104
127
  configured: boolean;
105
128
  appId: string;
@@ -107,18 +130,7 @@ export interface TransactionObserverResult {
107
130
  previouslyTrackedCount: number;
108
131
  iOSVersion: string;
109
132
  listenerStarted: boolean;
110
- entitlementCheck?: {
111
- totalFound: number;
112
- alreadyTracked: number;
113
- newPurchases: number;
114
- productIds: string[];
115
- newProductIds: string[];
116
- sentEvents?: SentEventResult[];
117
- skippedReasons?: Array<{
118
- productId: string;
119
- reason: string;
120
- }>;
121
- };
133
+ entitlementCheck?: EntitlementCheckResult;
122
134
  error?: string;
123
135
  }
124
136
  export type ImpactStyle = "light" | "medium" | "heavy" | "rigid" | "soft";
@@ -224,4 +236,12 @@ export declare const TransactionObserver: {
224
236
  * @returns The number of tracked transactions that were cleared
225
237
  */
226
238
  clearTracked(): Promise<number>;
239
+ /**
240
+ * Re-check current entitlements for any new purchases
241
+ * Call this after onboarding finishes or after a paywall is shown
242
+ * to catch any purchases that may have been made
243
+ *
244
+ * @returns The entitlement check result with details of all transactions
245
+ */
246
+ recheck(): Promise<EntitlementCheckResult | null>;
227
247
  };
@@ -81,6 +81,17 @@ function createFallbackModule() {
81
81
  },
82
82
  async stopTransactionObserver() { },
83
83
  async clearTrackedTransactions() { return 0; },
84
+ async recheckEntitlements() {
85
+ return {
86
+ totalFound: 0,
87
+ alreadyTracked: 0,
88
+ newPurchases: 0,
89
+ productIds: [],
90
+ newProductIds: [],
91
+ trackedIdsCount: 0,
92
+ error: "Native module not available - using fallback"
93
+ };
94
+ },
84
95
  async trackPurchaseCompleted(_productId, _transactionId, _originalTransactionId) { },
85
96
  async trackPurchaseFromProduct(_productId) { },
86
97
  };
@@ -279,6 +290,72 @@ exports.Notifications = {
279
290
  // ============================================================================
280
291
  // Transaction Observer API (StoreKit 2 / Google Play Billing)
281
292
  // ============================================================================
293
+ /**
294
+ * Helper function to log entitlement check results with full details
295
+ */
296
+ function logEntitlementCheckResult(result, context) {
297
+ console.log("[RampKit] ");
298
+ console.log("[RampKit] ═══════════════════════════════════════════════════════════");
299
+ console.log(`[RampKit] 📊 ENTITLEMENT CHECK RESULT (${context})`);
300
+ console.log("[RampKit] ═══════════════════════════════════════════════════════════");
301
+ console.log("[RampKit] Total entitlements found:", result.totalFound);
302
+ console.log("[RampKit] Already sent to backend: ", result.alreadyTracked);
303
+ console.log("[RampKit] New events sent: ", result.newPurchases);
304
+ console.log("[RampKit] Tracked IDs in storage: ", result.trackedIdsCount);
305
+ console.log("[RampKit] Product IDs: ", result.productIds);
306
+ // Log already tracked transactions with full details
307
+ if (result.alreadyTrackedDetails && result.alreadyTrackedDetails.length > 0) {
308
+ console.log("[RampKit] ");
309
+ console.log("[RampKit] ✅ ALREADY SENT TRANSACTIONS:");
310
+ for (const tx of result.alreadyTrackedDetails) {
311
+ console.log("[RampKit] ────────────────────────────────────────");
312
+ console.log("[RampKit] 📦 Product:", tx.productId);
313
+ console.log("[RampKit] Transaction ID:", tx.transactionId);
314
+ console.log("[RampKit] Original Transaction ID:", tx.originalTransactionId);
315
+ console.log("[RampKit] Purchase Date:", tx.purchaseDate);
316
+ if (tx.expirationDate) {
317
+ console.log("[RampKit] Expiration Date:", tx.expirationDate);
318
+ }
319
+ if (tx.environment) {
320
+ console.log("[RampKit] Environment:", tx.environment);
321
+ }
322
+ console.log("[RampKit] Status: ✅ ALREADY SENT TO BACKEND");
323
+ }
324
+ }
325
+ // Log newly sent events
326
+ if (result.sentEvents && result.sentEvents.length > 0) {
327
+ console.log("[RampKit] ");
328
+ console.log("[RampKit] 📤 NEWLY SENT EVENTS:");
329
+ for (const event of result.sentEvents) {
330
+ console.log("[RampKit] ────────────────────────────────────────");
331
+ console.log("[RampKit] 📦 Product:", event.productId);
332
+ console.log("[RampKit] Transaction ID:", event.transactionId);
333
+ console.log("[RampKit] Original Transaction ID:", event.originalTransactionId);
334
+ console.log("[RampKit] Purchase Date:", event.purchaseDate);
335
+ console.log("[RampKit] Status:", event.status === "sent" ? "✅ SENT" : `❌ ${event.status.toUpperCase()}`);
336
+ if (event.httpStatus) {
337
+ console.log("[RampKit] HTTP Status:", event.httpStatus);
338
+ }
339
+ if (event.error) {
340
+ console.log("[RampKit] Error:", event.error);
341
+ }
342
+ }
343
+ }
344
+ // Log skipped transactions
345
+ if (result.skippedReasons && result.skippedReasons.length > 0) {
346
+ console.log("[RampKit] ");
347
+ console.log("[RampKit] ⏭️ SKIPPED TRANSACTIONS:");
348
+ for (const skipped of result.skippedReasons) {
349
+ console.log("[RampKit] - Product:", skipped.productId, "| Reason:", skipped.reason);
350
+ }
351
+ }
352
+ if (result.error) {
353
+ console.log("[RampKit] ");
354
+ console.log("[RampKit] ⚠️ Error:", result.error);
355
+ }
356
+ console.log("[RampKit] ═══════════════════════════════════════════════════════════");
357
+ console.log("[RampKit] ");
358
+ }
282
359
  exports.TransactionObserver = {
283
360
  /**
284
361
  * Start listening for purchase transactions
@@ -300,29 +377,7 @@ exports.TransactionObserver = {
300
377
  console.log("[RampKit] - previouslyTrackedCount:", result.previouslyTrackedCount);
301
378
  console.log("[RampKit] - listenerStarted:", result.listenerStarted);
302
379
  if (result.entitlementCheck) {
303
- console.log("[RampKit] 📊 Entitlement check results:");
304
- console.log("[RampKit] - totalFound:", result.entitlementCheck.totalFound);
305
- console.log("[RampKit] - alreadyTracked:", result.entitlementCheck.alreadyTracked);
306
- console.log("[RampKit] - newPurchases:", result.entitlementCheck.newPurchases);
307
- console.log("[RampKit] - productIds:", result.entitlementCheck.productIds);
308
- console.log("[RampKit] - newProductIds:", result.entitlementCheck.newProductIds);
309
- // Log sent events details
310
- if (result.entitlementCheck.sentEvents && result.entitlementCheck.sentEvents.length > 0) {
311
- console.log("[RampKit] 📤 Sent events:");
312
- for (const event of result.entitlementCheck.sentEvents) {
313
- console.log("[RampKit] - productId:", event.productId);
314
- console.log("[RampKit] transactionId:", event.transactionId);
315
- console.log("[RampKit] originalTransactionId:", event.originalTransactionId);
316
- console.log("[RampKit] status:", event.status);
317
- console.log("[RampKit] httpStatus:", event.httpStatus);
318
- if (event.error) {
319
- console.log("[RampKit] error:", event.error);
320
- }
321
- if (event.reason) {
322
- console.log("[RampKit] reason:", event.reason);
323
- }
324
- }
325
- }
380
+ logEntitlementCheckResult(result.entitlementCheck, "STARTUP");
326
381
  }
327
382
  if (result.error) {
328
383
  console.warn("[RampKit] ⚠️ Error:", result.error);
@@ -399,4 +454,23 @@ exports.TransactionObserver = {
399
454
  return 0;
400
455
  }
401
456
  },
457
+ /**
458
+ * Re-check current entitlements for any new purchases
459
+ * Call this after onboarding finishes or after a paywall is shown
460
+ * to catch any purchases that may have been made
461
+ *
462
+ * @returns The entitlement check result with details of all transactions
463
+ */
464
+ async recheck() {
465
+ console.log("[RampKit] 🔄 Re-checking entitlements...");
466
+ try {
467
+ const result = await RampKitNativeModule.recheckEntitlements();
468
+ logEntitlementCheckResult(result, "RECHECK");
469
+ return result;
470
+ }
471
+ catch (e) {
472
+ console.warn("[RampKit] ❌ Failed to recheck entitlements:", e);
473
+ return null;
474
+ }
475
+ },
402
476
  };
package/build/index.d.ts CHANGED
@@ -10,6 +10,6 @@ export { collectDeviceInfo, getSessionDurationSeconds, getSessionStartTime, buil
10
10
  export { default as RampKitNative } from "./RampKitNative";
11
11
  export type { NativeDeviceInfo, NativeLaunchData } from "./RampKitNative";
12
12
  export { Haptics, StoreReview, Notifications, TransactionObserver, isNativeModuleAvailable } from "./RampKitNative";
13
- export type { ImpactStyle, NotificationType, NotificationOptions, NotificationPermissionResult, TransactionObserverResult, SentEventResult } from "./RampKitNative";
13
+ export type { ImpactStyle, NotificationType, NotificationOptions, NotificationPermissionResult, TransactionObserverResult, SentEventResult, TrackedTransactionDetail, EntitlementCheckResult } from "./RampKitNative";
14
14
  export type { DeviceInfo, RampKitEvent, EventDevice, EventContext, RampKitConfig, RampKitEventName, RampKitContext, RampKitDeviceContext, RampKitUserContext, NavigationData, ScreenPosition, OnboardingResponse, AppSessionStartedProperties, OnboardingStartedProperties, OnboardingCompletedProperties, OnboardingAbandonedProperties, OptionSelectedProperties, NotificationsResponseProperties, PaywallShownProperties, PurchaseStartedProperties, PurchaseCompletedProperties, PurchaseFailedProperties, PurchaseRestoredProperties, } from "./types";
15
15
  export { SDK_VERSION, CAPABILITIES } from "./constants";
@@ -119,6 +119,15 @@ public class RampKitModule: Module {
119
119
  return count
120
120
  }
121
121
 
122
+ AsyncFunction("recheckEntitlements") { () -> [String: Any] in
123
+ print("[RampKit] 🔄 Re-checking entitlements (called from JS)...")
124
+ if #available(iOS 15.0, *) {
125
+ return await self.checkAndTrackCurrentEntitlements()
126
+ } else {
127
+ return ["error": "iOS 15+ required"]
128
+ }
129
+ }
130
+
122
131
  // ============================================================================
123
132
  // Manual Purchase Tracking (Fallback for Superwall/RevenueCat)
124
133
  // ============================================================================
@@ -480,6 +489,10 @@ public class RampKitModule: Module {
480
489
  @available(iOS 15.0, *)
481
490
  private func checkAndTrackCurrentEntitlements() async -> [String: Any] {
482
491
  print("[RampKit] 🔍 Checking current entitlements for missed purchases...")
492
+ print("[RampKit] 📚 Currently have \(trackedTransactionIds.count) tracked transaction IDs in storage")
493
+
494
+ let formatter = ISO8601DateFormatter()
495
+ formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
483
496
 
484
497
  var foundCount = 0
485
498
  var trackedCount = 0
@@ -488,6 +501,7 @@ public class RampKitModule: Module {
488
501
  var newProductIds: [String] = []
489
502
  var sentEvents: [[String: Any]] = []
490
503
  var skippedReasons: [[String: Any]] = []
504
+ var alreadyTrackedDetails: [[String: Any]] = [] // NEW: Details of already-tracked transactions
491
505
 
492
506
  for await result in Transaction.currentEntitlements {
493
507
  foundCount += 1
@@ -501,26 +515,51 @@ public class RampKitModule: Module {
501
515
  let originalId = String(transaction.originalID)
502
516
  let transactionId = String(transaction.id)
503
517
  productIds.append(transaction.productID)
504
- print("[RampKit] 📦 Found entitlement: \(transaction.productID), originalID: \(originalId), id: \(transactionId)")
518
+
519
+ // Build transaction details for logging
520
+ var txDetails: [String: Any] = [
521
+ "productId": transaction.productID,
522
+ "transactionId": transactionId,
523
+ "originalTransactionId": originalId,
524
+ "purchaseDate": formatter.string(from: transaction.purchaseDate)
525
+ ]
526
+ if let expirationDate = transaction.expirationDate {
527
+ txDetails["expirationDate"] = formatter.string(from: expirationDate)
528
+ }
529
+ if #available(iOS 16.0, *) {
530
+ txDetails["environment"] = transaction.environment.rawValue
531
+ }
532
+
533
+ print("[RampKit] 📦 Found entitlement:")
534
+ print("[RampKit] - productId: \(transaction.productID)")
535
+ print("[RampKit] - transactionId: \(transactionId)")
536
+ print("[RampKit] - originalTransactionId: \(originalId)")
537
+ print("[RampKit] - purchaseDate: \(formatter.string(from: transaction.purchaseDate))")
505
538
 
506
539
  // Check if we've already tracked this transaction
507
540
  if trackedTransactionIds.contains(originalId) {
508
541
  trackedCount += 1
509
- print("[RampKit] Already tracked: \(transaction.productID)")
542
+ txDetails["status"] = "already_sent"
543
+ alreadyTrackedDetails.append(txDetails)
544
+ print("[RampKit] ✅ STATUS: Already sent to backend (originalTransactionId in tracked set)")
510
545
  continue
511
546
  }
512
547
 
513
548
  // Skip renewals and revocations
514
549
  guard transaction.originalID == transaction.id,
515
550
  transaction.revocationDate == nil else {
516
- skippedReasons.append(["productId": transaction.productID, "reason": "renewal or revoked"])
551
+ let reason = transaction.revocationDate != nil ? "revoked" : "renewal"
552
+ txDetails["status"] = "skipped"
553
+ txDetails["reason"] = reason
554
+ skippedReasons.append(txDetails)
555
+ print("[RampKit] ⏭️ STATUS: Skipped (\(reason))")
517
556
  continue
518
557
  }
519
558
 
520
559
  // NEW transaction we haven't seen!
521
560
  newCount += 1
522
561
  newProductIds.append(transaction.productID)
523
- print("[RampKit] 🆕 NEW purchase detected: \(transaction.productID)")
562
+ print("[RampKit] 🆕 STATUS: NEW purchase - will send to backend now...")
524
563
 
525
564
  // Track it and get the result
526
565
  let sendResult = await self.handleTransactionWithResult(transaction)
@@ -530,16 +569,24 @@ public class RampKitModule: Module {
530
569
  if let status = sendResult["status"] as? String, status == "sent" {
531
570
  trackedTransactionIds.insert(originalId)
532
571
  saveTrackedTransactions()
533
- print("[RampKit] ✅ Marked as tracked after successful send: \(transaction.productID)")
572
+ print("[RampKit] ✅ Event sent successfully! HTTP status: \(sendResult["httpStatus"] ?? "unknown")")
573
+ print("[RampKit] ✅ Marked originalTransactionId \(originalId) as tracked")
534
574
  } else {
535
- print("[RampKit] ⚠️ Send failed, will retry next time: \(transaction.productID)")
575
+ print("[RampKit] Send failed: \(sendResult["error"] ?? "unknown error")")
576
+ print("[RampKit] ⚠️ Will retry on next app launch")
536
577
  }
537
578
  }
538
579
 
539
- print("[RampKit] 🔍 Entitlement check complete:")
540
- print("[RampKit] - Total found: \(foundCount)")
541
- print("[RampKit] - Already tracked: \(trackedCount)")
542
- print("[RampKit] - NEW (sent events): \(newCount)")
580
+ print("[RampKit] ")
581
+ print("[RampKit] 🔍 ═══════════════════════════════════════════")
582
+ print("[RampKit] 🔍 ENTITLEMENT CHECK SUMMARY:")
583
+ print("[RampKit] 🔍 ═══════════════════════════════════════════")
584
+ print("[RampKit] Total entitlements found: \(foundCount)")
585
+ print("[RampKit] Already sent to backend: \(trackedCount)")
586
+ print("[RampKit] Skipped (renewal/revoked): \(skippedReasons.count)")
587
+ print("[RampKit] NEW events sent: \(newCount)")
588
+ print("[RampKit] Tracked IDs in storage: \(trackedTransactionIds.count)")
589
+ print("[RampKit] 🔍 ═══════════════════════════════════════════")
543
590
 
544
591
  return [
545
592
  "totalFound": foundCount,
@@ -548,7 +595,9 @@ public class RampKitModule: Module {
548
595
  "productIds": productIds,
549
596
  "newProductIds": newProductIds,
550
597
  "sentEvents": sentEvents,
551
- "skippedReasons": skippedReasons
598
+ "skippedReasons": skippedReasons,
599
+ "alreadyTrackedDetails": alreadyTrackedDetails, // NEW
600
+ "trackedIdsCount": trackedTransactionIds.count
552
601
  ]
553
602
  }
554
603
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rampkit-expo-dev",
3
- "version": "0.0.70",
3
+ "version": "0.0.71",
4
4
  "description": "The Expo SDK for RampKit. Build, test, and personalize app onboardings with instant updates.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",