@umituz/react-native-subscription 2.15.4 → 2.15.5

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.15.4",
3
+ "version": "2.15.5",
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",
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Sandbox Duration Configuration
3
+ * Apple Sandbox subscription durations vs Production durations
4
+ *
5
+ * @see https://developer.apple.com/documentation/storekit/in-app_purchase/testing_in-app_purchases_with_sandbox
6
+ */
7
+
8
+ import type { SubscriptionPackageType } from '../../../utils/packageTypeDetector';
9
+
10
+ /**
11
+ * Apple Sandbox subscription durations in minutes
12
+ */
13
+ export const SANDBOX_DURATIONS: Record<SubscriptionPackageType, number> = {
14
+ weekly: 3,
15
+ monthly: 5,
16
+ yearly: 60,
17
+ unknown: 5,
18
+ };
19
+
20
+ /**
21
+ * Production subscription durations in days
22
+ */
23
+ export const PRODUCTION_DURATIONS: Record<SubscriptionPackageType, number> = {
24
+ weekly: 7,
25
+ monthly: 30,
26
+ yearly: 365,
27
+ unknown: 30,
28
+ };
29
+
30
+ /**
31
+ * Get production duration in days for a package type
32
+ */
33
+ export function getProductionDurationDays(packageType: SubscriptionPackageType): number {
34
+ return PRODUCTION_DURATIONS[packageType] ?? PRODUCTION_DURATIONS.unknown;
35
+ }
36
+
37
+ /**
38
+ * Get sandbox duration in minutes for a package type
39
+ */
40
+ export function getSandboxDurationMinutes(packageType: SubscriptionPackageType): number {
41
+ return SANDBOX_DURATIONS[packageType] ?? SANDBOX_DURATIONS.unknown;
42
+ }
@@ -1,109 +1,37 @@
1
1
  /**
2
2
  * Expiration Date Calculator
3
- * Handles RevenueCat expiration date extraction with edge case handling
4
- * Includes sandbox-to-production date conversion for better testing UX
3
+ * Main entry point for calculating subscription expiration dates
5
4
  */
6
5
 
7
6
  import type { RevenueCatEntitlement } from '../../domain/types/RevenueCatTypes';
8
- import { detectPackageType, type SubscriptionPackageType } from '../../../utils/packageTypeDetector';
7
+ import {
8
+ shouldConvertSandbox,
9
+ convertToProductionExpiration,
10
+ adjustPastExpiration,
11
+ } from './SandboxDurationConverter';
9
12
 
10
13
  /**
11
- * Add production subscription period to a date
12
- */
13
- function addProductionPeriod(date: Date, packageType: SubscriptionPackageType): Date {
14
- const newDate = new Date(date);
15
-
16
- switch (packageType) {
17
- case 'weekly':
18
- newDate.setDate(newDate.getDate() + 7);
19
- break;
20
- case 'monthly':
21
- newDate.setDate(newDate.getDate() + 30);
22
- break;
23
- case 'yearly':
24
- newDate.setDate(newDate.getDate() + 365);
25
- break;
26
- default:
27
- newDate.setDate(newDate.getDate() + 30);
28
- break;
29
- }
30
-
31
- return newDate;
32
- }
33
-
34
- /**
35
- * Convert sandbox expiration to production-equivalent expiration
36
- *
37
- * Apple Sandbox durations:
38
- * - Weekly: 3 minutes → 7 days
39
- * - Monthly: 5 minutes → 30 days
40
- * - Yearly: 1 hour → 365 days
41
- *
42
- * For better testing UX, we calculate what the expiration would be in production
43
- * based on the latest purchase date.
44
- */
45
- function convertSandboxToProduction(
46
- latestPurchaseDate: string | null,
47
- productIdentifier: string
48
- ): string {
49
- const purchaseDate = latestPurchaseDate
50
- ? new Date(latestPurchaseDate)
51
- : new Date();
52
-
53
- const packageType = detectPackageType(productIdentifier);
54
- const productionExpiration = addProductionPeriod(purchaseDate, packageType);
55
-
56
- return productionExpiration.toISOString();
57
- }
58
-
59
- /**
60
- * Adjust expiration date for edge cases
14
+ * Get adjusted expiration date from entitlement
61
15
  *
62
- * Handles two scenarios:
63
- * 1. Sandbox mode: Convert to production-equivalent dates for better UX
64
- * 2. Same-day expiration bug: Add period if expiration is in the past
16
+ * Handles:
17
+ * 1. Sandbox mode: Converts to production-equivalent dates for better UX
18
+ * 2. Past expiration: Adds subscription period if expiration is in the past
65
19
  */
66
- function adjustExpirationDate(
67
- expirationDate: string,
68
- productIdentifier: string,
69
- isSandbox: boolean,
70
- latestPurchaseDate: string | null
71
- ): string {
72
- // In sandbox mode, show production-equivalent expiration for better testing UX
73
- if (isSandbox && __DEV__) {
74
- return convertSandboxToProduction(latestPurchaseDate, productIdentifier);
75
- }
76
-
77
- const expDate = new Date(expirationDate);
78
- const now = new Date();
79
-
80
- // If expiration is in the future, no adjustment needed
81
- if (expDate > now) {
82
- return expirationDate;
83
- }
84
-
85
- // If expiration is today or past, add subscription period
86
- const packageType = detectPackageType(productIdentifier);
87
- const adjustedDate = addProductionPeriod(expDate, packageType);
88
-
89
- return adjustedDate.toISOString();
90
- }
91
-
92
20
  export function getExpirationDate(
93
21
  entitlement: RevenueCatEntitlement | null
94
22
  ): string | null {
95
- if (!entitlement) {
23
+ if (!entitlement?.expirationDate) {
96
24
  return null;
97
25
  }
98
26
 
99
- if (!entitlement.expirationDate) {
100
- return null;
27
+ const { expirationDate, productIdentifier, isSandbox, latestPurchaseDate } = entitlement;
28
+
29
+ if (shouldConvertSandbox(isSandbox)) {
30
+ return convertToProductionExpiration(latestPurchaseDate, productIdentifier);
101
31
  }
102
32
 
103
- return adjustExpirationDate(
104
- entitlement.expirationDate,
105
- entitlement.productIdentifier,
106
- entitlement.isSandbox ?? false,
107
- entitlement.latestPurchaseDate ?? null
108
- );
33
+ const expDate = new Date(expirationDate);
34
+ const adjustedDate = adjustPastExpiration(expDate, productIdentifier);
35
+
36
+ return adjustedDate.toISOString();
109
37
  }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Sandbox Duration Converter
3
+ * Converts Apple Sandbox subscription durations to production-equivalent dates
4
+ */
5
+
6
+ import { detectPackageType, type SubscriptionPackageType } from '../../../utils/packageTypeDetector';
7
+ import { getProductionDurationDays } from '../config/SandboxDurationConfig';
8
+
9
+ /**
10
+ * Add production period to a date based on package type
11
+ */
12
+ export function addProductionPeriod(
13
+ date: Date,
14
+ packageType: SubscriptionPackageType
15
+ ): Date {
16
+ const newDate = new Date(date);
17
+ const daysToAdd = getProductionDurationDays(packageType);
18
+ newDate.setDate(newDate.getDate() + daysToAdd);
19
+ return newDate;
20
+ }
21
+
22
+ /**
23
+ * Check if sandbox conversion should be applied
24
+ * Only applies in DEV mode with sandbox flag
25
+ */
26
+ export function shouldConvertSandbox(isSandbox: boolean): boolean {
27
+ return isSandbox && __DEV__;
28
+ }
29
+
30
+ /**
31
+ * Convert sandbox expiration to production-equivalent expiration
32
+ *
33
+ * In Apple Sandbox:
34
+ * - Weekly subscriptions expire in 3 minutes
35
+ * - Monthly subscriptions expire in 5 minutes
36
+ * - Yearly subscriptions expire in 1 hour
37
+ *
38
+ * For better testing UX, we calculate the production-equivalent expiration
39
+ * based on the purchase date + production duration.
40
+ */
41
+ export function convertToProductionExpiration(
42
+ purchaseDate: string | null,
43
+ productIdentifier: string
44
+ ): string {
45
+ const basePurchaseDate = purchaseDate ? new Date(purchaseDate) : new Date();
46
+ const packageType = detectPackageType(productIdentifier);
47
+ const productionExpiration = addProductionPeriod(basePurchaseDate, packageType);
48
+
49
+ return productionExpiration.toISOString();
50
+ }
51
+
52
+ /**
53
+ * Adjust expiration date if it's in the past
54
+ * Adds subscription period to prevent false expiration
55
+ */
56
+ export function adjustPastExpiration(
57
+ expirationDate: Date,
58
+ productIdentifier: string
59
+ ): Date {
60
+ const now = new Date();
61
+
62
+ if (expirationDate > now) {
63
+ return expirationDate;
64
+ }
65
+
66
+ const packageType = detectPackageType(productIdentifier);
67
+ return addProductionPeriod(expirationDate, packageType);
68
+ }