@peektravel/app-utilities 0.5.0 → 0.5.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/llms.txt CHANGED
@@ -30,26 +30,81 @@ const peek = new PeekAccessService({
30
30
  });
31
31
  ```
32
32
 
33
- ## Access options / PII
33
+ ## Access options / PII — `fullCustomerAccess`
34
34
 
35
- Every access service takes `accessOptions?: AccessOptions` (`{ fullCustomerAccess?: boolean }`,
36
- default `false`). With `fullCustomerAccess` off, customer PII is **not requested** at the
37
- GraphQL layer (booking guest identity + custom question answers + `portalUrl`,
38
- review reviewer name/email → `null`/empty), and `BookingService` **disables**
39
- `getPaymentsOnFile`/`makePayment`/`refund`/`createInvoiceLink`/`addAddon`/
40
- `removeAddon` (throw `PiiAccessDisabledError`). `create` (incl. `markAsPaid`) and
41
- non-payment reads/mutations stay available. Pass `{ fullCustomerAccess: true }` to opt in.
35
+ **The most commonly-misunderstood option in this package. Read this before
36
+ debugging "why is `customerName` null?" or "why did `makePayment` throw?".**
37
+
38
+ Every access service takes `accessOptions?: AccessOptions`
39
+ (`{ fullCustomerAccess?: boolean }`). It is passed **once at construction**, not
40
+ per call, and applies to every service that access service hands out.
41
+
42
+ ```ts
43
+ const peek = new PeekAccessService({
44
+ installId, jwtSecret, issuer, appId, gatewayKey,
45
+ accessOptions: { fullCustomerAccess: true }, // opt in to PII + payment ops
46
+ });
47
+ ```
48
+
49
+ - **Default is `false` (PII off).** Omitting `accessOptions`, passing `{}`, or
50
+ passing `undefined` are all identical to `{ fullCustomerAccess: false }`.
51
+ - There is **no per-call override** by design — an install either has customer-
52
+ data entitlement or it doesn't. Need both modes? Construct two access services.
53
+ - Consumed by `BookingService` and `ReviewService`; `parseWaiverWebhook(body,
54
+ options?)` takes the same object directly. `CngAccessService` /
55
+ `AcmeAccessService` accept the field but have no PII surface (inert).
56
+
57
+ ### With `fullCustomerAccess: false` (default) — two distinct effects
58
+
59
+ **1. PII is never requested.** Filtering happens in the GraphQL selection, so the
60
+ data never leaves the gateway; the fields simply arrive as `null`/empty in the
61
+ clean models. There is no error and no warning — a missing name looks exactly
62
+ like a customer who didn't provide one.
63
+
64
+ | Surface | Redacted (→ `null`/empty) | Always present |
65
+ | --- | --- | --- |
66
+ | Booking | primary-guest `customerName`/`email`/`phone`/`postalCode`/`isGdpr`/opt-ins; per-guest identity (name, country, DOB, email, phone, postal code, `isGdpr`, custom `fieldResponses`) — guests keep only ids + participation/opt-in flags; booking- and ticket-level custom `questionAnswers`; the customer `portalUrl` | notes, Peek Pro operator deep link, money/price breakdown, resources, timeslot + structural ids |
67
+ | Review | reviewer `customerName` / `customerEmail` | comment, rating, dates, credited guides |
68
+ | Waiver webhook | participant `guestName`, signed-document `fileUrl` (redacted at parse time — the payload is fixed, so there is no selection to trim) | signature/agreement ids, timestamps, booking linkage |
69
+
70
+ **2. Payment & booking-modification operations are disabled.** These throw
71
+ `PiiAccessDisabledError` (exported; `.operation` names the blocked method)
72
+ **before any network call**:
73
+
74
+ `getPaymentsOnFile`, `makePayment`, `refund`, `createInvoiceLink`, `addAddon`,
75
+ `removeAddon`.
76
+
77
+ Still available without the flag: `create` (**including `markAsPaid`**),
78
+ `getById`, `getGuests`, `searchByTimeRange`, `searchByTimeslot`, `listAddons`,
79
+ `cancel`, `appendNote`, `setCheckinStatus`, and every other resource service.
80
+
81
+ ### Choosing a value
82
+
83
+ Leave it `false` for operations/logistics tooling (manifests, check-in, guide
84
+ assignment, notes, availability) — that surface is fully functional without PII.
85
+ Set it `true` only when the app genuinely needs to contact customers or move
86
+ money, and only when the install is entitled to that data; the gateway is the
87
+ final authority and may still reject the request.
42
88
 
43
89
  ## Resources (accessor → methods)
44
90
 
45
91
  - `getProductService()` — `getAllProducts()` (flat list of activities + add-ons;
46
- add-ons have `type === ADD_ON_PRODUCT_TYPE`)
92
+ add-ons have `type === ADD_ON_PRODUCT_TYPE`); `Product.currency` carries the
93
+ activity's ISO currency (empty for add-ons). Each `Product.tickets[]` entry
94
+ carries `minPrice`/`maxPrice` (`PricingMoney | null`, `null` for add-ons and
95
+ when Peek reports no range); every `PricingMoney` includes a `displayPrice`
96
+ string (e.g. `"$50.00"`) on values read back from the gateway.
47
97
  - `getAccountUserService()` — `getAll()`, `getById(userId)`
48
98
  - `getResourcePoolService()` — `getAll(mode?)`
49
99
  - `getTimeslotService()` — `getForDay(productId, date, filter?)`, `getById(id)`,
50
100
  `setAvailability(...)`, `setNotes(...)`, `assignGuide({timeslotIds, guideIds, action})`
51
101
  - `getResellerService()` — `getAllChannels(agentsPerChannel?)`
52
102
  - `getPromoCodeService()` — `getAll()`, `create(input)`
103
+ - `getPricingService()` — `createEngine(input)`, `updateEngine(input)`,
104
+ `deleteEngine(id)` (idempotent), `upsertOverrides(input)`, `clearOverrides(input)`.
105
+ Primitives-only: caller builds the `UpsertOverridesInput` (segmentation,
106
+ override `order`, `spotsTaken` bounds are the caller's job); service sends it
107
+ as-is and returns the resolved `activityContexts`.
53
108
  - `getDailyNoteService()` — `getToday()`, `update(note)`
54
109
  - `getAvailabilityService()` — `getAvailabilityTimes({activityId, date, resourceOptionQuantities})`
55
110
  - `getMembershipService()` — `getAll()`, `purchase(input)`
@@ -60,6 +115,24 @@ non-payment reads/mutations stay available. Pass `{ fullCustomerAccess: true }`
60
115
  `listAddons(id)`, `addAddon(id, {addonOptionId, quantity})`,
61
116
  `removeAddon(id, {addonOptionId, quantity})`, `create(input)`
62
117
 
118
+ ## Sibling accessors (CNG, ACME — REST, not GraphQL)
119
+
120
+ Two brand-parallel accessors sit alongside `PeekAccessService` and share the same
121
+ auth/transport/UI plumbing. Both are **REST** and deliberately minimal today
122
+ (products only). Construct one per install, same config shape **minus `gatewayKey`**
123
+ (`installId`, `jwtSecret`, `issuer`, `appId`); both default the base URL to the
124
+ app-registry installations API.
125
+
126
+ - `CngAccessService` — `getProductService().getAllActivities()` (short-form
127
+ `getAllActivities()`) → `Activity[]` (`Activity`/`ActivityTicket` models).
128
+ Errors surface as `CngApiError`.
129
+ - `AcmeAccessService` — `getProductService().getAllActivities()` (short-form
130
+ `getAllActivities()`) → `AcmeActivity[]` (`AcmeActivity`/`AcmeActivityTicket`
131
+ models). Errors surface as `AcmeApiError`.
132
+
133
+ All are exported from the package root `.`; REST paths and raw response shapes
134
+ stay internal.
135
+
63
136
  ## Input conventions (enforced in the service layer; violations throw plain Error)
64
137
 
65
138
  - Booking ids normalized (lowercased, `-`→`_`): `B-ABC123` == `b_abc123`.
@@ -77,7 +150,8 @@ non-payment reads/mutations stay available. Pass `{ fullCustomerAccess: true }`
77
150
  - `AdminAccountRequiredError` (HTTP 418), `RateLimitError` (HTTP 429 after
78
151
  retries), `PeekGraphQLError` (`.graphqlErrors` holds the raw array),
79
152
  `PiiAccessDisabledError` (a payment/booking-modification op was called without
80
- `fullCustomerAccess`) — all importable; branch with `instanceof`.
153
+ `fullCustomerAccess`), and the REST-sibling `CngApiError` / `AcmeApiError` —
154
+ all importable; branch with `instanceof`.
81
155
  - Plain `Error` for validation/precondition failures thrown before any request.
82
156
 
83
157
  ## Webhooks (booking + waiver)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peektravel/app-utilities",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "GraphQL JS mapping utilities extracted from the Peek Pro Autopilot connector.",
5
5
  "license": "MIT",
6
6
  "repository": {