feat: turbostarter boilerplate
Production-ready Next.js boilerplate with: - Runtime env validation (fail-fast on missing vars) - Feature-gated config (S3, Stripe, email, OAuth) - Docker + Coolify deployment pipeline - PostgreSQL + pgvector, MinIO S3, Better Auth - TypeScript strict mode (no ignoreBuildErrors) - i18n (en/es), AI modules, billing, monitoring Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
48
packages/billing/src/providers/lemon-squeezy/subscription.ts
Normal file
48
packages/billing/src/providers/lemon-squeezy/subscription.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { getSubscription } from "@lemonsqueezy/lemonsqueezy.js";
|
||||
|
||||
import { HttpStatusCode } from "@turbostarter/shared/constants";
|
||||
import { logger } from "@turbostarter/shared/logger";
|
||||
import { HttpException } from "@turbostarter/shared/utils";
|
||||
|
||||
import { config } from "../../config";
|
||||
import { getCustomerByCustomerId, updateCustomer } from "../../lib/customer";
|
||||
|
||||
import { toBillingStatus } from "./mappers/to-billing-status";
|
||||
|
||||
export const subscriptionStatusChangeHandler = async ({
|
||||
id,
|
||||
}: {
|
||||
id: string;
|
||||
}) => {
|
||||
const { data } = await getSubscription(id);
|
||||
|
||||
const subscription = data?.data;
|
||||
|
||||
if (!subscription) {
|
||||
throw new HttpException(HttpStatusCode.NOT_FOUND, {
|
||||
code: "billing:error.subscriptionNotFound",
|
||||
});
|
||||
}
|
||||
|
||||
const customer = await getCustomerByCustomerId(
|
||||
subscription.attributes.customer_id.toString(),
|
||||
);
|
||||
|
||||
if (!customer) {
|
||||
throw new HttpException(HttpStatusCode.NOT_FOUND, {
|
||||
code: "billing:error.customerNotFound",
|
||||
});
|
||||
}
|
||||
|
||||
const priceId = subscription.attributes.variant_id.toString();
|
||||
const plan = config.plans.find((p) => p.prices.find((x) => x.id === priceId));
|
||||
|
||||
await updateCustomer(customer.userId, {
|
||||
status: toBillingStatus(subscription.attributes.status),
|
||||
...(plan && { plan: plan.id }),
|
||||
});
|
||||
|
||||
logger.info(
|
||||
`✅ Subscription status changed for user ${customer.userId} to ${subscription.attributes.status}`,
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user