@monigo/sdk 0.1.2
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 +712 -0
- package/dist/index.d.ts +992 -0
- package/dist/monigo.cjs +806 -0
- package/dist/monigo.cjs.map +1 -0
- package/dist/monigo.js +806 -0
- package/dist/monigo.js.map +1 -0
- package/package.json +60 -0
package/dist/monigo.cjs
ADDED
|
@@ -0,0 +1,806 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
class MonigoAPIError extends Error {
|
|
4
|
+
constructor(statusCode, message, details) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "MonigoAPIError";
|
|
7
|
+
this.statusCode = statusCode;
|
|
8
|
+
this.message = message;
|
|
9
|
+
this.details = details;
|
|
10
|
+
const capture = Error["captureStackTrace"];
|
|
11
|
+
capture?.(this, MonigoAPIError);
|
|
12
|
+
}
|
|
13
|
+
// -------------------------------------------------------------------------
|
|
14
|
+
// Instance guards (for use on a caught error known to be MonigoAPIError)
|
|
15
|
+
// -------------------------------------------------------------------------
|
|
16
|
+
get isNotFound() {
|
|
17
|
+
return this.statusCode === 404;
|
|
18
|
+
}
|
|
19
|
+
get isUnauthorized() {
|
|
20
|
+
return this.statusCode === 401;
|
|
21
|
+
}
|
|
22
|
+
get isForbidden() {
|
|
23
|
+
return this.statusCode === 403;
|
|
24
|
+
}
|
|
25
|
+
get isRateLimited() {
|
|
26
|
+
return this.statusCode === 429;
|
|
27
|
+
}
|
|
28
|
+
get isConflict() {
|
|
29
|
+
return this.statusCode === 409;
|
|
30
|
+
}
|
|
31
|
+
get isQuotaExceeded() {
|
|
32
|
+
return this.statusCode === 402;
|
|
33
|
+
}
|
|
34
|
+
get isServerError() {
|
|
35
|
+
return this.statusCode >= 500;
|
|
36
|
+
}
|
|
37
|
+
// -------------------------------------------------------------------------
|
|
38
|
+
// Static type-narrowing helpers (for use in catch clauses on `unknown`)
|
|
39
|
+
// -------------------------------------------------------------------------
|
|
40
|
+
static isNotFound(err) {
|
|
41
|
+
return err instanceof MonigoAPIError && err.statusCode === 404;
|
|
42
|
+
}
|
|
43
|
+
static isUnauthorized(err) {
|
|
44
|
+
return err instanceof MonigoAPIError && err.statusCode === 401;
|
|
45
|
+
}
|
|
46
|
+
static isForbidden(err) {
|
|
47
|
+
return err instanceof MonigoAPIError && err.statusCode === 403;
|
|
48
|
+
}
|
|
49
|
+
static isRateLimited(err) {
|
|
50
|
+
return err instanceof MonigoAPIError && err.statusCode === 429;
|
|
51
|
+
}
|
|
52
|
+
static isConflict(err) {
|
|
53
|
+
return err instanceof MonigoAPIError && err.statusCode === 409;
|
|
54
|
+
}
|
|
55
|
+
static isQuotaExceeded(err) {
|
|
56
|
+
return err instanceof MonigoAPIError && err.statusCode === 402;
|
|
57
|
+
}
|
|
58
|
+
static isServerError(err) {
|
|
59
|
+
return err instanceof MonigoAPIError && err.statusCode >= 500;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
class EventsResource {
|
|
63
|
+
constructor(client) {
|
|
64
|
+
this.client = client;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Ingest one or more usage events into the Monigo pipeline.
|
|
68
|
+
*
|
|
69
|
+
* Events are processed asynchronously. The response confirms receipt
|
|
70
|
+
* and reports any duplicate idempotency keys.
|
|
71
|
+
*
|
|
72
|
+
* **Requires `ingest` scope.**
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* const result = await monigo.events.ingest({
|
|
77
|
+
* events: [{
|
|
78
|
+
* event_name: 'api_call',
|
|
79
|
+
* customer_id: 'cust_abc',
|
|
80
|
+
* idempotency_key: crypto.randomUUID(),
|
|
81
|
+
* timestamp: new Date().toISOString(),
|
|
82
|
+
* properties: { endpoint: '/checkout', region: 'eu-west-1' },
|
|
83
|
+
* }],
|
|
84
|
+
* })
|
|
85
|
+
* console.log('Ingested:', result.ingested.length)
|
|
86
|
+
* console.log('Duplicates:', result.duplicates.length)
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
async ingest(request) {
|
|
90
|
+
const body = {
|
|
91
|
+
events: request.events.map((e) => ({
|
|
92
|
+
...e,
|
|
93
|
+
timestamp: e.timestamp ? MonigoClient.toISOString(e.timestamp) : (/* @__PURE__ */ new Date()).toISOString()
|
|
94
|
+
}))
|
|
95
|
+
};
|
|
96
|
+
return this.client._request("POST", "/v1/ingest", { body });
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Start an asynchronous replay of all raw events in a given time window
|
|
100
|
+
* through the current processing pipeline. Useful for backfilling usage
|
|
101
|
+
* data after changing metric definitions.
|
|
102
|
+
*
|
|
103
|
+
* Returns a replay job immediately — poll `getReplay()` to track progress.
|
|
104
|
+
*
|
|
105
|
+
* **Requires `ingest` scope.**
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* const job = await monigo.events.startReplay({
|
|
110
|
+
* from: '2025-01-01T00:00:00Z',
|
|
111
|
+
* to: '2025-01-31T23:59:59Z',
|
|
112
|
+
* event_name: 'api_call', // omit to replay all event types
|
|
113
|
+
* })
|
|
114
|
+
* console.log('Replay job:', job.id, job.status)
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
async startReplay(request) {
|
|
118
|
+
const body = {
|
|
119
|
+
from: MonigoClient.toISOString(request.from),
|
|
120
|
+
to: MonigoClient.toISOString(request.to),
|
|
121
|
+
...request.event_name ? { event_name: request.event_name } : {}
|
|
122
|
+
};
|
|
123
|
+
const wrapper = await this.client._request(
|
|
124
|
+
"POST",
|
|
125
|
+
"/v1/events/replay",
|
|
126
|
+
{ body }
|
|
127
|
+
);
|
|
128
|
+
return wrapper.job;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Fetch the current status and progress of an event replay job.
|
|
132
|
+
*
|
|
133
|
+
* **Requires `ingest` scope.**
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* const job = await monigo.events.getReplay(jobId)
|
|
138
|
+
* if (job.status === 'completed') {
|
|
139
|
+
* console.log(`Replayed ${job.events_replayed} / ${job.events_total} events`)
|
|
140
|
+
* }
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
async getReplay(jobId) {
|
|
144
|
+
const wrapper = await this.client._request(
|
|
145
|
+
"GET",
|
|
146
|
+
`/v1/events/replay/${jobId}`
|
|
147
|
+
);
|
|
148
|
+
return wrapper.job;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
class CustomersResource {
|
|
152
|
+
constructor(client) {
|
|
153
|
+
this.client = client;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Register a new customer.
|
|
157
|
+
*
|
|
158
|
+
* **Requires `write` scope.**
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```ts
|
|
162
|
+
* const customer = await monigo.customers.create({
|
|
163
|
+
* external_id: 'usr_12345',
|
|
164
|
+
* name: 'Acme Corp',
|
|
165
|
+
* email: 'billing@acme.com',
|
|
166
|
+
* metadata: { plan_tier: 'enterprise' },
|
|
167
|
+
* })
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
async create(request) {
|
|
171
|
+
const wrapper = await this.client._request(
|
|
172
|
+
"POST",
|
|
173
|
+
"/v1/customers",
|
|
174
|
+
{ body: request }
|
|
175
|
+
);
|
|
176
|
+
return wrapper.customer;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Return all customers in the authenticated organisation.
|
|
180
|
+
*
|
|
181
|
+
* **Requires `read` scope.**
|
|
182
|
+
*/
|
|
183
|
+
async list() {
|
|
184
|
+
return this.client._request("GET", "/v1/customers");
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Fetch a single customer by their Monigo UUID.
|
|
188
|
+
*
|
|
189
|
+
* **Requires `read` scope.**
|
|
190
|
+
*/
|
|
191
|
+
async get(customerId) {
|
|
192
|
+
const wrapper = await this.client._request(
|
|
193
|
+
"GET",
|
|
194
|
+
`/v1/customers/${customerId}`
|
|
195
|
+
);
|
|
196
|
+
return wrapper.customer;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Update a customer's name, email, or metadata.
|
|
200
|
+
* Only fields that are present in `request` are updated.
|
|
201
|
+
*
|
|
202
|
+
* **Requires `write` scope.**
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* ```ts
|
|
206
|
+
* const updated = await monigo.customers.update(customerId, {
|
|
207
|
+
* email: 'new@acme.com',
|
|
208
|
+
* })
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
async update(customerId, request) {
|
|
212
|
+
const wrapper = await this.client._request(
|
|
213
|
+
"PUT",
|
|
214
|
+
`/v1/customers/${customerId}`,
|
|
215
|
+
{ body: request }
|
|
216
|
+
);
|
|
217
|
+
return wrapper.customer;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Permanently delete a customer record.
|
|
221
|
+
*
|
|
222
|
+
* **Requires `write` scope.**
|
|
223
|
+
*/
|
|
224
|
+
async delete(customerId) {
|
|
225
|
+
await this.client._request("DELETE", `/v1/customers/${customerId}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
class MetricsResource {
|
|
229
|
+
constructor(client) {
|
|
230
|
+
this.client = client;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Create a new metric.
|
|
234
|
+
*
|
|
235
|
+
* **Requires `write` scope.**
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```ts
|
|
239
|
+
* const metric = await monigo.metrics.create({
|
|
240
|
+
* name: 'API Calls',
|
|
241
|
+
* event_name: 'api_call',
|
|
242
|
+
* aggregation: 'count',
|
|
243
|
+
* })
|
|
244
|
+
* ```
|
|
245
|
+
*/
|
|
246
|
+
async create(request) {
|
|
247
|
+
const wrapper = await this.client._request(
|
|
248
|
+
"POST",
|
|
249
|
+
"/v1/metrics",
|
|
250
|
+
{ body: request }
|
|
251
|
+
);
|
|
252
|
+
return wrapper.metric;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Return all metrics in the authenticated organisation.
|
|
256
|
+
*
|
|
257
|
+
* **Requires `read` scope.**
|
|
258
|
+
*/
|
|
259
|
+
async list() {
|
|
260
|
+
return this.client._request("GET", "/v1/metrics");
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Fetch a single metric by its UUID.
|
|
264
|
+
*
|
|
265
|
+
* **Requires `read` scope.**
|
|
266
|
+
*/
|
|
267
|
+
async get(metricId) {
|
|
268
|
+
const wrapper = await this.client._request(
|
|
269
|
+
"GET",
|
|
270
|
+
`/v1/metrics/${metricId}`
|
|
271
|
+
);
|
|
272
|
+
return wrapper.metric;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Update a metric's name, event name, aggregation, or description.
|
|
276
|
+
*
|
|
277
|
+
* **Requires `write` scope.**
|
|
278
|
+
*/
|
|
279
|
+
async update(metricId, request) {
|
|
280
|
+
const wrapper = await this.client._request(
|
|
281
|
+
"PUT",
|
|
282
|
+
`/v1/metrics/${metricId}`,
|
|
283
|
+
{ body: request }
|
|
284
|
+
);
|
|
285
|
+
return wrapper.metric;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Permanently delete a metric.
|
|
289
|
+
*
|
|
290
|
+
* **Requires `write` scope.**
|
|
291
|
+
*/
|
|
292
|
+
async delete(metricId) {
|
|
293
|
+
await this.client._request("DELETE", `/v1/metrics/${metricId}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
class PlansResource {
|
|
297
|
+
constructor(client) {
|
|
298
|
+
this.client = client;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Create a new billing plan, optionally with prices attached.
|
|
302
|
+
*
|
|
303
|
+
* **Requires `write` scope.**
|
|
304
|
+
*
|
|
305
|
+
* @example
|
|
306
|
+
* ```ts
|
|
307
|
+
* const plan = await monigo.plans.create({
|
|
308
|
+
* name: 'Pro',
|
|
309
|
+
* currency: 'NGN',
|
|
310
|
+
* billing_period: 'monthly',
|
|
311
|
+
* prices: [{
|
|
312
|
+
* metric_id: 'metric_abc',
|
|
313
|
+
* model: 'flat',
|
|
314
|
+
* unit_price: '2.500000',
|
|
315
|
+
* }],
|
|
316
|
+
* })
|
|
317
|
+
* ```
|
|
318
|
+
*/
|
|
319
|
+
async create(request) {
|
|
320
|
+
const wrapper = await this.client._request(
|
|
321
|
+
"POST",
|
|
322
|
+
"/v1/plans",
|
|
323
|
+
{ body: request }
|
|
324
|
+
);
|
|
325
|
+
return wrapper.plan;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Return all billing plans in the authenticated organisation.
|
|
329
|
+
*
|
|
330
|
+
* **Requires `read` scope.**
|
|
331
|
+
*/
|
|
332
|
+
async list() {
|
|
333
|
+
return this.client._request("GET", "/v1/plans");
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Fetch a single plan by its UUID, including its prices.
|
|
337
|
+
*
|
|
338
|
+
* **Requires `read` scope.**
|
|
339
|
+
*/
|
|
340
|
+
async get(planId) {
|
|
341
|
+
const wrapper = await this.client._request(
|
|
342
|
+
"GET",
|
|
343
|
+
`/v1/plans/${planId}`
|
|
344
|
+
);
|
|
345
|
+
return wrapper.plan;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Update a plan's name, description, currency, or prices.
|
|
349
|
+
*
|
|
350
|
+
* **Requires `write` scope.**
|
|
351
|
+
*/
|
|
352
|
+
async update(planId, request) {
|
|
353
|
+
const wrapper = await this.client._request(
|
|
354
|
+
"PUT",
|
|
355
|
+
`/v1/plans/${planId}`,
|
|
356
|
+
{ body: request }
|
|
357
|
+
);
|
|
358
|
+
return wrapper.plan;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Permanently delete a plan.
|
|
362
|
+
*
|
|
363
|
+
* **Requires `write` scope.**
|
|
364
|
+
*/
|
|
365
|
+
async delete(planId) {
|
|
366
|
+
await this.client._request("DELETE", `/v1/plans/${planId}`);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
class SubscriptionsResource {
|
|
370
|
+
constructor(client) {
|
|
371
|
+
this.client = client;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Subscribe a customer to a plan.
|
|
375
|
+
*
|
|
376
|
+
* Returns a 409 Conflict error (check with `MonigoAPIError.isConflict(err)`)
|
|
377
|
+
* if the customer already has an active subscription to the same plan.
|
|
378
|
+
*
|
|
379
|
+
* **Requires `write` scope.**
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```ts
|
|
383
|
+
* const sub = await monigo.subscriptions.create({
|
|
384
|
+
* customer_id: 'cust_abc',
|
|
385
|
+
* plan_id: 'plan_xyz',
|
|
386
|
+
* })
|
|
387
|
+
* ```
|
|
388
|
+
*/
|
|
389
|
+
async create(request) {
|
|
390
|
+
const wrapper = await this.client._request(
|
|
391
|
+
"POST",
|
|
392
|
+
"/v1/subscriptions",
|
|
393
|
+
{ body: request }
|
|
394
|
+
);
|
|
395
|
+
return wrapper.subscription;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Return subscriptions, optionally filtered by customer, plan, or status.
|
|
399
|
+
*
|
|
400
|
+
* **Requires `read` scope.**
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* ```ts
|
|
404
|
+
* const { subscriptions } = await monigo.subscriptions.list({
|
|
405
|
+
* customer_id: 'cust_abc',
|
|
406
|
+
* status: 'active',
|
|
407
|
+
* })
|
|
408
|
+
* ```
|
|
409
|
+
*/
|
|
410
|
+
async list(params = {}) {
|
|
411
|
+
return this.client._request("GET", "/v1/subscriptions", {
|
|
412
|
+
query: {
|
|
413
|
+
customer_id: params.customer_id,
|
|
414
|
+
plan_id: params.plan_id,
|
|
415
|
+
status: params.status
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Fetch a single subscription by its UUID.
|
|
421
|
+
*
|
|
422
|
+
* **Requires `read` scope.**
|
|
423
|
+
*/
|
|
424
|
+
async get(subscriptionId) {
|
|
425
|
+
const wrapper = await this.client._request(
|
|
426
|
+
"GET",
|
|
427
|
+
`/v1/subscriptions/${subscriptionId}`
|
|
428
|
+
);
|
|
429
|
+
return wrapper.subscription;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Change the status of a subscription.
|
|
433
|
+
* Use `SubscriptionStatus` constants: `"active"`, `"paused"`, `"canceled"`.
|
|
434
|
+
*
|
|
435
|
+
* **Requires `write` scope.**
|
|
436
|
+
*
|
|
437
|
+
* @example
|
|
438
|
+
* ```ts
|
|
439
|
+
* await monigo.subscriptions.updateStatus(subId, SubscriptionStatus.Paused)
|
|
440
|
+
* ```
|
|
441
|
+
*/
|
|
442
|
+
async updateStatus(subscriptionId, status) {
|
|
443
|
+
const wrapper = await this.client._request(
|
|
444
|
+
"PATCH",
|
|
445
|
+
`/v1/subscriptions/${subscriptionId}`,
|
|
446
|
+
{ body: { status } }
|
|
447
|
+
);
|
|
448
|
+
return wrapper.subscription;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Cancel and delete a subscription record.
|
|
452
|
+
*
|
|
453
|
+
* **Requires `write` scope.**
|
|
454
|
+
*/
|
|
455
|
+
async delete(subscriptionId) {
|
|
456
|
+
await this.client._request("DELETE", `/v1/subscriptions/${subscriptionId}`);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
class PayoutAccountsResource {
|
|
460
|
+
constructor(client) {
|
|
461
|
+
this.client = client;
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Add a payout account for a customer.
|
|
465
|
+
*
|
|
466
|
+
* **Requires `write` scope.**
|
|
467
|
+
*
|
|
468
|
+
* @example
|
|
469
|
+
* ```ts
|
|
470
|
+
* const account = await monigo.payoutAccounts.create('cust_abc', {
|
|
471
|
+
* account_name: 'Acme Corp',
|
|
472
|
+
* payout_method: 'bank_transfer',
|
|
473
|
+
* bank_name: 'Zenith Bank',
|
|
474
|
+
* bank_code: '057',
|
|
475
|
+
* account_number: '1234567890',
|
|
476
|
+
* currency: 'NGN',
|
|
477
|
+
* is_default: true,
|
|
478
|
+
* })
|
|
479
|
+
* ```
|
|
480
|
+
*/
|
|
481
|
+
async create(customerId, request) {
|
|
482
|
+
const wrapper = await this.client._request(
|
|
483
|
+
"POST",
|
|
484
|
+
`/v1/customers/${customerId}/payout-accounts`,
|
|
485
|
+
{ body: request }
|
|
486
|
+
);
|
|
487
|
+
return wrapper.payout_account;
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Return all payout accounts for a customer.
|
|
491
|
+
*
|
|
492
|
+
* **Requires `read` scope.**
|
|
493
|
+
*/
|
|
494
|
+
async list(customerId) {
|
|
495
|
+
return this.client._request(
|
|
496
|
+
"GET",
|
|
497
|
+
`/v1/customers/${customerId}/payout-accounts`
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Fetch a single payout account by its UUID.
|
|
502
|
+
*
|
|
503
|
+
* **Requires `read` scope.**
|
|
504
|
+
*/
|
|
505
|
+
async get(customerId, accountId) {
|
|
506
|
+
const wrapper = await this.client._request(
|
|
507
|
+
"GET",
|
|
508
|
+
`/v1/customers/${customerId}/payout-accounts/${accountId}`
|
|
509
|
+
);
|
|
510
|
+
return wrapper.payout_account;
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Update a payout account's details.
|
|
514
|
+
*
|
|
515
|
+
* **Requires `write` scope.**
|
|
516
|
+
*/
|
|
517
|
+
async update(customerId, accountId, request) {
|
|
518
|
+
const wrapper = await this.client._request(
|
|
519
|
+
"PUT",
|
|
520
|
+
`/v1/customers/${customerId}/payout-accounts/${accountId}`,
|
|
521
|
+
{ body: request }
|
|
522
|
+
);
|
|
523
|
+
return wrapper.payout_account;
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Delete a payout account.
|
|
527
|
+
*
|
|
528
|
+
* **Requires `write` scope.**
|
|
529
|
+
*/
|
|
530
|
+
async delete(customerId, accountId) {
|
|
531
|
+
await this.client._request(
|
|
532
|
+
"DELETE",
|
|
533
|
+
`/v1/customers/${customerId}/payout-accounts/${accountId}`
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
class InvoicesResource {
|
|
538
|
+
constructor(client) {
|
|
539
|
+
this.client = client;
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Generate a draft invoice for a subscription based on current period usage.
|
|
543
|
+
* The invoice starts in `"draft"` status and is not sent to the customer yet.
|
|
544
|
+
*
|
|
545
|
+
* **Requires `write` scope.**
|
|
546
|
+
*
|
|
547
|
+
* @example
|
|
548
|
+
* ```ts
|
|
549
|
+
* const invoice = await monigo.invoices.generate('sub_xyz')
|
|
550
|
+
* console.log('Draft invoice total:', invoice.total)
|
|
551
|
+
* ```
|
|
552
|
+
*/
|
|
553
|
+
async generate(subscriptionId) {
|
|
554
|
+
const wrapper = await this.client._request(
|
|
555
|
+
"POST",
|
|
556
|
+
"/v1/invoices/generate",
|
|
557
|
+
{ body: { subscription_id: subscriptionId } }
|
|
558
|
+
);
|
|
559
|
+
return wrapper.invoice;
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Return invoices, optionally filtered by status or customer.
|
|
563
|
+
*
|
|
564
|
+
* **Requires `read` scope.**
|
|
565
|
+
*
|
|
566
|
+
* @example
|
|
567
|
+
* ```ts
|
|
568
|
+
* const { invoices } = await monigo.invoices.list({
|
|
569
|
+
* status: 'finalized',
|
|
570
|
+
* customer_id: 'cust_abc',
|
|
571
|
+
* })
|
|
572
|
+
* ```
|
|
573
|
+
*/
|
|
574
|
+
async list(params = {}) {
|
|
575
|
+
return this.client._request("GET", "/v1/invoices", {
|
|
576
|
+
query: {
|
|
577
|
+
status: params.status,
|
|
578
|
+
customer_id: params.customer_id
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Fetch a single invoice by its UUID, including line items.
|
|
584
|
+
*
|
|
585
|
+
* **Requires `read` scope.**
|
|
586
|
+
*/
|
|
587
|
+
async get(invoiceId) {
|
|
588
|
+
const wrapper = await this.client._request(
|
|
589
|
+
"GET",
|
|
590
|
+
`/v1/invoices/${invoiceId}`
|
|
591
|
+
);
|
|
592
|
+
return wrapper.invoice;
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Finalize a draft invoice, making it ready for payment.
|
|
596
|
+
* A finalized invoice cannot be edited.
|
|
597
|
+
*
|
|
598
|
+
* **Requires `write` scope.**
|
|
599
|
+
*/
|
|
600
|
+
async finalize(invoiceId) {
|
|
601
|
+
const wrapper = await this.client._request(
|
|
602
|
+
"POST",
|
|
603
|
+
`/v1/invoices/${invoiceId}/finalize`
|
|
604
|
+
);
|
|
605
|
+
return wrapper.invoice;
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Void an invoice, making it permanently non-payable.
|
|
609
|
+
* Only admins and owners can void invoices.
|
|
610
|
+
*
|
|
611
|
+
* **Requires `write` scope.**
|
|
612
|
+
*/
|
|
613
|
+
async void(invoiceId) {
|
|
614
|
+
const wrapper = await this.client._request(
|
|
615
|
+
"POST",
|
|
616
|
+
`/v1/invoices/${invoiceId}/void`
|
|
617
|
+
);
|
|
618
|
+
return wrapper.invoice;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
class UsageResource {
|
|
622
|
+
constructor(client) {
|
|
623
|
+
this.client = client;
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Return per-customer, per-metric usage rollups for the organisation.
|
|
627
|
+
* All parameters are optional — omitting them returns the full current
|
|
628
|
+
* billing period for all customers and metrics.
|
|
629
|
+
*
|
|
630
|
+
* **Requires `read` scope.**
|
|
631
|
+
*
|
|
632
|
+
* @example
|
|
633
|
+
* ```ts
|
|
634
|
+
* // All usage for one customer this period
|
|
635
|
+
* const { rollups } = await monigo.usage.query({
|
|
636
|
+
* customer_id: 'cust_abc',
|
|
637
|
+
* })
|
|
638
|
+
*
|
|
639
|
+
* // Filtered by metric and custom date range
|
|
640
|
+
* const { rollups: filtered } = await monigo.usage.query({
|
|
641
|
+
* metric_id: 'metric_xyz',
|
|
642
|
+
* from: '2025-01-01T00:00:00Z',
|
|
643
|
+
* to: '2025-01-31T23:59:59Z',
|
|
644
|
+
* })
|
|
645
|
+
* ```
|
|
646
|
+
*/
|
|
647
|
+
async query(params = {}) {
|
|
648
|
+
const query = {
|
|
649
|
+
customer_id: params.customer_id,
|
|
650
|
+
metric_id: params.metric_id
|
|
651
|
+
};
|
|
652
|
+
if (params.from !== void 0) {
|
|
653
|
+
query.from = MonigoClient.toISOString(params.from);
|
|
654
|
+
}
|
|
655
|
+
if (params.to !== void 0) {
|
|
656
|
+
query.to = MonigoClient.toISOString(params.to);
|
|
657
|
+
}
|
|
658
|
+
return this.client._request("GET", "/v1/usage", { query });
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
const DEFAULT_BASE_URL = "https://api.monigo.co";
|
|
662
|
+
const DEFAULT_TIMEOUT_MS = 3e4;
|
|
663
|
+
class MonigoClient {
|
|
664
|
+
constructor(options) {
|
|
665
|
+
if (!options.apiKey) {
|
|
666
|
+
throw new Error("MonigoClient: apiKey is required");
|
|
667
|
+
}
|
|
668
|
+
this._apiKey = options.apiKey;
|
|
669
|
+
this._baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
670
|
+
this._timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
671
|
+
const fetchFn = options.fetch ?? (typeof globalThis !== "undefined" ? globalThis.fetch : void 0);
|
|
672
|
+
if (!fetchFn) {
|
|
673
|
+
throw new Error(
|
|
674
|
+
"MonigoClient: fetch is not available in this environment. Pass a custom fetch implementation via options.fetch, or upgrade to Node.js 18+."
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
this._fetchFn = fetchFn.bind(globalThis);
|
|
678
|
+
this.events = new EventsResource(this);
|
|
679
|
+
this.customers = new CustomersResource(this);
|
|
680
|
+
this.metrics = new MetricsResource(this);
|
|
681
|
+
this.plans = new PlansResource(this);
|
|
682
|
+
this.subscriptions = new SubscriptionsResource(this);
|
|
683
|
+
this.payoutAccounts = new PayoutAccountsResource(this);
|
|
684
|
+
this.invoices = new InvoicesResource(this);
|
|
685
|
+
this.usage = new UsageResource(this);
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Execute an authenticated HTTP request against the Monigo API.
|
|
689
|
+
* @internal — use the resource methods instead.
|
|
690
|
+
*/
|
|
691
|
+
async _request(method, path, options = {}) {
|
|
692
|
+
let url = this._baseURL + path;
|
|
693
|
+
if (options.query) {
|
|
694
|
+
const params = new URLSearchParams();
|
|
695
|
+
for (const [key, value] of Object.entries(options.query)) {
|
|
696
|
+
if (value !== void 0 && value !== "") {
|
|
697
|
+
params.set(key, value);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
const qs = params.toString();
|
|
701
|
+
if (qs) url += "?" + qs;
|
|
702
|
+
}
|
|
703
|
+
const controller = new AbortController();
|
|
704
|
+
const timeoutId = setTimeout(() => controller.abort(), this._timeout);
|
|
705
|
+
try {
|
|
706
|
+
const response = await this._fetchFn(url, {
|
|
707
|
+
method,
|
|
708
|
+
headers: {
|
|
709
|
+
Authorization: `Bearer ${this._apiKey}`,
|
|
710
|
+
"Content-Type": "application/json",
|
|
711
|
+
Accept: "application/json"
|
|
712
|
+
},
|
|
713
|
+
body: options.body != null ? JSON.stringify(options.body) : void 0,
|
|
714
|
+
signal: controller.signal
|
|
715
|
+
});
|
|
716
|
+
const text = await response.text();
|
|
717
|
+
if (!response.ok) {
|
|
718
|
+
let message = text || response.statusText;
|
|
719
|
+
let details;
|
|
720
|
+
try {
|
|
721
|
+
const parsed = JSON.parse(text);
|
|
722
|
+
message = parsed.error ?? parsed.message ?? message;
|
|
723
|
+
details = parsed.details;
|
|
724
|
+
} catch {
|
|
725
|
+
}
|
|
726
|
+
throw new MonigoAPIError(response.status, message, details);
|
|
727
|
+
}
|
|
728
|
+
if (!text) return void 0;
|
|
729
|
+
return JSON.parse(text);
|
|
730
|
+
} catch (err) {
|
|
731
|
+
if (err instanceof MonigoAPIError) throw err;
|
|
732
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
733
|
+
throw new Error(
|
|
734
|
+
`MonigoClient: request to ${url} timed out after ${this._timeout}ms`
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
throw err;
|
|
738
|
+
} finally {
|
|
739
|
+
clearTimeout(timeoutId);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
/** Normalise a `Date | string` value to an ISO 8601 string. */
|
|
743
|
+
static toISOString(value) {
|
|
744
|
+
return value instanceof Date ? value.toISOString() : value;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
const Aggregation = {
|
|
748
|
+
Count: "count",
|
|
749
|
+
Sum: "sum",
|
|
750
|
+
Max: "max",
|
|
751
|
+
Min: "minimum",
|
|
752
|
+
Average: "average",
|
|
753
|
+
Unique: "unique"
|
|
754
|
+
};
|
|
755
|
+
const PricingModel = {
|
|
756
|
+
Flat: "flat",
|
|
757
|
+
Tiered: "tiered",
|
|
758
|
+
Volume: "volume",
|
|
759
|
+
Package: "package",
|
|
760
|
+
Overage: "overage",
|
|
761
|
+
WeightedTiered: "weighted_tiered"
|
|
762
|
+
};
|
|
763
|
+
const PlanType = {
|
|
764
|
+
Collection: "collection",
|
|
765
|
+
Payout: "payout"
|
|
766
|
+
};
|
|
767
|
+
const BillingPeriod = {
|
|
768
|
+
Daily: "daily",
|
|
769
|
+
Weekly: "weekly",
|
|
770
|
+
Monthly: "monthly",
|
|
771
|
+
Quarterly: "quarterly",
|
|
772
|
+
Annually: "annually"
|
|
773
|
+
};
|
|
774
|
+
const SubscriptionStatus = {
|
|
775
|
+
Active: "active",
|
|
776
|
+
Paused: "paused",
|
|
777
|
+
Canceled: "canceled"
|
|
778
|
+
};
|
|
779
|
+
const InvoiceStatus = {
|
|
780
|
+
Draft: "draft",
|
|
781
|
+
Finalized: "finalized",
|
|
782
|
+
Paid: "paid",
|
|
783
|
+
Void: "void"
|
|
784
|
+
};
|
|
785
|
+
const PayoutMethod = {
|
|
786
|
+
BankTransfer: "bank_transfer",
|
|
787
|
+
MobileMoney: "mobile_money"
|
|
788
|
+
};
|
|
789
|
+
exports.Aggregation = Aggregation;
|
|
790
|
+
exports.BillingPeriod = BillingPeriod;
|
|
791
|
+
exports.CustomersResource = CustomersResource;
|
|
792
|
+
exports.EventsResource = EventsResource;
|
|
793
|
+
exports.InvoiceStatus = InvoiceStatus;
|
|
794
|
+
exports.InvoicesResource = InvoicesResource;
|
|
795
|
+
exports.MetricsResource = MetricsResource;
|
|
796
|
+
exports.MonigoAPIError = MonigoAPIError;
|
|
797
|
+
exports.MonigoClient = MonigoClient;
|
|
798
|
+
exports.PayoutAccountsResource = PayoutAccountsResource;
|
|
799
|
+
exports.PayoutMethod = PayoutMethod;
|
|
800
|
+
exports.PlanType = PlanType;
|
|
801
|
+
exports.PlansResource = PlansResource;
|
|
802
|
+
exports.PricingModel = PricingModel;
|
|
803
|
+
exports.SubscriptionStatus = SubscriptionStatus;
|
|
804
|
+
exports.SubscriptionsResource = SubscriptionsResource;
|
|
805
|
+
exports.UsageResource = UsageResource;
|
|
806
|
+
//# sourceMappingURL=monigo.cjs.map
|