@commet/node 1.7.0 → 1.7.1
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/README.md +34 -15
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,13 +13,26 @@
|
|
|
13
13
|
|
|
14
14
|
<br/>
|
|
15
15
|
|
|
16
|
+
[Commet](https://commet.co) is an all-in-one billing and payments platform for SaaS and AI products. `@commet/node` is the core SDK — use it to manage customers, track usage, handle subscriptions, and more from your server.
|
|
17
|
+
|
|
16
18
|
## Installation
|
|
17
19
|
|
|
18
20
|
```bash
|
|
19
21
|
npm install @commet/node
|
|
20
22
|
```
|
|
21
23
|
|
|
22
|
-
##
|
|
24
|
+
## Getting Started
|
|
25
|
+
|
|
26
|
+
### 1. Create a Commet account
|
|
27
|
+
|
|
28
|
+
Sign up at [commet.co](https://commet.co) and create an organization. Go to **Settings → API Keys** to get your key.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# .env
|
|
32
|
+
COMMET_API_KEY=ck_...
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 2. Initialize the SDK
|
|
23
36
|
|
|
24
37
|
```typescript
|
|
25
38
|
import { Commet } from '@commet/node';
|
|
@@ -30,9 +43,22 @@ const commet = new Commet({
|
|
|
30
43
|
});
|
|
31
44
|
```
|
|
32
45
|
|
|
33
|
-
|
|
46
|
+
### 3. Start using it
|
|
34
47
|
|
|
35
48
|
```typescript
|
|
49
|
+
// Create a customer
|
|
50
|
+
const customer = await commet.customers.create({
|
|
51
|
+
fullName: 'Acme Corp',
|
|
52
|
+
billingEmail: 'billing@acme.com'
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Subscribe them to a plan
|
|
56
|
+
await commet.subscriptions.create({
|
|
57
|
+
externalId: 'user_123',
|
|
58
|
+
planCode: 'pro', // autocomplete works after `commet pull`
|
|
59
|
+
billingInterval: 'yearly',
|
|
60
|
+
});
|
|
61
|
+
|
|
36
62
|
// Track usage events
|
|
37
63
|
await commet.usage.create({
|
|
38
64
|
feature: 'api_call',
|
|
@@ -47,22 +73,15 @@ await commet.seats.add({
|
|
|
47
73
|
count: 5
|
|
48
74
|
});
|
|
49
75
|
|
|
50
|
-
//
|
|
51
|
-
await commet.
|
|
76
|
+
// Check feature access
|
|
77
|
+
const feature = await commet.features.check({
|
|
52
78
|
externalId: 'user_123',
|
|
53
|
-
|
|
54
|
-
billingInterval: 'yearly',
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
// Manage customers
|
|
58
|
-
await commet.customers.create({
|
|
59
|
-
fullName: 'Acme Corp',
|
|
60
|
-
billingEmail: 'billing@acme.com'
|
|
79
|
+
code: 'api_calls'
|
|
61
80
|
});
|
|
62
81
|
|
|
63
|
-
// Generate customer portal
|
|
64
|
-
await commet.portal.getUrl({
|
|
65
|
-
|
|
82
|
+
// Generate customer portal link
|
|
83
|
+
const portal = await commet.portal.getUrl({
|
|
84
|
+
externalId: 'user_123'
|
|
66
85
|
});
|
|
67
86
|
```
|
|
68
87
|
|
package/dist/index.js
CHANGED
|
@@ -633,7 +633,7 @@ var Webhooks = class {
|
|
|
633
633
|
Buffer.from(signature, "hex"),
|
|
634
634
|
Buffer.from(expectedSignature, "hex")
|
|
635
635
|
);
|
|
636
|
-
} catch (
|
|
636
|
+
} catch (_error) {
|
|
637
637
|
return false;
|
|
638
638
|
}
|
|
639
639
|
}
|
|
@@ -785,10 +785,10 @@ var CommetHTTPClient = class {
|
|
|
785
785
|
try {
|
|
786
786
|
responseData = await response.json();
|
|
787
787
|
responseText = "";
|
|
788
|
-
} catch (
|
|
788
|
+
} catch (_jsonError) {
|
|
789
789
|
try {
|
|
790
790
|
responseText = await response.text();
|
|
791
|
-
} catch (
|
|
791
|
+
} catch (_textError) {
|
|
792
792
|
responseText = "Failed to read response body";
|
|
793
793
|
}
|
|
794
794
|
if (this.config.debug) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/customer.ts","../src/resources/credit-packs.ts","../src/resources/customers.ts","../src/resources/features.ts","../src/resources/plans.ts","../src/resources/portal.ts","../src/resources/seats.ts","../src/resources/subscriptions.ts","../src/resources/usage.ts","../src/resources/webhooks.ts","../src/types/common.ts","../src/utils/http.ts","../src/client.ts","../src/utils/environment.ts"],"sourcesContent":["/**\n * Commet SDK - Billing and usage tracking for SaaS\n */\nexport { Commet } from \"./client\";\nexport { CustomerContext } from \"./customer\";\n\n// Type exports\nexport type {\n CommetConfig,\n CommetGeneratedTypes,\n GeneratedSeatType,\n GeneratedPlanCode,\n GeneratedFeatureCode,\n Environment,\n ApiResponse,\n PaginatedResponse,\n PaginatedList,\n Currency,\n CustomerID,\n EventID,\n RequestOptions,\n} from \"./types/common\";\n\n// Error exports\nexport {\n CommetError,\n CommetAPIError,\n CommetValidationError,\n} from \"./types/common\";\n\n// Customers\nexport type {\n Customer,\n CustomerAddress,\n CreateParams as CreateCustomerParams,\n UpdateParams as UpdateCustomerParams,\n ListCustomersParams,\n BatchResult as CustomersBatchResult,\n} from \"./resources/customers\";\n\n// Usage\nexport type {\n UsageEvent,\n UsageEventProperty,\n TrackParams,\n TrackUsageParams,\n TrackModelTokensParams,\n BatchResult as UsageBatchResult,\n} from \"./resources/usage\";\n\n// Seats\nexport type {\n SeatEvent,\n SeatBalance,\n AddParams as AddSeatsParams,\n RemoveParams as RemoveSeatsParams,\n SetParams as SetSeatsParams,\n SetAllParams as SetAllSeatsParams,\n GetBalanceParams,\n GetAllBalancesParams,\n} from \"./resources/seats\";\n\n// Credit Packs\nexport type { CreditPack } from \"./resources/credit-packs\";\n\n// Plans\nexport type {\n Plan,\n PlanDetail,\n PlanPrice,\n PlanFeature,\n PlanID,\n BillingInterval,\n FeatureType,\n ListPlansParams,\n} from \"./resources/plans\";\n\n// Subscriptions\nexport type {\n CreatedSubscription,\n Subscription,\n ActiveSubscription,\n SubscriptionStatus,\n FeatureSummary,\n CreateSubscriptionParams,\n CancelParams,\n} from \"./resources/subscriptions\";\n\n// Portal\nexport type { PortalAccess, GetUrlParams } from \"./resources/portal\";\n\n// Features\nexport type {\n FeatureAccess,\n CanUseResult,\n CheckResult,\n GetFeatureParams,\n CheckFeatureParams,\n CanUseFeatureParams,\n} from \"./resources/features\";\n\n// Webhooks\nexport { Webhooks } from \"./resources/webhooks\";\nexport type {\n WebhookPayload,\n WebhookData,\n WebhookEvent,\n} from \"./resources/webhooks\";\n\n// Utility exports\nexport { isSandbox, isProduction } from \"./utils/environment\";\n\n// Default export\nimport { Commet } from \"./client\";\nexport default Commet;\n","import type { FeaturesResource } from \"./resources/features\";\nimport type { PortalResource } from \"./resources/portal\";\nimport type { SeatsResource } from \"./resources/seats\";\nimport type { SubscriptionsResource } from \"./resources/subscriptions\";\nimport type { UsageResource } from \"./resources/usage\";\nimport type { RequestOptions } from \"./types/common\";\n\n/**\n * Customer-scoped API context\n *\n * Provides a cleaner API where you don't have to pass externalId\n * on every call. All operations are scoped to a specific customer.\n *\n * @example\n * ```typescript\n * const customer = commet.customer(\"user_123\");\n *\n * // All operations are now scoped to this customer\n * const seats = await customer.features.get(\"team_members\");\n * await customer.seats.add(\"member\");\n * await customer.usage.track(\"api_call\");\n * ```\n */\nexport class CustomerContext {\n private readonly externalId: string;\n private readonly featuresResource: FeaturesResource;\n private readonly seatsResource: SeatsResource;\n private readonly usageResource: UsageResource;\n private readonly subscriptionsResource: SubscriptionsResource;\n private readonly portalResource: PortalResource;\n\n constructor(\n externalId: string,\n resources: {\n features: FeaturesResource;\n seats: SeatsResource;\n usage: UsageResource;\n subscriptions: SubscriptionsResource;\n portal: PortalResource;\n },\n ) {\n this.externalId = externalId;\n this.featuresResource = resources.features;\n this.seatsResource = resources.seats;\n this.usageResource = resources.usage;\n this.subscriptionsResource = resources.subscriptions;\n this.portalResource = resources.portal;\n }\n\n /**\n * Feature access methods - delegates to FeaturesResource\n */\n features = {\n get: (code: string, options?: RequestOptions) =>\n this.featuresResource.get({ code, externalId: this.externalId }, options),\n\n check: (code: string, options?: RequestOptions) =>\n this.featuresResource.check(\n { code, externalId: this.externalId },\n options,\n ),\n\n canUse: (code: string, options?: RequestOptions) =>\n this.featuresResource.canUse(\n { code, externalId: this.externalId },\n options,\n ),\n\n list: (options?: RequestOptions) =>\n this.featuresResource.list(this.externalId, options),\n };\n\n /**\n * Seat management methods - delegates to SeatsResource\n */\n seats = {\n add: (seatType: string, count = 1, options?: RequestOptions) =>\n this.seatsResource.add(\n { externalId: this.externalId, seatType, count },\n options,\n ),\n\n remove: (seatType: string, count = 1, options?: RequestOptions) =>\n this.seatsResource.remove(\n { externalId: this.externalId, seatType, count },\n options,\n ),\n\n set: (seatType: string, count: number, options?: RequestOptions) =>\n this.seatsResource.set(\n { externalId: this.externalId, seatType, count },\n options,\n ),\n\n getBalance: (seatType: string) =>\n this.seatsResource.getBalance({ externalId: this.externalId, seatType }),\n };\n\n /**\n * Usage tracking methods - delegates to UsageResource\n */\n usage = {\n track: (\n feature: string,\n value?: number,\n properties?: Record<string, string>,\n options?: RequestOptions,\n ) =>\n this.usageResource.track(\n { externalId: this.externalId, feature, value, properties },\n options,\n ),\n };\n\n /**\n * Subscription methods - delegates to SubscriptionsResource\n */\n subscription = {\n get: () => this.subscriptionsResource.get(this.externalId),\n };\n\n /**\n * Portal methods - delegates to PortalResource\n */\n portal = {\n getUrl: (options?: RequestOptions) =>\n this.portalResource.getUrl({ externalId: this.externalId }, options),\n };\n}\n","import type { ApiResponse } from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface CreditPack {\n id: string;\n name: string;\n description: string | null;\n credits: number;\n price: number;\n currency: string;\n}\n\n/**\n * Credit Packs resource for listing available credit packs\n */\nexport class CreditPacksResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * List all active credit packs\n *\n * @example\n * ```typescript\n * const packs = await commet.creditPacks.list();\n * console.log(packs.data); // [{ id: \"cp_xxx\", name: \"100 Credits\", ... }]\n * ```\n */\n async list(): Promise<ApiResponse<CreditPack[]>> {\n return this.httpClient.get(\"/credit-packs\");\n }\n}\n","import type {\n ApiResponse,\n ListParams as BaseListParams,\n CustomerID,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface Customer {\n id: CustomerID;\n organizationId: string;\n externalId?: string;\n fullName?: string;\n domain?: string;\n website?: string;\n billingEmail: string;\n timezone?: string;\n language?: string;\n industry?: string;\n employeeCount?: string;\n metadata?: Record<string, unknown>;\n isActive: boolean;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CustomerAddress {\n line1: string;\n line2?: string;\n city: string;\n state?: string;\n postalCode: string;\n country: string; // ISO-2\n}\n\nexport interface CreateParams {\n email: string; // billingEmail - the only required field\n externalId?: string;\n fullName?: string;\n domain?: string;\n website?: string;\n timezone?: string;\n language?: string;\n industry?: string;\n metadata?: Record<string, unknown>;\n address?: CustomerAddress;\n}\n\nexport interface UpdateParams {\n customerId: CustomerID;\n externalId?: string;\n email?: string;\n fullName?: string;\n domain?: string;\n website?: string;\n timezone?: string;\n language?: string;\n industry?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ListCustomersParams extends BaseListParams {\n externalId?: string;\n isActive?: boolean;\n search?: string;\n}\n\nexport interface BatchResult {\n successful: Customer[];\n failed: Array<{\n index: number;\n error: string;\n data: CreateParams;\n }>;\n}\n\n/**\n * Customers resource - Manage your customers\n */\nexport class CustomersResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Create a customer (idempotent with externalId)\n */\n async create(\n params: CreateParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<Customer>> {\n return this.httpClient.post(\n \"/customers\",\n {\n billingEmail: params.email,\n externalId: params.externalId,\n fullName: params.fullName,\n domain: params.domain,\n website: params.website,\n timezone: params.timezone,\n language: params.language,\n industry: params.industry,\n metadata: params.metadata,\n address: params.address,\n },\n options,\n );\n }\n\n /**\n * Create multiple customers in batch\n */\n async createBatch(\n params: { customers: CreateParams[] },\n options?: RequestOptions,\n ): Promise<ApiResponse<BatchResult>> {\n const customers = params.customers.map((c) => ({\n billingEmail: c.email,\n externalId: c.externalId,\n fullName: c.fullName,\n domain: c.domain,\n website: c.website,\n timezone: c.timezone,\n language: c.language,\n industry: c.industry,\n metadata: c.metadata,\n address: c.address,\n }));\n return this.httpClient.post(\"/customers/batch\", { customers }, options);\n }\n\n /**\n * Get a customer by ID\n */\n async get(customerId: CustomerID): Promise<ApiResponse<Customer>> {\n return this.httpClient.get(`/customers/${customerId}`);\n }\n\n /**\n * Update a customer\n */\n async update(\n params: UpdateParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<Customer>> {\n return this.httpClient.put(\n `/customers/${params.customerId}`,\n {\n billingEmail: params.email,\n externalId: params.externalId,\n fullName: params.fullName,\n domain: params.domain,\n website: params.website,\n timezone: params.timezone,\n language: params.language,\n industry: params.industry,\n metadata: params.metadata,\n },\n options,\n );\n }\n\n /**\n * List customers with optional filters\n */\n async list(params?: ListCustomersParams): Promise<ApiResponse<Customer[]>> {\n return this.httpClient.get(\"/customers\", params as Record<string, unknown>);\n }\n\n /**\n * Archive a customer\n */\n async archive(\n customerId: CustomerID,\n options?: RequestOptions,\n ): Promise<ApiResponse<Customer>> {\n return this.httpClient.put(\n `/customers/${customerId}`,\n { isActive: false },\n options,\n );\n }\n}\n","import type {\n ApiResponse,\n GeneratedFeatureCode,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface FeatureParams {\n externalId: string;\n code: GeneratedFeatureCode;\n}\n\nexport type GetFeatureParams = FeatureParams;\nexport type CheckFeatureParams = FeatureParams;\nexport type CanUseFeatureParams = FeatureParams;\n\nexport interface FeatureAccess {\n code: string;\n name: string;\n type: \"boolean\" | \"metered\" | \"seats\";\n allowed: boolean;\n // For boolean features\n enabled?: boolean;\n // For metered/seats features\n current?: number;\n included?: number;\n remaining?: number;\n overage?: number;\n overageUnitPrice?: number;\n unlimited?: boolean;\n overageEnabled?: boolean;\n}\n\nexport interface CanUseResult {\n allowed: boolean;\n willBeCharged: boolean;\n reason?: string;\n}\n\nexport interface CheckResult {\n allowed: boolean;\n}\n\n/**\n * Features resource for checking feature access and usage\n *\n * Provides a clean API to check if a customer can use a feature\n * without having to manually parse subscription data.\n */\nexport class FeaturesResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Get detailed feature access/usage for a customer\n *\n * @example\n * ```typescript\n * const seats = await commet.features.get({ code: \"team_members\", externalId: \"user_123\" });\n * console.log(seats.current, seats.included, seats.remaining);\n * ```\n */\n async get(\n params: GetFeatureParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<FeatureAccess>> {\n const { code, externalId } = params;\n\n return this.httpClient.get(\n `/features/${code}`,\n { externalId: externalId },\n options,\n );\n }\n\n /**\n * Check if a boolean feature is enabled for a customer\n *\n * @example\n * ```typescript\n * const { allowed } = await commet.features.check({\n * code: \"custom_branding\",\n * externalId: \"user_123\"\n * });\n * if (!allowed) redirect(\"/upgrade\");\n * ```\n */\n async check(\n params: CheckFeatureParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<CheckResult>> {\n const { code, externalId } = params;\n\n const result = await this.httpClient.get<FeatureAccess>(\n `/features/${code}`,\n { externalId: externalId },\n options,\n );\n\n if (!result.success || !result.data) {\n return {\n success: false,\n data: { allowed: false },\n message: result.message,\n };\n }\n\n return {\n success: true,\n data: { allowed: result.data.allowed },\n message: result.message,\n };\n }\n\n /**\n * Check if customer can use one more unit of a feature\n *\n * Returns whether the customer can add one more (allowed)\n * and whether they'll be charged extra (willBeCharged).\n *\n * @example\n * ```typescript\n * const { allowed, willBeCharged } = await commet.features.canUse({\n * code: \"team_members\",\n * externalId: \"user_123\"\n * });\n *\n * if (!allowed) {\n * return { error: \"Upgrade to add more members\" };\n * }\n *\n * if (willBeCharged) {\n * // Show confirmation: \"This will cost $10/month extra\"\n * }\n * ```\n */\n async canUse(\n params: CanUseFeatureParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<CanUseResult>> {\n const { code, externalId } = params;\n\n return this.httpClient.get(\n `/features/${code}`,\n { externalId: externalId, action: \"canUse\" },\n options,\n );\n }\n\n /**\n * List all features for a customer's active subscription\n *\n * @example\n * ```typescript\n * const features = await commet.features.list({ externalId: \"user_123\" });\n * for (const feature of features) {\n * console.log(feature.code, feature.allowed);\n * }\n * ```\n */\n async list(\n externalId: string,\n options?: RequestOptions,\n ): Promise<ApiResponse<FeatureAccess[]>> {\n return this.httpClient.get(\"/features\", { externalId }, options);\n }\n}\n","import type {\n ApiResponse,\n GeneratedPlanCode,\n ListParams,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport type PlanID = `plan_${string}`;\nexport type BillingInterval = \"monthly\" | \"quarterly\" | \"yearly\";\nexport type FeatureType = \"boolean\" | \"metered\" | \"seats\";\n\nexport interface PlanPrice {\n billingInterval: BillingInterval;\n price: number; // in cents\n isDefault: boolean;\n trialDays: number;\n}\n\nexport interface PlanFeature {\n code: string;\n name: string;\n type: FeatureType;\n unitName: string | null;\n enabled?: boolean;\n includedAmount?: number;\n unlimited?: boolean;\n overageEnabled?: boolean;\n overageUnitPrice?: number;\n}\n\nexport interface Plan {\n id: PlanID;\n code: string;\n name: string;\n description: string | null;\n isPublic: boolean;\n isFree: boolean;\n isDefault: boolean;\n sortOrder: number;\n prices: PlanPrice[];\n features: PlanFeature[];\n createdAt: string;\n}\n\nexport interface PlanDetailPrice {\n billingInterval: BillingInterval;\n price: number;\n isDefault: boolean;\n trialDays: number;\n introOffer: {\n enabled: boolean;\n discountType: \"percentage\" | \"amount\" | null;\n discountValue: number | null;\n durationCycles: number | null;\n } | null;\n}\n\nexport interface PlanDetailFeature extends PlanFeature {\n overage: {\n enabled: boolean;\n model: \"per_unit\" | \"tiered\" | null;\n unitPrice: number | null;\n } | null;\n}\n\nexport interface PlanDetail {\n id: PlanID;\n code: string;\n name: string;\n description: string | null;\n isPublic: boolean;\n isDefault: boolean;\n sortOrder: number;\n prices: PlanDetailPrice[];\n features: PlanDetailFeature[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ListPlansParams extends ListParams {\n includePrivate?: boolean;\n}\n\n/**\n * Plans resource for listing available plans\n */\nexport class PlansResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * List all available plans\n *\n * @example\n * ```typescript\n * // List public plans\n * const plans = await commet.plans.list();\n *\n * // Include private plans\n * const allPlans = await commet.plans.list({ includePrivate: true });\n * ```\n */\n async list(params?: ListPlansParams): Promise<ApiResponse<Plan[]>> {\n return this.httpClient.get(\"/plans\", params);\n }\n\n /**\n * Get a specific plan by code\n *\n * @example\n * ```typescript\n * const plan = await commet.plans.get('pro');\n * console.log(plan.data.name); // \"Pro\"\n * console.log(plan.data.prices); // [{ billingInterval: 'monthly', price: 9900 }]\n * ```\n */\n async get(planCode: GeneratedPlanCode): Promise<ApiResponse<PlanDetail>> {\n return this.httpClient.get(`/plans/${planCode}`);\n }\n}\n","import type { ApiResponse, CustomerID, RequestOptions } from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface PortalAccess {\n success: boolean;\n message: string;\n portalUrl: string;\n}\n\ninterface GetUrlByCustomerId {\n customerId: CustomerID;\n email?: never;\n externalId?: never;\n}\n\ninterface GetUrlByExternalId {\n externalId: string;\n email?: never;\n customerId?: never;\n}\n\ninterface GetUrlByEmail {\n email: string;\n customerId?: never;\n externalId?: never;\n}\n\nexport type GetUrlParams =\n | GetUrlByCustomerId\n | GetUrlByExternalId\n | GetUrlByEmail;\n\n/**\n * Portal resource - Generate customer portal access\n */\nexport class PortalResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Get a portal URL\n *\n * @example\n * ```typescript\n * const portal = await commet.portal.getUrl({ externalId: 'user_123' });\n * ```\n */\n async getUrl(\n params: GetUrlParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<PortalAccess>> {\n return this.httpClient.post(\"/portal/request-access\", params, options);\n }\n}\n","import type {\n ApiResponse,\n CustomerID,\n GeneratedSeatType,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface SeatEvent {\n id: string;\n organizationId: string;\n customerId: CustomerID;\n seatType: GeneratedSeatType;\n eventType: \"add\" | \"remove\" | \"set\";\n quantity: number;\n previousBalance?: number;\n newBalance: number;\n ts: string;\n createdAt: string;\n}\n\nexport interface SeatBalance {\n current: number;\n asOf: string;\n}\n\nexport interface AddParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n count: number;\n}\n\nexport interface RemoveParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n count: number;\n}\n\nexport interface SetParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n count: number;\n}\n\nexport interface SetAllParams {\n customerId?: CustomerID;\n externalId?: string;\n seats: Record<string, number>;\n}\n\nexport interface GetBalanceParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n}\n\nexport interface GetAllBalancesParams {\n customerId?: CustomerID;\n externalId?: string;\n}\n\n/**\n * Seats resource - Manage seat-based licenses\n */\nexport class SeatsResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Add seats\n *\n * @example\n * ```typescript\n * await commet.seats.add({\n * externalId: 'user_123',\n * seatType: 'editor',\n * count: 5\n * });\n * ```\n */\n async add(\n params: AddParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent>> {\n return this.httpClient.post(\"/seats\", params, options);\n }\n\n /**\n * Remove seats\n *\n * @example\n * ```typescript\n * await commet.seats.remove({\n * externalId: 'user_123',\n * seatType: 'editor',\n * count: 2\n * });\n * ```\n */\n async remove(\n params: RemoveParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent>> {\n return this.httpClient.delete(\"/seats\", params, options);\n }\n\n /**\n * Set seats to a specific count\n *\n * @example\n * ```typescript\n * await commet.seats.set({\n * externalId: 'user_123',\n * seatType: 'editor',\n * count: 10\n * });\n * ```\n */\n async set(\n params: SetParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent>> {\n return this.httpClient.put(\"/seats\", params, options);\n }\n\n /**\n * Set all seat types\n *\n * @example\n * ```typescript\n * await commet.seats.setAll({\n * externalId: 'user_123',\n * seats: { editor: 10, viewer: 50 }\n * });\n * ```\n */\n async setAll(\n params: SetAllParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent[]>> {\n return this.httpClient.put(\"/seats/bulk\", params, options);\n }\n\n /**\n * Get balance for a seat type\n *\n * @example\n * ```typescript\n * const balance = await commet.seats.getBalance({\n * externalId: 'user_123',\n * seatType: 'editor'\n * });\n * ```\n */\n async getBalance(\n params: GetBalanceParams,\n ): Promise<ApiResponse<SeatBalance>> {\n const { customerId, externalId, seatType } = params;\n\n return this.httpClient.get(\"/seats/balance\", {\n customerId: customerId,\n externalId: externalId,\n seatType: seatType,\n });\n }\n\n /**\n * Get all seat balances\n *\n * @example\n * ```typescript\n * const balances = await commet.seats.getAllBalances({\n * externalId: 'user_123'\n * });\n * ```\n */\n async getAllBalances(\n params: GetAllBalancesParams,\n ): Promise<ApiResponse<Record<string, SeatBalance>>> {\n const { customerId, externalId } = params;\n\n return this.httpClient.get(\"/seats/balances\", {\n customerId: customerId,\n externalId: externalId,\n });\n }\n}\n","import type {\n ApiResponse,\n GeneratedPlanCode,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\nimport type { BillingInterval } from \"./plans\";\n\nexport type SubscriptionStatus =\n | \"draft\"\n | \"pending_payment\"\n | \"trialing\"\n | \"active\"\n | \"paused\"\n | \"past_due\"\n | \"canceled\"\n | \"expired\";\n\nexport interface FeatureSummary {\n code: string;\n name: string;\n type: \"boolean\" | \"metered\" | \"seats\";\n enabled?: boolean;\n usage?: {\n current: number;\n included: number;\n overage: number;\n overageUnitPrice?: number;\n };\n}\n\nexport interface ActiveSubscription {\n id: string;\n customerId: string;\n plan: {\n id: string;\n name: string;\n basePrice: number;\n billingInterval: BillingInterval | null;\n };\n name: string;\n description: string | null;\n status: SubscriptionStatus;\n trialEndsAt: string | null;\n currentPeriod: {\n start: string;\n end: string;\n daysRemaining: number;\n };\n features: FeatureSummary[];\n startDate: string;\n endDate: string | null;\n billingDayOfMonth: number;\n nextBillingDate: string;\n checkoutUrl: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CreatedSubscription {\n id: string;\n customerId: string;\n externalId: string;\n planId: string;\n planName: string;\n name: string;\n status: SubscriptionStatus;\n billingInterval: BillingInterval | null;\n trialEndsAt: string | null;\n startDate: string;\n endDate: string | null;\n currentPeriodStart: string | null;\n currentPeriodEnd: string | null;\n billingDayOfMonth: number;\n checkoutUrl: string | null;\n createdAt: string;\n updatedAt: string;\n introOfferEndsAt: string | null;\n introOfferDiscountType: \"percentage\" | \"amount\" | null;\n introOfferDiscountValue: number | null;\n}\n\nexport interface Subscription {\n id: string;\n customerId: string;\n planId: string;\n planName: string;\n name: string;\n description?: string;\n status: SubscriptionStatus;\n billingInterval: BillingInterval;\n trialEndsAt?: string;\n startDate: string;\n endDate?: string;\n currentPeriodStart?: string;\n currentPeriodEnd?: string;\n billingDayOfMonth: number;\n checkoutUrl?: string;\n createdAt: string;\n updatedAt: string;\n}\n\n// Customer identifier: mutually exclusive customerId or externalId\ntype CustomerIdentifier =\n | { customerId: string; externalId?: never }\n | { customerId?: never; externalId: string };\n\n// Plan identifier: use planCode (with autocomplete) or planId (legacy)\ntype PlanIdentifier =\n | { planCode: GeneratedPlanCode; planId?: never }\n | { planCode?: never; planId: string };\n\nexport type CreateSubscriptionParams = CustomerIdentifier &\n PlanIdentifier & {\n billingInterval?: BillingInterval;\n initialSeats?: Record<string, number>;\n skipTrial?: boolean;\n name?: string;\n startDate?: string;\n successUrl?: string;\n };\n\nexport interface CancelParams {\n subscriptionId: string;\n reason?: string;\n immediate?: boolean;\n}\n\n/**\n * Subscription resource for managing subscriptions (plan-first model)\n *\n * Each customer can only have ONE active subscription at a time.\n */\nexport class SubscriptionsResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Create a subscription with a plan\n *\n * @example\n * ```typescript\n * await commet.subscriptions.create({\n * externalId: 'user_123',\n * planCode: 'pro', // autocomplete works after `commet pull`\n * billingInterval: 'yearly',\n * initialSeats: { editor: 5 }\n * });\n * ```\n */\n async create(\n params: CreateSubscriptionParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<CreatedSubscription>> {\n return this.httpClient.post(\"/subscriptions\", params, options);\n }\n\n /**\n * Get the active subscription for a customer\n *\n * @example\n * ```typescript\n * const sub = await commet.subscriptions.get('user_123');\n * ```\n */\n async get(\n externalId: string,\n ): Promise<ApiResponse<ActiveSubscription | null>> {\n return this.httpClient.get(\"/subscriptions/active\", { externalId });\n }\n\n /**\n * Cancel a subscription\n *\n * @example\n * ```typescript\n * await commet.subscriptions.cancel({\n * subscriptionId: 'sub_xxx',\n * reason: 'switched_to_competitor'\n * });\n * ```\n */\n async cancel(\n params: CancelParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<Subscription>> {\n return this.httpClient.post(\n `/subscriptions/${params.subscriptionId}/cancel`,\n params || {},\n options,\n );\n }\n}\n","import type {\n ApiResponse,\n CustomerID,\n EventID,\n GeneratedFeatureCode,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface UsageEvent {\n id: EventID;\n organizationId: string;\n customerId: CustomerID;\n feature: string;\n idempotencyKey?: string;\n ts: string;\n properties?: UsageEventProperty[];\n createdAt: string;\n}\n\nexport interface UsageEventProperty {\n id: string;\n usageEventId: EventID;\n property: string;\n value: string;\n createdAt: string;\n}\n\nexport interface BatchResult<T> {\n successful: T[];\n failed: Array<{\n index: number;\n error: string;\n data: TrackParams;\n }>;\n}\n\ninterface TrackBaseParams {\n feature: GeneratedFeatureCode;\n customerId?: CustomerID;\n externalId?: string;\n idempotencyKey?: string;\n timestamp?: string;\n properties?: Record<string, string>;\n}\n\nexport interface TrackUsageParams extends TrackBaseParams {\n value?: number;\n model?: never;\n}\n\nexport interface TrackModelTokensParams extends TrackBaseParams {\n model: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n value?: never;\n}\n\nexport type TrackParams = TrackUsageParams | TrackModelTokensParams;\n\nexport class UsageResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n async track(\n params: TrackParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<UsageEvent>> {\n const eventData: Record<string, unknown> = {\n feature: params.feature,\n customerId: params.customerId,\n externalId: params.externalId,\n idempotencyKey: params.idempotencyKey,\n timestamp: params.timestamp || new Date().toISOString(),\n properties: params.properties\n ? Object.entries(params.properties).map(([property, value]) => ({\n property,\n value,\n }))\n : undefined,\n };\n\n if (\"model\" in params && params.model) {\n eventData.model = params.model;\n eventData.inputTokens = params.inputTokens;\n eventData.outputTokens = params.outputTokens;\n if (params.cacheReadTokens) {\n eventData.cacheReadTokens = params.cacheReadTokens;\n }\n if (params.cacheWriteTokens) {\n eventData.cacheWriteTokens = params.cacheWriteTokens;\n }\n } else {\n eventData.value = (params as TrackUsageParams).value;\n }\n\n return this.httpClient.post(\"/usage/events\", eventData, options);\n }\n\n async trackBatch(\n params: { events: TrackParams[] },\n options?: RequestOptions,\n ): Promise<ApiResponse<BatchResult<UsageEvent>>> {\n const events = params.events.map((event) => {\n const eventData: Record<string, unknown> = {\n feature: event.feature,\n customerId: event.customerId,\n externalId: event.externalId,\n idempotencyKey: event.idempotencyKey,\n timestamp: event.timestamp || new Date().toISOString(),\n properties: event.properties\n ? Object.entries(event.properties).map(([property, value]) => ({\n property,\n value,\n }))\n : undefined,\n };\n\n if (\"model\" in event && event.model) {\n eventData.model = event.model;\n eventData.inputTokens = event.inputTokens;\n eventData.outputTokens = event.outputTokens;\n if (event.cacheReadTokens) {\n eventData.cacheReadTokens = event.cacheReadTokens;\n }\n if (event.cacheWriteTokens) {\n eventData.cacheWriteTokens = event.cacheWriteTokens;\n }\n } else {\n eventData.value = (event as TrackUsageParams).value;\n }\n\n return eventData;\n });\n\n return this.httpClient.post(\"/usage/events/batch\", { events }, options);\n }\n}\n","import crypto from \"node:crypto\";\n\n/**\n * Webhook payload structure from Commet\n */\nexport interface WebhookPayload {\n event: WebhookEvent;\n timestamp: string;\n organizationId: string;\n data: WebhookData;\n}\n\n/**\n * Webhook data structure (subscription-related fields)\n */\nexport interface WebhookData {\n id?: string;\n publicId?: string;\n subscriptionId?: string;\n customerId?: string;\n externalId?: string;\n status?: string;\n name?: string;\n canceledAt?: string;\n [key: string]: unknown;\n}\n\n/**\n * Supported webhook events\n */\nexport type WebhookEvent =\n | \"subscription.created\"\n | \"subscription.activated\"\n | \"subscription.canceled\"\n | \"subscription.updated\";\n\nexport interface VerifyParams {\n payload: string;\n signature: string | null;\n secret: string;\n}\n\nexport interface GenerateSignatureParams {\n payload: string;\n secret: string;\n}\n\nexport interface VerifyAndParseParams {\n rawBody: string;\n signature: string | null;\n secret: string;\n}\n\n/**\n * Webhooks resource for signature verification\n */\nexport class Webhooks {\n /**\n * Verify HMAC-SHA256 webhook signature\n *\n * Use this method to verify that webhooks are authentically from Commet.\n * The signature is included in the `X-Commet-Signature` header.\n *\n * @param payload - Raw request body as string (IMPORTANT: Do not parse JSON first)\n * @param signature - Value from X-Commet-Signature header\n * @param secret - Your webhook secret from Commet dashboard\n * @returns true if signature is valid, false otherwise\n *\n * @example\n * ```typescript\n * // Next.js API route example\n * export async function POST(request: Request) {\n * const rawBody = await request.text();\n * const signature = request.headers.get('x-commet-signature');\n *\n * const isValid = commet.webhooks.verify(\n * rawBody,\n * signature,\n * process.env.COMMET_WEBHOOK_SECRET\n * );\n *\n * if (!isValid) {\n * return new Response('Invalid signature', { status: 401 });\n * }\n *\n * const payload = JSON.parse(rawBody);\n * // Handle webhook event...\n * }\n * ```\n */\n verify(params: VerifyParams): boolean {\n const { payload, signature, secret } = params;\n\n if (!signature || !secret || !payload) {\n return false;\n }\n\n try {\n const expectedSignature = this.generateSignature({ payload, secret });\n\n // Use timing-safe comparison to prevent timing attacks\n return crypto.timingSafeEqual(\n Buffer.from(signature, \"hex\"),\n Buffer.from(expectedSignature, \"hex\"),\n );\n } catch (error) {\n // timingSafeEqual throws if lengths don't match\n return false;\n }\n }\n\n /**\n * Generate HMAC-SHA256 signature (internal use)\n * @internal\n */\n private generateSignature(params: GenerateSignatureParams): string {\n const { payload, secret } = params;\n return crypto.createHmac(\"sha256\", secret).update(payload).digest(\"hex\");\n }\n\n /**\n * Parse and verify webhook payload in one step\n *\n * @example\n * ```typescript\n * const payload = commet.webhooks.verifyAndParse({\n * rawBody,\n * signature,\n * secret: process.env.COMMET_WEBHOOK_SECRET\n * });\n *\n * if (!payload) {\n * return new Response('Invalid signature', { status: 401 });\n * }\n *\n * // payload is typed and validated\n * if (payload.event === 'subscription.activated') {\n * // Handle activation...\n * }\n * ```\n */\n verifyAndParse(params: VerifyAndParseParams): WebhookPayload | null {\n const { rawBody, signature, secret } = params;\n\n if (!this.verify({ payload: rawBody, signature, secret })) {\n return null;\n }\n\n try {\n return JSON.parse(params.rawBody) as WebhookPayload;\n } catch {\n return null;\n }\n }\n}\n","export type Environment = \"sandbox\" | \"production\";\n\nexport type CommetConfig = {\n apiKey: string;\n environment?: Environment;\n debug?: boolean;\n timeout?: number;\n retries?: number;\n};\n\n// API Response types\nexport interface ApiResponse<T = unknown> {\n success: boolean;\n data?: T;\n code?: string;\n message?: string;\n details?: unknown;\n // Pagination fields (optional, included for list endpoints)\n hasMore?: boolean;\n nextCursor?: string;\n}\n\nexport interface PaginatedResponse<T> {\n data: T[];\n hasMore: boolean;\n nextCursor?: string;\n totalCount?: number;\n}\n\nexport interface PaginatedList<T> extends PaginatedResponse<T> {\n next(): Promise<PaginatedList<T>>;\n all(): Promise<T[]>;\n}\n\n// Error types\nexport class CommetError extends Error {\n constructor(\n message: string,\n public code?: string,\n public statusCode?: number,\n public details?: unknown,\n ) {\n super(message);\n this.name = \"CommetError\";\n }\n}\n\nexport class CommetAPIError extends CommetError {\n constructor(\n message: string,\n public statusCode: number,\n public code?: string,\n public details?: unknown,\n ) {\n super(message, code, statusCode, details);\n this.name = \"CommetAPIError\";\n }\n}\n\nexport class CommetValidationError extends CommetError {\n constructor(\n message: string,\n public validationErrors: Record<string, string[]>,\n ) {\n super(message);\n this.name = \"CommetValidationError\";\n }\n}\n\nexport type CustomerID = `cus_${string}`;\nexport type AgreementID = `agr_${string}`;\nexport type InvoiceID = `inv_${string}`;\nexport type PhaseID = `phs_${string}`;\nexport type ItemID = `itm_${string}`;\nexport type ProductID = `prd_${string}`;\nexport type EventID = `evt_${string}`;\nexport type WebhookID = `wh_${string}`;\n\n// Currency enum\nexport type Currency =\n | \"USD\"\n | \"EUR\"\n | \"GBP\"\n | \"CAD\"\n | \"AUD\"\n | \"JPY\"\n | \"ARS\"\n | \"BRL\"\n | \"MXN\"\n | \"CLP\";\n\n// Common parameters\nexport interface ListParams extends Record<string, unknown> {\n limit?: number;\n cursor?: string;\n startDate?: string;\n endDate?: string;\n}\n\nexport interface RetrieveOptions {\n expand?: string[];\n}\n\n// Request options\nexport interface RequestOptions {\n idempotencyKey?: string;\n timeout?: number;\n}\n\n/**\n * Generated types interface - augmented by CLI after 'commet pull'\n *\n * This interface gets filled by module augmentation when you run `commet pull`.\n * The CLI generates a .commet/types.d.ts file that augments this interface with your\n * organization's specific feature codes, seat types, and plan codes.\n *\n * @example\n * // After running `commet pull`, TypeScript will automatically know your types:\n * await commet.usage.track({\n * feature: 'api_calls', // Autocomplete works!\n * externalId: 'user_123'\n * });\n */\n\n// biome-ignore lint/suspicious/noEmptyInterface: augmented by CLI-generated .commet/types.d.ts\nexport interface CommetGeneratedTypes {}\n\nexport type GeneratedSeatType = CommetGeneratedTypes extends {\n seatType: infer T;\n}\n ? T\n : string;\n\nexport type GeneratedPlanCode = CommetGeneratedTypes extends {\n planCode: infer T;\n}\n ? T\n : string;\n\nexport type GeneratedFeatureCode = CommetGeneratedTypes extends {\n featureCode: infer T;\n}\n ? T\n : string;\n","import type {\n ApiResponse,\n CommetConfig,\n Environment,\n RequestOptions,\n} from \"../types/common\";\nimport { CommetAPIError, CommetValidationError } from \"../types/common\";\n\nexport interface RetryConfig {\n maxRetries: number;\n baseDelay: number;\n maxDelay: number;\n retryableStatusCodes: number[];\n}\n\nconst DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 3,\n baseDelay: 1000, // 1s\n maxDelay: 8000, // 8s\n retryableStatusCodes: [408, 429, 500, 502, 503, 504],\n};\n\nexport class CommetHTTPClient {\n private config: CommetConfig;\n private environment: Environment;\n private retryConfig: RetryConfig;\n\n constructor(config: CommetConfig, environment: Environment) {\n this.config = config;\n this.environment = environment;\n this.retryConfig = {\n ...DEFAULT_RETRY_CONFIG,\n maxRetries: config.retries ?? DEFAULT_RETRY_CONFIG.maxRetries,\n };\n }\n\n async get<T = unknown>(\n endpoint: string,\n params?: Record<string, unknown>,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"GET\", endpoint, undefined, options, params);\n }\n\n async post<T = unknown>(\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"POST\", endpoint, data, options);\n }\n\n async put<T = unknown>(\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"PUT\", endpoint, data, options);\n }\n\n async delete<T = unknown>(\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"DELETE\", endpoint, data, options);\n }\n\n /**\n * Core request method with retry logic\n */\n private async request<T = unknown>(\n method: string,\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n params?: Record<string, unknown>,\n ): Promise<ApiResponse<T>> {\n const url = this.buildURL(endpoint, params);\n return this.executeRequest(method, url, data, options);\n }\n\n /**\n * Execute real API request with retry logic\n */\n private async executeRequest<T = unknown>(\n method: string,\n url: string,\n data?: unknown,\n options?: RequestOptions,\n attempt = 1,\n ): Promise<ApiResponse<T>> {\n try {\n const headers: Record<string, string> = {\n \"x-api-key\": this.config.apiKey,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"commet/0.1.0\",\n };\n\n if (options?.idempotencyKey) {\n headers[\"Idempotency-Key\"] = options.idempotencyKey;\n } else if (method === \"POST\" && data) {\n headers[\"Idempotency-Key\"] = this.generateIdempotencyKey();\n }\n\n const requestConfig: RequestInit = {\n method,\n headers,\n signal: AbortSignal.timeout(\n options?.timeout ?? this.config.timeout ?? 30000,\n ),\n };\n\n if (data) {\n requestConfig.body = JSON.stringify(data);\n }\n\n if (this.config.debug) {\n console.log(`[Commet SDK] ${method} ${url}`);\n if (data) {\n console.log(\"Request data:\", JSON.stringify(data, null, 2));\n }\n }\n\n const response = await fetch(url, requestConfig);\n\n if (this.config.debug) {\n console.log(\n `[Commet SDK] Response status: ${response.status} ${response.statusText}`,\n );\n }\n\n let responseData: unknown;\n let responseText: string;\n\n try {\n responseData = await response.json();\n responseText = \"\";\n } catch (jsonError) {\n try {\n responseText = await response.text();\n } catch (textError) {\n responseText = \"Failed to read response body\";\n }\n if (this.config.debug) {\n console.log(\n \"[Commet SDK] Failed to parse JSON response:\",\n responseText,\n );\n }\n\n // For 404 errors with invalid JSON, return a graceful response\n // This handles cases like HTML error pages or empty responses\n if (response.status === 404) {\n return {\n success: false,\n code: \"not_found\",\n message: \"Resource not found\",\n } as ApiResponse<T>;\n }\n\n throw new CommetAPIError(\n `Invalid JSON response: ${response.status} ${response.statusText}`,\n response.status,\n \"INVALID_JSON\",\n { responseText },\n );\n }\n\n if (!response.ok) {\n // Check if we should retry\n if (\n attempt <= this.retryConfig.maxRetries &&\n this.retryConfig.retryableStatusCodes.includes(response.status)\n ) {\n const delay = Math.min(\n this.retryConfig.baseDelay * 2 ** (attempt - 1),\n this.retryConfig.maxDelay,\n );\n\n if (this.config.debug) {\n console.log(\n `[Commet SDK] Retrying in ${delay}ms (attempt ${attempt}/${this.retryConfig.maxRetries})`,\n );\n }\n\n await this.sleep(delay);\n return this.executeRequest(method, url, data, options, attempt + 1);\n }\n\n // Log error response for debugging\n if (this.config.debug) {\n console.log(\n \"[Commet SDK] Error response:\",\n JSON.stringify(responseData, null, 2),\n );\n }\n\n // Type guard for error response\n const isErrorResponse = (\n data: unknown,\n ): data is {\n message?: string;\n code?: string;\n details?: unknown;\n } => {\n return typeof data === \"object\" && data !== null;\n };\n\n const errorData = isErrorResponse(responseData) ? responseData : {};\n\n // Handle validation errors (new normalized shape)\n if (\n errorData.code === \"validation_error\" &&\n Array.isArray(errorData.details)\n ) {\n const errors: Record<string, string[]> = {};\n for (const detail of errorData.details as Array<{\n field: string;\n message: string;\n }>) {\n if (!errors[detail.field]) errors[detail.field] = [];\n errors[detail.field].push(detail.message);\n }\n throw new CommetValidationError(\n errorData.message || \"Validation failed\",\n errors,\n );\n }\n\n throw new CommetAPIError(\n errorData.message || `Request failed with status ${response.status}`,\n response.status,\n errorData.code,\n errorData.details,\n );\n }\n\n if (this.config.debug) {\n console.log(\"[Commet SDK] Response:\", responseData);\n }\n\n return responseData as ApiResponse<T>;\n } catch (error) {\n // Handle network errors and timeouts\n if (error instanceof TypeError && error.message.includes(\"fetch\")) {\n if (attempt <= this.retryConfig.maxRetries) {\n const delay = Math.min(\n this.retryConfig.baseDelay * 2 ** (attempt - 1),\n this.retryConfig.maxDelay,\n );\n\n if (this.config.debug) {\n console.log(`[Commet SDK] Network error, retrying in ${delay}ms`);\n }\n\n await this.sleep(delay);\n return this.executeRequest(method, url, data, options, attempt + 1);\n }\n }\n\n throw error;\n }\n }\n\n /**\n * Get base URL based on environment\n */\n private getBaseURL(): string {\n return this.environment === \"production\"\n ? \"https://commet.co\"\n : \"https://sandbox.commet.co\";\n }\n\n /**\n * Build full URL from endpoint and params\n */\n private buildURL(endpoint: string, params?: Record<string, unknown>): string {\n const baseURL = this.getBaseURL();\n\n // Construct full path with /api prefix\n const normalizedEndpoint = endpoint.startsWith(\"/\")\n ? endpoint\n : `/${endpoint}`;\n const fullPath = `/api${normalizedEndpoint}`;\n\n // Debug logging\n if (this.config.debug) {\n console.log(\n `[Commet SDK] Building URL - baseURL: ${baseURL}, endpoint: ${endpoint}, fullPath: ${fullPath}`,\n );\n }\n\n const url = new URL(fullPath, baseURL);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value));\n }\n }\n }\n\n const finalUrl = url.toString();\n\n // Debug final URL\n if (this.config.debug) {\n console.log(`[Commet SDK] Final URL: ${finalUrl}`);\n }\n\n return finalUrl;\n }\n\n /**\n * Generate idempotency key\n */\n private generateIdempotencyKey(): string {\n // Generate UUID-like key for idempotency\n return `sdk_${Date.now()}_${Math.random().toString(36).substring(2)}`;\n }\n\n /**\n * Sleep for specified milliseconds\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { CustomerContext } from \"./customer\";\nimport { CreditPacksResource } from \"./resources/credit-packs\";\nimport { CustomersResource } from \"./resources/customers\";\nimport { FeaturesResource } from \"./resources/features\";\nimport { PlansResource } from \"./resources/plans\";\nimport { PortalResource } from \"./resources/portal\";\nimport { SeatsResource } from \"./resources/seats\";\nimport { SubscriptionsResource } from \"./resources/subscriptions\";\nimport { UsageResource } from \"./resources/usage\";\nimport { Webhooks } from \"./resources/webhooks\";\nimport type { CommetConfig, Environment } from \"./types/common\";\nimport { CommetHTTPClient } from \"./utils/http\";\n\n/**\n * Main Commet SDK client\n */\nexport class Commet {\n private httpClient: CommetHTTPClient;\n private environment: Environment;\n\n public readonly customers: CustomersResource;\n public readonly creditPacks: CreditPacksResource;\n public readonly plans: PlansResource;\n public readonly usage: UsageResource;\n public readonly seats: SeatsResource;\n public readonly subscriptions: SubscriptionsResource;\n public readonly portal: PortalResource;\n public readonly features: FeaturesResource;\n public readonly webhooks: Webhooks;\n\n constructor(config: CommetConfig) {\n if (!config.apiKey) {\n throw new Error(\"Commet SDK: API key is required\");\n }\n\n if (!config.apiKey.startsWith(\"ck_\")) {\n throw new Error(\n \"Commet SDK: Invalid API key format. Expected format: ck_xxx...\",\n );\n }\n\n // Default to sandbox for safety\n this.environment = config.environment || \"sandbox\";\n\n this.httpClient = new CommetHTTPClient(config, this.environment);\n this.customers = new CustomersResource(this.httpClient);\n this.creditPacks = new CreditPacksResource(this.httpClient);\n this.plans = new PlansResource(this.httpClient);\n this.usage = new UsageResource(this.httpClient);\n this.seats = new SeatsResource(this.httpClient);\n this.subscriptions = new SubscriptionsResource(this.httpClient);\n this.portal = new PortalResource(this.httpClient);\n this.features = new FeaturesResource(this.httpClient);\n this.webhooks = new Webhooks();\n\n if (config.debug) {\n console.log(`[Commet SDK] Initialized in ${this.environment} mode`);\n console.log(\"API Key:\", `${config.apiKey.substring(0, 12)}...`);\n const baseURL =\n this.environment === \"production\"\n ? \"https://commet.co\"\n : \"https://sandbox.commet.co\";\n console.log(\"Base URL:\", baseURL);\n }\n }\n\n /**\n * Create a customer-scoped context for cleaner API usage\n *\n * @example\n * ```typescript\n * const customer = commet.customer(\"user_123\");\n *\n * // All operations are now scoped to this customer\n * const seats = await customer.features.get(\"team_members\");\n * await customer.seats.add(\"member\");\n * await customer.usage.track(\"api_call\");\n * ```\n */\n customer(externalId: string): CustomerContext {\n return new CustomerContext(externalId, {\n features: this.features,\n seats: this.seats,\n usage: this.usage,\n subscriptions: this.subscriptions,\n portal: this.portal,\n });\n }\n\n getEnvironment(): Environment {\n return this.environment;\n }\n\n isSandbox(): boolean {\n return this.environment === \"sandbox\";\n }\n\n isProduction(): boolean {\n return this.environment === \"production\";\n }\n}\n","import type { Environment } from \"../types/common\";\n\n/**\n * Check if environment is sandbox\n */\nexport function isSandbox(environment: Environment): boolean {\n return environment === \"sandbox\";\n}\n\n/**\n * Check if environment is production\n */\nexport function isProduction(environment: Environment): boolean {\n return environment === \"production\";\n}\n"],"mappings":"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","names":["crypto","data"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/customer.ts","../src/resources/credit-packs.ts","../src/resources/customers.ts","../src/resources/features.ts","../src/resources/plans.ts","../src/resources/portal.ts","../src/resources/seats.ts","../src/resources/subscriptions.ts","../src/resources/usage.ts","../src/resources/webhooks.ts","../src/types/common.ts","../src/utils/http.ts","../src/client.ts","../src/utils/environment.ts"],"sourcesContent":["/**\n * Commet SDK - Billing and usage tracking for SaaS\n */\nexport { Commet } from \"./client\";\nexport { CustomerContext } from \"./customer\";\n// Credit Packs\nexport type { CreditPack } from \"./resources/credit-packs\";\n// Customers\nexport type {\n BatchResult as CustomersBatchResult,\n CreateParams as CreateCustomerParams,\n Customer,\n CustomerAddress,\n ListCustomersParams,\n UpdateParams as UpdateCustomerParams,\n} from \"./resources/customers\";\n// Features\nexport type {\n CanUseFeatureParams,\n CanUseResult,\n CheckFeatureParams,\n CheckResult,\n FeatureAccess,\n GetFeatureParams,\n} from \"./resources/features\";\n// Plans\nexport type {\n BillingInterval,\n FeatureType,\n ListPlansParams,\n Plan,\n PlanDetail,\n PlanFeature,\n PlanID,\n PlanPrice,\n} from \"./resources/plans\";\n// Portal\nexport type { GetUrlParams, PortalAccess } from \"./resources/portal\";\n// Seats\nexport type {\n AddParams as AddSeatsParams,\n GetAllBalancesParams,\n GetBalanceParams,\n RemoveParams as RemoveSeatsParams,\n SeatBalance,\n SeatEvent,\n SetAllParams as SetAllSeatsParams,\n SetParams as SetSeatsParams,\n} from \"./resources/seats\";\n// Subscriptions\nexport type {\n ActiveSubscription,\n CancelParams,\n CreatedSubscription,\n CreateSubscriptionParams,\n FeatureSummary,\n Subscription,\n SubscriptionStatus,\n} from \"./resources/subscriptions\";\n// Usage\nexport type {\n BatchResult as UsageBatchResult,\n TrackModelTokensParams,\n TrackParams,\n TrackUsageParams,\n UsageEvent,\n UsageEventProperty,\n} from \"./resources/usage\";\nexport type {\n WebhookData,\n WebhookEvent,\n WebhookPayload,\n} from \"./resources/webhooks\";\n// Webhooks\nexport { Webhooks } from \"./resources/webhooks\";\n// Type exports\nexport type {\n ApiResponse,\n CommetConfig,\n CommetGeneratedTypes,\n Currency,\n CustomerID,\n Environment,\n EventID,\n GeneratedFeatureCode,\n GeneratedPlanCode,\n GeneratedSeatType,\n PaginatedList,\n PaginatedResponse,\n RequestOptions,\n} from \"./types/common\";\n// Error exports\nexport {\n CommetAPIError,\n CommetError,\n CommetValidationError,\n} from \"./types/common\";\n\n// Utility exports\nexport { isProduction, isSandbox } from \"./utils/environment\";\n\n// Default export\nimport { Commet } from \"./client\";\nexport default Commet;\n","import type { FeaturesResource } from \"./resources/features\";\nimport type { PortalResource } from \"./resources/portal\";\nimport type { SeatsResource } from \"./resources/seats\";\nimport type { SubscriptionsResource } from \"./resources/subscriptions\";\nimport type { UsageResource } from \"./resources/usage\";\nimport type { RequestOptions } from \"./types/common\";\n\n/**\n * Customer-scoped API context\n *\n * Provides a cleaner API where you don't have to pass externalId\n * on every call. All operations are scoped to a specific customer.\n *\n * @example\n * ```typescript\n * const customer = commet.customer(\"user_123\");\n *\n * // All operations are now scoped to this customer\n * const seats = await customer.features.get(\"team_members\");\n * await customer.seats.add(\"member\");\n * await customer.usage.track(\"api_call\");\n * ```\n */\nexport class CustomerContext {\n private readonly externalId: string;\n private readonly featuresResource: FeaturesResource;\n private readonly seatsResource: SeatsResource;\n private readonly usageResource: UsageResource;\n private readonly subscriptionsResource: SubscriptionsResource;\n private readonly portalResource: PortalResource;\n\n constructor(\n externalId: string,\n resources: {\n features: FeaturesResource;\n seats: SeatsResource;\n usage: UsageResource;\n subscriptions: SubscriptionsResource;\n portal: PortalResource;\n },\n ) {\n this.externalId = externalId;\n this.featuresResource = resources.features;\n this.seatsResource = resources.seats;\n this.usageResource = resources.usage;\n this.subscriptionsResource = resources.subscriptions;\n this.portalResource = resources.portal;\n }\n\n /**\n * Feature access methods - delegates to FeaturesResource\n */\n features = {\n get: (code: string, options?: RequestOptions) =>\n this.featuresResource.get({ code, externalId: this.externalId }, options),\n\n check: (code: string, options?: RequestOptions) =>\n this.featuresResource.check(\n { code, externalId: this.externalId },\n options,\n ),\n\n canUse: (code: string, options?: RequestOptions) =>\n this.featuresResource.canUse(\n { code, externalId: this.externalId },\n options,\n ),\n\n list: (options?: RequestOptions) =>\n this.featuresResource.list(this.externalId, options),\n };\n\n /**\n * Seat management methods - delegates to SeatsResource\n */\n seats = {\n add: (seatType: string, count = 1, options?: RequestOptions) =>\n this.seatsResource.add(\n { externalId: this.externalId, seatType, count },\n options,\n ),\n\n remove: (seatType: string, count = 1, options?: RequestOptions) =>\n this.seatsResource.remove(\n { externalId: this.externalId, seatType, count },\n options,\n ),\n\n set: (seatType: string, count: number, options?: RequestOptions) =>\n this.seatsResource.set(\n { externalId: this.externalId, seatType, count },\n options,\n ),\n\n getBalance: (seatType: string) =>\n this.seatsResource.getBalance({ externalId: this.externalId, seatType }),\n };\n\n /**\n * Usage tracking methods - delegates to UsageResource\n */\n usage = {\n track: (\n feature: string,\n value?: number,\n properties?: Record<string, string>,\n options?: RequestOptions,\n ) =>\n this.usageResource.track(\n { externalId: this.externalId, feature, value, properties },\n options,\n ),\n };\n\n /**\n * Subscription methods - delegates to SubscriptionsResource\n */\n subscription = {\n get: () => this.subscriptionsResource.get(this.externalId),\n };\n\n /**\n * Portal methods - delegates to PortalResource\n */\n portal = {\n getUrl: (options?: RequestOptions) =>\n this.portalResource.getUrl({ externalId: this.externalId }, options),\n };\n}\n","import type { ApiResponse } from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface CreditPack {\n id: string;\n name: string;\n description: string | null;\n credits: number;\n price: number;\n currency: string;\n}\n\n/**\n * Credit Packs resource for listing available credit packs\n */\nexport class CreditPacksResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * List all active credit packs\n *\n * @example\n * ```typescript\n * const packs = await commet.creditPacks.list();\n * console.log(packs.data); // [{ id: \"cp_xxx\", name: \"100 Credits\", ... }]\n * ```\n */\n async list(): Promise<ApiResponse<CreditPack[]>> {\n return this.httpClient.get(\"/credit-packs\");\n }\n}\n","import type {\n ApiResponse,\n ListParams as BaseListParams,\n CustomerID,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface Customer {\n id: CustomerID;\n organizationId: string;\n externalId?: string;\n fullName?: string;\n domain?: string;\n website?: string;\n billingEmail: string;\n timezone?: string;\n language?: string;\n industry?: string;\n employeeCount?: string;\n metadata?: Record<string, unknown>;\n isActive: boolean;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CustomerAddress {\n line1: string;\n line2?: string;\n city: string;\n state?: string;\n postalCode: string;\n country: string; // ISO-2\n}\n\nexport interface CreateParams {\n email: string; // billingEmail - the only required field\n externalId?: string;\n fullName?: string;\n domain?: string;\n website?: string;\n timezone?: string;\n language?: string;\n industry?: string;\n metadata?: Record<string, unknown>;\n address?: CustomerAddress;\n}\n\nexport interface UpdateParams {\n customerId: CustomerID;\n externalId?: string;\n email?: string;\n fullName?: string;\n domain?: string;\n website?: string;\n timezone?: string;\n language?: string;\n industry?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ListCustomersParams extends BaseListParams {\n externalId?: string;\n isActive?: boolean;\n search?: string;\n}\n\nexport interface BatchResult {\n successful: Customer[];\n failed: Array<{\n index: number;\n error: string;\n data: CreateParams;\n }>;\n}\n\n/**\n * Customers resource - Manage your customers\n */\nexport class CustomersResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Create a customer (idempotent with externalId)\n */\n async create(\n params: CreateParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<Customer>> {\n return this.httpClient.post(\n \"/customers\",\n {\n billingEmail: params.email,\n externalId: params.externalId,\n fullName: params.fullName,\n domain: params.domain,\n website: params.website,\n timezone: params.timezone,\n language: params.language,\n industry: params.industry,\n metadata: params.metadata,\n address: params.address,\n },\n options,\n );\n }\n\n /**\n * Create multiple customers in batch\n */\n async createBatch(\n params: { customers: CreateParams[] },\n options?: RequestOptions,\n ): Promise<ApiResponse<BatchResult>> {\n const customers = params.customers.map((c) => ({\n billingEmail: c.email,\n externalId: c.externalId,\n fullName: c.fullName,\n domain: c.domain,\n website: c.website,\n timezone: c.timezone,\n language: c.language,\n industry: c.industry,\n metadata: c.metadata,\n address: c.address,\n }));\n return this.httpClient.post(\"/customers/batch\", { customers }, options);\n }\n\n /**\n * Get a customer by ID\n */\n async get(customerId: CustomerID): Promise<ApiResponse<Customer>> {\n return this.httpClient.get(`/customers/${customerId}`);\n }\n\n /**\n * Update a customer\n */\n async update(\n params: UpdateParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<Customer>> {\n return this.httpClient.put(\n `/customers/${params.customerId}`,\n {\n billingEmail: params.email,\n externalId: params.externalId,\n fullName: params.fullName,\n domain: params.domain,\n website: params.website,\n timezone: params.timezone,\n language: params.language,\n industry: params.industry,\n metadata: params.metadata,\n },\n options,\n );\n }\n\n /**\n * List customers with optional filters\n */\n async list(params?: ListCustomersParams): Promise<ApiResponse<Customer[]>> {\n return this.httpClient.get(\"/customers\", params as Record<string, unknown>);\n }\n\n /**\n * Archive a customer\n */\n async archive(\n customerId: CustomerID,\n options?: RequestOptions,\n ): Promise<ApiResponse<Customer>> {\n return this.httpClient.put(\n `/customers/${customerId}`,\n { isActive: false },\n options,\n );\n }\n}\n","import type {\n ApiResponse,\n GeneratedFeatureCode,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface FeatureParams {\n externalId: string;\n code: GeneratedFeatureCode;\n}\n\nexport type GetFeatureParams = FeatureParams;\nexport type CheckFeatureParams = FeatureParams;\nexport type CanUseFeatureParams = FeatureParams;\n\nexport interface FeatureAccess {\n code: string;\n name: string;\n type: \"boolean\" | \"metered\" | \"seats\";\n allowed: boolean;\n // For boolean features\n enabled?: boolean;\n // For metered/seats features\n current?: number;\n included?: number;\n remaining?: number;\n overage?: number;\n overageUnitPrice?: number;\n unlimited?: boolean;\n overageEnabled?: boolean;\n}\n\nexport interface CanUseResult {\n allowed: boolean;\n willBeCharged: boolean;\n reason?: string;\n}\n\nexport interface CheckResult {\n allowed: boolean;\n}\n\n/**\n * Features resource for checking feature access and usage\n *\n * Provides a clean API to check if a customer can use a feature\n * without having to manually parse subscription data.\n */\nexport class FeaturesResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Get detailed feature access/usage for a customer\n *\n * @example\n * ```typescript\n * const seats = await commet.features.get({ code: \"team_members\", externalId: \"user_123\" });\n * console.log(seats.current, seats.included, seats.remaining);\n * ```\n */\n async get(\n params: GetFeatureParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<FeatureAccess>> {\n const { code, externalId } = params;\n\n return this.httpClient.get(\n `/features/${code}`,\n { externalId: externalId },\n options,\n );\n }\n\n /**\n * Check if a boolean feature is enabled for a customer\n *\n * @example\n * ```typescript\n * const { allowed } = await commet.features.check({\n * code: \"custom_branding\",\n * externalId: \"user_123\"\n * });\n * if (!allowed) redirect(\"/upgrade\");\n * ```\n */\n async check(\n params: CheckFeatureParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<CheckResult>> {\n const { code, externalId } = params;\n\n const result = await this.httpClient.get<FeatureAccess>(\n `/features/${code}`,\n { externalId: externalId },\n options,\n );\n\n if (!result.success || !result.data) {\n return {\n success: false,\n data: { allowed: false },\n message: result.message,\n };\n }\n\n return {\n success: true,\n data: { allowed: result.data.allowed },\n message: result.message,\n };\n }\n\n /**\n * Check if customer can use one more unit of a feature\n *\n * Returns whether the customer can add one more (allowed)\n * and whether they'll be charged extra (willBeCharged).\n *\n * @example\n * ```typescript\n * const { allowed, willBeCharged } = await commet.features.canUse({\n * code: \"team_members\",\n * externalId: \"user_123\"\n * });\n *\n * if (!allowed) {\n * return { error: \"Upgrade to add more members\" };\n * }\n *\n * if (willBeCharged) {\n * // Show confirmation: \"This will cost $10/month extra\"\n * }\n * ```\n */\n async canUse(\n params: CanUseFeatureParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<CanUseResult>> {\n const { code, externalId } = params;\n\n return this.httpClient.get(\n `/features/${code}`,\n { externalId: externalId, action: \"canUse\" },\n options,\n );\n }\n\n /**\n * List all features for a customer's active subscription\n *\n * @example\n * ```typescript\n * const features = await commet.features.list({ externalId: \"user_123\" });\n * for (const feature of features) {\n * console.log(feature.code, feature.allowed);\n * }\n * ```\n */\n async list(\n externalId: string,\n options?: RequestOptions,\n ): Promise<ApiResponse<FeatureAccess[]>> {\n return this.httpClient.get(\"/features\", { externalId }, options);\n }\n}\n","import type {\n ApiResponse,\n GeneratedPlanCode,\n ListParams,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport type PlanID = `plan_${string}`;\nexport type BillingInterval = \"monthly\" | \"quarterly\" | \"yearly\";\nexport type FeatureType = \"boolean\" | \"metered\" | \"seats\";\n\nexport interface PlanPrice {\n billingInterval: BillingInterval;\n price: number; // in cents\n isDefault: boolean;\n trialDays: number;\n}\n\nexport interface PlanFeature {\n code: string;\n name: string;\n type: FeatureType;\n unitName: string | null;\n enabled?: boolean;\n includedAmount?: number;\n unlimited?: boolean;\n overageEnabled?: boolean;\n overageUnitPrice?: number;\n}\n\nexport interface Plan {\n id: PlanID;\n code: string;\n name: string;\n description: string | null;\n isPublic: boolean;\n isFree: boolean;\n isDefault: boolean;\n sortOrder: number;\n prices: PlanPrice[];\n features: PlanFeature[];\n createdAt: string;\n}\n\nexport interface PlanDetailPrice {\n billingInterval: BillingInterval;\n price: number;\n isDefault: boolean;\n trialDays: number;\n introOffer: {\n enabled: boolean;\n discountType: \"percentage\" | \"amount\" | null;\n discountValue: number | null;\n durationCycles: number | null;\n } | null;\n}\n\nexport interface PlanDetailFeature extends PlanFeature {\n overage: {\n enabled: boolean;\n model: \"per_unit\" | \"tiered\" | null;\n unitPrice: number | null;\n } | null;\n}\n\nexport interface PlanDetail {\n id: PlanID;\n code: string;\n name: string;\n description: string | null;\n isPublic: boolean;\n isDefault: boolean;\n sortOrder: number;\n prices: PlanDetailPrice[];\n features: PlanDetailFeature[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ListPlansParams extends ListParams {\n includePrivate?: boolean;\n}\n\n/**\n * Plans resource for listing available plans\n */\nexport class PlansResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * List all available plans\n *\n * @example\n * ```typescript\n * // List public plans\n * const plans = await commet.plans.list();\n *\n * // Include private plans\n * const allPlans = await commet.plans.list({ includePrivate: true });\n * ```\n */\n async list(params?: ListPlansParams): Promise<ApiResponse<Plan[]>> {\n return this.httpClient.get(\"/plans\", params);\n }\n\n /**\n * Get a specific plan by code\n *\n * @example\n * ```typescript\n * const plan = await commet.plans.get('pro');\n * console.log(plan.data.name); // \"Pro\"\n * console.log(plan.data.prices); // [{ billingInterval: 'monthly', price: 9900 }]\n * ```\n */\n async get(planCode: GeneratedPlanCode): Promise<ApiResponse<PlanDetail>> {\n return this.httpClient.get(`/plans/${planCode}`);\n }\n}\n","import type { ApiResponse, CustomerID, RequestOptions } from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface PortalAccess {\n success: boolean;\n message: string;\n portalUrl: string;\n}\n\ninterface GetUrlByCustomerId {\n customerId: CustomerID;\n email?: never;\n externalId?: never;\n}\n\ninterface GetUrlByExternalId {\n externalId: string;\n email?: never;\n customerId?: never;\n}\n\ninterface GetUrlByEmail {\n email: string;\n customerId?: never;\n externalId?: never;\n}\n\nexport type GetUrlParams =\n | GetUrlByCustomerId\n | GetUrlByExternalId\n | GetUrlByEmail;\n\n/**\n * Portal resource - Generate customer portal access\n */\nexport class PortalResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Get a portal URL\n *\n * @example\n * ```typescript\n * const portal = await commet.portal.getUrl({ externalId: 'user_123' });\n * ```\n */\n async getUrl(\n params: GetUrlParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<PortalAccess>> {\n return this.httpClient.post(\"/portal/request-access\", params, options);\n }\n}\n","import type {\n ApiResponse,\n CustomerID,\n GeneratedSeatType,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface SeatEvent {\n id: string;\n organizationId: string;\n customerId: CustomerID;\n seatType: GeneratedSeatType;\n eventType: \"add\" | \"remove\" | \"set\";\n quantity: number;\n previousBalance?: number;\n newBalance: number;\n ts: string;\n createdAt: string;\n}\n\nexport interface SeatBalance {\n current: number;\n asOf: string;\n}\n\nexport interface AddParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n count: number;\n}\n\nexport interface RemoveParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n count: number;\n}\n\nexport interface SetParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n count: number;\n}\n\nexport interface SetAllParams {\n customerId?: CustomerID;\n externalId?: string;\n seats: Record<string, number>;\n}\n\nexport interface GetBalanceParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n}\n\nexport interface GetAllBalancesParams {\n customerId?: CustomerID;\n externalId?: string;\n}\n\n/**\n * Seats resource - Manage seat-based licenses\n */\nexport class SeatsResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Add seats\n *\n * @example\n * ```typescript\n * await commet.seats.add({\n * externalId: 'user_123',\n * seatType: 'editor',\n * count: 5\n * });\n * ```\n */\n async add(\n params: AddParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent>> {\n return this.httpClient.post(\"/seats\", params, options);\n }\n\n /**\n * Remove seats\n *\n * @example\n * ```typescript\n * await commet.seats.remove({\n * externalId: 'user_123',\n * seatType: 'editor',\n * count: 2\n * });\n * ```\n */\n async remove(\n params: RemoveParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent>> {\n return this.httpClient.delete(\"/seats\", params, options);\n }\n\n /**\n * Set seats to a specific count\n *\n * @example\n * ```typescript\n * await commet.seats.set({\n * externalId: 'user_123',\n * seatType: 'editor',\n * count: 10\n * });\n * ```\n */\n async set(\n params: SetParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent>> {\n return this.httpClient.put(\"/seats\", params, options);\n }\n\n /**\n * Set all seat types\n *\n * @example\n * ```typescript\n * await commet.seats.setAll({\n * externalId: 'user_123',\n * seats: { editor: 10, viewer: 50 }\n * });\n * ```\n */\n async setAll(\n params: SetAllParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent[]>> {\n return this.httpClient.put(\"/seats/bulk\", params, options);\n }\n\n /**\n * Get balance for a seat type\n *\n * @example\n * ```typescript\n * const balance = await commet.seats.getBalance({\n * externalId: 'user_123',\n * seatType: 'editor'\n * });\n * ```\n */\n async getBalance(\n params: GetBalanceParams,\n ): Promise<ApiResponse<SeatBalance>> {\n const { customerId, externalId, seatType } = params;\n\n return this.httpClient.get(\"/seats/balance\", {\n customerId: customerId,\n externalId: externalId,\n seatType: seatType,\n });\n }\n\n /**\n * Get all seat balances\n *\n * @example\n * ```typescript\n * const balances = await commet.seats.getAllBalances({\n * externalId: 'user_123'\n * });\n * ```\n */\n async getAllBalances(\n params: GetAllBalancesParams,\n ): Promise<ApiResponse<Record<string, SeatBalance>>> {\n const { customerId, externalId } = params;\n\n return this.httpClient.get(\"/seats/balances\", {\n customerId: customerId,\n externalId: externalId,\n });\n }\n}\n","import type {\n ApiResponse,\n GeneratedPlanCode,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\nimport type { BillingInterval } from \"./plans\";\n\nexport type SubscriptionStatus =\n | \"draft\"\n | \"pending_payment\"\n | \"trialing\"\n | \"active\"\n | \"paused\"\n | \"past_due\"\n | \"canceled\"\n | \"expired\";\n\nexport interface FeatureSummary {\n code: string;\n name: string;\n type: \"boolean\" | \"metered\" | \"seats\";\n enabled?: boolean;\n usage?: {\n current: number;\n included: number;\n overage: number;\n overageUnitPrice?: number;\n };\n}\n\nexport interface ActiveSubscription {\n id: string;\n customerId: string;\n plan: {\n id: string;\n name: string;\n basePrice: number;\n billingInterval: BillingInterval | null;\n };\n name: string;\n description: string | null;\n status: SubscriptionStatus;\n trialEndsAt: string | null;\n currentPeriod: {\n start: string;\n end: string;\n daysRemaining: number;\n };\n features: FeatureSummary[];\n startDate: string;\n endDate: string | null;\n billingDayOfMonth: number;\n nextBillingDate: string;\n checkoutUrl: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CreatedSubscription {\n id: string;\n customerId: string;\n externalId: string;\n planId: string;\n planName: string;\n name: string;\n status: SubscriptionStatus;\n billingInterval: BillingInterval | null;\n trialEndsAt: string | null;\n startDate: string;\n endDate: string | null;\n currentPeriodStart: string | null;\n currentPeriodEnd: string | null;\n billingDayOfMonth: number;\n checkoutUrl: string | null;\n createdAt: string;\n updatedAt: string;\n introOfferEndsAt: string | null;\n introOfferDiscountType: \"percentage\" | \"amount\" | null;\n introOfferDiscountValue: number | null;\n}\n\nexport interface Subscription {\n id: string;\n customerId: string;\n planId: string;\n planName: string;\n name: string;\n description?: string;\n status: SubscriptionStatus;\n billingInterval: BillingInterval;\n trialEndsAt?: string;\n startDate: string;\n endDate?: string;\n currentPeriodStart?: string;\n currentPeriodEnd?: string;\n billingDayOfMonth: number;\n checkoutUrl?: string;\n createdAt: string;\n updatedAt: string;\n}\n\n// Customer identifier: mutually exclusive customerId or externalId\ntype CustomerIdentifier =\n | { customerId: string; externalId?: never }\n | { customerId?: never; externalId: string };\n\n// Plan identifier: use planCode (with autocomplete) or planId (legacy)\ntype PlanIdentifier =\n | { planCode: GeneratedPlanCode; planId?: never }\n | { planCode?: never; planId: string };\n\nexport type CreateSubscriptionParams = CustomerIdentifier &\n PlanIdentifier & {\n billingInterval?: BillingInterval;\n initialSeats?: Record<string, number>;\n skipTrial?: boolean;\n name?: string;\n startDate?: string;\n successUrl?: string;\n };\n\nexport interface CancelParams {\n subscriptionId: string;\n reason?: string;\n immediate?: boolean;\n}\n\n/**\n * Subscription resource for managing subscriptions (plan-first model)\n *\n * Each customer can only have ONE active subscription at a time.\n */\nexport class SubscriptionsResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Create a subscription with a plan\n *\n * @example\n * ```typescript\n * await commet.subscriptions.create({\n * externalId: 'user_123',\n * planCode: 'pro', // autocomplete works after `commet pull`\n * billingInterval: 'yearly',\n * initialSeats: { editor: 5 }\n * });\n * ```\n */\n async create(\n params: CreateSubscriptionParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<CreatedSubscription>> {\n return this.httpClient.post(\"/subscriptions\", params, options);\n }\n\n /**\n * Get the active subscription for a customer\n *\n * @example\n * ```typescript\n * const sub = await commet.subscriptions.get('user_123');\n * ```\n */\n async get(\n externalId: string,\n ): Promise<ApiResponse<ActiveSubscription | null>> {\n return this.httpClient.get(\"/subscriptions/active\", { externalId });\n }\n\n /**\n * Cancel a subscription\n *\n * @example\n * ```typescript\n * await commet.subscriptions.cancel({\n * subscriptionId: 'sub_xxx',\n * reason: 'switched_to_competitor'\n * });\n * ```\n */\n async cancel(\n params: CancelParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<Subscription>> {\n return this.httpClient.post(\n `/subscriptions/${params.subscriptionId}/cancel`,\n params || {},\n options,\n );\n }\n}\n","import type {\n ApiResponse,\n CustomerID,\n EventID,\n GeneratedFeatureCode,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface UsageEvent {\n id: EventID;\n organizationId: string;\n customerId: CustomerID;\n feature: string;\n idempotencyKey?: string;\n ts: string;\n properties?: UsageEventProperty[];\n createdAt: string;\n}\n\nexport interface UsageEventProperty {\n id: string;\n usageEventId: EventID;\n property: string;\n value: string;\n createdAt: string;\n}\n\nexport interface BatchResult<T> {\n successful: T[];\n failed: Array<{\n index: number;\n error: string;\n data: TrackParams;\n }>;\n}\n\ninterface TrackBaseParams {\n feature: GeneratedFeatureCode;\n customerId?: CustomerID;\n externalId?: string;\n idempotencyKey?: string;\n timestamp?: string;\n properties?: Record<string, string>;\n}\n\nexport interface TrackUsageParams extends TrackBaseParams {\n value?: number;\n model?: never;\n}\n\nexport interface TrackModelTokensParams extends TrackBaseParams {\n model: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n value?: never;\n}\n\nexport type TrackParams = TrackUsageParams | TrackModelTokensParams;\n\nexport class UsageResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n async track(\n params: TrackParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<UsageEvent>> {\n const eventData: Record<string, unknown> = {\n feature: params.feature,\n customerId: params.customerId,\n externalId: params.externalId,\n idempotencyKey: params.idempotencyKey,\n timestamp: params.timestamp || new Date().toISOString(),\n properties: params.properties\n ? Object.entries(params.properties).map(([property, value]) => ({\n property,\n value,\n }))\n : undefined,\n };\n\n if (\"model\" in params && params.model) {\n eventData.model = params.model;\n eventData.inputTokens = params.inputTokens;\n eventData.outputTokens = params.outputTokens;\n if (params.cacheReadTokens) {\n eventData.cacheReadTokens = params.cacheReadTokens;\n }\n if (params.cacheWriteTokens) {\n eventData.cacheWriteTokens = params.cacheWriteTokens;\n }\n } else {\n eventData.value = (params as TrackUsageParams).value;\n }\n\n return this.httpClient.post(\"/usage/events\", eventData, options);\n }\n\n async trackBatch(\n params: { events: TrackParams[] },\n options?: RequestOptions,\n ): Promise<ApiResponse<BatchResult<UsageEvent>>> {\n const events = params.events.map((event) => {\n const eventData: Record<string, unknown> = {\n feature: event.feature,\n customerId: event.customerId,\n externalId: event.externalId,\n idempotencyKey: event.idempotencyKey,\n timestamp: event.timestamp || new Date().toISOString(),\n properties: event.properties\n ? Object.entries(event.properties).map(([property, value]) => ({\n property,\n value,\n }))\n : undefined,\n };\n\n if (\"model\" in event && event.model) {\n eventData.model = event.model;\n eventData.inputTokens = event.inputTokens;\n eventData.outputTokens = event.outputTokens;\n if (event.cacheReadTokens) {\n eventData.cacheReadTokens = event.cacheReadTokens;\n }\n if (event.cacheWriteTokens) {\n eventData.cacheWriteTokens = event.cacheWriteTokens;\n }\n } else {\n eventData.value = (event as TrackUsageParams).value;\n }\n\n return eventData;\n });\n\n return this.httpClient.post(\"/usage/events/batch\", { events }, options);\n }\n}\n","import crypto from \"node:crypto\";\n\n/**\n * Webhook payload structure from Commet\n */\nexport interface WebhookPayload {\n event: WebhookEvent;\n timestamp: string;\n organizationId: string;\n data: WebhookData;\n}\n\n/**\n * Webhook data structure (subscription-related fields)\n */\nexport interface WebhookData {\n id?: string;\n publicId?: string;\n subscriptionId?: string;\n customerId?: string;\n externalId?: string;\n status?: string;\n name?: string;\n canceledAt?: string;\n [key: string]: unknown;\n}\n\n/**\n * Supported webhook events\n */\nexport type WebhookEvent =\n | \"subscription.created\"\n | \"subscription.activated\"\n | \"subscription.canceled\"\n | \"subscription.updated\";\n\nexport interface VerifyParams {\n payload: string;\n signature: string | null;\n secret: string;\n}\n\nexport interface GenerateSignatureParams {\n payload: string;\n secret: string;\n}\n\nexport interface VerifyAndParseParams {\n rawBody: string;\n signature: string | null;\n secret: string;\n}\n\n/**\n * Webhooks resource for signature verification\n */\nexport class Webhooks {\n /**\n * Verify HMAC-SHA256 webhook signature\n *\n * Use this method to verify that webhooks are authentically from Commet.\n * The signature is included in the `X-Commet-Signature` header.\n *\n * @param payload - Raw request body as string (IMPORTANT: Do not parse JSON first)\n * @param signature - Value from X-Commet-Signature header\n * @param secret - Your webhook secret from Commet dashboard\n * @returns true if signature is valid, false otherwise\n *\n * @example\n * ```typescript\n * // Next.js API route example\n * export async function POST(request: Request) {\n * const rawBody = await request.text();\n * const signature = request.headers.get('x-commet-signature');\n *\n * const isValid = commet.webhooks.verify(\n * rawBody,\n * signature,\n * process.env.COMMET_WEBHOOK_SECRET\n * );\n *\n * if (!isValid) {\n * return new Response('Invalid signature', { status: 401 });\n * }\n *\n * const payload = JSON.parse(rawBody);\n * // Handle webhook event...\n * }\n * ```\n */\n verify(params: VerifyParams): boolean {\n const { payload, signature, secret } = params;\n\n if (!signature || !secret || !payload) {\n return false;\n }\n\n try {\n const expectedSignature = this.generateSignature({ payload, secret });\n\n // Use timing-safe comparison to prevent timing attacks\n return crypto.timingSafeEqual(\n Buffer.from(signature, \"hex\"),\n Buffer.from(expectedSignature, \"hex\"),\n );\n } catch (_error) {\n // timingSafeEqual throws if lengths don't match\n return false;\n }\n }\n\n /**\n * Generate HMAC-SHA256 signature (internal use)\n * @internal\n */\n private generateSignature(params: GenerateSignatureParams): string {\n const { payload, secret } = params;\n return crypto.createHmac(\"sha256\", secret).update(payload).digest(\"hex\");\n }\n\n /**\n * Parse and verify webhook payload in one step\n *\n * @example\n * ```typescript\n * const payload = commet.webhooks.verifyAndParse({\n * rawBody,\n * signature,\n * secret: process.env.COMMET_WEBHOOK_SECRET\n * });\n *\n * if (!payload) {\n * return new Response('Invalid signature', { status: 401 });\n * }\n *\n * // payload is typed and validated\n * if (payload.event === 'subscription.activated') {\n * // Handle activation...\n * }\n * ```\n */\n verifyAndParse(params: VerifyAndParseParams): WebhookPayload | null {\n const { rawBody, signature, secret } = params;\n\n if (!this.verify({ payload: rawBody, signature, secret })) {\n return null;\n }\n\n try {\n return JSON.parse(params.rawBody) as WebhookPayload;\n } catch {\n return null;\n }\n }\n}\n","export type Environment = \"sandbox\" | \"production\";\n\nexport type CommetConfig = {\n apiKey: string;\n environment?: Environment;\n debug?: boolean;\n timeout?: number;\n retries?: number;\n};\n\n// API Response types\nexport interface ApiResponse<T = unknown> {\n success: boolean;\n data?: T;\n code?: string;\n message?: string;\n details?: unknown;\n // Pagination fields (optional, included for list endpoints)\n hasMore?: boolean;\n nextCursor?: string;\n}\n\nexport interface PaginatedResponse<T> {\n data: T[];\n hasMore: boolean;\n nextCursor?: string;\n totalCount?: number;\n}\n\nexport interface PaginatedList<T> extends PaginatedResponse<T> {\n next(): Promise<PaginatedList<T>>;\n all(): Promise<T[]>;\n}\n\n// Error types\nexport class CommetError extends Error {\n constructor(\n message: string,\n public code?: string,\n public statusCode?: number,\n public details?: unknown,\n ) {\n super(message);\n this.name = \"CommetError\";\n }\n}\n\nexport class CommetAPIError extends CommetError {\n constructor(\n message: string,\n public statusCode: number,\n public code?: string,\n public details?: unknown,\n ) {\n super(message, code, statusCode, details);\n this.name = \"CommetAPIError\";\n }\n}\n\nexport class CommetValidationError extends CommetError {\n constructor(\n message: string,\n public validationErrors: Record<string, string[]>,\n ) {\n super(message);\n this.name = \"CommetValidationError\";\n }\n}\n\nexport type CustomerID = `cus_${string}`;\nexport type AgreementID = `agr_${string}`;\nexport type InvoiceID = `inv_${string}`;\nexport type PhaseID = `phs_${string}`;\nexport type ItemID = `itm_${string}`;\nexport type ProductID = `prd_${string}`;\nexport type EventID = `evt_${string}`;\nexport type WebhookID = `wh_${string}`;\n\n// Currency enum\nexport type Currency =\n | \"USD\"\n | \"EUR\"\n | \"GBP\"\n | \"CAD\"\n | \"AUD\"\n | \"JPY\"\n | \"ARS\"\n | \"BRL\"\n | \"MXN\"\n | \"CLP\";\n\n// Common parameters\nexport interface ListParams extends Record<string, unknown> {\n limit?: number;\n cursor?: string;\n startDate?: string;\n endDate?: string;\n}\n\nexport interface RetrieveOptions {\n expand?: string[];\n}\n\n// Request options\nexport interface RequestOptions {\n idempotencyKey?: string;\n timeout?: number;\n}\n\n/**\n * Generated types interface - augmented by CLI after 'commet pull'\n *\n * This interface gets filled by module augmentation when you run `commet pull`.\n * The CLI generates a .commet/types.d.ts file that augments this interface with your\n * organization's specific feature codes, seat types, and plan codes.\n *\n * @example\n * // After running `commet pull`, TypeScript will automatically know your types:\n * await commet.usage.track({\n * feature: 'api_calls', // Autocomplete works!\n * externalId: 'user_123'\n * });\n */\n\n// biome-ignore lint/suspicious/noEmptyInterface: augmented by CLI-generated .commet/types.d.ts\nexport interface CommetGeneratedTypes {}\n\nexport type GeneratedSeatType = CommetGeneratedTypes extends {\n seatType: infer T;\n}\n ? T\n : string;\n\nexport type GeneratedPlanCode = CommetGeneratedTypes extends {\n planCode: infer T;\n}\n ? T\n : string;\n\nexport type GeneratedFeatureCode = CommetGeneratedTypes extends {\n featureCode: infer T;\n}\n ? T\n : string;\n","import type {\n ApiResponse,\n CommetConfig,\n Environment,\n RequestOptions,\n} from \"../types/common\";\nimport { CommetAPIError, CommetValidationError } from \"../types/common\";\n\nexport interface RetryConfig {\n maxRetries: number;\n baseDelay: number;\n maxDelay: number;\n retryableStatusCodes: number[];\n}\n\nconst DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 3,\n baseDelay: 1000, // 1s\n maxDelay: 8000, // 8s\n retryableStatusCodes: [408, 429, 500, 502, 503, 504],\n};\n\nexport class CommetHTTPClient {\n private config: CommetConfig;\n private environment: Environment;\n private retryConfig: RetryConfig;\n\n constructor(config: CommetConfig, environment: Environment) {\n this.config = config;\n this.environment = environment;\n this.retryConfig = {\n ...DEFAULT_RETRY_CONFIG,\n maxRetries: config.retries ?? DEFAULT_RETRY_CONFIG.maxRetries,\n };\n }\n\n async get<T = unknown>(\n endpoint: string,\n params?: Record<string, unknown>,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"GET\", endpoint, undefined, options, params);\n }\n\n async post<T = unknown>(\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"POST\", endpoint, data, options);\n }\n\n async put<T = unknown>(\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"PUT\", endpoint, data, options);\n }\n\n async delete<T = unknown>(\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"DELETE\", endpoint, data, options);\n }\n\n /**\n * Core request method with retry logic\n */\n private async request<T = unknown>(\n method: string,\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n params?: Record<string, unknown>,\n ): Promise<ApiResponse<T>> {\n const url = this.buildURL(endpoint, params);\n return this.executeRequest(method, url, data, options);\n }\n\n /**\n * Execute real API request with retry logic\n */\n private async executeRequest<T = unknown>(\n method: string,\n url: string,\n data?: unknown,\n options?: RequestOptions,\n attempt = 1,\n ): Promise<ApiResponse<T>> {\n try {\n const headers: Record<string, string> = {\n \"x-api-key\": this.config.apiKey,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"commet/0.1.0\",\n };\n\n if (options?.idempotencyKey) {\n headers[\"Idempotency-Key\"] = options.idempotencyKey;\n } else if (method === \"POST\" && data) {\n headers[\"Idempotency-Key\"] = this.generateIdempotencyKey();\n }\n\n const requestConfig: RequestInit = {\n method,\n headers,\n signal: AbortSignal.timeout(\n options?.timeout ?? this.config.timeout ?? 30000,\n ),\n };\n\n if (data) {\n requestConfig.body = JSON.stringify(data);\n }\n\n if (this.config.debug) {\n console.log(`[Commet SDK] ${method} ${url}`);\n if (data) {\n console.log(\"Request data:\", JSON.stringify(data, null, 2));\n }\n }\n\n const response = await fetch(url, requestConfig);\n\n if (this.config.debug) {\n console.log(\n `[Commet SDK] Response status: ${response.status} ${response.statusText}`,\n );\n }\n\n let responseData: unknown;\n let responseText: string;\n\n try {\n responseData = await response.json();\n responseText = \"\";\n } catch (_jsonError) {\n try {\n responseText = await response.text();\n } catch (_textError) {\n responseText = \"Failed to read response body\";\n }\n if (this.config.debug) {\n console.log(\n \"[Commet SDK] Failed to parse JSON response:\",\n responseText,\n );\n }\n\n // For 404 errors with invalid JSON, return a graceful response\n // This handles cases like HTML error pages or empty responses\n if (response.status === 404) {\n return {\n success: false,\n code: \"not_found\",\n message: \"Resource not found\",\n } as ApiResponse<T>;\n }\n\n throw new CommetAPIError(\n `Invalid JSON response: ${response.status} ${response.statusText}`,\n response.status,\n \"INVALID_JSON\",\n { responseText },\n );\n }\n\n if (!response.ok) {\n // Check if we should retry\n if (\n attempt <= this.retryConfig.maxRetries &&\n this.retryConfig.retryableStatusCodes.includes(response.status)\n ) {\n const delay = Math.min(\n this.retryConfig.baseDelay * 2 ** (attempt - 1),\n this.retryConfig.maxDelay,\n );\n\n if (this.config.debug) {\n console.log(\n `[Commet SDK] Retrying in ${delay}ms (attempt ${attempt}/${this.retryConfig.maxRetries})`,\n );\n }\n\n await this.sleep(delay);\n return this.executeRequest(method, url, data, options, attempt + 1);\n }\n\n // Log error response for debugging\n if (this.config.debug) {\n console.log(\n \"[Commet SDK] Error response:\",\n JSON.stringify(responseData, null, 2),\n );\n }\n\n // Type guard for error response\n const isErrorResponse = (\n data: unknown,\n ): data is {\n message?: string;\n code?: string;\n details?: unknown;\n } => {\n return typeof data === \"object\" && data !== null;\n };\n\n const errorData = isErrorResponse(responseData) ? responseData : {};\n\n // Handle validation errors (new normalized shape)\n if (\n errorData.code === \"validation_error\" &&\n Array.isArray(errorData.details)\n ) {\n const errors: Record<string, string[]> = {};\n for (const detail of errorData.details as Array<{\n field: string;\n message: string;\n }>) {\n if (!errors[detail.field]) errors[detail.field] = [];\n errors[detail.field].push(detail.message);\n }\n throw new CommetValidationError(\n errorData.message || \"Validation failed\",\n errors,\n );\n }\n\n throw new CommetAPIError(\n errorData.message || `Request failed with status ${response.status}`,\n response.status,\n errorData.code,\n errorData.details,\n );\n }\n\n if (this.config.debug) {\n console.log(\"[Commet SDK] Response:\", responseData);\n }\n\n return responseData as ApiResponse<T>;\n } catch (error) {\n // Handle network errors and timeouts\n if (error instanceof TypeError && error.message.includes(\"fetch\")) {\n if (attempt <= this.retryConfig.maxRetries) {\n const delay = Math.min(\n this.retryConfig.baseDelay * 2 ** (attempt - 1),\n this.retryConfig.maxDelay,\n );\n\n if (this.config.debug) {\n console.log(`[Commet SDK] Network error, retrying in ${delay}ms`);\n }\n\n await this.sleep(delay);\n return this.executeRequest(method, url, data, options, attempt + 1);\n }\n }\n\n throw error;\n }\n }\n\n /**\n * Get base URL based on environment\n */\n private getBaseURL(): string {\n return this.environment === \"production\"\n ? \"https://commet.co\"\n : \"https://sandbox.commet.co\";\n }\n\n /**\n * Build full URL from endpoint and params\n */\n private buildURL(endpoint: string, params?: Record<string, unknown>): string {\n const baseURL = this.getBaseURL();\n\n // Construct full path with /api prefix\n const normalizedEndpoint = endpoint.startsWith(\"/\")\n ? endpoint\n : `/${endpoint}`;\n const fullPath = `/api${normalizedEndpoint}`;\n\n // Debug logging\n if (this.config.debug) {\n console.log(\n `[Commet SDK] Building URL - baseURL: ${baseURL}, endpoint: ${endpoint}, fullPath: ${fullPath}`,\n );\n }\n\n const url = new URL(fullPath, baseURL);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value));\n }\n }\n }\n\n const finalUrl = url.toString();\n\n // Debug final URL\n if (this.config.debug) {\n console.log(`[Commet SDK] Final URL: ${finalUrl}`);\n }\n\n return finalUrl;\n }\n\n /**\n * Generate idempotency key\n */\n private generateIdempotencyKey(): string {\n // Generate UUID-like key for idempotency\n return `sdk_${Date.now()}_${Math.random().toString(36).substring(2)}`;\n }\n\n /**\n * Sleep for specified milliseconds\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { CustomerContext } from \"./customer\";\nimport { CreditPacksResource } from \"./resources/credit-packs\";\nimport { CustomersResource } from \"./resources/customers\";\nimport { FeaturesResource } from \"./resources/features\";\nimport { PlansResource } from \"./resources/plans\";\nimport { PortalResource } from \"./resources/portal\";\nimport { SeatsResource } from \"./resources/seats\";\nimport { SubscriptionsResource } from \"./resources/subscriptions\";\nimport { UsageResource } from \"./resources/usage\";\nimport { Webhooks } from \"./resources/webhooks\";\nimport type { CommetConfig, Environment } from \"./types/common\";\nimport { CommetHTTPClient } from \"./utils/http\";\n\n/**\n * Main Commet SDK client\n */\nexport class Commet {\n private httpClient: CommetHTTPClient;\n private environment: Environment;\n\n public readonly customers: CustomersResource;\n public readonly creditPacks: CreditPacksResource;\n public readonly plans: PlansResource;\n public readonly usage: UsageResource;\n public readonly seats: SeatsResource;\n public readonly subscriptions: SubscriptionsResource;\n public readonly portal: PortalResource;\n public readonly features: FeaturesResource;\n public readonly webhooks: Webhooks;\n\n constructor(config: CommetConfig) {\n if (!config.apiKey) {\n throw new Error(\"Commet SDK: API key is required\");\n }\n\n if (!config.apiKey.startsWith(\"ck_\")) {\n throw new Error(\n \"Commet SDK: Invalid API key format. Expected format: ck_xxx...\",\n );\n }\n\n // Default to sandbox for safety\n this.environment = config.environment || \"sandbox\";\n\n this.httpClient = new CommetHTTPClient(config, this.environment);\n this.customers = new CustomersResource(this.httpClient);\n this.creditPacks = new CreditPacksResource(this.httpClient);\n this.plans = new PlansResource(this.httpClient);\n this.usage = new UsageResource(this.httpClient);\n this.seats = new SeatsResource(this.httpClient);\n this.subscriptions = new SubscriptionsResource(this.httpClient);\n this.portal = new PortalResource(this.httpClient);\n this.features = new FeaturesResource(this.httpClient);\n this.webhooks = new Webhooks();\n\n if (config.debug) {\n console.log(`[Commet SDK] Initialized in ${this.environment} mode`);\n console.log(\"API Key:\", `${config.apiKey.substring(0, 12)}...`);\n const baseURL =\n this.environment === \"production\"\n ? \"https://commet.co\"\n : \"https://sandbox.commet.co\";\n console.log(\"Base URL:\", baseURL);\n }\n }\n\n /**\n * Create a customer-scoped context for cleaner API usage\n *\n * @example\n * ```typescript\n * const customer = commet.customer(\"user_123\");\n *\n * // All operations are now scoped to this customer\n * const seats = await customer.features.get(\"team_members\");\n * await customer.seats.add(\"member\");\n * await customer.usage.track(\"api_call\");\n * ```\n */\n customer(externalId: string): CustomerContext {\n return new CustomerContext(externalId, {\n features: this.features,\n seats: this.seats,\n usage: this.usage,\n subscriptions: this.subscriptions,\n portal: this.portal,\n });\n }\n\n getEnvironment(): Environment {\n return this.environment;\n }\n\n isSandbox(): boolean {\n return this.environment === \"sandbox\";\n }\n\n isProduction(): boolean {\n return this.environment === \"production\";\n }\n}\n","import type { Environment } from \"../types/common\";\n\n/**\n * Check if environment is sandbox\n */\nexport function isSandbox(environment: Environment): boolean {\n return environment === \"sandbox\";\n}\n\n/**\n * Check if environment is production\n */\nexport function isProduction(environment: Environment): boolean {\n return environment === \"production\";\n}\n"],"mappings":"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","names":["crypto","data"]}
|
package/dist/index.mjs
CHANGED
|
@@ -589,7 +589,7 @@ var Webhooks = class {
|
|
|
589
589
|
Buffer.from(signature, "hex"),
|
|
590
590
|
Buffer.from(expectedSignature, "hex")
|
|
591
591
|
);
|
|
592
|
-
} catch (
|
|
592
|
+
} catch (_error) {
|
|
593
593
|
return false;
|
|
594
594
|
}
|
|
595
595
|
}
|
|
@@ -741,10 +741,10 @@ var CommetHTTPClient = class {
|
|
|
741
741
|
try {
|
|
742
742
|
responseData = await response.json();
|
|
743
743
|
responseText = "";
|
|
744
|
-
} catch (
|
|
744
|
+
} catch (_jsonError) {
|
|
745
745
|
try {
|
|
746
746
|
responseText = await response.text();
|
|
747
|
-
} catch (
|
|
747
|
+
} catch (_textError) {
|
|
748
748
|
responseText = "Failed to read response body";
|
|
749
749
|
}
|
|
750
750
|
if (this.config.debug) {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/customer.ts","../src/resources/credit-packs.ts","../src/resources/customers.ts","../src/resources/features.ts","../src/resources/plans.ts","../src/resources/portal.ts","../src/resources/seats.ts","../src/resources/subscriptions.ts","../src/resources/usage.ts","../src/resources/webhooks.ts","../src/types/common.ts","../src/utils/http.ts","../src/client.ts","../src/utils/environment.ts","../src/index.ts"],"sourcesContent":["import type { FeaturesResource } from \"./resources/features\";\nimport type { PortalResource } from \"./resources/portal\";\nimport type { SeatsResource } from \"./resources/seats\";\nimport type { SubscriptionsResource } from \"./resources/subscriptions\";\nimport type { UsageResource } from \"./resources/usage\";\nimport type { RequestOptions } from \"./types/common\";\n\n/**\n * Customer-scoped API context\n *\n * Provides a cleaner API where you don't have to pass externalId\n * on every call. All operations are scoped to a specific customer.\n *\n * @example\n * ```typescript\n * const customer = commet.customer(\"user_123\");\n *\n * // All operations are now scoped to this customer\n * const seats = await customer.features.get(\"team_members\");\n * await customer.seats.add(\"member\");\n * await customer.usage.track(\"api_call\");\n * ```\n */\nexport class CustomerContext {\n private readonly externalId: string;\n private readonly featuresResource: FeaturesResource;\n private readonly seatsResource: SeatsResource;\n private readonly usageResource: UsageResource;\n private readonly subscriptionsResource: SubscriptionsResource;\n private readonly portalResource: PortalResource;\n\n constructor(\n externalId: string,\n resources: {\n features: FeaturesResource;\n seats: SeatsResource;\n usage: UsageResource;\n subscriptions: SubscriptionsResource;\n portal: PortalResource;\n },\n ) {\n this.externalId = externalId;\n this.featuresResource = resources.features;\n this.seatsResource = resources.seats;\n this.usageResource = resources.usage;\n this.subscriptionsResource = resources.subscriptions;\n this.portalResource = resources.portal;\n }\n\n /**\n * Feature access methods - delegates to FeaturesResource\n */\n features = {\n get: (code: string, options?: RequestOptions) =>\n this.featuresResource.get({ code, externalId: this.externalId }, options),\n\n check: (code: string, options?: RequestOptions) =>\n this.featuresResource.check(\n { code, externalId: this.externalId },\n options,\n ),\n\n canUse: (code: string, options?: RequestOptions) =>\n this.featuresResource.canUse(\n { code, externalId: this.externalId },\n options,\n ),\n\n list: (options?: RequestOptions) =>\n this.featuresResource.list(this.externalId, options),\n };\n\n /**\n * Seat management methods - delegates to SeatsResource\n */\n seats = {\n add: (seatType: string, count = 1, options?: RequestOptions) =>\n this.seatsResource.add(\n { externalId: this.externalId, seatType, count },\n options,\n ),\n\n remove: (seatType: string, count = 1, options?: RequestOptions) =>\n this.seatsResource.remove(\n { externalId: this.externalId, seatType, count },\n options,\n ),\n\n set: (seatType: string, count: number, options?: RequestOptions) =>\n this.seatsResource.set(\n { externalId: this.externalId, seatType, count },\n options,\n ),\n\n getBalance: (seatType: string) =>\n this.seatsResource.getBalance({ externalId: this.externalId, seatType }),\n };\n\n /**\n * Usage tracking methods - delegates to UsageResource\n */\n usage = {\n track: (\n feature: string,\n value?: number,\n properties?: Record<string, string>,\n options?: RequestOptions,\n ) =>\n this.usageResource.track(\n { externalId: this.externalId, feature, value, properties },\n options,\n ),\n };\n\n /**\n * Subscription methods - delegates to SubscriptionsResource\n */\n subscription = {\n get: () => this.subscriptionsResource.get(this.externalId),\n };\n\n /**\n * Portal methods - delegates to PortalResource\n */\n portal = {\n getUrl: (options?: RequestOptions) =>\n this.portalResource.getUrl({ externalId: this.externalId }, options),\n };\n}\n","import type { ApiResponse } from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface CreditPack {\n id: string;\n name: string;\n description: string | null;\n credits: number;\n price: number;\n currency: string;\n}\n\n/**\n * Credit Packs resource for listing available credit packs\n */\nexport class CreditPacksResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * List all active credit packs\n *\n * @example\n * ```typescript\n * const packs = await commet.creditPacks.list();\n * console.log(packs.data); // [{ id: \"cp_xxx\", name: \"100 Credits\", ... }]\n * ```\n */\n async list(): Promise<ApiResponse<CreditPack[]>> {\n return this.httpClient.get(\"/credit-packs\");\n }\n}\n","import type {\n ApiResponse,\n ListParams as BaseListParams,\n CustomerID,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface Customer {\n id: CustomerID;\n organizationId: string;\n externalId?: string;\n fullName?: string;\n domain?: string;\n website?: string;\n billingEmail: string;\n timezone?: string;\n language?: string;\n industry?: string;\n employeeCount?: string;\n metadata?: Record<string, unknown>;\n isActive: boolean;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CustomerAddress {\n line1: string;\n line2?: string;\n city: string;\n state?: string;\n postalCode: string;\n country: string; // ISO-2\n}\n\nexport interface CreateParams {\n email: string; // billingEmail - the only required field\n externalId?: string;\n fullName?: string;\n domain?: string;\n website?: string;\n timezone?: string;\n language?: string;\n industry?: string;\n metadata?: Record<string, unknown>;\n address?: CustomerAddress;\n}\n\nexport interface UpdateParams {\n customerId: CustomerID;\n externalId?: string;\n email?: string;\n fullName?: string;\n domain?: string;\n website?: string;\n timezone?: string;\n language?: string;\n industry?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ListCustomersParams extends BaseListParams {\n externalId?: string;\n isActive?: boolean;\n search?: string;\n}\n\nexport interface BatchResult {\n successful: Customer[];\n failed: Array<{\n index: number;\n error: string;\n data: CreateParams;\n }>;\n}\n\n/**\n * Customers resource - Manage your customers\n */\nexport class CustomersResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Create a customer (idempotent with externalId)\n */\n async create(\n params: CreateParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<Customer>> {\n return this.httpClient.post(\n \"/customers\",\n {\n billingEmail: params.email,\n externalId: params.externalId,\n fullName: params.fullName,\n domain: params.domain,\n website: params.website,\n timezone: params.timezone,\n language: params.language,\n industry: params.industry,\n metadata: params.metadata,\n address: params.address,\n },\n options,\n );\n }\n\n /**\n * Create multiple customers in batch\n */\n async createBatch(\n params: { customers: CreateParams[] },\n options?: RequestOptions,\n ): Promise<ApiResponse<BatchResult>> {\n const customers = params.customers.map((c) => ({\n billingEmail: c.email,\n externalId: c.externalId,\n fullName: c.fullName,\n domain: c.domain,\n website: c.website,\n timezone: c.timezone,\n language: c.language,\n industry: c.industry,\n metadata: c.metadata,\n address: c.address,\n }));\n return this.httpClient.post(\"/customers/batch\", { customers }, options);\n }\n\n /**\n * Get a customer by ID\n */\n async get(customerId: CustomerID): Promise<ApiResponse<Customer>> {\n return this.httpClient.get(`/customers/${customerId}`);\n }\n\n /**\n * Update a customer\n */\n async update(\n params: UpdateParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<Customer>> {\n return this.httpClient.put(\n `/customers/${params.customerId}`,\n {\n billingEmail: params.email,\n externalId: params.externalId,\n fullName: params.fullName,\n domain: params.domain,\n website: params.website,\n timezone: params.timezone,\n language: params.language,\n industry: params.industry,\n metadata: params.metadata,\n },\n options,\n );\n }\n\n /**\n * List customers with optional filters\n */\n async list(params?: ListCustomersParams): Promise<ApiResponse<Customer[]>> {\n return this.httpClient.get(\"/customers\", params as Record<string, unknown>);\n }\n\n /**\n * Archive a customer\n */\n async archive(\n customerId: CustomerID,\n options?: RequestOptions,\n ): Promise<ApiResponse<Customer>> {\n return this.httpClient.put(\n `/customers/${customerId}`,\n { isActive: false },\n options,\n );\n }\n}\n","import type {\n ApiResponse,\n GeneratedFeatureCode,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface FeatureParams {\n externalId: string;\n code: GeneratedFeatureCode;\n}\n\nexport type GetFeatureParams = FeatureParams;\nexport type CheckFeatureParams = FeatureParams;\nexport type CanUseFeatureParams = FeatureParams;\n\nexport interface FeatureAccess {\n code: string;\n name: string;\n type: \"boolean\" | \"metered\" | \"seats\";\n allowed: boolean;\n // For boolean features\n enabled?: boolean;\n // For metered/seats features\n current?: number;\n included?: number;\n remaining?: number;\n overage?: number;\n overageUnitPrice?: number;\n unlimited?: boolean;\n overageEnabled?: boolean;\n}\n\nexport interface CanUseResult {\n allowed: boolean;\n willBeCharged: boolean;\n reason?: string;\n}\n\nexport interface CheckResult {\n allowed: boolean;\n}\n\n/**\n * Features resource for checking feature access and usage\n *\n * Provides a clean API to check if a customer can use a feature\n * without having to manually parse subscription data.\n */\nexport class FeaturesResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Get detailed feature access/usage for a customer\n *\n * @example\n * ```typescript\n * const seats = await commet.features.get({ code: \"team_members\", externalId: \"user_123\" });\n * console.log(seats.current, seats.included, seats.remaining);\n * ```\n */\n async get(\n params: GetFeatureParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<FeatureAccess>> {\n const { code, externalId } = params;\n\n return this.httpClient.get(\n `/features/${code}`,\n { externalId: externalId },\n options,\n );\n }\n\n /**\n * Check if a boolean feature is enabled for a customer\n *\n * @example\n * ```typescript\n * const { allowed } = await commet.features.check({\n * code: \"custom_branding\",\n * externalId: \"user_123\"\n * });\n * if (!allowed) redirect(\"/upgrade\");\n * ```\n */\n async check(\n params: CheckFeatureParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<CheckResult>> {\n const { code, externalId } = params;\n\n const result = await this.httpClient.get<FeatureAccess>(\n `/features/${code}`,\n { externalId: externalId },\n options,\n );\n\n if (!result.success || !result.data) {\n return {\n success: false,\n data: { allowed: false },\n message: result.message,\n };\n }\n\n return {\n success: true,\n data: { allowed: result.data.allowed },\n message: result.message,\n };\n }\n\n /**\n * Check if customer can use one more unit of a feature\n *\n * Returns whether the customer can add one more (allowed)\n * and whether they'll be charged extra (willBeCharged).\n *\n * @example\n * ```typescript\n * const { allowed, willBeCharged } = await commet.features.canUse({\n * code: \"team_members\",\n * externalId: \"user_123\"\n * });\n *\n * if (!allowed) {\n * return { error: \"Upgrade to add more members\" };\n * }\n *\n * if (willBeCharged) {\n * // Show confirmation: \"This will cost $10/month extra\"\n * }\n * ```\n */\n async canUse(\n params: CanUseFeatureParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<CanUseResult>> {\n const { code, externalId } = params;\n\n return this.httpClient.get(\n `/features/${code}`,\n { externalId: externalId, action: \"canUse\" },\n options,\n );\n }\n\n /**\n * List all features for a customer's active subscription\n *\n * @example\n * ```typescript\n * const features = await commet.features.list({ externalId: \"user_123\" });\n * for (const feature of features) {\n * console.log(feature.code, feature.allowed);\n * }\n * ```\n */\n async list(\n externalId: string,\n options?: RequestOptions,\n ): Promise<ApiResponse<FeatureAccess[]>> {\n return this.httpClient.get(\"/features\", { externalId }, options);\n }\n}\n","import type {\n ApiResponse,\n GeneratedPlanCode,\n ListParams,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport type PlanID = `plan_${string}`;\nexport type BillingInterval = \"monthly\" | \"quarterly\" | \"yearly\";\nexport type FeatureType = \"boolean\" | \"metered\" | \"seats\";\n\nexport interface PlanPrice {\n billingInterval: BillingInterval;\n price: number; // in cents\n isDefault: boolean;\n trialDays: number;\n}\n\nexport interface PlanFeature {\n code: string;\n name: string;\n type: FeatureType;\n unitName: string | null;\n enabled?: boolean;\n includedAmount?: number;\n unlimited?: boolean;\n overageEnabled?: boolean;\n overageUnitPrice?: number;\n}\n\nexport interface Plan {\n id: PlanID;\n code: string;\n name: string;\n description: string | null;\n isPublic: boolean;\n isFree: boolean;\n isDefault: boolean;\n sortOrder: number;\n prices: PlanPrice[];\n features: PlanFeature[];\n createdAt: string;\n}\n\nexport interface PlanDetailPrice {\n billingInterval: BillingInterval;\n price: number;\n isDefault: boolean;\n trialDays: number;\n introOffer: {\n enabled: boolean;\n discountType: \"percentage\" | \"amount\" | null;\n discountValue: number | null;\n durationCycles: number | null;\n } | null;\n}\n\nexport interface PlanDetailFeature extends PlanFeature {\n overage: {\n enabled: boolean;\n model: \"per_unit\" | \"tiered\" | null;\n unitPrice: number | null;\n } | null;\n}\n\nexport interface PlanDetail {\n id: PlanID;\n code: string;\n name: string;\n description: string | null;\n isPublic: boolean;\n isDefault: boolean;\n sortOrder: number;\n prices: PlanDetailPrice[];\n features: PlanDetailFeature[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ListPlansParams extends ListParams {\n includePrivate?: boolean;\n}\n\n/**\n * Plans resource for listing available plans\n */\nexport class PlansResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * List all available plans\n *\n * @example\n * ```typescript\n * // List public plans\n * const plans = await commet.plans.list();\n *\n * // Include private plans\n * const allPlans = await commet.plans.list({ includePrivate: true });\n * ```\n */\n async list(params?: ListPlansParams): Promise<ApiResponse<Plan[]>> {\n return this.httpClient.get(\"/plans\", params);\n }\n\n /**\n * Get a specific plan by code\n *\n * @example\n * ```typescript\n * const plan = await commet.plans.get('pro');\n * console.log(plan.data.name); // \"Pro\"\n * console.log(plan.data.prices); // [{ billingInterval: 'monthly', price: 9900 }]\n * ```\n */\n async get(planCode: GeneratedPlanCode): Promise<ApiResponse<PlanDetail>> {\n return this.httpClient.get(`/plans/${planCode}`);\n }\n}\n","import type { ApiResponse, CustomerID, RequestOptions } from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface PortalAccess {\n success: boolean;\n message: string;\n portalUrl: string;\n}\n\ninterface GetUrlByCustomerId {\n customerId: CustomerID;\n email?: never;\n externalId?: never;\n}\n\ninterface GetUrlByExternalId {\n externalId: string;\n email?: never;\n customerId?: never;\n}\n\ninterface GetUrlByEmail {\n email: string;\n customerId?: never;\n externalId?: never;\n}\n\nexport type GetUrlParams =\n | GetUrlByCustomerId\n | GetUrlByExternalId\n | GetUrlByEmail;\n\n/**\n * Portal resource - Generate customer portal access\n */\nexport class PortalResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Get a portal URL\n *\n * @example\n * ```typescript\n * const portal = await commet.portal.getUrl({ externalId: 'user_123' });\n * ```\n */\n async getUrl(\n params: GetUrlParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<PortalAccess>> {\n return this.httpClient.post(\"/portal/request-access\", params, options);\n }\n}\n","import type {\n ApiResponse,\n CustomerID,\n GeneratedSeatType,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface SeatEvent {\n id: string;\n organizationId: string;\n customerId: CustomerID;\n seatType: GeneratedSeatType;\n eventType: \"add\" | \"remove\" | \"set\";\n quantity: number;\n previousBalance?: number;\n newBalance: number;\n ts: string;\n createdAt: string;\n}\n\nexport interface SeatBalance {\n current: number;\n asOf: string;\n}\n\nexport interface AddParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n count: number;\n}\n\nexport interface RemoveParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n count: number;\n}\n\nexport interface SetParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n count: number;\n}\n\nexport interface SetAllParams {\n customerId?: CustomerID;\n externalId?: string;\n seats: Record<string, number>;\n}\n\nexport interface GetBalanceParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n}\n\nexport interface GetAllBalancesParams {\n customerId?: CustomerID;\n externalId?: string;\n}\n\n/**\n * Seats resource - Manage seat-based licenses\n */\nexport class SeatsResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Add seats\n *\n * @example\n * ```typescript\n * await commet.seats.add({\n * externalId: 'user_123',\n * seatType: 'editor',\n * count: 5\n * });\n * ```\n */\n async add(\n params: AddParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent>> {\n return this.httpClient.post(\"/seats\", params, options);\n }\n\n /**\n * Remove seats\n *\n * @example\n * ```typescript\n * await commet.seats.remove({\n * externalId: 'user_123',\n * seatType: 'editor',\n * count: 2\n * });\n * ```\n */\n async remove(\n params: RemoveParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent>> {\n return this.httpClient.delete(\"/seats\", params, options);\n }\n\n /**\n * Set seats to a specific count\n *\n * @example\n * ```typescript\n * await commet.seats.set({\n * externalId: 'user_123',\n * seatType: 'editor',\n * count: 10\n * });\n * ```\n */\n async set(\n params: SetParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent>> {\n return this.httpClient.put(\"/seats\", params, options);\n }\n\n /**\n * Set all seat types\n *\n * @example\n * ```typescript\n * await commet.seats.setAll({\n * externalId: 'user_123',\n * seats: { editor: 10, viewer: 50 }\n * });\n * ```\n */\n async setAll(\n params: SetAllParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent[]>> {\n return this.httpClient.put(\"/seats/bulk\", params, options);\n }\n\n /**\n * Get balance for a seat type\n *\n * @example\n * ```typescript\n * const balance = await commet.seats.getBalance({\n * externalId: 'user_123',\n * seatType: 'editor'\n * });\n * ```\n */\n async getBalance(\n params: GetBalanceParams,\n ): Promise<ApiResponse<SeatBalance>> {\n const { customerId, externalId, seatType } = params;\n\n return this.httpClient.get(\"/seats/balance\", {\n customerId: customerId,\n externalId: externalId,\n seatType: seatType,\n });\n }\n\n /**\n * Get all seat balances\n *\n * @example\n * ```typescript\n * const balances = await commet.seats.getAllBalances({\n * externalId: 'user_123'\n * });\n * ```\n */\n async getAllBalances(\n params: GetAllBalancesParams,\n ): Promise<ApiResponse<Record<string, SeatBalance>>> {\n const { customerId, externalId } = params;\n\n return this.httpClient.get(\"/seats/balances\", {\n customerId: customerId,\n externalId: externalId,\n });\n }\n}\n","import type {\n ApiResponse,\n GeneratedPlanCode,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\nimport type { BillingInterval } from \"./plans\";\n\nexport type SubscriptionStatus =\n | \"draft\"\n | \"pending_payment\"\n | \"trialing\"\n | \"active\"\n | \"paused\"\n | \"past_due\"\n | \"canceled\"\n | \"expired\";\n\nexport interface FeatureSummary {\n code: string;\n name: string;\n type: \"boolean\" | \"metered\" | \"seats\";\n enabled?: boolean;\n usage?: {\n current: number;\n included: number;\n overage: number;\n overageUnitPrice?: number;\n };\n}\n\nexport interface ActiveSubscription {\n id: string;\n customerId: string;\n plan: {\n id: string;\n name: string;\n basePrice: number;\n billingInterval: BillingInterval | null;\n };\n name: string;\n description: string | null;\n status: SubscriptionStatus;\n trialEndsAt: string | null;\n currentPeriod: {\n start: string;\n end: string;\n daysRemaining: number;\n };\n features: FeatureSummary[];\n startDate: string;\n endDate: string | null;\n billingDayOfMonth: number;\n nextBillingDate: string;\n checkoutUrl: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CreatedSubscription {\n id: string;\n customerId: string;\n externalId: string;\n planId: string;\n planName: string;\n name: string;\n status: SubscriptionStatus;\n billingInterval: BillingInterval | null;\n trialEndsAt: string | null;\n startDate: string;\n endDate: string | null;\n currentPeriodStart: string | null;\n currentPeriodEnd: string | null;\n billingDayOfMonth: number;\n checkoutUrl: string | null;\n createdAt: string;\n updatedAt: string;\n introOfferEndsAt: string | null;\n introOfferDiscountType: \"percentage\" | \"amount\" | null;\n introOfferDiscountValue: number | null;\n}\n\nexport interface Subscription {\n id: string;\n customerId: string;\n planId: string;\n planName: string;\n name: string;\n description?: string;\n status: SubscriptionStatus;\n billingInterval: BillingInterval;\n trialEndsAt?: string;\n startDate: string;\n endDate?: string;\n currentPeriodStart?: string;\n currentPeriodEnd?: string;\n billingDayOfMonth: number;\n checkoutUrl?: string;\n createdAt: string;\n updatedAt: string;\n}\n\n// Customer identifier: mutually exclusive customerId or externalId\ntype CustomerIdentifier =\n | { customerId: string; externalId?: never }\n | { customerId?: never; externalId: string };\n\n// Plan identifier: use planCode (with autocomplete) or planId (legacy)\ntype PlanIdentifier =\n | { planCode: GeneratedPlanCode; planId?: never }\n | { planCode?: never; planId: string };\n\nexport type CreateSubscriptionParams = CustomerIdentifier &\n PlanIdentifier & {\n billingInterval?: BillingInterval;\n initialSeats?: Record<string, number>;\n skipTrial?: boolean;\n name?: string;\n startDate?: string;\n successUrl?: string;\n };\n\nexport interface CancelParams {\n subscriptionId: string;\n reason?: string;\n immediate?: boolean;\n}\n\n/**\n * Subscription resource for managing subscriptions (plan-first model)\n *\n * Each customer can only have ONE active subscription at a time.\n */\nexport class SubscriptionsResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Create a subscription with a plan\n *\n * @example\n * ```typescript\n * await commet.subscriptions.create({\n * externalId: 'user_123',\n * planCode: 'pro', // autocomplete works after `commet pull`\n * billingInterval: 'yearly',\n * initialSeats: { editor: 5 }\n * });\n * ```\n */\n async create(\n params: CreateSubscriptionParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<CreatedSubscription>> {\n return this.httpClient.post(\"/subscriptions\", params, options);\n }\n\n /**\n * Get the active subscription for a customer\n *\n * @example\n * ```typescript\n * const sub = await commet.subscriptions.get('user_123');\n * ```\n */\n async get(\n externalId: string,\n ): Promise<ApiResponse<ActiveSubscription | null>> {\n return this.httpClient.get(\"/subscriptions/active\", { externalId });\n }\n\n /**\n * Cancel a subscription\n *\n * @example\n * ```typescript\n * await commet.subscriptions.cancel({\n * subscriptionId: 'sub_xxx',\n * reason: 'switched_to_competitor'\n * });\n * ```\n */\n async cancel(\n params: CancelParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<Subscription>> {\n return this.httpClient.post(\n `/subscriptions/${params.subscriptionId}/cancel`,\n params || {},\n options,\n );\n }\n}\n","import type {\n ApiResponse,\n CustomerID,\n EventID,\n GeneratedFeatureCode,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface UsageEvent {\n id: EventID;\n organizationId: string;\n customerId: CustomerID;\n feature: string;\n idempotencyKey?: string;\n ts: string;\n properties?: UsageEventProperty[];\n createdAt: string;\n}\n\nexport interface UsageEventProperty {\n id: string;\n usageEventId: EventID;\n property: string;\n value: string;\n createdAt: string;\n}\n\nexport interface BatchResult<T> {\n successful: T[];\n failed: Array<{\n index: number;\n error: string;\n data: TrackParams;\n }>;\n}\n\ninterface TrackBaseParams {\n feature: GeneratedFeatureCode;\n customerId?: CustomerID;\n externalId?: string;\n idempotencyKey?: string;\n timestamp?: string;\n properties?: Record<string, string>;\n}\n\nexport interface TrackUsageParams extends TrackBaseParams {\n value?: number;\n model?: never;\n}\n\nexport interface TrackModelTokensParams extends TrackBaseParams {\n model: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n value?: never;\n}\n\nexport type TrackParams = TrackUsageParams | TrackModelTokensParams;\n\nexport class UsageResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n async track(\n params: TrackParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<UsageEvent>> {\n const eventData: Record<string, unknown> = {\n feature: params.feature,\n customerId: params.customerId,\n externalId: params.externalId,\n idempotencyKey: params.idempotencyKey,\n timestamp: params.timestamp || new Date().toISOString(),\n properties: params.properties\n ? Object.entries(params.properties).map(([property, value]) => ({\n property,\n value,\n }))\n : undefined,\n };\n\n if (\"model\" in params && params.model) {\n eventData.model = params.model;\n eventData.inputTokens = params.inputTokens;\n eventData.outputTokens = params.outputTokens;\n if (params.cacheReadTokens) {\n eventData.cacheReadTokens = params.cacheReadTokens;\n }\n if (params.cacheWriteTokens) {\n eventData.cacheWriteTokens = params.cacheWriteTokens;\n }\n } else {\n eventData.value = (params as TrackUsageParams).value;\n }\n\n return this.httpClient.post(\"/usage/events\", eventData, options);\n }\n\n async trackBatch(\n params: { events: TrackParams[] },\n options?: RequestOptions,\n ): Promise<ApiResponse<BatchResult<UsageEvent>>> {\n const events = params.events.map((event) => {\n const eventData: Record<string, unknown> = {\n feature: event.feature,\n customerId: event.customerId,\n externalId: event.externalId,\n idempotencyKey: event.idempotencyKey,\n timestamp: event.timestamp || new Date().toISOString(),\n properties: event.properties\n ? Object.entries(event.properties).map(([property, value]) => ({\n property,\n value,\n }))\n : undefined,\n };\n\n if (\"model\" in event && event.model) {\n eventData.model = event.model;\n eventData.inputTokens = event.inputTokens;\n eventData.outputTokens = event.outputTokens;\n if (event.cacheReadTokens) {\n eventData.cacheReadTokens = event.cacheReadTokens;\n }\n if (event.cacheWriteTokens) {\n eventData.cacheWriteTokens = event.cacheWriteTokens;\n }\n } else {\n eventData.value = (event as TrackUsageParams).value;\n }\n\n return eventData;\n });\n\n return this.httpClient.post(\"/usage/events/batch\", { events }, options);\n }\n}\n","import crypto from \"node:crypto\";\n\n/**\n * Webhook payload structure from Commet\n */\nexport interface WebhookPayload {\n event: WebhookEvent;\n timestamp: string;\n organizationId: string;\n data: WebhookData;\n}\n\n/**\n * Webhook data structure (subscription-related fields)\n */\nexport interface WebhookData {\n id?: string;\n publicId?: string;\n subscriptionId?: string;\n customerId?: string;\n externalId?: string;\n status?: string;\n name?: string;\n canceledAt?: string;\n [key: string]: unknown;\n}\n\n/**\n * Supported webhook events\n */\nexport type WebhookEvent =\n | \"subscription.created\"\n | \"subscription.activated\"\n | \"subscription.canceled\"\n | \"subscription.updated\";\n\nexport interface VerifyParams {\n payload: string;\n signature: string | null;\n secret: string;\n}\n\nexport interface GenerateSignatureParams {\n payload: string;\n secret: string;\n}\n\nexport interface VerifyAndParseParams {\n rawBody: string;\n signature: string | null;\n secret: string;\n}\n\n/**\n * Webhooks resource for signature verification\n */\nexport class Webhooks {\n /**\n * Verify HMAC-SHA256 webhook signature\n *\n * Use this method to verify that webhooks are authentically from Commet.\n * The signature is included in the `X-Commet-Signature` header.\n *\n * @param payload - Raw request body as string (IMPORTANT: Do not parse JSON first)\n * @param signature - Value from X-Commet-Signature header\n * @param secret - Your webhook secret from Commet dashboard\n * @returns true if signature is valid, false otherwise\n *\n * @example\n * ```typescript\n * // Next.js API route example\n * export async function POST(request: Request) {\n * const rawBody = await request.text();\n * const signature = request.headers.get('x-commet-signature');\n *\n * const isValid = commet.webhooks.verify(\n * rawBody,\n * signature,\n * process.env.COMMET_WEBHOOK_SECRET\n * );\n *\n * if (!isValid) {\n * return new Response('Invalid signature', { status: 401 });\n * }\n *\n * const payload = JSON.parse(rawBody);\n * // Handle webhook event...\n * }\n * ```\n */\n verify(params: VerifyParams): boolean {\n const { payload, signature, secret } = params;\n\n if (!signature || !secret || !payload) {\n return false;\n }\n\n try {\n const expectedSignature = this.generateSignature({ payload, secret });\n\n // Use timing-safe comparison to prevent timing attacks\n return crypto.timingSafeEqual(\n Buffer.from(signature, \"hex\"),\n Buffer.from(expectedSignature, \"hex\"),\n );\n } catch (error) {\n // timingSafeEqual throws if lengths don't match\n return false;\n }\n }\n\n /**\n * Generate HMAC-SHA256 signature (internal use)\n * @internal\n */\n private generateSignature(params: GenerateSignatureParams): string {\n const { payload, secret } = params;\n return crypto.createHmac(\"sha256\", secret).update(payload).digest(\"hex\");\n }\n\n /**\n * Parse and verify webhook payload in one step\n *\n * @example\n * ```typescript\n * const payload = commet.webhooks.verifyAndParse({\n * rawBody,\n * signature,\n * secret: process.env.COMMET_WEBHOOK_SECRET\n * });\n *\n * if (!payload) {\n * return new Response('Invalid signature', { status: 401 });\n * }\n *\n * // payload is typed and validated\n * if (payload.event === 'subscription.activated') {\n * // Handle activation...\n * }\n * ```\n */\n verifyAndParse(params: VerifyAndParseParams): WebhookPayload | null {\n const { rawBody, signature, secret } = params;\n\n if (!this.verify({ payload: rawBody, signature, secret })) {\n return null;\n }\n\n try {\n return JSON.parse(params.rawBody) as WebhookPayload;\n } catch {\n return null;\n }\n }\n}\n","export type Environment = \"sandbox\" | \"production\";\n\nexport type CommetConfig = {\n apiKey: string;\n environment?: Environment;\n debug?: boolean;\n timeout?: number;\n retries?: number;\n};\n\n// API Response types\nexport interface ApiResponse<T = unknown> {\n success: boolean;\n data?: T;\n code?: string;\n message?: string;\n details?: unknown;\n // Pagination fields (optional, included for list endpoints)\n hasMore?: boolean;\n nextCursor?: string;\n}\n\nexport interface PaginatedResponse<T> {\n data: T[];\n hasMore: boolean;\n nextCursor?: string;\n totalCount?: number;\n}\n\nexport interface PaginatedList<T> extends PaginatedResponse<T> {\n next(): Promise<PaginatedList<T>>;\n all(): Promise<T[]>;\n}\n\n// Error types\nexport class CommetError extends Error {\n constructor(\n message: string,\n public code?: string,\n public statusCode?: number,\n public details?: unknown,\n ) {\n super(message);\n this.name = \"CommetError\";\n }\n}\n\nexport class CommetAPIError extends CommetError {\n constructor(\n message: string,\n public statusCode: number,\n public code?: string,\n public details?: unknown,\n ) {\n super(message, code, statusCode, details);\n this.name = \"CommetAPIError\";\n }\n}\n\nexport class CommetValidationError extends CommetError {\n constructor(\n message: string,\n public validationErrors: Record<string, string[]>,\n ) {\n super(message);\n this.name = \"CommetValidationError\";\n }\n}\n\nexport type CustomerID = `cus_${string}`;\nexport type AgreementID = `agr_${string}`;\nexport type InvoiceID = `inv_${string}`;\nexport type PhaseID = `phs_${string}`;\nexport type ItemID = `itm_${string}`;\nexport type ProductID = `prd_${string}`;\nexport type EventID = `evt_${string}`;\nexport type WebhookID = `wh_${string}`;\n\n// Currency enum\nexport type Currency =\n | \"USD\"\n | \"EUR\"\n | \"GBP\"\n | \"CAD\"\n | \"AUD\"\n | \"JPY\"\n | \"ARS\"\n | \"BRL\"\n | \"MXN\"\n | \"CLP\";\n\n// Common parameters\nexport interface ListParams extends Record<string, unknown> {\n limit?: number;\n cursor?: string;\n startDate?: string;\n endDate?: string;\n}\n\nexport interface RetrieveOptions {\n expand?: string[];\n}\n\n// Request options\nexport interface RequestOptions {\n idempotencyKey?: string;\n timeout?: number;\n}\n\n/**\n * Generated types interface - augmented by CLI after 'commet pull'\n *\n * This interface gets filled by module augmentation when you run `commet pull`.\n * The CLI generates a .commet/types.d.ts file that augments this interface with your\n * organization's specific feature codes, seat types, and plan codes.\n *\n * @example\n * // After running `commet pull`, TypeScript will automatically know your types:\n * await commet.usage.track({\n * feature: 'api_calls', // Autocomplete works!\n * externalId: 'user_123'\n * });\n */\n\n// biome-ignore lint/suspicious/noEmptyInterface: augmented by CLI-generated .commet/types.d.ts\nexport interface CommetGeneratedTypes {}\n\nexport type GeneratedSeatType = CommetGeneratedTypes extends {\n seatType: infer T;\n}\n ? T\n : string;\n\nexport type GeneratedPlanCode = CommetGeneratedTypes extends {\n planCode: infer T;\n}\n ? T\n : string;\n\nexport type GeneratedFeatureCode = CommetGeneratedTypes extends {\n featureCode: infer T;\n}\n ? T\n : string;\n","import type {\n ApiResponse,\n CommetConfig,\n Environment,\n RequestOptions,\n} from \"../types/common\";\nimport { CommetAPIError, CommetValidationError } from \"../types/common\";\n\nexport interface RetryConfig {\n maxRetries: number;\n baseDelay: number;\n maxDelay: number;\n retryableStatusCodes: number[];\n}\n\nconst DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 3,\n baseDelay: 1000, // 1s\n maxDelay: 8000, // 8s\n retryableStatusCodes: [408, 429, 500, 502, 503, 504],\n};\n\nexport class CommetHTTPClient {\n private config: CommetConfig;\n private environment: Environment;\n private retryConfig: RetryConfig;\n\n constructor(config: CommetConfig, environment: Environment) {\n this.config = config;\n this.environment = environment;\n this.retryConfig = {\n ...DEFAULT_RETRY_CONFIG,\n maxRetries: config.retries ?? DEFAULT_RETRY_CONFIG.maxRetries,\n };\n }\n\n async get<T = unknown>(\n endpoint: string,\n params?: Record<string, unknown>,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"GET\", endpoint, undefined, options, params);\n }\n\n async post<T = unknown>(\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"POST\", endpoint, data, options);\n }\n\n async put<T = unknown>(\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"PUT\", endpoint, data, options);\n }\n\n async delete<T = unknown>(\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"DELETE\", endpoint, data, options);\n }\n\n /**\n * Core request method with retry logic\n */\n private async request<T = unknown>(\n method: string,\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n params?: Record<string, unknown>,\n ): Promise<ApiResponse<T>> {\n const url = this.buildURL(endpoint, params);\n return this.executeRequest(method, url, data, options);\n }\n\n /**\n * Execute real API request with retry logic\n */\n private async executeRequest<T = unknown>(\n method: string,\n url: string,\n data?: unknown,\n options?: RequestOptions,\n attempt = 1,\n ): Promise<ApiResponse<T>> {\n try {\n const headers: Record<string, string> = {\n \"x-api-key\": this.config.apiKey,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"commet/0.1.0\",\n };\n\n if (options?.idempotencyKey) {\n headers[\"Idempotency-Key\"] = options.idempotencyKey;\n } else if (method === \"POST\" && data) {\n headers[\"Idempotency-Key\"] = this.generateIdempotencyKey();\n }\n\n const requestConfig: RequestInit = {\n method,\n headers,\n signal: AbortSignal.timeout(\n options?.timeout ?? this.config.timeout ?? 30000,\n ),\n };\n\n if (data) {\n requestConfig.body = JSON.stringify(data);\n }\n\n if (this.config.debug) {\n console.log(`[Commet SDK] ${method} ${url}`);\n if (data) {\n console.log(\"Request data:\", JSON.stringify(data, null, 2));\n }\n }\n\n const response = await fetch(url, requestConfig);\n\n if (this.config.debug) {\n console.log(\n `[Commet SDK] Response status: ${response.status} ${response.statusText}`,\n );\n }\n\n let responseData: unknown;\n let responseText: string;\n\n try {\n responseData = await response.json();\n responseText = \"\";\n } catch (jsonError) {\n try {\n responseText = await response.text();\n } catch (textError) {\n responseText = \"Failed to read response body\";\n }\n if (this.config.debug) {\n console.log(\n \"[Commet SDK] Failed to parse JSON response:\",\n responseText,\n );\n }\n\n // For 404 errors with invalid JSON, return a graceful response\n // This handles cases like HTML error pages or empty responses\n if (response.status === 404) {\n return {\n success: false,\n code: \"not_found\",\n message: \"Resource not found\",\n } as ApiResponse<T>;\n }\n\n throw new CommetAPIError(\n `Invalid JSON response: ${response.status} ${response.statusText}`,\n response.status,\n \"INVALID_JSON\",\n { responseText },\n );\n }\n\n if (!response.ok) {\n // Check if we should retry\n if (\n attempt <= this.retryConfig.maxRetries &&\n this.retryConfig.retryableStatusCodes.includes(response.status)\n ) {\n const delay = Math.min(\n this.retryConfig.baseDelay * 2 ** (attempt - 1),\n this.retryConfig.maxDelay,\n );\n\n if (this.config.debug) {\n console.log(\n `[Commet SDK] Retrying in ${delay}ms (attempt ${attempt}/${this.retryConfig.maxRetries})`,\n );\n }\n\n await this.sleep(delay);\n return this.executeRequest(method, url, data, options, attempt + 1);\n }\n\n // Log error response for debugging\n if (this.config.debug) {\n console.log(\n \"[Commet SDK] Error response:\",\n JSON.stringify(responseData, null, 2),\n );\n }\n\n // Type guard for error response\n const isErrorResponse = (\n data: unknown,\n ): data is {\n message?: string;\n code?: string;\n details?: unknown;\n } => {\n return typeof data === \"object\" && data !== null;\n };\n\n const errorData = isErrorResponse(responseData) ? responseData : {};\n\n // Handle validation errors (new normalized shape)\n if (\n errorData.code === \"validation_error\" &&\n Array.isArray(errorData.details)\n ) {\n const errors: Record<string, string[]> = {};\n for (const detail of errorData.details as Array<{\n field: string;\n message: string;\n }>) {\n if (!errors[detail.field]) errors[detail.field] = [];\n errors[detail.field].push(detail.message);\n }\n throw new CommetValidationError(\n errorData.message || \"Validation failed\",\n errors,\n );\n }\n\n throw new CommetAPIError(\n errorData.message || `Request failed with status ${response.status}`,\n response.status,\n errorData.code,\n errorData.details,\n );\n }\n\n if (this.config.debug) {\n console.log(\"[Commet SDK] Response:\", responseData);\n }\n\n return responseData as ApiResponse<T>;\n } catch (error) {\n // Handle network errors and timeouts\n if (error instanceof TypeError && error.message.includes(\"fetch\")) {\n if (attempt <= this.retryConfig.maxRetries) {\n const delay = Math.min(\n this.retryConfig.baseDelay * 2 ** (attempt - 1),\n this.retryConfig.maxDelay,\n );\n\n if (this.config.debug) {\n console.log(`[Commet SDK] Network error, retrying in ${delay}ms`);\n }\n\n await this.sleep(delay);\n return this.executeRequest(method, url, data, options, attempt + 1);\n }\n }\n\n throw error;\n }\n }\n\n /**\n * Get base URL based on environment\n */\n private getBaseURL(): string {\n return this.environment === \"production\"\n ? \"https://commet.co\"\n : \"https://sandbox.commet.co\";\n }\n\n /**\n * Build full URL from endpoint and params\n */\n private buildURL(endpoint: string, params?: Record<string, unknown>): string {\n const baseURL = this.getBaseURL();\n\n // Construct full path with /api prefix\n const normalizedEndpoint = endpoint.startsWith(\"/\")\n ? endpoint\n : `/${endpoint}`;\n const fullPath = `/api${normalizedEndpoint}`;\n\n // Debug logging\n if (this.config.debug) {\n console.log(\n `[Commet SDK] Building URL - baseURL: ${baseURL}, endpoint: ${endpoint}, fullPath: ${fullPath}`,\n );\n }\n\n const url = new URL(fullPath, baseURL);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value));\n }\n }\n }\n\n const finalUrl = url.toString();\n\n // Debug final URL\n if (this.config.debug) {\n console.log(`[Commet SDK] Final URL: ${finalUrl}`);\n }\n\n return finalUrl;\n }\n\n /**\n * Generate idempotency key\n */\n private generateIdempotencyKey(): string {\n // Generate UUID-like key for idempotency\n return `sdk_${Date.now()}_${Math.random().toString(36).substring(2)}`;\n }\n\n /**\n * Sleep for specified milliseconds\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { CustomerContext } from \"./customer\";\nimport { CreditPacksResource } from \"./resources/credit-packs\";\nimport { CustomersResource } from \"./resources/customers\";\nimport { FeaturesResource } from \"./resources/features\";\nimport { PlansResource } from \"./resources/plans\";\nimport { PortalResource } from \"./resources/portal\";\nimport { SeatsResource } from \"./resources/seats\";\nimport { SubscriptionsResource } from \"./resources/subscriptions\";\nimport { UsageResource } from \"./resources/usage\";\nimport { Webhooks } from \"./resources/webhooks\";\nimport type { CommetConfig, Environment } from \"./types/common\";\nimport { CommetHTTPClient } from \"./utils/http\";\n\n/**\n * Main Commet SDK client\n */\nexport class Commet {\n private httpClient: CommetHTTPClient;\n private environment: Environment;\n\n public readonly customers: CustomersResource;\n public readonly creditPacks: CreditPacksResource;\n public readonly plans: PlansResource;\n public readonly usage: UsageResource;\n public readonly seats: SeatsResource;\n public readonly subscriptions: SubscriptionsResource;\n public readonly portal: PortalResource;\n public readonly features: FeaturesResource;\n public readonly webhooks: Webhooks;\n\n constructor(config: CommetConfig) {\n if (!config.apiKey) {\n throw new Error(\"Commet SDK: API key is required\");\n }\n\n if (!config.apiKey.startsWith(\"ck_\")) {\n throw new Error(\n \"Commet SDK: Invalid API key format. Expected format: ck_xxx...\",\n );\n }\n\n // Default to sandbox for safety\n this.environment = config.environment || \"sandbox\";\n\n this.httpClient = new CommetHTTPClient(config, this.environment);\n this.customers = new CustomersResource(this.httpClient);\n this.creditPacks = new CreditPacksResource(this.httpClient);\n this.plans = new PlansResource(this.httpClient);\n this.usage = new UsageResource(this.httpClient);\n this.seats = new SeatsResource(this.httpClient);\n this.subscriptions = new SubscriptionsResource(this.httpClient);\n this.portal = new PortalResource(this.httpClient);\n this.features = new FeaturesResource(this.httpClient);\n this.webhooks = new Webhooks();\n\n if (config.debug) {\n console.log(`[Commet SDK] Initialized in ${this.environment} mode`);\n console.log(\"API Key:\", `${config.apiKey.substring(0, 12)}...`);\n const baseURL =\n this.environment === \"production\"\n ? \"https://commet.co\"\n : \"https://sandbox.commet.co\";\n console.log(\"Base URL:\", baseURL);\n }\n }\n\n /**\n * Create a customer-scoped context for cleaner API usage\n *\n * @example\n * ```typescript\n * const customer = commet.customer(\"user_123\");\n *\n * // All operations are now scoped to this customer\n * const seats = await customer.features.get(\"team_members\");\n * await customer.seats.add(\"member\");\n * await customer.usage.track(\"api_call\");\n * ```\n */\n customer(externalId: string): CustomerContext {\n return new CustomerContext(externalId, {\n features: this.features,\n seats: this.seats,\n usage: this.usage,\n subscriptions: this.subscriptions,\n portal: this.portal,\n });\n }\n\n getEnvironment(): Environment {\n return this.environment;\n }\n\n isSandbox(): boolean {\n return this.environment === \"sandbox\";\n }\n\n isProduction(): boolean {\n return this.environment === \"production\";\n }\n}\n","import type { Environment } from \"../types/common\";\n\n/**\n * Check if environment is sandbox\n */\nexport function isSandbox(environment: Environment): boolean {\n return environment === \"sandbox\";\n}\n\n/**\n * Check if environment is production\n */\nexport function isProduction(environment: Environment): boolean {\n return environment === \"production\";\n}\n","/**\n * Commet SDK - Billing and usage tracking for SaaS\n */\nexport { Commet } from \"./client\";\nexport { CustomerContext } from \"./customer\";\n\n// Type exports\nexport type {\n CommetConfig,\n CommetGeneratedTypes,\n GeneratedSeatType,\n GeneratedPlanCode,\n GeneratedFeatureCode,\n Environment,\n ApiResponse,\n PaginatedResponse,\n PaginatedList,\n Currency,\n CustomerID,\n EventID,\n RequestOptions,\n} from \"./types/common\";\n\n// Error exports\nexport {\n CommetError,\n CommetAPIError,\n CommetValidationError,\n} from \"./types/common\";\n\n// Customers\nexport type {\n Customer,\n CustomerAddress,\n CreateParams as CreateCustomerParams,\n UpdateParams as UpdateCustomerParams,\n ListCustomersParams,\n BatchResult as CustomersBatchResult,\n} from \"./resources/customers\";\n\n// Usage\nexport type {\n UsageEvent,\n UsageEventProperty,\n TrackParams,\n TrackUsageParams,\n TrackModelTokensParams,\n BatchResult as UsageBatchResult,\n} from \"./resources/usage\";\n\n// Seats\nexport type {\n SeatEvent,\n SeatBalance,\n AddParams as AddSeatsParams,\n RemoveParams as RemoveSeatsParams,\n SetParams as SetSeatsParams,\n SetAllParams as SetAllSeatsParams,\n GetBalanceParams,\n GetAllBalancesParams,\n} from \"./resources/seats\";\n\n// Credit Packs\nexport type { CreditPack } from \"./resources/credit-packs\";\n\n// Plans\nexport type {\n Plan,\n PlanDetail,\n PlanPrice,\n PlanFeature,\n PlanID,\n BillingInterval,\n FeatureType,\n ListPlansParams,\n} from \"./resources/plans\";\n\n// Subscriptions\nexport type {\n CreatedSubscription,\n Subscription,\n ActiveSubscription,\n SubscriptionStatus,\n FeatureSummary,\n CreateSubscriptionParams,\n CancelParams,\n} from \"./resources/subscriptions\";\n\n// Portal\nexport type { PortalAccess, GetUrlParams } from \"./resources/portal\";\n\n// Features\nexport type {\n FeatureAccess,\n CanUseResult,\n CheckResult,\n GetFeatureParams,\n CheckFeatureParams,\n CanUseFeatureParams,\n} from \"./resources/features\";\n\n// Webhooks\nexport { Webhooks } from \"./resources/webhooks\";\nexport type {\n WebhookPayload,\n WebhookData,\n WebhookEvent,\n} from \"./resources/webhooks\";\n\n// Utility exports\nexport { isSandbox, isProduction } from \"./utils/environment\";\n\n// Default export\nimport { Commet } from \"./client\";\nexport default Commet;\n"],"mappings":"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","names":["data"]}
|
|
1
|
+
{"version":3,"sources":["../src/customer.ts","../src/resources/credit-packs.ts","../src/resources/customers.ts","../src/resources/features.ts","../src/resources/plans.ts","../src/resources/portal.ts","../src/resources/seats.ts","../src/resources/subscriptions.ts","../src/resources/usage.ts","../src/resources/webhooks.ts","../src/types/common.ts","../src/utils/http.ts","../src/client.ts","../src/utils/environment.ts","../src/index.ts"],"sourcesContent":["import type { FeaturesResource } from \"./resources/features\";\nimport type { PortalResource } from \"./resources/portal\";\nimport type { SeatsResource } from \"./resources/seats\";\nimport type { SubscriptionsResource } from \"./resources/subscriptions\";\nimport type { UsageResource } from \"./resources/usage\";\nimport type { RequestOptions } from \"./types/common\";\n\n/**\n * Customer-scoped API context\n *\n * Provides a cleaner API where you don't have to pass externalId\n * on every call. All operations are scoped to a specific customer.\n *\n * @example\n * ```typescript\n * const customer = commet.customer(\"user_123\");\n *\n * // All operations are now scoped to this customer\n * const seats = await customer.features.get(\"team_members\");\n * await customer.seats.add(\"member\");\n * await customer.usage.track(\"api_call\");\n * ```\n */\nexport class CustomerContext {\n private readonly externalId: string;\n private readonly featuresResource: FeaturesResource;\n private readonly seatsResource: SeatsResource;\n private readonly usageResource: UsageResource;\n private readonly subscriptionsResource: SubscriptionsResource;\n private readonly portalResource: PortalResource;\n\n constructor(\n externalId: string,\n resources: {\n features: FeaturesResource;\n seats: SeatsResource;\n usage: UsageResource;\n subscriptions: SubscriptionsResource;\n portal: PortalResource;\n },\n ) {\n this.externalId = externalId;\n this.featuresResource = resources.features;\n this.seatsResource = resources.seats;\n this.usageResource = resources.usage;\n this.subscriptionsResource = resources.subscriptions;\n this.portalResource = resources.portal;\n }\n\n /**\n * Feature access methods - delegates to FeaturesResource\n */\n features = {\n get: (code: string, options?: RequestOptions) =>\n this.featuresResource.get({ code, externalId: this.externalId }, options),\n\n check: (code: string, options?: RequestOptions) =>\n this.featuresResource.check(\n { code, externalId: this.externalId },\n options,\n ),\n\n canUse: (code: string, options?: RequestOptions) =>\n this.featuresResource.canUse(\n { code, externalId: this.externalId },\n options,\n ),\n\n list: (options?: RequestOptions) =>\n this.featuresResource.list(this.externalId, options),\n };\n\n /**\n * Seat management methods - delegates to SeatsResource\n */\n seats = {\n add: (seatType: string, count = 1, options?: RequestOptions) =>\n this.seatsResource.add(\n { externalId: this.externalId, seatType, count },\n options,\n ),\n\n remove: (seatType: string, count = 1, options?: RequestOptions) =>\n this.seatsResource.remove(\n { externalId: this.externalId, seatType, count },\n options,\n ),\n\n set: (seatType: string, count: number, options?: RequestOptions) =>\n this.seatsResource.set(\n { externalId: this.externalId, seatType, count },\n options,\n ),\n\n getBalance: (seatType: string) =>\n this.seatsResource.getBalance({ externalId: this.externalId, seatType }),\n };\n\n /**\n * Usage tracking methods - delegates to UsageResource\n */\n usage = {\n track: (\n feature: string,\n value?: number,\n properties?: Record<string, string>,\n options?: RequestOptions,\n ) =>\n this.usageResource.track(\n { externalId: this.externalId, feature, value, properties },\n options,\n ),\n };\n\n /**\n * Subscription methods - delegates to SubscriptionsResource\n */\n subscription = {\n get: () => this.subscriptionsResource.get(this.externalId),\n };\n\n /**\n * Portal methods - delegates to PortalResource\n */\n portal = {\n getUrl: (options?: RequestOptions) =>\n this.portalResource.getUrl({ externalId: this.externalId }, options),\n };\n}\n","import type { ApiResponse } from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface CreditPack {\n id: string;\n name: string;\n description: string | null;\n credits: number;\n price: number;\n currency: string;\n}\n\n/**\n * Credit Packs resource for listing available credit packs\n */\nexport class CreditPacksResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * List all active credit packs\n *\n * @example\n * ```typescript\n * const packs = await commet.creditPacks.list();\n * console.log(packs.data); // [{ id: \"cp_xxx\", name: \"100 Credits\", ... }]\n * ```\n */\n async list(): Promise<ApiResponse<CreditPack[]>> {\n return this.httpClient.get(\"/credit-packs\");\n }\n}\n","import type {\n ApiResponse,\n ListParams as BaseListParams,\n CustomerID,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface Customer {\n id: CustomerID;\n organizationId: string;\n externalId?: string;\n fullName?: string;\n domain?: string;\n website?: string;\n billingEmail: string;\n timezone?: string;\n language?: string;\n industry?: string;\n employeeCount?: string;\n metadata?: Record<string, unknown>;\n isActive: boolean;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CustomerAddress {\n line1: string;\n line2?: string;\n city: string;\n state?: string;\n postalCode: string;\n country: string; // ISO-2\n}\n\nexport interface CreateParams {\n email: string; // billingEmail - the only required field\n externalId?: string;\n fullName?: string;\n domain?: string;\n website?: string;\n timezone?: string;\n language?: string;\n industry?: string;\n metadata?: Record<string, unknown>;\n address?: CustomerAddress;\n}\n\nexport interface UpdateParams {\n customerId: CustomerID;\n externalId?: string;\n email?: string;\n fullName?: string;\n domain?: string;\n website?: string;\n timezone?: string;\n language?: string;\n industry?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ListCustomersParams extends BaseListParams {\n externalId?: string;\n isActive?: boolean;\n search?: string;\n}\n\nexport interface BatchResult {\n successful: Customer[];\n failed: Array<{\n index: number;\n error: string;\n data: CreateParams;\n }>;\n}\n\n/**\n * Customers resource - Manage your customers\n */\nexport class CustomersResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Create a customer (idempotent with externalId)\n */\n async create(\n params: CreateParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<Customer>> {\n return this.httpClient.post(\n \"/customers\",\n {\n billingEmail: params.email,\n externalId: params.externalId,\n fullName: params.fullName,\n domain: params.domain,\n website: params.website,\n timezone: params.timezone,\n language: params.language,\n industry: params.industry,\n metadata: params.metadata,\n address: params.address,\n },\n options,\n );\n }\n\n /**\n * Create multiple customers in batch\n */\n async createBatch(\n params: { customers: CreateParams[] },\n options?: RequestOptions,\n ): Promise<ApiResponse<BatchResult>> {\n const customers = params.customers.map((c) => ({\n billingEmail: c.email,\n externalId: c.externalId,\n fullName: c.fullName,\n domain: c.domain,\n website: c.website,\n timezone: c.timezone,\n language: c.language,\n industry: c.industry,\n metadata: c.metadata,\n address: c.address,\n }));\n return this.httpClient.post(\"/customers/batch\", { customers }, options);\n }\n\n /**\n * Get a customer by ID\n */\n async get(customerId: CustomerID): Promise<ApiResponse<Customer>> {\n return this.httpClient.get(`/customers/${customerId}`);\n }\n\n /**\n * Update a customer\n */\n async update(\n params: UpdateParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<Customer>> {\n return this.httpClient.put(\n `/customers/${params.customerId}`,\n {\n billingEmail: params.email,\n externalId: params.externalId,\n fullName: params.fullName,\n domain: params.domain,\n website: params.website,\n timezone: params.timezone,\n language: params.language,\n industry: params.industry,\n metadata: params.metadata,\n },\n options,\n );\n }\n\n /**\n * List customers with optional filters\n */\n async list(params?: ListCustomersParams): Promise<ApiResponse<Customer[]>> {\n return this.httpClient.get(\"/customers\", params as Record<string, unknown>);\n }\n\n /**\n * Archive a customer\n */\n async archive(\n customerId: CustomerID,\n options?: RequestOptions,\n ): Promise<ApiResponse<Customer>> {\n return this.httpClient.put(\n `/customers/${customerId}`,\n { isActive: false },\n options,\n );\n }\n}\n","import type {\n ApiResponse,\n GeneratedFeatureCode,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface FeatureParams {\n externalId: string;\n code: GeneratedFeatureCode;\n}\n\nexport type GetFeatureParams = FeatureParams;\nexport type CheckFeatureParams = FeatureParams;\nexport type CanUseFeatureParams = FeatureParams;\n\nexport interface FeatureAccess {\n code: string;\n name: string;\n type: \"boolean\" | \"metered\" | \"seats\";\n allowed: boolean;\n // For boolean features\n enabled?: boolean;\n // For metered/seats features\n current?: number;\n included?: number;\n remaining?: number;\n overage?: number;\n overageUnitPrice?: number;\n unlimited?: boolean;\n overageEnabled?: boolean;\n}\n\nexport interface CanUseResult {\n allowed: boolean;\n willBeCharged: boolean;\n reason?: string;\n}\n\nexport interface CheckResult {\n allowed: boolean;\n}\n\n/**\n * Features resource for checking feature access and usage\n *\n * Provides a clean API to check if a customer can use a feature\n * without having to manually parse subscription data.\n */\nexport class FeaturesResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Get detailed feature access/usage for a customer\n *\n * @example\n * ```typescript\n * const seats = await commet.features.get({ code: \"team_members\", externalId: \"user_123\" });\n * console.log(seats.current, seats.included, seats.remaining);\n * ```\n */\n async get(\n params: GetFeatureParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<FeatureAccess>> {\n const { code, externalId } = params;\n\n return this.httpClient.get(\n `/features/${code}`,\n { externalId: externalId },\n options,\n );\n }\n\n /**\n * Check if a boolean feature is enabled for a customer\n *\n * @example\n * ```typescript\n * const { allowed } = await commet.features.check({\n * code: \"custom_branding\",\n * externalId: \"user_123\"\n * });\n * if (!allowed) redirect(\"/upgrade\");\n * ```\n */\n async check(\n params: CheckFeatureParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<CheckResult>> {\n const { code, externalId } = params;\n\n const result = await this.httpClient.get<FeatureAccess>(\n `/features/${code}`,\n { externalId: externalId },\n options,\n );\n\n if (!result.success || !result.data) {\n return {\n success: false,\n data: { allowed: false },\n message: result.message,\n };\n }\n\n return {\n success: true,\n data: { allowed: result.data.allowed },\n message: result.message,\n };\n }\n\n /**\n * Check if customer can use one more unit of a feature\n *\n * Returns whether the customer can add one more (allowed)\n * and whether they'll be charged extra (willBeCharged).\n *\n * @example\n * ```typescript\n * const { allowed, willBeCharged } = await commet.features.canUse({\n * code: \"team_members\",\n * externalId: \"user_123\"\n * });\n *\n * if (!allowed) {\n * return { error: \"Upgrade to add more members\" };\n * }\n *\n * if (willBeCharged) {\n * // Show confirmation: \"This will cost $10/month extra\"\n * }\n * ```\n */\n async canUse(\n params: CanUseFeatureParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<CanUseResult>> {\n const { code, externalId } = params;\n\n return this.httpClient.get(\n `/features/${code}`,\n { externalId: externalId, action: \"canUse\" },\n options,\n );\n }\n\n /**\n * List all features for a customer's active subscription\n *\n * @example\n * ```typescript\n * const features = await commet.features.list({ externalId: \"user_123\" });\n * for (const feature of features) {\n * console.log(feature.code, feature.allowed);\n * }\n * ```\n */\n async list(\n externalId: string,\n options?: RequestOptions,\n ): Promise<ApiResponse<FeatureAccess[]>> {\n return this.httpClient.get(\"/features\", { externalId }, options);\n }\n}\n","import type {\n ApiResponse,\n GeneratedPlanCode,\n ListParams,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport type PlanID = `plan_${string}`;\nexport type BillingInterval = \"monthly\" | \"quarterly\" | \"yearly\";\nexport type FeatureType = \"boolean\" | \"metered\" | \"seats\";\n\nexport interface PlanPrice {\n billingInterval: BillingInterval;\n price: number; // in cents\n isDefault: boolean;\n trialDays: number;\n}\n\nexport interface PlanFeature {\n code: string;\n name: string;\n type: FeatureType;\n unitName: string | null;\n enabled?: boolean;\n includedAmount?: number;\n unlimited?: boolean;\n overageEnabled?: boolean;\n overageUnitPrice?: number;\n}\n\nexport interface Plan {\n id: PlanID;\n code: string;\n name: string;\n description: string | null;\n isPublic: boolean;\n isFree: boolean;\n isDefault: boolean;\n sortOrder: number;\n prices: PlanPrice[];\n features: PlanFeature[];\n createdAt: string;\n}\n\nexport interface PlanDetailPrice {\n billingInterval: BillingInterval;\n price: number;\n isDefault: boolean;\n trialDays: number;\n introOffer: {\n enabled: boolean;\n discountType: \"percentage\" | \"amount\" | null;\n discountValue: number | null;\n durationCycles: number | null;\n } | null;\n}\n\nexport interface PlanDetailFeature extends PlanFeature {\n overage: {\n enabled: boolean;\n model: \"per_unit\" | \"tiered\" | null;\n unitPrice: number | null;\n } | null;\n}\n\nexport interface PlanDetail {\n id: PlanID;\n code: string;\n name: string;\n description: string | null;\n isPublic: boolean;\n isDefault: boolean;\n sortOrder: number;\n prices: PlanDetailPrice[];\n features: PlanDetailFeature[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ListPlansParams extends ListParams {\n includePrivate?: boolean;\n}\n\n/**\n * Plans resource for listing available plans\n */\nexport class PlansResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * List all available plans\n *\n * @example\n * ```typescript\n * // List public plans\n * const plans = await commet.plans.list();\n *\n * // Include private plans\n * const allPlans = await commet.plans.list({ includePrivate: true });\n * ```\n */\n async list(params?: ListPlansParams): Promise<ApiResponse<Plan[]>> {\n return this.httpClient.get(\"/plans\", params);\n }\n\n /**\n * Get a specific plan by code\n *\n * @example\n * ```typescript\n * const plan = await commet.plans.get('pro');\n * console.log(plan.data.name); // \"Pro\"\n * console.log(plan.data.prices); // [{ billingInterval: 'monthly', price: 9900 }]\n * ```\n */\n async get(planCode: GeneratedPlanCode): Promise<ApiResponse<PlanDetail>> {\n return this.httpClient.get(`/plans/${planCode}`);\n }\n}\n","import type { ApiResponse, CustomerID, RequestOptions } from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface PortalAccess {\n success: boolean;\n message: string;\n portalUrl: string;\n}\n\ninterface GetUrlByCustomerId {\n customerId: CustomerID;\n email?: never;\n externalId?: never;\n}\n\ninterface GetUrlByExternalId {\n externalId: string;\n email?: never;\n customerId?: never;\n}\n\ninterface GetUrlByEmail {\n email: string;\n customerId?: never;\n externalId?: never;\n}\n\nexport type GetUrlParams =\n | GetUrlByCustomerId\n | GetUrlByExternalId\n | GetUrlByEmail;\n\n/**\n * Portal resource - Generate customer portal access\n */\nexport class PortalResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Get a portal URL\n *\n * @example\n * ```typescript\n * const portal = await commet.portal.getUrl({ externalId: 'user_123' });\n * ```\n */\n async getUrl(\n params: GetUrlParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<PortalAccess>> {\n return this.httpClient.post(\"/portal/request-access\", params, options);\n }\n}\n","import type {\n ApiResponse,\n CustomerID,\n GeneratedSeatType,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface SeatEvent {\n id: string;\n organizationId: string;\n customerId: CustomerID;\n seatType: GeneratedSeatType;\n eventType: \"add\" | \"remove\" | \"set\";\n quantity: number;\n previousBalance?: number;\n newBalance: number;\n ts: string;\n createdAt: string;\n}\n\nexport interface SeatBalance {\n current: number;\n asOf: string;\n}\n\nexport interface AddParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n count: number;\n}\n\nexport interface RemoveParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n count: number;\n}\n\nexport interface SetParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n count: number;\n}\n\nexport interface SetAllParams {\n customerId?: CustomerID;\n externalId?: string;\n seats: Record<string, number>;\n}\n\nexport interface GetBalanceParams {\n customerId?: CustomerID;\n externalId?: string;\n seatType: GeneratedSeatType;\n}\n\nexport interface GetAllBalancesParams {\n customerId?: CustomerID;\n externalId?: string;\n}\n\n/**\n * Seats resource - Manage seat-based licenses\n */\nexport class SeatsResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Add seats\n *\n * @example\n * ```typescript\n * await commet.seats.add({\n * externalId: 'user_123',\n * seatType: 'editor',\n * count: 5\n * });\n * ```\n */\n async add(\n params: AddParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent>> {\n return this.httpClient.post(\"/seats\", params, options);\n }\n\n /**\n * Remove seats\n *\n * @example\n * ```typescript\n * await commet.seats.remove({\n * externalId: 'user_123',\n * seatType: 'editor',\n * count: 2\n * });\n * ```\n */\n async remove(\n params: RemoveParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent>> {\n return this.httpClient.delete(\"/seats\", params, options);\n }\n\n /**\n * Set seats to a specific count\n *\n * @example\n * ```typescript\n * await commet.seats.set({\n * externalId: 'user_123',\n * seatType: 'editor',\n * count: 10\n * });\n * ```\n */\n async set(\n params: SetParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent>> {\n return this.httpClient.put(\"/seats\", params, options);\n }\n\n /**\n * Set all seat types\n *\n * @example\n * ```typescript\n * await commet.seats.setAll({\n * externalId: 'user_123',\n * seats: { editor: 10, viewer: 50 }\n * });\n * ```\n */\n async setAll(\n params: SetAllParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<SeatEvent[]>> {\n return this.httpClient.put(\"/seats/bulk\", params, options);\n }\n\n /**\n * Get balance for a seat type\n *\n * @example\n * ```typescript\n * const balance = await commet.seats.getBalance({\n * externalId: 'user_123',\n * seatType: 'editor'\n * });\n * ```\n */\n async getBalance(\n params: GetBalanceParams,\n ): Promise<ApiResponse<SeatBalance>> {\n const { customerId, externalId, seatType } = params;\n\n return this.httpClient.get(\"/seats/balance\", {\n customerId: customerId,\n externalId: externalId,\n seatType: seatType,\n });\n }\n\n /**\n * Get all seat balances\n *\n * @example\n * ```typescript\n * const balances = await commet.seats.getAllBalances({\n * externalId: 'user_123'\n * });\n * ```\n */\n async getAllBalances(\n params: GetAllBalancesParams,\n ): Promise<ApiResponse<Record<string, SeatBalance>>> {\n const { customerId, externalId } = params;\n\n return this.httpClient.get(\"/seats/balances\", {\n customerId: customerId,\n externalId: externalId,\n });\n }\n}\n","import type {\n ApiResponse,\n GeneratedPlanCode,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\nimport type { BillingInterval } from \"./plans\";\n\nexport type SubscriptionStatus =\n | \"draft\"\n | \"pending_payment\"\n | \"trialing\"\n | \"active\"\n | \"paused\"\n | \"past_due\"\n | \"canceled\"\n | \"expired\";\n\nexport interface FeatureSummary {\n code: string;\n name: string;\n type: \"boolean\" | \"metered\" | \"seats\";\n enabled?: boolean;\n usage?: {\n current: number;\n included: number;\n overage: number;\n overageUnitPrice?: number;\n };\n}\n\nexport interface ActiveSubscription {\n id: string;\n customerId: string;\n plan: {\n id: string;\n name: string;\n basePrice: number;\n billingInterval: BillingInterval | null;\n };\n name: string;\n description: string | null;\n status: SubscriptionStatus;\n trialEndsAt: string | null;\n currentPeriod: {\n start: string;\n end: string;\n daysRemaining: number;\n };\n features: FeatureSummary[];\n startDate: string;\n endDate: string | null;\n billingDayOfMonth: number;\n nextBillingDate: string;\n checkoutUrl: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CreatedSubscription {\n id: string;\n customerId: string;\n externalId: string;\n planId: string;\n planName: string;\n name: string;\n status: SubscriptionStatus;\n billingInterval: BillingInterval | null;\n trialEndsAt: string | null;\n startDate: string;\n endDate: string | null;\n currentPeriodStart: string | null;\n currentPeriodEnd: string | null;\n billingDayOfMonth: number;\n checkoutUrl: string | null;\n createdAt: string;\n updatedAt: string;\n introOfferEndsAt: string | null;\n introOfferDiscountType: \"percentage\" | \"amount\" | null;\n introOfferDiscountValue: number | null;\n}\n\nexport interface Subscription {\n id: string;\n customerId: string;\n planId: string;\n planName: string;\n name: string;\n description?: string;\n status: SubscriptionStatus;\n billingInterval: BillingInterval;\n trialEndsAt?: string;\n startDate: string;\n endDate?: string;\n currentPeriodStart?: string;\n currentPeriodEnd?: string;\n billingDayOfMonth: number;\n checkoutUrl?: string;\n createdAt: string;\n updatedAt: string;\n}\n\n// Customer identifier: mutually exclusive customerId or externalId\ntype CustomerIdentifier =\n | { customerId: string; externalId?: never }\n | { customerId?: never; externalId: string };\n\n// Plan identifier: use planCode (with autocomplete) or planId (legacy)\ntype PlanIdentifier =\n | { planCode: GeneratedPlanCode; planId?: never }\n | { planCode?: never; planId: string };\n\nexport type CreateSubscriptionParams = CustomerIdentifier &\n PlanIdentifier & {\n billingInterval?: BillingInterval;\n initialSeats?: Record<string, number>;\n skipTrial?: boolean;\n name?: string;\n startDate?: string;\n successUrl?: string;\n };\n\nexport interface CancelParams {\n subscriptionId: string;\n reason?: string;\n immediate?: boolean;\n}\n\n/**\n * Subscription resource for managing subscriptions (plan-first model)\n *\n * Each customer can only have ONE active subscription at a time.\n */\nexport class SubscriptionsResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n /**\n * Create a subscription with a plan\n *\n * @example\n * ```typescript\n * await commet.subscriptions.create({\n * externalId: 'user_123',\n * planCode: 'pro', // autocomplete works after `commet pull`\n * billingInterval: 'yearly',\n * initialSeats: { editor: 5 }\n * });\n * ```\n */\n async create(\n params: CreateSubscriptionParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<CreatedSubscription>> {\n return this.httpClient.post(\"/subscriptions\", params, options);\n }\n\n /**\n * Get the active subscription for a customer\n *\n * @example\n * ```typescript\n * const sub = await commet.subscriptions.get('user_123');\n * ```\n */\n async get(\n externalId: string,\n ): Promise<ApiResponse<ActiveSubscription | null>> {\n return this.httpClient.get(\"/subscriptions/active\", { externalId });\n }\n\n /**\n * Cancel a subscription\n *\n * @example\n * ```typescript\n * await commet.subscriptions.cancel({\n * subscriptionId: 'sub_xxx',\n * reason: 'switched_to_competitor'\n * });\n * ```\n */\n async cancel(\n params: CancelParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<Subscription>> {\n return this.httpClient.post(\n `/subscriptions/${params.subscriptionId}/cancel`,\n params || {},\n options,\n );\n }\n}\n","import type {\n ApiResponse,\n CustomerID,\n EventID,\n GeneratedFeatureCode,\n RequestOptions,\n} from \"../types/common\";\nimport type { CommetHTTPClient } from \"../utils/http\";\n\nexport interface UsageEvent {\n id: EventID;\n organizationId: string;\n customerId: CustomerID;\n feature: string;\n idempotencyKey?: string;\n ts: string;\n properties?: UsageEventProperty[];\n createdAt: string;\n}\n\nexport interface UsageEventProperty {\n id: string;\n usageEventId: EventID;\n property: string;\n value: string;\n createdAt: string;\n}\n\nexport interface BatchResult<T> {\n successful: T[];\n failed: Array<{\n index: number;\n error: string;\n data: TrackParams;\n }>;\n}\n\ninterface TrackBaseParams {\n feature: GeneratedFeatureCode;\n customerId?: CustomerID;\n externalId?: string;\n idempotencyKey?: string;\n timestamp?: string;\n properties?: Record<string, string>;\n}\n\nexport interface TrackUsageParams extends TrackBaseParams {\n value?: number;\n model?: never;\n}\n\nexport interface TrackModelTokensParams extends TrackBaseParams {\n model: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n value?: never;\n}\n\nexport type TrackParams = TrackUsageParams | TrackModelTokensParams;\n\nexport class UsageResource {\n constructor(private httpClient: CommetHTTPClient) {}\n\n async track(\n params: TrackParams,\n options?: RequestOptions,\n ): Promise<ApiResponse<UsageEvent>> {\n const eventData: Record<string, unknown> = {\n feature: params.feature,\n customerId: params.customerId,\n externalId: params.externalId,\n idempotencyKey: params.idempotencyKey,\n timestamp: params.timestamp || new Date().toISOString(),\n properties: params.properties\n ? Object.entries(params.properties).map(([property, value]) => ({\n property,\n value,\n }))\n : undefined,\n };\n\n if (\"model\" in params && params.model) {\n eventData.model = params.model;\n eventData.inputTokens = params.inputTokens;\n eventData.outputTokens = params.outputTokens;\n if (params.cacheReadTokens) {\n eventData.cacheReadTokens = params.cacheReadTokens;\n }\n if (params.cacheWriteTokens) {\n eventData.cacheWriteTokens = params.cacheWriteTokens;\n }\n } else {\n eventData.value = (params as TrackUsageParams).value;\n }\n\n return this.httpClient.post(\"/usage/events\", eventData, options);\n }\n\n async trackBatch(\n params: { events: TrackParams[] },\n options?: RequestOptions,\n ): Promise<ApiResponse<BatchResult<UsageEvent>>> {\n const events = params.events.map((event) => {\n const eventData: Record<string, unknown> = {\n feature: event.feature,\n customerId: event.customerId,\n externalId: event.externalId,\n idempotencyKey: event.idempotencyKey,\n timestamp: event.timestamp || new Date().toISOString(),\n properties: event.properties\n ? Object.entries(event.properties).map(([property, value]) => ({\n property,\n value,\n }))\n : undefined,\n };\n\n if (\"model\" in event && event.model) {\n eventData.model = event.model;\n eventData.inputTokens = event.inputTokens;\n eventData.outputTokens = event.outputTokens;\n if (event.cacheReadTokens) {\n eventData.cacheReadTokens = event.cacheReadTokens;\n }\n if (event.cacheWriteTokens) {\n eventData.cacheWriteTokens = event.cacheWriteTokens;\n }\n } else {\n eventData.value = (event as TrackUsageParams).value;\n }\n\n return eventData;\n });\n\n return this.httpClient.post(\"/usage/events/batch\", { events }, options);\n }\n}\n","import crypto from \"node:crypto\";\n\n/**\n * Webhook payload structure from Commet\n */\nexport interface WebhookPayload {\n event: WebhookEvent;\n timestamp: string;\n organizationId: string;\n data: WebhookData;\n}\n\n/**\n * Webhook data structure (subscription-related fields)\n */\nexport interface WebhookData {\n id?: string;\n publicId?: string;\n subscriptionId?: string;\n customerId?: string;\n externalId?: string;\n status?: string;\n name?: string;\n canceledAt?: string;\n [key: string]: unknown;\n}\n\n/**\n * Supported webhook events\n */\nexport type WebhookEvent =\n | \"subscription.created\"\n | \"subscription.activated\"\n | \"subscription.canceled\"\n | \"subscription.updated\";\n\nexport interface VerifyParams {\n payload: string;\n signature: string | null;\n secret: string;\n}\n\nexport interface GenerateSignatureParams {\n payload: string;\n secret: string;\n}\n\nexport interface VerifyAndParseParams {\n rawBody: string;\n signature: string | null;\n secret: string;\n}\n\n/**\n * Webhooks resource for signature verification\n */\nexport class Webhooks {\n /**\n * Verify HMAC-SHA256 webhook signature\n *\n * Use this method to verify that webhooks are authentically from Commet.\n * The signature is included in the `X-Commet-Signature` header.\n *\n * @param payload - Raw request body as string (IMPORTANT: Do not parse JSON first)\n * @param signature - Value from X-Commet-Signature header\n * @param secret - Your webhook secret from Commet dashboard\n * @returns true if signature is valid, false otherwise\n *\n * @example\n * ```typescript\n * // Next.js API route example\n * export async function POST(request: Request) {\n * const rawBody = await request.text();\n * const signature = request.headers.get('x-commet-signature');\n *\n * const isValid = commet.webhooks.verify(\n * rawBody,\n * signature,\n * process.env.COMMET_WEBHOOK_SECRET\n * );\n *\n * if (!isValid) {\n * return new Response('Invalid signature', { status: 401 });\n * }\n *\n * const payload = JSON.parse(rawBody);\n * // Handle webhook event...\n * }\n * ```\n */\n verify(params: VerifyParams): boolean {\n const { payload, signature, secret } = params;\n\n if (!signature || !secret || !payload) {\n return false;\n }\n\n try {\n const expectedSignature = this.generateSignature({ payload, secret });\n\n // Use timing-safe comparison to prevent timing attacks\n return crypto.timingSafeEqual(\n Buffer.from(signature, \"hex\"),\n Buffer.from(expectedSignature, \"hex\"),\n );\n } catch (_error) {\n // timingSafeEqual throws if lengths don't match\n return false;\n }\n }\n\n /**\n * Generate HMAC-SHA256 signature (internal use)\n * @internal\n */\n private generateSignature(params: GenerateSignatureParams): string {\n const { payload, secret } = params;\n return crypto.createHmac(\"sha256\", secret).update(payload).digest(\"hex\");\n }\n\n /**\n * Parse and verify webhook payload in one step\n *\n * @example\n * ```typescript\n * const payload = commet.webhooks.verifyAndParse({\n * rawBody,\n * signature,\n * secret: process.env.COMMET_WEBHOOK_SECRET\n * });\n *\n * if (!payload) {\n * return new Response('Invalid signature', { status: 401 });\n * }\n *\n * // payload is typed and validated\n * if (payload.event === 'subscription.activated') {\n * // Handle activation...\n * }\n * ```\n */\n verifyAndParse(params: VerifyAndParseParams): WebhookPayload | null {\n const { rawBody, signature, secret } = params;\n\n if (!this.verify({ payload: rawBody, signature, secret })) {\n return null;\n }\n\n try {\n return JSON.parse(params.rawBody) as WebhookPayload;\n } catch {\n return null;\n }\n }\n}\n","export type Environment = \"sandbox\" | \"production\";\n\nexport type CommetConfig = {\n apiKey: string;\n environment?: Environment;\n debug?: boolean;\n timeout?: number;\n retries?: number;\n};\n\n// API Response types\nexport interface ApiResponse<T = unknown> {\n success: boolean;\n data?: T;\n code?: string;\n message?: string;\n details?: unknown;\n // Pagination fields (optional, included for list endpoints)\n hasMore?: boolean;\n nextCursor?: string;\n}\n\nexport interface PaginatedResponse<T> {\n data: T[];\n hasMore: boolean;\n nextCursor?: string;\n totalCount?: number;\n}\n\nexport interface PaginatedList<T> extends PaginatedResponse<T> {\n next(): Promise<PaginatedList<T>>;\n all(): Promise<T[]>;\n}\n\n// Error types\nexport class CommetError extends Error {\n constructor(\n message: string,\n public code?: string,\n public statusCode?: number,\n public details?: unknown,\n ) {\n super(message);\n this.name = \"CommetError\";\n }\n}\n\nexport class CommetAPIError extends CommetError {\n constructor(\n message: string,\n public statusCode: number,\n public code?: string,\n public details?: unknown,\n ) {\n super(message, code, statusCode, details);\n this.name = \"CommetAPIError\";\n }\n}\n\nexport class CommetValidationError extends CommetError {\n constructor(\n message: string,\n public validationErrors: Record<string, string[]>,\n ) {\n super(message);\n this.name = \"CommetValidationError\";\n }\n}\n\nexport type CustomerID = `cus_${string}`;\nexport type AgreementID = `agr_${string}`;\nexport type InvoiceID = `inv_${string}`;\nexport type PhaseID = `phs_${string}`;\nexport type ItemID = `itm_${string}`;\nexport type ProductID = `prd_${string}`;\nexport type EventID = `evt_${string}`;\nexport type WebhookID = `wh_${string}`;\n\n// Currency enum\nexport type Currency =\n | \"USD\"\n | \"EUR\"\n | \"GBP\"\n | \"CAD\"\n | \"AUD\"\n | \"JPY\"\n | \"ARS\"\n | \"BRL\"\n | \"MXN\"\n | \"CLP\";\n\n// Common parameters\nexport interface ListParams extends Record<string, unknown> {\n limit?: number;\n cursor?: string;\n startDate?: string;\n endDate?: string;\n}\n\nexport interface RetrieveOptions {\n expand?: string[];\n}\n\n// Request options\nexport interface RequestOptions {\n idempotencyKey?: string;\n timeout?: number;\n}\n\n/**\n * Generated types interface - augmented by CLI after 'commet pull'\n *\n * This interface gets filled by module augmentation when you run `commet pull`.\n * The CLI generates a .commet/types.d.ts file that augments this interface with your\n * organization's specific feature codes, seat types, and plan codes.\n *\n * @example\n * // After running `commet pull`, TypeScript will automatically know your types:\n * await commet.usage.track({\n * feature: 'api_calls', // Autocomplete works!\n * externalId: 'user_123'\n * });\n */\n\n// biome-ignore lint/suspicious/noEmptyInterface: augmented by CLI-generated .commet/types.d.ts\nexport interface CommetGeneratedTypes {}\n\nexport type GeneratedSeatType = CommetGeneratedTypes extends {\n seatType: infer T;\n}\n ? T\n : string;\n\nexport type GeneratedPlanCode = CommetGeneratedTypes extends {\n planCode: infer T;\n}\n ? T\n : string;\n\nexport type GeneratedFeatureCode = CommetGeneratedTypes extends {\n featureCode: infer T;\n}\n ? T\n : string;\n","import type {\n ApiResponse,\n CommetConfig,\n Environment,\n RequestOptions,\n} from \"../types/common\";\nimport { CommetAPIError, CommetValidationError } from \"../types/common\";\n\nexport interface RetryConfig {\n maxRetries: number;\n baseDelay: number;\n maxDelay: number;\n retryableStatusCodes: number[];\n}\n\nconst DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 3,\n baseDelay: 1000, // 1s\n maxDelay: 8000, // 8s\n retryableStatusCodes: [408, 429, 500, 502, 503, 504],\n};\n\nexport class CommetHTTPClient {\n private config: CommetConfig;\n private environment: Environment;\n private retryConfig: RetryConfig;\n\n constructor(config: CommetConfig, environment: Environment) {\n this.config = config;\n this.environment = environment;\n this.retryConfig = {\n ...DEFAULT_RETRY_CONFIG,\n maxRetries: config.retries ?? DEFAULT_RETRY_CONFIG.maxRetries,\n };\n }\n\n async get<T = unknown>(\n endpoint: string,\n params?: Record<string, unknown>,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"GET\", endpoint, undefined, options, params);\n }\n\n async post<T = unknown>(\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"POST\", endpoint, data, options);\n }\n\n async put<T = unknown>(\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"PUT\", endpoint, data, options);\n }\n\n async delete<T = unknown>(\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<ApiResponse<T>> {\n return this.request(\"DELETE\", endpoint, data, options);\n }\n\n /**\n * Core request method with retry logic\n */\n private async request<T = unknown>(\n method: string,\n endpoint: string,\n data?: unknown,\n options?: RequestOptions,\n params?: Record<string, unknown>,\n ): Promise<ApiResponse<T>> {\n const url = this.buildURL(endpoint, params);\n return this.executeRequest(method, url, data, options);\n }\n\n /**\n * Execute real API request with retry logic\n */\n private async executeRequest<T = unknown>(\n method: string,\n url: string,\n data?: unknown,\n options?: RequestOptions,\n attempt = 1,\n ): Promise<ApiResponse<T>> {\n try {\n const headers: Record<string, string> = {\n \"x-api-key\": this.config.apiKey,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"commet/0.1.0\",\n };\n\n if (options?.idempotencyKey) {\n headers[\"Idempotency-Key\"] = options.idempotencyKey;\n } else if (method === \"POST\" && data) {\n headers[\"Idempotency-Key\"] = this.generateIdempotencyKey();\n }\n\n const requestConfig: RequestInit = {\n method,\n headers,\n signal: AbortSignal.timeout(\n options?.timeout ?? this.config.timeout ?? 30000,\n ),\n };\n\n if (data) {\n requestConfig.body = JSON.stringify(data);\n }\n\n if (this.config.debug) {\n console.log(`[Commet SDK] ${method} ${url}`);\n if (data) {\n console.log(\"Request data:\", JSON.stringify(data, null, 2));\n }\n }\n\n const response = await fetch(url, requestConfig);\n\n if (this.config.debug) {\n console.log(\n `[Commet SDK] Response status: ${response.status} ${response.statusText}`,\n );\n }\n\n let responseData: unknown;\n let responseText: string;\n\n try {\n responseData = await response.json();\n responseText = \"\";\n } catch (_jsonError) {\n try {\n responseText = await response.text();\n } catch (_textError) {\n responseText = \"Failed to read response body\";\n }\n if (this.config.debug) {\n console.log(\n \"[Commet SDK] Failed to parse JSON response:\",\n responseText,\n );\n }\n\n // For 404 errors with invalid JSON, return a graceful response\n // This handles cases like HTML error pages or empty responses\n if (response.status === 404) {\n return {\n success: false,\n code: \"not_found\",\n message: \"Resource not found\",\n } as ApiResponse<T>;\n }\n\n throw new CommetAPIError(\n `Invalid JSON response: ${response.status} ${response.statusText}`,\n response.status,\n \"INVALID_JSON\",\n { responseText },\n );\n }\n\n if (!response.ok) {\n // Check if we should retry\n if (\n attempt <= this.retryConfig.maxRetries &&\n this.retryConfig.retryableStatusCodes.includes(response.status)\n ) {\n const delay = Math.min(\n this.retryConfig.baseDelay * 2 ** (attempt - 1),\n this.retryConfig.maxDelay,\n );\n\n if (this.config.debug) {\n console.log(\n `[Commet SDK] Retrying in ${delay}ms (attempt ${attempt}/${this.retryConfig.maxRetries})`,\n );\n }\n\n await this.sleep(delay);\n return this.executeRequest(method, url, data, options, attempt + 1);\n }\n\n // Log error response for debugging\n if (this.config.debug) {\n console.log(\n \"[Commet SDK] Error response:\",\n JSON.stringify(responseData, null, 2),\n );\n }\n\n // Type guard for error response\n const isErrorResponse = (\n data: unknown,\n ): data is {\n message?: string;\n code?: string;\n details?: unknown;\n } => {\n return typeof data === \"object\" && data !== null;\n };\n\n const errorData = isErrorResponse(responseData) ? responseData : {};\n\n // Handle validation errors (new normalized shape)\n if (\n errorData.code === \"validation_error\" &&\n Array.isArray(errorData.details)\n ) {\n const errors: Record<string, string[]> = {};\n for (const detail of errorData.details as Array<{\n field: string;\n message: string;\n }>) {\n if (!errors[detail.field]) errors[detail.field] = [];\n errors[detail.field].push(detail.message);\n }\n throw new CommetValidationError(\n errorData.message || \"Validation failed\",\n errors,\n );\n }\n\n throw new CommetAPIError(\n errorData.message || `Request failed with status ${response.status}`,\n response.status,\n errorData.code,\n errorData.details,\n );\n }\n\n if (this.config.debug) {\n console.log(\"[Commet SDK] Response:\", responseData);\n }\n\n return responseData as ApiResponse<T>;\n } catch (error) {\n // Handle network errors and timeouts\n if (error instanceof TypeError && error.message.includes(\"fetch\")) {\n if (attempt <= this.retryConfig.maxRetries) {\n const delay = Math.min(\n this.retryConfig.baseDelay * 2 ** (attempt - 1),\n this.retryConfig.maxDelay,\n );\n\n if (this.config.debug) {\n console.log(`[Commet SDK] Network error, retrying in ${delay}ms`);\n }\n\n await this.sleep(delay);\n return this.executeRequest(method, url, data, options, attempt + 1);\n }\n }\n\n throw error;\n }\n }\n\n /**\n * Get base URL based on environment\n */\n private getBaseURL(): string {\n return this.environment === \"production\"\n ? \"https://commet.co\"\n : \"https://sandbox.commet.co\";\n }\n\n /**\n * Build full URL from endpoint and params\n */\n private buildURL(endpoint: string, params?: Record<string, unknown>): string {\n const baseURL = this.getBaseURL();\n\n // Construct full path with /api prefix\n const normalizedEndpoint = endpoint.startsWith(\"/\")\n ? endpoint\n : `/${endpoint}`;\n const fullPath = `/api${normalizedEndpoint}`;\n\n // Debug logging\n if (this.config.debug) {\n console.log(\n `[Commet SDK] Building URL - baseURL: ${baseURL}, endpoint: ${endpoint}, fullPath: ${fullPath}`,\n );\n }\n\n const url = new URL(fullPath, baseURL);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value));\n }\n }\n }\n\n const finalUrl = url.toString();\n\n // Debug final URL\n if (this.config.debug) {\n console.log(`[Commet SDK] Final URL: ${finalUrl}`);\n }\n\n return finalUrl;\n }\n\n /**\n * Generate idempotency key\n */\n private generateIdempotencyKey(): string {\n // Generate UUID-like key for idempotency\n return `sdk_${Date.now()}_${Math.random().toString(36).substring(2)}`;\n }\n\n /**\n * Sleep for specified milliseconds\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { CustomerContext } from \"./customer\";\nimport { CreditPacksResource } from \"./resources/credit-packs\";\nimport { CustomersResource } from \"./resources/customers\";\nimport { FeaturesResource } from \"./resources/features\";\nimport { PlansResource } from \"./resources/plans\";\nimport { PortalResource } from \"./resources/portal\";\nimport { SeatsResource } from \"./resources/seats\";\nimport { SubscriptionsResource } from \"./resources/subscriptions\";\nimport { UsageResource } from \"./resources/usage\";\nimport { Webhooks } from \"./resources/webhooks\";\nimport type { CommetConfig, Environment } from \"./types/common\";\nimport { CommetHTTPClient } from \"./utils/http\";\n\n/**\n * Main Commet SDK client\n */\nexport class Commet {\n private httpClient: CommetHTTPClient;\n private environment: Environment;\n\n public readonly customers: CustomersResource;\n public readonly creditPacks: CreditPacksResource;\n public readonly plans: PlansResource;\n public readonly usage: UsageResource;\n public readonly seats: SeatsResource;\n public readonly subscriptions: SubscriptionsResource;\n public readonly portal: PortalResource;\n public readonly features: FeaturesResource;\n public readonly webhooks: Webhooks;\n\n constructor(config: CommetConfig) {\n if (!config.apiKey) {\n throw new Error(\"Commet SDK: API key is required\");\n }\n\n if (!config.apiKey.startsWith(\"ck_\")) {\n throw new Error(\n \"Commet SDK: Invalid API key format. Expected format: ck_xxx...\",\n );\n }\n\n // Default to sandbox for safety\n this.environment = config.environment || \"sandbox\";\n\n this.httpClient = new CommetHTTPClient(config, this.environment);\n this.customers = new CustomersResource(this.httpClient);\n this.creditPacks = new CreditPacksResource(this.httpClient);\n this.plans = new PlansResource(this.httpClient);\n this.usage = new UsageResource(this.httpClient);\n this.seats = new SeatsResource(this.httpClient);\n this.subscriptions = new SubscriptionsResource(this.httpClient);\n this.portal = new PortalResource(this.httpClient);\n this.features = new FeaturesResource(this.httpClient);\n this.webhooks = new Webhooks();\n\n if (config.debug) {\n console.log(`[Commet SDK] Initialized in ${this.environment} mode`);\n console.log(\"API Key:\", `${config.apiKey.substring(0, 12)}...`);\n const baseURL =\n this.environment === \"production\"\n ? \"https://commet.co\"\n : \"https://sandbox.commet.co\";\n console.log(\"Base URL:\", baseURL);\n }\n }\n\n /**\n * Create a customer-scoped context for cleaner API usage\n *\n * @example\n * ```typescript\n * const customer = commet.customer(\"user_123\");\n *\n * // All operations are now scoped to this customer\n * const seats = await customer.features.get(\"team_members\");\n * await customer.seats.add(\"member\");\n * await customer.usage.track(\"api_call\");\n * ```\n */\n customer(externalId: string): CustomerContext {\n return new CustomerContext(externalId, {\n features: this.features,\n seats: this.seats,\n usage: this.usage,\n subscriptions: this.subscriptions,\n portal: this.portal,\n });\n }\n\n getEnvironment(): Environment {\n return this.environment;\n }\n\n isSandbox(): boolean {\n return this.environment === \"sandbox\";\n }\n\n isProduction(): boolean {\n return this.environment === \"production\";\n }\n}\n","import type { Environment } from \"../types/common\";\n\n/**\n * Check if environment is sandbox\n */\nexport function isSandbox(environment: Environment): boolean {\n return environment === \"sandbox\";\n}\n\n/**\n * Check if environment is production\n */\nexport function isProduction(environment: Environment): boolean {\n return environment === \"production\";\n}\n","/**\n * Commet SDK - Billing and usage tracking for SaaS\n */\nexport { Commet } from \"./client\";\nexport { CustomerContext } from \"./customer\";\n// Credit Packs\nexport type { CreditPack } from \"./resources/credit-packs\";\n// Customers\nexport type {\n BatchResult as CustomersBatchResult,\n CreateParams as CreateCustomerParams,\n Customer,\n CustomerAddress,\n ListCustomersParams,\n UpdateParams as UpdateCustomerParams,\n} from \"./resources/customers\";\n// Features\nexport type {\n CanUseFeatureParams,\n CanUseResult,\n CheckFeatureParams,\n CheckResult,\n FeatureAccess,\n GetFeatureParams,\n} from \"./resources/features\";\n// Plans\nexport type {\n BillingInterval,\n FeatureType,\n ListPlansParams,\n Plan,\n PlanDetail,\n PlanFeature,\n PlanID,\n PlanPrice,\n} from \"./resources/plans\";\n// Portal\nexport type { GetUrlParams, PortalAccess } from \"./resources/portal\";\n// Seats\nexport type {\n AddParams as AddSeatsParams,\n GetAllBalancesParams,\n GetBalanceParams,\n RemoveParams as RemoveSeatsParams,\n SeatBalance,\n SeatEvent,\n SetAllParams as SetAllSeatsParams,\n SetParams as SetSeatsParams,\n} from \"./resources/seats\";\n// Subscriptions\nexport type {\n ActiveSubscription,\n CancelParams,\n CreatedSubscription,\n CreateSubscriptionParams,\n FeatureSummary,\n Subscription,\n SubscriptionStatus,\n} from \"./resources/subscriptions\";\n// Usage\nexport type {\n BatchResult as UsageBatchResult,\n TrackModelTokensParams,\n TrackParams,\n TrackUsageParams,\n UsageEvent,\n UsageEventProperty,\n} from \"./resources/usage\";\nexport type {\n WebhookData,\n WebhookEvent,\n WebhookPayload,\n} from \"./resources/webhooks\";\n// Webhooks\nexport { Webhooks } from \"./resources/webhooks\";\n// Type exports\nexport type {\n ApiResponse,\n CommetConfig,\n CommetGeneratedTypes,\n Currency,\n CustomerID,\n Environment,\n EventID,\n GeneratedFeatureCode,\n GeneratedPlanCode,\n GeneratedSeatType,\n PaginatedList,\n PaginatedResponse,\n RequestOptions,\n} from \"./types/common\";\n// Error exports\nexport {\n CommetAPIError,\n CommetError,\n CommetValidationError,\n} from \"./types/common\";\n\n// Utility exports\nexport { isProduction, isSandbox } from \"./utils/environment\";\n\n// Default export\nimport { Commet } from \"./client\";\nexport default Commet;\n"],"mappings":"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","names":["data"]}
|