@umituz/react-native-subscription 2.27.12 → 2.27.14

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.27.12",
3
+ "version": "2.27.14",
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
@@ -97,6 +97,15 @@ export * from "./utils";
97
97
  // RevenueCat
98
98
  export * from "./revenuecat";
99
99
 
100
+ // App Service Helpers (for configureAppServices)
101
+ export {
102
+ createCreditService,
103
+ createPaywallService,
104
+ type CreditServiceConfig,
105
+ type ICreditService,
106
+ type IPaywallService,
107
+ } from "./infrastructure/services/app-service-helpers";
108
+
100
109
  // Init Module Factory
101
110
  export {
102
111
  createSubscriptionInitModule,
@@ -0,0 +1,113 @@
1
+ /**
2
+ * App Service Helpers
3
+ * Creates ready-to-use service implementations for configureAppServices
4
+ */
5
+
6
+ import { getCreditsRepository } from "../repositories/CreditsRepositoryProvider";
7
+ import { getRevenueCatService } from "../../revenuecat/infrastructure/services/RevenueCatService";
8
+ import { getPremiumEntitlement } from "../../revenuecat/domain/types/RevenueCatTypes";
9
+ import { creditsQueryKeys } from "../../presentation/hooks/useCredits";
10
+ import { paywallControl } from "../../presentation/hooks/usePaywallVisibility";
11
+ import {
12
+ getGlobalQueryClient,
13
+ hasGlobalQueryClient,
14
+ } from "@umituz/react-native-design-system";
15
+ import {
16
+ useAuthStore,
17
+ selectUserId,
18
+ } from "@umituz/react-native-auth";
19
+
20
+ declare const __DEV__: boolean;
21
+
22
+ export interface CreditServiceConfig {
23
+ entitlementId: string;
24
+ }
25
+
26
+ export interface ICreditService {
27
+ checkCredits: (cost: number) => Promise<boolean>;
28
+ deductCredits: (cost: number) => Promise<void>;
29
+ refundCredits: (amount: number, error?: unknown) => Promise<void>;
30
+ calculateCost: (capability: string, metadata?: Record<string, unknown>) => number;
31
+ }
32
+
33
+ export interface IPaywallService {
34
+ showPaywall: (requiredCredits: number) => void;
35
+ }
36
+
37
+ const checkPremiumStatus = async (entitlementId: string): Promise<boolean> => {
38
+ try {
39
+ const rcService = getRevenueCatService();
40
+ if (!rcService) return false;
41
+
42
+ const customerInfo = await rcService.getCustomerInfo();
43
+ if (!customerInfo) return false;
44
+
45
+ return !!getPremiumEntitlement(customerInfo, entitlementId);
46
+ } catch {
47
+ return false;
48
+ }
49
+ };
50
+
51
+ /**
52
+ * Creates a credit service implementation
53
+ */
54
+ export function createCreditService(config: CreditServiceConfig): ICreditService {
55
+ const { entitlementId } = config;
56
+
57
+ return {
58
+ checkCredits: async (cost: number): Promise<boolean> => {
59
+ const userId = selectUserId(useAuthStore.getState());
60
+ if (!userId) return false;
61
+
62
+ // Premium users bypass credit check
63
+ if (await checkPremiumStatus(entitlementId)) return true;
64
+
65
+ try {
66
+ const repository = getCreditsRepository();
67
+ const result = await repository.getCredits(userId);
68
+ if (!result.success || !result.data) return false;
69
+ return (result.data.credits ?? 0) >= cost;
70
+ } catch {
71
+ return false;
72
+ }
73
+ },
74
+
75
+ deductCredits: async (cost: number): Promise<void> => {
76
+ const userId = selectUserId(useAuthStore.getState());
77
+ if (!userId) return;
78
+
79
+ // Premium users don't consume credits
80
+ if (await checkPremiumStatus(entitlementId)) return;
81
+
82
+ try {
83
+ const repository = getCreditsRepository();
84
+ await repository.deductCredit(userId, cost);
85
+
86
+ if (hasGlobalQueryClient()) {
87
+ getGlobalQueryClient().invalidateQueries({
88
+ queryKey: creditsQueryKeys.user(userId),
89
+ });
90
+ }
91
+ } catch (error) {
92
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
93
+ console.error("[CreditService] Deduct error:", error);
94
+ }
95
+ }
96
+ },
97
+
98
+ refundCredits: async (): Promise<void> => {
99
+ // No-op for now
100
+ },
101
+
102
+ calculateCost: (): number => 1,
103
+ };
104
+ }
105
+
106
+ /**
107
+ * Creates a paywall service implementation
108
+ */
109
+ export function createPaywallService(): IPaywallService {
110
+ return {
111
+ showPaywall: () => paywallControl.open(),
112
+ };
113
+ }