@lukoweb/apitogo-plugin-dev-portal-billing 0.1.138 → 0.1.139
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/index.d.mts +41 -1
- package/dist/index.mjs +43 -6
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
|
+
import { UseQueryResult } from "@lukoweb/apitogo/react-query";
|
|
2
3
|
import * as _lukoweb_apitogo0 from "@lukoweb/apitogo";
|
|
3
4
|
import * as _tanstack_react_query0 from "@tanstack/react-query";
|
|
4
5
|
|
|
@@ -9,6 +10,23 @@ declare const AccountPlansPage: () => react_jsx_runtime0.JSX.Element;
|
|
|
9
10
|
declare const OverviewDashboardPage: () => react_jsx_runtime0.JSX.Element;
|
|
10
11
|
//#endregion
|
|
11
12
|
//#region src/types.d.ts
|
|
13
|
+
type DevPortalPlan = {
|
|
14
|
+
sku: string;
|
|
15
|
+
displayName: string;
|
|
16
|
+
limitsJson: string | null;
|
|
17
|
+
priceAmount: number; /** `custom` plans are sold via a contact-sales form instead of checkout. Absent means `fixed`. */
|
|
18
|
+
pricingModel?: string; /** Text shown instead of the price (custom plans), e.g. "Let's talk". */
|
|
19
|
+
priceLabel?: string | null;
|
|
20
|
+
priceCurrency: string;
|
|
21
|
+
billingPeriod: string;
|
|
22
|
+
syncedAtUtc?: string;
|
|
23
|
+
includedActionKeys?: string[]; /** Optional marketing bullets for pricing cards (preview / local catalog). */
|
|
24
|
+
features?: string[];
|
|
25
|
+
};
|
|
26
|
+
type DevPortalPlanCatalog = {
|
|
27
|
+
plans: DevPortalPlan[];
|
|
28
|
+
lastSyncedAtUtc?: string | null;
|
|
29
|
+
};
|
|
12
30
|
type DevPortalPricingCompareRow = {
|
|
13
31
|
label: string;
|
|
14
32
|
values: string[];
|
|
@@ -207,4 +225,26 @@ declare function useCreateApiKey(): _tanstack_react_query0.UseMutationResult<Dev
|
|
|
207
225
|
}, unknown>;
|
|
208
226
|
declare function useRevokeApiKey(): _tanstack_react_query0.UseMutationResult<void, Error, string, unknown>;
|
|
209
227
|
//#endregion
|
|
210
|
-
|
|
228
|
+
//#region src/hooks/usePlans.d.ts
|
|
229
|
+
declare function usePlans(): UseQueryResult<DevPortalPlanCatalog>;
|
|
230
|
+
//#endregion
|
|
231
|
+
//#region src/hooks/usePlansPreview.d.ts
|
|
232
|
+
/** Matches `PlansPreviewPlan` from `@lukoweb/apitogo-module-landing`. */
|
|
233
|
+
type PlansPreviewItem = {
|
|
234
|
+
name: string;
|
|
235
|
+
price: string;
|
|
236
|
+
unit: string;
|
|
237
|
+
blurb: string;
|
|
238
|
+
featured?: boolean;
|
|
239
|
+
};
|
|
240
|
+
/** Maps plans to landing `PlansPreviewSection` cards, highlighting the same plan as /pricing. */
|
|
241
|
+
declare const toPlansPreviewItems: (plans: DevPortalPlan[]) => PlansPreviewItem[];
|
|
242
|
+
/**
|
|
243
|
+
* Plan cards for the landing `PlansPreviewSection`, sourced like the /pricing page: the dev
|
|
244
|
+
* portal backend when live, `modules.userPanel.plans.items` from `apitogo.config.json` in
|
|
245
|
+
* preview/demo mode. Falls back to the config catalog while the live one is loading or
|
|
246
|
+
* unavailable, so prerendered pages still show plans.
|
|
247
|
+
*/
|
|
248
|
+
declare const usePlansPreview: () => PlansPreviewItem[];
|
|
249
|
+
//#endregion
|
|
250
|
+
export { ACCOUNT_PLANS_PATH, API_KEY_CAP_REACHED, AccountPlansPage, ApiKeysPanel, CHECKOUT_PATH, CONTACT_SALES_PATH, CREDENTIALS_PATH, type DevPortalPlan, type DevPortalPlanCatalog, OverviewDashboardPage, PRICING_PATH, type PlansPreviewItem, SUBSCRIPTIONS_PATH, USAGE_PATH, devPortalBillingPlugin, toPlansPreviewItems, useApiKeys, useCreateApiKey, usePlans, usePlansPreview, useRevokeApiKey };
|
package/dist/index.mjs
CHANGED
|
@@ -136,6 +136,21 @@ function formatBillingPeriod(period) {
|
|
|
136
136
|
if (normalized === "custom") return "talk to us";
|
|
137
137
|
return period;
|
|
138
138
|
}
|
|
139
|
+
/** Headline price for a plan card, without the period suffix (e.g. `$19`, `$0`, `Custom`). */
|
|
140
|
+
function formatPlanDisplayPrice(plan) {
|
|
141
|
+
if (isPlanCustomPriced(plan)) return formatCustomPriceLabel(plan);
|
|
142
|
+
if (isPlanFree(plan)) return "$0";
|
|
143
|
+
const priceLabel = formatPlanPrice(plan);
|
|
144
|
+
return priceLabel.replace(/\/mo$/, "").replace(/\/yr$/, "") || priceLabel;
|
|
145
|
+
}
|
|
146
|
+
/** Caption shown under the plan price (e.g. `per month`, `talk to us`). */
|
|
147
|
+
function formatPlanPriceUnit(plan) {
|
|
148
|
+
return isPlanCustomPriced(plan) ? "talk to us" : formatBillingPeriod(plan.billingPeriod);
|
|
149
|
+
}
|
|
150
|
+
/** SKU of the plan to highlight: `developer` if present, else the first low-priced paid plan. */
|
|
151
|
+
function pickFeaturedPlanSku(plans) {
|
|
152
|
+
return plans.find((p) => p.sku === "developer")?.sku ?? plans.find((p) => p.priceAmount > 0 && p.priceAmount < 50)?.sku ?? plans.find((p) => p.priceAmount > 0)?.sku;
|
|
153
|
+
}
|
|
139
154
|
function formatRateLimit(rate) {
|
|
140
155
|
if (!rate || typeof rate !== "object") return null;
|
|
141
156
|
const { calls, renewalPeriodSeconds } = rate;
|
|
@@ -219,9 +234,7 @@ const planCtaPath = (plan) => `${isPlanCustomPriced(plan) ? CONTACT_SALES_PATH :
|
|
|
219
234
|
const PricingCard = ({ plan, mode = "public", subscriptionStatus, isSubscribed = false, onUnsubscribe, isCanceling = false, cancelDisabled = false, featured = false }) => {
|
|
220
235
|
const isActive = isSubscribed || isActiveSubscription(subscriptionStatus ?? "");
|
|
221
236
|
const features = listPlanFeatureLines(plan);
|
|
222
|
-
const
|
|
223
|
-
const isCustom = isPlanCustomPriced(plan);
|
|
224
|
-
const displayPrice = isCustom ? formatCustomPriceLabel(plan) : isPlanFree(plan) ? "$0" : priceLabel.replace(/\/mo$/, "").replace(/\/yr$/, "") || priceLabel;
|
|
237
|
+
const displayPrice = formatPlanDisplayPrice(plan);
|
|
225
238
|
return /* @__PURE__ */ jsxs("article", {
|
|
226
239
|
className: cn("flex h-full w-full flex-col rounded-xl border border-border bg-card p-7", featured && "border-primary/50 shadow-[0_10px_28px_rgba(13,148,136,0.28)] ring-1 ring-primary/25", isActive && mode === "account" && "border-primary/40 ring-1 ring-primary/20"),
|
|
227
240
|
"data-testid": `pricing-card-${plan.sku}`,
|
|
@@ -250,7 +263,7 @@ const PricingCard = ({ plan, mode = "public", subscriptionStatus, isSubscribed =
|
|
|
250
263
|
}),
|
|
251
264
|
/* @__PURE__ */ jsx("p", {
|
|
252
265
|
className: "mb-[18px] mt-0.5 text-[0.78125rem] text-muted-foreground",
|
|
253
|
-
children:
|
|
266
|
+
children: formatPlanPriceUnit(plan)
|
|
254
267
|
}),
|
|
255
268
|
/* @__PURE__ */ jsx("div", {
|
|
256
269
|
className: "space-y-2",
|
|
@@ -1905,7 +1918,7 @@ const PricingPage = () => {
|
|
|
1905
1918
|
const title = pricing?.title ?? "Pay for what you call";
|
|
1906
1919
|
const subtitle = pricing?.subtitle ?? "Every plan includes the full endpoint catalog. Higher tiers raise your request quota, rate limit, and support level.";
|
|
1907
1920
|
const plans = catalog?.plans ?? [];
|
|
1908
|
-
const featuredSku =
|
|
1921
|
+
const featuredSku = pickFeaturedPlanSku(plans);
|
|
1909
1922
|
const compareRows = pricing?.compareRows && pricing.compareRows.length > 0 ? pricing.compareRows : DEFAULT_COMPARE_ROWS;
|
|
1910
1923
|
const faqs = pricing?.faqs && pricing.faqs.length > 0 ? pricing.faqs : DEFAULT_FAQS;
|
|
1911
1924
|
const compareHeaders = plans.length > 0 ? plans.map((p) => p.displayName) : [
|
|
@@ -2593,4 +2606,28 @@ const devPortalBillingPlugin = createPlugin((options = {}) => ({
|
|
|
2593
2606
|
}));
|
|
2594
2607
|
|
|
2595
2608
|
//#endregion
|
|
2596
|
-
|
|
2609
|
+
//#region src/hooks/usePlansPreview.ts
|
|
2610
|
+
/** Maps plans to landing `PlansPreviewSection` cards, highlighting the same plan as /pricing. */
|
|
2611
|
+
const toPlansPreviewItems = (plans) => {
|
|
2612
|
+
const featuredSku = pickFeaturedPlanSku(plans);
|
|
2613
|
+
return plans.map((plan) => ({
|
|
2614
|
+
name: plan.displayName,
|
|
2615
|
+
price: formatPlanDisplayPrice(plan),
|
|
2616
|
+
unit: formatPlanPriceUnit(plan),
|
|
2617
|
+
blurb: listPlanFeatureLines(plan).slice(0, 2).join(" · "),
|
|
2618
|
+
featured: plan.sku === featuredSku
|
|
2619
|
+
}));
|
|
2620
|
+
};
|
|
2621
|
+
/**
|
|
2622
|
+
* Plan cards for the landing `PlansPreviewSection`, sourced like the /pricing page: the dev
|
|
2623
|
+
* portal backend when live, `modules.userPanel.plans.items` from `apitogo.config.json` in
|
|
2624
|
+
* preview/demo mode. Falls back to the config catalog while the live one is loading or
|
|
2625
|
+
* unavailable, so prerendered pages still show plans.
|
|
2626
|
+
*/
|
|
2627
|
+
const usePlansPreview = () => {
|
|
2628
|
+
const { data } = usePlans();
|
|
2629
|
+
return toPlansPreviewItems(data?.plans ?? parseManifestPlans().plans);
|
|
2630
|
+
};
|
|
2631
|
+
|
|
2632
|
+
//#endregion
|
|
2633
|
+
export { ACCOUNT_PLANS_PATH, API_KEY_CAP_REACHED, AccountPlansPage, ApiKeysPanel, CHECKOUT_PATH, CONTACT_SALES_PATH, CREDENTIALS_PATH, OverviewDashboardPage, PRICING_PATH, SUBSCRIPTIONS_PATH, USAGE_PATH, devPortalBillingPlugin, toPlansPreviewItems, useApiKeys, useCreateApiKey, usePlans, usePlansPreview, useRevokeApiKey };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lukoweb/apitogo-plugin-dev-portal-billing",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.139",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/zuplo/zudoku",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"react": "19.2.4",
|
|
47
47
|
"react-dom": "19.2.4",
|
|
48
48
|
"tsdown": "0.20.3",
|
|
49
|
-
"@lukoweb/apitogo": "0.1.
|
|
50
|
-
"@lukoweb/apitogo-module-user-panel": "0.1.
|
|
49
|
+
"@lukoweb/apitogo": "0.1.139",
|
|
50
|
+
"@lukoweb/apitogo-module-user-panel": "0.1.139"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"react": ">=19.2.0",
|