@commet/next 0.2.14 → 0.2.15

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 CHANGED
@@ -167,7 +167,7 @@ var CustomerPortal = ({
167
167
  externalId: customerId
168
168
  });
169
169
  if (!result.success || !result.data) {
170
- throw new Error(result.error || "Failed to create portal session");
170
+ throw new Error(result.message || "Failed to create portal session");
171
171
  }
172
172
  return import_server2.NextResponse.redirect(result.data.portalUrl);
173
173
  } catch (error) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/webhooks.ts","../src/portal.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\nexport { Webhooks } from \"./webhooks\";\nexport type {\n WebhooksConfig,\n WebhookPayload,\n WebhookData,\n WebhookEvent,\n} from \"./types\";\n\nexport { CustomerPortal } from \"./portal\";\nexport type { CustomerPortalConfig } from \"./portal\";\n","import { Webhooks as CommetWebhooks } from \"@commet/node\";\nimport type { WebhookPayload } 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 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 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","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 environment?: \"sandbox\" | \"production\";\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 environment = \"production\",\n getCustomerId,\n onError,\n}: CustomerPortalConfig) => {\n const commet = new Commet({\n apiKey,\n environment,\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 externalId: customerId,\n });\n\n if (!result.success || !result.data) {\n throw new Error(result.error || \"Failed to create portal session\");\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"],"mappings":"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","names":["CommetWebhooks","import_node","import_server"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/webhooks.ts","../src/portal.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\nexport { Webhooks } from \"./webhooks\";\nexport type {\n WebhooksConfig,\n WebhookPayload,\n WebhookData,\n WebhookEvent,\n} from \"./types\";\n\nexport { CustomerPortal } from \"./portal\";\nexport type { CustomerPortalConfig } from \"./portal\";\n","import { Webhooks as CommetWebhooks } from \"@commet/node\";\nimport type { WebhookPayload } 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 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 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","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 environment?: \"sandbox\" | \"production\";\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 environment = \"production\",\n getCustomerId,\n onError,\n}: CustomerPortalConfig) => {\n const commet = new Commet({\n apiKey,\n environment,\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 externalId: customerId,\n });\n\n if (!result.success || !result.data) {\n throw new Error(result.message || \"Failed to create portal session\");\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"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAA2C;AAE3C,oBAA+C;AA2BxC,IAAM,WAAW,CAAC,WAA2B;AAClD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAGJ,QAAM,WAAW,IAAI,YAAAA,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,2BAAa;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,2BAAa;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;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,2BAAa;AAAA,UAClB,EAAE,UAAU,MAAM,SAAS,iBAAiB;AAAA,UAC5C,EAAE,QAAQ,IAAI;AAAA,QAChB;AAAA,MACF;AAGA,aAAO,2BAAa,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,2BAAa;AAAA,QAClB,EAAE,UAAU,OAAO,OAAO,iBAAiB;AAAA,QAC3C,EAAE,QAAQ,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACF;;;AC1KA,IAAAC,eAAuB;AACvB,IAAAC,iBAA+C;AAuCxC,IAAM,iBAAiB,CAAC;AAAA,EAC7B;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AACF,MAA4B;AAC1B,QAAM,SAAS,IAAI,oBAAO;AAAA,IACxB;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,OAAO,QAAqB;AACjC,QAAI;AAEF,YAAM,aAAa,MAAM,cAAc,GAAG;AAE1C,UAAI,CAAC,YAAY;AACf,eAAO,4BAAa;AAAA,UAClB,EAAE,OAAO,6BAA6B;AAAA,UACtC,EAAE,QAAQ,IAAI;AAAA,QAChB;AAAA,MACF;AAGA,YAAM,SAAS,MAAM,OAAO,OAAO,OAAO;AAAA,QACxC,YAAY;AAAA,MACd,CAAC;AAED,UAAI,CAAC,OAAO,WAAW,CAAC,OAAO,MAAM;AACnC,cAAM,IAAI,MAAM,OAAO,WAAW,iCAAiC;AAAA,MACrE;AAGA,aAAO,4BAAa,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,4BAAa;AAAA,QAClB,EAAE,OAAO,mCAAmC;AAAA,QAC5C,EAAE,QAAQ,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACF;","names":["CommetWebhooks","import_node","import_server"]}
package/dist/index.mjs CHANGED
@@ -140,7 +140,7 @@ var CustomerPortal = ({
140
140
  externalId: customerId
141
141
  });
142
142
  if (!result.success || !result.data) {
143
- throw new Error(result.error || "Failed to create portal session");
143
+ throw new Error(result.message || "Failed to create portal session");
144
144
  }
145
145
  return NextResponse2.redirect(result.data.portalUrl);
146
146
  } catch (error) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/webhooks.ts","../src/portal.ts"],"sourcesContent":["import { Webhooks as CommetWebhooks } from \"@commet/node\";\nimport type { WebhookPayload } 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 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 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","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 environment?: \"sandbox\" | \"production\";\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 environment = \"production\",\n getCustomerId,\n onError,\n}: CustomerPortalConfig) => {\n const commet = new Commet({\n apiKey,\n environment,\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 externalId: customerId,\n });\n\n if (!result.success || !result.data) {\n throw new Error(result.error || \"Failed to create portal session\");\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"],"mappings":"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","names":["NextResponse"]}
1
+ {"version":3,"sources":["../src/webhooks.ts","../src/portal.ts"],"sourcesContent":["import { Webhooks as CommetWebhooks } from \"@commet/node\";\nimport type { WebhookPayload } 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 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 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","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 environment?: \"sandbox\" | \"production\";\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 environment = \"production\",\n getCustomerId,\n onError,\n}: CustomerPortalConfig) => {\n const commet = new Commet({\n apiKey,\n environment,\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 externalId: customerId,\n });\n\n if (!result.success || !result.data) {\n throw new Error(result.message || \"Failed to create portal session\");\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"],"mappings":"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","names":["NextResponse"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commet/next",
3
- "version": "0.2.14",
3
+ "version": "0.2.15",
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": "1.6.0"
29
+ "@commet/node": "1.6.1"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "24.10.1",