@windrun-huaiin/third-ui 30.1.0 → 31.0.0
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/README.md +109 -143
- package/dist/ai/ai-prompt-textarea.js +5 -5
- package/dist/ai/ai-prompt-textarea.mjs +5 -5
- package/dist/clerk/clerk-auth-appearance.d.ts +13 -0
- package/dist/clerk/clerk-auth-appearance.js +19 -0
- package/dist/clerk/clerk-auth-appearance.mjs +15 -0
- package/dist/clerk/clerk-auth-modal-appearance.d.ts +12 -0
- package/dist/clerk/clerk-auth-modal-appearance.js +17 -0
- package/dist/clerk/clerk-auth-modal-appearance.mjs +14 -0
- package/dist/clerk/clerk-page-context-generator.js +3 -3
- package/dist/clerk/clerk-page-context-generator.mjs +3 -3
- package/dist/clerk/clerk-page-generator.js +4 -4
- package/dist/clerk/clerk-page-generator.mjs +4 -4
- package/dist/clerk/clerk-user-client.js +2 -1
- package/dist/clerk/clerk-user-client.mjs +2 -1
- package/dist/clerk/fingerprint/fingerprint-client.d.ts +10 -10
- package/dist/clerk/fingerprint/fingerprint-client.js +20 -20
- package/dist/clerk/fingerprint/fingerprint-client.mjs +20 -20
- package/dist/clerk/fingerprint/fingerprint-provider.d.ts +3 -3
- package/dist/clerk/fingerprint/fingerprint-provider.js +8 -8
- package/dist/clerk/fingerprint/fingerprint-provider.mjs +8 -8
- package/dist/clerk/fingerprint/fingerprint-server.d.ts +12 -12
- package/dist/clerk/fingerprint/fingerprint-server.js +17 -17
- package/dist/clerk/fingerprint/fingerprint-server.mjs +17 -17
- package/dist/clerk/fingerprint/fingerprint-shared.d.ts +3 -3
- package/dist/clerk/fingerprint/fingerprint-shared.js +10 -10
- package/dist/clerk/fingerprint/fingerprint-shared.mjs +10 -10
- package/dist/clerk/fingerprint/types.d.ts +0 -1
- package/dist/clerk/fingerprint/use-fingerprint.js +7 -7
- package/dist/clerk/fingerprint/use-fingerprint.mjs +7 -7
- package/dist/clerk/signin-with-fingerprint-client.d.ts +2 -2
- package/dist/clerk/signin-with-fingerprint-client.js +7 -6
- package/dist/clerk/signin-with-fingerprint-client.mjs +7 -6
- package/dist/clerk/signup-button-with-fingerprint-client.js +6 -4
- package/dist/clerk/signup-button-with-fingerprint-client.mjs +6 -4
- package/dist/clerk/signup-with-fingerprint-client.d.ts +2 -2
- package/dist/clerk/signup-with-fingerprint-client.js +7 -6
- package/dist/clerk/signup-with-fingerprint-client.mjs +7 -6
- package/dist/fuma/heavy/mermaid.js +1 -1
- package/dist/fuma/heavy/mermaid.mjs +1 -1
- package/dist/fuma/site-x.js +0 -1
- package/dist/fuma/site-x.mjs +0 -1
- package/dist/main/calendar/calendar-date-range-input.js +1 -1
- package/dist/main/calendar/calendar-date-range-input.mjs +1 -1
- package/dist/main/credit/types.d.ts +8 -8
- package/dist/main/money-price/index.d.ts +1 -1
- package/dist/main/money-price/money-price-button.js +10 -10
- package/dist/main/money-price/money-price-button.mjs +10 -10
- package/dist/main/money-price/money-price-config-util.d.ts +30 -30
- package/dist/main/money-price/money-price-config-util.js +48 -48
- package/dist/main/money-price/money-price-config-util.mjs +48 -48
- package/dist/main/money-price/money-price-interactive.js +30 -18
- package/dist/main/money-price/money-price-interactive.mjs +30 -18
- package/dist/main/money-price/money-price-types.d.ts +7 -1
- package/dist/main/money-price/money-price-types.js +2 -2
- package/dist/main/money-price/money-price-types.mjs +2 -2
- package/dist/main/money-price/server.d.ts +1 -1
- package/dist/main/pill-select/x-pill-select.js +2 -2
- package/dist/main/pill-select/x-pill-select.mjs +2 -2
- package/dist/main/server.d.ts +1 -1
- package/package.json +13 -7
- package/src/ai/ai-prompt-textarea.tsx +6 -6
- package/src/clerk/clerk-auth-appearance.ts +16 -0
- package/src/clerk/clerk-page-context-generator.tsx +3 -5
- package/src/clerk/clerk-page-generator.tsx +9 -8
- package/src/clerk/clerk-user-client.tsx +14 -5
- package/src/clerk/fingerprint/fingerprint-client.ts +20 -20
- package/src/clerk/fingerprint/fingerprint-provider.tsx +11 -11
- package/src/clerk/fingerprint/fingerprint-server.ts +17 -17
- package/src/clerk/fingerprint/fingerprint-shared.ts +10 -10
- package/src/clerk/fingerprint/types.ts +0 -1
- package/src/clerk/fingerprint/use-fingerprint.ts +7 -7
- package/src/clerk/signin-with-fingerprint-client.tsx +7 -7
- package/src/clerk/signup-button-with-fingerprint-client.tsx +7 -5
- package/src/clerk/signup-with-fingerprint-client.tsx +7 -7
- package/src/fuma/base/custom-home-layout.tsx +4 -4
- package/src/fuma/heavy/mermaid.tsx +1 -1
- package/src/fuma/site-x.tsx +0 -1
- package/src/main/calendar/calendar-date-range-input.tsx +1 -1
- package/src/main/credit/types.ts +8 -8
- package/src/main/gallery/gallery-mobile-swiper.tsx +0 -1
- package/src/main/gallery/gallery-server.tsx +2 -2
- package/src/main/money-price/index.ts +2 -0
- package/src/main/money-price/money-price-button.tsx +10 -10
- package/src/main/money-price/money-price-config-util.ts +49 -49
- package/src/main/money-price/money-price-interactive.tsx +40 -20
- package/src/main/money-price/money-price-types.ts +21 -14
- package/src/main/money-price/server.ts +2 -0
- package/src/main/pill-select/x-pill-select.tsx +2 -2
- package/src/main/server.ts +3 -1
- package/src/styles/third-ui.css +8 -0
|
@@ -29,21 +29,21 @@ export interface CreditCTAConfig {
|
|
|
29
29
|
}
|
|
30
30
|
export type CreditBucketStatus = 'active' | 'expiringSoon' | 'expired';
|
|
31
31
|
export interface CreditBucket {
|
|
32
|
-
/**
|
|
32
|
+
/** Business-defined credit type identifier for translation mapping or analytics. */
|
|
33
33
|
kind: string;
|
|
34
|
-
/**
|
|
34
|
+
/** Display name override; otherwise the component uses the default translation for kind. */
|
|
35
35
|
label?: string;
|
|
36
|
-
/**
|
|
36
|
+
/** Current credit balance. */
|
|
37
37
|
balance: number;
|
|
38
|
-
/**
|
|
38
|
+
/** Credit limit for this credit type. */
|
|
39
39
|
limit: number;
|
|
40
|
-
/**
|
|
40
|
+
/** Optional status label for highlighting states such as expiration. */
|
|
41
41
|
status?: CreditBucketStatus;
|
|
42
|
-
/**
|
|
42
|
+
/** Credit expiration time as a local time string, used to derive component state. */
|
|
43
43
|
expiresAt?: string;
|
|
44
|
-
/**
|
|
44
|
+
/** Progress percentage from 0 to 100; computed from balance/limit when omitted. */
|
|
45
45
|
progressPercent?: number;
|
|
46
|
-
/**
|
|
46
|
+
/** Additional details, such as remaining days or usage limits. */
|
|
47
47
|
description?: string;
|
|
48
48
|
}
|
|
49
49
|
export interface SubscriptionInfo {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { MoneyPriceInteractive } from './money-price-interactive';
|
|
2
2
|
export { MoneyPriceButton } from './money-price-button';
|
|
3
|
-
export type { MoneyPriceConfig, MoneyPriceData, InitUserContext, MoneyPriceInteractiveProps, MoneyPriceButtonProps, PaymentProvider, PaymentProviderConfig, EnhancePricePlan, SubscriptionProductConfig, CreditPackProductConfig, UserContext, } from './money-price-types';
|
|
3
|
+
export type { MoneyPriceConfig, MoneyPriceData, MoneyPriceAnimeTone, MoneyPriceStrictDiffAnime, InitUserContext, MoneyPriceInteractiveProps, MoneyPriceButtonProps, PaymentProvider, PaymentProviderConfig, EnhancePricePlan, SubscriptionProductConfig, CreditPackProductConfig, UserContext, } from './money-price-types';
|
|
4
4
|
export { UserState } from './money-price-types';
|
|
@@ -26,9 +26,9 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
|
|
|
26
26
|
return billing === 'monthly' ? 2 : 4;
|
|
27
27
|
return 0;
|
|
28
28
|
};
|
|
29
|
-
//
|
|
29
|
+
// Button configuration for one-time mode.
|
|
30
30
|
const getOnetimeButtonConfig = () => {
|
|
31
|
-
//
|
|
31
|
+
// Anonymous users: show the sign-in button on every card.
|
|
32
32
|
if (!isAuthenticated) {
|
|
33
33
|
return {
|
|
34
34
|
text: texts.getStarted,
|
|
@@ -38,11 +38,11 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
|
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
if (subscriptionStatus === moneyPriceTypes.UserState.Anonymous) {
|
|
41
|
-
//
|
|
41
|
+
// Signed in but status unknown: treat as FreeUser.
|
|
42
42
|
console.warn('Clerk is authed OK but user is anonymous!');
|
|
43
43
|
return { text: '', disabled: true, hidden: true };
|
|
44
44
|
}
|
|
45
|
-
//
|
|
45
|
+
// Signed-in users: show the buy-credits button on every card in one-time mode.
|
|
46
46
|
return {
|
|
47
47
|
text: texts.buyCredits || texts.upgrade,
|
|
48
48
|
onClick: () => onAction(planKey, billingType),
|
|
@@ -50,9 +50,9 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
|
|
|
50
50
|
hidden: false
|
|
51
51
|
};
|
|
52
52
|
};
|
|
53
|
-
//
|
|
53
|
+
// Button configuration for subscription mode.
|
|
54
54
|
const getSubscriptionButtonConfig = () => {
|
|
55
|
-
//
|
|
55
|
+
// Anonymous users.
|
|
56
56
|
if (!isAuthenticated) {
|
|
57
57
|
const getButtonText = () => {
|
|
58
58
|
switch (planKey) {
|
|
@@ -73,7 +73,7 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
|
|
|
73
73
|
hidden: false
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
|
-
//
|
|
76
|
+
// Signed-in users.
|
|
77
77
|
switch (subscriptionStatus) {
|
|
78
78
|
case moneyPriceTypes.UserState.FreeUser: {
|
|
79
79
|
if (planTier === 'F1') {
|
|
@@ -91,7 +91,7 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
|
|
|
91
91
|
};
|
|
92
92
|
}
|
|
93
93
|
case moneyPriceTypes.UserState.ProUser: {
|
|
94
|
-
//
|
|
94
|
+
// Do not allow downgrades to Free.
|
|
95
95
|
if (planTier === 'F1') {
|
|
96
96
|
return { hidden: true };
|
|
97
97
|
}
|
|
@@ -169,12 +169,12 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
|
|
|
169
169
|
return { hidden: true };
|
|
170
170
|
}
|
|
171
171
|
default:
|
|
172
|
-
//
|
|
172
|
+
// Signed in but status unknown: treat as FreeUser.
|
|
173
173
|
console.warn('Clerk is authed OK but user is anonymous!');
|
|
174
174
|
return { text: '', disabled: true, hidden: true };
|
|
175
175
|
}
|
|
176
176
|
};
|
|
177
|
-
//
|
|
177
|
+
// Main button configuration function.
|
|
178
178
|
const getButtonConfig = () => {
|
|
179
179
|
if (billingType === 'onetime') {
|
|
180
180
|
return getOnetimeButtonConfig();
|
|
@@ -24,9 +24,9 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
|
|
|
24
24
|
return billing === 'monthly' ? 2 : 4;
|
|
25
25
|
return 0;
|
|
26
26
|
};
|
|
27
|
-
//
|
|
27
|
+
// Button configuration for one-time mode.
|
|
28
28
|
const getOnetimeButtonConfig = () => {
|
|
29
|
-
//
|
|
29
|
+
// Anonymous users: show the sign-in button on every card.
|
|
30
30
|
if (!isAuthenticated) {
|
|
31
31
|
return {
|
|
32
32
|
text: texts.getStarted,
|
|
@@ -36,11 +36,11 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
|
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
if (subscriptionStatus === UserState.Anonymous) {
|
|
39
|
-
//
|
|
39
|
+
// Signed in but status unknown: treat as FreeUser.
|
|
40
40
|
console.warn('Clerk is authed OK but user is anonymous!');
|
|
41
41
|
return { text: '', disabled: true, hidden: true };
|
|
42
42
|
}
|
|
43
|
-
//
|
|
43
|
+
// Signed-in users: show the buy-credits button on every card in one-time mode.
|
|
44
44
|
return {
|
|
45
45
|
text: texts.buyCredits || texts.upgrade,
|
|
46
46
|
onClick: () => onAction(planKey, billingType),
|
|
@@ -48,9 +48,9 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
|
|
|
48
48
|
hidden: false
|
|
49
49
|
};
|
|
50
50
|
};
|
|
51
|
-
//
|
|
51
|
+
// Button configuration for subscription mode.
|
|
52
52
|
const getSubscriptionButtonConfig = () => {
|
|
53
|
-
//
|
|
53
|
+
// Anonymous users.
|
|
54
54
|
if (!isAuthenticated) {
|
|
55
55
|
const getButtonText = () => {
|
|
56
56
|
switch (planKey) {
|
|
@@ -71,7 +71,7 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
|
|
|
71
71
|
hidden: false
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
|
-
//
|
|
74
|
+
// Signed-in users.
|
|
75
75
|
switch (subscriptionStatus) {
|
|
76
76
|
case UserState.FreeUser: {
|
|
77
77
|
if (planTier === 'F1') {
|
|
@@ -89,7 +89,7 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
|
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
91
|
case UserState.ProUser: {
|
|
92
|
-
//
|
|
92
|
+
// Do not allow downgrades to Free.
|
|
93
93
|
if (planTier === 'F1') {
|
|
94
94
|
return { hidden: true };
|
|
95
95
|
}
|
|
@@ -167,12 +167,12 @@ function MoneyPriceButton({ planKey, userContext, billingType, onAuth, onAction,
|
|
|
167
167
|
return { hidden: true };
|
|
168
168
|
}
|
|
169
169
|
default:
|
|
170
|
-
//
|
|
170
|
+
// Signed in but status unknown: treat as FreeUser.
|
|
171
171
|
console.warn('Clerk is authed OK but user is anonymous!');
|
|
172
172
|
return { text: '', disabled: true, hidden: true };
|
|
173
173
|
}
|
|
174
174
|
};
|
|
175
|
-
//
|
|
175
|
+
// Main button configuration function.
|
|
176
176
|
const getButtonConfig = () => {
|
|
177
177
|
if (billingType === 'onetime') {
|
|
178
178
|
return getOnetimeButtonConfig();
|
|
@@ -1,52 +1,52 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Money Price Configuration
|
|
3
|
-
*
|
|
3
|
+
* Pricing component configuration.
|
|
4
4
|
*/
|
|
5
5
|
import type { MoneyPriceConfig, PaymentProviderConfig, EnhancePricePlan } from './money-price-types';
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Get the currently active payment provider configuration.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
* -
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
9
|
+
* Security design:
|
|
10
|
+
* - The utility layer extracts the active provider configuration from the config.
|
|
11
|
+
* - Only the extracted result is returned; the full config structure is not exposed.
|
|
12
|
+
* - Application-level wrappers hide the config object from callers.
|
|
13
13
|
*
|
|
14
|
-
* @param config - MoneyPriceConfig
|
|
15
|
-
* @returns
|
|
14
|
+
* @param config - MoneyPriceConfig object provided by the application layer.
|
|
15
|
+
* @returns The currently active payment provider configuration.
|
|
16
16
|
*/
|
|
17
17
|
export declare function getActiveProviderConfigUtil(config: MoneyPriceConfig): PaymentProviderConfig;
|
|
18
18
|
export declare function getProductPricing(productKey: 'F1' | 'P2' | 'U3', billingType: string, provider: string, config: MoneyPriceConfig): EnhancePricePlan;
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* Get the credit amount for a price ID.
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
* -
|
|
24
|
-
* -
|
|
25
|
-
* -
|
|
22
|
+
* Security design:
|
|
23
|
+
* - The utility layer parses the config and extracts only the required data.
|
|
24
|
+
* - Only the query result is returned; the full config structure is not exposed.
|
|
25
|
+
* - Application-level wrappers hide the config object from callers.
|
|
26
26
|
*
|
|
27
|
-
* @param priceId -
|
|
28
|
-
* @param config - MoneyPriceConfig
|
|
29
|
-
* @returns
|
|
27
|
+
* @param priceId - Price ID to query.
|
|
28
|
+
* @param config - MoneyPriceConfig object provided by the application layer.
|
|
29
|
+
* @returns The matching credit amount, or null.
|
|
30
30
|
*/
|
|
31
31
|
export declare function getCreditsFromPriceIdUtil(priceId: string | undefined, config: MoneyPriceConfig): number | null;
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
33
|
+
* Get price configuration by query parameters.
|
|
34
34
|
*
|
|
35
|
-
*
|
|
36
|
-
* 1.
|
|
37
|
-
* 2.
|
|
38
|
-
* 3.
|
|
35
|
+
* Supported query modes:
|
|
36
|
+
* 1. Query directly by priceId.
|
|
37
|
+
* 2. Query by plan and billingType.
|
|
38
|
+
* 3. Query by plan.
|
|
39
39
|
*
|
|
40
|
-
*
|
|
41
|
-
* -
|
|
42
|
-
* -
|
|
43
|
-
* -
|
|
40
|
+
* Security design:
|
|
41
|
+
* - The utility layer parses the config and extracts only matching data.
|
|
42
|
+
* - Only the query result is returned; the full config structure is not exposed.
|
|
43
|
+
* - Application-level wrappers hide the config object from callers.
|
|
44
44
|
*
|
|
45
|
-
* @param priceId -
|
|
46
|
-
* @param plan -
|
|
47
|
-
* @param billingType -
|
|
48
|
-
* @param config - MoneyPriceConfig
|
|
49
|
-
* @returns
|
|
45
|
+
* @param priceId - Optional price ID to query.
|
|
46
|
+
* @param plan - Optional plan name, such as 'P2' or 'U3'.
|
|
47
|
+
* @param billingType - Optional billing type, such as 'monthly' or 'yearly'.
|
|
48
|
+
* @param config - MoneyPriceConfig object provided by the application layer.
|
|
49
|
+
* @returns The matching price config with derived metadata: priceName, description, and interval.
|
|
50
50
|
*/
|
|
51
51
|
export declare function getPriceConfigUtil(priceId: string | undefined, plan: string | undefined, billingType: string | undefined, config: MoneyPriceConfig): (EnhancePricePlan & {
|
|
52
52
|
priceName: string;
|
|
@@ -2,30 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Money Price Configuration
|
|
5
|
-
*
|
|
5
|
+
* Pricing component configuration.
|
|
6
6
|
*/
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* Get the currently active payment provider configuration.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
10
|
+
* Security design:
|
|
11
|
+
* - The utility layer extracts the active provider configuration from the config.
|
|
12
|
+
* - Only the extracted result is returned; the full config structure is not exposed.
|
|
13
|
+
* - Application-level wrappers hide the config object from callers.
|
|
14
14
|
*
|
|
15
|
-
* @param config - MoneyPriceConfig
|
|
16
|
-
* @returns
|
|
15
|
+
* @param config - MoneyPriceConfig object provided by the application layer.
|
|
16
|
+
* @returns The currently active payment provider configuration.
|
|
17
17
|
*/
|
|
18
18
|
function getActiveProviderConfigUtil(config) {
|
|
19
19
|
const provider = config.activeProvider;
|
|
20
20
|
return config.paymentProviders[provider];
|
|
21
21
|
}
|
|
22
|
-
//
|
|
22
|
+
// Helper: get pricing information for a specific product.
|
|
23
23
|
function getProductPricing(productKey, billingType, provider, config) {
|
|
24
24
|
const providerConfig = config.paymentProviders[provider];
|
|
25
|
-
//
|
|
25
|
+
// For one-time billing, try to resolve pricing from credit packs.
|
|
26
26
|
if (billingType === 'onetime') {
|
|
27
27
|
const creditPacks = providerConfig.creditPackProducts;
|
|
28
|
-
//
|
|
28
|
+
// Use the same product key directly: F1 -> F1, P2 -> P2, U3 -> U3.
|
|
29
29
|
if (creditPacks && creditPacks[productKey]) {
|
|
30
30
|
const pack = creditPacks[productKey];
|
|
31
31
|
return {
|
|
@@ -36,33 +36,33 @@ function getProductPricing(productKey, billingType, provider, config) {
|
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
//
|
|
39
|
+
// Otherwise resolve pricing from subscription products.
|
|
40
40
|
const products = providerConfig.subscriptionProducts || providerConfig.products;
|
|
41
41
|
if (products && products[productKey] && products[productKey].plans[billingType]) {
|
|
42
42
|
return products[productKey].plans[billingType];
|
|
43
43
|
}
|
|
44
44
|
throw new Error(`Product pricing not found for ${productKey} ${billingType}`);
|
|
45
45
|
}
|
|
46
|
-
// ============
|
|
46
|
+
// ============ Safe utility functions: accept only simple mapping inputs and do not expose config internals ============
|
|
47
47
|
/**
|
|
48
|
-
*
|
|
48
|
+
* Get the credit amount for a price ID.
|
|
49
49
|
*
|
|
50
|
-
*
|
|
51
|
-
* -
|
|
52
|
-
* -
|
|
53
|
-
* -
|
|
50
|
+
* Security design:
|
|
51
|
+
* - The utility layer parses the config and extracts only the required data.
|
|
52
|
+
* - Only the query result is returned; the full config structure is not exposed.
|
|
53
|
+
* - Application-level wrappers hide the config object from callers.
|
|
54
54
|
*
|
|
55
|
-
* @param priceId -
|
|
56
|
-
* @param config - MoneyPriceConfig
|
|
57
|
-
* @returns
|
|
55
|
+
* @param priceId - Price ID to query.
|
|
56
|
+
* @param config - MoneyPriceConfig object provided by the application layer.
|
|
57
|
+
* @returns The matching credit amount, or null.
|
|
58
58
|
*/
|
|
59
59
|
function getCreditsFromPriceIdUtil(priceId, config) {
|
|
60
60
|
if (!priceId) {
|
|
61
61
|
return null;
|
|
62
62
|
}
|
|
63
|
-
//
|
|
63
|
+
// Iterate through all payment providers.
|
|
64
64
|
for (const provider of Object.values(config.paymentProviders)) {
|
|
65
|
-
//
|
|
65
|
+
// Iterate through subscription products.
|
|
66
66
|
const subscriptionProducts = (provider.subscriptionProducts || provider.products);
|
|
67
67
|
if (subscriptionProducts) {
|
|
68
68
|
for (const product of Object.values(subscriptionProducts)) {
|
|
@@ -76,7 +76,7 @@ function getCreditsFromPriceIdUtil(priceId, config) {
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
-
//
|
|
79
|
+
// Iterate through credit pack products.
|
|
80
80
|
const creditPacks = provider.creditPackProducts;
|
|
81
81
|
if (creditPacks) {
|
|
82
82
|
for (const pack of Object.values(creditPacks)) {
|
|
@@ -90,46 +90,46 @@ function getCreditsFromPriceIdUtil(priceId, config) {
|
|
|
90
90
|
return null;
|
|
91
91
|
}
|
|
92
92
|
/**
|
|
93
|
-
*
|
|
93
|
+
* Get price configuration by query parameters.
|
|
94
94
|
*
|
|
95
|
-
*
|
|
96
|
-
* 1.
|
|
97
|
-
* 2.
|
|
98
|
-
* 3.
|
|
95
|
+
* Supported query modes:
|
|
96
|
+
* 1. Query directly by priceId.
|
|
97
|
+
* 2. Query by plan and billingType.
|
|
98
|
+
* 3. Query by plan.
|
|
99
99
|
*
|
|
100
|
-
*
|
|
101
|
-
* -
|
|
102
|
-
* -
|
|
103
|
-
* -
|
|
100
|
+
* Security design:
|
|
101
|
+
* - The utility layer parses the config and extracts only matching data.
|
|
102
|
+
* - Only the query result is returned; the full config structure is not exposed.
|
|
103
|
+
* - Application-level wrappers hide the config object from callers.
|
|
104
104
|
*
|
|
105
|
-
* @param priceId -
|
|
106
|
-
* @param plan -
|
|
107
|
-
* @param billingType -
|
|
108
|
-
* @param config - MoneyPriceConfig
|
|
109
|
-
* @returns
|
|
105
|
+
* @param priceId - Optional price ID to query.
|
|
106
|
+
* @param plan - Optional plan name, such as 'P2' or 'U3'.
|
|
107
|
+
* @param billingType - Optional billing type, such as 'monthly' or 'yearly'.
|
|
108
|
+
* @param config - MoneyPriceConfig object provided by the application layer.
|
|
109
|
+
* @returns The matching price config with derived metadata: priceName, description, and interval.
|
|
110
110
|
*/
|
|
111
111
|
function getPriceConfigUtil(priceId, plan, billingType, config) {
|
|
112
|
-
//
|
|
112
|
+
// Iterate through all payment providers.
|
|
113
113
|
for (const provider of Object.values(config.paymentProviders)) {
|
|
114
|
-
//
|
|
114
|
+
// Iterate through subscription products.
|
|
115
115
|
const subscriptionProducts = (provider.subscriptionProducts || provider.products);
|
|
116
116
|
if (subscriptionProducts) {
|
|
117
117
|
for (const [productKey, product] of Object.entries(subscriptionProducts)) {
|
|
118
118
|
if (product.plans) {
|
|
119
119
|
for (const [billingKey, planConfig] of Object.entries(product.plans)) {
|
|
120
120
|
const plan_config = planConfig;
|
|
121
|
-
//
|
|
122
|
-
// 1.
|
|
121
|
+
// Matching order by priority.
|
|
122
|
+
// 1. Exact priceId match with highest priority.
|
|
123
123
|
if (priceId && plan_config.priceId === priceId) {
|
|
124
124
|
return Object.assign(Object.assign({}, plan_config), { priceName: `${productKey} ${billingKey}`, description: `${productKey} plan - ${billingKey} billing`, interval: billingKey === 'yearly' ? 'year' : 'month' });
|
|
125
125
|
}
|
|
126
|
-
// 2.
|
|
126
|
+
// 2. Match by both plan and billingType.
|
|
127
127
|
if (!priceId && plan && billingType) {
|
|
128
128
|
if (productKey === plan && billingKey === billingType) {
|
|
129
129
|
return Object.assign(Object.assign({}, plan_config), { priceName: `${productKey} ${billingKey}`, description: `${productKey} plan - ${billingKey} billing`, interval: billingKey === 'yearly' ? 'year' : 'month' });
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
|
-
// 3.
|
|
132
|
+
// 3. Match by plan when billingType is empty.
|
|
133
133
|
if (!priceId && !billingType && plan && productKey === plan) {
|
|
134
134
|
return Object.assign(Object.assign({}, plan_config), { priceName: `${productKey} ${billingKey}`, description: `${productKey} plan - ${billingKey} billing`, interval: billingKey === 'yearly' ? 'year' : 'month' });
|
|
135
135
|
}
|
|
@@ -137,12 +137,12 @@ function getPriceConfigUtil(priceId, plan, billingType, config) {
|
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
-
//
|
|
140
|
+
// Iterate through credit pack products.
|
|
141
141
|
const creditPacks = provider.creditPackProducts;
|
|
142
142
|
if (creditPacks) {
|
|
143
143
|
for (const [packKey, pack] of Object.entries(creditPacks)) {
|
|
144
144
|
const pack_typed = pack;
|
|
145
|
-
//
|
|
145
|
+
// Credit pack match.
|
|
146
146
|
if (priceId && pack_typed.priceId === priceId) {
|
|
147
147
|
return {
|
|
148
148
|
priceId: pack_typed.priceId,
|
|
@@ -154,7 +154,7 @@ function getPriceConfigUtil(priceId, plan, billingType, config) {
|
|
|
154
154
|
interval: 'onetime',
|
|
155
155
|
};
|
|
156
156
|
}
|
|
157
|
-
//
|
|
157
|
+
// Match by plan and one-time billing.
|
|
158
158
|
if (!priceId && plan && billingType === 'onetime') {
|
|
159
159
|
if (packKey === plan) {
|
|
160
160
|
return {
|
|
@@ -168,7 +168,7 @@ function getPriceConfigUtil(priceId, plan, billingType, config) {
|
|
|
168
168
|
};
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
|
-
//
|
|
171
|
+
// Match by plan; also resolves the first credit pack when billingType is empty.
|
|
172
172
|
if (!priceId && !billingType && plan && packKey === plan) {
|
|
173
173
|
return {
|
|
174
174
|
priceId: pack_typed.priceId,
|