@commet/next 1.0.8 → 1.0.10
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 +4 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -181,7 +181,9 @@ function renderPlansTable(plans, filterIntervals) {
|
|
|
181
181
|
(plan) => (plan.prices ?? []).some((price) => price.trialDays > 0)
|
|
182
182
|
);
|
|
183
183
|
for (const plan of trialPlans) {
|
|
184
|
-
const trialPrice = (plan.prices ?? []).find(
|
|
184
|
+
const trialPrice = (plan.prices ?? []).find(
|
|
185
|
+
(price) => price.trialDays > 0
|
|
186
|
+
);
|
|
185
187
|
footnotes.push(
|
|
186
188
|
`*${plan.name} plan includes a ${trialPrice.trialDays}-day free trial.*`
|
|
187
189
|
);
|
|
@@ -446,7 +448,7 @@ var Webhooks = (config) => {
|
|
|
446
448
|
};
|
|
447
449
|
|
|
448
450
|
// src/index.ts
|
|
449
|
-
(0, import_node4.registerIntegration)("@commet/next", "1.0.
|
|
451
|
+
(0, import_node4.registerIntegration)("@commet/next", "1.0.10");
|
|
450
452
|
// Annotate the CommonJS export names for ESM import in node:
|
|
451
453
|
0 && (module.exports = {
|
|
452
454
|
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 { 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"]}
|
|
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(\n (price) => price.trialDays > 0,\n )!;\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
|
@@ -155,7 +155,9 @@ function renderPlansTable(plans, filterIntervals) {
|
|
|
155
155
|
(plan) => (plan.prices ?? []).some((price) => price.trialDays > 0)
|
|
156
156
|
);
|
|
157
157
|
for (const plan of trialPlans) {
|
|
158
|
-
const trialPrice = (plan.prices ?? []).find(
|
|
158
|
+
const trialPrice = (plan.prices ?? []).find(
|
|
159
|
+
(price) => price.trialDays > 0
|
|
160
|
+
);
|
|
159
161
|
footnotes.push(
|
|
160
162
|
`*${plan.name} plan includes a ${trialPrice.trialDays}-day free trial.*`
|
|
161
163
|
);
|
|
@@ -420,7 +422,7 @@ var Webhooks = (config) => {
|
|
|
420
422
|
};
|
|
421
423
|
|
|
422
424
|
// src/index.ts
|
|
423
|
-
registerIntegration("@commet/next", "1.0.
|
|
425
|
+
registerIntegration("@commet/next", "1.0.10");
|
|
424
426
|
export {
|
|
425
427
|
CustomerPortal,
|
|
426
428
|
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 { 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"]}
|
|
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(\n (price) => price.trialDays > 0,\n )!;\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.10",
|
|
4
4
|
"description": "Next.js integration for Commet billing platform",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -26,14 +26,14 @@
|
|
|
26
26
|
"author": "Commet Team",
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@commet/node": "7.
|
|
29
|
+
"@commet/node": "7.2.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@types/node": "24.
|
|
33
|
-
"next": "16.2.
|
|
32
|
+
"@types/node": "24.13.1",
|
|
33
|
+
"next": "16.2.9",
|
|
34
34
|
"tsup": "8.5.1",
|
|
35
35
|
"typescript": "5.9.3",
|
|
36
|
-
"vitest": "4.1.
|
|
36
|
+
"vitest": "4.1.8"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"next": ">=16.0.0"
|