@peektravel/app-utilities 0.4.0 → 0.5.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 CHANGED
@@ -70,6 +70,34 @@ add-on pages for you.
70
70
  | `logger` | no-op | Inject a `Logger` for diagnostics |
71
71
  | `fetch` | global `fetch` | Custom fetch (e.g. for tests) |
72
72
  | `itemOptionsPageSize` | `50` | Add-on pagination page size |
73
+ | `accessOptions` | `{ fullCustomerAccess: false }` | PII exposure — see [Access options / PII](#access-options--pii) |
74
+
75
+ ### Access options / PII
76
+
77
+ Every access service accepts `accessOptions?: AccessOptions` — today a single
78
+ flag, `fullCustomerAccess` (default `false`). It's an object so future cross-cutting
79
+ flags can be added without breaking signatures.
80
+
81
+ With `fullCustomerAccess` **off** (the default):
82
+
83
+ - **Customer PII is never requested** (the GraphQL queries omit the fields, so
84
+ they come back `null`/empty): booking guest identity (name/email/phone/DOB/
85
+ postal code/GDPR + custom field responses — guests keep only ids and
86
+ participation/opt-in flags), booking custom question answers, the customer
87
+ `portalUrl`, and review reviewer `customerName`/`customerEmail`. Waiver
88
+ webhooks (a fixed payload with no query to trim) instead have `guestName` and
89
+ `fileUrl` redacted at parse time.
90
+ - **Payment / booking-modification operations are disabled** —
91
+ `getPaymentsOnFile`, `makePayment`, `refund`, `createInvoiceLink`, `addAddon`,
92
+ and `removeAddon` throw `PiiAccessDisabledError`. `create` (including
93
+ `markAsPaid`) and non-payment reads/mutations remain available.
94
+
95
+ ```ts
96
+ const peek = new PeekAccessService({
97
+ installId, jwtSecret, issuer, appId, gatewayKey,
98
+ accessOptions: { fullCustomerAccess: true }, // opt into PII + payment operations
99
+ });
100
+ ```
73
101
 
74
102
  ### Errors
75
103
 
@@ -83,6 +111,9 @@ Two kinds of failures surface as exceptions:
83
111
  exhausted. Carries `.statusCode === 429`.
84
112
  - `PeekGraphQLError` — the response contained a GraphQL `errors` array, preserved
85
113
  on `.graphqlErrors`.
114
+ - `PiiAccessDisabledError` — a payment / booking-modification operation was
115
+ called on an access service created without `fullCustomerAccess` (see [Access options
116
+ / PII](#access-options--pii)). Carries `.operation` (the blocked method name).
86
117
 
87
118
  **Plain `Error` validation/precondition failures** thrown by the service layer
88
119
  *before* any network call — e.g. an empty config field, a `bookingId` that
@@ -216,13 +247,16 @@ app.post("/booking-webhook", (req, res) => {
216
247
  });
217
248
 
218
249
  app.post("/waiver-webhook", (req, res) => {
219
- const waiver: Waiver = parseWaiverWebhook(req.body);
250
+ // guestName/fileUrl are redacted unless you opt into PII:
251
+ const waiver: Waiver = parseWaiverWebhook(req.body, { fullCustomerAccess: true });
220
252
  res.sendStatus(200);
221
253
  });
222
254
  ```
223
255
 
224
256
  Both tolerate the delivery envelope / a bare node / a JSON string and never throw
225
- on malformed input. They differ on registration: a **booking** webhook's payload
257
+ on malformed input. `parseWaiverWebhook` also takes an optional `AccessOptions`
258
+ (`{ fullCustomerAccess }`) and redacts the participant `guestName` + document `fileUrl`
259
+ by default — see [Access options / PII](#access-options--pii) below. They differ on registration: a **booking** webhook's payload
226
260
  shape is set by a GraphQL query configured **once in an external system** (the
227
261
  App Store `broadcast_to_url` config) — this package documents and drift-guards
228
262
  the exact query to paste there — whereas a **waiver** webhook has a fixed payload,
package/dist/index.cjs CHANGED
@@ -203,6 +203,73 @@ var AvailabilityService = class {
203
203
  }
204
204
  };
205
205
 
206
+ // src/access-options.ts
207
+ function resolveAccessOptions(options) {
208
+ return { fullCustomerAccess: options?.fullCustomerAccess ?? false };
209
+ }
210
+
211
+ // src/errors.ts
212
+ var AdminAccountRequiredError = class extends Error {
213
+ /** The HTTP status that triggered this error. */
214
+ statusCode = 418;
215
+ constructor(message = "Admin account required") {
216
+ super(message);
217
+ this.name = "AdminAccountRequiredError";
218
+ }
219
+ };
220
+ var RateLimitError = class extends Error {
221
+ /** The HTTP status that triggered this error. */
222
+ statusCode = 429;
223
+ constructor(message = "Rate limit exceeded") {
224
+ super(message);
225
+ this.name = "RateLimitError";
226
+ }
227
+ };
228
+ var PeekGraphQLError = class extends Error {
229
+ /** The raw `errors` array returned by the GraphQL endpoint. */
230
+ graphqlErrors;
231
+ constructor(graphqlErrors, message = "GraphQL request failed") {
232
+ super(message);
233
+ this.name = "PeekGraphQLError";
234
+ this.graphqlErrors = graphqlErrors;
235
+ }
236
+ };
237
+ var PiiAccessDisabledError = class extends Error {
238
+ /** The name of the operation that was blocked (e.g. `"makePayment"`). */
239
+ operation;
240
+ constructor(operation) {
241
+ super(
242
+ `"${operation}" is disabled because this access service was created without "fullCustomerAccess"; enable it to allow payment and booking-modification operations`
243
+ );
244
+ this.name = "PiiAccessDisabledError";
245
+ this.operation = operation;
246
+ }
247
+ };
248
+ var CngApiError = class extends Error {
249
+ /** The HTTP status that triggered this error. */
250
+ statusCode;
251
+ /** The raw response body (parsed JSON when possible, otherwise text). */
252
+ body;
253
+ constructor(statusCode, body, message) {
254
+ super(message ?? `CNG request failed with HTTP ${statusCode}`);
255
+ this.name = "CngApiError";
256
+ this.statusCode = statusCode;
257
+ this.body = body;
258
+ }
259
+ };
260
+ var AcmeApiError = class extends Error {
261
+ /** The HTTP status that triggered this error. */
262
+ statusCode;
263
+ /** The raw response body (parsed JSON when possible, otherwise text). */
264
+ body;
265
+ constructor(statusCode, body, message) {
266
+ super(message ?? `ACME request failed with HTTP ${statusCode}`);
267
+ this.name = "AcmeApiError";
268
+ this.statusCode = statusCode;
269
+ this.body = body;
270
+ }
271
+ };
272
+
206
273
  // src/models/peek/product.ts
207
274
  var ACTIVITY_PRODUCT_TYPE = "ACTIVITY";
208
275
  var RENTAL_PRODUCT_TYPE = "RENTAL";
@@ -214,17 +281,8 @@ var SEARCH_BY_ACTIVITY_DATE = "activityDate";
214
281
  function normalizeBookingId(bookingId) {
215
282
  return bookingId.toLowerCase().replace(/-/g, "_");
216
283
  }
217
- var guestFields = `
218
- id
219
- name
220
- country
221
- dateOfBirth
222
- email
223
- isGdpr
224
- isParticipant
225
- optinSms
226
- optinMarketing
227
- phone
284
+ var GUEST_IDENTITY_PII_FIELDS = "name country dateOfBirth email isGdpr";
285
+ var GUEST_CONTACT_PII_FIELDS = `phone
228
286
  postalCode
229
287
  fieldResponses {
230
288
  id
@@ -234,9 +292,20 @@ var guestFields = `
234
292
  name
235
293
  }
236
294
  }
237
- }
295
+ }`;
296
+ function buildGuestFields(fullCustomerAccess) {
297
+ return `
298
+ id
299
+ ${fullCustomerAccess ? GUEST_IDENTITY_PII_FIELDS : ""}
300
+ isParticipant
301
+ optinSms
302
+ optinMarketing
303
+ ${fullCustomerAccess ? GUEST_CONTACT_PII_FIELDS : ""}
238
304
  `;
239
- var bookingGuestsFields = `
305
+ }
306
+ function buildBookingGuestsFields(fullCustomerAccess) {
307
+ const guestFields = buildGuestFields(fullCustomerAccess);
308
+ return `
240
309
  bookingGuests {
241
310
  ${guestFields}
242
311
  }
@@ -244,10 +313,9 @@ var bookingGuestsFields = `
244
313
  ${guestFields}
245
314
  }
246
315
  `;
247
- var bookingQueryFields = `
248
- displayId
249
- id
250
- primaryGuest {
316
+ }
317
+ var bookingGuestsFields = buildBookingGuestsFields(true);
318
+ var BOOKING_PRIMARY_GUEST_PII_FIELDS = `primaryGuest {
251
319
  name
252
320
  email
253
321
  phone
@@ -255,7 +323,26 @@ var bookingQueryFields = `
255
323
  optinSms
256
324
  isGdpr
257
325
  postalCode
326
+ }`;
327
+ var BOOKING_QUESTION_ANSWERS_PII_FIELDS = `questionAnswers {
328
+ answer
329
+ questionText
330
+ questionLocationSnapshot {
331
+ latitude
332
+ longitude
333
+ }
258
334
  }
335
+ tickets {
336
+ questionAnswers {
337
+ answer
338
+ questionText
339
+ }
340
+ }`;
341
+ function buildBookingQueryFields(fullCustomerAccess) {
342
+ return `
343
+ displayId
344
+ id
345
+ ${fullCustomerAccess ? BOOKING_PRIMARY_GUEST_PII_FIELDS : ""}
259
346
  activitySnapshot {
260
347
  type
261
348
  name
@@ -285,7 +372,7 @@ var bookingQueryFields = `
285
372
  endsAt
286
373
  endsAtUtc
287
374
  availabilityTimeId
288
- bookingPortalUrl
375
+ ${fullCustomerAccess ? "bookingPortalUrl" : ""}
289
376
  operatorNotes
290
377
  value {
291
378
  total {
@@ -327,20 +414,7 @@ var bookingQueryFields = `
327
414
  }
328
415
  }
329
416
  }
330
- questionAnswers {
331
- answer
332
- questionText
333
- questionLocationSnapshot {
334
- latitude
335
- longitude
336
- }
337
- }
338
- tickets {
339
- questionAnswers {
340
- answer
341
- questionText
342
- }
343
- }
417
+ ${fullCustomerAccess ? BOOKING_QUESTION_ANSWERS_PII_FIELDS : ""}
344
418
  resourcePoolAssignments {
345
419
  quantity
346
420
  resourcePool {
@@ -358,6 +432,8 @@ var bookingQueryFields = `
358
432
  }
359
433
  }
360
434
  `;
435
+ }
436
+ var bookingQueryFields = buildBookingQueryFields(true);
361
437
  var PRICE_BREAKDOWN_FIELDS = `
362
438
  convenienceFee { amount formatted }
363
439
  deposit { amount formatted }
@@ -376,9 +452,10 @@ var TICKET_VALUE_FIELDS = `
376
452
  total { amount formatted }
377
453
  }
378
454
  `;
379
- function buildBookingsListingQuery(includeGuests, includePriceBreakdown) {
380
- const guestsSection = includeGuests ? bookingGuestsFields : "";
381
- const fields = includePriceBreakdown ? bookingQueryFields.replace("value {", `value { ${PRICE_BREAKDOWN_FIELDS}`).replace("ticketQuantities {", `ticketQuantities { ${TICKET_VALUE_FIELDS}`) : bookingQueryFields;
455
+ function buildBookingsListingQuery(includeGuests, includePriceBreakdown, fullCustomerAccess = true) {
456
+ const guestsSection = includeGuests ? buildBookingGuestsFields(fullCustomerAccess) : "";
457
+ const baseFields = buildBookingQueryFields(fullCustomerAccess);
458
+ const fields = includePriceBreakdown ? baseFields.replace("value {", `value { ${PRICE_BREAKDOWN_FIELDS}`).replace("ticketQuantities {", `ticketQuantities { ${TICKET_VALUE_FIELDS}`) : baseFields;
382
459
  return `
383
460
  query Sales($after: String, $first: Int, $filter: SalesFilter!, $orderBy: SalesOrdering) {
384
461
  sales(after: $after, first: $first, filter: $filter, orderBy: $orderBy) {
@@ -395,7 +472,8 @@ function buildBookingsListingQuery(includeGuests, includePriceBreakdown) {
395
472
  }
396
473
  `;
397
474
  }
398
- var BOOKING_GUESTS_QUERY = `
475
+ function buildBookingGuestsQuery(fullCustomerAccess) {
476
+ return `
399
477
  query Sales($after: String, $first: Int, $filter: SalesFilter!, $orderBy: SalesOrdering) {
400
478
  sales(after: $after, first: $first, filter: $filter, orderBy: $orderBy) {
401
479
  pageInfo { endCursor hasNextPage }
@@ -404,13 +482,14 @@ var BOOKING_GUESTS_QUERY = `
404
482
  ... on Booking {
405
483
  displayId
406
484
  id
407
- ${bookingGuestsFields}
485
+ ${buildBookingGuestsFields(fullCustomerAccess)}
408
486
  }
409
487
  }
410
488
  }
411
489
  }
412
490
  }
413
491
  `;
492
+ }
414
493
  var BOOKING_PAYMENTS_ON_FILE_QUERY = `
415
494
  query Sales($after: String, $first: Int, $filter: SalesFilter!, $orderBy: SalesOrdering) {
416
495
  sales(after: $after, first: $first, filter: $filter, orderBy: $orderBy) {
@@ -996,10 +1075,23 @@ var BookingService = class {
996
1075
  this.client = client;
997
1076
  this.deps = deps;
998
1077
  this.pageSize = options.pageSize ?? DEFAULT_PAGE_SIZE2;
1078
+ this.fullCustomerAccess = resolveAccessOptions(options.accessOptions).fullCustomerAccess;
999
1079
  }
1000
1080
  client;
1001
1081
  deps;
1002
1082
  pageSize;
1083
+ /** Whether customer PII is requested and payment operations are allowed. */
1084
+ fullCustomerAccess;
1085
+ /**
1086
+ * Throws a {@link PiiAccessDisabledError} for `operation` when this service was
1087
+ * created without `fullCustomerAccess` — used to gate payment and booking-modification
1088
+ * operations that touch customer financial data.
1089
+ */
1090
+ assertPiiEnabled(operation) {
1091
+ if (!this.fullCustomerAccess) {
1092
+ throw new PiiAccessDisabledError(operation);
1093
+ }
1094
+ }
1003
1095
  /**
1004
1096
  * Returns a single booking by id, or null when not found. The `bookingId` is
1005
1097
  * normalized internally (lowercased, `-` → `_`), so `B-ABC123` and `b_abc123`
@@ -1021,7 +1113,7 @@ var BookingService = class {
1021
1113
  const includePriceBreakdown = options.includePriceBreakdown ?? false;
1022
1114
  const body = await this.client.request(
1023
1115
  SALES_ENDPOINT,
1024
- buildBookingsListingQuery(includeGuests, includePriceBreakdown),
1116
+ buildBookingsListingQuery(includeGuests, includePriceBreakdown, this.fullCustomerAccess),
1025
1117
  buildBookingsVariables({
1026
1118
  pageSize: this.pageSize,
1027
1119
  after: null,
@@ -1039,7 +1131,7 @@ var BookingService = class {
1039
1131
  const includeGuests = input.includeGuests ?? false;
1040
1132
  const includePriceBreakdown = input.includePriceBreakdown ?? false;
1041
1133
  return this.fetchPaginated(
1042
- buildBookingsListingQuery(includeGuests, includePriceBreakdown),
1134
+ buildBookingsListingQuery(includeGuests, includePriceBreakdown, this.fullCustomerAccess),
1043
1135
  {
1044
1136
  startDateTime: input.start,
1045
1137
  endDateTime: input.end,
@@ -1057,7 +1149,7 @@ var BookingService = class {
1057
1149
  const includeGuests = options.includeGuests ?? false;
1058
1150
  const includePriceBreakdown = options.includePriceBreakdown ?? false;
1059
1151
  return this.fetchPaginated(
1060
- buildBookingsListingQuery(includeGuests, includePriceBreakdown),
1152
+ buildBookingsListingQuery(includeGuests, includePriceBreakdown, this.fullCustomerAccess),
1061
1153
  { timeslotId },
1062
1154
  includeGuests,
1063
1155
  includePriceBreakdown
@@ -1068,7 +1160,7 @@ var BookingService = class {
1068
1160
  assertBookingId(bookingId);
1069
1161
  const body = await this.client.request(
1070
1162
  SALES_ENDPOINT,
1071
- BOOKING_GUESTS_QUERY,
1163
+ buildBookingGuestsQuery(this.fullCustomerAccess),
1072
1164
  buildBookingsVariables({
1073
1165
  pageSize: this.pageSize,
1074
1166
  after: null,
@@ -1079,6 +1171,7 @@ var BookingService = class {
1079
1171
  }
1080
1172
  /** Returns the payments on file for a booking, or null when not found. */
1081
1173
  async getPaymentsOnFile(bookingId) {
1174
+ this.assertPiiEnabled("getPaymentsOnFile");
1082
1175
  assertBookingId(bookingId);
1083
1176
  const normalized = normalizeBookingId(bookingId);
1084
1177
  const body = await this.client.request(
@@ -1163,6 +1256,7 @@ ${note}`;
1163
1256
  * charge fails.
1164
1257
  */
1165
1258
  async makePayment(input) {
1259
+ this.assertPiiEnabled("makePayment");
1166
1260
  this.validatePaymentInput(input);
1167
1261
  const normalized = normalizeBookingId(input.bookingId);
1168
1262
  const onFile = await this.getPaymentsOnFile(normalized);
@@ -1205,6 +1299,7 @@ ${note}`;
1205
1299
  * payments-on-file, then applies the refund.
1206
1300
  */
1207
1301
  async refund(input) {
1302
+ this.assertPiiEnabled("refund");
1208
1303
  this.validateRefundInput(input);
1209
1304
  const normalized = normalizeBookingId(input.bookingId);
1210
1305
  const onFile = await this.getPaymentsOnFile(normalized);
@@ -1245,6 +1340,7 @@ ${note}`;
1245
1340
  }
1246
1341
  /** Creates an invoice link for a booking's order. */
1247
1342
  async createInvoiceLink(bookingId) {
1343
+ this.assertPiiEnabled("createInvoiceLink");
1248
1344
  assertBookingId(bookingId);
1249
1345
  const normalized = normalizeBookingId(bookingId);
1250
1346
  const booking = await this.getById(normalized);
@@ -1300,6 +1396,7 @@ ${note}`;
1300
1396
  * the underlying quote/order mutations fail.
1301
1397
  */
1302
1398
  async addAddon(bookingId, input) {
1399
+ this.assertPiiEnabled("addAddon");
1303
1400
  assertBookingId(bookingId);
1304
1401
  const addonOptionId = (input?.addonOptionId || input?.addonId || "").trim();
1305
1402
  if (!addonOptionId) {
@@ -1353,6 +1450,7 @@ ${note}`;
1353
1450
  * variables. Returns the booking's add-ons after the change.
1354
1451
  */
1355
1452
  async removeAddon(bookingId, input) {
1453
+ this.assertPiiEnabled("removeAddon");
1356
1454
  assertBookingId(bookingId);
1357
1455
  const addonOptionId = (input?.addonOptionId || input?.addonId || "").trim();
1358
1456
  if (!addonOptionId) {
@@ -1842,57 +1940,6 @@ function createTokenManager(config) {
1842
1940
  });
1843
1941
  }
1844
1942
 
1845
- // src/errors.ts
1846
- var AdminAccountRequiredError = class extends Error {
1847
- /** The HTTP status that triggered this error. */
1848
- statusCode = 418;
1849
- constructor(message = "Admin account required") {
1850
- super(message);
1851
- this.name = "AdminAccountRequiredError";
1852
- }
1853
- };
1854
- var RateLimitError = class extends Error {
1855
- /** The HTTP status that triggered this error. */
1856
- statusCode = 429;
1857
- constructor(message = "Rate limit exceeded") {
1858
- super(message);
1859
- this.name = "RateLimitError";
1860
- }
1861
- };
1862
- var PeekGraphQLError = class extends Error {
1863
- /** The raw `errors` array returned by the GraphQL endpoint. */
1864
- graphqlErrors;
1865
- constructor(graphqlErrors, message = "GraphQL request failed") {
1866
- super(message);
1867
- this.name = "PeekGraphQLError";
1868
- this.graphqlErrors = graphqlErrors;
1869
- }
1870
- };
1871
- var CngApiError = class extends Error {
1872
- /** The HTTP status that triggered this error. */
1873
- statusCode;
1874
- /** The raw response body (parsed JSON when possible, otherwise text). */
1875
- body;
1876
- constructor(statusCode, body, message) {
1877
- super(message ?? `CNG request failed with HTTP ${statusCode}`);
1878
- this.name = "CngApiError";
1879
- this.statusCode = statusCode;
1880
- this.body = body;
1881
- }
1882
- };
1883
- var AcmeApiError = class extends Error {
1884
- /** The HTTP status that triggered this error. */
1885
- statusCode;
1886
- /** The raw response body (parsed JSON when possible, otherwise text). */
1887
- body;
1888
- constructor(statusCode, body, message) {
1889
- super(message ?? `ACME request failed with HTTP ${statusCode}`);
1890
- this.name = "AcmeApiError";
1891
- this.statusCode = statusCode;
1892
- this.body = body;
1893
- }
1894
- };
1895
-
1896
1943
  // src/internal/http-transport.ts
1897
1944
  var RATE_LIMIT_STATUS = 429;
1898
1945
  var ADMIN_ACCOUNT_REQUIRED_STATUS = 418;
@@ -2311,7 +2358,8 @@ function encodeCursor(offset, pageSize) {
2311
2358
  }
2312
2359
 
2313
2360
  // src/internal/peek/reviews/review-queries.ts
2314
- var REVIEWS_QUERY = `
2361
+ function buildReviewsQuery(fullCustomerAccess) {
2362
+ return `
2315
2363
  query Reviews($first: Int, $filter: ReviewFilter, $after: String) {
2316
2364
  reviews(first: $first, filter: $filter, after: $after) {
2317
2365
  edges {
@@ -2325,8 +2373,7 @@ var REVIEWS_QUERY = `
2325
2373
  name
2326
2374
  }
2327
2375
  id
2328
- name
2329
- email
2376
+ ${fullCustomerAccess ? "name\n email" : ""}
2330
2377
  rating
2331
2378
  comment
2332
2379
  reviewedAt
@@ -2337,6 +2384,7 @@ var REVIEWS_QUERY = `
2337
2384
  }
2338
2385
  }
2339
2386
  `;
2387
+ }
2340
2388
  function buildReviewsVariables(params) {
2341
2389
  return {
2342
2390
  first: params.first,
@@ -2353,10 +2401,13 @@ var ERROR_PRODUCT_ID_REQUIRED = "productId is required";
2353
2401
  var ERROR_INVALID_REVIEW_COUNT = `reviewCount must be an integer between ${MIN_REVIEW_COUNT} and ${MAX_REVIEW_COUNT}`;
2354
2402
  var ERROR_INVALID_REVIEW_OFFSET = "reviewOffset must be a non-negative integer";
2355
2403
  var ReviewService = class {
2356
- constructor(client) {
2404
+ constructor(client, accessOptions) {
2357
2405
  this.client = client;
2406
+ this.fullCustomerAccess = resolveAccessOptions(accessOptions).fullCustomerAccess;
2358
2407
  }
2359
2408
  client;
2409
+ /** Whether reviewer PII (name/email) is requested. */
2410
+ fullCustomerAccess;
2360
2411
  /**
2361
2412
  * Returns up to `reviewCount` reviews for an activity in **descending order
2362
2413
  * by review date (newest first)**, skipping the `reviewOffset` newest reviews
@@ -2387,7 +2438,7 @@ var ReviewService = class {
2387
2438
  const after = reviewOffset > 0 ? encodeCursor(reviewOffset - 1, reviewCount) : null;
2388
2439
  const body = await this.client.request(
2389
2440
  SALES_ENDPOINT,
2390
- REVIEWS_QUERY,
2441
+ buildReviewsQuery(this.fullCustomerAccess),
2391
2442
  buildReviewsVariables({ activityId: productId, first: reviewCount, after })
2392
2443
  );
2393
2444
  const edges = body.data?.reviews?.edges ?? [];
@@ -3029,6 +3080,7 @@ var PEEK_TOKEN_ISSUER = "app_registry_v2";
3029
3080
  var PeekAccessService = class {
3030
3081
  client;
3031
3082
  productServiceOptions;
3083
+ accessOptions;
3032
3084
  jwtSecret;
3033
3085
  productService;
3034
3086
  accountUserService;
@@ -3065,6 +3117,7 @@ var PeekAccessService = class {
3065
3117
  this.productServiceOptions = {
3066
3118
  itemOptionsPageSize: config.itemOptionsPageSize
3067
3119
  };
3120
+ this.accessOptions = resolveAccessOptions(config.accessOptions);
3068
3121
  }
3069
3122
  /**
3070
3123
  * Verifies a Peek auth token issued by the app registry and returns the
@@ -3205,9 +3258,11 @@ var PeekAccessService = class {
3205
3258
  */
3206
3259
  getBookingService() {
3207
3260
  if (!this.bookingService) {
3208
- this.bookingService = new BookingService(this.client, {
3209
- productService: this.getProductService()
3210
- });
3261
+ this.bookingService = new BookingService(
3262
+ this.client,
3263
+ { productService: this.getProductService() },
3264
+ { accessOptions: this.accessOptions }
3265
+ );
3211
3266
  }
3212
3267
  return this.bookingService;
3213
3268
  }
@@ -3217,7 +3272,7 @@ var PeekAccessService = class {
3217
3272
  */
3218
3273
  getReviewService() {
3219
3274
  if (!this.reviewService) {
3220
- this.reviewService = new ReviewService(this.client);
3275
+ this.reviewService = new ReviewService(this.client, this.accessOptions);
3221
3276
  }
3222
3277
  return this.reviewService;
3223
3278
  }
@@ -3519,7 +3574,7 @@ var CngAccessService = class {
3519
3574
  };
3520
3575
 
3521
3576
  // src/internal/acme/endpoints.ts
3522
- var ACME_EXTENDABLE_SLUG = "acme_backoffice_api@v1";
3577
+ var ACME_EXTENDABLE_SLUG = "acme_backoffice_api-v1";
3523
3578
  var TEMPLATES_PATH = "v2/b2b/event/templates/names?pageSize=-1&page=1";
3524
3579
 
3525
3580
  // src/models/acme/product.ts
@@ -3710,8 +3765,13 @@ function hasPriceBreakdown(node) {
3710
3765
 
3711
3766
  // src/internal/peek/waivers/waiver-webhook.ts
3712
3767
  var PAYLOAD_WAIVER_KEY = "waiver";
3713
- function parseWaiverWebhook(payload) {
3714
- return fromWaiverNode(extractWaiverNode(payload));
3768
+ function parseWaiverWebhook(payload, options) {
3769
+ const waiver = fromWaiverNode(extractWaiverNode(payload));
3770
+ if (!resolveAccessOptions(options).fullCustomerAccess) {
3771
+ waiver.guestName = null;
3772
+ waiver.fileUrl = "";
3773
+ }
3774
+ return waiver;
3715
3775
  }
3716
3776
  function fromWaiverNode(node) {
3717
3777
  const data = node ?? {};
@@ -3759,6 +3819,7 @@ exports.DailyNoteService = DailyNoteService;
3759
3819
  exports.MembershipService = MembershipService;
3760
3820
  exports.PeekAccessService = PeekAccessService;
3761
3821
  exports.PeekGraphQLError = PeekGraphQLError;
3822
+ exports.PiiAccessDisabledError = PiiAccessDisabledError;
3762
3823
  exports.ProductService = ProductService;
3763
3824
  exports.PromoCodeService = PromoCodeService;
3764
3825
  exports.RENTAL_PRODUCT_TYPE = RENTAL_PRODUCT_TYPE;