@ophelio/sdk 0.4.0 → 0.5.1
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 +137 -39
- package/dist/index.cjs +20 -1
- package/dist/index.d.cts +51 -1
- package/dist/index.d.mts +51 -1
- package/dist/index.mjs +20 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,9 +30,11 @@ if (result.admitted) {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// Offline gate cache
|
|
33
|
-
const { members, generated_at } = await ophelio.members.sync(
|
|
33
|
+
const { members, generated_at } = await ophelio.members.sync({
|
|
34
|
+
targets: ['venue_a'], // roster for this gate; optional
|
|
35
|
+
})
|
|
34
36
|
// later, incremental:
|
|
35
|
-
await ophelio.members.sync({ since: generated_at })
|
|
37
|
+
await ophelio.members.sync({ since: generated_at, targets: ['venue_a'] })
|
|
36
38
|
```
|
|
37
39
|
|
|
38
40
|
## Authentication
|
|
@@ -139,11 +141,11 @@ for await (const change of paginate((page) =>
|
|
|
139
141
|
// …
|
|
140
142
|
}
|
|
141
143
|
|
|
142
|
-
// or
|
|
144
|
+
// or load everything into one array (holds the whole collection in memory):
|
|
143
145
|
const customers = await collect((page) => ophelio.customers.list(page))
|
|
144
146
|
```
|
|
145
147
|
|
|
146
|
-
To page manually —
|
|
148
|
+
To page manually — for example to show `total_size` or build numbered pages — feed
|
|
147
149
|
`next_page_token` back in as `page_token` until it comes back empty.
|
|
148
150
|
|
|
149
151
|
`page_size` defaults to 50 and is capped at 250. Because pagination is
|
|
@@ -160,7 +162,7 @@ Everything reachable with an API key is covered:
|
|
|
160
162
|
| Namespace | Methods |
|
|
161
163
|
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
162
164
|
| `admit` | `check({ card, targets? })` |
|
|
163
|
-
| `members` | `sync({ since? })`, `get(id)`, `listEntitlements(id, { type?, targets? })`, `update(id, ...)`, `remove(id)`, `setPrimary(id)`, `reissueCard(id, { note? })`
|
|
165
|
+
| `members` | `sync({ since?, targets? })`, `get(id)`, `listEntitlements(id, { type?, targets? })`, `update(id, ...)`, `remove(id)`, `setPrimary(id)`, `reissueCard(id, { note? })` |
|
|
164
166
|
| `memberships` | `list(params?)`, `get(id)`, `create(...)`, `update(id, ...)`, `cancel(id, ...)`, `uncancel(id)`, `renew(id, ...)`, `upgrade(id, ...)`, `downgrade(id, ...)`, `listMembers(id)`, `addMember(id, ...)`, `listScheduledChanges(id, params?)`, `cancelScheduledChange(id, changeId)`, `listTransactions(id, params?)`, `listTermTransactions(id, termId, params?)`, `createTransaction(id, ...)` |
|
|
165
167
|
| `customers` | `list(params?)`, `get(id, params?)`, `create(...)`, `update(id, ...)`, `delete(id)`, `listMemberships(id, params?)` — `list`/`get` accept `view: 'full'` to include `membership_summary` |
|
|
166
168
|
| `entitlements` | `redeem(...)`, `recordUsage(...)`, `list()`, `get(id)`, `create(...)`, `update(id, ...)`, `delete(id)` |
|
|
@@ -186,6 +188,70 @@ Every method accepts a trailing `options` argument: `{ signal?, headers? }`
|
|
|
186
188
|
Endpoints requiring a user session (API key management, organisation and
|
|
187
189
|
project admin) are intentionally not in the SDK — API keys cannot call them.
|
|
188
190
|
|
|
191
|
+
### Admission
|
|
192
|
+
|
|
193
|
+
`admit.check` admits a member who has free entry they can use **here and
|
|
194
|
+
now**. `admitted` comes back `true` only when the member holds a `free_entry`
|
|
195
|
+
entitlement that passes all three checks: the membership's status still allows
|
|
196
|
+
it; if the membership is in its grace period, the entitlement has
|
|
197
|
+
`active_during_grace` set; and no availability row rules it out for the date
|
|
198
|
+
and place of the request — an entitlement with no rows applies everywhere and
|
|
199
|
+
always, and one that has rows needs just one of them to match. An active
|
|
200
|
+
membership on its own is not enough.
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
const result = await ophelio.admit.check({ card: 'M-123456' })
|
|
204
|
+
|
|
205
|
+
if (result.admitted) {
|
|
206
|
+
console.log(result.pricing_group) // 'member_adult' — price the ticket
|
|
207
|
+
} else if (
|
|
208
|
+
result.deny_reason === 'free_entry_not_granted' ||
|
|
209
|
+
result.deny_reason === 'free_entry_unavailable'
|
|
210
|
+
) {
|
|
211
|
+
result.entitlements // still populated — discounts, guest passes, early access
|
|
212
|
+
result.pricing_group // still resolved — prices the ticket at the member rate
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Two results of that rule are deliberate, and you will meet both on a default
|
|
217
|
+
configuration:
|
|
218
|
+
|
|
219
|
+
- A membership in its **grace period** is not admitted unless its free entry
|
|
220
|
+
has `active_during_grace` set. A grace period is time to renew, not
|
|
221
|
+
permission to enter. The denial reads `free_entry_unavailable`.
|
|
222
|
+
- A plan with **no free-entry entitlement** never admits anyone. It still
|
|
223
|
+
works for discounts, guest passes and early access — a benefits-only plan.
|
|
224
|
+
|
|
225
|
+
The two cases have separate deny reasons, because staff act on them
|
|
226
|
+
differently:
|
|
227
|
+
|
|
228
|
+
| `deny_reason` | Meaning |
|
|
229
|
+
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
230
|
+
| `free_entry_not_granted` | The plan grants no free entry at all. Permanent — no operator action changes it, so do not alert on it. |
|
|
231
|
+
| `free_entry_unavailable` | The plan grants free entry, but it is not usable for this request: no availability row covers this date or this target, or the membership is in its grace period and its free entry does not have `active_during_grace` set. May stop happening on its own. |
|
|
232
|
+
|
|
233
|
+
`free_entry_unavailable` is the one worth monitoring: a calendar nobody rolled
|
|
234
|
+
over to the new year turns away a whole plan at once and shows up as this
|
|
235
|
+
reason. It also covers the everyday grace-period case above, so alert on a rise
|
|
236
|
+
in how often it happens rather than on the reason itself.
|
|
237
|
+
|
|
238
|
+
Only these two free-entry denials return the member's remaining `entitlements`
|
|
239
|
+
and their `pricing_group`, because a visitor who has benefits but not free
|
|
240
|
+
entry is usually about to buy a ticket at the desk. Every other denial —
|
|
241
|
+
`card_not_found`, `member_removed`, `membership_expired`,
|
|
242
|
+
`membership_cancelled`, `membership_incomplete` and `payment_overdue` —
|
|
243
|
+
returns an empty `entitlements` list and a `null` `pricing_group`. If you build
|
|
244
|
+
a desk screen that offers the member their benefits, drive it from the two
|
|
245
|
+
free-entry denials only. The `renew_at_desk` action is separate again: it
|
|
246
|
+
depends on the membership's status, not on whether the member was admitted, so
|
|
247
|
+
it can appear on an admitted response too.
|
|
248
|
+
|
|
249
|
+
`members.sync` returns **more** members than `admit.check` would admit, and
|
|
250
|
+
that is deliberate: a benefits-only member is turned away at the gate but still
|
|
251
|
+
has discounts and guest passes an offline till needs. An offline gate reaches
|
|
252
|
+
the same answer by reading each cached member's `entitlements` — if free entry
|
|
253
|
+
is in the list, admit — and applies no rules of its own.
|
|
254
|
+
|
|
189
255
|
### Calendar rules
|
|
190
256
|
|
|
191
257
|
`date_from` and `date_until` are **timezone-free calendar dates** (`YYYY-MM-DD`),
|
|
@@ -197,8 +263,8 @@ open-ended on that side.
|
|
|
197
263
|
JavaScript's `Date.prototype.getDay()` calls Sunday 0). An empty array means
|
|
198
264
|
every day.
|
|
199
265
|
|
|
200
|
-
|
|
201
|
-
August" is a single rule:
|
|
266
|
+
A date has to satisfy every condition in a rule, and a calendar matches a date
|
|
267
|
+
if any one of its rules does. So "weekends in August" is a single rule:
|
|
202
268
|
|
|
203
269
|
```ts
|
|
204
270
|
await ophelio.calendars.createRule(calendar.id, {
|
|
@@ -208,7 +274,20 @@ await ophelio.calendars.createRule(calendar.id, {
|
|
|
208
274
|
})
|
|
209
275
|
```
|
|
210
276
|
|
|
211
|
-
A calendar
|
|
277
|
+
A calendar with no rules matches **every** date, not none: a half-finished
|
|
278
|
+
calendar lets everyone through rather than quietly turning members away. You
|
|
279
|
+
cannot reach that state through the API, because three requests are refused:
|
|
280
|
+
|
|
281
|
+
- A rule has to restrict something. One that sets neither `date_from` nor
|
|
282
|
+
`date_until` nor a weekday is refused with a **400**.
|
|
283
|
+
- A calendar with no rules cannot be attached to a plan entitlement, whether an
|
|
284
|
+
availability row is being created with it or an existing row repointed to it.
|
|
285
|
+
Attaching one is refused with a **409**, because a row that restricts no
|
|
286
|
+
dates would make the entitlement valid on every date, no matter what the
|
|
287
|
+
other rows say.
|
|
288
|
+
- The last rule of a calendar that is in use cannot be deleted. Deleting it is
|
|
289
|
+
refused with a **409** that says how many plan entitlements use the calendar.
|
|
290
|
+
Add the replacement rule first, then delete.
|
|
212
291
|
|
|
213
292
|
### Target codes
|
|
214
293
|
|
|
@@ -220,8 +299,8 @@ underscores between segments, at least one letter, 2–64 characters — and it
|
|
|
220
299
|
**matched exactly**. A miscased code is an unregistered code, so send values
|
|
221
300
|
back verbatim from `list()` rather than constructing or case-folding them.
|
|
222
301
|
|
|
223
|
-
A code
|
|
224
|
-
back as a 400,
|
|
302
|
+
A code that does not match that format is **rejected, never corrected for
|
|
303
|
+
you**: `Venue A` comes back as a 400, rather than being stored as `venue_a`.
|
|
225
304
|
|
|
226
305
|
`code` is **immutable from creation**; `display_name` and `description` stay
|
|
227
306
|
editable forever. `UpdateTargetCodeParams` therefore has no `code` field, so a
|
|
@@ -252,18 +331,20 @@ await ophelio.planEntitlements.createAvailability(planEntitlement.id, {
|
|
|
252
331
|
})
|
|
253
332
|
```
|
|
254
333
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
334
|
+
A plan entitlement applies if **any one** of its rows matches. Having no rows
|
|
335
|
+
is decided for each plan entitlement on its own: an entitlement with no rows
|
|
336
|
+
applies on every date and in every place, rather than nowhere. Every code in
|
|
337
|
+
`targets` must already be registered as a target code — an unregistered one is
|
|
338
|
+
rejected, not registered for you.
|
|
259
339
|
|
|
260
340
|
### Target context
|
|
261
341
|
|
|
262
342
|
A read can say where it is being made, and the entitlements it gets back are
|
|
263
|
-
|
|
264
|
-
`members.listEntitlements` take `targets` — a set of
|
|
265
|
-
sent comma-separated on the wire — and
|
|
266
|
-
singular `target`, because one usage event
|
|
343
|
+
checked against the availability rows for that place. `admit.check`,
|
|
344
|
+
`members.listEntitlements` and `members.sync` take `targets` — a set of
|
|
345
|
+
registered target codes, sent comma-separated on the wire — and
|
|
346
|
+
`entitlements.recordUsage` takes a singular `target`, because one usage event
|
|
347
|
+
happens at one place.
|
|
267
348
|
|
|
268
349
|
```ts
|
|
269
350
|
const result = await ophelio.admit.check({
|
|
@@ -279,29 +360,46 @@ for (const entitlement of result.entitlements) {
|
|
|
279
360
|
}
|
|
280
361
|
```
|
|
281
362
|
|
|
282
|
-
**Three
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
363
|
+
**Three cases, answered differently on `admit.check` and
|
|
364
|
+
`members.listEntitlements`.** Omitting `targets` says nothing about where the
|
|
365
|
+
request is: every target restriction is then treated as met, and
|
|
366
|
+
`target_context_applied` comes back `false`. Passing `[]` says the caller names
|
|
367
|
+
no targets, so only benefits valid everywhere come back. Passing codes means a
|
|
368
|
+
benefit has to name one of them. Dates are checked in all three cases.
|
|
287
369
|
|
|
288
370
|
**Codes are matched exactly.** Send them back verbatim from
|
|
289
371
|
`targetCodes.list()`; an unregistered or miscased code is refused with a 400
|
|
290
372
|
rather than dropped, so a typo cannot pass for a benefit that does not apply.
|
|
291
373
|
|
|
292
|
-
**The parameter
|
|
293
|
-
the
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
374
|
+
**The parameter does a different job on each endpoint.** At the gate it is part
|
|
375
|
+
of the admission decision; on `members.listEntitlements` it filters the list you
|
|
376
|
+
get back. On `members.sync` it is the scope of what one gate stores for later:
|
|
377
|
+
each member's entitlements are a snapshot taken at the moment of the sync, read
|
|
378
|
+
back during an outage without being checked again, so the targets you sync with
|
|
379
|
+
settle what that gate can grant while it is offline. The gate applies no rules
|
|
380
|
+
of its own.
|
|
381
|
+
|
|
382
|
+
**`members.sync` differs from the other two in two ways, both deliberate.** An
|
|
383
|
+
empty `targets` is refused with a 400 there. It is not read as naming no
|
|
384
|
+
targets, so it never returns only the benefits valid everywhere. And the
|
|
385
|
+
per-project setting below does not apply to it — a sync that omits `targets`
|
|
386
|
+
is always answered and returns the whole roster. The roster is the copy a gate
|
|
387
|
+
falls back on when it cannot reach us, so a quietly shortened or unfetchable
|
|
388
|
+
one would go unnoticed until the outage it exists for. Neither is an oversight
|
|
389
|
+
to be tidied up into consistency.
|
|
390
|
+
|
|
391
|
+
`valid_on` and `valid_at` list only what an entitlement **matched**. `valid_on`
|
|
392
|
+
is omitted when no date restricts it, and `valid_at` when no place does. What
|
|
393
|
+
it failed to match is never returned: the response says where and when a
|
|
394
|
+
benefit is valid, never which restrictions the member missed. Read the two
|
|
395
|
+
lists separately — because an entitlement applies if any one row matches, a
|
|
396
|
+
date in `valid_on` and a place in `valid_at` need not come from the same row.
|
|
397
|
+
|
|
398
|
+
A project can require `admit.check` and `members.listEntitlements` to say where
|
|
399
|
+
they are. Once all of its gates send their own `targets`, an operator turns the
|
|
400
|
+
setting on, and from then on one of those reads that omits `targets` altogether
|
|
401
|
+
is refused with a 400. `members.sync` is exempt, as above. Passing `[]` is not
|
|
402
|
+
the same as omitting it: that read has said where it is and named no targets,
|
|
403
|
+
so it is still answered, exactly as the three cases above describe. It is a
|
|
404
|
+
per-project setting rather than anything the client sends, so start sending
|
|
405
|
+
`targets` before expecting it to be required.
|
package/dist/index.cjs
CHANGED
|
@@ -687,12 +687,31 @@ var MembersResource = class extends APIResource {
|
|
|
687
687
|
/**
|
|
688
688
|
* Active-member list for offline gate caching. Pass the previous
|
|
689
689
|
* response's `generated_at` as `since` to fetch incrementally.
|
|
690
|
+
*
|
|
691
|
+
* `targets` names the venue, zone, shop or gate this roster is for, and
|
|
692
|
+
* settles what the gate can grant while it is offline: each member's
|
|
693
|
+
* entitlements are stored as they stand at the moment of the sync and are
|
|
694
|
+
* read back during an outage without being checked again. Omit it for the
|
|
695
|
+
* whole roster. Codes are matched exactly, so send them back verbatim from
|
|
696
|
+
* `targetCodes.list()` — an unregistered one is refused with a 400.
|
|
697
|
+
*
|
|
698
|
+
* Two things work differently here than on `admit.check` and
|
|
699
|
+
* `members.listEntitlements`, both on purpose. An empty `targets` is
|
|
700
|
+
* refused with a 400. It is not read as naming no targets, so it never
|
|
701
|
+
* returns only the benefits valid everywhere. And a project that requires
|
|
702
|
+
* every read to say where it is still answers a sync that omits `targets`.
|
|
703
|
+
* The roster is what a gate falls back on when it cannot reach us, so a
|
|
704
|
+
* quietly shortened or unfetchable copy would only show up during the
|
|
705
|
+
* outage it was kept for.
|
|
690
706
|
*/
|
|
691
707
|
sync(params = {}, options) {
|
|
692
708
|
return this.transport.request({
|
|
693
709
|
method: "GET",
|
|
694
710
|
path: "/api/v1/members/sync",
|
|
695
|
-
query: {
|
|
711
|
+
query: {
|
|
712
|
+
since: params.since,
|
|
713
|
+
targets: params.targets
|
|
714
|
+
},
|
|
696
715
|
retryable: true,
|
|
697
716
|
options
|
|
698
717
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1652,7 +1652,7 @@ interface components {
|
|
|
1652
1652
|
reason: string;
|
|
1653
1653
|
})[];
|
|
1654
1654
|
admitted: boolean; /** @enum {string|null} */
|
|
1655
|
-
deny_reason: "card_not_found" | "member_removed" | "membership_cancelled" | "membership_expired" | "membership_incomplete" | "payment_overdue" | null;
|
|
1655
|
+
deny_reason: "card_not_found" | "free_entry_not_granted" | "free_entry_unavailable" | "member_removed" | "membership_cancelled" | "membership_expired" | "membership_incomplete" | "payment_overdue" | null;
|
|
1656
1656
|
member: components["schemas"]["AdmitMember"] | null;
|
|
1657
1657
|
membership_id: string | null; /** @enum {string|null} */
|
|
1658
1658
|
membership_status: "active" | "cancelled" | "expired" | "grace_period" | "incomplete" | "past_due" | null;
|
|
@@ -3329,6 +3329,14 @@ interface operations {
|
|
|
3329
3329
|
"application/json": components["schemas"]["ErrorResponse"];
|
|
3330
3330
|
};
|
|
3331
3331
|
};
|
|
3332
|
+
409: {
|
|
3333
|
+
headers: {
|
|
3334
|
+
[name: string]: unknown;
|
|
3335
|
+
};
|
|
3336
|
+
content: {
|
|
3337
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
3338
|
+
};
|
|
3339
|
+
};
|
|
3332
3340
|
};
|
|
3333
3341
|
};
|
|
3334
3342
|
PlanEntitlementAvailabilitiesController_get: {
|
|
@@ -3422,6 +3430,14 @@ interface operations {
|
|
|
3422
3430
|
"application/json": components["schemas"]["ErrorResponse"];
|
|
3423
3431
|
};
|
|
3424
3432
|
};
|
|
3433
|
+
409: {
|
|
3434
|
+
headers: {
|
|
3435
|
+
[name: string]: unknown;
|
|
3436
|
+
};
|
|
3437
|
+
content: {
|
|
3438
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
3439
|
+
};
|
|
3440
|
+
};
|
|
3425
3441
|
};
|
|
3426
3442
|
};
|
|
3427
3443
|
PlanPricingGroupMappingsController_delete: {
|
|
@@ -3671,6 +3687,7 @@ interface operations {
|
|
|
3671
3687
|
MembersController_sync: {
|
|
3672
3688
|
parameters: {
|
|
3673
3689
|
query?: {
|
|
3690
|
+
/** @description Registered target codes of the place this roster is for, sent comma-separated (`?targets=venue_a,coffee_shop`). Each member's entitlements are then narrowed to those usable there. Codes are matched exactly; an unregistered code is refused. Omit the parameter to receive the whole roster, with entitlements narrowed by date alone. Sending it with nothing in it (`?targets=`) is an error here, unlike on `GET /admit` and `GET /members/:id/entitlements`, where it means the caller named no place: this roster is used during an outage without being checked again, so an empty value would leave a gate short of entitlements it would not discover until the outage it kept the roster for. */targets?: string[];
|
|
3674
3691
|
since?: string;
|
|
3675
3692
|
};
|
|
3676
3693
|
header?: never;
|
|
@@ -3687,6 +3704,14 @@ interface operations {
|
|
|
3687
3704
|
"application/json": components["schemas"]["MemberSyncResponse"];
|
|
3688
3705
|
};
|
|
3689
3706
|
};
|
|
3707
|
+
400: {
|
|
3708
|
+
headers: {
|
|
3709
|
+
[name: string]: unknown;
|
|
3710
|
+
};
|
|
3711
|
+
content: {
|
|
3712
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
3713
|
+
};
|
|
3714
|
+
};
|
|
3690
3715
|
};
|
|
3691
3716
|
};
|
|
3692
3717
|
MembersController_get: {
|
|
@@ -4768,6 +4793,14 @@ interface operations {
|
|
|
4768
4793
|
"application/json": components["schemas"]["ErrorResponse"];
|
|
4769
4794
|
};
|
|
4770
4795
|
};
|
|
4796
|
+
409: {
|
|
4797
|
+
headers: {
|
|
4798
|
+
[name: string]: unknown;
|
|
4799
|
+
};
|
|
4800
|
+
content: {
|
|
4801
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
4802
|
+
};
|
|
4803
|
+
};
|
|
4771
4804
|
};
|
|
4772
4805
|
};
|
|
4773
4806
|
CalendarRulesController_update: {
|
|
@@ -5855,9 +5888,26 @@ declare class MembersResource extends APIResource {
|
|
|
5855
5888
|
/**
|
|
5856
5889
|
* Active-member list for offline gate caching. Pass the previous
|
|
5857
5890
|
* response's `generated_at` as `since` to fetch incrementally.
|
|
5891
|
+
*
|
|
5892
|
+
* `targets` names the venue, zone, shop or gate this roster is for, and
|
|
5893
|
+
* settles what the gate can grant while it is offline: each member's
|
|
5894
|
+
* entitlements are stored as they stand at the moment of the sync and are
|
|
5895
|
+
* read back during an outage without being checked again. Omit it for the
|
|
5896
|
+
* whole roster. Codes are matched exactly, so send them back verbatim from
|
|
5897
|
+
* `targetCodes.list()` — an unregistered one is refused with a 400.
|
|
5898
|
+
*
|
|
5899
|
+
* Two things work differently here than on `admit.check` and
|
|
5900
|
+
* `members.listEntitlements`, both on purpose. An empty `targets` is
|
|
5901
|
+
* refused with a 400. It is not read as naming no targets, so it never
|
|
5902
|
+
* returns only the benefits valid everywhere. And a project that requires
|
|
5903
|
+
* every read to say where it is still answers a sync that omits `targets`.
|
|
5904
|
+
* The roster is what a gate falls back on when it cannot reach us, so a
|
|
5905
|
+
* quietly shortened or unfetchable copy would only show up during the
|
|
5906
|
+
* outage it was kept for.
|
|
5858
5907
|
*/
|
|
5859
5908
|
sync(params?: {
|
|
5860
5909
|
since?: string;
|
|
5910
|
+
targets?: string[];
|
|
5861
5911
|
}, options?: RequestOptions): Promise<MemberSyncResponse>;
|
|
5862
5912
|
get(id: string, options?: RequestOptions): Promise<Member>;
|
|
5863
5913
|
/**
|
package/dist/index.d.mts
CHANGED
|
@@ -1652,7 +1652,7 @@ interface components {
|
|
|
1652
1652
|
reason: string;
|
|
1653
1653
|
})[];
|
|
1654
1654
|
admitted: boolean; /** @enum {string|null} */
|
|
1655
|
-
deny_reason: "card_not_found" | "member_removed" | "membership_cancelled" | "membership_expired" | "membership_incomplete" | "payment_overdue" | null;
|
|
1655
|
+
deny_reason: "card_not_found" | "free_entry_not_granted" | "free_entry_unavailable" | "member_removed" | "membership_cancelled" | "membership_expired" | "membership_incomplete" | "payment_overdue" | null;
|
|
1656
1656
|
member: components["schemas"]["AdmitMember"] | null;
|
|
1657
1657
|
membership_id: string | null; /** @enum {string|null} */
|
|
1658
1658
|
membership_status: "active" | "cancelled" | "expired" | "grace_period" | "incomplete" | "past_due" | null;
|
|
@@ -3329,6 +3329,14 @@ interface operations {
|
|
|
3329
3329
|
"application/json": components["schemas"]["ErrorResponse"];
|
|
3330
3330
|
};
|
|
3331
3331
|
};
|
|
3332
|
+
409: {
|
|
3333
|
+
headers: {
|
|
3334
|
+
[name: string]: unknown;
|
|
3335
|
+
};
|
|
3336
|
+
content: {
|
|
3337
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
3338
|
+
};
|
|
3339
|
+
};
|
|
3332
3340
|
};
|
|
3333
3341
|
};
|
|
3334
3342
|
PlanEntitlementAvailabilitiesController_get: {
|
|
@@ -3422,6 +3430,14 @@ interface operations {
|
|
|
3422
3430
|
"application/json": components["schemas"]["ErrorResponse"];
|
|
3423
3431
|
};
|
|
3424
3432
|
};
|
|
3433
|
+
409: {
|
|
3434
|
+
headers: {
|
|
3435
|
+
[name: string]: unknown;
|
|
3436
|
+
};
|
|
3437
|
+
content: {
|
|
3438
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
3439
|
+
};
|
|
3440
|
+
};
|
|
3425
3441
|
};
|
|
3426
3442
|
};
|
|
3427
3443
|
PlanPricingGroupMappingsController_delete: {
|
|
@@ -3671,6 +3687,7 @@ interface operations {
|
|
|
3671
3687
|
MembersController_sync: {
|
|
3672
3688
|
parameters: {
|
|
3673
3689
|
query?: {
|
|
3690
|
+
/** @description Registered target codes of the place this roster is for, sent comma-separated (`?targets=venue_a,coffee_shop`). Each member's entitlements are then narrowed to those usable there. Codes are matched exactly; an unregistered code is refused. Omit the parameter to receive the whole roster, with entitlements narrowed by date alone. Sending it with nothing in it (`?targets=`) is an error here, unlike on `GET /admit` and `GET /members/:id/entitlements`, where it means the caller named no place: this roster is used during an outage without being checked again, so an empty value would leave a gate short of entitlements it would not discover until the outage it kept the roster for. */targets?: string[];
|
|
3674
3691
|
since?: string;
|
|
3675
3692
|
};
|
|
3676
3693
|
header?: never;
|
|
@@ -3687,6 +3704,14 @@ interface operations {
|
|
|
3687
3704
|
"application/json": components["schemas"]["MemberSyncResponse"];
|
|
3688
3705
|
};
|
|
3689
3706
|
};
|
|
3707
|
+
400: {
|
|
3708
|
+
headers: {
|
|
3709
|
+
[name: string]: unknown;
|
|
3710
|
+
};
|
|
3711
|
+
content: {
|
|
3712
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
3713
|
+
};
|
|
3714
|
+
};
|
|
3690
3715
|
};
|
|
3691
3716
|
};
|
|
3692
3717
|
MembersController_get: {
|
|
@@ -4768,6 +4793,14 @@ interface operations {
|
|
|
4768
4793
|
"application/json": components["schemas"]["ErrorResponse"];
|
|
4769
4794
|
};
|
|
4770
4795
|
};
|
|
4796
|
+
409: {
|
|
4797
|
+
headers: {
|
|
4798
|
+
[name: string]: unknown;
|
|
4799
|
+
};
|
|
4800
|
+
content: {
|
|
4801
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
4802
|
+
};
|
|
4803
|
+
};
|
|
4771
4804
|
};
|
|
4772
4805
|
};
|
|
4773
4806
|
CalendarRulesController_update: {
|
|
@@ -5855,9 +5888,26 @@ declare class MembersResource extends APIResource {
|
|
|
5855
5888
|
/**
|
|
5856
5889
|
* Active-member list for offline gate caching. Pass the previous
|
|
5857
5890
|
* response's `generated_at` as `since` to fetch incrementally.
|
|
5891
|
+
*
|
|
5892
|
+
* `targets` names the venue, zone, shop or gate this roster is for, and
|
|
5893
|
+
* settles what the gate can grant while it is offline: each member's
|
|
5894
|
+
* entitlements are stored as they stand at the moment of the sync and are
|
|
5895
|
+
* read back during an outage without being checked again. Omit it for the
|
|
5896
|
+
* whole roster. Codes are matched exactly, so send them back verbatim from
|
|
5897
|
+
* `targetCodes.list()` — an unregistered one is refused with a 400.
|
|
5898
|
+
*
|
|
5899
|
+
* Two things work differently here than on `admit.check` and
|
|
5900
|
+
* `members.listEntitlements`, both on purpose. An empty `targets` is
|
|
5901
|
+
* refused with a 400. It is not read as naming no targets, so it never
|
|
5902
|
+
* returns only the benefits valid everywhere. And a project that requires
|
|
5903
|
+
* every read to say where it is still answers a sync that omits `targets`.
|
|
5904
|
+
* The roster is what a gate falls back on when it cannot reach us, so a
|
|
5905
|
+
* quietly shortened or unfetchable copy would only show up during the
|
|
5906
|
+
* outage it was kept for.
|
|
5858
5907
|
*/
|
|
5859
5908
|
sync(params?: {
|
|
5860
5909
|
since?: string;
|
|
5910
|
+
targets?: string[];
|
|
5861
5911
|
}, options?: RequestOptions): Promise<MemberSyncResponse>;
|
|
5862
5912
|
get(id: string, options?: RequestOptions): Promise<Member>;
|
|
5863
5913
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -686,12 +686,31 @@ var MembersResource = class extends APIResource {
|
|
|
686
686
|
/**
|
|
687
687
|
* Active-member list for offline gate caching. Pass the previous
|
|
688
688
|
* response's `generated_at` as `since` to fetch incrementally.
|
|
689
|
+
*
|
|
690
|
+
* `targets` names the venue, zone, shop or gate this roster is for, and
|
|
691
|
+
* settles what the gate can grant while it is offline: each member's
|
|
692
|
+
* entitlements are stored as they stand at the moment of the sync and are
|
|
693
|
+
* read back during an outage without being checked again. Omit it for the
|
|
694
|
+
* whole roster. Codes are matched exactly, so send them back verbatim from
|
|
695
|
+
* `targetCodes.list()` — an unregistered one is refused with a 400.
|
|
696
|
+
*
|
|
697
|
+
* Two things work differently here than on `admit.check` and
|
|
698
|
+
* `members.listEntitlements`, both on purpose. An empty `targets` is
|
|
699
|
+
* refused with a 400. It is not read as naming no targets, so it never
|
|
700
|
+
* returns only the benefits valid everywhere. And a project that requires
|
|
701
|
+
* every read to say where it is still answers a sync that omits `targets`.
|
|
702
|
+
* The roster is what a gate falls back on when it cannot reach us, so a
|
|
703
|
+
* quietly shortened or unfetchable copy would only show up during the
|
|
704
|
+
* outage it was kept for.
|
|
689
705
|
*/
|
|
690
706
|
sync(params = {}, options) {
|
|
691
707
|
return this.transport.request({
|
|
692
708
|
method: "GET",
|
|
693
709
|
path: "/api/v1/members/sync",
|
|
694
|
-
query: {
|
|
710
|
+
query: {
|
|
711
|
+
since: params.since,
|
|
712
|
+
targets: params.targets
|
|
713
|
+
},
|
|
695
714
|
retryable: true,
|
|
696
715
|
options
|
|
697
716
|
});
|