@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/dist/index.cjs +389 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +314 -1
- package/dist/index.d.ts +314 -1
- package/dist/index.js +389 -3
- package/dist/index.js.map +1 -1
- package/llms.txt +84 -10
- package/package.json +1 -1
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
`
|
|
40
|
-
|
|
41
|
-
|
|
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`)
|
|
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)
|