@umituz/react-native-subscription 2.14.82 → 2.14.83

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.
@@ -1,8 +1,6 @@
1
1
  /**
2
2
  * useDeductCredit Hook
3
- *
4
3
  * TanStack Query mutation hook for deducting credits.
5
- * Generic and reusable - uses module-level repository.
6
4
  */
7
5
 
8
6
  import { useCallback } from "react";
@@ -17,9 +15,7 @@ export interface UseDeductCreditParams {
17
15
  }
18
16
 
19
17
  export interface UseDeductCreditResult {
20
- /** Deduct a single credit */
21
18
  deductCredit: (creditType: CreditType) => Promise<boolean>;
22
- /** Deduct multiple credits (loops internally) */
23
19
  deductCredits: (cost: number, creditType?: CreditType) => Promise<boolean>;
24
20
  isDeducting: boolean;
25
21
  }
@@ -33,169 +29,47 @@ export const useDeductCredit = ({
33
29
 
34
30
  const mutation = useMutation({
35
31
  mutationFn: async (creditType: CreditType) => {
36
- if (!userId) {
37
- throw new Error("User not authenticated");
38
- }
32
+ if (!userId) throw new Error("User not authenticated");
39
33
  return repository.deductCredit(userId, creditType);
40
34
  },
41
35
  onMutate: async (creditType: CreditType) => {
42
36
  if (!userId) return;
43
-
44
- await queryClient.cancelQueries({
45
- queryKey: creditsQueryKeys.user(userId),
37
+ await queryClient.cancelQueries({ queryKey: creditsQueryKeys.user(userId) });
38
+ const previousCredits = queryClient.getQueryData<UserCredits>(creditsQueryKeys.user(userId));
39
+ queryClient.setQueryData<UserCredits | null>(creditsQueryKeys.user(userId), (old) => {
40
+ if (!old) return old;
41
+ const field = creditType === "text" ? "textCredits" : "imageCredits";
42
+ return { ...old, [field]: Math.max(0, old[field] - 1), lastUpdatedAt: new Date() };
46
43
  });
47
-
48
- const previousCredits = queryClient.getQueryData<UserCredits>(
49
- creditsQueryKeys.user(userId)
50
- );
51
-
52
- queryClient.setQueryData<UserCredits | null>(
53
- creditsQueryKeys.user(userId),
54
- (old) => {
55
- if (!old) return old;
56
- const fieldName =
57
- creditType === "text" ? "textCredits" : "imageCredits";
58
- return {
59
- ...old,
60
- [fieldName]: Math.max(0, old[fieldName] - 1),
61
- lastUpdatedAt: new Date(),
62
- };
63
- }
64
- );
65
-
66
44
  return { previousCredits };
67
45
  },
68
- onError: (_err, _creditType, context) => {
46
+ onError: (_err, _type, context) => {
69
47
  if (userId && context?.previousCredits) {
70
- queryClient.setQueryData(
71
- creditsQueryKeys.user(userId),
72
- context.previousCredits
73
- );
48
+ queryClient.setQueryData(creditsQueryKeys.user(userId), context.previousCredits);
74
49
  }
75
50
  },
76
51
  onSettled: () => {
77
- if (userId) {
78
- queryClient.invalidateQueries({
79
- queryKey: creditsQueryKeys.user(userId),
80
- });
81
- }
52
+ if (userId) queryClient.invalidateQueries({ queryKey: creditsQueryKeys.user(userId) });
82
53
  },
83
54
  });
84
55
 
85
- const deductCredit = useCallback(async (creditType: CreditType): Promise<boolean> => {
56
+ const deductCredit = useCallback(async (type: CreditType): Promise<boolean> => {
86
57
  try {
87
- const result = await mutation.mutateAsync(creditType);
88
-
89
- if (!result.success) {
90
- if (result.error?.code === "CREDITS_EXHAUSTED") {
91
- onCreditsExhausted?.();
92
- }
58
+ const res = await mutation.mutateAsync(type);
59
+ if (!res.success) {
60
+ if (res.error?.code === "CREDITS_EXHAUSTED") onCreditsExhausted?.();
93
61
  return false;
94
62
  }
95
-
96
63
  return true;
97
- } catch {
98
- return false;
99
- }
64
+ } catch { return false; }
100
65
  }, [mutation, onCreditsExhausted]);
101
66
 
102
- /**
103
- * Deduct multiple credits at once
104
- * Loops internally to deduct `cost` credits of the specified type
105
- */
106
- const deductCredits = useCallback(
107
- async (cost: number, creditType: CreditType = "image"): Promise<boolean> => {
108
- for (let i = 0; i < cost; i++) {
109
- const success = await deductCredit(creditType);
110
- if (!success) return false;
111
- }
112
- return true;
113
- },
114
- [deductCredit],
115
- );
116
-
117
- return {
118
- deductCredit,
119
- deductCredits,
120
- isDeducting: mutation.isPending,
121
- };
122
- };
123
-
124
- export interface UseInitializeCreditsParams {
125
- userId: string | undefined;
126
- }
127
-
128
- export interface InitializeCreditsOptions {
129
- purchaseId?: string;
130
- productId?: string;
131
- }
132
-
133
- export interface UseInitializeCreditsResult {
134
- initializeCredits: (options?: InitializeCreditsOptions) => Promise<boolean>;
135
- isInitializing: boolean;
136
- }
137
-
138
- export const useInitializeCredits = ({
139
- userId,
140
- }: UseInitializeCreditsParams): UseInitializeCreditsResult => {
141
- const repository = getCreditsRepository();
142
- const queryClient = useQueryClient();
143
-
144
- const mutation = useMutation({
145
- mutationFn: async (options?: InitializeCreditsOptions) => {
146
- if (!userId) {
147
- throw new Error("User not authenticated");
148
- }
149
-
150
- if (__DEV__) {
151
- console.log("[useInitializeCredits] Initializing credits:", {
152
- userId,
153
- purchaseId: options?.purchaseId,
154
- productId: options?.productId,
155
- });
156
- }
157
-
158
- return repository.initializeCredits(
159
- userId,
160
- options?.purchaseId,
161
- options?.productId
162
- );
163
- },
164
- onSuccess: (result) => {
165
- if (userId && result.success && result.data) {
166
- if (__DEV__) {
167
- console.log("[useInitializeCredits] Success, updating cache:", result.data);
168
- }
169
-
170
- // Set the data immediately for optimistic UI
171
- queryClient.setQueryData(creditsQueryKeys.user(userId), result.data);
172
- // Also invalidate to ensure all subscribers get the update
173
- queryClient.invalidateQueries({
174
- queryKey: creditsQueryKeys.user(userId),
175
- });
176
- }
177
- },
178
- onError: (error) => {
179
- if (__DEV__) {
180
- console.error("[useInitializeCredits] Error:", error);
181
- }
182
- },
183
- });
184
-
185
- const initializeCredits = useCallback(
186
- async (options?: InitializeCreditsOptions): Promise<boolean> => {
187
- try {
188
- const result = await mutation.mutateAsync(options);
189
- return result.success;
190
- } catch {
191
- return false;
192
- }
193
- },
194
- [mutation]
195
- );
67
+ const deductCredits = useCallback(async (cost: number, type: CreditType = "image"): Promise<boolean> => {
68
+ for (let i = 0; i < cost; i++) {
69
+ if (!(await deductCredit(type))) return false;
70
+ }
71
+ return true;
72
+ }, [deductCredit]);
196
73
 
197
- return {
198
- initializeCredits,
199
- isInitializing: mutation.isPending,
200
- };
74
+ return { deductCredit, deductCredits, isDeducting: mutation.isPending };
201
75
  };
@@ -0,0 +1,57 @@
1
+ /**
2
+ * useInitializeCredits Hook
3
+ * TanStack Query mutation hook for initializing credits after purchase.
4
+ */
5
+
6
+ import { useCallback } from "react";
7
+ import { useMutation, useQueryClient } from "@tanstack/react-query";
8
+ import { getCreditsRepository } from "../../infrastructure/repositories/CreditsRepositoryProvider";
9
+ import { creditsQueryKeys } from "./useCredits";
10
+
11
+ declare const __DEV__: boolean;
12
+
13
+ export interface UseInitializeCreditsParams {
14
+ userId: string | undefined;
15
+ }
16
+
17
+ export interface InitializeCreditsOptions {
18
+ purchaseId?: string;
19
+ productId?: string;
20
+ }
21
+
22
+ export interface UseInitializeCreditsResult {
23
+ initializeCredits: (options?: InitializeCreditsOptions) => Promise<boolean>;
24
+ isInitializing: boolean;
25
+ }
26
+
27
+ export const useInitializeCredits = ({
28
+ userId,
29
+ }: UseInitializeCreditsParams): UseInitializeCreditsResult => {
30
+ const repository = getCreditsRepository();
31
+ const queryClient = useQueryClient();
32
+
33
+ const mutation = useMutation({
34
+ mutationFn: async (options?: InitializeCreditsOptions) => {
35
+ if (!userId) throw new Error("User not authenticated");
36
+ if (__DEV__) console.log("[useInitializeCredits] Initializing:", { userId, ...options });
37
+ return repository.initializeCredits(userId, options?.purchaseId, options?.productId);
38
+ },
39
+ onSuccess: (result) => {
40
+ if (userId && result.success && result.data) {
41
+ if (__DEV__) console.log("[useInitializeCredits] Success:", result.data);
42
+ queryClient.setQueryData(creditsQueryKeys.user(userId), result.data);
43
+ queryClient.invalidateQueries({ queryKey: creditsQueryKeys.user(userId) });
44
+ }
45
+ },
46
+ onError: (error) => { if (__DEV__) console.error("[useInitializeCredits] Error:", error); },
47
+ });
48
+
49
+ const initializeCredits = useCallback(async (opts?: InitializeCreditsOptions): Promise<boolean> => {
50
+ try {
51
+ const res = await mutation.mutateAsync(opts);
52
+ return res.success;
53
+ } catch { return false; }
54
+ }, [mutation]);
55
+
56
+ return { initializeCredits, isInitializing: mutation.isPending };
57
+ };
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { useEffect, useCallback } from "react";
9
9
  import { useCredits, type UseCreditsResult } from "./useCredits";
10
- import { useInitializeCredits } from "./useDeductCredit";
10
+ import { useInitializeCredits } from "./useInitializeCredits";
11
11
 
12
12
  export interface UsePremiumWithCreditsParams {
13
13
  userId: string | undefined;
@@ -0,0 +1,12 @@
1
+ export * from "./domain/errors/RevenueCatError";
2
+ export * from "./domain/value-objects/RevenueCatConfig";
3
+ export * from "./domain/types/RevenueCatTypes";
4
+ export * from "./domain/constants/RevenueCatConstants";
5
+ export * from "./application/ports/IRevenueCatService";
6
+ export * from "./infrastructure/services/RevenueCatService";
7
+ export * from "./infrastructure/managers/SubscriptionManager";
8
+ export * from "./infrastructure/handlers/PackageHandler";
9
+ export * from "./presentation/hooks/useRevenueCat";
10
+ export * from "./presentation/hooks/useCustomerInfo";
11
+ export * from "./presentation/hooks/usePaywallFlow";
12
+ export * from "./presentation/hooks/useSubscriptionQueries";
@@ -0,0 +1,15 @@
1
+ export * from "./aiCreditHelpers";
2
+ export * from "./authUtils";
3
+ export * from "./creditChecker";
4
+ export * from "./creditMapper";
5
+ export * from "./dateValidationUtils";
6
+ export * from "./packageFilter";
7
+ export * from "./packagePeriodUtils";
8
+ export * from "./packageTypeDetector";
9
+ export * from "./premiumAsyncUtils";
10
+ export * from "./premiumStatusUtils";
11
+ export * from "./priceUtils";
12
+ export * from "./tierUtils";
13
+ export * from "./types";
14
+ export * from "./userTierUtils";
15
+ export * from "./validation";