@ophelio/sdk 0.3.0 → 0.3.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/dist/index.mjs CHANGED
@@ -125,6 +125,21 @@ const DEFAULT_MAX_RETRIES = 2;
125
125
  function resolveIdempotencyKey(idempotencyKey) {
126
126
  return idempotencyKey?.trim() || crypto.randomUUID();
127
127
  }
128
+ /**
129
+ * Serialises query parameters into a search string.
130
+ *
131
+ * `undefined` drops the parameter entirely. An empty array does not: it emits
132
+ * the bare key (`?status=`), because "filter by nothing" and "do not filter"
133
+ * are different requests and the API distinguishes them.
134
+ */
135
+ function serialiseQuery(query) {
136
+ const search = new URLSearchParams();
137
+ for (const [key, value] of Object.entries(query ?? {})) {
138
+ if (value === void 0) continue;
139
+ search.set(key, Array.isArray(value) ? value.join(",") : value);
140
+ }
141
+ return search.toString();
142
+ }
128
143
  var Transport = class {
129
144
  apiKey;
130
145
  baseUrl;
@@ -179,9 +194,7 @@ var Transport = class {
179
194
  throw lastError;
180
195
  }
181
196
  buildUrl(params) {
182
- const search = new URLSearchParams();
183
- for (const [key, value] of Object.entries(params.query ?? {})) if (value !== void 0) search.set(key, value);
184
- const queryString = search.toString();
197
+ const queryString = serialiseQuery(params.query);
185
198
  return `${this.baseUrl}${params.path}${queryString ? `?${queryString}` : ""}`;
186
199
  }
187
200
  buildHeaders(params) {
@@ -313,6 +326,125 @@ var BillingOptionsResource = class extends APIResource {
313
326
  }
314
327
  };
315
328
  //#endregion
329
+ //#region src/resources/calendar-rules.ts
330
+ /**
331
+ * A calendar rule is one row of a calendar's date vocabulary. Conditions AND
332
+ * within a rule and rules OR across a calendar, so "weekends in August" is a
333
+ * single rule rather than two.
334
+ *
335
+ * Rules are created and listed through their calendar
336
+ * (`ophelio.calendars.createRule` / `ophelio.calendars.listRules`); this
337
+ * resource addresses an individual rule.
338
+ */
339
+ var CalendarRulesResource = class extends APIResource {
340
+ get(id, options) {
341
+ return this.transport.request({
342
+ method: "GET",
343
+ path: `/api/v1/calendar-rules/${encodeURIComponent(id)}`,
344
+ retryable: true,
345
+ options
346
+ });
347
+ }
348
+ update(id, params, options) {
349
+ return this.transport.request({
350
+ method: "PATCH",
351
+ path: `/api/v1/calendar-rules/${encodeURIComponent(id)}`,
352
+ body: params,
353
+ retryable: false,
354
+ options
355
+ });
356
+ }
357
+ async delete(id, options) {
358
+ await this.transport.request({
359
+ method: "DELETE",
360
+ path: `/api/v1/calendar-rules/${encodeURIComponent(id)}`,
361
+ retryable: false,
362
+ options
363
+ });
364
+ }
365
+ };
366
+ //#endregion
367
+ //#region src/resources/calendars.ts
368
+ /**
369
+ * Calendars are named, reusable date vocabularies ("Peak 2026", "Weekends").
370
+ * The dates themselves live in the rules attached to them.
371
+ *
372
+ * A calendar containing no rules is valid for **all** dates, not none.
373
+ */
374
+ var CalendarsResource = class extends APIResource {
375
+ async list(params, options) {
376
+ const response = await this.transport.request({
377
+ method: "GET",
378
+ path: "/api/v1/calendars",
379
+ query: pageQuery(params),
380
+ retryable: true,
381
+ options
382
+ });
383
+ return {
384
+ items: response.calendars,
385
+ next_page_token: response.next_page_token,
386
+ total_size: response.total_size
387
+ };
388
+ }
389
+ get(id, options) {
390
+ return this.transport.request({
391
+ method: "GET",
392
+ path: `/api/v1/calendars/${encodeURIComponent(id)}`,
393
+ retryable: true,
394
+ options
395
+ });
396
+ }
397
+ create(params, options) {
398
+ return this.transport.request({
399
+ method: "POST",
400
+ path: "/api/v1/calendars",
401
+ body: params,
402
+ retryable: false,
403
+ options
404
+ });
405
+ }
406
+ update(id, params, options) {
407
+ return this.transport.request({
408
+ method: "PATCH",
409
+ path: `/api/v1/calendars/${encodeURIComponent(id)}`,
410
+ body: params,
411
+ retryable: false,
412
+ options
413
+ });
414
+ }
415
+ async delete(id, options) {
416
+ await this.transport.request({
417
+ method: "DELETE",
418
+ path: `/api/v1/calendars/${encodeURIComponent(id)}`,
419
+ retryable: false,
420
+ options
421
+ });
422
+ }
423
+ async listRules(id, params, options) {
424
+ const response = await this.transport.request({
425
+ method: "GET",
426
+ path: `/api/v1/calendars/${encodeURIComponent(id)}/rules`,
427
+ query: pageQuery(params),
428
+ retryable: true,
429
+ options
430
+ });
431
+ return {
432
+ items: response.rules,
433
+ next_page_token: response.next_page_token,
434
+ total_size: response.total_size
435
+ };
436
+ }
437
+ createRule(id, params, options) {
438
+ return this.transport.request({
439
+ method: "POST",
440
+ path: `/api/v1/calendars/${encodeURIComponent(id)}/rules`,
441
+ body: params,
442
+ retryable: false,
443
+ options
444
+ });
445
+ }
446
+ };
447
+ //#endregion
316
448
  //#region src/resources/customers.ts
317
449
  var CustomersResource = class extends APIResource {
318
450
  /**
@@ -798,6 +930,45 @@ var MembershipsResource = class extends APIResource {
798
930
  }
799
931
  };
800
932
  //#endregion
933
+ //#region src/resources/plan-entitlement-availabilities.ts
934
+ /**
935
+ * An availability row says when and where one plan entitlement applies: a
936
+ * calendar (null = any date) and a set of registered target codes (empty =
937
+ * anywhere). Rows OR, and a plan entitlement with no rows at all is
938
+ * unrestricted.
939
+ *
940
+ * Rows are created and listed through their plan entitlement
941
+ * (`ophelio.planEntitlements.createAvailability` / `listAvailabilities`); this
942
+ * resource addresses an individual row.
943
+ */
944
+ var PlanEntitlementAvailabilitiesResource = class extends APIResource {
945
+ get(id, options) {
946
+ return this.transport.request({
947
+ method: "GET",
948
+ path: `/api/v1/plan-entitlement-availabilities/${encodeURIComponent(id)}`,
949
+ retryable: true,
950
+ options
951
+ });
952
+ }
953
+ update(id, params, options) {
954
+ return this.transport.request({
955
+ method: "PATCH",
956
+ path: `/api/v1/plan-entitlement-availabilities/${encodeURIComponent(id)}`,
957
+ body: params,
958
+ retryable: false,
959
+ options
960
+ });
961
+ }
962
+ async delete(id, options) {
963
+ await this.transport.request({
964
+ method: "DELETE",
965
+ path: `/api/v1/plan-entitlement-availabilities/${encodeURIComponent(id)}`,
966
+ retryable: false,
967
+ options
968
+ });
969
+ }
970
+ };
971
+ //#endregion
801
972
  //#region src/resources/plan-entitlements.ts
802
973
  var PlanEntitlementsResource = class extends APIResource {
803
974
  get(id, options) {
@@ -826,6 +997,29 @@ var PlanEntitlementsResource = class extends APIResource {
826
997
  options
827
998
  });
828
999
  }
1000
+ async listAvailabilities(id, params, options) {
1001
+ const response = await this.transport.request({
1002
+ method: "GET",
1003
+ path: `/api/v1/plan-entitlements/${encodeURIComponent(id)}/availabilities`,
1004
+ query: pageQuery(params),
1005
+ retryable: true,
1006
+ options
1007
+ });
1008
+ return {
1009
+ items: response.availabilities,
1010
+ next_page_token: response.next_page_token,
1011
+ total_size: response.total_size
1012
+ };
1013
+ }
1014
+ createAvailability(id, params, options) {
1015
+ return this.transport.request({
1016
+ method: "POST",
1017
+ path: `/api/v1/plan-entitlements/${encodeURIComponent(id)}/availabilities`,
1018
+ body: params,
1019
+ retryable: false,
1020
+ options
1021
+ });
1022
+ }
829
1023
  };
830
1024
  //#endregion
831
1025
  //#region src/resources/plan-links.ts
@@ -1060,6 +1254,74 @@ var SalesChannelsResource = class extends APIResource {
1060
1254
  }
1061
1255
  };
1062
1256
  //#endregion
1257
+ //#region src/resources/target-codes.ts
1258
+ /**
1259
+ * The registered vocabulary of locations a gate can report (`venue_a`,
1260
+ * `coffee_shop`). Codes are matched exactly — list them and send values back
1261
+ * verbatim rather than constructing or case-folding them.
1262
+ */
1263
+ var TargetCodesResource = class extends APIResource {
1264
+ async list(params, options) {
1265
+ const response = await this.transport.request({
1266
+ method: "GET",
1267
+ path: "/api/v1/target-codes",
1268
+ query: pageQuery(params),
1269
+ retryable: true,
1270
+ options
1271
+ });
1272
+ return {
1273
+ items: response.target_codes,
1274
+ next_page_token: response.next_page_token,
1275
+ total_size: response.total_size
1276
+ };
1277
+ }
1278
+ get(id, options) {
1279
+ return this.transport.request({
1280
+ method: "GET",
1281
+ path: `/api/v1/target-codes/${encodeURIComponent(id)}`,
1282
+ retryable: true,
1283
+ options
1284
+ });
1285
+ }
1286
+ /**
1287
+ * `code` is lowercase letters and digits with single underscores between
1288
+ * segments, at least one letter, 2–64 characters. Anything else is refused
1289
+ * with a 400 rather than normalised, so `Venue A` is an error, not
1290
+ * `venue_a`.
1291
+ */
1292
+ create(params, options) {
1293
+ return this.transport.request({
1294
+ method: "POST",
1295
+ path: "/api/v1/target-codes",
1296
+ body: params,
1297
+ retryable: false,
1298
+ options
1299
+ });
1300
+ }
1301
+ /**
1302
+ * `display_name` and `description` only — `code` is immutable from
1303
+ * creation and sending it is a 400. To correct a typo, create the right
1304
+ * code, repoint whatever uses it, then delete the old one.
1305
+ */
1306
+ update(id, params, options) {
1307
+ return this.transport.request({
1308
+ method: "PATCH",
1309
+ path: `/api/v1/target-codes/${encodeURIComponent(id)}`,
1310
+ body: params,
1311
+ retryable: false,
1312
+ options
1313
+ });
1314
+ }
1315
+ async delete(id, options) {
1316
+ await this.transport.request({
1317
+ method: "DELETE",
1318
+ path: `/api/v1/target-codes/${encodeURIComponent(id)}`,
1319
+ retryable: false,
1320
+ options
1321
+ });
1322
+ }
1323
+ };
1324
+ //#endregion
1063
1325
  //#region src/resources/webhook-subscriptions.ts
1064
1326
  var WebhookSubscriptionsResource = class extends APIResource {
1065
1327
  async list(options) {
@@ -1184,7 +1446,11 @@ var Ophelio = class Ophelio {
1184
1446
  memberRoles;
1185
1447
  pricingGroups;
1186
1448
  salesChannels;
1449
+ targetCodes;
1450
+ calendars;
1451
+ calendarRules;
1187
1452
  planEntitlements;
1453
+ planEntitlementAvailabilities;
1188
1454
  planLinks;
1189
1455
  planPricingGroupMappings;
1190
1456
  billingOptionSalesChannels;
@@ -1207,7 +1473,11 @@ var Ophelio = class Ophelio {
1207
1473
  this.memberRoles = new MemberRolesResource(transport);
1208
1474
  this.pricingGroups = new PricingGroupsResource(transport);
1209
1475
  this.salesChannels = new SalesChannelsResource(transport);
1476
+ this.targetCodes = new TargetCodesResource(transport);
1477
+ this.calendars = new CalendarsResource(transport);
1478
+ this.calendarRules = new CalendarRulesResource(transport);
1210
1479
  this.planEntitlements = new PlanEntitlementsResource(transport);
1480
+ this.planEntitlementAvailabilities = new PlanEntitlementAvailabilitiesResource(transport);
1211
1481
  this.planLinks = new PlanLinksResource(transport);
1212
1482
  this.planPricingGroupMappings = new PlanPricingGroupMappingsResource(transport);
1213
1483
  this.billingOptionSalesChannels = new BillingOptionSalesChannelsResource(transport);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ophelio/sdk",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Official JavaScript / TypeScript SDK for the Ophel.io membership & entitlement API.",
5
5
  "license": "MIT",
6
6
  "author": "Ophel.io",