@windrun-huaiin/backend-core 31.0.1 → 31.0.2
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/dist/app/api/user/credit-overview/route.d.ts +1 -0
- package/dist/app/api/user/credit-overview/route.d.ts.map +1 -1
- package/dist/app/api/user/credit-overview/route.js +8 -0
- package/dist/app/api/user/credit-overview/route.mjs +8 -0
- package/dist/lib/credit-overview.d.ts +1 -0
- package/dist/lib/credit-overview.d.ts.map +1 -1
- package/dist/lib/credit-overview.js +37 -21
- package/dist/lib/credit-overview.mjs +37 -21
- package/package.json +3 -3
- package/src/app/api/user/credit-overview/route.ts +9 -0
- package/src/lib/credit-overview.ts +48 -18
|
@@ -8,6 +8,7 @@ export interface CreateGETOptions {
|
|
|
8
8
|
pricingPath?: string;
|
|
9
9
|
checkoutApiEndpoint?: string;
|
|
10
10
|
customerPortalApiEndpoint?: string;
|
|
11
|
+
enabledBillingTypes?: string[];
|
|
11
12
|
}
|
|
12
13
|
export declare function createGET(options: CreateGETOptions): (request: Request) => Promise<NextResponse<import("@core/lib/credit-overview").CreditOverviewPayload | null>>;
|
|
13
14
|
//# sourceMappingURL=route.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/app/api/user/credit-overview/route.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,MAAM,kCAAkC,GAAG,CAC/C,MAAM,EAAE,MAAM,KACX,0BAA0B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAC;AAEtE,MAAM,WAAW,gBAAgB;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,mBAAmB,EAAE,kCAAkC,CAAC;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,yBAAyB,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/app/api/user/credit-overview/route.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,MAAM,kCAAkC,GAAG,CAC/C,MAAM,EAAE,MAAM,KACX,0BAA0B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAC;AAEtE,MAAM,WAAW,gBAAgB;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,mBAAmB,EAAE,kCAAkC,CAAC;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,IACvB,SAAS,OAAO,6FAyB3C"}
|
|
@@ -14,6 +14,11 @@ function createGET(options) {
|
|
|
14
14
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
15
15
|
const { searchParams } = new URL(request.url);
|
|
16
16
|
const locale = searchParams.get('locale') || options.defaultLocale || 'en';
|
|
17
|
+
const requestEnabledBillingTypes = searchParams
|
|
18
|
+
.getAll('enabledBillingTypes')
|
|
19
|
+
.flatMap((value) => value.split(','))
|
|
20
|
+
.map((value) => value.trim())
|
|
21
|
+
.filter((value) => value.length > 0);
|
|
17
22
|
const translations = yield options.resolveTranslations(locale);
|
|
18
23
|
const payload = yield creditOverview.buildCreditOverviewPayload({
|
|
19
24
|
locale,
|
|
@@ -23,6 +28,9 @@ function createGET(options) {
|
|
|
23
28
|
pricingPath: options.pricingPath,
|
|
24
29
|
checkoutApiEndpoint: options.checkoutApiEndpoint,
|
|
25
30
|
customerPortalApiEndpoint: options.customerPortalApiEndpoint,
|
|
31
|
+
enabledBillingTypes: requestEnabledBillingTypes.length
|
|
32
|
+
? requestEnabledBillingTypes
|
|
33
|
+
: options.enabledBillingTypes,
|
|
26
34
|
});
|
|
27
35
|
return server.NextResponse.json(payload);
|
|
28
36
|
});
|
|
@@ -12,6 +12,11 @@ function createGET(options) {
|
|
|
12
12
|
return __awaiter(this, void 0, void 0, function* () {
|
|
13
13
|
const { searchParams } = new URL(request.url);
|
|
14
14
|
const locale = searchParams.get('locale') || options.defaultLocale || 'en';
|
|
15
|
+
const requestEnabledBillingTypes = searchParams
|
|
16
|
+
.getAll('enabledBillingTypes')
|
|
17
|
+
.flatMap((value) => value.split(','))
|
|
18
|
+
.map((value) => value.trim())
|
|
19
|
+
.filter((value) => value.length > 0);
|
|
15
20
|
const translations = yield options.resolveTranslations(locale);
|
|
16
21
|
const payload = yield buildCreditOverviewPayload({
|
|
17
22
|
locale,
|
|
@@ -21,6 +26,9 @@ function createGET(options) {
|
|
|
21
26
|
pricingPath: options.pricingPath,
|
|
22
27
|
checkoutApiEndpoint: options.checkoutApiEndpoint,
|
|
23
28
|
customerPortalApiEndpoint: options.customerPortalApiEndpoint,
|
|
29
|
+
enabledBillingTypes: requestEnabledBillingTypes.length
|
|
30
|
+
? requestEnabledBillingTypes
|
|
31
|
+
: options.enabledBillingTypes,
|
|
24
32
|
});
|
|
25
33
|
return NextResponse.json(payload);
|
|
26
34
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credit-overview.d.ts","sourceRoot":"","sources":["../../src/lib/credit-overview.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAE3G,MAAM,WAAW,iCAAiC;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,YAAY,EAAE,0BAA0B,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,yBAAyB,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"credit-overview.d.ts","sourceRoot":"","sources":["../../src/lib/credit-overview.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAE3G,MAAM,WAAW,iCAAiC;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,YAAY,EAAE,0BAA0B,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,kBAAkB,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,0BAA0B,CAAC;CAC1C;AAiBD,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,iCAAiC,GACzC,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAqIvC"}
|
|
@@ -15,6 +15,14 @@ var server = require('@windrun-huaiin/third-ui/main/money-price/server');
|
|
|
15
15
|
BigInt.prototype.toJSON = function () {
|
|
16
16
|
return this.toString();
|
|
17
17
|
};
|
|
18
|
+
const DEFAULT_ENABLED_BILLING_TYPES = ['monthly', 'yearly', 'onetime'];
|
|
19
|
+
const SUBSCRIPTION_BILLING_TYPES = new Set(['monthly', 'yearly']);
|
|
20
|
+
function normalizeEnabledBillingTypes(enabledBillingTypes) {
|
|
21
|
+
const normalized = Array.from(new Set(((enabledBillingTypes === null || enabledBillingTypes === void 0 ? void 0 : enabledBillingTypes.length) ? enabledBillingTypes : DEFAULT_ENABLED_BILLING_TYPES)
|
|
22
|
+
.map((billingType) => billingType.trim())
|
|
23
|
+
.filter((billingType) => billingType.length > 0)));
|
|
24
|
+
return normalized.length ? normalized : DEFAULT_ENABLED_BILLING_TYPES;
|
|
25
|
+
}
|
|
18
26
|
function buildCreditOverviewPayload(options) {
|
|
19
27
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
20
28
|
var _a, _b, _c, _d;
|
|
@@ -22,16 +30,19 @@ function buildCreditOverviewPayload(options) {
|
|
|
22
30
|
if (!authUser) {
|
|
23
31
|
return null;
|
|
24
32
|
}
|
|
25
|
-
const { locale, defaultLocale = 'en', localePrefixAsNeeded = true, translations, pricingPath = '/pricing', checkoutApiEndpoint = '/api/stripe/checkout', customerPortalApiEndpoint = '/api/stripe/customer-portal', } = options;
|
|
33
|
+
const { locale, defaultLocale = 'en', localePrefixAsNeeded = true, translations, pricingPath = '/pricing', checkoutApiEndpoint = '/api/stripe/checkout', customerPortalApiEndpoint = '/api/stripe/customer-portal', enabledBillingTypes: enabledBillingTypesOption, } = options;
|
|
26
34
|
const { user } = authUser;
|
|
27
35
|
const enableSubscriptionUpgrade = process.env.ENABLE_STRIPE_SUBSCRIPTION_UPGRADE !== 'false';
|
|
36
|
+
const enabledBillingTypes = normalizeEnabledBillingTypes(enabledBillingTypesOption);
|
|
37
|
+
const subscriptionBillingEnabled = enabledBillingTypes.some((billingType) => SUBSCRIPTION_BILLING_TYPES.has(billingType));
|
|
38
|
+
const onetimeBillingEnabled = enabledBillingTypes.includes('onetime');
|
|
28
39
|
const [credit, subscription, moneyPriceData] = yield Promise.all([
|
|
29
40
|
credit_service.creditService.getCredit(user.userId),
|
|
30
41
|
subscription_service.subscriptionService.getActiveSubscription(user.userId),
|
|
31
42
|
server.buildMoneyPriceData({
|
|
32
43
|
locale,
|
|
33
44
|
currency: moneyPriceConfig.moneyPriceConfig.display.currency,
|
|
34
|
-
enabledBillingTypes
|
|
45
|
+
enabledBillingTypes,
|
|
35
46
|
}),
|
|
36
47
|
]);
|
|
37
48
|
if (!credit) {
|
|
@@ -43,10 +54,10 @@ function buildCreditOverviewPayload(options) {
|
|
|
43
54
|
subscription,
|
|
44
55
|
});
|
|
45
56
|
const totalBalance = ((_a = credit.balanceFree) !== null && _a !== void 0 ? _a : 0) +
|
|
46
|
-
((_b = credit.balancePaid) !== null && _b !== void 0 ? _b : 0) +
|
|
47
|
-
((_c = credit.balanceOneTimePaid) !== null && _c !== void 0 ? _c : 0);
|
|
57
|
+
(subscriptionBillingEnabled ? (_b = credit.balancePaid) !== null && _b !== void 0 ? _b : 0 : 0) +
|
|
58
|
+
(onetimeBillingEnabled ? (_c = credit.balanceOneTimePaid) !== null && _c !== void 0 ? _c : 0 : 0);
|
|
48
59
|
const buckets = [
|
|
49
|
-
...(credit.balancePaid > 0
|
|
60
|
+
...(subscriptionBillingEnabled && credit.balancePaid > 0
|
|
50
61
|
? [{
|
|
51
62
|
kind: 'subscription',
|
|
52
63
|
balance: credit.balancePaid,
|
|
@@ -54,7 +65,7 @@ function buildCreditOverviewPayload(options) {
|
|
|
54
65
|
expiresAt: utils.viewLocalTime(credit.paidEnd),
|
|
55
66
|
}]
|
|
56
67
|
: []),
|
|
57
|
-
...(credit.balanceOneTimePaid > 0
|
|
68
|
+
...(onetimeBillingEnabled && credit.balanceOneTimePaid > 0
|
|
58
69
|
? [{
|
|
59
70
|
kind: 'onetime',
|
|
60
71
|
balance: credit.balanceOneTimePaid,
|
|
@@ -83,22 +94,27 @@ function buildCreditOverviewPayload(options) {
|
|
|
83
94
|
enableSubscriptionUpgrade,
|
|
84
95
|
initUserContext,
|
|
85
96
|
},
|
|
86
|
-
ctaBehaviors: {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
ctaBehaviors: Object.assign(Object.assign({}, (subscriptionBillingEnabled
|
|
98
|
+
? {
|
|
99
|
+
subscribe: {
|
|
100
|
+
desktop: { kind: 'modal', mode: 'subscription' },
|
|
101
|
+
mobile: { kind: 'redirect', url: `${pricingPageBaseUrl}?initialBillingType=subscription` },
|
|
102
|
+
},
|
|
103
|
+
manage: {
|
|
104
|
+
desktop: { kind: 'auth' },
|
|
105
|
+
mobile: { kind: 'auth' },
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
: {})), (onetimeBillingEnabled
|
|
109
|
+
? {
|
|
110
|
+
onetime: {
|
|
111
|
+
desktop: { kind: 'modal', mode: 'onetime' },
|
|
112
|
+
mobile: { kind: 'redirect', url: `${pricingPageBaseUrl}?initialBillingType=onetime` },
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
: {})),
|
|
100
116
|
};
|
|
101
|
-
if (subscription) {
|
|
117
|
+
if (subscriptionBillingEnabled && subscription) {
|
|
102
118
|
data.subscription = {
|
|
103
119
|
planName: (_d = subscription.priceName) !== null && _d !== void 0 ? _d : '',
|
|
104
120
|
periodStart: utils.viewLocalTime(subscription.subPeriodStart),
|
|
@@ -13,6 +13,14 @@ import { buildMoneyPriceData } from '@windrun-huaiin/third-ui/main/money-price/s
|
|
|
13
13
|
BigInt.prototype.toJSON = function () {
|
|
14
14
|
return this.toString();
|
|
15
15
|
};
|
|
16
|
+
const DEFAULT_ENABLED_BILLING_TYPES = ['monthly', 'yearly', 'onetime'];
|
|
17
|
+
const SUBSCRIPTION_BILLING_TYPES = new Set(['monthly', 'yearly']);
|
|
18
|
+
function normalizeEnabledBillingTypes(enabledBillingTypes) {
|
|
19
|
+
const normalized = Array.from(new Set(((enabledBillingTypes === null || enabledBillingTypes === void 0 ? void 0 : enabledBillingTypes.length) ? enabledBillingTypes : DEFAULT_ENABLED_BILLING_TYPES)
|
|
20
|
+
.map((billingType) => billingType.trim())
|
|
21
|
+
.filter((billingType) => billingType.length > 0)));
|
|
22
|
+
return normalized.length ? normalized : DEFAULT_ENABLED_BILLING_TYPES;
|
|
23
|
+
}
|
|
16
24
|
function buildCreditOverviewPayload(options) {
|
|
17
25
|
return __awaiter(this, void 0, void 0, function* () {
|
|
18
26
|
var _a, _b, _c, _d;
|
|
@@ -20,16 +28,19 @@ function buildCreditOverviewPayload(options) {
|
|
|
20
28
|
if (!authUser) {
|
|
21
29
|
return null;
|
|
22
30
|
}
|
|
23
|
-
const { locale, defaultLocale = 'en', localePrefixAsNeeded = true, translations, pricingPath = '/pricing', checkoutApiEndpoint = '/api/stripe/checkout', customerPortalApiEndpoint = '/api/stripe/customer-portal', } = options;
|
|
31
|
+
const { locale, defaultLocale = 'en', localePrefixAsNeeded = true, translations, pricingPath = '/pricing', checkoutApiEndpoint = '/api/stripe/checkout', customerPortalApiEndpoint = '/api/stripe/customer-portal', enabledBillingTypes: enabledBillingTypesOption, } = options;
|
|
24
32
|
const { user } = authUser;
|
|
25
33
|
const enableSubscriptionUpgrade = process.env.ENABLE_STRIPE_SUBSCRIPTION_UPGRADE !== 'false';
|
|
34
|
+
const enabledBillingTypes = normalizeEnabledBillingTypes(enabledBillingTypesOption);
|
|
35
|
+
const subscriptionBillingEnabled = enabledBillingTypes.some((billingType) => SUBSCRIPTION_BILLING_TYPES.has(billingType));
|
|
36
|
+
const onetimeBillingEnabled = enabledBillingTypes.includes('onetime');
|
|
26
37
|
const [credit, subscription, moneyPriceData] = yield Promise.all([
|
|
27
38
|
creditService.getCredit(user.userId),
|
|
28
39
|
subscriptionService.getActiveSubscription(user.userId),
|
|
29
40
|
buildMoneyPriceData({
|
|
30
41
|
locale,
|
|
31
42
|
currency: moneyPriceConfig.display.currency,
|
|
32
|
-
enabledBillingTypes
|
|
43
|
+
enabledBillingTypes,
|
|
33
44
|
}),
|
|
34
45
|
]);
|
|
35
46
|
if (!credit) {
|
|
@@ -41,10 +52,10 @@ function buildCreditOverviewPayload(options) {
|
|
|
41
52
|
subscription,
|
|
42
53
|
});
|
|
43
54
|
const totalBalance = ((_a = credit.balanceFree) !== null && _a !== void 0 ? _a : 0) +
|
|
44
|
-
((_b = credit.balancePaid) !== null && _b !== void 0 ? _b : 0) +
|
|
45
|
-
((_c = credit.balanceOneTimePaid) !== null && _c !== void 0 ? _c : 0);
|
|
55
|
+
(subscriptionBillingEnabled ? (_b = credit.balancePaid) !== null && _b !== void 0 ? _b : 0 : 0) +
|
|
56
|
+
(onetimeBillingEnabled ? (_c = credit.balanceOneTimePaid) !== null && _c !== void 0 ? _c : 0 : 0);
|
|
46
57
|
const buckets = [
|
|
47
|
-
...(credit.balancePaid > 0
|
|
58
|
+
...(subscriptionBillingEnabled && credit.balancePaid > 0
|
|
48
59
|
? [{
|
|
49
60
|
kind: 'subscription',
|
|
50
61
|
balance: credit.balancePaid,
|
|
@@ -52,7 +63,7 @@ function buildCreditOverviewPayload(options) {
|
|
|
52
63
|
expiresAt: viewLocalTime(credit.paidEnd),
|
|
53
64
|
}]
|
|
54
65
|
: []),
|
|
55
|
-
...(credit.balanceOneTimePaid > 0
|
|
66
|
+
...(onetimeBillingEnabled && credit.balanceOneTimePaid > 0
|
|
56
67
|
? [{
|
|
57
68
|
kind: 'onetime',
|
|
58
69
|
balance: credit.balanceOneTimePaid,
|
|
@@ -81,22 +92,27 @@ function buildCreditOverviewPayload(options) {
|
|
|
81
92
|
enableSubscriptionUpgrade,
|
|
82
93
|
initUserContext,
|
|
83
94
|
},
|
|
84
|
-
ctaBehaviors: {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
ctaBehaviors: Object.assign(Object.assign({}, (subscriptionBillingEnabled
|
|
96
|
+
? {
|
|
97
|
+
subscribe: {
|
|
98
|
+
desktop: { kind: 'modal', mode: 'subscription' },
|
|
99
|
+
mobile: { kind: 'redirect', url: `${pricingPageBaseUrl}?initialBillingType=subscription` },
|
|
100
|
+
},
|
|
101
|
+
manage: {
|
|
102
|
+
desktop: { kind: 'auth' },
|
|
103
|
+
mobile: { kind: 'auth' },
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
: {})), (onetimeBillingEnabled
|
|
107
|
+
? {
|
|
108
|
+
onetime: {
|
|
109
|
+
desktop: { kind: 'modal', mode: 'onetime' },
|
|
110
|
+
mobile: { kind: 'redirect', url: `${pricingPageBaseUrl}?initialBillingType=onetime` },
|
|
111
|
+
},
|
|
112
|
+
}
|
|
113
|
+
: {})),
|
|
98
114
|
};
|
|
99
|
-
if (subscription) {
|
|
115
|
+
if (subscriptionBillingEnabled && subscription) {
|
|
100
116
|
data.subscription = {
|
|
101
117
|
planName: (_d = subscription.priceName) !== null && _d !== void 0 ? _d : '',
|
|
102
118
|
periodStart: viewLocalTime(subscription.subPeriodStart),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@windrun-huaiin/backend-core",
|
|
3
|
-
"version": "31.0.
|
|
3
|
+
"version": "31.0.2",
|
|
4
4
|
"description": "Shared backend primitives: Prisma schema/client, database services, routing helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -153,9 +153,9 @@
|
|
|
153
153
|
"svix": "^1.86.0",
|
|
154
154
|
"tslib": "^2.8.1",
|
|
155
155
|
"zod": "^4.3.6",
|
|
156
|
-
"@windrun-huaiin/lib": "^31.0.2",
|
|
157
156
|
"@windrun-huaiin/contracts": "^31.0.0",
|
|
158
|
-
"@windrun-huaiin/
|
|
157
|
+
"@windrun-huaiin/lib": "^31.0.3",
|
|
158
|
+
"@windrun-huaiin/third-ui": "^31.3.7"
|
|
159
159
|
},
|
|
160
160
|
"devDependencies": {
|
|
161
161
|
"@rollup/plugin-alias": "^5.1.1",
|
|
@@ -20,12 +20,18 @@ export interface CreateGETOptions {
|
|
|
20
20
|
pricingPath?: string;
|
|
21
21
|
checkoutApiEndpoint?: string;
|
|
22
22
|
customerPortalApiEndpoint?: string;
|
|
23
|
+
enabledBillingTypes?: string[];
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export function createGET(options: CreateGETOptions) {
|
|
26
27
|
return async function GET(request: Request) {
|
|
27
28
|
const { searchParams } = new URL(request.url);
|
|
28
29
|
const locale = searchParams.get('locale') || options.defaultLocale || 'en';
|
|
30
|
+
const requestEnabledBillingTypes = searchParams
|
|
31
|
+
.getAll('enabledBillingTypes')
|
|
32
|
+
.flatMap((value) => value.split(','))
|
|
33
|
+
.map((value) => value.trim())
|
|
34
|
+
.filter((value) => value.length > 0);
|
|
29
35
|
const translations = await options.resolveTranslations(locale);
|
|
30
36
|
|
|
31
37
|
const payload = await buildCreditOverviewPayload({
|
|
@@ -36,6 +42,9 @@ export function createGET(options: CreateGETOptions) {
|
|
|
36
42
|
pricingPath: options.pricingPath,
|
|
37
43
|
checkoutApiEndpoint: options.checkoutApiEndpoint,
|
|
38
44
|
customerPortalApiEndpoint: options.customerPortalApiEndpoint,
|
|
45
|
+
enabledBillingTypes: requestEnabledBillingTypes.length
|
|
46
|
+
? requestEnabledBillingTypes
|
|
47
|
+
: options.enabledBillingTypes,
|
|
39
48
|
});
|
|
40
49
|
|
|
41
50
|
return NextResponse.json(payload);
|
|
@@ -21,6 +21,7 @@ export interface BuildCreditOverviewPayloadOptions {
|
|
|
21
21
|
pricingPath?: string;
|
|
22
22
|
checkoutApiEndpoint?: string;
|
|
23
23
|
customerPortalApiEndpoint?: string;
|
|
24
|
+
enabledBillingTypes?: string[];
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export interface CreditOverviewPayload {
|
|
@@ -29,6 +30,21 @@ export interface CreditOverviewPayload {
|
|
|
29
30
|
translations: CreditOverviewTranslations;
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
const DEFAULT_ENABLED_BILLING_TYPES = ['monthly', 'yearly', 'onetime'];
|
|
34
|
+
const SUBSCRIPTION_BILLING_TYPES = new Set(['monthly', 'yearly']);
|
|
35
|
+
|
|
36
|
+
function normalizeEnabledBillingTypes(enabledBillingTypes: string[] | undefined) {
|
|
37
|
+
const normalized = Array.from(
|
|
38
|
+
new Set(
|
|
39
|
+
(enabledBillingTypes?.length ? enabledBillingTypes : DEFAULT_ENABLED_BILLING_TYPES)
|
|
40
|
+
.map((billingType) => billingType.trim())
|
|
41
|
+
.filter((billingType) => billingType.length > 0),
|
|
42
|
+
),
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
return normalized.length ? normalized : DEFAULT_ENABLED_BILLING_TYPES;
|
|
46
|
+
}
|
|
47
|
+
|
|
32
48
|
export async function buildCreditOverviewPayload(
|
|
33
49
|
options: BuildCreditOverviewPayloadOptions,
|
|
34
50
|
): Promise<CreditOverviewPayload | null> {
|
|
@@ -46,10 +62,16 @@ export async function buildCreditOverviewPayload(
|
|
|
46
62
|
pricingPath = '/pricing',
|
|
47
63
|
checkoutApiEndpoint = '/api/stripe/checkout',
|
|
48
64
|
customerPortalApiEndpoint = '/api/stripe/customer-portal',
|
|
65
|
+
enabledBillingTypes: enabledBillingTypesOption,
|
|
49
66
|
} = options;
|
|
50
67
|
|
|
51
68
|
const { user } = authUser;
|
|
52
69
|
const enableSubscriptionUpgrade = process.env.ENABLE_STRIPE_SUBSCRIPTION_UPGRADE !== 'false';
|
|
70
|
+
const enabledBillingTypes = normalizeEnabledBillingTypes(enabledBillingTypesOption);
|
|
71
|
+
const subscriptionBillingEnabled = enabledBillingTypes.some((billingType) =>
|
|
72
|
+
SUBSCRIPTION_BILLING_TYPES.has(billingType),
|
|
73
|
+
);
|
|
74
|
+
const onetimeBillingEnabled = enabledBillingTypes.includes('onetime');
|
|
53
75
|
|
|
54
76
|
const [credit, subscription, moneyPriceData] = await Promise.all([
|
|
55
77
|
creditService.getCredit(user.userId),
|
|
@@ -57,7 +79,7 @@ export async function buildCreditOverviewPayload(
|
|
|
57
79
|
buildMoneyPriceData({
|
|
58
80
|
locale,
|
|
59
81
|
currency: moneyPriceConfig.display.currency,
|
|
60
|
-
enabledBillingTypes
|
|
82
|
+
enabledBillingTypes,
|
|
61
83
|
}),
|
|
62
84
|
]);
|
|
63
85
|
|
|
@@ -73,11 +95,11 @@ export async function buildCreditOverviewPayload(
|
|
|
73
95
|
|
|
74
96
|
const totalBalance =
|
|
75
97
|
(credit.balanceFree ?? 0) +
|
|
76
|
-
(credit.balancePaid ?? 0) +
|
|
77
|
-
(credit.balanceOneTimePaid ?? 0);
|
|
98
|
+
(subscriptionBillingEnabled ? credit.balancePaid ?? 0 : 0) +
|
|
99
|
+
(onetimeBillingEnabled ? credit.balanceOneTimePaid ?? 0 : 0);
|
|
78
100
|
|
|
79
101
|
const buckets = [
|
|
80
|
-
...(credit.balancePaid > 0
|
|
102
|
+
...(subscriptionBillingEnabled && credit.balancePaid > 0
|
|
81
103
|
? [{
|
|
82
104
|
kind: 'subscription' as const,
|
|
83
105
|
balance: credit.balancePaid,
|
|
@@ -85,7 +107,7 @@ export async function buildCreditOverviewPayload(
|
|
|
85
107
|
expiresAt: viewLocalTime(credit.paidEnd),
|
|
86
108
|
}]
|
|
87
109
|
: []),
|
|
88
|
-
...(credit.balanceOneTimePaid > 0
|
|
110
|
+
...(onetimeBillingEnabled && credit.balanceOneTimePaid > 0
|
|
89
111
|
? [{
|
|
90
112
|
kind: 'onetime' as const,
|
|
91
113
|
balance: credit.balanceOneTimePaid,
|
|
@@ -122,22 +144,30 @@ export async function buildCreditOverviewPayload(
|
|
|
122
144
|
initUserContext,
|
|
123
145
|
},
|
|
124
146
|
ctaBehaviors: {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
147
|
+
...(subscriptionBillingEnabled
|
|
148
|
+
? {
|
|
149
|
+
subscribe: {
|
|
150
|
+
desktop: { kind: 'modal', mode: 'subscription' },
|
|
151
|
+
mobile: { kind: 'redirect', url: `${pricingPageBaseUrl}?initialBillingType=subscription` },
|
|
152
|
+
},
|
|
153
|
+
manage: {
|
|
154
|
+
desktop: { kind: 'auth' },
|
|
155
|
+
mobile: { kind: 'auth' },
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
: {}),
|
|
159
|
+
...(onetimeBillingEnabled
|
|
160
|
+
? {
|
|
161
|
+
onetime: {
|
|
162
|
+
desktop: { kind: 'modal', mode: 'onetime' },
|
|
163
|
+
mobile: { kind: 'redirect', url: `${pricingPageBaseUrl}?initialBillingType=onetime` },
|
|
164
|
+
},
|
|
165
|
+
}
|
|
166
|
+
: {}),
|
|
137
167
|
},
|
|
138
168
|
};
|
|
139
169
|
|
|
140
|
-
if (subscription) {
|
|
170
|
+
if (subscriptionBillingEnabled && subscription) {
|
|
141
171
|
data.subscription = {
|
|
142
172
|
planName: subscription.priceName ?? '',
|
|
143
173
|
periodStart: viewLocalTime(subscription.subPeriodStart),
|