@umituz/react-native-subscription 2.14.57 → 2.14.59

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-subscription",
3
- "version": "2.14.57",
3
+ "version": "2.14.59",
4
4
  "description": "Complete subscription management with RevenueCat, paywall UI, and credits system for React Native apps",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
package/src/index.ts CHANGED
@@ -33,6 +33,7 @@ export {
33
33
  export {
34
34
  initializeSubscription,
35
35
  type SubscriptionInitConfig,
36
+ type CreditPackageConfig,
36
37
  } from "./infrastructure/services/SubscriptionInitializer";
37
38
 
38
39
  export { useSubscription } from "./presentation/hooks/useSubscription";
@@ -4,8 +4,9 @@
4
4
  * Apps just call initializeSubscription with config
5
5
  */
6
6
 
7
+ import type { CustomerInfo } from "react-native-purchases";
7
8
  import type { CreditsConfig } from "../../domain/entities/Credits";
8
- import { configureCreditsRepository } from "../repositories/CreditsRepositoryProvider";
9
+ import { configureCreditsRepository, getCreditsRepository } from "../repositories/CreditsRepositoryProvider";
9
10
  import { SubscriptionManager } from "../../revenuecat/infrastructure/managers/SubscriptionManager";
10
11
  import { configureAuthProvider } from "../../presentation/hooks/useAuthAwarePurchase";
11
12
 
@@ -14,6 +15,13 @@ export interface FirebaseAuthLike {
14
15
  onAuthStateChanged: (callback: (user: { uid: string; isAnonymous: boolean } | null) => void) => () => void;
15
16
  }
16
17
 
18
+ export interface CreditPackageConfig {
19
+ /** Identifier pattern to match credit packages (e.g., "credit") */
20
+ identifierPattern?: string;
21
+ /** Map of productId to credit amounts */
22
+ amounts?: Record<string, number>;
23
+ }
24
+
17
25
  export interface SubscriptionInitConfig {
18
26
  apiKey: string;
19
27
  testStoreKey?: string;
@@ -22,8 +30,10 @@ export interface SubscriptionInitConfig {
22
30
  getAnonymousUserId: () => Promise<string>;
23
31
  getFirebaseAuth: () => FirebaseAuthLike | null;
24
32
  showAuthModal: () => void;
33
+ /** Callback after credits are updated (for cache invalidation) */
25
34
  onCreditsUpdated?: (userId: string) => void;
26
- onCreditRenewal?: (userId: string, productId: string, renewalId: string) => Promise<void>;
35
+ /** Credit package configuration for consumable purchases */
36
+ creditPackages?: CreditPackageConfig;
27
37
  timeoutMs?: number;
28
38
  authStateTimeoutMs?: number;
29
39
  }
@@ -59,6 +69,15 @@ const waitForAuthState = async (
59
69
  });
60
70
  };
61
71
 
72
+ /**
73
+ * Check if a product is a credit package
74
+ */
75
+ const isCreditPackage = (productId: string, pattern?: string): boolean => {
76
+ const patternToUse = pattern || "credit";
77
+ return productId.toLowerCase().includes(patternToUse.toLowerCase());
78
+ };
79
+
80
+
62
81
  export const initializeSubscription = async (
63
82
  config: SubscriptionInitConfig,
64
83
  ): Promise<void> => {
@@ -71,7 +90,7 @@ export const initializeSubscription = async (
71
90
  getFirebaseAuth,
72
91
  showAuthModal,
73
92
  onCreditsUpdated,
74
- onCreditRenewal,
93
+ creditPackages,
75
94
  timeoutMs = 10000,
76
95
  authStateTimeoutMs = 2000,
77
96
  } = config;
@@ -82,13 +101,87 @@ export const initializeSubscription = async (
82
101
 
83
102
  configureCreditsRepository(credits);
84
103
 
104
+ // Build consumable product identifiers from credit package pattern
105
+ const consumableIdentifiers: string[] = [];
106
+ if (creditPackages?.identifierPattern) {
107
+ consumableIdentifiers.push(creditPackages.identifierPattern);
108
+ } else {
109
+ consumableIdentifiers.push("credit");
110
+ }
111
+
112
+ // Create onPurchaseCompleted handler for credit packages
113
+ const handlePurchaseCompleted = async (
114
+ userId: string,
115
+ productId: string,
116
+ _customerInfo: CustomerInfo
117
+ ): Promise<void> => {
118
+ const isCredit = isCreditPackage(productId, creditPackages?.identifierPattern);
119
+
120
+ if (!isCredit) {
121
+ return;
122
+ }
123
+
124
+ try {
125
+ const repository = getCreditsRepository();
126
+ const purchaseId = `purchase_${productId}_${Date.now()}`;
127
+
128
+ await repository.initializeCredits(userId, purchaseId, productId);
129
+
130
+ if (__DEV__) {
131
+ console.log("[SubscriptionInitializer] Credits added for purchase:", {
132
+ userId,
133
+ productId,
134
+ purchaseId,
135
+ });
136
+ }
137
+
138
+ if (onCreditsUpdated) {
139
+ onCreditsUpdated(userId);
140
+ }
141
+ } catch (error) {
142
+ if (__DEV__) {
143
+ console.error("[SubscriptionInitializer] Failed to add credits:", error);
144
+ }
145
+ }
146
+ };
147
+
148
+ // Create onCreditRenewal handler for subscription renewals
149
+ const handleCreditRenewal = async (
150
+ userId: string,
151
+ productId: string,
152
+ renewalId: string
153
+ ): Promise<void> => {
154
+ try {
155
+ const repository = getCreditsRepository();
156
+ await repository.initializeCredits(userId, renewalId, productId);
157
+
158
+ if (__DEV__) {
159
+ console.log("[SubscriptionInitializer] Credits renewed:", {
160
+ userId,
161
+ productId,
162
+ renewalId,
163
+ });
164
+ }
165
+
166
+ if (onCreditsUpdated) {
167
+ onCreditsUpdated(userId);
168
+ }
169
+ } catch (error) {
170
+ if (__DEV__) {
171
+ console.error("[SubscriptionInitializer] Failed to renew credits:", error);
172
+ }
173
+ }
174
+ };
175
+
85
176
  SubscriptionManager.configure({
86
177
  config: {
87
178
  apiKey,
88
179
  testStoreKey,
89
180
  entitlementIdentifier: entitlementId,
90
- onCreditRenewal,
181
+ consumableProductIdentifiers: consumableIdentifiers,
182
+ onCreditRenewal: handleCreditRenewal,
91
183
  onCreditsUpdated,
184
+ onPurchaseCompleted: handlePurchaseCompleted,
92
185
  },
93
186
  apiKey,
94
187
  getAnonymousUserId,
@@ -54,6 +54,12 @@ export async function handlePurchase(
54
54
  const customerInfo = purchaseResult.customerInfo;
55
55
 
56
56
  if (isConsumable) {
57
+ await notifyPurchaseCompleted(
58
+ deps.config,
59
+ userId,
60
+ pkg.product.identifier,
61
+ customerInfo
62
+ );
57
63
  return {
58
64
  success: true,
59
65
  isPremium: false,