alepha
Version:
Easy-to-use modern TypeScript framework for building many kind of applications.
57 lines (50 loc) • 1.73 kB
text/typescript
import { z } from "alepha";
import { $parameter } from "alepha/api/parameters";
import { BadRequestError } from "alepha/server";
import {
type PlanDefinition,
planDefinitionSchema,
} from "../schemas/planDefinitionSchema.ts";
import {
type SubscriptionSettings,
subscriptionSettingsSchema,
} from "../schemas/subscriptionSettingsSchema.ts";
export class SubscriptionConfig {
protected readonly plans = $parameter({
name: "subscriptions.plans",
description: "Subscription plan definitions",
schema: z.object({ plans: z.array(planDefinitionSchema) }),
default: { plans: [] },
});
protected readonly settings = $parameter({
name: "subscriptions.settings",
description: "Global subscription settings",
schema: subscriptionSettingsSchema,
default: {
trialDays: 14,
gracePeriodDays: 7,
dunningSchedule: [1, 3, 5, 7],
cancelAtPeriodEnd: true,
prorateOnChange: true,
},
});
public async getPlans(): Promise<PlanDefinition[]> {
return (await this.plans.get()).plans;
}
public async getSettings(): Promise<SubscriptionSettings> {
return this.settings.get();
}
public async getPlan(planId: string): Promise<PlanDefinition> {
const plans = await this.getPlans();
const plan = plans.find((p) => p.id === planId);
if (!plan) throw new BadRequestError(`Plan '${planId}' not found`);
return plan;
}
public async getPlanPricing(planId: string, interval: "monthly" | "yearly") {
const plan = await this.getPlan(planId);
const pricing = plan.pricing.find((p) => p.interval === interval);
if (!pricing)
throw new BadRequestError(`No ${interval} pricing for plan '${planId}'`);
return pricing;
}
}