@commet/node 0.8.0 → 0.10.0

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 CHANGED
@@ -1,15 +1,22 @@
1
- # @commet/node
1
+ <div align="center">
2
+ <p align="center">
3
+ <a href="https://commet.co">
4
+ <img src="https://commet.co/logo-bg-dark.png" height="96">
5
+ <h3 align="center">Commet</h3>
6
+ </a>
7
+ </p>
8
+ <p>TypeScript SDK for Commet billing platform</p>
2
9
 
3
- TypeScript SDK for Commet billing platform - track usage, manage seats, and handle customers.
10
+ <a href="https://www.npmjs.com/package/@commet/node"><img alt="NPM version" src="https://img.shields.io/npm/v/@commet/node.svg?style=for-the-badge&labelColor=000000"></a>
11
+ <a href="https://docs.commet.co/docs/library/quickstart"><img alt="Documentation" src="https://img.shields.io/badge/docs-SDK-blue.svg?style=for-the-badge&labelColor=000000"></a>
12
+ </div>
13
+
14
+ <br/>
4
15
 
5
16
  ## Installation
6
17
 
7
18
  ```bash
8
19
  npm install @commet/node
9
- # or
10
- pnpm add @commet/node
11
- # or
12
- yarn add @commet/node
13
20
  ```
14
21
 
15
22
  ## Quick Start
@@ -18,260 +25,70 @@ yarn add @commet/node
18
25
  import { Commet } from '@commet/node';
19
26
 
20
27
  const commet = new Commet({
21
- apiKey: process.env.COMMET_API_KEY!,
22
- environment: 'production', // or 'sandbox' (default)
23
- debug: false, // Enable debug logging
28
+ apiKey: process.env.COMMET_API_KEY,
29
+ environment: 'production' // or 'sandbox'
24
30
  });
25
31
  ```
26
32
 
27
- ## Usage Examples
28
-
29
- ### Subscriptions (Simple API)
33
+ ## Usage
30
34
 
31
35
  ```typescript
32
- // Create subscription - Minimal (fixed product)
33
- await commet.subscriptions.create({
34
- productId: 'prod_enterprise_plan',
35
- customerId: 'cus_acme'
36
- });
37
- // Backend auto-configures: quantity=1, billingDay=today
38
-
39
- // Create with custom quantity
40
- await commet.subscriptions.create({
41
- productId: 'prod_api_platform',
42
- externalId: 'my-customer-123', // Use your own ID
43
- quantity: 5,
44
- status: 'active' // Generate invoice immediately
45
- });
46
-
47
- // Usage-based product (no quantity needed)
48
- await commet.subscriptions.create({
49
- productId: 'prod_api_calls',
50
- customerId: 'cus_startup'
51
- });
52
- // Backend uses usageMetricId from product
53
- // Send events: commet.usage.create(...)
54
-
55
- // Seat-based product
56
- await commet.subscriptions.create({
57
- productId: 'prod_saas_licenses',
58
- customerId: 'cus_tech_company',
59
- initialSeats: 10,
60
- name: 'Tech Company - SaaS Plan'
61
- });
62
- // Backend uses seatTypeId from product
63
- // Adjust seats: commet.seats.add(...)
64
-
65
- // List subscriptions
66
- const subs = await commet.subscriptions.list({
67
- customerId: 'cus_acme',
68
- status: 'active'
69
- });
70
-
71
- // Get subscription
72
- const sub = await commet.subscriptions.retrieve('sub_abc123');
73
-
74
- // Cancel subscription
75
- await commet.subscriptions.cancel('sub_abc123');
76
- ```
77
-
78
- ### Usage Events (Consumption-Based Billing)
79
-
80
- ```typescript
81
- // Send a single event using customerId (Commet's ID)
36
+ // Track usage events
82
37
  await commet.usage.create({
83
38
  eventType: 'api_call',
84
- customerId: 'cus_123',
85
- timestamp: new Date().toISOString(),
86
- properties: [
87
- { property: 'endpoint', value: '/api/users' },
88
- { property: 'method', value: 'GET' }
89
- ]
90
- });
91
-
92
- // OR use your own externalId
93
- await commet.usage.create({
94
- eventType: 'api_call',
95
- externalId: 'my-customer-123', // Your own customer ID
96
- timestamp: new Date().toISOString(),
97
- properties: [
98
- { property: 'endpoint', value: '/api/users' },
99
- { property: 'method', value: 'GET' }
100
- ]
101
- });
102
-
103
- // Batch events
104
- await commet.usage.createBatch({
105
- events: [
106
- { eventType: 'api_call', externalId: 'my-customer-123' },
107
- { eventType: 'api_call', customerId: 'cus_456' },
108
- ]
109
- });
110
-
111
- // List events
112
- const events = await commet.usage.list({
113
- externalId: 'my-customer-123', // Or use customerId
114
- limit: 100
39
+ customerId: 'cus_123'
115
40
  });
116
- ```
117
-
118
- ### Seat Management (Per-Seat Licensing)
119
41
 
120
- ```typescript
121
- // Add seats using customerId or externalId
42
+ // Manage seats
122
43
  await commet.seats.add({
123
- externalId: 'my-customer-123', // Or use customerId: 'cus_123'
44
+ customerId: 'cus_123',
124
45
  seatType: 'admin',
125
46
  count: 5
126
47
  });
127
48
 
128
- // Remove seats
129
- await commet.seats.remove({
130
- externalId: 'my-customer-123',
131
- seatType: 'admin',
132
- count: 2
133
- });
134
-
135
- // Set exact count
136
- await commet.seats.set({
137
- externalId: 'my-customer-123',
138
- seatType: 'admin',
139
- count: 10
140
- });
141
-
142
- // Get balance
143
- const balance = await commet.seats.getBalance({
144
- externalId: 'my-customer-123',
145
- seatType: 'admin'
146
- });
147
- console.log(balance.data.current); // 10
148
-
149
- // Get all balances for a customer
150
- const allBalances = await commet.seats.getAllBalances({
151
- externalId: 'my-customer-123'
152
- });
153
-
154
- // Bulk update multiple seat types
155
- await commet.seats.bulkUpdate({
156
- externalId: 'my-customer-123',
157
- seats: {
158
- admin: 5,
159
- editor: 20,
160
- viewer: 100
161
- }
162
- });
163
-
164
- // List seat events
165
- const events = await commet.seats.listEvents({
166
- externalId: 'my-customer-123',
167
- limit: 50
49
+ // Create subscriptions
50
+ await commet.subscriptions.create({
51
+ productId: 'prod_xxx',
52
+ customerId: 'cus_123',
53
+ status: 'active'
168
54
  });
169
- ```
170
55
 
171
- ### Customer Management
172
-
173
- ```typescript
174
- // Create customer
175
- const customer = await commet.customers.create({
176
- legalName: 'Acme Corporation',
177
- displayName: 'Acme',
178
- currency: 'USD',
179
- taxStatus: 'TAXED',
180
- address: {
181
- line1: '123 Main St',
182
- city: 'San Francisco',
183
- state: 'CA',
184
- postalCode: '94105',
185
- country: 'US'
186
- },
56
+ // Manage customers
57
+ await commet.customers.create({
58
+ legalName: 'Acme Corp',
187
59
  billingEmail: 'billing@acme.com'
188
60
  });
189
-
190
- // Update customer
191
- await commet.customers.update('cus_123', {
192
- displayName: 'Acme Inc',
193
- billingEmail: 'finance@acme.com'
194
- });
195
-
196
- // List customers
197
- const customers = await commet.customers.list({
198
- isActive: true,
199
- limit: 50
200
- });
201
-
202
- // Deactivate customer
203
- await commet.customers.deactivate('cus_123');
204
61
  ```
205
62
 
206
- ## API Reference
207
-
208
- ### Configuration
209
-
210
- ```typescript
211
- interface CommetConfig {
212
- apiKey: string; // Required: Your Commet API key
213
- environment?: 'sandbox' | 'production'; // Default: 'sandbox'
214
- debug?: boolean; // Default: false
215
- timeout?: number; // Request timeout in ms (default: 30000)
216
- retries?: number; // Max retry attempts (default: 3)
217
- }
218
- ```
219
-
220
- ### Resources
221
-
222
- - `commet.subscriptions` - Simple subscription management
223
- - `commet.usage` - Usage event tracking
224
- - `commet.seats` - Seat management
225
- - `commet.customers` - Customer CRUD operations
63
+ ## Type Safety
226
64
 
227
- ### Error Handling
65
+ Use the [Commet CLI](https://www.npmjs.com/package/commet) to generate TypeScript types from your organization:
228
66
 
229
- ```typescript
230
- import { CommetAPIError, CommetValidationError } from '@commet/node';
231
-
232
- try {
233
- await commet.usage.create({ ... });
234
- } catch (error) {
235
- if (error instanceof CommetValidationError) {
236
- console.error('Validation errors:', error.validationErrors);
237
- } else if (error instanceof CommetAPIError) {
238
- console.error('API error:', error.statusCode, error.message);
239
- }
240
- }
67
+ ```bash
68
+ npm install -g commet
69
+ commet login
70
+ commet link
71
+ commet pull
241
72
  ```
242
73
 
243
- ## Environment Detection
74
+ This generates type-safe autocomplete for your event types, seat types, and products.
244
75
 
245
- ```typescript
246
- // Check environment
247
- console.log(commet.getEnvironment()); // 'sandbox' | 'production'
248
- console.log(commet.isSandbox()); // boolean
249
- console.log(commet.isProduction()); // boolean
250
- ```
76
+ ## Documentation
251
77
 
252
- ## TypeScript Support
78
+ Visit [docs.commet.co/docs/library/quickstart](https://docs.commet.co/docs/library/quickstart) for:
253
79
 
254
- Fully typed with TypeScript. All API responses and parameters are type-safe.
80
+ - Complete API reference
81
+ - Advanced usage examples
82
+ - Error handling
83
+ - Best practices
255
84
 
256
- ```typescript
257
- import type {
258
- Subscription,
259
- CreateSubscriptionParams,
260
- Customer,
261
- UsageEvent,
262
- SeatBalance,
263
- Currency
264
- } from '@commet/node';
265
- ```
85
+ ## Resources
266
86
 
267
- ## Links
268
-
269
- - [Documentation](https://docs.commet.co)
270
- - [API Reference](https://docs.commet.co/api)
271
- - [GitHub](https://github.com/commet-labs/commet-node)
272
- - [Issues](https://github.com/commet-labs/commet-node/issues)
87
+ - [CLI Documentation](https://docs.commet.co/docs/library/cli/overview)
88
+ - [SDK Reference](https://docs.commet.co/docs/library/quickstart)
89
+ - [GitHub](https://github.com/commet-labs/commet)
90
+ - [Issues](https://github.com/commet-labs/commet/issues)
273
91
 
274
92
  ## License
275
93
 
276
94
  MIT
277
-
package/dist/index.d.mts CHANGED
@@ -90,6 +90,12 @@ type GeneratedEventType = CommetGeneratedTypes extends {
90
90
  type GeneratedSeatType = CommetGeneratedTypes extends {
91
91
  seatType: infer T;
92
92
  } ? T : string;
93
+ /**
94
+ * Helper type that provides fallback to string if types are not generated
95
+ */
96
+ type GeneratedProductId = CommetGeneratedTypes extends {
97
+ productId: infer T;
98
+ } ? T : string;
93
99
 
94
100
  declare class CommetHTTPClient {
95
101
  private config;
@@ -306,10 +312,9 @@ declare class SeatsResource {
306
312
  interface Subscription {
307
313
  id: string;
308
314
  customerId: string;
309
- productId?: string;
310
315
  name: string;
311
316
  description?: string;
312
- status: "draft" | "active" | "completed" | "canceled";
317
+ status: "draft" | "pending_payment" | "active" | "completed" | "canceled";
313
318
  startDate: string;
314
319
  endDate?: string;
315
320
  billingDayOfMonth: number;
@@ -317,9 +322,15 @@ interface Subscription {
317
322
  poNumber?: string;
318
323
  reference?: string;
319
324
  isTemplate?: boolean;
325
+ checkoutUrl?: string;
320
326
  createdAt: string;
321
327
  updatedAt: string;
322
328
  }
329
+ interface SubscriptionItem {
330
+ priceId: string;
331
+ quantity?: number;
332
+ initialSeats?: number;
333
+ }
323
334
  type CustomerIdentifier = {
324
335
  customerId: string;
325
336
  externalId?: never;
@@ -328,17 +339,15 @@ type CustomerIdentifier = {
328
339
  externalId: string;
329
340
  };
330
341
  type CreateSubscriptionParams = CustomerIdentifier & {
331
- productId: string;
342
+ items: SubscriptionItem[];
332
343
  name?: string;
333
344
  startDate?: string;
334
- status?: "draft" | "active";
335
- quantity?: number;
336
- initialSeats?: number;
345
+ status?: "draft" | "pending_payment" | "active";
337
346
  };
338
347
  interface ListSubscriptionsParams extends ListParams {
339
348
  customerId?: string;
340
349
  externalId?: string;
341
- status?: "draft" | "active" | "completed" | "canceled";
350
+ status?: "draft" | "pending_payment" | "active" | "completed" | "canceled";
342
351
  }
343
352
  /**
344
353
  * Subscription resource for managing subscriptions
@@ -347,29 +356,29 @@ declare class SubscriptionsResource {
347
356
  private httpClient;
348
357
  constructor(httpClient: CommetHTTPClient);
349
358
  /**
350
- * Create a simple subscription with smart defaults
359
+ * Create a subscription with multiple items (products)
351
360
  *
352
361
  * @example
353
362
  * ```typescript
354
- * // Minimal - Fixed product
355
- * await commet.subscriptions.create({
356
- * productId: "prod_xxx",
357
- * customerId: "cus_xxx"
358
- * });
359
- *
360
- * // With custom quantity
363
+ * // Free plan - Multiple products
361
364
  * await commet.subscriptions.create({
362
- * productId: "prod_xxx",
363
- * externalId: "my-customer-123",
364
- * quantity: 5,
365
- * status: "active"
365
+ * externalId: "org_123",
366
+ * items: [
367
+ * { priceId: "price_tasks_free", quantity: 1 },
368
+ * { priceId: "price_usage_free" },
369
+ * { priceId: "price_seats_free", initialSeats: 1 }
370
+ * ]
366
371
  * });
367
372
  *
368
- * // Seat-based product
373
+ * // Pro plan upgrade
369
374
  * await commet.subscriptions.create({
370
- * productId: "prod_saas",
371
375
  * customerId: "cus_xxx",
372
- * initialSeats: 10
376
+ * items: [
377
+ * { priceId: "price_tasks_pro" },
378
+ * { priceId: "price_usage_pro" },
379
+ * { priceId: "price_seats_pro", initialSeats: 5 }
380
+ * ],
381
+ * status: "active"
373
382
  * });
374
383
  * ```
375
384
  */
@@ -467,6 +476,105 @@ declare class UsageResource {
467
476
  }>>;
468
477
  }
469
478
 
479
+ /**
480
+ * Webhook payload structure from Commet
481
+ */
482
+ interface WebhookPayload {
483
+ event: WebhookEvent;
484
+ timestamp: string;
485
+ organizationId: string;
486
+ data: WebhookData;
487
+ }
488
+ /**
489
+ * Webhook data structure (subscription-related fields)
490
+ */
491
+ interface WebhookData {
492
+ id?: string;
493
+ publicId?: string;
494
+ subscriptionId?: string;
495
+ customerId?: string;
496
+ externalId?: string;
497
+ status?: string;
498
+ name?: string;
499
+ canceledAt?: string;
500
+ [key: string]: unknown;
501
+ }
502
+ /**
503
+ * Supported webhook events
504
+ */
505
+ type WebhookEvent = "subscription.created" | "subscription.activated" | "subscription.canceled" | "subscription.updated";
506
+ /**
507
+ * Webhooks resource for signature verification
508
+ */
509
+ declare class Webhooks {
510
+ /**
511
+ * Verify HMAC-SHA256 webhook signature
512
+ *
513
+ * Use this method to verify that webhooks are authentically from Commet.
514
+ * The signature is included in the `X-Commet-Signature` header.
515
+ *
516
+ * @param payload - Raw request body as string (IMPORTANT: Do not parse JSON first)
517
+ * @param signature - Value from X-Commet-Signature header
518
+ * @param secret - Your webhook secret from Commet dashboard
519
+ * @returns true if signature is valid, false otherwise
520
+ *
521
+ * @example
522
+ * ```typescript
523
+ * // Next.js API route example
524
+ * export async function POST(request: Request) {
525
+ * const rawBody = await request.text();
526
+ * const signature = request.headers.get('x-commet-signature');
527
+ *
528
+ * const isValid = commet.webhooks.verify(
529
+ * rawBody,
530
+ * signature,
531
+ * process.env.COMMET_WEBHOOK_SECRET
532
+ * );
533
+ *
534
+ * if (!isValid) {
535
+ * return new Response('Invalid signature', { status: 401 });
536
+ * }
537
+ *
538
+ * const payload = JSON.parse(rawBody);
539
+ * // Handle webhook event...
540
+ * }
541
+ * ```
542
+ */
543
+ verify(payload: string, signature: string | null, secret: string): boolean;
544
+ /**
545
+ * Generate HMAC-SHA256 signature (internal use)
546
+ * @internal
547
+ */
548
+ private generateSignature;
549
+ /**
550
+ * Parse and verify webhook payload in one step
551
+ *
552
+ * @param rawBody - Raw request body as string
553
+ * @param signature - Value from X-Commet-Signature header
554
+ * @param secret - Your webhook secret from Commet dashboard
555
+ * @returns Parsed payload if valid, null if invalid
556
+ *
557
+ * @example
558
+ * ```typescript
559
+ * const payload = commet.webhooks.verifyAndParse(
560
+ * rawBody,
561
+ * signature,
562
+ * process.env.COMMET_WEBHOOK_SECRET
563
+ * );
564
+ *
565
+ * if (!payload) {
566
+ * return new Response('Invalid signature', { status: 401 });
567
+ * }
568
+ *
569
+ * // payload is typed and validated
570
+ * if (payload.event === 'subscription.activated') {
571
+ * // Handle activation...
572
+ * }
573
+ * ```
574
+ */
575
+ verifyAndParse(rawBody: string, signature: string | null, secret: string): WebhookPayload | null;
576
+ }
577
+
470
578
  /**
471
579
  * Main Commet SDK client
472
580
  */
@@ -477,6 +585,7 @@ declare class Commet {
477
585
  readonly usage: UsageResource;
478
586
  readonly seats: SeatsResource;
479
587
  readonly subscriptions: SubscriptionsResource;
588
+ readonly webhooks: Webhooks;
480
589
  constructor(config: CommetConfig);
481
590
  getEnvironment(): Environment;
482
591
  isSandbox(): boolean;
@@ -496,4 +605,4 @@ declare function isProduction(environment: Environment): boolean;
496
605
  * Commet SDK - Billing and usage tracking SDK
497
606
  */
498
607
 
499
- export { type AddSeatsParams, type AgreementID, type ApiResponse, type BatchResult, type BulkSeatUpdate, type BulkUpdateSeatsParams, Commet, CommetAPIError, type CommetConfig, CommetError, type CommetGeneratedTypes, CommetValidationError, type CreateBatchUsageEventsParams, type CreateCustomerParams, type CreateSubscriptionParams, type CreateUsageEventParams, type Currency, type Customer, type CustomerID, type Environment, type EventID, type GeneratedEventType, type GeneratedSeatType, type GetAllBalancesParams, type GetBalanceParams, type InvoiceID, type ItemID, type ListCustomersParams, type ListParams, type ListSeatEventsParams, type ListSubscriptionsParams, type ListUsageEventsParams, type PaginatedList, type PaginatedResponse, type PhaseID, type ProductID, type RemoveSeatsParams, type RequestOptions, type RetrieveOptions, type SeatBalance, type SeatBalanceResponse, type SeatEvent, type SetSeatsParams, type Subscription, type UpdateCustomerParams, type UsageEvent, type UsageEventProperty, type WebhookID, Commet as default, isProduction, isSandbox };
608
+ export { type AddSeatsParams, type AgreementID, type ApiResponse, type BatchResult, type BulkSeatUpdate, type BulkUpdateSeatsParams, Commet, CommetAPIError, type CommetConfig, CommetError, type CommetGeneratedTypes, CommetValidationError, type CreateBatchUsageEventsParams, type CreateCustomerParams, type CreateSubscriptionParams, type CreateUsageEventParams, type Currency, type Customer, type CustomerID, type Environment, type EventID, type GeneratedEventType, type GeneratedProductId, type GeneratedSeatType, type GetAllBalancesParams, type GetBalanceParams, type InvoiceID, type ItemID, type ListCustomersParams, type ListParams, type ListSeatEventsParams, type ListSubscriptionsParams, type ListUsageEventsParams, type PaginatedList, type PaginatedResponse, type PhaseID, type ProductID, type RemoveSeatsParams, type RequestOptions, type RetrieveOptions, type SeatBalance, type SeatBalanceResponse, type SeatEvent, type SetSeatsParams, type Subscription, type SubscriptionItem, type UpdateCustomerParams, type UsageEvent, type UsageEventProperty, type WebhookData, type WebhookEvent, type WebhookID, type WebhookPayload, Commet as default, isProduction, isSandbox };