@commet/node 0.11.0 → 1.0.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/dist/index.js CHANGED
@@ -46,23 +46,84 @@ var CustomersResource = class {
46
46
  constructor(httpClient) {
47
47
  this.httpClient = httpClient;
48
48
  }
49
+ /**
50
+ * Create a customer (idempotent with externalId)
51
+ */
49
52
  async create(params, options) {
50
- return this.httpClient.post("/customers", params, options);
53
+ return this.httpClient.post(
54
+ "/customers",
55
+ {
56
+ billingEmail: params.email,
57
+ externalId: params.externalId,
58
+ legalName: params.legalName,
59
+ displayName: params.displayName,
60
+ domain: params.domain,
61
+ website: params.website,
62
+ timezone: params.timezone,
63
+ language: params.language,
64
+ industry: params.industry,
65
+ metadata: params.metadata,
66
+ address: params.address
67
+ },
68
+ options
69
+ );
70
+ }
71
+ /**
72
+ * Create multiple customers in batch
73
+ */
74
+ async createBatch(params, options) {
75
+ const customers = params.customers.map((c) => ({
76
+ billingEmail: c.email,
77
+ externalId: c.externalId,
78
+ legalName: c.legalName,
79
+ displayName: c.displayName,
80
+ domain: c.domain,
81
+ website: c.website,
82
+ timezone: c.timezone,
83
+ language: c.language,
84
+ industry: c.industry,
85
+ metadata: c.metadata,
86
+ address: c.address
87
+ }));
88
+ return this.httpClient.post("/customers/batch", { customers }, options);
51
89
  }
52
- async retrieve(customerId, options) {
53
- const params = options?.expand ? { expand: options.expand.join(",") } : void 0;
54
- return this.httpClient.get(`/customers/${customerId}`, params);
90
+ /**
91
+ * Get a customer by ID
92
+ */
93
+ async get(customerId) {
94
+ return this.httpClient.get(`/customers/${customerId}`);
55
95
  }
96
+ /**
97
+ * Update a customer
98
+ */
56
99
  async update(customerId, params, options) {
57
- return this.httpClient.put(`/customers/${customerId}`, params, options);
100
+ return this.httpClient.put(
101
+ `/customers/${customerId}`,
102
+ {
103
+ billingEmail: params.email,
104
+ externalId: params.externalId,
105
+ legalName: params.legalName,
106
+ displayName: params.displayName,
107
+ domain: params.domain,
108
+ website: params.website,
109
+ timezone: params.timezone,
110
+ language: params.language,
111
+ industry: params.industry,
112
+ metadata: params.metadata
113
+ },
114
+ options
115
+ );
58
116
  }
117
+ /**
118
+ * List customers with optional filters
119
+ */
59
120
  async list(params) {
60
121
  return this.httpClient.get("/customers", params);
61
122
  }
62
123
  /**
63
- * Deactivate a customer (soft delete)
124
+ * Archive a customer
64
125
  */
65
- async deactivate(customerId, options) {
126
+ async archive(customerId, options) {
66
127
  return this.httpClient.put(
67
128
  `/customers/${customerId}`,
68
129
  { isActive: false },
@@ -71,40 +132,55 @@ var CustomersResource = class {
71
132
  }
72
133
  };
73
134
 
74
- // src/resources/portal.ts
75
- var PortalResource = class {
135
+ // src/resources/plans.ts
136
+ var PlansResource = class {
76
137
  constructor(httpClient) {
77
138
  this.httpClient = httpClient;
78
139
  }
79
140
  /**
80
- * Request portal access for a customer
81
- *
82
- * Generates a secure portal URL that can be sent to the customer via email or used directly.
83
- * The URL contains a time-limited token for secure access to the customer portal.
84
- *
85
- * @param params - customerId, externalId, or email
86
- * @param options - Request options (idempotency, timeout)
87
- * @returns Portal access response with URL
141
+ * List all available plans
88
142
  *
89
143
  * @example
90
- * // External ID (recommended)
91
- * const portal = await commet.portal.requestAccess({
92
- * externalId: 'my-customer-123'
93
- * });
144
+ * ```typescript
145
+ * // List public plans
146
+ * const plans = await commet.plans.list();
147
+ *
148
+ * // Include private plans
149
+ * const allPlans = await commet.plans.list({ includePrivate: true });
150
+ * ```
151
+ */
152
+ async list(params) {
153
+ return this.httpClient.get("/plans", params);
154
+ }
155
+ /**
156
+ * Get a specific plan by ID
94
157
  *
95
158
  * @example
96
- * // Customer ID
97
- * const portal = await commet.portal.requestAccess({
98
- * customerId: 'cus_123'
99
- * });
159
+ * ```typescript
160
+ * const plan = await commet.plans.get('plan_xxx');
161
+ * console.log(plan.data.name); // "Pro"
162
+ * console.log(plan.data.prices); // [{ billingInterval: 'monthly', price: 9900 }]
163
+ * ```
164
+ */
165
+ async get(planId) {
166
+ return this.httpClient.get(`/plans/${planId}`);
167
+ }
168
+ };
169
+
170
+ // src/resources/portal.ts
171
+ var PortalResource = class {
172
+ constructor(httpClient) {
173
+ this.httpClient = httpClient;
174
+ }
175
+ /**
176
+ * Get a portal URL
100
177
  *
101
178
  * @example
102
- * // Email
103
- * const portal = await commet.portal.requestAccess({
104
- * email: 'customer@example.com'
105
- * });
179
+ * ```typescript
180
+ * const portal = await commet.portal.getUrl({ externalId: 'user_123' });
181
+ * ```
106
182
  */
107
- async requestAccess(params, options) {
183
+ async getUrl(params, options) {
108
184
  return this.httpClient.post("/portal/request-access", params, options);
109
185
  }
110
186
  };
@@ -114,53 +190,76 @@ var SeatsResource = class {
114
190
  constructor(httpClient) {
115
191
  this.httpClient = httpClient;
116
192
  }
193
+ /**
194
+ * Add seats
195
+ *
196
+ * @example
197
+ * ```typescript
198
+ * await commet.seats.add({
199
+ * externalId: 'user_123',
200
+ * seatType: 'editor',
201
+ * count: 5
202
+ * });
203
+ * ```
204
+ */
117
205
  async add(params, options) {
118
- return this.httpClient.post(
119
- "/seats",
120
- {
121
- customerId: params.customerId,
122
- externalId: params.externalId,
123
- seatType: params.seatType,
124
- count: params.count
125
- },
126
- options
127
- );
206
+ return this.httpClient.post("/seats", params, options);
128
207
  }
208
+ /**
209
+ * Remove seats
210
+ *
211
+ * @example
212
+ * ```typescript
213
+ * await commet.seats.remove({
214
+ * externalId: 'user_123',
215
+ * seatType: 'editor',
216
+ * count: 2
217
+ * });
218
+ * ```
219
+ */
129
220
  async remove(params, options) {
130
- return this.httpClient.delete(
131
- "/seats",
132
- {
133
- customerId: params.customerId,
134
- externalId: params.externalId,
135
- seatType: params.seatType,
136
- count: params.count
137
- },
138
- options
139
- );
221
+ return this.httpClient.delete("/seats", params, options);
140
222
  }
223
+ /**
224
+ * Set seats to a specific count
225
+ *
226
+ * @example
227
+ * ```typescript
228
+ * await commet.seats.set({
229
+ * externalId: 'user_123',
230
+ * seatType: 'editor',
231
+ * count: 10
232
+ * });
233
+ * ```
234
+ */
141
235
  async set(params, options) {
142
- return this.httpClient.put(
143
- "/seats",
144
- {
145
- customerId: params.customerId,
146
- externalId: params.externalId,
147
- seatType: params.seatType,
148
- count: params.count
149
- },
150
- options
151
- );
236
+ return this.httpClient.put("/seats", params, options);
152
237
  }
153
- async bulkUpdate(params, options) {
154
- return this.httpClient.put(
155
- "/seats/bulk",
156
- {
157
- customerId: params.customerId,
158
- externalId: params.externalId,
159
- seats: params.seats
160
- },
161
- options
162
- );
238
+ /**
239
+ * Set all seat types
240
+ *
241
+ * @example
242
+ * ```typescript
243
+ * await commet.seats.setAll({
244
+ * externalId: 'user_123',
245
+ * seats: { editor: 10, viewer: 50 }
246
+ * });
247
+ * ```
248
+ */
249
+ async setAll(params, options) {
250
+ return this.httpClient.put("/seats/bulk", params, options);
163
251
  }
252
+ /**
253
+ * Get balance for a seat type
254
+ *
255
+ * @example
256
+ * ```typescript
257
+ * const balance = await commet.seats.getBalance({
258
+ * externalId: 'user_123',
259
+ * seatType: 'editor'
260
+ * });
261
+ * ```
262
+ */
164
263
  async getBalance(params) {
165
264
  return this.httpClient.get("/seats/balance", {
166
265
  customerId: params.customerId,
@@ -168,15 +267,22 @@ var SeatsResource = class {
168
267
  seatType: params.seatType
169
268
  });
170
269
  }
270
+ /**
271
+ * Get all seat balances
272
+ *
273
+ * @example
274
+ * ```typescript
275
+ * const balances = await commet.seats.getAllBalances({
276
+ * externalId: 'user_123'
277
+ * });
278
+ * ```
279
+ */
171
280
  async getAllBalances(params) {
172
281
  return this.httpClient.get("/seats/balances", {
173
282
  customerId: params.customerId,
174
283
  externalId: params.externalId
175
284
  });
176
285
  }
177
- async listEvents(params) {
178
- return this.httpClient.get("/seats/events", params);
179
- }
180
286
  };
181
287
 
182
288
  // src/resources/subscriptions.ts
@@ -185,29 +291,15 @@ var SubscriptionsResource = class {
185
291
  this.httpClient = httpClient;
186
292
  }
187
293
  /**
188
- * Create a subscription with multiple items (products)
294
+ * Create a subscription with a plan
189
295
  *
190
296
  * @example
191
297
  * ```typescript
192
- * // Free plan - Multiple products
193
- * await commet.subscriptions.create({
194
- * externalId: "org_123",
195
- * items: [
196
- * { priceId: "price_tasks_free", quantity: 1 },
197
- * { priceId: "price_usage_free" },
198
- * { priceId: "price_seats_free", initialSeats: 1 }
199
- * ]
200
- * });
201
- *
202
- * // Pro plan upgrade
203
298
  * await commet.subscriptions.create({
204
- * customerId: "cus_xxx",
205
- * items: [
206
- * { priceId: "price_tasks_pro" },
207
- * { priceId: "price_usage_pro" },
208
- * { priceId: "price_seats_pro", initialSeats: 5 }
209
- * ],
210
- * status: "active"
299
+ * externalId: 'user_123',
300
+ * planCode: 'pro', // autocomplete works after `commet pull`
301
+ * billingInterval: 'yearly',
302
+ * initialSeats: { editor: 5 }
211
303
  * });
212
304
  * ```
213
305
  */
@@ -215,44 +307,47 @@ var SubscriptionsResource = class {
215
307
  return this.httpClient.post("/subscriptions", params, options);
216
308
  }
217
309
  /**
218
- * Retrieve a subscription by ID
310
+ * Get the active subscription for a customer
311
+ *
312
+ * @example
313
+ * ```typescript
314
+ * const sub = await commet.subscriptions.get({ externalId: 'user_123' });
315
+ * ```
219
316
  */
220
- async retrieve(subscriptionId, options) {
221
- const params = options?.expand ? { expand: options.expand.join(",") } : void 0;
222
- return this.httpClient.get(`/subscriptions/${subscriptionId}`, params);
317
+ async get(params) {
318
+ return this.httpClient.get("/subscriptions/active", params);
223
319
  }
224
320
  /**
225
- * List subscriptions with optional filters
321
+ * Change the plan of a subscription (upgrade/downgrade)
226
322
  *
227
323
  * @example
228
324
  * ```typescript
229
- * // List all active subscriptions for a customer
230
- * await commet.subscriptions.list({
231
- * customerId: "cus_xxx",
232
- * status: "active"
233
- * });
234
- *
235
- * // Using externalId
236
- * await commet.subscriptions.list({
237
- * externalId: "my-customer-123"
325
+ * await commet.subscriptions.changePlan('sub_xxx', {
326
+ * planCode: 'enterprise' // autocomplete works after `commet pull`
238
327
  * });
239
328
  * ```
240
329
  */
241
- async list(params) {
242
- return this.httpClient.get("/subscriptions", params);
330
+ async changePlan(subscriptionId, params, options) {
331
+ return this.httpClient.post(
332
+ `/subscriptions/${subscriptionId}/change-plan`,
333
+ params,
334
+ options
335
+ );
243
336
  }
244
337
  /**
245
338
  * Cancel a subscription
246
339
  *
247
340
  * @example
248
341
  * ```typescript
249
- * await commet.subscriptions.cancel("sub_xxx");
342
+ * await commet.subscriptions.cancel('sub_xxx', {
343
+ * reason: 'switched_to_competitor'
344
+ * });
250
345
  * ```
251
346
  */
252
- async cancel(subscriptionId, options) {
347
+ async cancel(subscriptionId, params, options) {
253
348
  return this.httpClient.post(
254
349
  `/subscriptions/${subscriptionId}/cancel`,
255
- {},
350
+ params || {},
256
351
  options
257
352
  );
258
353
  }
@@ -263,28 +358,59 @@ var UsageResource = class {
263
358
  constructor(httpClient) {
264
359
  this.httpClient = httpClient;
265
360
  }
266
- async create(params, options) {
361
+ /**
362
+ * Track a usage event
363
+ *
364
+ * @example
365
+ * ```typescript
366
+ * await commet.usage.track({
367
+ * externalId: 'user_123',
368
+ * eventType: 'api_call',
369
+ * idempotencyKey: `evt_${requestId}`,
370
+ * properties: { endpoint: '/users', method: 'GET' }
371
+ * });
372
+ * ```
373
+ */
374
+ async track(params, options) {
267
375
  const eventData = {
268
- ...params,
269
- ts: params.timestamp || (/* @__PURE__ */ new Date()).toISOString()
376
+ eventType: params.eventType,
377
+ customerId: params.customerId,
378
+ externalId: params.externalId,
379
+ idempotencyKey: params.idempotencyKey,
380
+ ts: params.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
381
+ properties: params.properties ? Object.entries(params.properties).map(([property, value]) => ({
382
+ property,
383
+ value
384
+ })) : void 0
270
385
  };
271
386
  return this.httpClient.post("/usage/events", eventData, options);
272
387
  }
273
- async createBatch(params, options) {
274
- return this.httpClient.post("/usage/events/batch", params, options);
275
- }
276
- async retrieve(eventId) {
277
- return this.httpClient.get(`/usage/events/${eventId}`);
278
- }
279
- async list(params) {
280
- return this.httpClient.get("/usage/events", params);
281
- }
282
- async delete(eventId, options) {
283
- return this.httpClient.delete(
284
- `/usage/events/${eventId}`,
285
- void 0,
286
- options
287
- );
388
+ /**
389
+ * Track multiple usage events in a batch
390
+ *
391
+ * @example
392
+ * ```typescript
393
+ * await commet.usage.trackBatch({
394
+ * events: [
395
+ * { externalId: 'user_123', eventType: 'api_call', idempotencyKey: 'evt_1' },
396
+ * { externalId: 'user_456', eventType: 'api_call', idempotencyKey: 'evt_2' }
397
+ * ]
398
+ * });
399
+ * ```
400
+ */
401
+ async trackBatch(params, options) {
402
+ const events = params.events.map((event) => ({
403
+ eventType: event.eventType,
404
+ customerId: event.customerId,
405
+ externalId: event.externalId,
406
+ idempotencyKey: event.idempotencyKey,
407
+ ts: event.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
408
+ properties: event.properties ? Object.entries(event.properties).map(([property, value]) => ({
409
+ property,
410
+ value
411
+ })) : void 0
412
+ }));
413
+ return this.httpClient.post("/usage/events/batch", { events }, options);
288
414
  }
289
415
  };
290
416
 
@@ -487,7 +613,6 @@ var CommetHTTPClient = class {
487
613
  let responseData;
488
614
  let responseText;
489
615
  try {
490
- const responseClone = response.clone();
491
616
  responseData = await response.json();
492
617
  responseText = "";
493
618
  } catch (jsonError) {
@@ -502,6 +627,12 @@ var CommetHTTPClient = class {
502
627
  responseText
503
628
  );
504
629
  }
630
+ if (response.status === 404) {
631
+ return {
632
+ success: false,
633
+ error: "Resource not found"
634
+ };
635
+ }
505
636
  throw new CommetAPIError(
506
637
  `Invalid JSON response: ${response.status} ${response.statusText}`,
507
638
  response.status,
@@ -627,6 +758,7 @@ var Commet = class {
627
758
  this.environment = config.environment || "sandbox";
628
759
  this.httpClient = new CommetHTTPClient(config, this.environment);
629
760
  this.customers = new CustomersResource(this.httpClient);
761
+ this.plans = new PlansResource(this.httpClient);
630
762
  this.usage = new UsageResource(this.httpClient);
631
763
  this.seats = new SeatsResource(this.httpClient);
632
764
  this.subscriptions = new SubscriptionsResource(this.httpClient);