@ophelio/sdk 0.1.0 → 0.2.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 +63 -45
- package/dist/index.cjs +120 -21
- package/dist/index.d.cts +164 -23
- package/dist/index.d.mts +164 -23
- package/dist/index.mjs +119 -22
- package/package.json +12 -2
package/README.md
CHANGED
|
@@ -5,9 +5,7 @@ membership & entitlement API. Works on Node 20+, Cloudflare Workers, Deno and
|
|
|
5
5
|
Bun — zero runtime dependencies, ESM + CJS, fully typed from the platform's
|
|
6
6
|
OpenAPI spec.
|
|
7
7
|
|
|
8
|
-
> **Status:** pre-1.0. Minor versions may contain breaking changes
|
|
9
|
-
> notably, list-method return shapes will change when the API gains
|
|
10
|
-
> pagination).
|
|
8
|
+
> **Status:** pre-1.0. Minor versions may contain breaking changes.
|
|
11
9
|
|
|
12
10
|
## Install
|
|
13
11
|
|
|
@@ -42,17 +40,6 @@ Pass your project API key (`o_live_…`); the project is implied by the key:
|
|
|
42
40
|
new Ophelio({ apiKey: 'o_live_…' })
|
|
43
41
|
```
|
|
44
42
|
|
|
45
|
-
For first-party / server-side session use, pass auth headers instead and
|
|
46
|
-
optionally your own `fetch`:
|
|
47
|
-
|
|
48
|
-
```ts
|
|
49
|
-
new Ophelio({
|
|
50
|
-
baseUrl: 'https://api.your-deployment.example',
|
|
51
|
-
headers: { cookie: cookieHeader },
|
|
52
|
-
fetch: event.fetch, // e.g. SvelteKit
|
|
53
|
-
})
|
|
54
|
-
```
|
|
55
|
-
|
|
56
43
|
## Errors
|
|
57
44
|
|
|
58
45
|
Non-2xx responses throw a typed subclass of `OphelioError` mapped from the
|
|
@@ -115,44 +102,75 @@ switch (event.type) {
|
|
|
115
102
|
Unknown event types still verify and parse, so new platform events don't
|
|
116
103
|
break older SDK versions.
|
|
117
104
|
|
|
105
|
+
## Pagination
|
|
106
|
+
|
|
107
|
+
The larger list endpoints are paginated. Their `list*` methods accept an
|
|
108
|
+
optional `{ page_size?, page_token? }` and resolve to a `Page<T>`:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
interface Page<T> {
|
|
112
|
+
items: T[]
|
|
113
|
+
next_page_token: string // '' on the last page
|
|
114
|
+
total_size: number // exact count across all pages
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Most of the time, let `paginate` walk the pages for you — pass a closure that
|
|
119
|
+
forwards the pagination params, capturing any ids, filters and options in it:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
import { collect, paginate } from '@ophelio/sdk'
|
|
123
|
+
|
|
124
|
+
for await (const membership of paginate((page) =>
|
|
125
|
+
ophelio.memberships.list(page),
|
|
126
|
+
)) {
|
|
127
|
+
// …
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// nested + filtered:
|
|
131
|
+
for await (const change of paginate((page) =>
|
|
132
|
+
ophelio.memberships.listScheduledChanges(id, { ...page, status: 'all' }),
|
|
133
|
+
)) {
|
|
134
|
+
// …
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// or drain everything into an array (loads the whole collection into memory):
|
|
138
|
+
const customers = await collect((page) => ophelio.customers.list(page))
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
To page manually — e.g. to surface `total_size` or drive numbered pages — feed
|
|
142
|
+
`next_page_token` back in as `page_token` until it comes back empty.
|
|
143
|
+
|
|
144
|
+
`page_size` defaults to 50 and is capped at 250. Because pagination is
|
|
145
|
+
offset-based, a row can be seen twice or skipped across a page boundary if the
|
|
146
|
+
collection is written to while you iterate. Paginated methods are marked
|
|
147
|
+
`(params?)` in the table below; the bounded lists (config resources,
|
|
148
|
+
`listMembers`) return a plain array.
|
|
149
|
+
|
|
118
150
|
## API surface
|
|
119
151
|
|
|
120
152
|
Everything reachable with an API key is covered:
|
|
121
153
|
|
|
122
|
-
| Namespace | Methods
|
|
123
|
-
| ---------------------------- |
|
|
124
|
-
| `admit` | `check({ card })`
|
|
125
|
-
| `members` | `sync({ since? })`, `get(id)`, `listEntitlements(id, { type? })`, `reissueCard(id, { note? })`
|
|
126
|
-
| `memberships` | `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `cancel(id, ...)`, `uncancel(id)`, `renew(id, ...)`, `upgrade(id, ...)`, `downgrade(id, ...)`, `listMembers(id)`, `listScheduledChanges(id,
|
|
127
|
-
| `customers` | `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)`, `listMemberships(id)`
|
|
128
|
-
| `entitlements` | `redeem(...)`, `recordUsage(...)`, `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)`
|
|
129
|
-
| `plans` | `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)`, `listBillingOptions(id)`, `createBillingOption(id, ...)`, `listEntitlements(id)`, `createEntitlement(id, ...)`, `listPlanLinks(id)`, `createPlanLink(id, ...)`, `listPricingGroupMappings(id)`, `createPricingGroupMapping(id, ...)`
|
|
130
|
-
| `billingOptions` | `list()`, `get(id)`, `update(id, ...)`, `delete(id)`, `listSalesChannels(id)`, `createSalesChannelLink(id, ...)`
|
|
131
|
-
| `memberRoles` | `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)`
|
|
132
|
-
| `pricingGroups` | `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)`
|
|
133
|
-
| `salesChannels` | `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)`
|
|
134
|
-
| `planEntitlements` | `get(id)`, `update(id, ...)`, `delete(id)`
|
|
135
|
-
| `planLinks` | `delete(id)`
|
|
136
|
-
| `planPricingGroupMappings` | `delete(id)`
|
|
137
|
-
| `billingOptionSalesChannels` | `delete(id)`
|
|
138
|
-
| `webhookSubscriptions` | `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)`, `listDeliveries(id)`
|
|
154
|
+
| Namespace | Methods |
|
|
155
|
+
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
156
|
+
| `admit` | `check({ card })` |
|
|
157
|
+
| `members` | `sync({ since? })`, `get(id)`, `listEntitlements(id, { type? })`, `reissueCard(id, { note? })` |
|
|
158
|
+
| `memberships` | `list(params?)`, `get(id)`, `create(...)`, `update(id, ...)`, `cancel(id, ...)`, `uncancel(id)`, `renew(id, ...)`, `upgrade(id, ...)`, `downgrade(id, ...)`, `listMembers(id)`, `listScheduledChanges(id, params?)`, `cancelScheduledChange(id, changeId)`, `listTransactions(id, params?)`, `listTermTransactions(id, termId, params?)`, `createTransaction(id, ...)` |
|
|
159
|
+
| `customers` | `list(params?)`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)`, `listMemberships(id, params?)` |
|
|
160
|
+
| `entitlements` | `redeem(...)`, `recordUsage(...)`, `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)` |
|
|
161
|
+
| `plans` | `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)`, `listBillingOptions(id)`, `createBillingOption(id, ...)`, `listEntitlements(id)`, `createEntitlement(id, ...)`, `listPlanLinks(id)`, `createPlanLink(id, ...)`, `listPricingGroupMappings(id)`, `createPricingGroupMapping(id, ...)` |
|
|
162
|
+
| `billingOptions` | `list()`, `get(id)`, `update(id, ...)`, `delete(id)`, `listSalesChannels(id)`, `createSalesChannelLink(id, ...)` |
|
|
163
|
+
| `memberRoles` | `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)` |
|
|
164
|
+
| `pricingGroups` | `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)` |
|
|
165
|
+
| `salesChannels` | `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)` |
|
|
166
|
+
| `planEntitlements` | `get(id)`, `update(id, ...)`, `delete(id)` |
|
|
167
|
+
| `planLinks` | `delete(id)` |
|
|
168
|
+
| `planPricingGroupMappings` | `delete(id)` |
|
|
169
|
+
| `billingOptionSalesChannels` | `delete(id)` |
|
|
170
|
+
| `webhookSubscriptions` | `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)`, `listDeliveries(id, params?)` |
|
|
139
171
|
|
|
140
172
|
Every method accepts a trailing `options` argument: `{ signal?, headers? }`
|
|
141
173
|
(plus `idempotencyKey?` on `redeem` / `recordUsage`).
|
|
142
174
|
|
|
143
175
|
Endpoints requiring a user session (API key management, organisation and
|
|
144
176
|
project admin) are intentionally not in the SDK — API keys cannot call them.
|
|
145
|
-
|
|
146
|
-
## Development (monorepo)
|
|
147
|
-
|
|
148
|
-
Types are generated from `packages/ophelio-api/openapi.json`:
|
|
149
|
-
|
|
150
|
-
```sh
|
|
151
|
-
npm run generate:sdk # repo root: regenerate spec + SDK types
|
|
152
|
-
npm test -w packages/ophelio-sdk
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
`src/generated/schema.d.ts` is a build artifact (git-ignored), regenerated
|
|
156
|
-
from the committed spec on every `build`, `typecheck`, and `test`. The
|
|
157
|
-
committed source of truth is `packages/ophelio-api/openapi.json`; CI fails
|
|
158
|
-
if it drifts from the API controllers.
|
package/dist/index.cjs
CHANGED
|
@@ -216,6 +216,13 @@ var APIResource = class {
|
|
|
216
216
|
this.transport = transport;
|
|
217
217
|
}
|
|
218
218
|
};
|
|
219
|
+
function pageQuery(params) {
|
|
220
|
+
if (!params) return void 0;
|
|
221
|
+
const query = {};
|
|
222
|
+
if (params.page_size !== void 0) query.page_size = String(params.page_size);
|
|
223
|
+
if (params.page_token !== void 0) query.page_token = params.page_token;
|
|
224
|
+
return query;
|
|
225
|
+
}
|
|
219
226
|
//#endregion
|
|
220
227
|
//#region src/resources/admit.ts
|
|
221
228
|
var AdmitResource = class extends APIResource {
|
|
@@ -300,13 +307,19 @@ var BillingOptionsResource = class extends APIResource {
|
|
|
300
307
|
//#endregion
|
|
301
308
|
//#region src/resources/customers.ts
|
|
302
309
|
var CustomersResource = class extends APIResource {
|
|
303
|
-
async list(options) {
|
|
304
|
-
|
|
310
|
+
async list(params, options) {
|
|
311
|
+
const response = await this.transport.request({
|
|
305
312
|
method: "GET",
|
|
306
313
|
path: "/api/v1/customers",
|
|
314
|
+
query: pageQuery(params),
|
|
307
315
|
retryable: true,
|
|
308
316
|
options
|
|
309
|
-
})
|
|
317
|
+
});
|
|
318
|
+
return {
|
|
319
|
+
items: response.customers,
|
|
320
|
+
next_page_token: response.next_page_token,
|
|
321
|
+
total_size: response.total_size
|
|
322
|
+
};
|
|
310
323
|
}
|
|
311
324
|
get(id, options) {
|
|
312
325
|
return this.transport.request({
|
|
@@ -342,13 +355,19 @@ var CustomersResource = class extends APIResource {
|
|
|
342
355
|
options
|
|
343
356
|
});
|
|
344
357
|
}
|
|
345
|
-
async listMemberships(id, options) {
|
|
346
|
-
|
|
358
|
+
async listMemberships(id, params, options) {
|
|
359
|
+
const response = await this.transport.request({
|
|
347
360
|
method: "GET",
|
|
348
361
|
path: `/api/v1/customers/${encodeURIComponent(id)}/memberships`,
|
|
362
|
+
query: pageQuery(params),
|
|
349
363
|
retryable: true,
|
|
350
364
|
options
|
|
351
|
-
})
|
|
365
|
+
});
|
|
366
|
+
return {
|
|
367
|
+
items: response.memberships,
|
|
368
|
+
next_page_token: response.next_page_token,
|
|
369
|
+
total_size: response.total_size
|
|
370
|
+
};
|
|
352
371
|
}
|
|
353
372
|
};
|
|
354
373
|
//#endregion
|
|
@@ -521,13 +540,19 @@ var MembersResource = class extends APIResource {
|
|
|
521
540
|
//#endregion
|
|
522
541
|
//#region src/resources/memberships.ts
|
|
523
542
|
var MembershipsResource = class extends APIResource {
|
|
524
|
-
async list(options) {
|
|
525
|
-
|
|
543
|
+
async list(params, options) {
|
|
544
|
+
const response = await this.transport.request({
|
|
526
545
|
method: "GET",
|
|
527
546
|
path: "/api/v1/memberships",
|
|
547
|
+
query: pageQuery(params),
|
|
528
548
|
retryable: true,
|
|
529
549
|
options
|
|
530
|
-
})
|
|
550
|
+
});
|
|
551
|
+
return {
|
|
552
|
+
items: response.memberships,
|
|
553
|
+
next_page_token: response.next_page_token,
|
|
554
|
+
total_size: response.total_size
|
|
555
|
+
};
|
|
531
556
|
}
|
|
532
557
|
get(id, options) {
|
|
533
558
|
return this.transport.request({
|
|
@@ -573,13 +598,19 @@ var MembershipsResource = class extends APIResource {
|
|
|
573
598
|
options
|
|
574
599
|
});
|
|
575
600
|
}
|
|
576
|
-
async listTransactions(id, options) {
|
|
577
|
-
|
|
601
|
+
async listTransactions(id, params, options) {
|
|
602
|
+
const response = await this.transport.request({
|
|
578
603
|
method: "GET",
|
|
579
604
|
path: `/api/v1/memberships/${encodeURIComponent(id)}/transactions`,
|
|
605
|
+
query: pageQuery(params),
|
|
580
606
|
retryable: true,
|
|
581
607
|
options
|
|
582
|
-
})
|
|
608
|
+
});
|
|
609
|
+
return {
|
|
610
|
+
items: response.transactions,
|
|
611
|
+
next_page_token: response.next_page_token,
|
|
612
|
+
total_size: response.total_size
|
|
613
|
+
};
|
|
583
614
|
}
|
|
584
615
|
/**
|
|
585
616
|
* Report a payment outcome. Ophel.io never processes payments — your
|
|
@@ -636,13 +667,21 @@ var MembershipsResource = class extends APIResource {
|
|
|
636
667
|
});
|
|
637
668
|
}
|
|
638
669
|
async listScheduledChanges(id, params, options) {
|
|
639
|
-
|
|
670
|
+
const response = await this.transport.request({
|
|
640
671
|
method: "GET",
|
|
641
672
|
path: `/api/v1/memberships/${encodeURIComponent(id)}/scheduled-changes`,
|
|
642
|
-
query:
|
|
673
|
+
query: {
|
|
674
|
+
...pageQuery(params),
|
|
675
|
+
...params?.status ? { status: params.status } : {}
|
|
676
|
+
},
|
|
643
677
|
retryable: true,
|
|
644
678
|
options
|
|
645
|
-
})
|
|
679
|
+
});
|
|
680
|
+
return {
|
|
681
|
+
items: response.scheduled_changes,
|
|
682
|
+
next_page_token: response.next_page_token,
|
|
683
|
+
total_size: response.total_size
|
|
684
|
+
};
|
|
646
685
|
}
|
|
647
686
|
async cancelScheduledChange(id, changeId, options) {
|
|
648
687
|
await this.transport.request({
|
|
@@ -652,13 +691,19 @@ var MembershipsResource = class extends APIResource {
|
|
|
652
691
|
options
|
|
653
692
|
});
|
|
654
693
|
}
|
|
655
|
-
async listTermTransactions(id, termId, options) {
|
|
656
|
-
|
|
694
|
+
async listTermTransactions(id, termId, params, options) {
|
|
695
|
+
const response = await this.transport.request({
|
|
657
696
|
method: "GET",
|
|
658
697
|
path: `/api/v1/memberships/${encodeURIComponent(id)}/terms/${encodeURIComponent(termId)}/transactions`,
|
|
698
|
+
query: pageQuery(params),
|
|
659
699
|
retryable: true,
|
|
660
700
|
options
|
|
661
|
-
})
|
|
701
|
+
});
|
|
702
|
+
return {
|
|
703
|
+
items: response.transactions,
|
|
704
|
+
next_page_token: response.next_page_token,
|
|
705
|
+
total_size: response.total_size
|
|
706
|
+
};
|
|
662
707
|
}
|
|
663
708
|
};
|
|
664
709
|
//#endregion
|
|
@@ -942,13 +987,19 @@ var WebhookSubscriptionsResource = class extends APIResource {
|
|
|
942
987
|
options
|
|
943
988
|
});
|
|
944
989
|
}
|
|
945
|
-
async listDeliveries(id, options) {
|
|
946
|
-
|
|
990
|
+
async listDeliveries(id, params, options) {
|
|
991
|
+
const response = await this.transport.request({
|
|
947
992
|
method: "GET",
|
|
948
993
|
path: `/api/v1/webhook-subscriptions/${encodeURIComponent(id)}/deliveries`,
|
|
994
|
+
query: pageQuery(params),
|
|
949
995
|
retryable: true,
|
|
950
996
|
options
|
|
951
|
-
})
|
|
997
|
+
});
|
|
998
|
+
return {
|
|
999
|
+
items: response.webhook_deliveries,
|
|
1000
|
+
next_page_token: response.next_page_token,
|
|
1001
|
+
total_size: response.total_size
|
|
1002
|
+
};
|
|
952
1003
|
}
|
|
953
1004
|
/** The HMAC signing secret is only returned on creation — store it then. */
|
|
954
1005
|
create(params, options) {
|
|
@@ -1072,6 +1123,52 @@ var Ophelio = class Ophelio {
|
|
|
1072
1123
|
this.webhookSubscriptions = new WebhookSubscriptionsResource(transport);
|
|
1073
1124
|
}
|
|
1074
1125
|
};
|
|
1126
|
+
//#endregion
|
|
1127
|
+
//#region src/core/pagination.ts
|
|
1128
|
+
/**
|
|
1129
|
+
* Streams every item across all pages of a paginated `list*` method, fetching
|
|
1130
|
+
* the next page lazily as you iterate:
|
|
1131
|
+
*
|
|
1132
|
+
* ```ts
|
|
1133
|
+
* for await (const membership of paginate((page) => ophelio.memberships.list(page))) {
|
|
1134
|
+
* // …
|
|
1135
|
+
* }
|
|
1136
|
+
*
|
|
1137
|
+
* // nested + filtered + abortable:
|
|
1138
|
+
* for await (const change of paginate((page) =>
|
|
1139
|
+
* ophelio.memberships.listScheduledChanges(id, { ...page, status: 'all' }, { signal }))) {
|
|
1140
|
+
* // …
|
|
1141
|
+
* }
|
|
1142
|
+
* ```
|
|
1143
|
+
*
|
|
1144
|
+
* Because this walks offset pages, a row may be seen twice or skipped across a
|
|
1145
|
+
* page boundary if the collection is written to concurrently.
|
|
1146
|
+
*/
|
|
1147
|
+
async function* paginate(fetchPage, params = {}) {
|
|
1148
|
+
let pageToken = params.page_token;
|
|
1149
|
+
do {
|
|
1150
|
+
const page = await fetchPage({
|
|
1151
|
+
...params,
|
|
1152
|
+
page_token: pageToken
|
|
1153
|
+
});
|
|
1154
|
+
yield* page.items;
|
|
1155
|
+
pageToken = page.next_page_token || void 0;
|
|
1156
|
+
} while (pageToken);
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* Drains every page into a single array — the "give me everything" shortcut
|
|
1160
|
+
* over `paginate`. Loads the whole collection into memory, so prefer
|
|
1161
|
+
* `paginate` for large or unbounded lists.
|
|
1162
|
+
*
|
|
1163
|
+
* ```ts
|
|
1164
|
+
* const customers = await collect((page) => ophelio.customers.list(page))
|
|
1165
|
+
* ```
|
|
1166
|
+
*/
|
|
1167
|
+
async function collect(fetchPage, params = {}) {
|
|
1168
|
+
const items = [];
|
|
1169
|
+
for await (const item of paginate(fetchPage, params)) items.push(item);
|
|
1170
|
+
return items;
|
|
1171
|
+
}
|
|
1075
1172
|
/**
|
|
1076
1173
|
* Canonical webhook event codes for the Ophel.io platform.
|
|
1077
1174
|
*
|
|
@@ -1112,5 +1209,7 @@ exports.UnavailableError = UnavailableError;
|
|
|
1112
1209
|
exports.UnimplementedError = UnimplementedError;
|
|
1113
1210
|
exports.WEBHOOK_EVENT_CODES = WEBHOOK_EVENT_CODES;
|
|
1114
1211
|
exports.WebhookSignatureVerificationError = WebhookSignatureVerificationError;
|
|
1212
|
+
exports.collect = collect;
|
|
1115
1213
|
exports.constructEvent = constructEvent;
|
|
1214
|
+
exports.paginate = paginate;
|
|
1116
1215
|
exports.verifyWebhookSignature = verifyWebhookSignature;
|