@sudobility/subscription_lib 0.0.1

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 (52) hide show
  1. package/dist/core/index.d.ts +6 -0
  2. package/dist/core/index.d.ts.map +1 -0
  3. package/dist/core/index.js +5 -0
  4. package/dist/core/service.d.ts +74 -0
  5. package/dist/core/service.d.ts.map +1 -0
  6. package/dist/core/service.js +251 -0
  7. package/dist/core/singleton.d.ts +65 -0
  8. package/dist/core/singleton.d.ts.map +1 -0
  9. package/dist/core/singleton.js +73 -0
  10. package/dist/hooks/index.d.ts +9 -0
  11. package/dist/hooks/index.d.ts.map +1 -0
  12. package/dist/hooks/index.js +8 -0
  13. package/dist/hooks/useSubscribable.d.ts +50 -0
  14. package/dist/hooks/useSubscribable.d.ts.map +1 -0
  15. package/dist/hooks/useSubscribable.js +80 -0
  16. package/dist/hooks/useSubscriptionForPeriod.d.ts +48 -0
  17. package/dist/hooks/useSubscriptionForPeriod.d.ts.map +1 -0
  18. package/dist/hooks/useSubscriptionForPeriod.js +59 -0
  19. package/dist/hooks/useSubscriptionPeriods.d.ts +38 -0
  20. package/dist/hooks/useSubscriptionPeriods.d.ts.map +1 -0
  21. package/dist/hooks/useSubscriptionPeriods.js +44 -0
  22. package/dist/hooks/useSubscriptions.d.ts +43 -0
  23. package/dist/hooks/useSubscriptions.d.ts.map +1 -0
  24. package/dist/hooks/useSubscriptions.js +80 -0
  25. package/dist/hooks/useUserSubscription.d.ts +39 -0
  26. package/dist/hooks/useUserSubscription.d.ts.map +1 -0
  27. package/dist/hooks/useUserSubscription.js +76 -0
  28. package/dist/index.d.ts +12 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +13 -0
  31. package/dist/types/adapter.d.ts +149 -0
  32. package/dist/types/adapter.d.ts.map +1 -0
  33. package/dist/types/adapter.js +7 -0
  34. package/dist/types/index.d.ts +8 -0
  35. package/dist/types/index.d.ts.map +1 -0
  36. package/dist/types/index.js +4 -0
  37. package/dist/types/period.d.ts +18 -0
  38. package/dist/types/period.d.ts.map +1 -0
  39. package/dist/types/period.js +25 -0
  40. package/dist/types/subscription.d.ts +95 -0
  41. package/dist/types/subscription.d.ts.map +1 -0
  42. package/dist/types/subscription.js +6 -0
  43. package/dist/utils/index.d.ts +6 -0
  44. package/dist/utils/index.d.ts.map +1 -0
  45. package/dist/utils/index.js +5 -0
  46. package/dist/utils/level-calculator.d.ts +68 -0
  47. package/dist/utils/level-calculator.d.ts.map +1 -0
  48. package/dist/utils/level-calculator.js +164 -0
  49. package/dist/utils/period-parser.d.ts +45 -0
  50. package/dist/utils/period-parser.d.ts.map +1 -0
  51. package/dist/utils/period-parser.js +113 -0
  52. package/package.json +55 -0
@@ -0,0 +1,48 @@
1
+ /**
2
+ * useSubscriptionForPeriod Hook
3
+ *
4
+ * Get packages filtered by billing period, sorted by price.
5
+ */
6
+ import type { SubscriptionPackage } from '../types/subscription';
7
+ import type { SubscriptionPeriod } from '../types/period';
8
+ /**
9
+ * Result of useSubscriptionForPeriod hook
10
+ */
11
+ export interface UseSubscriptionForPeriodResult {
12
+ /** Packages for the period, sorted by price (ascending), includes free tier first */
13
+ packages: SubscriptionPackage[];
14
+ /** Whether data is being loaded */
15
+ isLoading: boolean;
16
+ /** Error if loading failed */
17
+ error: Error | null;
18
+ }
19
+ /**
20
+ * Hook to get packages filtered by billing period
21
+ *
22
+ * Returns packages sorted by price (ascending):
23
+ * - Free tier first (if configured)
24
+ * - Then paid packages from lowest to highest price
25
+ *
26
+ * @param offerId Offer identifier
27
+ * @param period Billing period to filter by
28
+ * @returns Filtered and sorted packages
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const { packages, isLoading } = useSubscriptionForPeriod('default', 'monthly');
33
+ *
34
+ * return (
35
+ * <div className="grid">
36
+ * {packages.map(pkg => (
37
+ * <SubscriptionTile
38
+ * key={pkg.packageId}
39
+ * title={pkg.name}
40
+ * price={pkg.product?.priceString ?? 'Free'}
41
+ * />
42
+ * ))}
43
+ * </div>
44
+ * );
45
+ * ```
46
+ */
47
+ export declare function useSubscriptionForPeriod(offerId: string, period: SubscriptionPeriod): UseSubscriptionForPeriodResult;
48
+ //# sourceMappingURL=useSubscriptionForPeriod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSubscriptionForPeriod.d.ts","sourceRoot":"","sources":["../../src/hooks/useSubscriptionForPeriod.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAO1D;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C,qFAAqF;IACrF,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,8BAA8B;IAC9B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,kBAAkB,GACzB,8BAA8B,CA6BhC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * useSubscriptionForPeriod Hook
3
+ *
4
+ * Get packages filtered by billing period, sorted by price.
5
+ */
6
+ import { useMemo } from 'react';
7
+ import { useSubscriptions } from './useSubscriptions';
8
+ import { getSubscriptionInstance, isSubscriptionInitialized, } from '../core/singleton';
9
+ /**
10
+ * Hook to get packages filtered by billing period
11
+ *
12
+ * Returns packages sorted by price (ascending):
13
+ * - Free tier first (if configured)
14
+ * - Then paid packages from lowest to highest price
15
+ *
16
+ * @param offerId Offer identifier
17
+ * @param period Billing period to filter by
18
+ * @returns Filtered and sorted packages
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const { packages, isLoading } = useSubscriptionForPeriod('default', 'monthly');
23
+ *
24
+ * return (
25
+ * <div className="grid">
26
+ * {packages.map(pkg => (
27
+ * <SubscriptionTile
28
+ * key={pkg.packageId}
29
+ * title={pkg.name}
30
+ * price={pkg.product?.priceString ?? 'Free'}
31
+ * />
32
+ * ))}
33
+ * </div>
34
+ * );
35
+ * ```
36
+ */
37
+ export function useSubscriptionForPeriod(offerId, period) {
38
+ const { offer, isLoading, error } = useSubscriptions(offerId);
39
+ const packages = useMemo(() => {
40
+ if (!offer)
41
+ return [];
42
+ // Filter packages by period
43
+ const periodPackages = offer.packages.filter(pkg => pkg.product && pkg.product.period === period);
44
+ // Sort by price ascending
45
+ periodPackages.sort((a, b) => {
46
+ const priceA = a.product?.price ?? 0;
47
+ const priceB = b.product?.price ?? 0;
48
+ return priceA - priceB;
49
+ });
50
+ // Add free tier at the beginning if subscription is initialized
51
+ if (isSubscriptionInitialized()) {
52
+ const service = getSubscriptionInstance();
53
+ const freeTier = service.getFreeTierPackage();
54
+ return [freeTier, ...periodPackages];
55
+ }
56
+ return periodPackages;
57
+ }, [offer, period]);
58
+ return { packages, isLoading, error };
59
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * useSubscriptionPeriods Hook
3
+ *
4
+ * Extract unique billing periods from an offer's packages.
5
+ */
6
+ import type { SubscriptionPeriod } from '../types/period';
7
+ /**
8
+ * Result of useSubscriptionPeriods hook
9
+ */
10
+ export interface UseSubscriptionPeriodsResult {
11
+ /** Available periods sorted (weekly → monthly → quarterly → yearly → lifetime) */
12
+ periods: SubscriptionPeriod[];
13
+ /** Whether data is being loaded */
14
+ isLoading: boolean;
15
+ /** Error if loading failed */
16
+ error: Error | null;
17
+ }
18
+ /**
19
+ * Hook to get available billing periods from an offer
20
+ *
21
+ * @param offerId Offer identifier
22
+ * @returns Available periods, sorted from shortest to longest
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const { periods, isLoading } = useSubscriptionPeriods('default');
27
+ *
28
+ * return (
29
+ * <SegmentedControl
30
+ * options={periods.map(p => ({ value: p, label: capitalize(p) }))}
31
+ * value={selectedPeriod}
32
+ * onChange={setSelectedPeriod}
33
+ * />
34
+ * );
35
+ * ```
36
+ */
37
+ export declare function useSubscriptionPeriods(offerId: string): UseSubscriptionPeriodsResult;
38
+ //# sourceMappingURL=useSubscriptionPeriods.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSubscriptionPeriods.d.ts","sourceRoot":"","sources":["../../src/hooks/useSubscriptionPeriods.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAI1D;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,kFAAkF;IAClF,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,8BAA8B;IAC9B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,GACd,4BAA4B,CAoB9B"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * useSubscriptionPeriods Hook
3
+ *
4
+ * Extract unique billing periods from an offer's packages.
5
+ */
6
+ import { useMemo } from 'react';
7
+ import { ALL_PERIODS } from '../types/period';
8
+ import { useSubscriptions } from './useSubscriptions';
9
+ /**
10
+ * Hook to get available billing periods from an offer
11
+ *
12
+ * @param offerId Offer identifier
13
+ * @returns Available periods, sorted from shortest to longest
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const { periods, isLoading } = useSubscriptionPeriods('default');
18
+ *
19
+ * return (
20
+ * <SegmentedControl
21
+ * options={periods.map(p => ({ value: p, label: capitalize(p) }))}
22
+ * value={selectedPeriod}
23
+ * onChange={setSelectedPeriod}
24
+ * />
25
+ * );
26
+ * ```
27
+ */
28
+ export function useSubscriptionPeriods(offerId) {
29
+ const { offer, isLoading, error } = useSubscriptions(offerId);
30
+ const periods = useMemo(() => {
31
+ if (!offer)
32
+ return [];
33
+ // Collect unique periods from packages that have products
34
+ const periodSet = new Set();
35
+ for (const pkg of offer.packages) {
36
+ if (pkg.product) {
37
+ periodSet.add(pkg.product.period);
38
+ }
39
+ }
40
+ // Sort by the standard order
41
+ return ALL_PERIODS.filter(p => periodSet.has(p));
42
+ }, [offer]);
43
+ return { periods, isLoading, error };
44
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * useSubscriptions Hook
3
+ *
4
+ * Fetch and manage subscription offer data.
5
+ */
6
+ import type { SubscriptionOffer } from '../types/subscription';
7
+ /**
8
+ * Result of useSubscriptions hook
9
+ */
10
+ export interface UseSubscriptionsResult {
11
+ /** The requested offer, null if not found or loading */
12
+ offer: SubscriptionOffer | null;
13
+ /** Whether data is being loaded */
14
+ isLoading: boolean;
15
+ /** Error if loading failed */
16
+ error: Error | null;
17
+ /** Manually refetch the data */
18
+ refetch: () => Promise<void>;
19
+ }
20
+ /**
21
+ * Hook to get subscription offer data
22
+ *
23
+ * @param offerId Offer identifier to fetch
24
+ * @returns Offer data, loading state, and error
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const { offer, isLoading, error } = useSubscriptions('default');
29
+ *
30
+ * if (isLoading) return <Spinner />;
31
+ * if (error) return <Error message={error.message} />;
32
+ *
33
+ * return (
34
+ * <div>
35
+ * {offer?.packages.map(pkg => (
36
+ * <SubscriptionTile key={pkg.packageId} package={pkg} />
37
+ * ))}
38
+ * </div>
39
+ * );
40
+ * ```
41
+ */
42
+ export declare function useSubscriptions(offerId: string): UseSubscriptionsResult;
43
+ //# sourceMappingURL=useSubscriptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSubscriptions.d.ts","sourceRoot":"","sources":["../../src/hooks/useSubscriptions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAM/D;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,wDAAwD;IACxD,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAChC,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,8BAA8B;IAC9B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,gCAAgC;IAChC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,sBAAsB,CAsDxE"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * useSubscriptions Hook
3
+ *
4
+ * Fetch and manage subscription offer data.
5
+ */
6
+ import { useCallback, useEffect, useState } from 'react';
7
+ import { getSubscriptionInstance, isSubscriptionInitialized, } from '../core/singleton';
8
+ /**
9
+ * Hook to get subscription offer data
10
+ *
11
+ * @param offerId Offer identifier to fetch
12
+ * @returns Offer data, loading state, and error
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const { offer, isLoading, error } = useSubscriptions('default');
17
+ *
18
+ * if (isLoading) return <Spinner />;
19
+ * if (error) return <Error message={error.message} />;
20
+ *
21
+ * return (
22
+ * <div>
23
+ * {offer?.packages.map(pkg => (
24
+ * <SubscriptionTile key={pkg.packageId} package={pkg} />
25
+ * ))}
26
+ * </div>
27
+ * );
28
+ * ```
29
+ */
30
+ export function useSubscriptions(offerId) {
31
+ const [offer, setOffer] = useState(null);
32
+ const [isLoading, setIsLoading] = useState(true);
33
+ const [error, setError] = useState(null);
34
+ const loadData = useCallback(async () => {
35
+ if (!isSubscriptionInitialized()) {
36
+ setError(new Error('Subscription not initialized'));
37
+ setIsLoading(false);
38
+ return;
39
+ }
40
+ const service = getSubscriptionInstance();
41
+ try {
42
+ setIsLoading(true);
43
+ setError(null);
44
+ // Load offerings if not already loaded
45
+ if (!service.hasLoadedOfferings()) {
46
+ await service.loadOfferings();
47
+ }
48
+ const loadedOffer = service.getOffer(offerId);
49
+ setOffer(loadedOffer);
50
+ }
51
+ catch (err) {
52
+ setError(err instanceof Error ? err : new Error('Failed to load offer'));
53
+ }
54
+ finally {
55
+ setIsLoading(false);
56
+ }
57
+ }, [offerId]);
58
+ useEffect(() => {
59
+ loadData();
60
+ }, [loadData]);
61
+ const refetch = useCallback(async () => {
62
+ if (!isSubscriptionInitialized())
63
+ return;
64
+ const service = getSubscriptionInstance();
65
+ try {
66
+ setIsLoading(true);
67
+ setError(null);
68
+ await service.loadOfferings();
69
+ const loadedOffer = service.getOffer(offerId);
70
+ setOffer(loadedOffer);
71
+ }
72
+ catch (err) {
73
+ setError(err instanceof Error ? err : new Error('Failed to load offer'));
74
+ }
75
+ finally {
76
+ setIsLoading(false);
77
+ }
78
+ }, [offerId]);
79
+ return { offer, isLoading, error, refetch };
80
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * useUserSubscription Hook
3
+ *
4
+ * Fetch and manage current user's subscription status.
5
+ */
6
+ import type { CurrentSubscription } from '../types/subscription';
7
+ /**
8
+ * Result of useUserSubscription hook
9
+ */
10
+ export interface UseUserSubscriptionResult {
11
+ /** Current subscription info, null if loading */
12
+ subscription: CurrentSubscription | null;
13
+ /** Whether data is being loaded */
14
+ isLoading: boolean;
15
+ /** Error if loading failed */
16
+ error: Error | null;
17
+ /** Manually refetch the data */
18
+ refetch: () => Promise<void>;
19
+ }
20
+ /**
21
+ * Hook to get current user's subscription status
22
+ *
23
+ * @returns Current subscription data, loading state, and error
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * const { subscription, isLoading } = useUserSubscription();
28
+ *
29
+ * if (isLoading) return <Spinner />;
30
+ *
31
+ * if (subscription?.isActive) {
32
+ * return <div>Your plan: {subscription.entitlements.join(', ')}</div>;
33
+ * } else {
34
+ * return <div>No active subscription</div>;
35
+ * }
36
+ * ```
37
+ */
38
+ export declare function useUserSubscription(): UseUserSubscriptionResult;
39
+ //# sourceMappingURL=useUserSubscription.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useUserSubscription.d.ts","sourceRoot":"","sources":["../../src/hooks/useUserSubscription.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAMjE;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,iDAAiD;IACjD,YAAY,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACzC,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,8BAA8B;IAC9B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,gCAAgC;IAChC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,IAAI,yBAAyB,CA4D/D"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * useUserSubscription Hook
3
+ *
4
+ * Fetch and manage current user's subscription status.
5
+ */
6
+ import { useCallback, useEffect, useState } from 'react';
7
+ import { getSubscriptionInstance, isSubscriptionInitialized, } from '../core/singleton';
8
+ /**
9
+ * Hook to get current user's subscription status
10
+ *
11
+ * @returns Current subscription data, loading state, and error
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const { subscription, isLoading } = useUserSubscription();
16
+ *
17
+ * if (isLoading) return <Spinner />;
18
+ *
19
+ * if (subscription?.isActive) {
20
+ * return <div>Your plan: {subscription.entitlements.join(', ')}</div>;
21
+ * } else {
22
+ * return <div>No active subscription</div>;
23
+ * }
24
+ * ```
25
+ */
26
+ export function useUserSubscription() {
27
+ const [subscription, setSubscription] = useState(null);
28
+ const [isLoading, setIsLoading] = useState(true);
29
+ const [error, setError] = useState(null);
30
+ const loadData = useCallback(async () => {
31
+ if (!isSubscriptionInitialized()) {
32
+ setError(new Error('Subscription not initialized'));
33
+ setIsLoading(false);
34
+ return;
35
+ }
36
+ const service = getSubscriptionInstance();
37
+ try {
38
+ setIsLoading(true);
39
+ setError(null);
40
+ // Load customer info if not already loaded
41
+ if (!service.hasLoadedCustomerInfo()) {
42
+ await service.loadCustomerInfo();
43
+ }
44
+ const currentSub = service.getCurrentSubscription();
45
+ setSubscription(currentSub);
46
+ }
47
+ catch (err) {
48
+ setError(err instanceof Error ? err : new Error('Failed to load subscription'));
49
+ }
50
+ finally {
51
+ setIsLoading(false);
52
+ }
53
+ }, []);
54
+ useEffect(() => {
55
+ loadData();
56
+ }, [loadData]);
57
+ const refetch = useCallback(async () => {
58
+ if (!isSubscriptionInitialized())
59
+ return;
60
+ const service = getSubscriptionInstance();
61
+ try {
62
+ setIsLoading(true);
63
+ setError(null);
64
+ await service.loadCustomerInfo();
65
+ const currentSub = service.getCurrentSubscription();
66
+ setSubscription(currentSub);
67
+ }
68
+ catch (err) {
69
+ setError(err instanceof Error ? err : new Error('Failed to load subscription'));
70
+ }
71
+ finally {
72
+ setIsLoading(false);
73
+ }
74
+ }, []);
75
+ return { subscription, isLoading, error, refetch };
76
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @sudobility/subscription_lib
3
+ *
4
+ * Cross-platform subscription management library with RevenueCat adapter pattern.
5
+ * Works with both React (web) and React Native.
6
+ */
7
+ export { initializeSubscription, getSubscriptionInstance, isSubscriptionInitialized, resetSubscription, refreshSubscription, SubscriptionService, type SubscriptionConfig, type SubscriptionServiceConfig, } from './core';
8
+ export { useSubscriptions, useUserSubscription, useSubscriptionPeriods, useSubscriptionForPeriod, useSubscribable, type UseSubscriptionsResult, type UseUserSubscriptionResult, type UseSubscriptionPeriodsResult, type UseSubscriptionForPeriodResult, type UseSubscribableResult, } from './hooks';
9
+ export type { SubscriptionAdapter, AdapterOfferings, AdapterOffering, AdapterPackage, AdapterProduct, AdapterSubscriptionOption, AdapterPricingPhase, AdapterCustomerInfo, AdapterEntitlementInfo, AdapterPurchaseParams, AdapterPurchaseResult, SubscriptionProduct, SubscriptionPackage, SubscriptionOffer, CurrentSubscription, FreeTierConfig, PackageWithLevel, SubscriptionPeriod, } from './types';
10
+ export { PERIOD_RANKS, ALL_PERIODS } from './types';
11
+ export { parseISO8601Period, getPeriodRank, comparePeriods, isPeriodGreaterOrEqual, calculatePackageLevels, addLevelsToPackages, getPackageLevel, findUpgradeablePackages, } from './utils';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,GAC/B,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,EACtB,wBAAwB,EACxB,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,4BAA4B,EACjC,KAAK,8BAA8B,EACnC,KAAK,qBAAqB,GAC3B,MAAM,SAAS,CAAC;AAGjB,YAAY,EAEV,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,cAAc,EACd,yBAAyB,EACzB,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EAErB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAEhB,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGpD,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,eAAe,EACf,uBAAuB,GACxB,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @sudobility/subscription_lib
3
+ *
4
+ * Cross-platform subscription management library with RevenueCat adapter pattern.
5
+ * Works with both React (web) and React Native.
6
+ */
7
+ // Core
8
+ export { initializeSubscription, getSubscriptionInstance, isSubscriptionInitialized, resetSubscription, refreshSubscription, SubscriptionService, } from './core';
9
+ // Hooks
10
+ export { useSubscriptions, useUserSubscription, useSubscriptionPeriods, useSubscriptionForPeriod, useSubscribable, } from './hooks';
11
+ export { PERIOD_RANKS, ALL_PERIODS } from './types';
12
+ // Utils
13
+ export { parseISO8601Period, getPeriodRank, comparePeriods, isPeriodGreaterOrEqual, calculatePackageLevels, addLevelsToPackages, getPackageLevel, findUpgradeablePackages, } from './utils';
@@ -0,0 +1,149 @@
1
+ /**
2
+ * RevenueCat Adapter Interface
3
+ *
4
+ * Platform-agnostic interface that abstracts RevenueCat SDK differences
5
+ * between web (@revenuecat/purchases-js) and React Native (react-native-purchases).
6
+ */
7
+ /**
8
+ * Pricing phase information for trials and intro prices
9
+ */
10
+ export interface AdapterPricingPhase {
11
+ /** Duration in ISO 8601 format (e.g., "P7D", "P1M") */
12
+ periodDuration: string | null;
13
+ /** Price in standard units (not micros), null for free trials */
14
+ price: number | null;
15
+ /** Formatted price string, null for free trials */
16
+ priceString: string | null;
17
+ /** Number of billing cycles for this phase */
18
+ cycleCount: number;
19
+ }
20
+ /**
21
+ * Subscription option with trial and intro price information
22
+ */
23
+ export interface AdapterSubscriptionOption {
24
+ /** Unique identifier for this option */
25
+ id: string;
26
+ /** Trial phase information, null if no trial */
27
+ trial: AdapterPricingPhase | null;
28
+ /** Introductory price phase, null if no intro price */
29
+ introPrice: AdapterPricingPhase | null;
30
+ }
31
+ /**
32
+ * Product information from RevenueCat
33
+ */
34
+ export interface AdapterProduct {
35
+ /** Product ID from the store */
36
+ identifier: string;
37
+ /** Display title */
38
+ title: string;
39
+ /** Product description */
40
+ description: string | null;
41
+ /** Price in standard units (e.g., 9.99 not 9990000) */
42
+ price: number;
43
+ /** Formatted price string (e.g., "$9.99") */
44
+ priceString: string;
45
+ /** Currency code (e.g., "USD") */
46
+ currencyCode: string;
47
+ /** Billing period in ISO 8601 format (e.g., "P1M", "P1Y"), null for non-subscriptions */
48
+ normalPeriodDuration: string | null;
49
+ /** Available subscription options with offers */
50
+ subscriptionOptions?: Record<string, AdapterSubscriptionOption>;
51
+ }
52
+ /**
53
+ * Package containing a product
54
+ */
55
+ export interface AdapterPackage {
56
+ /** Package identifier (e.g., "pro_monthly") */
57
+ identifier: string;
58
+ /** Package type (e.g., "$rc_monthly", "custom") */
59
+ packageType: string;
60
+ /** The product in this package */
61
+ product: AdapterProduct;
62
+ }
63
+ /**
64
+ * Offering containing packages
65
+ */
66
+ export interface AdapterOffering {
67
+ /** Offering identifier */
68
+ identifier: string;
69
+ /** Offering metadata from RevenueCat dashboard */
70
+ metadata: Record<string, unknown> | null;
71
+ /** Available packages in this offering */
72
+ availablePackages: AdapterPackage[];
73
+ }
74
+ /**
75
+ * All offerings response
76
+ */
77
+ export interface AdapterOfferings {
78
+ /** Map of all offerings by identifier */
79
+ all: Record<string, AdapterOffering>;
80
+ /** Current/default offering */
81
+ current: AdapterOffering | null;
82
+ }
83
+ /**
84
+ * Entitlement info for a customer
85
+ */
86
+ export interface AdapterEntitlementInfo {
87
+ /** Entitlement identifier */
88
+ identifier: string;
89
+ /** Product that granted this entitlement */
90
+ productIdentifier: string;
91
+ /** Expiration date in ISO format, null for lifetime */
92
+ expirationDate: string | null;
93
+ /** Whether subscription will auto-renew */
94
+ willRenew: boolean;
95
+ }
96
+ /**
97
+ * Customer info from RevenueCat
98
+ */
99
+ export interface AdapterCustomerInfo {
100
+ /** Set of active subscription product identifiers */
101
+ activeSubscriptions: string[];
102
+ /** Entitlements information */
103
+ entitlements: {
104
+ /** Active entitlements map */
105
+ active: Record<string, AdapterEntitlementInfo>;
106
+ };
107
+ }
108
+ /**
109
+ * Parameters for making a purchase
110
+ */
111
+ export interface AdapterPurchaseParams {
112
+ /** Package identifier to purchase */
113
+ packageId: string;
114
+ /** Offering identifier the package belongs to */
115
+ offeringId: string;
116
+ /** Customer email for web billing */
117
+ customerEmail?: string;
118
+ }
119
+ /**
120
+ * Result of a purchase operation
121
+ */
122
+ export interface AdapterPurchaseResult {
123
+ /** Updated customer info after purchase */
124
+ customerInfo: AdapterCustomerInfo;
125
+ }
126
+ /**
127
+ * RevenueCat Adapter Interface
128
+ *
129
+ * Implement this interface to provide platform-specific RevenueCat SDK integration.
130
+ */
131
+ export interface SubscriptionAdapter {
132
+ /**
133
+ * Get all configured offerings
134
+ * @param params Optional parameters like currency
135
+ */
136
+ getOfferings(params?: {
137
+ currency?: string;
138
+ }): Promise<AdapterOfferings>;
139
+ /**
140
+ * Get current customer info including entitlements
141
+ */
142
+ getCustomerInfo(): Promise<AdapterCustomerInfo>;
143
+ /**
144
+ * Make a purchase
145
+ * @param params Purchase parameters
146
+ */
147
+ purchase(params: AdapterPurchaseParams): Promise<AdapterPurchaseResult>;
148
+ }
149
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/types/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * RevenueCat Adapter Interface
3
+ *
4
+ * Platform-agnostic interface that abstracts RevenueCat SDK differences
5
+ * between web (@revenuecat/purchases-js) and React Native (react-native-purchases).
6
+ */
7
+ export {};
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Type Exports
3
+ */
4
+ export type { SubscriptionAdapter, AdapterOfferings, AdapterOffering, AdapterPackage, AdapterProduct, AdapterSubscriptionOption, AdapterPricingPhase, AdapterCustomerInfo, AdapterEntitlementInfo, AdapterPurchaseParams, AdapterPurchaseResult, } from './adapter';
5
+ export type { SubscriptionProduct, SubscriptionPackage, SubscriptionOffer, CurrentSubscription, FreeTierConfig, PackageWithLevel, } from './subscription';
6
+ export type { SubscriptionPeriod } from './period';
7
+ export { PERIOD_RANKS, ALL_PERIODS } from './period';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,cAAc,EACd,yBAAyB,EACzB,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,WAAW,CAAC;AAGnB,YAAY,EACV,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Type Exports
3
+ */
4
+ export { PERIOD_RANKS, ALL_PERIODS } from './period';