export type BillingPlanId = "starter" | "basic" | "pro" | "ultimate"; export type PaidBillingPlanId = Exclude; export type BillingPlanDefinition = { id: BillingPlanId; name: string; price: string; period: string; monthlyImageLimit: number | null; }; export const BILLING_PLAN_DEFINITIONS: BillingPlanDefinition[] = [ { id: "starter", name: "Starter", price: "¥0", period: "/month", monthlyImageLimit: 200, }, { id: "basic", name: "Basic", price: "¥69", period: "/month", monthlyImageLimit: 1200, }, { id: "pro", name: "Pro", price: "¥199", period: "/month", monthlyImageLimit: 6000, }, { id: "ultimate", name: "Ultimate", price: "¥599", period: "/month", monthlyImageLimit: null, }, ]; const PAID_PLAN_IDS: PaidBillingPlanId[] = ["basic", "pro", "ultimate"]; const STRIPE_PRICE_ENV: Record = { basic: "STRIPE_PRICE_ID_BASIC", pro: "STRIPE_PRICE_ID_PRO", ultimate: "STRIPE_PRICE_ID_ULTIMATE", }; export function isBillingPlanId(value: string): value is BillingPlanId { return BILLING_PLAN_DEFINITIONS.some((plan) => plan.id === value); } export function isPaidBillingPlanId(value: string): value is PaidBillingPlanId { return PAID_PLAN_IDS.includes(value as PaidBillingPlanId); } export function getBillingPlanById(planId: BillingPlanId) { return BILLING_PLAN_DEFINITIONS.find((plan) => plan.id === planId) || null; } export function getPaidPlanById(planId: PaidBillingPlanId) { return BILLING_PLAN_DEFINITIONS.find((plan) => plan.id === planId) || null; } export function getMonthlyImageLimitByPlanId(planId: BillingPlanId) { return getBillingPlanById(planId)?.monthlyImageLimit ?? null; } export function getStripePriceIdForPlan(planId: PaidBillingPlanId) { const envName = STRIPE_PRICE_ENV[planId]; const value = process.env[envName]; return value && value.trim().length > 0 ? value.trim() : null; } export function getCheckoutEnabledPlans() { return PAID_PLAN_IDS.reduce>((acc, planId) => { acc[planId] = Boolean(getStripePriceIdForPlan(planId)); return acc; }, { basic: false, pro: false, ultimate: false, }); }