@umituz/react-native-subscription 2.27.41 → 2.27.43

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.41",
3
+ "version": "2.27.43",
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",
@@ -8,8 +8,6 @@ import React, { useMemo, useEffect } from "react";
8
8
  import { usePaywallVisibility } from "../../../presentation/hooks/usePaywallVisibility";
9
9
  import { useSubscriptionPackages } from "../../../revenuecat/presentation/hooks/useSubscriptionPackages";
10
10
  import { useRevenueCatTrialEligibility } from "../../../revenuecat/presentation/hooks/useRevenueCatTrialEligibility";
11
- import { filterPackagesByMode } from "../../../utils/packageFilter";
12
- import { createCreditAmountsFromPackages } from "../../../utils/creditMapper";
13
11
  import { PaywallModal, type TrialEligibilityInfo } from "./PaywallModal";
14
12
  import { usePaywallActions } from "../hooks/usePaywallActions";
15
13
  import type { PaywallContainerProps } from "./PaywallContainer.types";
@@ -17,14 +15,10 @@ import type { PaywallContainerProps } from "./PaywallContainer.types";
17
15
  export const PaywallContainer: React.FC<PaywallContainerProps> = (props) => {
18
16
  const {
19
17
  translations,
20
- mode = "subscription",
21
18
  legalUrls,
22
19
  features,
23
20
  heroImage,
24
21
  bestValueIdentifier,
25
- creditsLabel,
26
- creditAmounts,
27
- packageFilterConfig,
28
22
  source,
29
23
  onPurchaseSuccess,
30
24
  onPurchaseError,
@@ -40,7 +34,7 @@ export const PaywallContainer: React.FC<PaywallContainerProps> = (props) => {
40
34
 
41
35
  const purchaseSource = source ?? currentSource ?? "settings";
42
36
 
43
- const { data: allPackages = [], isLoading } = useSubscriptionPackages();
37
+ const { data: packages = [], isLoading } = useSubscriptionPackages();
44
38
  const { eligibilityMap, checkEligibility } = useRevenueCatTrialEligibility();
45
39
  const { handlePurchase, handleRestore } = usePaywallActions({
46
40
  source: purchaseSource,
@@ -53,10 +47,10 @@ export const PaywallContainer: React.FC<PaywallContainerProps> = (props) => {
53
47
  // Check trial eligibility only if trialConfig is enabled
54
48
  useEffect(() => {
55
49
  if (!trialConfig?.enabled) return;
56
- if (allPackages.length === 0) return;
50
+ if (packages.length === 0) return;
57
51
 
58
52
  // Get all actual product IDs from packages
59
- const allProductIds = allPackages.map((pkg) => pkg.product.identifier);
53
+ const allProductIds = packages.map((pkg) => pkg.product.identifier);
60
54
 
61
55
  // If eligibleProductIds are provided, filter to matching packages (partial match)
62
56
  // e.g., "yearly" matches "futureus.yearly"
@@ -74,7 +68,7 @@ export const PaywallContainer: React.FC<PaywallContainerProps> = (props) => {
74
68
  if (productIdsToCheck.length > 0) {
75
69
  checkEligibility(productIdsToCheck);
76
70
  }
77
- }, [allPackages, checkEligibility, trialConfig?.enabled, trialConfig?.eligibleProductIds]);
71
+ }, [packages, checkEligibility, trialConfig?.enabled, trialConfig?.eligibleProductIds]);
78
72
 
79
73
  // Convert eligibility map to format expected by PaywallModal
80
74
  // Only process if trial is enabled
@@ -91,11 +85,6 @@ export const PaywallContainer: React.FC<PaywallContainerProps> = (props) => {
91
85
  return result;
92
86
  }, [eligibilityMap, trialConfig?.enabled, trialConfig?.durationDays]);
93
87
 
94
- const { filteredPackages, computedCreditAmounts } = useMemo(() => ({
95
- filteredPackages: filterPackagesByMode(allPackages, mode, packageFilterConfig),
96
- computedCreditAmounts: mode !== "subscription" && !creditAmounts ? createCreditAmountsFromPackages(allPackages) : creditAmounts
97
- }), [allPackages, mode, packageFilterConfig, creditAmounts]);
98
-
99
88
  if (!isVisible) return null;
100
89
 
101
90
  return (
@@ -103,14 +92,12 @@ export const PaywallContainer: React.FC<PaywallContainerProps> = (props) => {
103
92
  visible={isVisible}
104
93
  onClose={handleClose}
105
94
  translations={translations}
106
- packages={filteredPackages}
95
+ packages={packages}
107
96
  isLoading={isLoading}
108
97
  legalUrls={legalUrls}
109
98
  features={features ? [...features] : undefined}
110
99
  heroImage={heroImage}
111
100
  bestValueIdentifier={bestValueIdentifier}
112
- creditsLabel={creditsLabel}
113
- creditAmounts={computedCreditAmounts}
114
101
  onPurchase={handlePurchase}
115
102
  onRestore={handleRestore}
116
103
  trialEligibility={trialEligibility}
@@ -1,11 +1,10 @@
1
1
  /**
2
2
  * PaywallContainer Types
3
- * Props for package-driven paywall with mode-based filtering
3
+ * Props for subscription paywall
4
4
  */
5
5
 
6
6
  import type { ImageSourcePropType } from "react-native";
7
- import type { PaywallMode, PaywallTranslations, PaywallLegalUrls, SubscriptionFeature } from "../entities";
8
- import type { PackageFilterConfig } from "../../../utils/packageFilter";
7
+ import type { PaywallTranslations, PaywallLegalUrls, SubscriptionFeature } from "../entities";
9
8
  import type { PurchaseSource } from "../../../domain/entities/Credits";
10
9
 
11
10
  /**
@@ -26,8 +25,6 @@ export interface TrialConfig {
26
25
  export interface PaywallContainerProps {
27
26
  /** Paywall translations - no defaults, must be provided */
28
27
  readonly translations: PaywallTranslations;
29
- /** Paywall mode - subscription, credits, or hybrid */
30
- readonly mode?: PaywallMode;
31
28
  /** Legal URLs for privacy and terms */
32
29
  readonly legalUrls?: PaywallLegalUrls;
33
30
  /** Feature list to display */
@@ -36,12 +33,6 @@ export interface PaywallContainerProps {
36
33
  readonly heroImage?: ImageSourcePropType;
37
34
  /** Best value package identifier for badge */
38
35
  readonly bestValueIdentifier?: string;
39
- /** Credits label text */
40
- readonly creditsLabel?: string;
41
- /** Credit amounts per package identifier */
42
- readonly creditAmounts?: Record<string, number>;
43
- /** Custom filter config for package categorization */
44
- readonly packageFilterConfig?: PackageFilterConfig;
45
36
  /** Source of the paywall - affects pending purchase handling */
46
37
  readonly source?: PurchaseSource;
47
38
  /** Callback when purchase succeeds */
@@ -57,4 +48,3 @@ export interface PaywallContainerProps {
57
48
  /** Trial display configuration (Apple-compliant) */
58
49
  readonly trialConfig?: TrialConfig;
59
50
  }
60
-
@@ -33,8 +33,6 @@ export interface PaywallModalProps {
33
33
  isLoading?: boolean;
34
34
  legalUrls?: PaywallLegalUrls;
35
35
  bestValueIdentifier?: string;
36
- creditAmounts?: Record<string, number>;
37
- creditsLabel?: string;
38
36
  heroImage?: ImageSourcePropType;
39
37
  onPurchase?: (pkg: PurchasesPackage) => Promise<void | boolean>;
40
38
  onRestore?: () => Promise<void | boolean>;
@@ -45,7 +43,7 @@ export interface PaywallModalProps {
45
43
  }
46
44
 
47
45
  export const PaywallModal: React.FC<PaywallModalProps> = React.memo((props) => {
48
- const { visible, onClose, translations, packages = [], features = [], isLoading = false, legalUrls = {}, bestValueIdentifier, creditAmounts, creditsLabel, heroImage, onPurchase, onRestore, trialEligibility = {}, trialSubtitleText } = props;
46
+ const { visible, onClose, translations, packages = [], features = [], isLoading = false, legalUrls = {}, bestValueIdentifier, heroImage, onPurchase, onRestore, trialEligibility = {}, trialSubtitleText } = props;
49
47
  const tokens = useAppDesignTokens();
50
48
  const [selectedPlanId, setSelectedPlanId] = useState<string | null>(null);
51
49
  const [isLocalProcessing, setIsLocalProcessing] = useState(false);
@@ -152,8 +150,6 @@ export const PaywallModal: React.FC<PaywallModalProps> = React.memo((props) => {
152
150
  isSelected={selectedPlanId === productId}
153
151
  onSelect={() => setSelectedPlanId(productId)}
154
152
  badge={productId === bestValueIdentifier ? translations.bestValueBadgeText : undefined}
155
- creditAmount={creditAmounts?.[productId]}
156
- creditsLabel={creditsLabel}
157
153
  hasFreeTrial={hasFreeTrial}
158
154
  trialSubtitleText={hasFreeTrial ? trialSubtitleText : undefined}
159
155
  />
@@ -21,8 +21,6 @@ interface PlanCardProps {
21
21
  onSelect: () => void;
22
22
  /** Badge text (e.g., "Best Value") - NOT for trial */
23
23
  badge?: string;
24
- creditAmount?: number;
25
- creditsLabel?: string;
26
24
  /** Whether this plan has a free trial (Apple-compliant display) */
27
25
  hasFreeTrial?: boolean;
28
26
  /** Trial subtitle text (e.g., "7 days free, then billed") - shown as small gray text */
@@ -30,7 +28,7 @@ interface PlanCardProps {
30
28
  }
31
29
 
32
30
  export const PlanCard: React.FC<PlanCardProps> = React.memo(
33
- ({ pkg, isSelected, onSelect, badge, creditAmount, creditsLabel, hasFreeTrial, trialSubtitleText }) => {
31
+ ({ pkg, isSelected, onSelect, badge, hasFreeTrial, trialSubtitleText }) => {
34
32
  const tokens = useAppDesignTokens();
35
33
  const title = pkg.product.title;
36
34
  const price = formatPriceWithPeriod(pkg.product.price, pkg.product.currencyCode, pkg.identifier);
@@ -75,13 +73,6 @@ export const PlanCard: React.FC<PlanCardProps> = React.memo(
75
73
  {title}
76
74
  </AtomicText>
77
75
 
78
- {/* Credits info */}
79
- {creditAmount && creditsLabel && (
80
- <AtomicText type="bodySmall" style={{ color: tokens.colors.textSecondary }}>
81
- {creditAmount} {creditsLabel}
82
- </AtomicText>
83
- )}
84
-
85
76
  {/* Trial info - Apple-compliant: small, gray, subordinate */}
86
77
  {hasFreeTrial && trialSubtitleText && (
87
78
  <AtomicText
@@ -9,9 +9,7 @@ export { PaywallModal } from "./PaywallModal";
9
9
  export type { PaywallModalProps } from "./PaywallModal";
10
10
 
11
11
  export { PaywallHeader } from "./PaywallHeader";
12
- export { PaywallTabBar } from "./PaywallTabBar";
13
12
  export { PaywallFooter } from "./PaywallFooter";
14
13
  export { FeatureList } from "./FeatureList";
15
14
  export { FeatureItem } from "./FeatureItem";
16
15
  export { PlanCard } from "./PlanCard";
17
- export { CreditCard } from "./CreditCard";
@@ -3,25 +3,6 @@
3
3
  * All paywall-related type definitions
4
4
  */
5
5
 
6
- export type PaywallMode = "subscription" | "credits" | "hybrid";
7
-
8
- export type PaywallTabType = "credits" | "subscription";
9
-
10
- export interface PaywallTab {
11
- id: PaywallTabType;
12
- label: string;
13
- }
14
-
15
- export interface CreditsPackage {
16
- id: string;
17
- credits: number;
18
- price: number;
19
- currency: string;
20
- bonus?: number;
21
- badge?: string;
22
- description?: string;
23
- }
24
-
25
6
  export interface SubscriptionFeature {
26
7
  icon: string;
27
8
  text: string;
@@ -30,10 +11,7 @@ export interface SubscriptionFeature {
30
11
  export interface PaywallTranslations {
31
12
  title: string;
32
13
  subtitle?: string;
33
- creditsTabLabel?: string;
34
- subscriptionTabLabel?: string;
35
14
  purchaseButtonText: string;
36
- subscribeButtonText?: string;
37
15
  restoreButtonText: string;
38
16
  loadingText: string;
39
17
  emptyText: string;
@@ -2,7 +2,6 @@
2
2
  * Paywall Hooks Index
3
3
  */
4
4
 
5
- export { usePaywall } from './usePaywall';
6
5
  export { useSubscriptionModal } from './useSubscriptionModal';
7
6
  export { usePaywallActions } from './usePaywallActions';
8
7
  export {
@@ -1,4 +1,4 @@
1
- import { detectPackageType, type SubscriptionPackageType } from "./packageTypeDetector";
1
+ import type { SubscriptionPackageType } from "./packageTypeDetector";
2
2
  import type { PackageAllocationMap } from "../domain/entities/Credits";
3
3
 
4
4
  /**
@@ -11,31 +11,3 @@ export function getCreditAllocation(
11
11
  if (packageType === "unknown" || !allocations) return null;
12
12
  return allocations[packageType]?.credits ?? null;
13
13
  }
14
-
15
- /**
16
- * Create credit amounts mapping for PaywallModal from RevenueCat packages
17
- * Maps product.identifier to credit amount using dynamic allocations
18
- */
19
- export function createCreditAmountsFromPackages(
20
- packages: Array<{ product: { identifier: string } }>,
21
- allocations?: PackageAllocationMap
22
- ): Record<string, number> {
23
- const result: Record<string, number> = {};
24
-
25
- if (!allocations) return result;
26
-
27
- for (const pkg of packages) {
28
- const identifier = pkg?.product?.identifier;
29
-
30
- if (!identifier) continue;
31
-
32
- const packageType = detectPackageType(identifier);
33
- const credits = getCreditAllocation(packageType, allocations);
34
-
35
- if (credits !== null) {
36
- result[identifier] = credits;
37
- }
38
- }
39
-
40
- return result;
41
- }
@@ -2,7 +2,6 @@ export * from "./aiCreditHelpers";
2
2
  export * from "./authUtils";
3
3
  export * from "./creditChecker";
4
4
  export * from "./creditMapper";
5
- export * from "./packageFilter";
6
5
  export * from "./packagePeriodUtils";
7
6
  export * from "./packageTypeDetector";
8
7
  export * from "./premiumStatusUtils";
@@ -1,120 +0,0 @@
1
- /**
2
- * Credit Card
3
- * Credit package selection card
4
- */
5
-
6
- import React from "react";
7
- import { View, TouchableOpacity, StyleSheet } from "react-native";
8
- import { AtomicText, AtomicIcon, AtomicBadge, useAppDesignTokens } from "@umituz/react-native-design-system";
9
- import type { CreditsPackage } from '../entities';
10
-
11
- import { formatPrice } from '../../../utils/priceUtils';
12
-
13
- interface CreditCardProps {
14
- pkg: CreditsPackage;
15
- isSelected: boolean;
16
- onSelect: () => void;
17
- }
18
-
19
- export const CreditCard: React.FC<CreditCardProps> = React.memo(({ pkg, isSelected, onSelect }) => {
20
- const tokens = useAppDesignTokens();
21
- const totalCredits = pkg.credits + (pkg.bonus ?? 0);
22
- const price = formatPrice(pkg.price, pkg.currency);
23
-
24
- return (
25
- <TouchableOpacity onPress={onSelect} activeOpacity={0.7} style={styles.touchable}>
26
- <View
27
- style={[
28
- styles.container,
29
- {
30
- backgroundColor: tokens.colors.surface,
31
- borderColor: isSelected ? tokens.colors.primary : tokens.colors.border,
32
- borderWidth: isSelected ? 2 : 1,
33
- },
34
- ]}
35
- >
36
- {pkg.badge && (
37
- <View style={styles.badgeContainer}>
38
- <AtomicBadge text={pkg.badge} variant="warning" size="sm" />
39
- </View>
40
- )}
41
-
42
- <View style={styles.content}>
43
- <View style={styles.leftSection}>
44
- <AtomicIcon name="flash" size="md" color={isSelected ? "primary" : "secondary"} />
45
- <AtomicText
46
- type="headlineSmall"
47
- style={[styles.credits, { color: isSelected ? tokens.colors.primary : tokens.colors.textPrimary }]}
48
- >
49
- {totalCredits.toLocaleString()}
50
- </AtomicText>
51
- </View>
52
-
53
- <View style={styles.rightSection}>
54
- <AtomicText
55
- type="titleLarge"
56
- style={[styles.price, { color: isSelected ? tokens.colors.primary : tokens.colors.textPrimary }]}
57
- >
58
- {price}
59
- </AtomicText>
60
- {isSelected && <AtomicIcon name="checkmark-circle" size="md" color="primary" />}
61
- </View>
62
- </View>
63
-
64
- {(pkg.bonus ?? 0) > 0 && (
65
- <View style={styles.bonusRow}>
66
- <AtomicIcon name="gift-outline" size="sm" color="success" />
67
- <AtomicText type="bodySmall" style={{ color: tokens.colors.success, marginLeft: 4 }}>
68
- +{pkg.bonus}
69
- </AtomicText>
70
- </View>
71
- )}
72
- </View>
73
- </TouchableOpacity>
74
- );
75
- });
76
-
77
- CreditCard.displayName = "CreditCard";
78
-
79
- const styles = StyleSheet.create({
80
- touchable: {
81
- marginBottom: 10,
82
- marginHorizontal: 24,
83
- },
84
- container: {
85
- borderRadius: 16,
86
- padding: 16,
87
- position: "relative",
88
- },
89
- badgeContainer: {
90
- position: "absolute",
91
- top: -10,
92
- right: 16,
93
- },
94
- content: {
95
- flexDirection: "row",
96
- justifyContent: "space-between",
97
- alignItems: "center",
98
- },
99
- leftSection: {
100
- flexDirection: "row",
101
- alignItems: "center",
102
- },
103
- credits: {
104
- fontWeight: "700",
105
- marginLeft: 8,
106
- },
107
- rightSection: {
108
- flexDirection: "row",
109
- alignItems: "center",
110
- },
111
- price: {
112
- fontWeight: "700",
113
- marginRight: 8,
114
- },
115
- bonusRow: {
116
- flexDirection: "row",
117
- alignItems: "center",
118
- marginTop: 8,
119
- },
120
- });
@@ -1,77 +0,0 @@
1
- /**
2
- * Paywall Tab Bar
3
- * Segmented control for hybrid mode
4
- */
5
-
6
- import React from "react";
7
- import { View, TouchableOpacity, StyleSheet } from "react-native";
8
- import { AtomicText, useAppDesignTokens } from "@umituz/react-native-design-system";
9
- import type { PaywallTabType } from '../entities';
10
-
11
- interface PaywallTabBarProps {
12
- activeTab: PaywallTabType;
13
- onTabChange: (tab: PaywallTabType) => void;
14
- creditsLabel: string;
15
- subscriptionLabel: string;
16
- }
17
-
18
- export const PaywallTabBar: React.FC<PaywallTabBarProps> = React.memo(
19
- ({ activeTab, onTabChange, creditsLabel, subscriptionLabel }) => {
20
- const tokens = useAppDesignTokens();
21
-
22
- const renderTab = (tab: PaywallTabType, label: string) => {
23
- const isActive = activeTab === tab;
24
-
25
- return (
26
- <TouchableOpacity
27
- key={tab}
28
- style={[
29
- styles.tab,
30
- isActive ? { backgroundColor: tokens.colors.surface } : undefined,
31
- ]}
32
- onPress={() => onTabChange(tab)}
33
- activeOpacity={0.7}
34
- >
35
- <AtomicText
36
- type="labelLarge"
37
- style={[
38
- styles.tabText,
39
- { color: isActive ? tokens.colors.primary : tokens.colors.textSecondary },
40
- ]}
41
- >
42
- {label}
43
- </AtomicText>
44
- </TouchableOpacity>
45
- );
46
- };
47
-
48
- return (
49
- <View style={[styles.container, { backgroundColor: tokens.colors.surfaceSecondary }]}>
50
- {renderTab("credits", creditsLabel)}
51
- {renderTab("subscription", subscriptionLabel)}
52
- </View>
53
- );
54
- }
55
- );
56
-
57
- PaywallTabBar.displayName = "PaywallTabBar";
58
-
59
- const styles = StyleSheet.create({
60
- container: {
61
- flexDirection: "row",
62
- borderRadius: 12,
63
- padding: 4,
64
- marginHorizontal: 24,
65
- marginBottom: 16,
66
- height: 44,
67
- },
68
- tab: {
69
- flex: 1,
70
- alignItems: "center",
71
- justifyContent: "center",
72
- borderRadius: 8,
73
- },
74
- tabText: {
75
- fontWeight: "600",
76
- },
77
- });
@@ -1,54 +0,0 @@
1
- import { useState, useCallback } from "react";
2
- import type { PurchasesPackage } from "react-native-purchases";
3
- import type { PaywallTabType } from "../entities";
4
-
5
- interface UsePaywallProps {
6
- initialTab?: PaywallTabType;
7
- onCreditsPurchase: (packageId: string) => Promise<void>;
8
- onSubscriptionPurchase: (pkg: PurchasesPackage) => Promise<void>;
9
- }
10
-
11
- export const usePaywall = ({
12
- initialTab = "credits",
13
- onCreditsPurchase,
14
- onSubscriptionPurchase,
15
- }: UsePaywallProps) => {
16
- const [activeTab, setActiveTab] = useState<PaywallTabType>(initialTab);
17
- const [selectedCreditsPackageId, setSelectedCreditsPackageId] = useState<string | null>(null);
18
- const [selectedSubscriptionPkg, setSelectedSubscriptionPkg] = useState<PurchasesPackage | null>(null);
19
-
20
- const handleTabChange = useCallback((tab: PaywallTabType) => {
21
- setActiveTab(tab);
22
- }, []);
23
-
24
- const handleCreditsPackageSelect = useCallback((packageId: string) => {
25
- setSelectedCreditsPackageId(packageId);
26
- }, []);
27
-
28
- const handleSubscriptionPackageSelect = useCallback((pkg: PurchasesPackage) => {
29
- setSelectedSubscriptionPkg(pkg);
30
- }, []);
31
-
32
- const handleCreditsPurchase = useCallback(async () => {
33
- if (selectedCreditsPackageId) {
34
- await onCreditsPurchase(selectedCreditsPackageId);
35
- }
36
- }, [selectedCreditsPackageId, onCreditsPurchase]);
37
-
38
- const handleSubscriptionPurchase = useCallback(async () => {
39
- if (selectedSubscriptionPkg) {
40
- await onSubscriptionPurchase(selectedSubscriptionPkg);
41
- }
42
- }, [selectedSubscriptionPkg, onSubscriptionPurchase]);
43
-
44
- return {
45
- activeTab,
46
- selectedCreditsPackageId,
47
- selectedSubscriptionPkg,
48
- handleTabChange,
49
- handleCreditsPackageSelect,
50
- handleSubscriptionPackageSelect,
51
- handleCreditsPurchase,
52
- handleSubscriptionPurchase,
53
- };
54
- };
@@ -1,62 +0,0 @@
1
- /**
2
- * Package Filter Utility
3
- * Filters RevenueCat packages by type (credits vs subscription)
4
- */
5
-
6
- import type { PurchasesPackage } from "react-native-purchases";
7
-
8
- export type PackageCategory = "credits" | "subscription";
9
-
10
- export interface PackageFilterConfig {
11
- creditIdentifierPattern?: RegExp;
12
- subscriptionIdentifierPattern?: RegExp;
13
- }
14
-
15
- const DEFAULT_CONFIG: PackageFilterConfig = {
16
- creditIdentifierPattern: /credit/i,
17
- subscriptionIdentifierPattern: /(monthly|yearly|annual|weekly|premium|subscription)/i,
18
- };
19
-
20
- export function getPackageCategory(
21
- pkg: PurchasesPackage,
22
- config: PackageFilterConfig = DEFAULT_CONFIG
23
- ): PackageCategory {
24
- const identifier = pkg.identifier.toLowerCase();
25
- const productIdentifier = pkg.product.identifier.toLowerCase();
26
-
27
- const isCreditPackage =
28
- config.creditIdentifierPattern?.test(identifier) ||
29
- config.creditIdentifierPattern?.test(productIdentifier);
30
-
31
- return isCreditPackage ? "credits" : "subscription";
32
- }
33
-
34
- export function filterPackagesByMode(
35
- packages: PurchasesPackage[],
36
- mode: "credits" | "subscription" | "hybrid",
37
- config: PackageFilterConfig = DEFAULT_CONFIG
38
- ): PurchasesPackage[] {
39
- if (mode === "hybrid") {
40
- return packages;
41
- }
42
-
43
- return packages.filter((pkg) => getPackageCategory(pkg, config) === mode);
44
- }
45
-
46
- export function separatePackages(
47
- packages: PurchasesPackage[],
48
- config: PackageFilterConfig = DEFAULT_CONFIG
49
- ): { creditPackages: PurchasesPackage[]; subscriptionPackages: PurchasesPackage[] } {
50
- const creditPackages: PurchasesPackage[] = [];
51
- const subscriptionPackages: PurchasesPackage[] = [];
52
-
53
- for (const pkg of packages) {
54
- if (getPackageCategory(pkg, config) === "credits") {
55
- creditPackages.push(pkg);
56
- } else {
57
- subscriptionPackages.push(pkg);
58
- }
59
- }
60
-
61
- return { creditPackages, subscriptionPackages };
62
- }