@peektravel/app-utilities 0.9.5 → 1.0.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 CHANGED
@@ -34,8 +34,8 @@ const peek = new PeekAccessService({
34
34
  installId: 'install-123', // JWT subject
35
35
  jwtSecret: process.env.PEEK_INTERNAL_SECRET!, // signs the JWT
36
36
  issuer: process.env.APP_NAME!, // JWT issuer
37
- appId: process.env.PEEK_APP_ID!, // gateway path segment
38
- gatewayKey: process.env.PEEK_GATEWAY_KEY!, // pk-api-key header
37
+ mode: 'v2', // connection generation — required (see below)
38
+ apiUrl: install.apiUrl, // per-install base URL from the install webhook (persisted)
39
39
  });
40
40
 
41
41
  const products: Product[] = await peek.getProductService().getAllProducts();
@@ -44,6 +44,41 @@ const products: Product[] = await peek.getProductService().getAllProducts();
44
44
  The access service is the authenticated root; each `get<Resource>Service()`
45
45
  returns a (memoized) service that owns that resource's calls.
46
46
 
47
+ ### Connection mode (`v1` / `v2`) — **required**
48
+
49
+ `mode` is a **mandatory** config field — you must choose a connection generation
50
+ explicitly. (It used to be optional, defaulting to `v1`; it is now required so
51
+ that updating the package forces a deliberate choice instead of silently keeping
52
+ the old behaviour.)
53
+
54
+ - **`mode: 'v2'`** — **use this going forward.** The app-registry connection. It
55
+ **requires** the install's `apiUrl` — the per-install base URL delivered on the
56
+ install webhook (`api.url`); the constructor throws without it. Persist that URL
57
+ per install (see [Webhooks](#webhooks)) and pass it as `apiUrl`; no `gatewayKey`
58
+ is needed. If you don't yet have a webhook `apiUrl` (e.g. an older install you
59
+ don't want to uninstall/reinstall just to get one), build one by appending your
60
+ **app slug** to the registry prefix and pass that as the `apiUrl` yourself —
61
+ `https://apps.peek.com/installations-api/<app-slug>` (same shape as the
62
+ webhook's `api.url`; the trailing app-slug segment is required — the prefix
63
+ alone is not a valid URL). Treat it as a transitional bridge and move to the
64
+ webhook URL.
65
+ - **`mode: 'v1'`** — **deprecated; will be removed.** The legacy gateway; needs
66
+ `appId` + `gatewayKey`. If your install relied on the previous default, the
67
+ fastest no-behaviour-change update is to pass `mode: 'v1'` — then plan the
68
+ migration to `v2`.
69
+
70
+ ```ts
71
+ // Legacy v1 (deprecated) — fastest update for an install that used the old default:
72
+ const peek = new PeekAccessService({
73
+ installId: 'install-123',
74
+ jwtSecret: process.env.PEEK_INTERNAL_SECRET!,
75
+ issuer: process.env.APP_NAME!,
76
+ appId: process.env.PEEK_APP_ID!, // gateway path segment
77
+ gatewayKey: process.env.PEEK_GATEWAY_KEY!, // pk-api-key header
78
+ mode: 'v1',
79
+ });
80
+ ```
81
+
47
82
  `getAllProducts()` returns a single flat list of activities **and** add-ons
48
83
  (add-ons tagged with `ADD_ON_PRODUCT_TYPE`), gathering all cursor-paginated
49
84
  add-on pages for you.
@@ -102,7 +137,7 @@ With `fullCustomerAccess` **off** (the default):
102
137
 
103
138
  ```ts
104
139
  const peek = new PeekAccessService({
105
- installId, jwtSecret, issuer, appId, gatewayKey,
140
+ installId, jwtSecret, issuer, mode: 'v2', apiUrl,
106
141
  accessOptions: { fullCustomerAccess: true }, // opt into PII + payment operations
107
142
  });
108
143
  ```
package/dist/index.cjs CHANGED
@@ -191,6 +191,12 @@ var AVAILABILITY_TIMES_QUERY = `
191
191
  }
192
192
  }
193
193
  status
194
+ minimumTicketsRequired
195
+ price {
196
+ amount
197
+ currency
198
+ formatted
199
+ }
194
200
  availability {
195
201
  qty
196
202
  taken
@@ -200,6 +206,24 @@ var AVAILABILITY_TIMES_QUERY = `
200
206
  }
201
207
  `;
202
208
 
209
+ // src/internal/peek/availability/availability-converter.ts
210
+ var DEFAULT_MINIMUM_TICKETS = 1;
211
+ function toAvailabilityTime(node) {
212
+ const rawMinimum = node.minimumTicketsRequired;
213
+ const minimumTicketsRequired = typeof rawMinimum === "number" && rawMinimum > 0 ? rawMinimum : DEFAULT_MINIMUM_TICKETS;
214
+ return {
215
+ id: node.id,
216
+ time: node.time,
217
+ from: node.from,
218
+ end: node.end,
219
+ duration: node.duration,
220
+ status: node.status,
221
+ minimumTicketsRequired,
222
+ price: node.price ?? null,
223
+ availability: node.availability ?? []
224
+ };
225
+ }
226
+
203
227
  // src/internal/peek/availability/availability-service.ts
204
228
  var AvailabilityService = class {
205
229
  constructor(client) {
@@ -217,7 +241,7 @@ var AvailabilityService = class {
217
241
  date: query.date
218
242
  }
219
243
  );
220
- return body.data?.availabilityTimes ?? [];
244
+ return (body.data?.availabilityTimes ?? []).map(toAvailabilityTime);
221
245
  }
222
246
  };
223
247
 
@@ -2791,7 +2815,7 @@ async function requestWithRetry(http, url, init, label, onResponse) {
2791
2815
  // src/internal/sdk-headers.ts
2792
2816
  var SDK_HEADER_NAME = "x-peek-sdk";
2793
2817
  var SDK_PLATFORM = "js";
2794
- var SDK_VERSION = "0.9.5";
2818
+ var SDK_VERSION = "1.0.1";
2795
2819
  var SDK_HEADER_VALUE = `${SDK_PLATFORM}-${SDK_VERSION}`;
2796
2820
 
2797
2821
  // src/internal/peek/graphql-client.ts
@@ -4434,7 +4458,9 @@ var noopLogger = {
4434
4458
 
4435
4459
  // src/peek-access-service.ts
4436
4460
  var DEFAULT_BASE_URL = "https://apps.peekapis.com/backoffice-gql";
4437
- var DEFAULT_V2_BASE_URL = "https://app-registry.peeklabs.com/installations-api";
4461
+ var V2_FALLBACK_URL_PREFIX = "https://apps.peek.com/installations-api";
4462
+ var ERROR_MODE_REQUIRED = `PeekAccessService: "mode" is required and must be "v1" or "v2". Existing installs used the previous default of "v1" \u2014 pass mode: "v1" for the fastest update. Note: "v1" is deprecated and will be removed; migrate to "v2" and pass the install webhook's apiUrl.`;
4463
+ var ERROR_V2_API_URL_REQUIRED = `PeekAccessService: mode "v2" requires an "apiUrl" \u2014 the per-install URL delivered on the install webhook (api.url) and persisted per install. If you do not have one yet, append your app slug to the registry prefix and pass that, e.g. "${V2_FALLBACK_URL_PREFIX}/<app-slug>" (the trailing app-slug segment is required \u2014 the prefix alone is not a valid apiUrl).`;
4438
4464
  var PeekAccessService = class {
4439
4465
  client;
4440
4466
  productServiceOptions;
@@ -4456,19 +4482,24 @@ var PeekAccessService = class {
4456
4482
  customQuestionService;
4457
4483
  constructor(config) {
4458
4484
  const hasApiUrl = !!config.apiUrl;
4485
+ if (config.mode !== "v1" && config.mode !== "v2") {
4486
+ throw new Error(ERROR_MODE_REQUIRED);
4487
+ }
4459
4488
  const isV2 = config.mode === "v2";
4460
4489
  requireNonEmpty(config.installId, "installId", "PeekAccessService");
4461
4490
  requireNonEmpty(config.jwtSecret, "jwtSecret", "PeekAccessService");
4462
4491
  requireNonEmpty(config.issuer, "issuer", "PeekAccessService");
4463
- if (!hasApiUrl) requireNonEmpty(config.appId ?? "", "appId", "PeekAccessService");
4464
- if (!hasApiUrl && !isV2) requireNonEmpty(config.gatewayKey ?? "", "gatewayKey", "PeekAccessService");
4492
+ if (isV2 && !hasApiUrl) throw new Error(ERROR_V2_API_URL_REQUIRED);
4493
+ if (!isV2 && !hasApiUrl) {
4494
+ requireNonEmpty(config.appId ?? "", "appId", "PeekAccessService");
4495
+ requireNonEmpty(config.gatewayKey ?? "", "gatewayKey", "PeekAccessService");
4496
+ }
4465
4497
  this.jwtSecret = config.jwtSecret;
4466
4498
  this.issuer = config.issuer;
4467
4499
  const logger = config.logger ?? noopLogger;
4468
4500
  const tokens = createTokenManager(config);
4469
- const useRegistrySlug = hasApiUrl || isV2;
4470
- const defaultBaseUrl = isV2 ? DEFAULT_V2_BASE_URL : DEFAULT_BASE_URL;
4471
- const baseApiUrl = hasApiUrl ? resolveBaseApiUrl(config.apiUrl, V2_EXTENDABLE_SLUG, "PeekAccessService") : `${config.baseUrl ?? defaultBaseUrl}/${config.appId}`;
4501
+ const useRegistrySlug = hasApiUrl;
4502
+ const baseApiUrl = hasApiUrl ? resolveBaseApiUrl(config.apiUrl, V2_EXTENDABLE_SLUG, "PeekAccessService") : `${config.baseUrl ?? DEFAULT_BASE_URL}/${config.appId}`;
4472
4503
  this.client = new GraphQLClient({
4473
4504
  baseApiUrl,
4474
4505
  endpoints: peekApiEndpoints(useRegistrySlug),
@@ -5133,7 +5164,12 @@ var AcmeAccessService = class {
5133
5164
 
5134
5165
  // src/access-service-factory.ts
5135
5166
  function createAccessServiceForInstall(install, config) {
5136
- const shared = { ...config, installId: install.installId, apiUrl: install.apiUrl };
5167
+ const shared = {
5168
+ ...config,
5169
+ installId: install.installId,
5170
+ apiUrl: install.apiUrl,
5171
+ mode: "v2"
5172
+ };
5137
5173
  switch (install.platform) {
5138
5174
  case "peek":
5139
5175
  return new PeekAccessService(shared);