@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.mjs CHANGED
@@ -3,23 +3,84 @@ var CustomersResource = class {
3
3
  constructor(httpClient) {
4
4
  this.httpClient = httpClient;
5
5
  }
6
+ /**
7
+ * Create a customer (idempotent with externalId)
8
+ */
6
9
  async create(params, options) {
7
- return this.httpClient.post("/customers", params, options);
10
+ return this.httpClient.post(
11
+ "/customers",
12
+ {
13
+ billingEmail: params.email,
14
+ externalId: params.externalId,
15
+ legalName: params.legalName,
16
+ displayName: params.displayName,
17
+ domain: params.domain,
18
+ website: params.website,
19
+ timezone: params.timezone,
20
+ language: params.language,
21
+ industry: params.industry,
22
+ metadata: params.metadata,
23
+ address: params.address
24
+ },
25
+ options
26
+ );
27
+ }
28
+ /**
29
+ * Create multiple customers in batch
30
+ */
31
+ async createBatch(params, options) {
32
+ const customers = params.customers.map((c) => ({
33
+ billingEmail: c.email,
34
+ externalId: c.externalId,
35
+ legalName: c.legalName,
36
+ displayName: c.displayName,
37
+ domain: c.domain,
38
+ website: c.website,
39
+ timezone: c.timezone,
40
+ language: c.language,
41
+ industry: c.industry,
42
+ metadata: c.metadata,
43
+ address: c.address
44
+ }));
45
+ return this.httpClient.post("/customers/batch", { customers }, options);
8
46
  }
9
- async retrieve(customerId, options) {
10
- const params = options?.expand ? { expand: options.expand.join(",") } : void 0;
11
- return this.httpClient.get(`/customers/${customerId}`, params);
47
+ /**
48
+ * Get a customer by ID
49
+ */
50
+ async get(customerId) {
51
+ return this.httpClient.get(`/customers/${customerId}`);
12
52
  }
53
+ /**
54
+ * Update a customer
55
+ */
13
56
  async update(customerId, params, options) {
14
- return this.httpClient.put(`/customers/${customerId}`, params, options);
57
+ return this.httpClient.put(
58
+ `/customers/${customerId}`,
59
+ {
60
+ billingEmail: params.email,
61
+ externalId: params.externalId,
62
+ legalName: params.legalName,
63
+ displayName: params.displayName,
64
+ domain: params.domain,
65
+ website: params.website,
66
+ timezone: params.timezone,
67
+ language: params.language,
68
+ industry: params.industry,
69
+ metadata: params.metadata
70
+ },
71
+ options
72
+ );
15
73
  }
74
+ /**
75
+ * List customers with optional filters
76
+ */
16
77
  async list(params) {
17
78
  return this.httpClient.get("/customers", params);
18
79
  }
19
80
  /**
20
- * Deactivate a customer (soft delete)
81
+ * Archive a customer
21
82
  */
22
- async deactivate(customerId, options) {
83
+ async archive(customerId, options) {
23
84
  return this.httpClient.put(
24
85
  `/customers/${customerId}`,
25
86
  { isActive: false },
@@ -28,40 +89,55 @@ var CustomersResource = class {
28
89
  }
29
90
  };
30
91
 
31
- // src/resources/portal.ts
32
- var PortalResource = class {
92
+ // src/resources/plans.ts
93
+ var PlansResource = class {
33
94
  constructor(httpClient) {
34
95
  this.httpClient = httpClient;
35
96
  }
36
97
  /**
37
- * Request portal access for a customer
38
- *
39
- * Generates a secure portal URL that can be sent to the customer via email or used directly.
40
- * The URL contains a time-limited token for secure access to the customer portal.
41
- *
42
- * @param params - customerId, externalId, or email
43
- * @param options - Request options (idempotency, timeout)
44
- * @returns Portal access response with URL
98
+ * List all available plans
45
99
  *
46
100
  * @example
47
- * // External ID (recommended)
48
- * const portal = await commet.portal.requestAccess({
49
- * externalId: 'my-customer-123'
50
- * });
101
+ * ```typescript
102
+ * // List public plans
103
+ * const plans = await commet.plans.list();
104
+ *
105
+ * // Include private plans
106
+ * const allPlans = await commet.plans.list({ includePrivate: true });
107
+ * ```
108
+ */
109
+ async list(params) {
110
+ return this.httpClient.get("/plans", params);
111
+ }
112
+ /**
113
+ * Get a specific plan by ID
51
114
  *
52
115
  * @example
53
- * // Customer ID
54
- * const portal = await commet.portal.requestAccess({
55
- * customerId: 'cus_123'
56
- * });
116
+ * ```typescript
117
+ * const plan = await commet.plans.get('plan_xxx');
118
+ * console.log(plan.data.name); // "Pro"
119
+ * console.log(plan.data.prices); // [{ billingInterval: 'monthly', price: 9900 }]
120
+ * ```
121
+ */
122
+ async get(planId) {
123
+ return this.httpClient.get(`/plans/${planId}`);
124
+ }
125
+ };
126
+
127
+ // src/resources/portal.ts
128
+ var PortalResource = class {
129
+ constructor(httpClient) {
130
+ this.httpClient = httpClient;
131
+ }
132
+ /**
133
+ * Get a portal URL
57
134
  *
58
135
  * @example
59
- * // Email
60
- * const portal = await commet.portal.requestAccess({
61
- * email: 'customer@example.com'
62
- * });
136
+ * ```typescript
137
+ * const portal = await commet.portal.getUrl({ externalId: 'user_123' });
138
+ * ```
63
139
  */
64
- async requestAccess(params, options) {
140
+ async getUrl(params, options) {
65
141
  return this.httpClient.post("/portal/request-access", params, options);
66
142
  }
67
143
  };
@@ -71,53 +147,76 @@ var SeatsResource = class {
71
147
  constructor(httpClient) {
72
148
  this.httpClient = httpClient;
73
149
  }
150
+ /**
151
+ * Add seats
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * await commet.seats.add({
156
+ * externalId: 'user_123',
157
+ * seatType: 'editor',
158
+ * count: 5
159
+ * });
160
+ * ```
161
+ */
74
162
  async add(params, options) {
75
- return this.httpClient.post(
76
- "/seats",
77
- {
78
- customerId: params.customerId,
79
- externalId: params.externalId,
80
- seatType: params.seatType,
81
- count: params.count
82
- },
83
- options
84
- );
163
+ return this.httpClient.post("/seats", params, options);
85
164
  }
165
+ /**
166
+ * Remove seats
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * await commet.seats.remove({
171
+ * externalId: 'user_123',
172
+ * seatType: 'editor',
173
+ * count: 2
174
+ * });
175
+ * ```
176
+ */
86
177
  async remove(params, options) {
87
- return this.httpClient.delete(
88
- "/seats",
89
- {
90
- customerId: params.customerId,
91
- externalId: params.externalId,
92
- seatType: params.seatType,
93
- count: params.count
94
- },
95
- options
96
- );
178
+ return this.httpClient.delete("/seats", params, options);
97
179
  }
180
+ /**
181
+ * Set seats to a specific count
182
+ *
183
+ * @example
184
+ * ```typescript
185
+ * await commet.seats.set({
186
+ * externalId: 'user_123',
187
+ * seatType: 'editor',
188
+ * count: 10
189
+ * });
190
+ * ```
191
+ */
98
192
  async set(params, options) {
99
- return this.httpClient.put(
100
- "/seats",
101
- {
102
- customerId: params.customerId,
103
- externalId: params.externalId,
104
- seatType: params.seatType,
105
- count: params.count
106
- },
107
- options
108
- );
193
+ return this.httpClient.put("/seats", params, options);
109
194
  }
110
- async bulkUpdate(params, options) {
111
- return this.httpClient.put(
112
- "/seats/bulk",
113
- {
114
- customerId: params.customerId,
115
- externalId: params.externalId,
116
- seats: params.seats
117
- },
118
- options
119
- );
195
+ /**
196
+ * Set all seat types
197
+ *
198
+ * @example
199
+ * ```typescript
200
+ * await commet.seats.setAll({
201
+ * externalId: 'user_123',
202
+ * seats: { editor: 10, viewer: 50 }
203
+ * });
204
+ * ```
205
+ */
206
+ async setAll(params, options) {
207
+ return this.httpClient.put("/seats/bulk", params, options);
120
208
  }
209
+ /**
210
+ * Get balance for a seat type
211
+ *
212
+ * @example
213
+ * ```typescript
214
+ * const balance = await commet.seats.getBalance({
215
+ * externalId: 'user_123',
216
+ * seatType: 'editor'
217
+ * });
218
+ * ```
219
+ */
121
220
  async getBalance(params) {
122
221
  return this.httpClient.get("/seats/balance", {
123
222
  customerId: params.customerId,
@@ -125,15 +224,22 @@ var SeatsResource = class {
125
224
  seatType: params.seatType
126
225
  });
127
226
  }
227
+ /**
228
+ * Get all seat balances
229
+ *
230
+ * @example
231
+ * ```typescript
232
+ * const balances = await commet.seats.getAllBalances({
233
+ * externalId: 'user_123'
234
+ * });
235
+ * ```
236
+ */
128
237
  async getAllBalances(params) {
129
238
  return this.httpClient.get("/seats/balances", {
130
239
  customerId: params.customerId,
131
240
  externalId: params.externalId
132
241
  });
133
242
  }
134
- async listEvents(params) {
135
- return this.httpClient.get("/seats/events", params);
136
- }
137
243
  };
138
244
 
139
245
  // src/resources/subscriptions.ts
@@ -142,29 +248,15 @@ var SubscriptionsResource = class {
142
248
  this.httpClient = httpClient;
143
249
  }
144
250
  /**
145
- * Create a subscription with multiple items (products)
251
+ * Create a subscription with a plan
146
252
  *
147
253
  * @example
148
254
  * ```typescript
149
- * // Free plan - Multiple products
150
- * await commet.subscriptions.create({
151
- * externalId: "org_123",
152
- * items: [
153
- * { priceId: "price_tasks_free", quantity: 1 },
154
- * { priceId: "price_usage_free" },
155
- * { priceId: "price_seats_free", initialSeats: 1 }
156
- * ]
157
- * });
158
- *
159
- * // Pro plan upgrade
160
255
  * await commet.subscriptions.create({
161
- * customerId: "cus_xxx",
162
- * items: [
163
- * { priceId: "price_tasks_pro" },
164
- * { priceId: "price_usage_pro" },
165
- * { priceId: "price_seats_pro", initialSeats: 5 }
166
- * ],
167
- * status: "active"
256
+ * externalId: 'user_123',
257
+ * planCode: 'pro', // autocomplete works after `commet pull`
258
+ * billingInterval: 'yearly',
259
+ * initialSeats: { editor: 5 }
168
260
  * });
169
261
  * ```
170
262
  */
@@ -172,44 +264,47 @@ var SubscriptionsResource = class {
172
264
  return this.httpClient.post("/subscriptions", params, options);
173
265
  }
174
266
  /**
175
- * Retrieve a subscription by ID
267
+ * Get the active subscription for a customer
268
+ *
269
+ * @example
270
+ * ```typescript
271
+ * const sub = await commet.subscriptions.get({ externalId: 'user_123' });
272
+ * ```
176
273
  */
177
- async retrieve(subscriptionId, options) {
178
- const params = options?.expand ? { expand: options.expand.join(",") } : void 0;
179
- return this.httpClient.get(`/subscriptions/${subscriptionId}`, params);
274
+ async get(params) {
275
+ return this.httpClient.get("/subscriptions/active", params);
180
276
  }
181
277
  /**
182
- * List subscriptions with optional filters
278
+ * Change the plan of a subscription (upgrade/downgrade)
183
279
  *
184
280
  * @example
185
281
  * ```typescript
186
- * // List all active subscriptions for a customer
187
- * await commet.subscriptions.list({
188
- * customerId: "cus_xxx",
189
- * status: "active"
190
- * });
191
- *
192
- * // Using externalId
193
- * await commet.subscriptions.list({
194
- * externalId: "my-customer-123"
282
+ * await commet.subscriptions.changePlan('sub_xxx', {
283
+ * planCode: 'enterprise' // autocomplete works after `commet pull`
195
284
  * });
196
285
  * ```
197
286
  */
198
- async list(params) {
199
- return this.httpClient.get("/subscriptions", params);
287
+ async changePlan(subscriptionId, params, options) {
288
+ return this.httpClient.post(
289
+ `/subscriptions/${subscriptionId}/change-plan`,
290
+ params,
291
+ options
292
+ );
200
293
  }
201
294
  /**
202
295
  * Cancel a subscription
203
296
  *
204
297
  * @example
205
298
  * ```typescript
206
- * await commet.subscriptions.cancel("sub_xxx");
299
+ * await commet.subscriptions.cancel('sub_xxx', {
300
+ * reason: 'switched_to_competitor'
301
+ * });
207
302
  * ```
208
303
  */
209
- async cancel(subscriptionId, options) {
304
+ async cancel(subscriptionId, params, options) {
210
305
  return this.httpClient.post(
211
306
  `/subscriptions/${subscriptionId}/cancel`,
212
- {},
307
+ params || {},
213
308
  options
214
309
  );
215
310
  }
@@ -220,28 +315,59 @@ var UsageResource = class {
220
315
  constructor(httpClient) {
221
316
  this.httpClient = httpClient;
222
317
  }
223
- async create(params, options) {
318
+ /**
319
+ * Track a usage event
320
+ *
321
+ * @example
322
+ * ```typescript
323
+ * await commet.usage.track({
324
+ * externalId: 'user_123',
325
+ * eventType: 'api_call',
326
+ * idempotencyKey: `evt_${requestId}`,
327
+ * properties: { endpoint: '/users', method: 'GET' }
328
+ * });
329
+ * ```
330
+ */
331
+ async track(params, options) {
224
332
  const eventData = {
225
- ...params,
226
- ts: params.timestamp || (/* @__PURE__ */ new Date()).toISOString()
333
+ eventType: params.eventType,
334
+ customerId: params.customerId,
335
+ externalId: params.externalId,
336
+ idempotencyKey: params.idempotencyKey,
337
+ ts: params.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
338
+ properties: params.properties ? Object.entries(params.properties).map(([property, value]) => ({
339
+ property,
340
+ value
341
+ })) : void 0
227
342
  };
228
343
  return this.httpClient.post("/usage/events", eventData, options);
229
344
  }
230
- async createBatch(params, options) {
231
- return this.httpClient.post("/usage/events/batch", params, options);
232
- }
233
- async retrieve(eventId) {
234
- return this.httpClient.get(`/usage/events/${eventId}`);
235
- }
236
- async list(params) {
237
- return this.httpClient.get("/usage/events", params);
238
- }
239
- async delete(eventId, options) {
240
- return this.httpClient.delete(
241
- `/usage/events/${eventId}`,
242
- void 0,
243
- options
244
- );
345
+ /**
346
+ * Track multiple usage events in a batch
347
+ *
348
+ * @example
349
+ * ```typescript
350
+ * await commet.usage.trackBatch({
351
+ * events: [
352
+ * { externalId: 'user_123', eventType: 'api_call', idempotencyKey: 'evt_1' },
353
+ * { externalId: 'user_456', eventType: 'api_call', idempotencyKey: 'evt_2' }
354
+ * ]
355
+ * });
356
+ * ```
357
+ */
358
+ async trackBatch(params, options) {
359
+ const events = params.events.map((event) => ({
360
+ eventType: event.eventType,
361
+ customerId: event.customerId,
362
+ externalId: event.externalId,
363
+ idempotencyKey: event.idempotencyKey,
364
+ ts: event.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
365
+ properties: event.properties ? Object.entries(event.properties).map(([property, value]) => ({
366
+ property,
367
+ value
368
+ })) : void 0
369
+ }));
370
+ return this.httpClient.post("/usage/events/batch", { events }, options);
245
371
  }
246
372
  };
247
373
 
@@ -444,7 +570,6 @@ var CommetHTTPClient = class {
444
570
  let responseData;
445
571
  let responseText;
446
572
  try {
447
- const responseClone = response.clone();
448
573
  responseData = await response.json();
449
574
  responseText = "";
450
575
  } catch (jsonError) {
@@ -459,6 +584,12 @@ var CommetHTTPClient = class {
459
584
  responseText
460
585
  );
461
586
  }
587
+ if (response.status === 404) {
588
+ return {
589
+ success: false,
590
+ error: "Resource not found"
591
+ };
592
+ }
462
593
  throw new CommetAPIError(
463
594
  `Invalid JSON response: ${response.status} ${response.statusText}`,
464
595
  response.status,
@@ -584,6 +715,7 @@ var Commet = class {
584
715
  this.environment = config.environment || "sandbox";
585
716
  this.httpClient = new CommetHTTPClient(config, this.environment);
586
717
  this.customers = new CustomersResource(this.httpClient);
718
+ this.plans = new PlansResource(this.httpClient);
587
719
  this.usage = new UsageResource(this.httpClient);
588
720
  this.seats = new SeatsResource(this.httpClient);
589
721
  this.subscriptions = new SubscriptionsResource(this.httpClient);