@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.
|
|
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
|
-
*
|
|
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 {
|
|
7
|
+
import {
|
|
8
|
+
shouldConvertSandbox,
|
|
9
|
+
convertToProductionExpiration,
|
|
10
|
+
adjustPastExpiration,
|
|
11
|
+
} from './SandboxDurationConverter';
|
|
9
12
|
|
|
10
13
|
/**
|
|
11
|
-
*
|
|
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
|
|
63
|
-
* 1. Sandbox mode:
|
|
64
|
-
* 2.
|
|
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
|
-
|
|
100
|
-
|
|
27
|
+
const { expirationDate, productIdentifier, isSandbox, latestPurchaseDate } = entitlement;
|
|
28
|
+
|
|
29
|
+
if (shouldConvertSandbox(isSandbox)) {
|
|
30
|
+
return convertToProductionExpiration(latestPurchaseDate, productIdentifier);
|
|
101
31
|
}
|
|
102
32
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
+
}
|