@umituz/react-native-subscription 2.37.38 → 2.37.40

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.
Files changed (141) hide show
  1. package/package.json +1 -1
  2. package/src/domains/credits/application/CreditLimitCalculator.ts +1 -9
  3. package/src/domains/credits/application/CreditsInitializer.ts +5 -20
  4. package/src/domains/credits/application/DeductCreditsCommand.ts +13 -6
  5. package/src/domains/credits/application/RefundCreditsCommand.ts +1 -5
  6. package/src/domains/credits/application/credit-strategies/CreditAllocationOrchestrator.ts +1 -9
  7. package/src/domains/credits/application/credit-strategies/ICreditStrategy.ts +1 -5
  8. package/src/domains/credits/application/credit-strategies/TrialCreditStrategy.ts +1 -5
  9. package/src/domains/credits/application/creditDocumentHelpers.ts +2 -9
  10. package/src/domains/credits/application/creditOperationUtils.ts +1 -43
  11. package/src/domains/credits/core/Credits.ts +0 -23
  12. package/src/domains/credits/core/CreditsConstants.ts +0 -11
  13. package/src/domains/credits/core/CreditsMapper.ts +0 -6
  14. package/src/domains/credits/core/UserCreditsDocument.ts +0 -12
  15. package/src/domains/credits/infrastructure/CreditsRepository.ts +6 -1
  16. package/src/domains/credits/infrastructure/CreditsRepositoryManager.ts +0 -21
  17. package/src/domains/credits/infrastructure/operations/CreditsWriter.ts +52 -1
  18. package/src/domains/credits/presentation/deduct-credit/useDeductCredit.ts +2 -2
  19. package/src/domains/credits/presentation/useCredits.ts +10 -9
  20. package/src/domains/paywall/components/PaywallContainer.types.ts +0 -28
  21. package/src/domains/paywall/components/PaywallModal.styles.ts +0 -4
  22. package/src/domains/paywall/entities/types.ts +0 -5
  23. package/src/domains/paywall/hooks/usePaywallActions.ts +1 -15
  24. package/src/domains/revenuecat/core/errors/RevenueCatError.ts +0 -6
  25. package/src/domains/revenuecat/core/errors/RevenueCatErrorHandler.ts +0 -24
  26. package/src/domains/revenuecat/core/errors/RevenueCatErrorMessages.ts +0 -18
  27. package/src/domains/revenuecat/core/errors/index.ts +0 -4
  28. package/src/domains/revenuecat/core/types/RevenueCatConfig.ts +3 -7
  29. package/src/domains/revenuecat/core/types/RevenueCatData.ts +4 -9
  30. package/src/domains/revenuecat/core/types/RevenueCatTypes.ts +5 -65
  31. package/src/domains/revenuecat/core/types/index.ts +0 -4
  32. package/src/domains/revenuecat/infrastructure/services/UserSwitchMutex.ts +1 -24
  33. package/src/domains/subscription/application/SubscriptionAuthListener.ts +5 -21
  34. package/src/domains/subscription/application/SubscriptionInitializerTypes.ts +1 -5
  35. package/src/domains/subscription/application/SubscriptionSyncProcessor.ts +0 -4
  36. package/src/domains/subscription/application/SubscriptionSyncService.ts +4 -8
  37. package/src/domains/subscription/application/SubscriptionSyncUtils.ts +1 -1
  38. package/src/domains/subscription/application/initializer/BackgroundInitializer.ts +15 -2
  39. package/src/domains/subscription/application/initializer/ServiceConfigurator.ts +9 -2
  40. package/src/domains/subscription/application/statusChangeHandlers.ts +14 -27
  41. package/src/domains/subscription/application/syncIdGenerators.ts +0 -4
  42. package/src/domains/subscription/constants/thresholds.ts +0 -9
  43. package/src/domains/subscription/core/SubscriptionConstants.ts +0 -4
  44. package/src/domains/subscription/core/SubscriptionStatus.ts +11 -21
  45. package/src/domains/subscription/core/SubscriptionStatusHandlers.ts +4 -7
  46. package/src/domains/subscription/infrastructure/handlers/PurchaseStatusResolver.ts +1 -1
  47. package/src/domains/subscription/infrastructure/hooks/subscriptionQueryKeys.ts +0 -13
  48. package/src/domains/subscription/infrastructure/hooks/usePurchasePackage.ts +0 -18
  49. package/src/domains/subscription/infrastructure/hooks/useRestorePurchase.ts +3 -17
  50. package/src/domains/subscription/infrastructure/hooks/useRevenueCatTrialEligibility.ts +0 -17
  51. package/src/domains/subscription/infrastructure/hooks/useSubscriptionPackages.ts +0 -19
  52. package/src/domains/subscription/infrastructure/hooks/useSubscriptionQueries.ts +0 -6
  53. package/src/domains/subscription/infrastructure/managers/subscriptionManagerUtils.ts +0 -17
  54. package/src/domains/subscription/infrastructure/state/initializationState.ts +0 -25
  55. package/src/domains/subscription/infrastructure/utils/InitializationCache.ts +0 -21
  56. package/src/domains/subscription/infrastructure/utils/PremiumStatusSyncer.ts +3 -17
  57. package/src/domains/subscription/infrastructure/utils/authPurchaseState.ts +0 -5
  58. package/src/domains/subscription/infrastructure/utils/renewal/PackageTierComparator.ts +1 -0
  59. package/src/domains/subscription/infrastructure/utils/trialEligibilityUtils.ts +0 -18
  60. package/src/domains/subscription/presentation/components/details/PremiumDetailsCard.styles.ts +0 -5
  61. package/src/domains/subscription/presentation/components/details/PremiumDetailsCardTypes.ts +0 -5
  62. package/src/domains/subscription/presentation/components/feedback/paywallFeedbackStyles.ts +0 -5
  63. package/src/domains/subscription/presentation/stores/index.ts +0 -4
  64. package/src/domains/subscription/presentation/stores/purchaseLoadingStore.ts +0 -13
  65. package/src/domains/subscription/presentation/useAuthAwarePurchase.ts +30 -21
  66. package/src/domains/subscription/presentation/usePaywallVisibility.ts +0 -9
  67. package/src/domains/subscription/presentation/useSubscriptionStatus.ts +8 -11
  68. package/src/domains/subscription/utils/authGuards.ts +3 -0
  69. package/src/domains/trial/application/TrialService.ts +0 -9
  70. package/src/domains/trial/core/TrialTypes.ts +0 -8
  71. package/src/domains/wallet/domain/mappers/TransactionMapper.ts +0 -5
  72. package/src/domains/wallet/domain/types/transaction.types.ts +0 -7
  73. package/src/domains/wallet/index.ts +0 -7
  74. package/src/domains/wallet/infrastructure/config/walletConfig.ts +0 -11
  75. package/src/domains/wallet/presentation/hooks/useTransactionHistory.ts +6 -3
  76. package/src/domains/wallet/presentation/hooks/useWallet.ts +0 -7
  77. package/src/domains/wallet/utils/transactionIconMap.ts +0 -10
  78. package/src/global.d.ts +0 -6
  79. package/src/index.ts +1 -4
  80. package/src/init/createSubscriptionInitModule.ts +12 -2
  81. package/src/init/index.ts +1 -5
  82. package/src/presentation/hooks/feedback/useFeedbackSubmit.ts +0 -11
  83. package/src/shared/application/FeedbackService.ts +3 -21
  84. package/src/shared/application/ports/ISubscriptionRepository.ts +0 -4
  85. package/src/shared/infrastructure/SubscriptionEventBus.ts +0 -13
  86. package/src/shared/infrastructure/firestore/collectionUtils.ts +1 -17
  87. package/src/shared/infrastructure/firestore/index.ts +0 -4
  88. package/src/shared/infrastructure/firestore/resultUtils.ts +0 -12
  89. package/src/shared/infrastructure/react-query/hooks/usePreviousUserCleanup.ts +0 -17
  90. package/src/shared/infrastructure/react-query/queryConfig.ts +0 -15
  91. package/src/shared/utils/BaseError.ts +0 -5
  92. package/src/shared/utils/Result.ts +0 -20
  93. package/src/shared/utils/dateConverter.ts +6 -46
  94. package/src/utils/appUtils.ts +0 -16
  95. package/src/utils/creditMapper.ts +0 -7
  96. package/src/utils/dateUtils.compare.ts +0 -24
  97. package/src/utils/dateUtils.core.ts +0 -39
  98. package/src/utils/dateUtils.format.ts +0 -41
  99. package/src/utils/dateUtils.math.ts +0 -41
  100. package/src/utils/dateUtils.ts +0 -5
  101. package/src/utils/packagePeriodUtils.ts +0 -20
  102. package/src/utils/packageTypeDetector.ts +1 -21
  103. package/src/utils/premiumStatusUtils.ts +1 -14
  104. package/src/utils/priceUtils.ts +0 -35
  105. package/src/utils/tierUtils.ts +1 -8
  106. package/src/utils/types.ts +1 -25
  107. package/src/utils/validation.ts +1 -7
  108. package/src/domains/README.md +0 -52
  109. package/src/domains/config/domain/README.md +0 -37
  110. package/src/domains/config/domain/entities/README.md +0 -41
  111. package/src/domains/credits/application/credit-strategies/SyncCreditStrategy.ts +0 -24
  112. package/src/domains/paywall/README.md +0 -101
  113. package/src/domains/paywall/entities/README.md +0 -40
  114. package/src/domains/paywall/hooks/README.md +0 -41
  115. package/src/domains/subscription/application/syncConstants.ts +0 -1
  116. package/src/domains/subscription/infrastructure/README.md +0 -41
  117. package/src/domains/subscription/infrastructure/config/README.md +0 -49
  118. package/src/domains/subscription/infrastructure/handlers/README.md +0 -41
  119. package/src/domains/subscription/infrastructure/hooks/README.md +0 -50
  120. package/src/domains/subscription/infrastructure/managers/README.md +0 -41
  121. package/src/domains/subscription/infrastructure/services/README.md +0 -42
  122. package/src/domains/subscription/infrastructure/utils/README.md +0 -41
  123. package/src/domains/subscription/presentation/components/README.md +0 -155
  124. package/src/domains/subscription/presentation/components/details/CreditRow.md +0 -92
  125. package/src/domains/subscription/presentation/components/details/DetailRow.md +0 -91
  126. package/src/domains/subscription/presentation/components/details/PremiumDetailsCard.md +0 -93
  127. package/src/domains/subscription/presentation/components/details/PremiumStatusBadge.md +0 -91
  128. package/src/domains/subscription/presentation/components/details/README.md +0 -99
  129. package/src/domains/subscription/presentation/components/feedback/PaywallFeedbackModal.md +0 -90
  130. package/src/domains/subscription/presentation/components/feedback/README.md +0 -99
  131. package/src/domains/subscription/presentation/components/paywall/PaywallModal.md +0 -94
  132. package/src/domains/subscription/presentation/components/paywall/README.md +0 -54
  133. package/src/domains/subscription/presentation/components/sections/README.md +0 -99
  134. package/src/domains/subscription/presentation/components/sections/SubscriptionSection.md +0 -94
  135. package/src/domains/subscription/presentation/utils/README.md +0 -31
  136. package/src/domains/wallet/README.md +0 -51
  137. package/src/domains/wallet/domain/README.md +0 -41
  138. package/src/domains/wallet/infrastructure/README.md +0 -41
  139. package/src/domains/wallet/presentation/components/README.md +0 -41
  140. package/src/domains/wallet/presentation/hooks/README.md +0 -41
  141. package/src/shared/application/ports/README.md +0 -48
@@ -1,11 +1,5 @@
1
- /**
2
- * Feedback Service
3
- * Handles feedback submission to Firestore
4
- * Feedback is stored under users/{userId}/feedback/{feedbackId}
5
- */
6
-
7
1
  import { collection, addDoc, doc } from "firebase/firestore";
8
- import { getFirestore } from "@umituz/react-native-firebase";
2
+ import { getFirestore, serverTimestamp } from "@umituz/react-native-firebase";
9
3
 
10
4
  interface FeedbackData {
11
5
  userId: string | null;
@@ -22,10 +16,6 @@ export interface FeedbackSubmitResult {
22
16
  error?: Error;
23
17
  }
24
18
 
25
- /**
26
- * Submit feedback to Firestore
27
- * Stores under users/{userId}/feedback
28
- */
29
19
  async function submitFeedback(
30
20
  data: FeedbackData
31
21
  ): Promise<FeedbackSubmitResult> {
@@ -40,8 +30,6 @@ async function submitFeedback(
40
30
  }
41
31
 
42
32
  try {
43
- const now = new Date().toISOString();
44
-
45
33
  const userDocRef = doc(db, "users", data.userId);
46
34
  const feedbackCollectionRef = collection(userDocRef, "feedback");
47
35
 
@@ -52,8 +40,8 @@ async function submitFeedback(
52
40
  description: data.description,
53
41
  rating: data.rating ?? null,
54
42
  status: data.status ?? "pending",
55
- createdAt: now,
56
- updatedAt: now,
43
+ createdAt: serverTimestamp(),
44
+ updatedAt: serverTimestamp(),
57
45
  });
58
46
 
59
47
  return { success: true };
@@ -65,9 +53,6 @@ async function submitFeedback(
65
53
  }
66
54
  }
67
55
 
68
- /**
69
- * Submit paywall decline feedback
70
- */
71
56
  export async function submitPaywallFeedback(
72
57
  userId: string | null,
73
58
  userEmail: string | null,
@@ -82,9 +67,6 @@ export async function submitPaywallFeedback(
82
67
  });
83
68
  }
84
69
 
85
- /**
86
- * Submit general settings feedback
87
- */
88
70
  export async function submitSettingsFeedback(
89
71
  userId: string | null,
90
72
  userEmail: string | null,
@@ -1,7 +1,3 @@
1
- /**
2
- * ISubscriptionRepository Interface
3
- */
4
-
5
1
  import { SubscriptionStatus } from '../../../domains/subscription/core/SubscriptionStatus';
6
2
 
7
3
  export interface ISubscriptionRepository {
@@ -1,9 +1,5 @@
1
1
  type EventCallback<T = unknown> = (data: T) => void;
2
2
 
3
- /**
4
- * Simple EventBus Implementation
5
- * Used to decouple services and provide an observer pattern for subscription events.
6
- */
7
3
  class SubscriptionEventBus {
8
4
  private static instance: SubscriptionEventBus;
9
5
  private listeners: Record<string, EventCallback<any>[]> = {};
@@ -23,13 +19,11 @@ class SubscriptionEventBus {
23
19
  }
24
20
  this.listeners[event].push(callback);
25
21
 
26
- // Return unsubscribe function
27
22
  return () => {
28
23
  const listeners = this.listeners[event];
29
24
  if (listeners) {
30
25
  this.listeners[event] = listeners.filter(l => l !== callback);
31
26
 
32
- // Clean up empty event arrays to prevent memory leak
33
27
  if (this.listeners[event].length === 0) {
34
28
  delete this.listeners[event];
35
29
  }
@@ -53,10 +47,6 @@ class SubscriptionEventBus {
53
47
  });
54
48
  }
55
49
 
56
- /**
57
- * Clear all listeners for a specific event or all events
58
- * Useful for cleanup during testing or app state reset
59
- */
60
50
  clear(event?: string): void {
61
51
  if (event) {
62
52
  delete this.listeners[event];
@@ -65,9 +55,6 @@ class SubscriptionEventBus {
65
55
  }
66
56
  }
67
57
 
68
- /**
69
- * Get listener count for debugging
70
- */
71
58
  getListenerCount(event?: string): number {
72
59
  if (event) {
73
60
  return this.listeners[event]?.length ?? 0;
@@ -1,8 +1,3 @@
1
- /**
2
- * Firestore Collection Utilities
3
- * Shared utilities for building Firestore collection and document references
4
- */
5
-
6
1
  import { collection, doc } from "firebase/firestore";
7
2
  import {
8
3
  getFirestore,
@@ -16,10 +11,6 @@ export interface CollectionConfig {
16
11
  useUserSubcollection: boolean;
17
12
  }
18
13
 
19
- /**
20
- * Build a collection reference based on configuration
21
- * Supports both root collections and user subcollections
22
- */
23
14
  export function buildCollectionRef(
24
15
  db: Firestore,
25
16
  userId: string,
@@ -31,10 +22,6 @@ export function buildCollectionRef(
31
22
  return collection(db, config.collectionName);
32
23
  }
33
24
 
34
- /**
35
- * Build a document reference based on configuration
36
- * Supports both root collections and user subcollections
37
- */
38
25
  export function buildDocRef(
39
26
  db: Firestore,
40
27
  userId: string,
@@ -44,12 +31,9 @@ export function buildDocRef(
44
31
  if (config.useUserSubcollection) {
45
32
  return doc(db, "users", userId, config.collectionName, docId);
46
33
  }
47
- return doc(db, config.collectionName, docId);
34
+ return doc(db, config.collectionName, userId);
48
35
  }
49
36
 
50
- /**
51
- * Get Firestore instance or throw error
52
- */
53
37
  export function requireFirestore(): Firestore {
54
38
  const db = getFirestore();
55
39
  if (!db) {
@@ -1,6 +1,2 @@
1
- /**
2
- * Firestore Infrastructure Utilities
3
- */
4
-
5
1
  export * from "./collectionUtils";
6
2
  export * from "./resultUtils";
@@ -1,8 +1,3 @@
1
- /**
2
- * Result Utilities
3
- * Shared helpers for working with Result pattern
4
- */
5
-
6
1
  import type { Result } from "../../utils/Result";
7
2
  import { failure } from "../../utils/Result";
8
3
 
@@ -11,9 +6,6 @@ interface ApiError {
11
6
  code: string;
12
7
  }
13
8
 
14
- /**
15
- * Create a standard error result
16
- */
17
9
  function createErrorResult(
18
10
  message: string,
19
11
  code: string = "UNKNOWN_ERROR"
@@ -21,12 +13,8 @@ function createErrorResult(
21
13
  return failure({ message, code });
22
14
  }
23
15
 
24
- /**
25
- * Map Error to ApiError result
26
- */
27
16
  export function mapErrorToResult<T>(error: unknown): Result<T, ApiError> {
28
17
  const message = error instanceof Error ? error.message : "An unknown error occurred";
29
18
  const code = error instanceof Error && "code" in error ? String(error.code) : "UNKNOWN_ERROR";
30
19
  return createErrorResult(message, code);
31
20
  }
32
-
@@ -1,23 +1,7 @@
1
- /**
2
- * User Cache Cleanup Hook
3
- * Automatically cleans up previous user's query cache when userId changes
4
- */
5
-
6
1
  import { useEffect, useRef } from "react";
7
2
  import type { QueryClient } from "@umituz/react-native-design-system";
8
3
  import { isAuthenticated } from "../../../../domains/subscription/utils/authGuards";
9
4
 
10
- /**
11
- * Cleans up previous user's cache when userId changes (logout or user switch)
12
- * Prevents data leakage between users
13
- *
14
- * @param userId - Current user ID
15
- * @param queryClient - TanStack Query client
16
- * @param queryKey - Query key factory function that takes userId
17
- *
18
- * @example
19
- * usePreviousUserCleanup(userId, queryClient, (id) => creditsQueryKeys.user(id));
20
- */
21
5
  export function usePreviousUserCleanup(
22
6
  userId: string | null | undefined,
23
7
  queryClient: QueryClient,
@@ -29,7 +13,6 @@ export function usePreviousUserCleanup(
29
13
  const prevUserId = prevUserIdRef.current;
30
14
  prevUserIdRef.current = userId;
31
15
 
32
- // Clear previous user's cache when userId changes (logout or user switch)
33
16
  if (prevUserId !== userId && isAuthenticated(prevUserId)) {
34
17
  queryClient.removeQueries({
35
18
  queryKey: queryKey(prevUserId),
@@ -1,18 +1,3 @@
1
- /**
2
- * Shared TanStack Query Configuration
3
- * Common query configurations to ensure consistency across hooks
4
- */
5
-
6
- /**
7
- * Configuration for queries that should never cache
8
- * Used for real-time sensitive data (subscriptions, credits, transactions)
9
- *
10
- * - gcTime: 0 - Don't keep unused data in memory
11
- * - staleTime: 0 - Always consider data stale
12
- * - refetchOnMount: "always" - Always refetch when component mounts
13
- * - refetchOnWindowFocus: "always" - Always refetch when window regains focus
14
- * - refetchOnReconnect: "always" - Always refetch when reconnecting
15
- */
16
1
  export const NO_CACHE_QUERY_CONFIG = {
17
2
  gcTime: 0,
18
3
  staleTime: 0,
@@ -1,8 +1,3 @@
1
- /**
2
- * Base Error Class
3
- * Common base error for all domain errors
4
- */
5
-
6
1
  export abstract class BaseError extends Error {
7
2
  public readonly code: string;
8
3
  public readonly cause?: Error;
@@ -1,47 +1,33 @@
1
- /**
2
- * Result Pattern
3
- * Type-safe error handling without exceptions.
4
- * Inspired by Rust's Result<T, E> and functional programming patterns.
5
- */
6
-
7
- /** Success result containing data */
8
1
  export interface Success<T> {
9
2
  readonly success: true;
10
3
  readonly data: T;
11
4
  readonly error?: never;
12
5
  }
13
6
 
14
- /** Failure result containing error */
15
7
  export interface Failure<E = Error> {
16
8
  readonly success: false;
17
9
  readonly data?: never;
18
10
  readonly error: E;
19
11
  }
20
12
 
21
- /** Union type representing either success or failure */
22
13
  export type Result<T, E = Error> = Success<T> | Failure<E>;
23
14
 
24
- /** Create a success result */
25
15
  export function success<T>(data: T): Success<T> {
26
16
  return { success: true, data };
27
17
  }
28
18
 
29
- /** Create a failure result */
30
19
  export function failure<E = Error>(error: E): Failure<E> {
31
20
  return { success: false, error };
32
21
  }
33
22
 
34
- /** Type guard to check if result is success */
35
23
  export function isSuccess<T, E>(result: Result<T, E>): result is Success<T> {
36
24
  return result.success === true;
37
25
  }
38
26
 
39
- /** Type guard to check if result is failure */
40
27
  export function isFailure<T, E>(result: Result<T, E>): result is Failure<E> {
41
28
  return result.success === false;
42
29
  }
43
30
 
44
- /** Unwrap result or throw if failure */
45
31
  export function unwrap<T, E extends Error>(result: Result<T, E>): T {
46
32
  if (isSuccess(result)) {
47
33
  return result.data;
@@ -49,7 +35,6 @@ export function unwrap<T, E extends Error>(result: Result<T, E>): T {
49
35
  throw result.error;
50
36
  }
51
37
 
52
- /** Unwrap result or return default value */
53
38
  export function unwrapOr<T, E>(result: Result<T, E>, defaultValue: T): T {
54
39
  if (isSuccess(result)) {
55
40
  return result.data;
@@ -57,7 +42,6 @@ export function unwrapOr<T, E>(result: Result<T, E>, defaultValue: T): T {
57
42
  return defaultValue;
58
43
  }
59
44
 
60
- /** Map success value to new value */
61
45
  export function map<T, U, E>(
62
46
  result: Result<T, E>,
63
47
  fn: (data: T) => U
@@ -68,7 +52,6 @@ export function map<T, U, E>(
68
52
  return result;
69
53
  }
70
54
 
71
- /** Chain results (flatMap) */
72
55
  export function flatMap<T, U, E>(
73
56
  result: Result<T, E>,
74
57
  fn: (data: T) => Result<U, E>
@@ -79,7 +62,6 @@ export function flatMap<T, U, E>(
79
62
  return result;
80
63
  }
81
64
 
82
- /** Execute async function and wrap result */
83
65
  export async function tryCatch<T>(
84
66
  fn: () => Promise<T>,
85
67
  errorMapper?: (error: unknown) => Error
@@ -97,7 +79,6 @@ export async function tryCatch<T>(
97
79
  }
98
80
  }
99
81
 
100
- /** Execute sync function and wrap result */
101
82
  export function tryCatchSync<T>(
102
83
  fn: () => T,
103
84
  errorMapper?: (error: unknown) => Error
@@ -115,7 +96,6 @@ export function tryCatchSync<T>(
115
96
  }
116
97
  }
117
98
 
118
- /** Combine multiple results into one */
119
99
  export function combine<T, E>(results: Result<T, E>[]): Result<T[], E> {
120
100
  const data: T[] = [];
121
101
  for (const result of results) {
@@ -1,13 +1,7 @@
1
- /**
2
- * Date Converter Utilities
3
- * Centralized date conversion and validation logic
4
- * Handles Date objects, ISO strings, timestamps, and null values safely
5
- */
6
-
7
- /**
8
- * Safely converts any date-like value to a Date object or null
9
- * Handles: Date objects, ISO strings, timestamps, null, undefined, invalid values
10
- */
1
+ import { Timestamp } from "@umituz/react-native-firebase";
2
+
3
+ type FirestoreTimestamp = ReturnType<typeof Timestamp.fromDate>;
4
+
11
5
  export function toDate(value: Date | string | number | null | undefined): Date | null {
12
6
  if (value === null || value === undefined) {
13
7
  return null;
@@ -25,64 +19,39 @@ export function toDate(value: Date | string | number | null | undefined): Date |
25
19
  return null;
26
20
  }
27
21
 
28
- /**
29
- * Safely converts any date-like value to an ISO string or null
30
- * Handles: Date objects, ISO strings, timestamps, null, undefined, invalid values
31
- */
32
22
  export function toISOString(value: Date | string | number | null | undefined): string | null {
33
23
  if (value === null || value === undefined) {
34
24
  return null;
35
25
  }
36
26
 
37
- // If already a string, validate it
38
27
  if (typeof value === 'string') {
39
28
  const parsed = new Date(value);
40
- return isValidDate(parsed) ? value : null;
29
+ return isValidDate(parsed) ? parsed.toISOString() : null;
41
30
  }
42
31
 
43
- // Convert to Date and then to ISO string
44
32
  const date = toDate(value);
45
33
  return date ? date.toISOString() : null;
46
34
  }
47
35
 
48
- /**
49
- * Checks if a Date object is valid (not Invalid Date)
50
- * @internal - Use for internal validation only
51
- */
52
36
  function isValidDate(date: Date): boolean {
53
37
  return date instanceof Date && !isNaN(date.getTime());
54
38
  }
55
39
 
56
- /**
57
- * Safely converts a Date or string to a Firestore Timestamp
58
- * Returns null if the value is invalid
59
- */
60
- export function toTimestamp(value: Date | string | number | null | undefined): any {
40
+ export function toTimestamp(value: Date | string | number | null | undefined): FirestoreTimestamp | null {
61
41
  const date = toDate(value);
62
42
  if (!date) return null;
63
43
 
64
- // Lazy import to avoid circular dependencies
65
- const { Timestamp } = require('firebase/firestore');
66
44
  return Timestamp.fromDate(date);
67
45
  }
68
46
 
69
- /**
70
- * Gets current date as ISO string
71
- */
72
47
  export function getCurrentISOString(): string {
73
48
  return new Date().toISOString();
74
49
  }
75
50
 
76
- /**
77
- * Gets current date as Date object
78
- */
79
51
  export function getCurrentDate(): Date {
80
52
  return new Date();
81
53
  }
82
54
 
83
- /**
84
- * Compares two dates and returns if first is before second
85
- */
86
55
  export function isBefore(date1: Date | string | null | undefined, date2: Date | string | null | undefined): boolean {
87
56
  const d1 = toDate(date1);
88
57
  const d2 = toDate(date2);
@@ -91,9 +60,6 @@ export function isBefore(date1: Date | string | null | undefined, date2: Date |
91
60
  return d1.getTime() < d2.getTime();
92
61
  }
93
62
 
94
- /**
95
- * Compares two dates and returns if first is after second
96
- */
97
63
  export function isAfter(date1: Date | string | null | undefined, date2: Date | string | null | undefined): boolean {
98
64
  const d1 = toDate(date1);
99
65
  const d2 = toDate(date2);
@@ -102,18 +68,12 @@ export function isAfter(date1: Date | string | null | undefined, date2: Date | s
102
68
  return d1.getTime() > d2.getTime();
103
69
  }
104
70
 
105
- /**
106
- * Checks if a date is in the past
107
- */
108
71
  export function isInPast(date: Date | string | null | undefined): boolean {
109
72
  const d = toDate(date);
110
73
  if (!d) return false;
111
74
  return d.getTime() < Date.now();
112
75
  }
113
76
 
114
- /**
115
- * Checks if a date is in the future
116
- */
117
77
  export function isInFuture(date: Date | string | null | undefined): boolean {
118
78
  const d = toDate(date);
119
79
  if (!d) return false;
@@ -1,18 +1,8 @@
1
- /**
2
- * App and Platform Utilities
3
- */
4
1
  import { Platform } from "react-native";
5
2
  import Constants from "expo-constants";
6
3
 
7
- /**
8
- * Development mode flag
9
- * Safe check for __DEV__ that works in all environments
10
- */
11
4
  export const IS_DEV_MODE = typeof __DEV__ !== "undefined" && __DEV__;
12
5
 
13
- /**
14
- * Gets the current app version from Expo constants
15
- */
16
6
  export function getAppVersion(): string {
17
7
  const version = Constants.expoConfig?.version;
18
8
 
@@ -22,9 +12,6 @@ export function getAppVersion(): string {
22
12
  return version;
23
13
  }
24
14
 
25
- /**
26
- * Validates if the current platform is supported
27
- */
28
15
  export function validatePlatform(): "ios" | "android" {
29
16
  const platform = Platform.OS;
30
17
  if (platform !== "ios" && platform !== "android") {
@@ -33,9 +20,6 @@ export function validatePlatform(): "ios" | "android" {
33
20
  return platform;
34
21
  }
35
22
 
36
- /**
37
- * Checks if the app is currently in development mode
38
- */
39
23
  export function isDev(): boolean {
40
24
  return __DEV__;
41
25
  }
@@ -1,9 +1,6 @@
1
1
  import { detectPackageType, type SubscriptionPackageType } from "./packageTypeDetector";
2
2
  import type { PackageAllocationMap } from "../domains/credits/core/Credits";
3
3
 
4
- /**
5
- * Get credit allocation for a package type from provided allocations map
6
- */
7
4
  export function getCreditAllocation(
8
5
  packageType: SubscriptionPackageType,
9
6
  allocations?: PackageAllocationMap
@@ -12,10 +9,6 @@ export function getCreditAllocation(
12
9
  return allocations[packageType]?.credits ?? null;
13
10
  }
14
11
 
15
- /**
16
- * Create credit amounts mapping for PaywallModal from RevenueCat packages
17
- * Maps product.identifier to credit amount using dynamic allocations
18
- */
19
12
  export function createCreditAmountsFromPackages(
20
13
  packages: Array<{ product: { identifier: string } }>,
21
14
  allocations?: PackageAllocationMap
@@ -1,14 +1,6 @@
1
- /**
2
- * Date Utilities - Comparison Operations
3
- * Date comparison and calculation functions
4
- */
5
-
6
1
  import { isValidDate, isPast, currentDate } from "./dateUtils.core";
7
2
  import { addDays } from "./dateUtils.math";
8
3
 
9
- /**
10
- * Calculate difference in days between two dates
11
- */
12
4
  export function daysBetween(date1: Date | string | number, date2: Date | string | number): number {
13
5
  const d1 = new Date(date1);
14
6
  const d2 = new Date(date2);
@@ -16,10 +8,6 @@ export function daysBetween(date1: Date | string | number, date2: Date | string
16
8
  return Math.floor(diffTime / (1000 * 60 * 60 * 24));
17
9
  }
18
10
 
19
- /**
20
- * Calculate days remaining until a date
21
- * Returns null if date is in the past or invalid
22
- */
23
11
  export function daysUntil(date: Date | string | number): number | null {
24
12
  const target = new Date(date);
25
13
  if (!isValidDate(target) || isPast(target)) {
@@ -28,9 +16,6 @@ export function daysUntil(date: Date | string | number): number | null {
28
16
  return daysBetween(currentDate(), target);
29
17
  }
30
18
 
31
- /**
32
- * Check if two dates are the same day
33
- */
34
19
  export function isSameDay(date1: Date | string | number, date2: Date | string | number): boolean {
35
20
  const d1 = new Date(date1);
36
21
  const d2 = new Date(date2);
@@ -41,24 +26,15 @@ export function isSameDay(date1: Date | string | number, date2: Date | string |
41
26
  );
42
27
  }
43
28
 
44
- /**
45
- * Check if a date is today
46
- */
47
29
  export function isToday(date: Date | string | number): boolean {
48
30
  return isSameDay(date, currentDate());
49
31
  }
50
32
 
51
- /**
52
- * Check if a date is yesterday
53
- */
54
33
  export function isYesterday(date: Date | string | number): boolean {
55
34
  const yesterday = addDays(currentDate(), -1);
56
35
  return isSameDay(date, yesterday);
57
36
  }
58
37
 
59
- /**
60
- * Check if a date is tomorrow
61
- */
62
38
  export function isTomorrow(date: Date | string | number): boolean {
63
39
  const tomorrow = addDays(currentDate(), 1);
64
40
  return isSameDay(date, tomorrow);
@@ -1,56 +1,26 @@
1
- /**
2
- * Date Utilities - Core Operations
3
- * Basic date manipulation and validation functions
4
- */
5
-
6
1
  export type DateLike = Date | string | number;
7
2
 
8
- /**
9
- * Checks if a date is in the past (strictly before now)
10
- * @param date - The date to check
11
- * @returns true if date < now, false if date >= now
12
- * @note A date exactly equal to Date.now() returns false (not past)
13
- */
14
3
  export function isPast(date: DateLike): boolean {
15
4
  const d = new Date(date);
16
5
  return d.getTime() < Date.now();
17
6
  }
18
7
 
19
- /**
20
- * Checks if a date is in the future (strictly after now)
21
- * @param date - The date to check
22
- * @returns true if date > now, false if date <= now
23
- * @note A date exactly equal to Date.now() returns false (not future)
24
- */
25
8
  export function isFuture(date: DateLike): boolean {
26
9
  const d = new Date(date);
27
10
  return d.getTime() > Date.now();
28
11
  }
29
12
 
30
- /**
31
- * Checks if a date is approximately now (within margin)
32
- * Useful for handling edge cases where isPast/isFuture might flicker
33
- * @param date - The date to check
34
- * @param marginMs - Margin in milliseconds (default: 1000ms)
35
- * @returns true if date is within margin of Date.now()
36
- */
37
13
  export function isNow(date: DateLike, marginMs: number = 1000): boolean {
38
14
  const d = new Date(date);
39
15
  const diff = Math.abs(d.getTime() - Date.now());
40
16
  return diff <= marginMs;
41
17
  }
42
18
 
43
- /**
44
- * Checks if a date is valid
45
- */
46
19
  export function isValidDate(date: DateLike): boolean {
47
20
  const d = date instanceof Date ? date : new Date(date);
48
21
  return !isNaN(d.getTime());
49
22
  }
50
23
 
51
- /**
52
- * Converts various timestamp formats to a safe Date object
53
- */
54
24
  export function toSafeDate(ts: unknown): Date | null {
55
25
  if (!ts) return null;
56
26
  if (typeof ts === "object" && ts !== null && "toDate" in ts && typeof ts.toDate === "function") {
@@ -64,23 +34,14 @@ export function toSafeDate(ts: unknown): Date | null {
64
34
  return null;
65
35
  }
66
36
 
67
- /**
68
- * Formats a date to ISO string safely
69
- */
70
37
  export function formatISO(date: Date | null): string | null {
71
38
  return date ? date.toISOString() : null;
72
39
  }
73
40
 
74
- /**
75
- * Get current timestamp in milliseconds
76
- */
77
41
  export function now(): number {
78
42
  return Date.now();
79
43
  }
80
44
 
81
- /**
82
- * Get current date
83
- */
84
45
  export function currentDate(): Date {
85
46
  return new Date();
86
47
  }