@commet/next 1.0.5 → 1.0.7
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.js +13 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +13 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -151,7 +151,7 @@ function renderPlansTable(plans, filterIntervals) {
|
|
|
151
151
|
const priceCell = renderPriceCell(plan, filterIntervals);
|
|
152
152
|
const cols = [plan.name, priceCell];
|
|
153
153
|
const featuresByCode = new Map(
|
|
154
|
-
plan.features.map((feature) => [feature.code, feature])
|
|
154
|
+
(plan.features ?? []).map((feature) => [feature.code, feature])
|
|
155
155
|
);
|
|
156
156
|
for (const { code } of usageFeatures) {
|
|
157
157
|
const feature = featuresByCode.get(code);
|
|
@@ -165,7 +165,7 @@ function renderPlansTable(plans, filterIntervals) {
|
|
|
165
165
|
}
|
|
166
166
|
const included = feature.includedAmount;
|
|
167
167
|
cols.push(included ? formatNumber(included) : "\u2014");
|
|
168
|
-
const overagePrice = feature.
|
|
168
|
+
const overagePrice = feature.overage?.enabled && feature.overage.unitPrice !== null ? formatRatePrice(feature.overage.unitPrice) : "\u2014";
|
|
169
169
|
cols.push(overagePrice);
|
|
170
170
|
}
|
|
171
171
|
return cols;
|
|
@@ -178,10 +178,10 @@ function renderPlansTable(plans, filterIntervals) {
|
|
|
178
178
|
];
|
|
179
179
|
const footnotes = [];
|
|
180
180
|
const trialPlans = plans.filter(
|
|
181
|
-
(plan) => plan.prices.some((price) => price.trialDays > 0)
|
|
181
|
+
(plan) => (plan.prices ?? []).some((price) => price.trialDays > 0)
|
|
182
182
|
);
|
|
183
183
|
for (const plan of trialPlans) {
|
|
184
|
-
const trialPrice = plan.prices.find((price) => price.trialDays > 0);
|
|
184
|
+
const trialPrice = (plan.prices ?? []).find((price) => price.trialDays > 0);
|
|
185
185
|
footnotes.push(
|
|
186
186
|
`*${plan.name} plan includes a ${trialPrice.trialDays}-day free trial.*`
|
|
187
187
|
);
|
|
@@ -201,9 +201,9 @@ ${lines.join("\n")}`;
|
|
|
201
201
|
}
|
|
202
202
|
function renderPriceCell(plan, filterIntervals) {
|
|
203
203
|
if (plan.isFree) return "Free";
|
|
204
|
-
const prices = filterIntervals ? plan.prices.filter(
|
|
204
|
+
const prices = filterIntervals ? (plan.prices ?? []).filter(
|
|
205
205
|
(price) => filterIntervals.includes(price.billingInterval)
|
|
206
|
-
) : plan.prices;
|
|
206
|
+
) : plan.prices ?? [];
|
|
207
207
|
if (prices.length === 0) return "\u2014";
|
|
208
208
|
return prices.map((price) => {
|
|
209
209
|
if (price.price === 0) return "Free";
|
|
@@ -213,7 +213,7 @@ function renderPriceCell(plan, filterIntervals) {
|
|
|
213
213
|
function renderFeatures(plans) {
|
|
214
214
|
const allBooleanCodes = /* @__PURE__ */ new Set();
|
|
215
215
|
for (const plan of plans) {
|
|
216
|
-
for (const feature of plan.features) {
|
|
216
|
+
for (const feature of plan.features ?? []) {
|
|
217
217
|
if (feature.type === "boolean") {
|
|
218
218
|
allBooleanCodes.add(feature.code);
|
|
219
219
|
}
|
|
@@ -223,7 +223,7 @@ function renderFeatures(plans) {
|
|
|
223
223
|
const enabledOnAll = /* @__PURE__ */ new Set();
|
|
224
224
|
for (const code of allBooleanCodes) {
|
|
225
225
|
const enabledOnEveryPlan = plans.every((plan) => {
|
|
226
|
-
const feature = plan.features.find((f) => f.code === code);
|
|
226
|
+
const feature = (plan.features ?? []).find((f) => f.code === code);
|
|
227
227
|
return feature?.enabled;
|
|
228
228
|
});
|
|
229
229
|
if (enabledOnEveryPlan) {
|
|
@@ -232,14 +232,14 @@ function renderFeatures(plans) {
|
|
|
232
232
|
}
|
|
233
233
|
const perPlanLines = [];
|
|
234
234
|
for (const plan of plans) {
|
|
235
|
-
const uniqueFeatures = plan.features.filter(
|
|
235
|
+
const uniqueFeatures = (plan.features ?? []).filter(
|
|
236
236
|
(feature) => feature.type === "boolean" && feature.enabled && !enabledOnAll.has(feature.code)
|
|
237
237
|
).map((feature) => feature.name);
|
|
238
238
|
if (uniqueFeatures.length > 0) {
|
|
239
239
|
perPlanLines.push(`- **${plan.name}**: ${uniqueFeatures.join(", ")}`);
|
|
240
240
|
}
|
|
241
241
|
}
|
|
242
|
-
const commonFeatures = plans[0]?.features.filter(
|
|
242
|
+
const commonFeatures = (plans[0]?.features ?? []).filter(
|
|
243
243
|
(feature) => feature.type === "boolean" && enabledOnAll.has(feature.code)
|
|
244
244
|
).map((feature) => feature.name);
|
|
245
245
|
const parts = [];
|
|
@@ -268,7 +268,7 @@ ${lines.join("\n")}`;
|
|
|
268
268
|
function collectUsageFeatures(plans) {
|
|
269
269
|
const seen = /* @__PURE__ */ new Map();
|
|
270
270
|
for (const plan of plans) {
|
|
271
|
-
for (const feature of plan.features) {
|
|
271
|
+
for (const feature of plan.features ?? []) {
|
|
272
272
|
if ((feature.type === "usage" || feature.type === "seats") && !seen.has(feature.code) && hasUsageData(feature)) {
|
|
273
273
|
seen.set(feature.code, {
|
|
274
274
|
code: feature.code,
|
|
@@ -281,7 +281,7 @@ function collectUsageFeatures(plans) {
|
|
|
281
281
|
return Array.from(seen.values());
|
|
282
282
|
}
|
|
283
283
|
function hasUsageData(feature) {
|
|
284
|
-
return feature.unlimited === true || feature.includedAmount !==
|
|
284
|
+
return feature.unlimited === true || feature.includedAmount !== null && feature.includedAmount > 0 || feature.overage?.enabled === true && feature.overage.unitPrice !== null;
|
|
285
285
|
}
|
|
286
286
|
function formatSettlementPrice(cents) {
|
|
287
287
|
if (cents === 0) return "Free";
|
|
@@ -446,7 +446,7 @@ var Webhooks = (config) => {
|
|
|
446
446
|
};
|
|
447
447
|
|
|
448
448
|
// src/index.ts
|
|
449
|
-
(0, import_node4.registerIntegration)("@commet/next", "1.0.
|
|
449
|
+
(0, import_node4.registerIntegration)("@commet/next", "1.0.7");
|
|
450
450
|
// Annotate the CommonJS export names for ESM import in node:
|
|
451
451
|
0 && (module.exports = {
|
|
452
452
|
CustomerPortal,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/portal.ts","../src/pricing-markdown.ts","../src/webhooks.ts"],"sourcesContent":["/**\n * @commet/next - Next.js integration for Commet\n *\n * @example\n * Webhooks\n * ```typescript\n * import { Webhooks } from \"@commet/next\";\n *\n * export const POST = Webhooks({\n * webhookSecret: process.env.COMMET_WEBHOOK_SECRET!,\n * onSubscriptionActivated: async (payload) => {\n * // Handle activation\n * },\n * });\n * ```\n *\n * @example\n * Customer Portal\n * ```typescript\n * import { CustomerPortal } from \"@commet/next\";\n *\n * export const GET = CustomerPortal({\n * apiKey: process.env.COMMET_API_KEY!,\n * getCustomerId: async (req) => {\n * const session = await auth.api.getSession({ headers: req.headers });\n * return session?.user.id;\n * },\n * });\n * ```\n *\n * @packageDocumentation\n */\n\nimport { registerIntegration } from \"@commet/node\";\n\ndeclare const __PKG_VERSION__: string;\nregisterIntegration(\"@commet/next\", __PKG_VERSION__);\n\nexport type { CustomerPortalConfig } from \"./portal\";\nexport { CustomerPortal } from \"./portal\";\nexport type { PricingMarkdownConfig } from \"./pricing-markdown\";\nexport { PricingMarkdown } from \"./pricing-markdown\";\nexport type {\n WebhookData,\n WebhookEvent,\n WebhookPayload,\n WebhooksConfig,\n} from \"./types\";\nexport { Webhooks } from \"./webhooks\";\n","import { Commet } from \"@commet/node\";\nimport { type NextRequest, NextResponse } from \"next/server\";\n\nexport interface CustomerPortalConfig {\n apiKey: string;\n getCustomerId: (req: NextRequest) => Promise<string | null>;\n onError?: (error: Error) => void;\n}\n\n/**\n * Creates Next.js route handler for Customer Portal access\n *\n * @example\n * ```typescript\n * // app/api/commet/portal/route.ts\n * import { CustomerPortal } from \"@commet/next\";\n * import { auth } from \"@/lib/auth\";\n *\n * export const GET = CustomerPortal({\n * apiKey: process.env.COMMET_API_KEY!,\n * getCustomerId: async (req) => {\n * const session = await auth.api.getSession({ headers: req.headers });\n * return session?.user.id ?? null;\n * },\n * });\n * ```\n *\n * @example\n * ```tsx\n * // Use in component\n * export function BillingButton() {\n * return (\n * <Button asChild>\n * <Link href=\"/api/commet/portal\">Manage Billing</Link>\n * </Button>\n * );\n * }\n * ```\n */\nexport const CustomerPortal = ({\n apiKey,\n getCustomerId,\n onError,\n}: CustomerPortalConfig) => {\n const commet = new Commet({\n apiKey,\n });\n\n return async (req: NextRequest) => {\n try {\n // Get customer identifier from request\n const customerId = await getCustomerId(req);\n\n if (!customerId) {\n return NextResponse.json(\n { error: \"Customer not authenticated\" },\n { status: 401 },\n );\n }\n\n // Get portal URL from Commet\n const result = await commet.portal.getUrl({\n customerId,\n });\n\n if (!result.success || !result.data) {\n throw new Error(\n result.error?.message || \"Failed to create portal session\",\n );\n }\n\n // Redirect to customer portal\n return NextResponse.redirect(result.data.portalUrl);\n } catch (error) {\n const errorObj =\n error instanceof Error ? error : new Error(String(error));\n\n // Call custom error handler if provided\n onError?.(errorObj);\n\n // Log error\n console.error(\"[Commet Portal]\", errorObj);\n\n // Return error response\n return NextResponse.json(\n { error: \"Failed to access customer portal\" },\n { status: 500 },\n );\n }\n };\n};\n","import type {\n BillingInterval,\n CreditPack,\n Plan,\n PlanFeature,\n} from \"@commet/node\";\nimport { Commet } from \"@commet/node\";\nimport { type NextRequest, NextResponse } from \"next/server\";\n\nexport interface PricingMarkdownConfig {\n apiKey: string;\n title: string;\n description?: string;\n includeCreditPacks?: boolean;\n billingIntervals?: BillingInterval[];\n cacheMaxAge?: number;\n onError?: (error: Error) => void;\n}\n\nconst INTERVAL_SHORT: Record<BillingInterval, string> = {\n weekly: \"/wk\",\n monthly: \"/mo\",\n quarterly: \"/qtr\",\n yearly: \"/yr\",\n one_time: \"\",\n};\n\nexport const PricingMarkdown = ({\n apiKey,\n title,\n description,\n includeCreditPacks = false,\n billingIntervals,\n cacheMaxAge = 3600,\n onError,\n}: PricingMarkdownConfig) => {\n const commet = new Commet({ apiKey });\n\n return async (_req: NextRequest) => {\n try {\n const plansResult = await commet.plans.list();\n\n if (!plansResult.success || !plansResult.data) {\n throw new Error(plansResult.error?.message ?? \"Failed to fetch plans\");\n }\n\n const publicPlans = plansResult.data.filter((plan) => plan.isPublic);\n\n const creditPacks = includeCreditPacks\n ? await commet.creditPacks\n .list()\n .then((result) =>\n result.success && result.data ? result.data : [],\n )\n : [];\n\n const markdown = generateMarkdown(\n title,\n description,\n publicPlans,\n creditPacks,\n billingIntervals,\n );\n\n return new NextResponse(markdown, {\n status: 200,\n headers: {\n \"Content-Type\": \"text/markdown; charset=utf-8\",\n \"Cache-Control\": `public, s-maxage=${cacheMaxAge}, stale-while-revalidate=${cacheMaxAge * 2}`,\n },\n });\n } catch (error) {\n const errorObj =\n error instanceof Error ? error : new Error(String(error));\n\n onError?.(errorObj);\n console.error(\"[Commet PricingMarkdown]\", errorObj);\n\n return NextResponse.json(\n { error: \"Failed to generate pricing markdown\" },\n { status: 500 },\n );\n }\n };\n};\n\nfunction generateMarkdown(\n title: string,\n description: string | undefined,\n plans: Plan[],\n creditPacks: CreditPack[],\n billingIntervals?: BillingInterval[],\n): string {\n const sections: string[] = [`# ${title}`];\n\n if (description) {\n sections.push(description);\n }\n\n if (plans.length > 0) {\n sections.push(renderPlansTable(plans, billingIntervals));\n\n const featuresSection = renderFeatures(plans);\n if (featuresSection) {\n sections.push(featuresSection);\n }\n }\n\n if (creditPacks.length > 0) {\n sections.push(renderCreditPacks(creditPacks));\n }\n\n return sections.join(\"\\n\\n\");\n}\n\nfunction renderPlansTable(\n plans: Plan[],\n filterIntervals?: BillingInterval[],\n): string {\n const usageFeatures = collectUsageFeatures(plans);\n\n const headerCols = [\"Plan\", \"Price\"];\n for (const { name, unitName } of usageFeatures) {\n headerCols.push(`${name}/${unitName ?? \"unit\"}`);\n headerCols.push(\"Overage\");\n }\n\n const rows = plans.map((plan) => {\n const priceCell = renderPriceCell(plan, filterIntervals);\n const cols = [plan.name, priceCell];\n\n const featuresByCode = new Map(\n plan.features.map((feature) => [feature.code, feature]),\n );\n\n for (const { code } of usageFeatures) {\n const feature = featuresByCode.get(code);\n\n if (!feature) {\n cols.push(\"—\", \"—\");\n continue;\n }\n\n if (feature.unlimited) {\n cols.push(\"Unlimited\", \"—\");\n continue;\n }\n\n const included = feature.includedAmount;\n cols.push(included ? formatNumber(included) : \"—\");\n\n const overagePrice =\n feature.overageEnabled && feature.overageUnitPrice !== undefined\n ? formatRatePrice(feature.overageUnitPrice)\n : \"—\";\n cols.push(overagePrice);\n }\n\n return cols;\n });\n\n const separator = headerCols.map(() => \"---\");\n const lines = [\n `| ${headerCols.join(\" | \")} |`,\n `| ${separator.join(\" | \")} |`,\n ...rows.map((cols) => `| ${cols.join(\" | \")} |`),\n ];\n\n const footnotes: string[] = [];\n\n const trialPlans = plans.filter((plan) =>\n plan.prices.some((price) => price.trialDays > 0),\n );\n for (const plan of trialPlans) {\n const trialPrice = plan.prices.find((price) => price.trialDays > 0)!;\n footnotes.push(\n `*${plan.name} plan includes a ${trialPrice.trialDays}-day free trial.*`,\n );\n }\n\n if (usageFeatures.length > 0) {\n footnotes.push(\n \"The overage rate applies only to usage beyond the included volume.\",\n );\n }\n\n return footnotes.length > 0\n ? `## Plans\\n\\n${lines.join(\"\\n\")}\\n\\n${footnotes.join(\"\\n\\n\")}`\n : `## Plans\\n\\n${lines.join(\"\\n\")}`;\n}\n\nfunction renderPriceCell(\n plan: Plan,\n filterIntervals?: BillingInterval[],\n): string {\n if (plan.isFree) return \"Free\";\n\n const prices = filterIntervals\n ? plan.prices.filter((price) =>\n filterIntervals.includes(price.billingInterval),\n )\n : plan.prices;\n\n if (prices.length === 0) return \"—\";\n\n return prices\n .map((price) => {\n if (price.price === 0) return \"Free\";\n return `${formatSettlementPrice(price.price)}${INTERVAL_SHORT[price.billingInterval]}`;\n })\n .join(\" / \");\n}\n\nfunction renderFeatures(plans: Plan[]): string | null {\n const allBooleanCodes = new Set<string>();\n for (const plan of plans) {\n for (const feature of plan.features) {\n if (feature.type === \"boolean\") {\n allBooleanCodes.add(feature.code);\n }\n }\n }\n\n if (allBooleanCodes.size === 0) return null;\n\n const enabledOnAll = new Set<string>();\n for (const code of allBooleanCodes) {\n const enabledOnEveryPlan = plans.every((plan) => {\n const feature = plan.features.find((f) => f.code === code);\n return feature?.enabled;\n });\n if (enabledOnEveryPlan) {\n enabledOnAll.add(code);\n }\n }\n\n const perPlanLines: string[] = [];\n for (const plan of plans) {\n const uniqueFeatures = plan.features\n .filter(\n (feature) =>\n feature.type === \"boolean\" &&\n feature.enabled &&\n !enabledOnAll.has(feature.code),\n )\n .map((feature) => feature.name);\n\n if (uniqueFeatures.length > 0) {\n perPlanLines.push(`- **${plan.name}**: ${uniqueFeatures.join(\", \")}`);\n }\n }\n\n const commonFeatures = plans[0]?.features\n .filter(\n (feature) => feature.type === \"boolean\" && enabledOnAll.has(feature.code),\n )\n .map((feature) => feature.name);\n\n const parts: string[] = [];\n\n if (perPlanLines.length > 0) {\n parts.push(perPlanLines.join(\"\\n\"));\n }\n\n if (commonFeatures && commonFeatures.length > 0) {\n parts.push(`All plans include: ${commonFeatures.join(\", \")}.`);\n }\n\n return parts.length > 0 ? `## Features\\n\\n${parts.join(\"\\n\\n\")}` : null;\n}\n\nfunction renderCreditPacks(packs: CreditPack[]): string {\n const lines = [\n \"| Pack | Credits | Price |\",\n \"| --- | --- | --- |\",\n ...packs.map(\n (pack) =>\n `| ${pack.name} | ${formatNumber(pack.credits)} credits | ${formatSettlementPrice(pack.price)} |`,\n ),\n ];\n\n return `## Credit Packs\\n\\n${lines.join(\"\\n\")}`;\n}\n\ninterface UsageFeatureColumn {\n code: string;\n name: string;\n unitName: string | null;\n}\n\nfunction collectUsageFeatures(plans: Plan[]): UsageFeatureColumn[] {\n const seen = new Map<string, UsageFeatureColumn>();\n for (const plan of plans) {\n for (const feature of plan.features) {\n if (\n (feature.type === \"usage\" || feature.type === \"seats\") &&\n !seen.has(feature.code) &&\n hasUsageData(feature)\n ) {\n seen.set(feature.code, {\n code: feature.code,\n name: feature.name,\n unitName: feature.unitName,\n });\n }\n }\n }\n return Array.from(seen.values());\n}\n\nfunction hasUsageData(feature: PlanFeature): boolean {\n return (\n feature.unlimited === true ||\n (feature.includedAmount !== undefined && feature.includedAmount > 0) ||\n (feature.overageEnabled === true && feature.overageUnitPrice !== undefined)\n );\n}\n\nfunction formatSettlementPrice(cents: number): string {\n if (cents === 0) return \"Free\";\n const dollars = cents / 100;\n const [whole, decimal] = dollars.toFixed(2).split(\".\");\n return `$${Number(whole).toLocaleString(\"en-US\")}.${decimal}`;\n}\n\nfunction formatRatePrice(rate: number): string {\n const dollars = rate / 10000;\n\n if (dollars === Math.floor(dollars)) {\n return `$${dollars.toFixed(2)}`;\n }\n\n const formatted = dollars.toFixed(4).replace(/0+$/, \"\");\n const decimalPlaces = formatted.split(\".\")[1]?.length ?? 0;\n if (decimalPlaces < 2) {\n return `$${dollars.toFixed(2)}`;\n }\n\n return `$${formatted}`;\n}\n\nfunction formatNumber(n: number): string {\n return n.toLocaleString(\"en-US\");\n}\n","import type { WebhookPayload } from \"@commet/node\";\nimport { Webhooks as CommetWebhooks } from \"@commet/node\";\nimport { type NextRequest, NextResponse } from \"next/server\";\nimport type { WebhooksConfig } from \"./types\";\n\n/**\n * Create a Next.js webhook handler for Commet events\n *\n * Automatically verifies signatures, routes events to handlers, and returns proper responses.\n *\n * @param config - Webhook configuration with secret and event handlers\n * @returns Next.js route handler function\n *\n * @example\n * ```typescript\n * // app/api/webhooks/commet/route.ts\n * import { Webhooks } from \"@commet/next\";\n *\n * export const POST = Webhooks({\n * webhookSecret: process.env.COMMET_WEBHOOK_SECRET!,\n * onSubscriptionActivated: async (payload) => {\n * // Grant access to user\n * },\n * onSubscriptionCanceled: async (payload) => {\n * // Revoke access from user\n * },\n * });\n * ```\n */\nexport const Webhooks = (config: WebhooksConfig) => {\n const {\n webhookSecret,\n onSubscriptionActivated,\n onSubscriptionCanceled,\n onSubscriptionCreated,\n onSubscriptionUpdated,\n onSubscriptionPlanChanged,\n onPaymentReceived,\n onPaymentFailed,\n onInvoiceCreated,\n onPayload,\n onError,\n } = config;\n\n // Create webhook verifier instance\n const webhooks = new CommetWebhooks();\n\n return async (request: NextRequest) => {\n try {\n // 1. Read raw request body\n const rawBody = await request.text();\n\n // 2. Extract signature from headers\n const signature = request.headers.get(\"x-commet-signature\");\n\n // 3. Verify signature\n const isValid = webhooks.verify({\n payload: rawBody,\n signature,\n secret: webhookSecret,\n });\n\n if (!isValid) {\n console.error(\"[Commet Webhook] Invalid signature\");\n return NextResponse.json(\n { received: false, error: \"Invalid signature\" },\n { status: 403 },\n );\n }\n\n // 4. Parse payload\n let payload: WebhookPayload;\n try {\n payload = JSON.parse(rawBody) as WebhookPayload;\n } catch (parseError) {\n console.error(\"[Commet Webhook] Failed to parse payload:\", parseError);\n if (onError) {\n await onError(\n parseError instanceof Error\n ? parseError\n : new Error(\"Failed to parse webhook payload\"),\n rawBody,\n );\n }\n return NextResponse.json(\n { received: false, error: \"Invalid payload\" },\n { status: 400 },\n );\n }\n\n // 5. Collect promises for parallel execution\n const promises: Promise<void>[] = [];\n\n // Call catch-all handler if provided\n if (onPayload) {\n promises.push(onPayload(payload));\n }\n\n // 6. Route to specific event handler\n switch (payload.event) {\n case \"subscription.activated\":\n if (onSubscriptionActivated) {\n promises.push(onSubscriptionActivated(payload));\n }\n break;\n\n case \"subscription.canceled\":\n if (onSubscriptionCanceled) {\n promises.push(onSubscriptionCanceled(payload));\n }\n break;\n\n case \"subscription.created\":\n if (onSubscriptionCreated) {\n promises.push(onSubscriptionCreated(payload));\n }\n break;\n\n case \"subscription.updated\":\n if (onSubscriptionUpdated) {\n promises.push(onSubscriptionUpdated(payload));\n }\n break;\n\n case \"subscription.plan_changed\":\n if (onSubscriptionPlanChanged) {\n promises.push(onSubscriptionPlanChanged(payload));\n }\n break;\n\n case \"payment.received\":\n if (onPaymentReceived) {\n promises.push(onPaymentReceived(payload));\n }\n break;\n\n case \"payment.failed\":\n if (onPaymentFailed) {\n promises.push(onPaymentFailed(payload));\n }\n break;\n\n case \"invoice.created\":\n if (onInvoiceCreated) {\n promises.push(onInvoiceCreated(payload));\n }\n break;\n\n default:\n console.log(`[Commet Webhook] Unhandled event: ${payload.event}`);\n }\n\n // 7. Execute all handlers in parallel\n try {\n await Promise.all(promises);\n } catch (handlerError) {\n console.error(\n \"[Commet Webhook] Handler error:\",\n handlerError instanceof Error ? handlerError.message : handlerError,\n );\n if (onError) {\n await onError(\n handlerError instanceof Error\n ? handlerError\n : new Error(\"Handler execution failed\"),\n payload,\n );\n }\n // Still return 200 to prevent retries for handler errors\n return NextResponse.json(\n { received: true, warning: \"Handler failed\" },\n { status: 200 },\n );\n }\n\n // 8. Success response\n return NextResponse.json({ received: true }, { status: 200 });\n } catch (error) {\n console.error(\"[Commet Webhook] Unexpected error:\", error);\n if (onError) {\n try {\n await onError(\n error instanceof Error ? error : new Error(\"Unexpected error\"),\n undefined,\n );\n } catch (errorHandlerError) {\n console.error(\n \"[Commet Webhook] Error handler failed:\",\n errorHandlerError,\n );\n }\n }\n return NextResponse.json(\n { received: false, error: \"Internal error\" },\n { status: 500 },\n );\n }\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiCA,IAAAA,eAAoC;;;ACjCpC,kBAAuB;AACvB,oBAA+C;AAsCxC,IAAM,iBAAiB,CAAC;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AACF,MAA4B;AAC1B,QAAM,SAAS,IAAI,mBAAO;AAAA,IACxB;AAAA,EACF,CAAC;AAED,SAAO,OAAO,QAAqB;AACjC,QAAI;AAEF,YAAM,aAAa,MAAM,cAAc,GAAG;AAE1C,UAAI,CAAC,YAAY;AACf,eAAO,2BAAa;AAAA,UAClB,EAAE,OAAO,6BAA6B;AAAA,UACtC,EAAE,QAAQ,IAAI;AAAA,QAChB;AAAA,MACF;AAGA,YAAM,SAAS,MAAM,OAAO,OAAO,OAAO;AAAA,QACxC;AAAA,MACF,CAAC;AAED,UAAI,CAAC,OAAO,WAAW,CAAC,OAAO,MAAM;AACnC,cAAM,IAAI;AAAA,UACR,OAAO,OAAO,WAAW;AAAA,QAC3B;AAAA,MACF;AAGA,aAAO,2BAAa,SAAS,OAAO,KAAK,SAAS;AAAA,IACpD,SAAS,OAAO;AACd,YAAM,WACJ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAG1D,gBAAU,QAAQ;AAGlB,cAAQ,MAAM,mBAAmB,QAAQ;AAGzC,aAAO,2BAAa;AAAA,QAClB,EAAE,OAAO,mCAAmC;AAAA,QAC5C,EAAE,QAAQ,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACF;;;ACpFA,IAAAC,eAAuB;AACvB,IAAAC,iBAA+C;AAY/C,IAAM,iBAAkD;AAAA,EACtD,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,UAAU;AACZ;AAEO,IAAM,kBAAkB,CAAC;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA,qBAAqB;AAAA,EACrB;AAAA,EACA,cAAc;AAAA,EACd;AACF,MAA6B;AAC3B,QAAM,SAAS,IAAI,oBAAO,EAAE,OAAO,CAAC;AAEpC,SAAO,OAAO,SAAsB;AAClC,QAAI;AACF,YAAM,cAAc,MAAM,OAAO,MAAM,KAAK;AAE5C,UAAI,CAAC,YAAY,WAAW,CAAC,YAAY,MAAM;AAC7C,cAAM,IAAI,MAAM,YAAY,OAAO,WAAW,uBAAuB;AAAA,MACvE;AAEA,YAAM,cAAc,YAAY,KAAK,OAAO,CAAC,SAAS,KAAK,QAAQ;AAEnE,YAAM,cAAc,qBAChB,MAAM,OAAO,YACV,KAAK,EACL;AAAA,QAAK,CAAC,WACL,OAAO,WAAW,OAAO,OAAO,OAAO,OAAO,CAAC;AAAA,MACjD,IACF,CAAC;AAEL,YAAM,WAAW;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,aAAO,IAAI,4BAAa,UAAU;AAAA,QAChC,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,iBAAiB,oBAAoB,WAAW,4BAA4B,cAAc,CAAC;AAAA,QAC7F;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,YAAM,WACJ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAE1D,gBAAU,QAAQ;AAClB,cAAQ,MAAM,4BAA4B,QAAQ;AAElD,aAAO,4BAAa;AAAA,QAClB,EAAE,OAAO,sCAAsC;AAAA,QAC/C,EAAE,QAAQ,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,iBACP,OACA,aACA,OACA,aACA,kBACQ;AACR,QAAM,WAAqB,CAAC,KAAK,KAAK,EAAE;AAExC,MAAI,aAAa;AACf,aAAS,KAAK,WAAW;AAAA,EAC3B;AAEA,MAAI,MAAM,SAAS,GAAG;AACpB,aAAS,KAAK,iBAAiB,OAAO,gBAAgB,CAAC;AAEvD,UAAM,kBAAkB,eAAe,KAAK;AAC5C,QAAI,iBAAiB;AACnB,eAAS,KAAK,eAAe;AAAA,IAC/B;AAAA,EACF;AAEA,MAAI,YAAY,SAAS,GAAG;AAC1B,aAAS,KAAK,kBAAkB,WAAW,CAAC;AAAA,EAC9C;AAEA,SAAO,SAAS,KAAK,MAAM;AAC7B;AAEA,SAAS,iBACP,OACA,iBACQ;AACR,QAAM,gBAAgB,qBAAqB,KAAK;AAEhD,QAAM,aAAa,CAAC,QAAQ,OAAO;AACnC,aAAW,EAAE,MAAM,SAAS,KAAK,eAAe;AAC9C,eAAW,KAAK,GAAG,IAAI,IAAI,YAAY,MAAM,EAAE;AAC/C,eAAW,KAAK,SAAS;AAAA,EAC3B;AAEA,QAAM,OAAO,MAAM,IAAI,CAAC,SAAS;AAC/B,UAAM,YAAY,gBAAgB,MAAM,eAAe;AACvD,UAAM,OAAO,CAAC,KAAK,MAAM,SAAS;AAElC,UAAM,iBAAiB,IAAI;AAAA,MACzB,KAAK,SAAS,IAAI,CAAC,YAAY,CAAC,QAAQ,MAAM,OAAO,CAAC;AAAA,IACxD;AAEA,eAAW,EAAE,KAAK,KAAK,eAAe;AACpC,YAAM,UAAU,eAAe,IAAI,IAAI;AAEvC,UAAI,CAAC,SAAS;AACZ,aAAK,KAAK,UAAK,QAAG;AAClB;AAAA,MACF;AAEA,UAAI,QAAQ,WAAW;AACrB,aAAK,KAAK,aAAa,QAAG;AAC1B;AAAA,MACF;AAEA,YAAM,WAAW,QAAQ;AACzB,WAAK,KAAK,WAAW,aAAa,QAAQ,IAAI,QAAG;AAEjD,YAAM,eACJ,QAAQ,kBAAkB,QAAQ,qBAAqB,SACnD,gBAAgB,QAAQ,gBAAgB,IACxC;AACN,WAAK,KAAK,YAAY;AAAA,IACxB;AAEA,WAAO;AAAA,EACT,CAAC;AAED,QAAM,YAAY,WAAW,IAAI,MAAM,KAAK;AAC5C,QAAM,QAAQ;AAAA,IACZ,KAAK,WAAW,KAAK,KAAK,CAAC;AAAA,IAC3B,KAAK,UAAU,KAAK,KAAK,CAAC;AAAA,IAC1B,GAAG,KAAK,IAAI,CAAC,SAAS,KAAK,KAAK,KAAK,KAAK,CAAC,IAAI;AAAA,EACjD;AAEA,QAAM,YAAsB,CAAC;AAE7B,QAAM,aAAa,MAAM;AAAA,IAAO,CAAC,SAC/B,KAAK,OAAO,KAAK,CAAC,UAAU,MAAM,YAAY,CAAC;AAAA,EACjD;AACA,aAAW,QAAQ,YAAY;AAC7B,UAAM,aAAa,KAAK,OAAO,KAAK,CAAC,UAAU,MAAM,YAAY,CAAC;AAClE,cAAU;AAAA,MACR,IAAI,KAAK,IAAI,oBAAoB,WAAW,SAAS;AAAA,IACvD;AAAA,EACF;AAEA,MAAI,cAAc,SAAS,GAAG;AAC5B,cAAU;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO,UAAU,SAAS,IACtB;AAAA;AAAA,EAAe,MAAM,KAAK,IAAI,CAAC;AAAA;AAAA,EAAO,UAAU,KAAK,MAAM,CAAC,KAC5D;AAAA;AAAA,EAAe,MAAM,KAAK,IAAI,CAAC;AACrC;AAEA,SAAS,gBACP,MACA,iBACQ;AACR,MAAI,KAAK,OAAQ,QAAO;AAExB,QAAM,SAAS,kBACX,KAAK,OAAO;AAAA,IAAO,CAAC,UAClB,gBAAgB,SAAS,MAAM,eAAe;AAAA,EAChD,IACA,KAAK;AAET,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO,OACJ,IAAI,CAAC,UAAU;AACd,QAAI,MAAM,UAAU,EAAG,QAAO;AAC9B,WAAO,GAAG,sBAAsB,MAAM,KAAK,CAAC,GAAG,eAAe,MAAM,eAAe,CAAC;AAAA,EACtF,CAAC,EACA,KAAK,KAAK;AACf;AAEA,SAAS,eAAe,OAA8B;AACpD,QAAM,kBAAkB,oBAAI,IAAY;AACxC,aAAW,QAAQ,OAAO;AACxB,eAAW,WAAW,KAAK,UAAU;AACnC,UAAI,QAAQ,SAAS,WAAW;AAC9B,wBAAgB,IAAI,QAAQ,IAAI;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,gBAAgB,SAAS,EAAG,QAAO;AAEvC,QAAM,eAAe,oBAAI,IAAY;AACrC,aAAW,QAAQ,iBAAiB;AAClC,UAAM,qBAAqB,MAAM,MAAM,CAAC,SAAS;AAC/C,YAAM,UAAU,KAAK,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AACzD,aAAO,SAAS;AAAA,IAClB,CAAC;AACD,QAAI,oBAAoB;AACtB,mBAAa,IAAI,IAAI;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,eAAyB,CAAC;AAChC,aAAW,QAAQ,OAAO;AACxB,UAAM,iBAAiB,KAAK,SACzB;AAAA,MACC,CAAC,YACC,QAAQ,SAAS,aACjB,QAAQ,WACR,CAAC,aAAa,IAAI,QAAQ,IAAI;AAAA,IAClC,EACC,IAAI,CAAC,YAAY,QAAQ,IAAI;AAEhC,QAAI,eAAe,SAAS,GAAG;AAC7B,mBAAa,KAAK,OAAO,KAAK,IAAI,OAAO,eAAe,KAAK,IAAI,CAAC,EAAE;AAAA,IACtE;AAAA,EACF;AAEA,QAAM,iBAAiB,MAAM,CAAC,GAAG,SAC9B;AAAA,IACC,CAAC,YAAY,QAAQ,SAAS,aAAa,aAAa,IAAI,QAAQ,IAAI;AAAA,EAC1E,EACC,IAAI,CAAC,YAAY,QAAQ,IAAI;AAEhC,QAAM,QAAkB,CAAC;AAEzB,MAAI,aAAa,SAAS,GAAG;AAC3B,UAAM,KAAK,aAAa,KAAK,IAAI,CAAC;AAAA,EACpC;AAEA,MAAI,kBAAkB,eAAe,SAAS,GAAG;AAC/C,UAAM,KAAK,sBAAsB,eAAe,KAAK,IAAI,CAAC,GAAG;AAAA,EAC/D;AAEA,SAAO,MAAM,SAAS,IAAI;AAAA;AAAA,EAAkB,MAAM,KAAK,MAAM,CAAC,KAAK;AACrE;AAEA,SAAS,kBAAkB,OAA6B;AACtD,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,IACA,GAAG,MAAM;AAAA,MACP,CAAC,SACC,KAAK,KAAK,IAAI,MAAM,aAAa,KAAK,OAAO,CAAC,cAAc,sBAAsB,KAAK,KAAK,CAAC;AAAA,IACjG;AAAA,EACF;AAEA,SAAO;AAAA;AAAA,EAAsB,MAAM,KAAK,IAAI,CAAC;AAC/C;AAQA,SAAS,qBAAqB,OAAqC;AACjE,QAAM,OAAO,oBAAI,IAAgC;AACjD,aAAW,QAAQ,OAAO;AACxB,eAAW,WAAW,KAAK,UAAU;AACnC,WACG,QAAQ,SAAS,WAAW,QAAQ,SAAS,YAC9C,CAAC,KAAK,IAAI,QAAQ,IAAI,KACtB,aAAa,OAAO,GACpB;AACA,aAAK,IAAI,QAAQ,MAAM;AAAA,UACrB,MAAM,QAAQ;AAAA,UACd,MAAM,QAAQ;AAAA,UACd,UAAU,QAAQ;AAAA,QACpB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACA,SAAO,MAAM,KAAK,KAAK,OAAO,CAAC;AACjC;AAEA,SAAS,aAAa,SAA+B;AACnD,SACE,QAAQ,cAAc,QACrB,QAAQ,mBAAmB,UAAa,QAAQ,iBAAiB,KACjE,QAAQ,mBAAmB,QAAQ,QAAQ,qBAAqB;AAErE;AAEA,SAAS,sBAAsB,OAAuB;AACpD,MAAI,UAAU,EAAG,QAAO;AACxB,QAAM,UAAU,QAAQ;AACxB,QAAM,CAAC,OAAO,OAAO,IAAI,QAAQ,QAAQ,CAAC,EAAE,MAAM,GAAG;AACrD,SAAO,IAAI,OAAO,KAAK,EAAE,eAAe,OAAO,CAAC,IAAI,OAAO;AAC7D;AAEA,SAAS,gBAAgB,MAAsB;AAC7C,QAAM,UAAU,OAAO;AAEvB,MAAI,YAAY,KAAK,MAAM,OAAO,GAAG;AACnC,WAAO,IAAI,QAAQ,QAAQ,CAAC,CAAC;AAAA,EAC/B;AAEA,QAAM,YAAY,QAAQ,QAAQ,CAAC,EAAE,QAAQ,OAAO,EAAE;AACtD,QAAM,gBAAgB,UAAU,MAAM,GAAG,EAAE,CAAC,GAAG,UAAU;AACzD,MAAI,gBAAgB,GAAG;AACrB,WAAO,IAAI,QAAQ,QAAQ,CAAC,CAAC;AAAA,EAC/B;AAEA,SAAO,IAAI,SAAS;AACtB;AAEA,SAAS,aAAa,GAAmB;AACvC,SAAO,EAAE,eAAe,OAAO;AACjC;;;ACtVA,IAAAC,eAA2C;AAC3C,IAAAC,iBAA+C;AA2BxC,IAAM,WAAW,CAAC,WAA2B;AAClD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAGJ,QAAM,WAAW,IAAI,aAAAC,SAAe;AAEpC,SAAO,OAAO,YAAyB;AACrC,QAAI;AAEF,YAAM,UAAU,MAAM,QAAQ,KAAK;AAGnC,YAAM,YAAY,QAAQ,QAAQ,IAAI,oBAAoB;AAG1D,YAAM,UAAU,SAAS,OAAO;AAAA,QAC9B,SAAS;AAAA,QACT;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,CAAC,SAAS;AACZ,gBAAQ,MAAM,oCAAoC;AAClD,eAAO,4BAAa;AAAA,UAClB,EAAE,UAAU,OAAO,OAAO,oBAAoB;AAAA,UAC9C,EAAE,QAAQ,IAAI;AAAA,QAChB;AAAA,MACF;AAGA,UAAI;AACJ,UAAI;AACF,kBAAU,KAAK,MAAM,OAAO;AAAA,MAC9B,SAAS,YAAY;AACnB,gBAAQ,MAAM,6CAA6C,UAAU;AACrE,YAAI,SAAS;AACX,gBAAM;AAAA,YACJ,sBAAsB,QAClB,aACA,IAAI,MAAM,iCAAiC;AAAA,YAC/C;AAAA,UACF;AAAA,QACF;AACA,eAAO,4BAAa;AAAA,UAClB,EAAE,UAAU,OAAO,OAAO,kBAAkB;AAAA,UAC5C,EAAE,QAAQ,IAAI;AAAA,QAChB;AAAA,MACF;AAGA,YAAM,WAA4B,CAAC;AAGnC,UAAI,WAAW;AACb,iBAAS,KAAK,UAAU,OAAO,CAAC;AAAA,MAClC;AAGA,cAAQ,QAAQ,OAAO;AAAA,QACrB,KAAK;AACH,cAAI,yBAAyB;AAC3B,qBAAS,KAAK,wBAAwB,OAAO,CAAC;AAAA,UAChD;AACA;AAAA,QAEF,KAAK;AACH,cAAI,wBAAwB;AAC1B,qBAAS,KAAK,uBAAuB,OAAO,CAAC;AAAA,UAC/C;AACA;AAAA,QAEF,KAAK;AACH,cAAI,uBAAuB;AACzB,qBAAS,KAAK,sBAAsB,OAAO,CAAC;AAAA,UAC9C;AACA;AAAA,QAEF,KAAK;AACH,cAAI,uBAAuB;AACzB,qBAAS,KAAK,sBAAsB,OAAO,CAAC;AAAA,UAC9C;AACA;AAAA,QAEF,KAAK;AACH,cAAI,2BAA2B;AAC7B,qBAAS,KAAK,0BAA0B,OAAO,CAAC;AAAA,UAClD;AACA;AAAA,QAEF,KAAK;AACH,cAAI,mBAAmB;AACrB,qBAAS,KAAK,kBAAkB,OAAO,CAAC;AAAA,UAC1C;AACA;AAAA,QAEF,KAAK;AACH,cAAI,iBAAiB;AACnB,qBAAS,KAAK,gBAAgB,OAAO,CAAC;AAAA,UACxC;AACA;AAAA,QAEF,KAAK;AACH,cAAI,kBAAkB;AACpB,qBAAS,KAAK,iBAAiB,OAAO,CAAC;AAAA,UACzC;AACA;AAAA,QAEF;AACE,kBAAQ,IAAI,qCAAqC,QAAQ,KAAK,EAAE;AAAA,MACpE;AAGA,UAAI;AACF,cAAM,QAAQ,IAAI,QAAQ;AAAA,MAC5B,SAAS,cAAc;AACrB,gBAAQ;AAAA,UACN;AAAA,UACA,wBAAwB,QAAQ,aAAa,UAAU;AAAA,QACzD;AACA,YAAI,SAAS;AACX,gBAAM;AAAA,YACJ,wBAAwB,QACpB,eACA,IAAI,MAAM,0BAA0B;AAAA,YACxC;AAAA,UACF;AAAA,QACF;AAEA,eAAO,4BAAa;AAAA,UAClB,EAAE,UAAU,MAAM,SAAS,iBAAiB;AAAA,UAC5C,EAAE,QAAQ,IAAI;AAAA,QAChB;AAAA,MACF;AAGA,aAAO,4BAAa,KAAK,EAAE,UAAU,KAAK,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC9D,SAAS,OAAO;AACd,cAAQ,MAAM,sCAAsC,KAAK;AACzD,UAAI,SAAS;AACX,YAAI;AACF,gBAAM;AAAA,YACJ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,kBAAkB;AAAA,YAC7D;AAAA,UACF;AAAA,QACF,SAAS,mBAAmB;AAC1B,kBAAQ;AAAA,YACN;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,aAAO,4BAAa;AAAA,QAClB,EAAE,UAAU,OAAO,OAAO,iBAAiB;AAAA,QAC3C,EAAE,QAAQ,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACF;;;IHlKA,kCAAoB,gBAAgB,OAAe;","names":["import_node","import_node","import_server","import_node","import_server","CommetWebhooks"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/portal.ts","../src/pricing-markdown.ts","../src/webhooks.ts"],"sourcesContent":["/**\n * @commet/next - Next.js integration for Commet\n *\n * @example\n * Webhooks\n * ```typescript\n * import { Webhooks } from \"@commet/next\";\n *\n * export const POST = Webhooks({\n * webhookSecret: process.env.COMMET_WEBHOOK_SECRET!,\n * onSubscriptionActivated: async (payload) => {\n * // Handle activation\n * },\n * });\n * ```\n *\n * @example\n * Customer Portal\n * ```typescript\n * import { CustomerPortal } from \"@commet/next\";\n *\n * export const GET = CustomerPortal({\n * apiKey: process.env.COMMET_API_KEY!,\n * getCustomerId: async (req) => {\n * const session = await auth.api.getSession({ headers: req.headers });\n * return session?.user.id;\n * },\n * });\n * ```\n *\n * @packageDocumentation\n */\n\nimport { registerIntegration } from \"@commet/node\";\n\ndeclare const __PKG_VERSION__: string;\nregisterIntegration(\"@commet/next\", __PKG_VERSION__);\n\nexport type { CustomerPortalConfig } from \"./portal\";\nexport { CustomerPortal } from \"./portal\";\nexport type { PricingMarkdownConfig } from \"./pricing-markdown\";\nexport { PricingMarkdown } from \"./pricing-markdown\";\nexport type {\n WebhookData,\n WebhookEvent,\n WebhookPayload,\n WebhooksConfig,\n} from \"./types\";\nexport { Webhooks } from \"./webhooks\";\n","import { Commet } from \"@commet/node\";\nimport { type NextRequest, NextResponse } from \"next/server\";\n\nexport interface CustomerPortalConfig {\n apiKey: string;\n getCustomerId: (req: NextRequest) => Promise<string | null>;\n onError?: (error: Error) => void;\n}\n\n/**\n * Creates Next.js route handler for Customer Portal access\n *\n * @example\n * ```typescript\n * // app/api/commet/portal/route.ts\n * import { CustomerPortal } from \"@commet/next\";\n * import { auth } from \"@/lib/auth\";\n *\n * export const GET = CustomerPortal({\n * apiKey: process.env.COMMET_API_KEY!,\n * getCustomerId: async (req) => {\n * const session = await auth.api.getSession({ headers: req.headers });\n * return session?.user.id ?? null;\n * },\n * });\n * ```\n *\n * @example\n * ```tsx\n * // Use in component\n * export function BillingButton() {\n * return (\n * <Button asChild>\n * <Link href=\"/api/commet/portal\">Manage Billing</Link>\n * </Button>\n * );\n * }\n * ```\n */\nexport const CustomerPortal = ({\n apiKey,\n getCustomerId,\n onError,\n}: CustomerPortalConfig) => {\n const commet = new Commet({\n apiKey,\n });\n\n return async (req: NextRequest) => {\n try {\n // Get customer identifier from request\n const customerId = await getCustomerId(req);\n\n if (!customerId) {\n return NextResponse.json(\n { error: \"Customer not authenticated\" },\n { status: 401 },\n );\n }\n\n // Get portal URL from Commet\n const result = await commet.portal.getUrl({\n customerId,\n });\n\n if (!result.success || !result.data) {\n throw new Error(\n result.error?.message || \"Failed to create portal session\",\n );\n }\n\n // Redirect to customer portal\n return NextResponse.redirect(result.data.portalUrl);\n } catch (error) {\n const errorObj =\n error instanceof Error ? error : new Error(String(error));\n\n // Call custom error handler if provided\n onError?.(errorObj);\n\n // Log error\n console.error(\"[Commet Portal]\", errorObj);\n\n // Return error response\n return NextResponse.json(\n { error: \"Failed to access customer portal\" },\n { status: 500 },\n );\n }\n };\n};\n","import type { BillingInterval, CreditPack, Plan } from \"@commet/node\";\nimport { Commet } from \"@commet/node\";\nimport { type NextRequest, NextResponse } from \"next/server\";\n\ntype PlanFeature = NonNullable<Plan[\"features\"]>[number];\n\nexport interface PricingMarkdownConfig {\n apiKey: string;\n title: string;\n description?: string;\n includeCreditPacks?: boolean;\n billingIntervals?: BillingInterval[];\n cacheMaxAge?: number;\n onError?: (error: Error) => void;\n}\n\nconst INTERVAL_SHORT: Record<BillingInterval, string> = {\n weekly: \"/wk\",\n monthly: \"/mo\",\n quarterly: \"/qtr\",\n yearly: \"/yr\",\n one_time: \"\",\n};\n\nexport const PricingMarkdown = ({\n apiKey,\n title,\n description,\n includeCreditPacks = false,\n billingIntervals,\n cacheMaxAge = 3600,\n onError,\n}: PricingMarkdownConfig) => {\n const commet = new Commet({ apiKey });\n\n return async (_req: NextRequest) => {\n try {\n const plansResult = await commet.plans.list();\n\n if (!plansResult.success || !plansResult.data) {\n throw new Error(plansResult.error?.message ?? \"Failed to fetch plans\");\n }\n\n const publicPlans = plansResult.data.filter((plan) => plan.isPublic);\n\n const creditPacks = includeCreditPacks\n ? await commet.creditPacks\n .list()\n .then((result) =>\n result.success && result.data ? result.data : [],\n )\n : [];\n\n const markdown = generateMarkdown(\n title,\n description,\n publicPlans,\n creditPacks,\n billingIntervals,\n );\n\n return new NextResponse(markdown, {\n status: 200,\n headers: {\n \"Content-Type\": \"text/markdown; charset=utf-8\",\n \"Cache-Control\": `public, s-maxage=${cacheMaxAge}, stale-while-revalidate=${cacheMaxAge * 2}`,\n },\n });\n } catch (error) {\n const errorObj =\n error instanceof Error ? error : new Error(String(error));\n\n onError?.(errorObj);\n console.error(\"[Commet PricingMarkdown]\", errorObj);\n\n return NextResponse.json(\n { error: \"Failed to generate pricing markdown\" },\n { status: 500 },\n );\n }\n };\n};\n\nfunction generateMarkdown(\n title: string,\n description: string | undefined,\n plans: Plan[],\n creditPacks: CreditPack[],\n billingIntervals?: BillingInterval[],\n): string {\n const sections: string[] = [`# ${title}`];\n\n if (description) {\n sections.push(description);\n }\n\n if (plans.length > 0) {\n sections.push(renderPlansTable(plans, billingIntervals));\n\n const featuresSection = renderFeatures(plans);\n if (featuresSection) {\n sections.push(featuresSection);\n }\n }\n\n if (creditPacks.length > 0) {\n sections.push(renderCreditPacks(creditPacks));\n }\n\n return sections.join(\"\\n\\n\");\n}\n\nfunction renderPlansTable(\n plans: Plan[],\n filterIntervals?: BillingInterval[],\n): string {\n const usageFeatures = collectUsageFeatures(plans);\n\n const headerCols = [\"Plan\", \"Price\"];\n for (const { name, unitName } of usageFeatures) {\n headerCols.push(`${name}/${unitName ?? \"unit\"}`);\n headerCols.push(\"Overage\");\n }\n\n const rows = plans.map((plan) => {\n const priceCell = renderPriceCell(plan, filterIntervals);\n const cols = [plan.name, priceCell];\n\n const featuresByCode = new Map(\n (plan.features ?? []).map((feature) => [feature.code, feature]),\n );\n\n for (const { code } of usageFeatures) {\n const feature = featuresByCode.get(code);\n\n if (!feature) {\n cols.push(\"—\", \"—\");\n continue;\n }\n\n if (feature.unlimited) {\n cols.push(\"Unlimited\", \"—\");\n continue;\n }\n\n const included = feature.includedAmount;\n cols.push(included ? formatNumber(included) : \"—\");\n\n const overagePrice =\n feature.overage?.enabled && feature.overage.unitPrice !== null\n ? formatRatePrice(feature.overage.unitPrice)\n : \"—\";\n cols.push(overagePrice);\n }\n\n return cols;\n });\n\n const separator = headerCols.map(() => \"---\");\n const lines = [\n `| ${headerCols.join(\" | \")} |`,\n `| ${separator.join(\" | \")} |`,\n ...rows.map((cols) => `| ${cols.join(\" | \")} |`),\n ];\n\n const footnotes: string[] = [];\n\n const trialPlans = plans.filter((plan) =>\n (plan.prices ?? []).some((price) => price.trialDays > 0),\n );\n for (const plan of trialPlans) {\n const trialPrice = (plan.prices ?? []).find((price) => price.trialDays > 0)!;\n footnotes.push(\n `*${plan.name} plan includes a ${trialPrice.trialDays}-day free trial.*`,\n );\n }\n\n if (usageFeatures.length > 0) {\n footnotes.push(\n \"The overage rate applies only to usage beyond the included volume.\",\n );\n }\n\n return footnotes.length > 0\n ? `## Plans\\n\\n${lines.join(\"\\n\")}\\n\\n${footnotes.join(\"\\n\\n\")}`\n : `## Plans\\n\\n${lines.join(\"\\n\")}`;\n}\n\nfunction renderPriceCell(\n plan: Plan,\n filterIntervals?: BillingInterval[],\n): string {\n if (plan.isFree) return \"Free\";\n\n const prices = filterIntervals\n ? (plan.prices ?? []).filter((price) =>\n filterIntervals.includes(price.billingInterval),\n )\n : (plan.prices ?? []);\n\n if (prices.length === 0) return \"—\";\n\n return prices\n .map((price) => {\n if (price.price === 0) return \"Free\";\n return `${formatSettlementPrice(price.price)}${INTERVAL_SHORT[price.billingInterval]}`;\n })\n .join(\" / \");\n}\n\nfunction renderFeatures(plans: Plan[]): string | null {\n const allBooleanCodes = new Set<string>();\n for (const plan of plans) {\n for (const feature of plan.features ?? []) {\n if (feature.type === \"boolean\") {\n allBooleanCodes.add(feature.code);\n }\n }\n }\n\n if (allBooleanCodes.size === 0) return null;\n\n const enabledOnAll = new Set<string>();\n for (const code of allBooleanCodes) {\n const enabledOnEveryPlan = plans.every((plan) => {\n const feature = (plan.features ?? []).find((f) => f.code === code);\n return feature?.enabled;\n });\n if (enabledOnEveryPlan) {\n enabledOnAll.add(code);\n }\n }\n\n const perPlanLines: string[] = [];\n for (const plan of plans) {\n const uniqueFeatures = (plan.features ?? [])\n .filter(\n (feature) =>\n feature.type === \"boolean\" &&\n feature.enabled &&\n !enabledOnAll.has(feature.code),\n )\n .map((feature) => feature.name);\n\n if (uniqueFeatures.length > 0) {\n perPlanLines.push(`- **${plan.name}**: ${uniqueFeatures.join(\", \")}`);\n }\n }\n\n const commonFeatures = (plans[0]?.features ?? [])\n .filter(\n (feature) => feature.type === \"boolean\" && enabledOnAll.has(feature.code),\n )\n .map((feature) => feature.name);\n\n const parts: string[] = [];\n\n if (perPlanLines.length > 0) {\n parts.push(perPlanLines.join(\"\\n\"));\n }\n\n if (commonFeatures && commonFeatures.length > 0) {\n parts.push(`All plans include: ${commonFeatures.join(\", \")}.`);\n }\n\n return parts.length > 0 ? `## Features\\n\\n${parts.join(\"\\n\\n\")}` : null;\n}\n\nfunction renderCreditPacks(packs: CreditPack[]): string {\n const lines = [\n \"| Pack | Credits | Price |\",\n \"| --- | --- | --- |\",\n ...packs.map(\n (pack) =>\n `| ${pack.name} | ${formatNumber(pack.credits)} credits | ${formatSettlementPrice(pack.price)} |`,\n ),\n ];\n\n return `## Credit Packs\\n\\n${lines.join(\"\\n\")}`;\n}\n\ninterface UsageFeatureColumn {\n code: string;\n name: string;\n unitName: string | null;\n}\n\nfunction collectUsageFeatures(plans: Plan[]): UsageFeatureColumn[] {\n const seen = new Map<string, UsageFeatureColumn>();\n for (const plan of plans) {\n for (const feature of plan.features ?? []) {\n if (\n (feature.type === \"usage\" || feature.type === \"seats\") &&\n !seen.has(feature.code) &&\n hasUsageData(feature)\n ) {\n seen.set(feature.code, {\n code: feature.code,\n name: feature.name,\n unitName: feature.unitName,\n });\n }\n }\n }\n return Array.from(seen.values());\n}\n\nfunction hasUsageData(feature: PlanFeature): boolean {\n return (\n feature.unlimited === true ||\n (feature.includedAmount !== null && feature.includedAmount > 0) ||\n (feature.overage?.enabled === true && feature.overage.unitPrice !== null)\n );\n}\n\nfunction formatSettlementPrice(cents: number): string {\n if (cents === 0) return \"Free\";\n const dollars = cents / 100;\n const [whole, decimal] = dollars.toFixed(2).split(\".\");\n return `$${Number(whole).toLocaleString(\"en-US\")}.${decimal}`;\n}\n\nfunction formatRatePrice(rate: number): string {\n const dollars = rate / 10000;\n\n if (dollars === Math.floor(dollars)) {\n return `$${dollars.toFixed(2)}`;\n }\n\n const formatted = dollars.toFixed(4).replace(/0+$/, \"\");\n const decimalPlaces = formatted.split(\".\")[1]?.length ?? 0;\n if (decimalPlaces < 2) {\n return `$${dollars.toFixed(2)}`;\n }\n\n return `$${formatted}`;\n}\n\nfunction formatNumber(n: number): string {\n return n.toLocaleString(\"en-US\");\n}\n","import type { WebhookPayload } from \"@commet/node\";\nimport { Webhooks as CommetWebhooks } from \"@commet/node\";\nimport { type NextRequest, NextResponse } from \"next/server\";\nimport type { WebhooksConfig } from \"./types\";\n\n/**\n * Create a Next.js webhook handler for Commet events\n *\n * Automatically verifies signatures, routes events to handlers, and returns proper responses.\n *\n * @param config - Webhook configuration with secret and event handlers\n * @returns Next.js route handler function\n *\n * @example\n * ```typescript\n * // app/api/webhooks/commet/route.ts\n * import { Webhooks } from \"@commet/next\";\n *\n * export const POST = Webhooks({\n * webhookSecret: process.env.COMMET_WEBHOOK_SECRET!,\n * onSubscriptionActivated: async (payload) => {\n * // Grant access to user\n * },\n * onSubscriptionCanceled: async (payload) => {\n * // Revoke access from user\n * },\n * });\n * ```\n */\nexport const Webhooks = (config: WebhooksConfig) => {\n const {\n webhookSecret,\n onSubscriptionActivated,\n onSubscriptionCanceled,\n onSubscriptionCreated,\n onSubscriptionUpdated,\n onSubscriptionPlanChanged,\n onPaymentReceived,\n onPaymentFailed,\n onInvoiceCreated,\n onPayload,\n onError,\n } = config;\n\n // Create webhook verifier instance\n const webhooks = new CommetWebhooks();\n\n return async (request: NextRequest) => {\n try {\n // 1. Read raw request body\n const rawBody = await request.text();\n\n // 2. Extract signature from headers\n const signature = request.headers.get(\"x-commet-signature\");\n\n // 3. Verify signature\n const isValid = webhooks.verify({\n payload: rawBody,\n signature,\n secret: webhookSecret,\n });\n\n if (!isValid) {\n console.error(\"[Commet Webhook] Invalid signature\");\n return NextResponse.json(\n { received: false, error: \"Invalid signature\" },\n { status: 403 },\n );\n }\n\n // 4. Parse payload\n let payload: WebhookPayload;\n try {\n payload = JSON.parse(rawBody) as WebhookPayload;\n } catch (parseError) {\n console.error(\"[Commet Webhook] Failed to parse payload:\", parseError);\n if (onError) {\n await onError(\n parseError instanceof Error\n ? parseError\n : new Error(\"Failed to parse webhook payload\"),\n rawBody,\n );\n }\n return NextResponse.json(\n { received: false, error: \"Invalid payload\" },\n { status: 400 },\n );\n }\n\n // 5. Collect promises for parallel execution\n const promises: Promise<void>[] = [];\n\n // Call catch-all handler if provided\n if (onPayload) {\n promises.push(onPayload(payload));\n }\n\n // 6. Route to specific event handler\n switch (payload.event) {\n case \"subscription.activated\":\n if (onSubscriptionActivated) {\n promises.push(onSubscriptionActivated(payload));\n }\n break;\n\n case \"subscription.canceled\":\n if (onSubscriptionCanceled) {\n promises.push(onSubscriptionCanceled(payload));\n }\n break;\n\n case \"subscription.created\":\n if (onSubscriptionCreated) {\n promises.push(onSubscriptionCreated(payload));\n }\n break;\n\n case \"subscription.updated\":\n if (onSubscriptionUpdated) {\n promises.push(onSubscriptionUpdated(payload));\n }\n break;\n\n case \"subscription.plan_changed\":\n if (onSubscriptionPlanChanged) {\n promises.push(onSubscriptionPlanChanged(payload));\n }\n break;\n\n case \"payment.received\":\n if (onPaymentReceived) {\n promises.push(onPaymentReceived(payload));\n }\n break;\n\n case \"payment.failed\":\n if (onPaymentFailed) {\n promises.push(onPaymentFailed(payload));\n }\n break;\n\n case \"invoice.created\":\n if (onInvoiceCreated) {\n promises.push(onInvoiceCreated(payload));\n }\n break;\n\n default:\n console.log(`[Commet Webhook] Unhandled event: ${payload.event}`);\n }\n\n // 7. Execute all handlers in parallel\n try {\n await Promise.all(promises);\n } catch (handlerError) {\n console.error(\n \"[Commet Webhook] Handler error:\",\n handlerError instanceof Error ? handlerError.message : handlerError,\n );\n if (onError) {\n await onError(\n handlerError instanceof Error\n ? handlerError\n : new Error(\"Handler execution failed\"),\n payload,\n );\n }\n // Still return 200 to prevent retries for handler errors\n return NextResponse.json(\n { received: true, warning: \"Handler failed\" },\n { status: 200 },\n );\n }\n\n // 8. Success response\n return NextResponse.json({ received: true }, { status: 200 });\n } catch (error) {\n console.error(\"[Commet Webhook] Unexpected error:\", error);\n if (onError) {\n try {\n await onError(\n error instanceof Error ? error : new Error(\"Unexpected error\"),\n undefined,\n );\n } catch (errorHandlerError) {\n console.error(\n \"[Commet Webhook] Error handler failed:\",\n errorHandlerError,\n );\n }\n }\n return NextResponse.json(\n { received: false, error: \"Internal error\" },\n { status: 500 },\n );\n }\n };\n};\n"],"mappings":"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","names":["import_node","import_node","import_server","import_node","import_server","CommetWebhooks"]}
|
package/dist/index.mjs
CHANGED
|
@@ -125,7 +125,7 @@ function renderPlansTable(plans, filterIntervals) {
|
|
|
125
125
|
const priceCell = renderPriceCell(plan, filterIntervals);
|
|
126
126
|
const cols = [plan.name, priceCell];
|
|
127
127
|
const featuresByCode = new Map(
|
|
128
|
-
plan.features.map((feature) => [feature.code, feature])
|
|
128
|
+
(plan.features ?? []).map((feature) => [feature.code, feature])
|
|
129
129
|
);
|
|
130
130
|
for (const { code } of usageFeatures) {
|
|
131
131
|
const feature = featuresByCode.get(code);
|
|
@@ -139,7 +139,7 @@ function renderPlansTable(plans, filterIntervals) {
|
|
|
139
139
|
}
|
|
140
140
|
const included = feature.includedAmount;
|
|
141
141
|
cols.push(included ? formatNumber(included) : "\u2014");
|
|
142
|
-
const overagePrice = feature.
|
|
142
|
+
const overagePrice = feature.overage?.enabled && feature.overage.unitPrice !== null ? formatRatePrice(feature.overage.unitPrice) : "\u2014";
|
|
143
143
|
cols.push(overagePrice);
|
|
144
144
|
}
|
|
145
145
|
return cols;
|
|
@@ -152,10 +152,10 @@ function renderPlansTable(plans, filterIntervals) {
|
|
|
152
152
|
];
|
|
153
153
|
const footnotes = [];
|
|
154
154
|
const trialPlans = plans.filter(
|
|
155
|
-
(plan) => plan.prices.some((price) => price.trialDays > 0)
|
|
155
|
+
(plan) => (plan.prices ?? []).some((price) => price.trialDays > 0)
|
|
156
156
|
);
|
|
157
157
|
for (const plan of trialPlans) {
|
|
158
|
-
const trialPrice = plan.prices.find((price) => price.trialDays > 0);
|
|
158
|
+
const trialPrice = (plan.prices ?? []).find((price) => price.trialDays > 0);
|
|
159
159
|
footnotes.push(
|
|
160
160
|
`*${plan.name} plan includes a ${trialPrice.trialDays}-day free trial.*`
|
|
161
161
|
);
|
|
@@ -175,9 +175,9 @@ ${lines.join("\n")}`;
|
|
|
175
175
|
}
|
|
176
176
|
function renderPriceCell(plan, filterIntervals) {
|
|
177
177
|
if (plan.isFree) return "Free";
|
|
178
|
-
const prices = filterIntervals ? plan.prices.filter(
|
|
178
|
+
const prices = filterIntervals ? (plan.prices ?? []).filter(
|
|
179
179
|
(price) => filterIntervals.includes(price.billingInterval)
|
|
180
|
-
) : plan.prices;
|
|
180
|
+
) : plan.prices ?? [];
|
|
181
181
|
if (prices.length === 0) return "\u2014";
|
|
182
182
|
return prices.map((price) => {
|
|
183
183
|
if (price.price === 0) return "Free";
|
|
@@ -187,7 +187,7 @@ function renderPriceCell(plan, filterIntervals) {
|
|
|
187
187
|
function renderFeatures(plans) {
|
|
188
188
|
const allBooleanCodes = /* @__PURE__ */ new Set();
|
|
189
189
|
for (const plan of plans) {
|
|
190
|
-
for (const feature of plan.features) {
|
|
190
|
+
for (const feature of plan.features ?? []) {
|
|
191
191
|
if (feature.type === "boolean") {
|
|
192
192
|
allBooleanCodes.add(feature.code);
|
|
193
193
|
}
|
|
@@ -197,7 +197,7 @@ function renderFeatures(plans) {
|
|
|
197
197
|
const enabledOnAll = /* @__PURE__ */ new Set();
|
|
198
198
|
for (const code of allBooleanCodes) {
|
|
199
199
|
const enabledOnEveryPlan = plans.every((plan) => {
|
|
200
|
-
const feature = plan.features.find((f) => f.code === code);
|
|
200
|
+
const feature = (plan.features ?? []).find((f) => f.code === code);
|
|
201
201
|
return feature?.enabled;
|
|
202
202
|
});
|
|
203
203
|
if (enabledOnEveryPlan) {
|
|
@@ -206,14 +206,14 @@ function renderFeatures(plans) {
|
|
|
206
206
|
}
|
|
207
207
|
const perPlanLines = [];
|
|
208
208
|
for (const plan of plans) {
|
|
209
|
-
const uniqueFeatures = plan.features.filter(
|
|
209
|
+
const uniqueFeatures = (plan.features ?? []).filter(
|
|
210
210
|
(feature) => feature.type === "boolean" && feature.enabled && !enabledOnAll.has(feature.code)
|
|
211
211
|
).map((feature) => feature.name);
|
|
212
212
|
if (uniqueFeatures.length > 0) {
|
|
213
213
|
perPlanLines.push(`- **${plan.name}**: ${uniqueFeatures.join(", ")}`);
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
|
-
const commonFeatures = plans[0]?.features.filter(
|
|
216
|
+
const commonFeatures = (plans[0]?.features ?? []).filter(
|
|
217
217
|
(feature) => feature.type === "boolean" && enabledOnAll.has(feature.code)
|
|
218
218
|
).map((feature) => feature.name);
|
|
219
219
|
const parts = [];
|
|
@@ -242,7 +242,7 @@ ${lines.join("\n")}`;
|
|
|
242
242
|
function collectUsageFeatures(plans) {
|
|
243
243
|
const seen = /* @__PURE__ */ new Map();
|
|
244
244
|
for (const plan of plans) {
|
|
245
|
-
for (const feature of plan.features) {
|
|
245
|
+
for (const feature of plan.features ?? []) {
|
|
246
246
|
if ((feature.type === "usage" || feature.type === "seats") && !seen.has(feature.code) && hasUsageData(feature)) {
|
|
247
247
|
seen.set(feature.code, {
|
|
248
248
|
code: feature.code,
|
|
@@ -255,7 +255,7 @@ function collectUsageFeatures(plans) {
|
|
|
255
255
|
return Array.from(seen.values());
|
|
256
256
|
}
|
|
257
257
|
function hasUsageData(feature) {
|
|
258
|
-
return feature.unlimited === true || feature.includedAmount !==
|
|
258
|
+
return feature.unlimited === true || feature.includedAmount !== null && feature.includedAmount > 0 || feature.overage?.enabled === true && feature.overage.unitPrice !== null;
|
|
259
259
|
}
|
|
260
260
|
function formatSettlementPrice(cents) {
|
|
261
261
|
if (cents === 0) return "Free";
|
|
@@ -420,7 +420,7 @@ var Webhooks = (config) => {
|
|
|
420
420
|
};
|
|
421
421
|
|
|
422
422
|
// src/index.ts
|
|
423
|
-
registerIntegration("@commet/next", "1.0.
|
|
423
|
+
registerIntegration("@commet/next", "1.0.7");
|
|
424
424
|
export {
|
|
425
425
|
CustomerPortal,
|
|
426
426
|
PricingMarkdown,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/portal.ts","../src/pricing-markdown.ts","../src/webhooks.ts"],"sourcesContent":["/**\n * @commet/next - Next.js integration for Commet\n *\n * @example\n * Webhooks\n * ```typescript\n * import { Webhooks } from \"@commet/next\";\n *\n * export const POST = Webhooks({\n * webhookSecret: process.env.COMMET_WEBHOOK_SECRET!,\n * onSubscriptionActivated: async (payload) => {\n * // Handle activation\n * },\n * });\n * ```\n *\n * @example\n * Customer Portal\n * ```typescript\n * import { CustomerPortal } from \"@commet/next\";\n *\n * export const GET = CustomerPortal({\n * apiKey: process.env.COMMET_API_KEY!,\n * getCustomerId: async (req) => {\n * const session = await auth.api.getSession({ headers: req.headers });\n * return session?.user.id;\n * },\n * });\n * ```\n *\n * @packageDocumentation\n */\n\nimport { registerIntegration } from \"@commet/node\";\n\ndeclare const __PKG_VERSION__: string;\nregisterIntegration(\"@commet/next\", __PKG_VERSION__);\n\nexport type { CustomerPortalConfig } from \"./portal\";\nexport { CustomerPortal } from \"./portal\";\nexport type { PricingMarkdownConfig } from \"./pricing-markdown\";\nexport { PricingMarkdown } from \"./pricing-markdown\";\nexport type {\n WebhookData,\n WebhookEvent,\n WebhookPayload,\n WebhooksConfig,\n} from \"./types\";\nexport { Webhooks } from \"./webhooks\";\n","import { Commet } from \"@commet/node\";\nimport { type NextRequest, NextResponse } from \"next/server\";\n\nexport interface CustomerPortalConfig {\n apiKey: string;\n getCustomerId: (req: NextRequest) => Promise<string | null>;\n onError?: (error: Error) => void;\n}\n\n/**\n * Creates Next.js route handler for Customer Portal access\n *\n * @example\n * ```typescript\n * // app/api/commet/portal/route.ts\n * import { CustomerPortal } from \"@commet/next\";\n * import { auth } from \"@/lib/auth\";\n *\n * export const GET = CustomerPortal({\n * apiKey: process.env.COMMET_API_KEY!,\n * getCustomerId: async (req) => {\n * const session = await auth.api.getSession({ headers: req.headers });\n * return session?.user.id ?? null;\n * },\n * });\n * ```\n *\n * @example\n * ```tsx\n * // Use in component\n * export function BillingButton() {\n * return (\n * <Button asChild>\n * <Link href=\"/api/commet/portal\">Manage Billing</Link>\n * </Button>\n * );\n * }\n * ```\n */\nexport const CustomerPortal = ({\n apiKey,\n getCustomerId,\n onError,\n}: CustomerPortalConfig) => {\n const commet = new Commet({\n apiKey,\n });\n\n return async (req: NextRequest) => {\n try {\n // Get customer identifier from request\n const customerId = await getCustomerId(req);\n\n if (!customerId) {\n return NextResponse.json(\n { error: \"Customer not authenticated\" },\n { status: 401 },\n );\n }\n\n // Get portal URL from Commet\n const result = await commet.portal.getUrl({\n customerId,\n });\n\n if (!result.success || !result.data) {\n throw new Error(\n result.error?.message || \"Failed to create portal session\",\n );\n }\n\n // Redirect to customer portal\n return NextResponse.redirect(result.data.portalUrl);\n } catch (error) {\n const errorObj =\n error instanceof Error ? error : new Error(String(error));\n\n // Call custom error handler if provided\n onError?.(errorObj);\n\n // Log error\n console.error(\"[Commet Portal]\", errorObj);\n\n // Return error response\n return NextResponse.json(\n { error: \"Failed to access customer portal\" },\n { status: 500 },\n );\n }\n };\n};\n","import type {\n BillingInterval,\n CreditPack,\n Plan,\n PlanFeature,\n} from \"@commet/node\";\nimport { Commet } from \"@commet/node\";\nimport { type NextRequest, NextResponse } from \"next/server\";\n\nexport interface PricingMarkdownConfig {\n apiKey: string;\n title: string;\n description?: string;\n includeCreditPacks?: boolean;\n billingIntervals?: BillingInterval[];\n cacheMaxAge?: number;\n onError?: (error: Error) => void;\n}\n\nconst INTERVAL_SHORT: Record<BillingInterval, string> = {\n weekly: \"/wk\",\n monthly: \"/mo\",\n quarterly: \"/qtr\",\n yearly: \"/yr\",\n one_time: \"\",\n};\n\nexport const PricingMarkdown = ({\n apiKey,\n title,\n description,\n includeCreditPacks = false,\n billingIntervals,\n cacheMaxAge = 3600,\n onError,\n}: PricingMarkdownConfig) => {\n const commet = new Commet({ apiKey });\n\n return async (_req: NextRequest) => {\n try {\n const plansResult = await commet.plans.list();\n\n if (!plansResult.success || !plansResult.data) {\n throw new Error(plansResult.error?.message ?? \"Failed to fetch plans\");\n }\n\n const publicPlans = plansResult.data.filter((plan) => plan.isPublic);\n\n const creditPacks = includeCreditPacks\n ? await commet.creditPacks\n .list()\n .then((result) =>\n result.success && result.data ? result.data : [],\n )\n : [];\n\n const markdown = generateMarkdown(\n title,\n description,\n publicPlans,\n creditPacks,\n billingIntervals,\n );\n\n return new NextResponse(markdown, {\n status: 200,\n headers: {\n \"Content-Type\": \"text/markdown; charset=utf-8\",\n \"Cache-Control\": `public, s-maxage=${cacheMaxAge}, stale-while-revalidate=${cacheMaxAge * 2}`,\n },\n });\n } catch (error) {\n const errorObj =\n error instanceof Error ? error : new Error(String(error));\n\n onError?.(errorObj);\n console.error(\"[Commet PricingMarkdown]\", errorObj);\n\n return NextResponse.json(\n { error: \"Failed to generate pricing markdown\" },\n { status: 500 },\n );\n }\n };\n};\n\nfunction generateMarkdown(\n title: string,\n description: string | undefined,\n plans: Plan[],\n creditPacks: CreditPack[],\n billingIntervals?: BillingInterval[],\n): string {\n const sections: string[] = [`# ${title}`];\n\n if (description) {\n sections.push(description);\n }\n\n if (plans.length > 0) {\n sections.push(renderPlansTable(plans, billingIntervals));\n\n const featuresSection = renderFeatures(plans);\n if (featuresSection) {\n sections.push(featuresSection);\n }\n }\n\n if (creditPacks.length > 0) {\n sections.push(renderCreditPacks(creditPacks));\n }\n\n return sections.join(\"\\n\\n\");\n}\n\nfunction renderPlansTable(\n plans: Plan[],\n filterIntervals?: BillingInterval[],\n): string {\n const usageFeatures = collectUsageFeatures(plans);\n\n const headerCols = [\"Plan\", \"Price\"];\n for (const { name, unitName } of usageFeatures) {\n headerCols.push(`${name}/${unitName ?? \"unit\"}`);\n headerCols.push(\"Overage\");\n }\n\n const rows = plans.map((plan) => {\n const priceCell = renderPriceCell(plan, filterIntervals);\n const cols = [plan.name, priceCell];\n\n const featuresByCode = new Map(\n plan.features.map((feature) => [feature.code, feature]),\n );\n\n for (const { code } of usageFeatures) {\n const feature = featuresByCode.get(code);\n\n if (!feature) {\n cols.push(\"—\", \"—\");\n continue;\n }\n\n if (feature.unlimited) {\n cols.push(\"Unlimited\", \"—\");\n continue;\n }\n\n const included = feature.includedAmount;\n cols.push(included ? formatNumber(included) : \"—\");\n\n const overagePrice =\n feature.overageEnabled && feature.overageUnitPrice !== undefined\n ? formatRatePrice(feature.overageUnitPrice)\n : \"—\";\n cols.push(overagePrice);\n }\n\n return cols;\n });\n\n const separator = headerCols.map(() => \"---\");\n const lines = [\n `| ${headerCols.join(\" | \")} |`,\n `| ${separator.join(\" | \")} |`,\n ...rows.map((cols) => `| ${cols.join(\" | \")} |`),\n ];\n\n const footnotes: string[] = [];\n\n const trialPlans = plans.filter((plan) =>\n plan.prices.some((price) => price.trialDays > 0),\n );\n for (const plan of trialPlans) {\n const trialPrice = plan.prices.find((price) => price.trialDays > 0)!;\n footnotes.push(\n `*${plan.name} plan includes a ${trialPrice.trialDays}-day free trial.*`,\n );\n }\n\n if (usageFeatures.length > 0) {\n footnotes.push(\n \"The overage rate applies only to usage beyond the included volume.\",\n );\n }\n\n return footnotes.length > 0\n ? `## Plans\\n\\n${lines.join(\"\\n\")}\\n\\n${footnotes.join(\"\\n\\n\")}`\n : `## Plans\\n\\n${lines.join(\"\\n\")}`;\n}\n\nfunction renderPriceCell(\n plan: Plan,\n filterIntervals?: BillingInterval[],\n): string {\n if (plan.isFree) return \"Free\";\n\n const prices = filterIntervals\n ? plan.prices.filter((price) =>\n filterIntervals.includes(price.billingInterval),\n )\n : plan.prices;\n\n if (prices.length === 0) return \"—\";\n\n return prices\n .map((price) => {\n if (price.price === 0) return \"Free\";\n return `${formatSettlementPrice(price.price)}${INTERVAL_SHORT[price.billingInterval]}`;\n })\n .join(\" / \");\n}\n\nfunction renderFeatures(plans: Plan[]): string | null {\n const allBooleanCodes = new Set<string>();\n for (const plan of plans) {\n for (const feature of plan.features) {\n if (feature.type === \"boolean\") {\n allBooleanCodes.add(feature.code);\n }\n }\n }\n\n if (allBooleanCodes.size === 0) return null;\n\n const enabledOnAll = new Set<string>();\n for (const code of allBooleanCodes) {\n const enabledOnEveryPlan = plans.every((plan) => {\n const feature = plan.features.find((f) => f.code === code);\n return feature?.enabled;\n });\n if (enabledOnEveryPlan) {\n enabledOnAll.add(code);\n }\n }\n\n const perPlanLines: string[] = [];\n for (const plan of plans) {\n const uniqueFeatures = plan.features\n .filter(\n (feature) =>\n feature.type === \"boolean\" &&\n feature.enabled &&\n !enabledOnAll.has(feature.code),\n )\n .map((feature) => feature.name);\n\n if (uniqueFeatures.length > 0) {\n perPlanLines.push(`- **${plan.name}**: ${uniqueFeatures.join(\", \")}`);\n }\n }\n\n const commonFeatures = plans[0]?.features\n .filter(\n (feature) => feature.type === \"boolean\" && enabledOnAll.has(feature.code),\n )\n .map((feature) => feature.name);\n\n const parts: string[] = [];\n\n if (perPlanLines.length > 0) {\n parts.push(perPlanLines.join(\"\\n\"));\n }\n\n if (commonFeatures && commonFeatures.length > 0) {\n parts.push(`All plans include: ${commonFeatures.join(\", \")}.`);\n }\n\n return parts.length > 0 ? `## Features\\n\\n${parts.join(\"\\n\\n\")}` : null;\n}\n\nfunction renderCreditPacks(packs: CreditPack[]): string {\n const lines = [\n \"| Pack | Credits | Price |\",\n \"| --- | --- | --- |\",\n ...packs.map(\n (pack) =>\n `| ${pack.name} | ${formatNumber(pack.credits)} credits | ${formatSettlementPrice(pack.price)} |`,\n ),\n ];\n\n return `## Credit Packs\\n\\n${lines.join(\"\\n\")}`;\n}\n\ninterface UsageFeatureColumn {\n code: string;\n name: string;\n unitName: string | null;\n}\n\nfunction collectUsageFeatures(plans: Plan[]): UsageFeatureColumn[] {\n const seen = new Map<string, UsageFeatureColumn>();\n for (const plan of plans) {\n for (const feature of plan.features) {\n if (\n (feature.type === \"usage\" || feature.type === \"seats\") &&\n !seen.has(feature.code) &&\n hasUsageData(feature)\n ) {\n seen.set(feature.code, {\n code: feature.code,\n name: feature.name,\n unitName: feature.unitName,\n });\n }\n }\n }\n return Array.from(seen.values());\n}\n\nfunction hasUsageData(feature: PlanFeature): boolean {\n return (\n feature.unlimited === true ||\n (feature.includedAmount !== undefined && feature.includedAmount > 0) ||\n (feature.overageEnabled === true && feature.overageUnitPrice !== undefined)\n );\n}\n\nfunction formatSettlementPrice(cents: number): string {\n if (cents === 0) return \"Free\";\n const dollars = cents / 100;\n const [whole, decimal] = dollars.toFixed(2).split(\".\");\n return `$${Number(whole).toLocaleString(\"en-US\")}.${decimal}`;\n}\n\nfunction formatRatePrice(rate: number): string {\n const dollars = rate / 10000;\n\n if (dollars === Math.floor(dollars)) {\n return `$${dollars.toFixed(2)}`;\n }\n\n const formatted = dollars.toFixed(4).replace(/0+$/, \"\");\n const decimalPlaces = formatted.split(\".\")[1]?.length ?? 0;\n if (decimalPlaces < 2) {\n return `$${dollars.toFixed(2)}`;\n }\n\n return `$${formatted}`;\n}\n\nfunction formatNumber(n: number): string {\n return n.toLocaleString(\"en-US\");\n}\n","import type { WebhookPayload } from \"@commet/node\";\nimport { Webhooks as CommetWebhooks } from \"@commet/node\";\nimport { type NextRequest, NextResponse } from \"next/server\";\nimport type { WebhooksConfig } from \"./types\";\n\n/**\n * Create a Next.js webhook handler for Commet events\n *\n * Automatically verifies signatures, routes events to handlers, and returns proper responses.\n *\n * @param config - Webhook configuration with secret and event handlers\n * @returns Next.js route handler function\n *\n * @example\n * ```typescript\n * // app/api/webhooks/commet/route.ts\n * import { Webhooks } from \"@commet/next\";\n *\n * export const POST = Webhooks({\n * webhookSecret: process.env.COMMET_WEBHOOK_SECRET!,\n * onSubscriptionActivated: async (payload) => {\n * // Grant access to user\n * },\n * onSubscriptionCanceled: async (payload) => {\n * // Revoke access from user\n * },\n * });\n * ```\n */\nexport const Webhooks = (config: WebhooksConfig) => {\n const {\n webhookSecret,\n onSubscriptionActivated,\n onSubscriptionCanceled,\n onSubscriptionCreated,\n onSubscriptionUpdated,\n onSubscriptionPlanChanged,\n onPaymentReceived,\n onPaymentFailed,\n onInvoiceCreated,\n onPayload,\n onError,\n } = config;\n\n // Create webhook verifier instance\n const webhooks = new CommetWebhooks();\n\n return async (request: NextRequest) => {\n try {\n // 1. Read raw request body\n const rawBody = await request.text();\n\n // 2. Extract signature from headers\n const signature = request.headers.get(\"x-commet-signature\");\n\n // 3. Verify signature\n const isValid = webhooks.verify({\n payload: rawBody,\n signature,\n secret: webhookSecret,\n });\n\n if (!isValid) {\n console.error(\"[Commet Webhook] Invalid signature\");\n return NextResponse.json(\n { received: false, error: \"Invalid signature\" },\n { status: 403 },\n );\n }\n\n // 4. Parse payload\n let payload: WebhookPayload;\n try {\n payload = JSON.parse(rawBody) as WebhookPayload;\n } catch (parseError) {\n console.error(\"[Commet Webhook] Failed to parse payload:\", parseError);\n if (onError) {\n await onError(\n parseError instanceof Error\n ? parseError\n : new Error(\"Failed to parse webhook payload\"),\n rawBody,\n );\n }\n return NextResponse.json(\n { received: false, error: \"Invalid payload\" },\n { status: 400 },\n );\n }\n\n // 5. Collect promises for parallel execution\n const promises: Promise<void>[] = [];\n\n // Call catch-all handler if provided\n if (onPayload) {\n promises.push(onPayload(payload));\n }\n\n // 6. Route to specific event handler\n switch (payload.event) {\n case \"subscription.activated\":\n if (onSubscriptionActivated) {\n promises.push(onSubscriptionActivated(payload));\n }\n break;\n\n case \"subscription.canceled\":\n if (onSubscriptionCanceled) {\n promises.push(onSubscriptionCanceled(payload));\n }\n break;\n\n case \"subscription.created\":\n if (onSubscriptionCreated) {\n promises.push(onSubscriptionCreated(payload));\n }\n break;\n\n case \"subscription.updated\":\n if (onSubscriptionUpdated) {\n promises.push(onSubscriptionUpdated(payload));\n }\n break;\n\n case \"subscription.plan_changed\":\n if (onSubscriptionPlanChanged) {\n promises.push(onSubscriptionPlanChanged(payload));\n }\n break;\n\n case \"payment.received\":\n if (onPaymentReceived) {\n promises.push(onPaymentReceived(payload));\n }\n break;\n\n case \"payment.failed\":\n if (onPaymentFailed) {\n promises.push(onPaymentFailed(payload));\n }\n break;\n\n case \"invoice.created\":\n if (onInvoiceCreated) {\n promises.push(onInvoiceCreated(payload));\n }\n break;\n\n default:\n console.log(`[Commet Webhook] Unhandled event: ${payload.event}`);\n }\n\n // 7. Execute all handlers in parallel\n try {\n await Promise.all(promises);\n } catch (handlerError) {\n console.error(\n \"[Commet Webhook] Handler error:\",\n handlerError instanceof Error ? handlerError.message : handlerError,\n );\n if (onError) {\n await onError(\n handlerError instanceof Error\n ? handlerError\n : new Error(\"Handler execution failed\"),\n payload,\n );\n }\n // Still return 200 to prevent retries for handler errors\n return NextResponse.json(\n { received: true, warning: \"Handler failed\" },\n { status: 200 },\n );\n }\n\n // 8. Success response\n return NextResponse.json({ received: true }, { status: 200 });\n } catch (error) {\n console.error(\"[Commet Webhook] Unexpected error:\", error);\n if (onError) {\n try {\n await onError(\n error instanceof Error ? error : new Error(\"Unexpected error\"),\n undefined,\n );\n } catch (errorHandlerError) {\n console.error(\n \"[Commet Webhook] Error handler failed:\",\n errorHandlerError,\n );\n }\n }\n return NextResponse.json(\n { received: false, error: \"Internal error\" },\n { status: 500 },\n );\n }\n };\n};\n"],"mappings":"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","names":["Commet","NextResponse","NextResponse"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/portal.ts","../src/pricing-markdown.ts","../src/webhooks.ts"],"sourcesContent":["/**\n * @commet/next - Next.js integration for Commet\n *\n * @example\n * Webhooks\n * ```typescript\n * import { Webhooks } from \"@commet/next\";\n *\n * export const POST = Webhooks({\n * webhookSecret: process.env.COMMET_WEBHOOK_SECRET!,\n * onSubscriptionActivated: async (payload) => {\n * // Handle activation\n * },\n * });\n * ```\n *\n * @example\n * Customer Portal\n * ```typescript\n * import { CustomerPortal } from \"@commet/next\";\n *\n * export const GET = CustomerPortal({\n * apiKey: process.env.COMMET_API_KEY!,\n * getCustomerId: async (req) => {\n * const session = await auth.api.getSession({ headers: req.headers });\n * return session?.user.id;\n * },\n * });\n * ```\n *\n * @packageDocumentation\n */\n\nimport { registerIntegration } from \"@commet/node\";\n\ndeclare const __PKG_VERSION__: string;\nregisterIntegration(\"@commet/next\", __PKG_VERSION__);\n\nexport type { CustomerPortalConfig } from \"./portal\";\nexport { CustomerPortal } from \"./portal\";\nexport type { PricingMarkdownConfig } from \"./pricing-markdown\";\nexport { PricingMarkdown } from \"./pricing-markdown\";\nexport type {\n WebhookData,\n WebhookEvent,\n WebhookPayload,\n WebhooksConfig,\n} from \"./types\";\nexport { Webhooks } from \"./webhooks\";\n","import { Commet } from \"@commet/node\";\nimport { type NextRequest, NextResponse } from \"next/server\";\n\nexport interface CustomerPortalConfig {\n apiKey: string;\n getCustomerId: (req: NextRequest) => Promise<string | null>;\n onError?: (error: Error) => void;\n}\n\n/**\n * Creates Next.js route handler for Customer Portal access\n *\n * @example\n * ```typescript\n * // app/api/commet/portal/route.ts\n * import { CustomerPortal } from \"@commet/next\";\n * import { auth } from \"@/lib/auth\";\n *\n * export const GET = CustomerPortal({\n * apiKey: process.env.COMMET_API_KEY!,\n * getCustomerId: async (req) => {\n * const session = await auth.api.getSession({ headers: req.headers });\n * return session?.user.id ?? null;\n * },\n * });\n * ```\n *\n * @example\n * ```tsx\n * // Use in component\n * export function BillingButton() {\n * return (\n * <Button asChild>\n * <Link href=\"/api/commet/portal\">Manage Billing</Link>\n * </Button>\n * );\n * }\n * ```\n */\nexport const CustomerPortal = ({\n apiKey,\n getCustomerId,\n onError,\n}: CustomerPortalConfig) => {\n const commet = new Commet({\n apiKey,\n });\n\n return async (req: NextRequest) => {\n try {\n // Get customer identifier from request\n const customerId = await getCustomerId(req);\n\n if (!customerId) {\n return NextResponse.json(\n { error: \"Customer not authenticated\" },\n { status: 401 },\n );\n }\n\n // Get portal URL from Commet\n const result = await commet.portal.getUrl({\n customerId,\n });\n\n if (!result.success || !result.data) {\n throw new Error(\n result.error?.message || \"Failed to create portal session\",\n );\n }\n\n // Redirect to customer portal\n return NextResponse.redirect(result.data.portalUrl);\n } catch (error) {\n const errorObj =\n error instanceof Error ? error : new Error(String(error));\n\n // Call custom error handler if provided\n onError?.(errorObj);\n\n // Log error\n console.error(\"[Commet Portal]\", errorObj);\n\n // Return error response\n return NextResponse.json(\n { error: \"Failed to access customer portal\" },\n { status: 500 },\n );\n }\n };\n};\n","import type { BillingInterval, CreditPack, Plan } from \"@commet/node\";\nimport { Commet } from \"@commet/node\";\nimport { type NextRequest, NextResponse } from \"next/server\";\n\ntype PlanFeature = NonNullable<Plan[\"features\"]>[number];\n\nexport interface PricingMarkdownConfig {\n apiKey: string;\n title: string;\n description?: string;\n includeCreditPacks?: boolean;\n billingIntervals?: BillingInterval[];\n cacheMaxAge?: number;\n onError?: (error: Error) => void;\n}\n\nconst INTERVAL_SHORT: Record<BillingInterval, string> = {\n weekly: \"/wk\",\n monthly: \"/mo\",\n quarterly: \"/qtr\",\n yearly: \"/yr\",\n one_time: \"\",\n};\n\nexport const PricingMarkdown = ({\n apiKey,\n title,\n description,\n includeCreditPacks = false,\n billingIntervals,\n cacheMaxAge = 3600,\n onError,\n}: PricingMarkdownConfig) => {\n const commet = new Commet({ apiKey });\n\n return async (_req: NextRequest) => {\n try {\n const plansResult = await commet.plans.list();\n\n if (!plansResult.success || !plansResult.data) {\n throw new Error(plansResult.error?.message ?? \"Failed to fetch plans\");\n }\n\n const publicPlans = plansResult.data.filter((plan) => plan.isPublic);\n\n const creditPacks = includeCreditPacks\n ? await commet.creditPacks\n .list()\n .then((result) =>\n result.success && result.data ? result.data : [],\n )\n : [];\n\n const markdown = generateMarkdown(\n title,\n description,\n publicPlans,\n creditPacks,\n billingIntervals,\n );\n\n return new NextResponse(markdown, {\n status: 200,\n headers: {\n \"Content-Type\": \"text/markdown; charset=utf-8\",\n \"Cache-Control\": `public, s-maxage=${cacheMaxAge}, stale-while-revalidate=${cacheMaxAge * 2}`,\n },\n });\n } catch (error) {\n const errorObj =\n error instanceof Error ? error : new Error(String(error));\n\n onError?.(errorObj);\n console.error(\"[Commet PricingMarkdown]\", errorObj);\n\n return NextResponse.json(\n { error: \"Failed to generate pricing markdown\" },\n { status: 500 },\n );\n }\n };\n};\n\nfunction generateMarkdown(\n title: string,\n description: string | undefined,\n plans: Plan[],\n creditPacks: CreditPack[],\n billingIntervals?: BillingInterval[],\n): string {\n const sections: string[] = [`# ${title}`];\n\n if (description) {\n sections.push(description);\n }\n\n if (plans.length > 0) {\n sections.push(renderPlansTable(plans, billingIntervals));\n\n const featuresSection = renderFeatures(plans);\n if (featuresSection) {\n sections.push(featuresSection);\n }\n }\n\n if (creditPacks.length > 0) {\n sections.push(renderCreditPacks(creditPacks));\n }\n\n return sections.join(\"\\n\\n\");\n}\n\nfunction renderPlansTable(\n plans: Plan[],\n filterIntervals?: BillingInterval[],\n): string {\n const usageFeatures = collectUsageFeatures(plans);\n\n const headerCols = [\"Plan\", \"Price\"];\n for (const { name, unitName } of usageFeatures) {\n headerCols.push(`${name}/${unitName ?? \"unit\"}`);\n headerCols.push(\"Overage\");\n }\n\n const rows = plans.map((plan) => {\n const priceCell = renderPriceCell(plan, filterIntervals);\n const cols = [plan.name, priceCell];\n\n const featuresByCode = new Map(\n (plan.features ?? []).map((feature) => [feature.code, feature]),\n );\n\n for (const { code } of usageFeatures) {\n const feature = featuresByCode.get(code);\n\n if (!feature) {\n cols.push(\"—\", \"—\");\n continue;\n }\n\n if (feature.unlimited) {\n cols.push(\"Unlimited\", \"—\");\n continue;\n }\n\n const included = feature.includedAmount;\n cols.push(included ? formatNumber(included) : \"—\");\n\n const overagePrice =\n feature.overage?.enabled && feature.overage.unitPrice !== null\n ? formatRatePrice(feature.overage.unitPrice)\n : \"—\";\n cols.push(overagePrice);\n }\n\n return cols;\n });\n\n const separator = headerCols.map(() => \"---\");\n const lines = [\n `| ${headerCols.join(\" | \")} |`,\n `| ${separator.join(\" | \")} |`,\n ...rows.map((cols) => `| ${cols.join(\" | \")} |`),\n ];\n\n const footnotes: string[] = [];\n\n const trialPlans = plans.filter((plan) =>\n (plan.prices ?? []).some((price) => price.trialDays > 0),\n );\n for (const plan of trialPlans) {\n const trialPrice = (plan.prices ?? []).find((price) => price.trialDays > 0)!;\n footnotes.push(\n `*${plan.name} plan includes a ${trialPrice.trialDays}-day free trial.*`,\n );\n }\n\n if (usageFeatures.length > 0) {\n footnotes.push(\n \"The overage rate applies only to usage beyond the included volume.\",\n );\n }\n\n return footnotes.length > 0\n ? `## Plans\\n\\n${lines.join(\"\\n\")}\\n\\n${footnotes.join(\"\\n\\n\")}`\n : `## Plans\\n\\n${lines.join(\"\\n\")}`;\n}\n\nfunction renderPriceCell(\n plan: Plan,\n filterIntervals?: BillingInterval[],\n): string {\n if (plan.isFree) return \"Free\";\n\n const prices = filterIntervals\n ? (plan.prices ?? []).filter((price) =>\n filterIntervals.includes(price.billingInterval),\n )\n : (plan.prices ?? []);\n\n if (prices.length === 0) return \"—\";\n\n return prices\n .map((price) => {\n if (price.price === 0) return \"Free\";\n return `${formatSettlementPrice(price.price)}${INTERVAL_SHORT[price.billingInterval]}`;\n })\n .join(\" / \");\n}\n\nfunction renderFeatures(plans: Plan[]): string | null {\n const allBooleanCodes = new Set<string>();\n for (const plan of plans) {\n for (const feature of plan.features ?? []) {\n if (feature.type === \"boolean\") {\n allBooleanCodes.add(feature.code);\n }\n }\n }\n\n if (allBooleanCodes.size === 0) return null;\n\n const enabledOnAll = new Set<string>();\n for (const code of allBooleanCodes) {\n const enabledOnEveryPlan = plans.every((plan) => {\n const feature = (plan.features ?? []).find((f) => f.code === code);\n return feature?.enabled;\n });\n if (enabledOnEveryPlan) {\n enabledOnAll.add(code);\n }\n }\n\n const perPlanLines: string[] = [];\n for (const plan of plans) {\n const uniqueFeatures = (plan.features ?? [])\n .filter(\n (feature) =>\n feature.type === \"boolean\" &&\n feature.enabled &&\n !enabledOnAll.has(feature.code),\n )\n .map((feature) => feature.name);\n\n if (uniqueFeatures.length > 0) {\n perPlanLines.push(`- **${plan.name}**: ${uniqueFeatures.join(\", \")}`);\n }\n }\n\n const commonFeatures = (plans[0]?.features ?? [])\n .filter(\n (feature) => feature.type === \"boolean\" && enabledOnAll.has(feature.code),\n )\n .map((feature) => feature.name);\n\n const parts: string[] = [];\n\n if (perPlanLines.length > 0) {\n parts.push(perPlanLines.join(\"\\n\"));\n }\n\n if (commonFeatures && commonFeatures.length > 0) {\n parts.push(`All plans include: ${commonFeatures.join(\", \")}.`);\n }\n\n return parts.length > 0 ? `## Features\\n\\n${parts.join(\"\\n\\n\")}` : null;\n}\n\nfunction renderCreditPacks(packs: CreditPack[]): string {\n const lines = [\n \"| Pack | Credits | Price |\",\n \"| --- | --- | --- |\",\n ...packs.map(\n (pack) =>\n `| ${pack.name} | ${formatNumber(pack.credits)} credits | ${formatSettlementPrice(pack.price)} |`,\n ),\n ];\n\n return `## Credit Packs\\n\\n${lines.join(\"\\n\")}`;\n}\n\ninterface UsageFeatureColumn {\n code: string;\n name: string;\n unitName: string | null;\n}\n\nfunction collectUsageFeatures(plans: Plan[]): UsageFeatureColumn[] {\n const seen = new Map<string, UsageFeatureColumn>();\n for (const plan of plans) {\n for (const feature of plan.features ?? []) {\n if (\n (feature.type === \"usage\" || feature.type === \"seats\") &&\n !seen.has(feature.code) &&\n hasUsageData(feature)\n ) {\n seen.set(feature.code, {\n code: feature.code,\n name: feature.name,\n unitName: feature.unitName,\n });\n }\n }\n }\n return Array.from(seen.values());\n}\n\nfunction hasUsageData(feature: PlanFeature): boolean {\n return (\n feature.unlimited === true ||\n (feature.includedAmount !== null && feature.includedAmount > 0) ||\n (feature.overage?.enabled === true && feature.overage.unitPrice !== null)\n );\n}\n\nfunction formatSettlementPrice(cents: number): string {\n if (cents === 0) return \"Free\";\n const dollars = cents / 100;\n const [whole, decimal] = dollars.toFixed(2).split(\".\");\n return `$${Number(whole).toLocaleString(\"en-US\")}.${decimal}`;\n}\n\nfunction formatRatePrice(rate: number): string {\n const dollars = rate / 10000;\n\n if (dollars === Math.floor(dollars)) {\n return `$${dollars.toFixed(2)}`;\n }\n\n const formatted = dollars.toFixed(4).replace(/0+$/, \"\");\n const decimalPlaces = formatted.split(\".\")[1]?.length ?? 0;\n if (decimalPlaces < 2) {\n return `$${dollars.toFixed(2)}`;\n }\n\n return `$${formatted}`;\n}\n\nfunction formatNumber(n: number): string {\n return n.toLocaleString(\"en-US\");\n}\n","import type { WebhookPayload } from \"@commet/node\";\nimport { Webhooks as CommetWebhooks } from \"@commet/node\";\nimport { type NextRequest, NextResponse } from \"next/server\";\nimport type { WebhooksConfig } from \"./types\";\n\n/**\n * Create a Next.js webhook handler for Commet events\n *\n * Automatically verifies signatures, routes events to handlers, and returns proper responses.\n *\n * @param config - Webhook configuration with secret and event handlers\n * @returns Next.js route handler function\n *\n * @example\n * ```typescript\n * // app/api/webhooks/commet/route.ts\n * import { Webhooks } from \"@commet/next\";\n *\n * export const POST = Webhooks({\n * webhookSecret: process.env.COMMET_WEBHOOK_SECRET!,\n * onSubscriptionActivated: async (payload) => {\n * // Grant access to user\n * },\n * onSubscriptionCanceled: async (payload) => {\n * // Revoke access from user\n * },\n * });\n * ```\n */\nexport const Webhooks = (config: WebhooksConfig) => {\n const {\n webhookSecret,\n onSubscriptionActivated,\n onSubscriptionCanceled,\n onSubscriptionCreated,\n onSubscriptionUpdated,\n onSubscriptionPlanChanged,\n onPaymentReceived,\n onPaymentFailed,\n onInvoiceCreated,\n onPayload,\n onError,\n } = config;\n\n // Create webhook verifier instance\n const webhooks = new CommetWebhooks();\n\n return async (request: NextRequest) => {\n try {\n // 1. Read raw request body\n const rawBody = await request.text();\n\n // 2. Extract signature from headers\n const signature = request.headers.get(\"x-commet-signature\");\n\n // 3. Verify signature\n const isValid = webhooks.verify({\n payload: rawBody,\n signature,\n secret: webhookSecret,\n });\n\n if (!isValid) {\n console.error(\"[Commet Webhook] Invalid signature\");\n return NextResponse.json(\n { received: false, error: \"Invalid signature\" },\n { status: 403 },\n );\n }\n\n // 4. Parse payload\n let payload: WebhookPayload;\n try {\n payload = JSON.parse(rawBody) as WebhookPayload;\n } catch (parseError) {\n console.error(\"[Commet Webhook] Failed to parse payload:\", parseError);\n if (onError) {\n await onError(\n parseError instanceof Error\n ? parseError\n : new Error(\"Failed to parse webhook payload\"),\n rawBody,\n );\n }\n return NextResponse.json(\n { received: false, error: \"Invalid payload\" },\n { status: 400 },\n );\n }\n\n // 5. Collect promises for parallel execution\n const promises: Promise<void>[] = [];\n\n // Call catch-all handler if provided\n if (onPayload) {\n promises.push(onPayload(payload));\n }\n\n // 6. Route to specific event handler\n switch (payload.event) {\n case \"subscription.activated\":\n if (onSubscriptionActivated) {\n promises.push(onSubscriptionActivated(payload));\n }\n break;\n\n case \"subscription.canceled\":\n if (onSubscriptionCanceled) {\n promises.push(onSubscriptionCanceled(payload));\n }\n break;\n\n case \"subscription.created\":\n if (onSubscriptionCreated) {\n promises.push(onSubscriptionCreated(payload));\n }\n break;\n\n case \"subscription.updated\":\n if (onSubscriptionUpdated) {\n promises.push(onSubscriptionUpdated(payload));\n }\n break;\n\n case \"subscription.plan_changed\":\n if (onSubscriptionPlanChanged) {\n promises.push(onSubscriptionPlanChanged(payload));\n }\n break;\n\n case \"payment.received\":\n if (onPaymentReceived) {\n promises.push(onPaymentReceived(payload));\n }\n break;\n\n case \"payment.failed\":\n if (onPaymentFailed) {\n promises.push(onPaymentFailed(payload));\n }\n break;\n\n case \"invoice.created\":\n if (onInvoiceCreated) {\n promises.push(onInvoiceCreated(payload));\n }\n break;\n\n default:\n console.log(`[Commet Webhook] Unhandled event: ${payload.event}`);\n }\n\n // 7. Execute all handlers in parallel\n try {\n await Promise.all(promises);\n } catch (handlerError) {\n console.error(\n \"[Commet Webhook] Handler error:\",\n handlerError instanceof Error ? handlerError.message : handlerError,\n );\n if (onError) {\n await onError(\n handlerError instanceof Error\n ? handlerError\n : new Error(\"Handler execution failed\"),\n payload,\n );\n }\n // Still return 200 to prevent retries for handler errors\n return NextResponse.json(\n { received: true, warning: \"Handler failed\" },\n { status: 200 },\n );\n }\n\n // 8. Success response\n return NextResponse.json({ received: true }, { status: 200 });\n } catch (error) {\n console.error(\"[Commet Webhook] Unexpected error:\", error);\n if (onError) {\n try {\n await onError(\n error instanceof Error ? error : new Error(\"Unexpected error\"),\n undefined,\n );\n } catch (errorHandlerError) {\n console.error(\n \"[Commet Webhook] Error handler failed:\",\n errorHandlerError,\n );\n }\n }\n return NextResponse.json(\n { received: false, error: \"Internal error\" },\n { status: 500 },\n );\n }\n };\n};\n"],"mappings":"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","names":["Commet","NextResponse","NextResponse"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@commet/next",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "Next.js integration for Commet billing platform",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"author": "Commet Team",
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@commet/node": "
|
|
29
|
+
"@commet/node": "6.0.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "24.12.4",
|