@peektravel/app-utilities 0.1.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/LICENSE +21 -0
- package/README.md +262 -0
- package/dist/index.cjs +2961 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1272 -0
- package/dist/index.d.ts +1272 -0
- package/dist/index.js +2924 -0
- package/dist/index.js.map +1 -0
- package/llms.txt +77 -0
- package/package.json +68 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal structured logger interface the package can write diagnostics to.
|
|
3
|
+
*
|
|
4
|
+
* Consumers may supply their own implementation (e.g. wrapping an existing
|
|
5
|
+
* application logger). When none is provided the package stays completely
|
|
6
|
+
* silent via {@link noopLogger}.
|
|
7
|
+
*/
|
|
8
|
+
interface Logger {
|
|
9
|
+
info(message: string, context?: Record<string, unknown>): void;
|
|
10
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
11
|
+
error(message: string, context?: Record<string, unknown>): void;
|
|
12
|
+
}
|
|
13
|
+
/** A {@link Logger} that discards everything. Used as the default. */
|
|
14
|
+
declare const noopLogger: Logger;
|
|
15
|
+
|
|
16
|
+
/** The raw body of a GraphQL HTTP response. */
|
|
17
|
+
interface GraphQLBody<T> {
|
|
18
|
+
data?: T;
|
|
19
|
+
errors?: unknown[];
|
|
20
|
+
}
|
|
21
|
+
interface GraphQLClientOptions {
|
|
22
|
+
/** Base URL of the backoffice GraphQL gateway (no trailing slash). */
|
|
23
|
+
baseUrl: string;
|
|
24
|
+
/** Peek app ID, used in the endpoint path. */
|
|
25
|
+
appId: string;
|
|
26
|
+
/** API gateway key sent as the `pk-api-key` header. */
|
|
27
|
+
gatewayKey: string;
|
|
28
|
+
/** Supplies a valid bearer token for each request. */
|
|
29
|
+
getToken: () => string;
|
|
30
|
+
/** Backoff delays (ms) applied on successive HTTP 429 responses. */
|
|
31
|
+
retryDelaysMs: number[];
|
|
32
|
+
/** Diagnostics sink. */
|
|
33
|
+
logger: Logger;
|
|
34
|
+
/** `fetch` implementation to use. */
|
|
35
|
+
fetchFn: typeof fetch;
|
|
36
|
+
}
|
|
37
|
+
declare class GraphQLClient {
|
|
38
|
+
private readonly options;
|
|
39
|
+
constructor(options: GraphQLClientOptions);
|
|
40
|
+
/**
|
|
41
|
+
* Executes a GraphQL query against the named endpoint and returns the raw
|
|
42
|
+
* response body. Retries on HTTP 429 per the configured backoff.
|
|
43
|
+
*/
|
|
44
|
+
request<T>(endpointName: string, query: string, variables: object): Promise<GraphQLBody<T>>;
|
|
45
|
+
private endpoint;
|
|
46
|
+
private buildHeaders;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The clean data model for a Peek Pro account user (staff member / guide).
|
|
51
|
+
*/
|
|
52
|
+
/**
|
|
53
|
+
* An account user on a Peek Pro account.
|
|
54
|
+
*
|
|
55
|
+
* Only **active** users are returned by the account-user service — inactive
|
|
56
|
+
* users are filtered out — so there is no status field on this model.
|
|
57
|
+
*/
|
|
58
|
+
interface AccountUser {
|
|
59
|
+
/** Unique identifier of the account user. */
|
|
60
|
+
id: string;
|
|
61
|
+
/** Full name. */
|
|
62
|
+
name: string;
|
|
63
|
+
/** Email address. */
|
|
64
|
+
email: string;
|
|
65
|
+
/** Phone number. */
|
|
66
|
+
phone: string;
|
|
67
|
+
/** The activities this user is assigned to. */
|
|
68
|
+
assignedActivities: AssignedActivity[];
|
|
69
|
+
}
|
|
70
|
+
/** An activity an {@link AccountUser} is assigned to. */
|
|
71
|
+
interface AssignedActivity {
|
|
72
|
+
/** Activity (product) id. */
|
|
73
|
+
id: string;
|
|
74
|
+
/** Activity name. */
|
|
75
|
+
name: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Tuning options for an {@link AccountUserService}. */
|
|
79
|
+
interface AccountUserServiceOptions {
|
|
80
|
+
/** Page size for cursor pagination. Default: 50. */
|
|
81
|
+
pageSize?: number;
|
|
82
|
+
}
|
|
83
|
+
declare class AccountUserService {
|
|
84
|
+
private readonly client;
|
|
85
|
+
private readonly pageSize;
|
|
86
|
+
constructor(client: GraphQLClient, options?: AccountUserServiceOptions);
|
|
87
|
+
/**
|
|
88
|
+
* Returns all active account users, walking the cursor pagination to the end.
|
|
89
|
+
* Inactive users are omitted.
|
|
90
|
+
*/
|
|
91
|
+
getAll(): Promise<AccountUser[]>;
|
|
92
|
+
/**
|
|
93
|
+
* Returns a single active account user by id, or `null` when no active user
|
|
94
|
+
* matches.
|
|
95
|
+
*/
|
|
96
|
+
getById(userId: string): Promise<AccountUser | null>;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* The clean data model for Peek Pro activity availability times.
|
|
101
|
+
*/
|
|
102
|
+
/** A single bookable availability time slot for an activity. */
|
|
103
|
+
interface AvailabilityTime {
|
|
104
|
+
/** Unique identifier. */
|
|
105
|
+
id: string;
|
|
106
|
+
/** Time label. */
|
|
107
|
+
time: string;
|
|
108
|
+
/** Slot start. */
|
|
109
|
+
from: string;
|
|
110
|
+
/** Slot end. */
|
|
111
|
+
end: string;
|
|
112
|
+
/** Slot duration. */
|
|
113
|
+
duration: Duration;
|
|
114
|
+
/** Availability status. */
|
|
115
|
+
status: string;
|
|
116
|
+
/** Per-resource-option availability. */
|
|
117
|
+
availability: Availability[];
|
|
118
|
+
}
|
|
119
|
+
/** Duration of an {@link AvailabilityTime} slot. */
|
|
120
|
+
interface Duration {
|
|
121
|
+
name: string;
|
|
122
|
+
length: {
|
|
123
|
+
amount: number;
|
|
124
|
+
unit: string;
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/** Availability for a specific resource option within a slot. */
|
|
128
|
+
interface Availability {
|
|
129
|
+
qty: number;
|
|
130
|
+
taken: number;
|
|
131
|
+
resourceOptionId: string;
|
|
132
|
+
}
|
|
133
|
+
/** A requested resource-option quantity used when querying availability. */
|
|
134
|
+
interface ResourceOptionQuantity {
|
|
135
|
+
resourceOptionId: string;
|
|
136
|
+
quantity: number;
|
|
137
|
+
}
|
|
138
|
+
/** Query parameters for fetching availability times. */
|
|
139
|
+
interface AvailabilityTimesQuery {
|
|
140
|
+
/** Activity (product) id. */
|
|
141
|
+
activityId: string;
|
|
142
|
+
/** Date (YYYY-MM-DD). */
|
|
143
|
+
date: string;
|
|
144
|
+
/** The resource options and quantities to check availability for. */
|
|
145
|
+
resourceOptionQuantities: ResourceOptionQuantity[];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
declare class AvailabilityService {
|
|
149
|
+
private readonly client;
|
|
150
|
+
constructor(client: GraphQLClient);
|
|
151
|
+
/** Returns the availability times for an activity/date and requested quantities. */
|
|
152
|
+
getAvailabilityTimes(query: AvailabilityTimesQuery): Promise<AvailabilityTime[]>;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* The clean, transport-agnostic data model for a Peek Pro product.
|
|
157
|
+
*
|
|
158
|
+
* This is the shape consumers of the package work with. It is intentionally
|
|
159
|
+
* decoupled from the underlying Peek GraphQL schema — the raw GraphQL types and
|
|
160
|
+
* the conversion logic live inside the package and are never exposed here.
|
|
161
|
+
*/
|
|
162
|
+
/**
|
|
163
|
+
* A bookable product in a Peek Pro account.
|
|
164
|
+
*
|
|
165
|
+
* `PeekAccessService.getAllProducts()` returns a single flat list that combines
|
|
166
|
+
* two distinct Peek concepts into one uniform shape:
|
|
167
|
+
*
|
|
168
|
+
* - **Activities** — the primary bookable experiences (tours, rentals, classes,
|
|
169
|
+
* etc.). Their {@link Product.type} is whatever Peek reports for the activity.
|
|
170
|
+
* - **Add-ons** — optional item options offered alongside activities. They are
|
|
171
|
+
* grouped under their parent item and always carry the
|
|
172
|
+
* {@link ADD_ON_PRODUCT_TYPE} (`"ADD-ON"`) type, so callers can tell the two
|
|
173
|
+
* apart with a single field check.
|
|
174
|
+
*/
|
|
175
|
+
interface Product {
|
|
176
|
+
/**
|
|
177
|
+
* Stable unique identifier for the product.
|
|
178
|
+
*
|
|
179
|
+
* - Activities: the primary GraphQL `id` (falls back to the `legacyId`).
|
|
180
|
+
* - Add-ons: the id of the parent item the options belong to.
|
|
181
|
+
*/
|
|
182
|
+
productId: string;
|
|
183
|
+
/** Human-readable display name. */
|
|
184
|
+
name: string;
|
|
185
|
+
/**
|
|
186
|
+
* Product type.
|
|
187
|
+
*
|
|
188
|
+
* For activities this is the type reported by Peek; for add-ons it is always
|
|
189
|
+
* {@link ADD_ON_PRODUCT_TYPE}.
|
|
190
|
+
*/
|
|
191
|
+
type: string;
|
|
192
|
+
/**
|
|
193
|
+
* Display color as a hex string (e.g. `"#1A2B3C"`).
|
|
194
|
+
*
|
|
195
|
+
* Add-ons default to white (`"#FFFFFF"`). Empty string when no color is set.
|
|
196
|
+
*/
|
|
197
|
+
color: string;
|
|
198
|
+
/**
|
|
199
|
+
* The bookable sub-options of this product.
|
|
200
|
+
*
|
|
201
|
+
* - Activities: the activity's resource options.
|
|
202
|
+
* - Add-ons: each individual item option grouped under the parent item.
|
|
203
|
+
*/
|
|
204
|
+
tickets: ProductTicket[];
|
|
205
|
+
}
|
|
206
|
+
/** A single bookable sub-option (resource option or add-on item option). */
|
|
207
|
+
interface ProductTicket {
|
|
208
|
+
/** Unique identifier of the ticket / option. */
|
|
209
|
+
id: string;
|
|
210
|
+
/** Human-readable name of the ticket / option. */
|
|
211
|
+
name: string;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* The {@link Product.type} value assigned to add-on products.
|
|
215
|
+
*
|
|
216
|
+
* Exposed so callers can filter add-ons out of (or in to) the combined list
|
|
217
|
+
* returned by {@link Product} queries without hard-coding the string.
|
|
218
|
+
*/
|
|
219
|
+
declare const ADD_ON_PRODUCT_TYPE = "ADD-ON";
|
|
220
|
+
|
|
221
|
+
/** Tuning options for a {@link ProductService}. */
|
|
222
|
+
interface ProductServiceOptions {
|
|
223
|
+
/** Page size for cursor-paginated item options. Default: 50. */
|
|
224
|
+
itemOptionsPageSize?: number;
|
|
225
|
+
}
|
|
226
|
+
declare class ProductService {
|
|
227
|
+
private readonly client;
|
|
228
|
+
private readonly itemOptionsPageSize;
|
|
229
|
+
constructor(client: GraphQLClient, options?: ProductServiceOptions);
|
|
230
|
+
/**
|
|
231
|
+
* Returns every product as a single flat list: activities plus add-ons (the
|
|
232
|
+
* latter tagged with the add-on type). Add-ons are gathered across all
|
|
233
|
+
* cursor-paginated pages.
|
|
234
|
+
*
|
|
235
|
+
* @example Split activities from add-ons
|
|
236
|
+
* ```ts
|
|
237
|
+
* import { ADD_ON_PRODUCT_TYPE } from "@peektravel/app-utilities";
|
|
238
|
+
*
|
|
239
|
+
* const products = await peek.getProductService().getAllProducts();
|
|
240
|
+
* const activities = products.filter((p) => p.type !== ADD_ON_PRODUCT_TYPE);
|
|
241
|
+
* const addons = products.filter((p) => p.type === ADD_ON_PRODUCT_TYPE);
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
getAllProducts(): Promise<Product[]>;
|
|
245
|
+
private fetchActivities;
|
|
246
|
+
private fetchAllItemOptionNodes;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* The clean data model for Peek Pro bookings.
|
|
251
|
+
*/
|
|
252
|
+
/** A ticket line within a booking. */
|
|
253
|
+
interface Ticket {
|
|
254
|
+
name: string;
|
|
255
|
+
quantity: number;
|
|
256
|
+
ticketId: string;
|
|
257
|
+
}
|
|
258
|
+
/** A formatted monetary value. */
|
|
259
|
+
interface Price {
|
|
260
|
+
display: string;
|
|
261
|
+
amount: string;
|
|
262
|
+
}
|
|
263
|
+
/** A resource used by a booking (e.g. a kayak). */
|
|
264
|
+
interface Resource {
|
|
265
|
+
quantity: number;
|
|
266
|
+
name: string;
|
|
267
|
+
shortName: string;
|
|
268
|
+
}
|
|
269
|
+
/** A concrete resource-pool assignment on a booking. */
|
|
270
|
+
interface ResourcePoolAssignment {
|
|
271
|
+
id: string;
|
|
272
|
+
name: string;
|
|
273
|
+
}
|
|
274
|
+
/** A custom question/answer captured on a booking or guest. */
|
|
275
|
+
interface CustomQuestionAnswer {
|
|
276
|
+
question: string;
|
|
277
|
+
answer: string;
|
|
278
|
+
latitude?: string;
|
|
279
|
+
longitude?: string;
|
|
280
|
+
}
|
|
281
|
+
/** A guest metadata field. */
|
|
282
|
+
interface GuestMetadata {
|
|
283
|
+
id: string;
|
|
284
|
+
name: string;
|
|
285
|
+
value: string;
|
|
286
|
+
}
|
|
287
|
+
/** A guest on a booking. */
|
|
288
|
+
interface Guest {
|
|
289
|
+
id: string;
|
|
290
|
+
name: string | null;
|
|
291
|
+
country: string | null;
|
|
292
|
+
dateOfBirth: Date | null;
|
|
293
|
+
phone: string | null;
|
|
294
|
+
email: string | null;
|
|
295
|
+
isGdpr: boolean;
|
|
296
|
+
isParticipant: boolean;
|
|
297
|
+
isPrimary: boolean;
|
|
298
|
+
optinSms: boolean;
|
|
299
|
+
optinMarketing: boolean;
|
|
300
|
+
postalCode: string | null;
|
|
301
|
+
metadata: GuestMetadata[];
|
|
302
|
+
}
|
|
303
|
+
/** A booking in Peek Pro. */
|
|
304
|
+
interface Booking {
|
|
305
|
+
bookingId: string;
|
|
306
|
+
displayId: string;
|
|
307
|
+
source: string;
|
|
308
|
+
sourceApp: string;
|
|
309
|
+
sourceDescription: string;
|
|
310
|
+
customerName: string | null;
|
|
311
|
+
customerEmail: string | null;
|
|
312
|
+
customerPhone: string | null;
|
|
313
|
+
productId: string;
|
|
314
|
+
productName: string;
|
|
315
|
+
isRentalProduct: boolean;
|
|
316
|
+
timeslotId: string | null;
|
|
317
|
+
totalTickets: number;
|
|
318
|
+
ticketDescription: string;
|
|
319
|
+
tickets: Ticket[];
|
|
320
|
+
isCanceled: boolean;
|
|
321
|
+
isNoShow: boolean;
|
|
322
|
+
isCheckedIn: boolean;
|
|
323
|
+
isReturned: boolean;
|
|
324
|
+
purchasedAt: string | null;
|
|
325
|
+
purchasedAtUtc: string | null;
|
|
326
|
+
startsAt: string | null;
|
|
327
|
+
startsAtUtc: string | null;
|
|
328
|
+
endsAt: string | null;
|
|
329
|
+
endsAtUtc: string | null;
|
|
330
|
+
durationMin: number;
|
|
331
|
+
availabilityTimeId: string | null;
|
|
332
|
+
portalUrl: string | null;
|
|
333
|
+
notes: string;
|
|
334
|
+
valueDisplay: string;
|
|
335
|
+
valueAmount: string;
|
|
336
|
+
outstandingBalanceAmount: string;
|
|
337
|
+
outstandingBalanceDisplay: string;
|
|
338
|
+
promoCodes: string[];
|
|
339
|
+
tips: Price[];
|
|
340
|
+
/** Price breakdown — only populated when `includePriceBreakdown` is requested. */
|
|
341
|
+
convenienceFee?: Price;
|
|
342
|
+
deposit?: Price;
|
|
343
|
+
discount?: Price;
|
|
344
|
+
discountedPrice?: Price;
|
|
345
|
+
fees?: Price;
|
|
346
|
+
flatPartnerFee?: Price;
|
|
347
|
+
price?: Price;
|
|
348
|
+
retailPrice?: Price;
|
|
349
|
+
taxes?: Price;
|
|
350
|
+
tipsBreakdown?: Price;
|
|
351
|
+
resources: Resource[];
|
|
352
|
+
resourcePoolAssignments: ResourcePoolAssignment[];
|
|
353
|
+
resellerId: string | null;
|
|
354
|
+
resellerName: string | null;
|
|
355
|
+
orderId: string;
|
|
356
|
+
customQuestionAnswers: CustomQuestionAnswer[];
|
|
357
|
+
customGuestQuestionAnswers: CustomQuestionAnswer[];
|
|
358
|
+
/** Guests — only populated when `includeGuests` is requested. */
|
|
359
|
+
guests?: Guest[];
|
|
360
|
+
}
|
|
361
|
+
/** How to interpret the start/end range when searching bookings. */
|
|
362
|
+
type BookingSearchBy = "purchaseDate" | "activityDate";
|
|
363
|
+
/** Options shared by booking reads. */
|
|
364
|
+
interface BookingReadOptions {
|
|
365
|
+
/** Include guests in the result. */
|
|
366
|
+
includeGuests?: boolean;
|
|
367
|
+
/** Include the price breakdown fields. */
|
|
368
|
+
includePriceBreakdown?: boolean;
|
|
369
|
+
}
|
|
370
|
+
/** Parameters for searching bookings by a time range. */
|
|
371
|
+
interface BookingTimeRangeSearch extends BookingReadOptions {
|
|
372
|
+
/** Range start (ISO datetime). */
|
|
373
|
+
start: string;
|
|
374
|
+
/** Range end (ISO datetime). */
|
|
375
|
+
end: string;
|
|
376
|
+
/** Whether the range matches purchase date or activity date. Default: purchaseDate. */
|
|
377
|
+
searchBy?: BookingSearchBy;
|
|
378
|
+
/** Restrict to a product/activity id. */
|
|
379
|
+
productId?: string;
|
|
380
|
+
/** Filter by primary guest email. */
|
|
381
|
+
email?: string;
|
|
382
|
+
/** Free-text search string. */
|
|
383
|
+
searchString?: string;
|
|
384
|
+
}
|
|
385
|
+
/** How an appended note should be applied. */
|
|
386
|
+
type NoteMode = "append" | "overwrite";
|
|
387
|
+
/** A requested ticket (resource option) and quantity for a new booking. */
|
|
388
|
+
interface CreateBookingTicket {
|
|
389
|
+
resourceOptionId: string;
|
|
390
|
+
quantity: number;
|
|
391
|
+
}
|
|
392
|
+
/** Guest details for a new booking. */
|
|
393
|
+
interface CreateBookingGuest {
|
|
394
|
+
name: string;
|
|
395
|
+
email?: string;
|
|
396
|
+
phone?: string;
|
|
397
|
+
postalCode?: string;
|
|
398
|
+
country?: string;
|
|
399
|
+
optinMarketing?: boolean;
|
|
400
|
+
optinSms?: boolean;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Input for creating a booking. IDs must already be resolved — the package does
|
|
404
|
+
* not do free-text product/ticket/time matching (that stays in the caller).
|
|
405
|
+
*/
|
|
406
|
+
interface CreateBookingInput {
|
|
407
|
+
/** Activity (product) id. */
|
|
408
|
+
activityId: string;
|
|
409
|
+
/** Availability time id for the slot. */
|
|
410
|
+
availabilityTimeId: string;
|
|
411
|
+
/** Tickets to book (each expanded to `quantity` seats). */
|
|
412
|
+
tickets: CreateBookingTicket[];
|
|
413
|
+
/** Primary guest. */
|
|
414
|
+
guest: CreateBookingGuest;
|
|
415
|
+
/** Operator notes to attach. */
|
|
416
|
+
operatorNotes?: string;
|
|
417
|
+
/** Suppress the customer confirmation email. Default: false. */
|
|
418
|
+
skipCustomerEmail?: boolean;
|
|
419
|
+
/** Clone the quote from an existing order. */
|
|
420
|
+
parentOrderId?: string | null;
|
|
421
|
+
/** Mark the booking paid after creation (requires `idempotencyKey`). */
|
|
422
|
+
markAsPaid?: boolean;
|
|
423
|
+
/** Partial payment amount when marking paid; defaults to the full balance. */
|
|
424
|
+
markAsPaidAmount?: string;
|
|
425
|
+
/** Idempotency key for the mark-paid charge. */
|
|
426
|
+
idempotencyKey?: string;
|
|
427
|
+
}
|
|
428
|
+
/** The result of creating a booking. */
|
|
429
|
+
interface CreatedBooking {
|
|
430
|
+
orderId: string;
|
|
431
|
+
bookingId: string;
|
|
432
|
+
displayId: string;
|
|
433
|
+
balanceAmount: string;
|
|
434
|
+
balanceCurrency: string;
|
|
435
|
+
balanceFormatted: string;
|
|
436
|
+
/** Set when the booking was marked paid. */
|
|
437
|
+
transactionId?: string;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* The clean data model for a booking's payments on file.
|
|
442
|
+
*/
|
|
443
|
+
/** A single payment applied to a booking's order. */
|
|
444
|
+
interface Payment {
|
|
445
|
+
id: string;
|
|
446
|
+
/** Date the payment was applied (YYYY-MM-DD). */
|
|
447
|
+
paidAt: string;
|
|
448
|
+
currentAmount: {
|
|
449
|
+
amount: string;
|
|
450
|
+
currency: string;
|
|
451
|
+
};
|
|
452
|
+
refundableAmount: {
|
|
453
|
+
amount: string;
|
|
454
|
+
currency: string;
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
/** A payment source on the order, with any payments made against it. */
|
|
458
|
+
interface PaymentSource {
|
|
459
|
+
description: string;
|
|
460
|
+
id: string;
|
|
461
|
+
type: string;
|
|
462
|
+
/** Payments made against this source, when any exist. */
|
|
463
|
+
payments?: Payment[];
|
|
464
|
+
}
|
|
465
|
+
/** The payments-on-file result for a booking. */
|
|
466
|
+
interface BookingPaymentsOnFile {
|
|
467
|
+
bookingId: string;
|
|
468
|
+
orderId: string;
|
|
469
|
+
paymentsOnFile: PaymentSource[];
|
|
470
|
+
}
|
|
471
|
+
/** Input for charging a booking. */
|
|
472
|
+
interface MakePaymentInput {
|
|
473
|
+
/** Booking id (normalized internally). */
|
|
474
|
+
bookingId: string;
|
|
475
|
+
/** Payment source id (`ps_…`, or one of `cash/cash`, `custom/other`, `custom/voucher`). */
|
|
476
|
+
paymentSourceId: string;
|
|
477
|
+
/** Amount as a numeric string. */
|
|
478
|
+
amount: string;
|
|
479
|
+
/** 3-letter uppercase ISO currency code. */
|
|
480
|
+
currency: string;
|
|
481
|
+
/** Idempotency key passed through to Peek. */
|
|
482
|
+
idempotencyKey: string;
|
|
483
|
+
/** Optional message appended to the default customer message. */
|
|
484
|
+
customerMessage?: string;
|
|
485
|
+
}
|
|
486
|
+
/** Result of charging a booking. */
|
|
487
|
+
interface MakePaymentResult {
|
|
488
|
+
transactionId: string;
|
|
489
|
+
bookingId: string;
|
|
490
|
+
orderId: string;
|
|
491
|
+
amount: string;
|
|
492
|
+
currency: string;
|
|
493
|
+
paymentSourceId: string;
|
|
494
|
+
}
|
|
495
|
+
/** Input for refunding a booking payment. */
|
|
496
|
+
interface RefundInput {
|
|
497
|
+
/** Booking id (normalized internally). */
|
|
498
|
+
bookingId: string;
|
|
499
|
+
/** Payment id to refund (`pmt_…`). */
|
|
500
|
+
paymentId: string;
|
|
501
|
+
/** Amount as a numeric string. */
|
|
502
|
+
amount: string;
|
|
503
|
+
/** 3-letter uppercase ISO currency code. */
|
|
504
|
+
currency: string;
|
|
505
|
+
/** Idempotency key passed through to Peek. */
|
|
506
|
+
idempotencyKey: string;
|
|
507
|
+
}
|
|
508
|
+
/** Result of refunding a booking payment. */
|
|
509
|
+
interface RefundResult {
|
|
510
|
+
transactionId: string;
|
|
511
|
+
bookingId: string;
|
|
512
|
+
orderId: string;
|
|
513
|
+
amount: string;
|
|
514
|
+
currency: string;
|
|
515
|
+
paymentId: string;
|
|
516
|
+
}
|
|
517
|
+
/** Result of creating an invoice link. */
|
|
518
|
+
interface InvoiceLinkResult {
|
|
519
|
+
bookingId: string;
|
|
520
|
+
orderId: string;
|
|
521
|
+
invoiceLink: string;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Clean, public data models for a booking's add-ons.
|
|
526
|
+
*
|
|
527
|
+
* These are the only add-on shapes a consumer sees. The detailed per-option
|
|
528
|
+
* model used to build add/cancel mutations (refids, reservation statuses) is
|
|
529
|
+
* an internal implementation detail and is intentionally not exported.
|
|
530
|
+
*/
|
|
531
|
+
/** Money amount for an add-on line, as returned by the gateway. */
|
|
532
|
+
interface BookingAddonMoney {
|
|
533
|
+
amount: string;
|
|
534
|
+
currency: string;
|
|
535
|
+
formatted: string;
|
|
536
|
+
}
|
|
537
|
+
/** A single add-on option with the quantity attached to the booking. */
|
|
538
|
+
interface BookingAddonOption {
|
|
539
|
+
/** The item option id (`itemOptionSnapshot.id`). */
|
|
540
|
+
addonOptionId: string;
|
|
541
|
+
/** The item option name (`itemOptionSnapshot.name`). */
|
|
542
|
+
addonOptionName: string;
|
|
543
|
+
/** How many live (non-canceled) units of this option are on the booking. */
|
|
544
|
+
quantity: number;
|
|
545
|
+
}
|
|
546
|
+
/** An add-on attached to a booking, grouped by add-on item. */
|
|
547
|
+
interface BookingAddon {
|
|
548
|
+
/** The add-on item id (`itemSnapshot.id`). */
|
|
549
|
+
addonId: string;
|
|
550
|
+
/** The add-on item name (`itemSnapshot.name`). */
|
|
551
|
+
addonName: string;
|
|
552
|
+
/** The booking line-item total for this add-on, when present. */
|
|
553
|
+
total: BookingAddonMoney | null;
|
|
554
|
+
/** Live options on this add-on, combined by option id with a count. */
|
|
555
|
+
addonOptions: BookingAddonOption[];
|
|
556
|
+
}
|
|
557
|
+
/** A booking's add-ons. */
|
|
558
|
+
interface BookingAddons {
|
|
559
|
+
bookingId: string;
|
|
560
|
+
displayId: string;
|
|
561
|
+
orderId: string;
|
|
562
|
+
/** Add-ons with at least one live option; fully-canceled add-ons are omitted. */
|
|
563
|
+
addons: BookingAddon[];
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Result of an add-on mutation (add or remove). Both operations finish by
|
|
567
|
+
* re-listing the booking's add-ons and returning the post-change state rather
|
|
568
|
+
* than echoing quote details.
|
|
569
|
+
*/
|
|
570
|
+
interface BookingAddonsMutationResult {
|
|
571
|
+
updatedBookingAddons: BookingAddons;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/** Result of cancelling a booking. */
|
|
575
|
+
interface CancelBookingResult {
|
|
576
|
+
id: string;
|
|
577
|
+
displayId: string;
|
|
578
|
+
reservationStatus: string;
|
|
579
|
+
}
|
|
580
|
+
/** Tuning options for a {@link BookingService}. */
|
|
581
|
+
interface BookingServiceOptions {
|
|
582
|
+
/** Page size for cursor pagination. Default: 50. */
|
|
583
|
+
pageSize?: number;
|
|
584
|
+
}
|
|
585
|
+
/** Dependencies the {@link BookingService} composes for add-on resolution. */
|
|
586
|
+
interface BookingServiceDeps {
|
|
587
|
+
productService: ProductService;
|
|
588
|
+
}
|
|
589
|
+
/** Input for adding or removing an add-on on a booking. */
|
|
590
|
+
interface AddAddonInput {
|
|
591
|
+
/** The add-on (item option) id. */
|
|
592
|
+
addonOptionId?: string;
|
|
593
|
+
/**
|
|
594
|
+
* @deprecated Use `addonOptionId`. Still accepted for backwards
|
|
595
|
+
* compatibility; treated as `addonOptionId` when `addonOptionId` is absent.
|
|
596
|
+
*/
|
|
597
|
+
addonId?: string;
|
|
598
|
+
/** Quantity as a positive integer string. */
|
|
599
|
+
quantity: string;
|
|
600
|
+
}
|
|
601
|
+
declare class BookingService {
|
|
602
|
+
private readonly client;
|
|
603
|
+
private readonly deps;
|
|
604
|
+
private readonly pageSize;
|
|
605
|
+
constructor(client: GraphQLClient, deps: BookingServiceDeps, options?: BookingServiceOptions);
|
|
606
|
+
/**
|
|
607
|
+
* Returns a single booking by id, or null when not found. The `bookingId` is
|
|
608
|
+
* normalized internally (lowercased, `-` → `_`), so `B-ABC123` and `b_abc123`
|
|
609
|
+
* resolve to the same booking.
|
|
610
|
+
*
|
|
611
|
+
* @example
|
|
612
|
+
* ```ts
|
|
613
|
+
* const bookings = peek.getBookingService();
|
|
614
|
+
* const booking = await bookings.getById("b_abc123", {
|
|
615
|
+
* includeGuests: true,
|
|
616
|
+
* includePriceBreakdown: true,
|
|
617
|
+
* });
|
|
618
|
+
* if (booking) console.log(booking.displayId, booking.outstandingBalanceAmount);
|
|
619
|
+
* ```
|
|
620
|
+
*/
|
|
621
|
+
getById(bookingId: string, options?: BookingReadOptions): Promise<Booking | null>;
|
|
622
|
+
/** Returns all bookings matching a time range (paginated). */
|
|
623
|
+
searchByTimeRange(input: BookingTimeRangeSearch): Promise<Booking[]>;
|
|
624
|
+
/** Returns all bookings on a timeslot (paginated). */
|
|
625
|
+
searchByTimeslot(timeslotId: string, options?: BookingReadOptions): Promise<Booking[]>;
|
|
626
|
+
/** Returns the guests on a booking (primary guest included). */
|
|
627
|
+
getGuests(bookingId: string): Promise<Guest[]>;
|
|
628
|
+
/** Returns the payments on file for a booking, or null when not found. */
|
|
629
|
+
getPaymentsOnFile(bookingId: string): Promise<BookingPaymentsOnFile | null>;
|
|
630
|
+
/**
|
|
631
|
+
* Appends to (or overwrites) a booking's operator notes. Returns the updated
|
|
632
|
+
* booking, or null when the booking is not found.
|
|
633
|
+
*/
|
|
634
|
+
appendNote(bookingId: string, note: string, mode?: NoteMode): Promise<Booking | null>;
|
|
635
|
+
/**
|
|
636
|
+
* Sets a booking's check-in status. Returns the refreshed booking, or null
|
|
637
|
+
* when not found.
|
|
638
|
+
*/
|
|
639
|
+
setCheckinStatus(bookingId: string, checkedIn: boolean): Promise<Booking | null>;
|
|
640
|
+
/** Cancels a booking and returns its id/displayId/status. */
|
|
641
|
+
cancel(bookingId: string, notes?: string): Promise<CancelBookingResult>;
|
|
642
|
+
/**
|
|
643
|
+
* Charges a booking. Validates input, resolves the order + payment source via
|
|
644
|
+
* payments-on-file, then applies the payment. The `idempotencyKey` is passed
|
|
645
|
+
* through to Peek.
|
|
646
|
+
*
|
|
647
|
+
* @example
|
|
648
|
+
* ```ts
|
|
649
|
+
* const result = await peek.getBookingService().makePayment({
|
|
650
|
+
* bookingId: "b_abc123",
|
|
651
|
+
* paymentSourceId: "custom/other", // or a "ps_…" source on file
|
|
652
|
+
* amount: "25.00",
|
|
653
|
+
* currency: "USD",
|
|
654
|
+
* idempotencyKey: crypto.randomUUID(),
|
|
655
|
+
* });
|
|
656
|
+
* console.log(result.transactionId);
|
|
657
|
+
* ```
|
|
658
|
+
*
|
|
659
|
+
* @throws {Error} when `paymentSourceId` is missing or not a `ps_…` id / one
|
|
660
|
+
* of `cash/cash`, `custom/other`, `custom/voucher`; when `amount` is not a
|
|
661
|
+
* valid number; when `currency` is not a 3-letter uppercase code; when
|
|
662
|
+
* `idempotencyKey` is empty; when `bookingId` does not resolve to a `b_…` id;
|
|
663
|
+
* when the booking or payment source is not found; or when the charge fails.
|
|
664
|
+
*/
|
|
665
|
+
makePayment(input: MakePaymentInput): Promise<MakePaymentResult>;
|
|
666
|
+
/**
|
|
667
|
+
* Refunds a booking payment. Validates input, resolves the order + payment via
|
|
668
|
+
* payments-on-file, then applies the refund.
|
|
669
|
+
*/
|
|
670
|
+
refund(input: RefundInput): Promise<RefundResult>;
|
|
671
|
+
/** Creates an invoice link for a booking's order. */
|
|
672
|
+
createInvoiceLink(bookingId: string): Promise<InvoiceLinkResult>;
|
|
673
|
+
/** Returns the add-ons on a booking, grouped by add-on item (clean model). */
|
|
674
|
+
listAddons(bookingId: string): Promise<BookingAddons>;
|
|
675
|
+
/**
|
|
676
|
+
* Adds an add-on to a booking via createQuoteFromOrder → updateQuoteV2 →
|
|
677
|
+
* amendOrder. Lists the booking's add-ons first to derive the order id and
|
|
678
|
+
* reuse an existing add-on refid; resolves the add-on's parent item via the
|
|
679
|
+
* product service. Returns the booking's add-ons after the change.
|
|
680
|
+
*
|
|
681
|
+
* `quantity` is a **positive-integer string** ("1", "2", …); one add-on
|
|
682
|
+
* itemOption is created per unit. `addonOptionId` is the add-on's item-option
|
|
683
|
+
* id (a ticket id on an `ADD_ON_PRODUCT_TYPE` product from
|
|
684
|
+
* {@link ProductService.getAllProducts}).
|
|
685
|
+
*
|
|
686
|
+
* @example
|
|
687
|
+
* ```ts
|
|
688
|
+
* const result = await peek.getBookingService().addAddon("b_abc123", {
|
|
689
|
+
* addonOptionId: "io_helmet",
|
|
690
|
+
* quantity: "2",
|
|
691
|
+
* });
|
|
692
|
+
* console.log(result.updatedBookingAddons.addons);
|
|
693
|
+
* ```
|
|
694
|
+
*
|
|
695
|
+
* @throws {Error} when `addonOptionId` is missing, `quantity` is not a
|
|
696
|
+
* positive-integer string, the add-on is not found on any product, or any of
|
|
697
|
+
* the underlying quote/order mutations fail.
|
|
698
|
+
*/
|
|
699
|
+
addAddon(bookingId: string, input: AddAddonInput): Promise<BookingAddonsMutationResult>;
|
|
700
|
+
/**
|
|
701
|
+
* Removes (cancels) add-on options from a booking. Lists the booking's
|
|
702
|
+
* add-ons first to get the order id and the existing item/option refids, then
|
|
703
|
+
* issues the same three mutations as {@link addAddon} but with cancellation
|
|
704
|
+
* variables. Returns the booking's add-ons after the change.
|
|
705
|
+
*/
|
|
706
|
+
removeAddon(bookingId: string, input: AddAddonInput): Promise<BookingAddonsMutationResult>;
|
|
707
|
+
/**
|
|
708
|
+
* Runs the sales add-ons query for a booking, validates that exactly one
|
|
709
|
+
* booking matched, and parses the node into the internal model.
|
|
710
|
+
*/
|
|
711
|
+
private fetchBookingSale;
|
|
712
|
+
/**
|
|
713
|
+
* Runs `createQuoteFromOrder` and validates the response, returning the new
|
|
714
|
+
* quote id and the first sale quote refid (empty string when absent).
|
|
715
|
+
*/
|
|
716
|
+
private createQuoteFromOrderOrThrow;
|
|
717
|
+
/** Runs `updateQuoteV2` with the given quoteInput and validates the response. */
|
|
718
|
+
private updateQuoteOrThrow;
|
|
719
|
+
/** Runs `amendOrder` and validates the response. */
|
|
720
|
+
private amendOrderOrThrow;
|
|
721
|
+
/**
|
|
722
|
+
* Creates a booking via createQuoteV2 → createOrderFromQuote, optionally
|
|
723
|
+
* marking it paid. IDs must be pre-resolved (no free-text matching) — resolve
|
|
724
|
+
* `activityId` + ticket `resourceOptionId`s from {@link ProductService} and
|
|
725
|
+
* `availabilityTimeId` from {@link AvailabilityService.getAvailabilityTimes}.
|
|
726
|
+
*
|
|
727
|
+
* @example
|
|
728
|
+
* ```ts
|
|
729
|
+
* const created = await peek.getBookingService().create({
|
|
730
|
+
* activityId: "a_kayak_tour",
|
|
731
|
+
* availabilityTimeId: "at_2026_06_20_0900",
|
|
732
|
+
* tickets: [{ resourceOptionId: "ro_adult", quantity: 2 }],
|
|
733
|
+
* guest: { name: "Sam Rivera", email: "sam@example.com" },
|
|
734
|
+
* markAsPaid: true,
|
|
735
|
+
* idempotencyKey: crypto.randomUUID(),
|
|
736
|
+
* });
|
|
737
|
+
* console.log(created.bookingId, created.displayId, created.balanceFormatted);
|
|
738
|
+
* ```
|
|
739
|
+
*
|
|
740
|
+
* @throws {Error} when `activityId`, `availabilityTimeId`, a ticket
|
|
741
|
+
* `resourceOptionId`/positive `quantity`, or the guest `name` is missing; when
|
|
742
|
+
* `markAsPaid` is set without an `idempotencyKey`; or when the quote/order
|
|
743
|
+
* mutations fail.
|
|
744
|
+
*/
|
|
745
|
+
create(input: CreateBookingInput): Promise<CreatedBooking>;
|
|
746
|
+
private markCreatedBookingPaid;
|
|
747
|
+
/** Finds the parent item id of an add-on by matching its option id. */
|
|
748
|
+
private resolveParentItemId;
|
|
749
|
+
private validatePaymentInput;
|
|
750
|
+
private validateRefundInput;
|
|
751
|
+
private fetchPaginated;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* The clean data model for a Peek Pro daily (dashboard) note.
|
|
756
|
+
*/
|
|
757
|
+
/** The daily note shown on the Peek Pro dashboard. */
|
|
758
|
+
interface DailyNote {
|
|
759
|
+
/** The note text. */
|
|
760
|
+
note: string;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
declare class DailyNoteService {
|
|
764
|
+
private readonly client;
|
|
765
|
+
constructor(client: GraphQLClient);
|
|
766
|
+
/** Returns today's daily note, or null when none is set. */
|
|
767
|
+
getToday(): Promise<DailyNote | null>;
|
|
768
|
+
/** Upserts the daily note and returns the saved note, or null. */
|
|
769
|
+
update(note: string): Promise<DailyNote | null>;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* The clean data model for Peek Pro memberships.
|
|
774
|
+
*/
|
|
775
|
+
/**
|
|
776
|
+
* A flat representation of a Peek Pro membership variant.
|
|
777
|
+
*
|
|
778
|
+
* A membership can expose multiple variants; this model flattens each variant
|
|
779
|
+
* into its own record, carrying the parent membership's stable id and display
|
|
780
|
+
* name alongside the variant-level details. Memberships with no variants
|
|
781
|
+
* produce no records.
|
|
782
|
+
*/
|
|
783
|
+
interface Membership {
|
|
784
|
+
/** Parent membership id. */
|
|
785
|
+
id: string;
|
|
786
|
+
/** Variant id. */
|
|
787
|
+
membershipVariantId: string;
|
|
788
|
+
/** Variant description, or null. */
|
|
789
|
+
description: string | null;
|
|
790
|
+
/** Variant external (customer-facing) name. */
|
|
791
|
+
externalName: string;
|
|
792
|
+
/** Variant image URL, or null. */
|
|
793
|
+
imageUrl: string | null;
|
|
794
|
+
/** Variant internal name. */
|
|
795
|
+
internalName: string;
|
|
796
|
+
/** Parent membership display name. */
|
|
797
|
+
displayName: string;
|
|
798
|
+
}
|
|
799
|
+
/** Input for purchasing a membership. */
|
|
800
|
+
interface MembershipPurchaseInput {
|
|
801
|
+
/** The membership variant to purchase. */
|
|
802
|
+
membershipVariantId: string;
|
|
803
|
+
/** Member email (required). */
|
|
804
|
+
email: string;
|
|
805
|
+
/** ISO country code (optional). */
|
|
806
|
+
country?: string;
|
|
807
|
+
/** Formatted address (optional). */
|
|
808
|
+
formattedAddress?: string;
|
|
809
|
+
/** Membership code (optional). */
|
|
810
|
+
membershipCode?: string;
|
|
811
|
+
/** Member phone (optional). */
|
|
812
|
+
phone?: string;
|
|
813
|
+
/** Member name (optional). */
|
|
814
|
+
name?: string;
|
|
815
|
+
}
|
|
816
|
+
/** The result of purchasing a membership. */
|
|
817
|
+
interface PurchasedMembership {
|
|
818
|
+
orderId: string;
|
|
819
|
+
membershipId: string;
|
|
820
|
+
displayId: string;
|
|
821
|
+
primaryMemberId: string | null;
|
|
822
|
+
primaryMemberName: string | null;
|
|
823
|
+
balanceAmount: string;
|
|
824
|
+
balanceCurrency: string;
|
|
825
|
+
balanceFormatted: string;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
declare class MembershipService {
|
|
829
|
+
private readonly client;
|
|
830
|
+
constructor(client: GraphQLClient);
|
|
831
|
+
/** Returns all membership variants, flattened into {@link Membership} records. */
|
|
832
|
+
getAll(): Promise<Membership[]>;
|
|
833
|
+
/**
|
|
834
|
+
* Purchases a membership via the two-step quote → order flow. Throws on
|
|
835
|
+
* invalid input or when Peek returns errors.
|
|
836
|
+
*/
|
|
837
|
+
purchase(input: MembershipPurchaseInput): Promise<PurchasedMembership>;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/**
|
|
841
|
+
* The clean data model for Peek Pro reseller channels and their agents.
|
|
842
|
+
*/
|
|
843
|
+
/** A reseller channel on a Peek Pro account. */
|
|
844
|
+
interface Channel {
|
|
845
|
+
/** Unique identifier. */
|
|
846
|
+
id: string;
|
|
847
|
+
/** Channel name. */
|
|
848
|
+
name: string;
|
|
849
|
+
/** Free-text notes, or null. */
|
|
850
|
+
notes: string | null;
|
|
851
|
+
/** Pricing model reported by Peek. */
|
|
852
|
+
pricingModel: string;
|
|
853
|
+
/** Channel state (e.g. active/inactive). */
|
|
854
|
+
state: string;
|
|
855
|
+
/** Channel type. */
|
|
856
|
+
type: string;
|
|
857
|
+
/** Agents belonging to this channel. */
|
|
858
|
+
agents: Agent[];
|
|
859
|
+
}
|
|
860
|
+
/** An agent (contact) belonging to a {@link Channel}. */
|
|
861
|
+
interface Agent {
|
|
862
|
+
/** Email address, or null. */
|
|
863
|
+
email: string | null;
|
|
864
|
+
/** Agent name. */
|
|
865
|
+
name: string;
|
|
866
|
+
/** Internal notes, or null. */
|
|
867
|
+
internalNotes: string | null;
|
|
868
|
+
/** Phone number, or null. */
|
|
869
|
+
phone: string | null;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
declare class ResellerService {
|
|
873
|
+
private readonly client;
|
|
874
|
+
constructor(client: GraphQLClient);
|
|
875
|
+
/**
|
|
876
|
+
* Returns all reseller channels, each with up to `agentsPerChannel` agents
|
|
877
|
+
* (default 10).
|
|
878
|
+
*/
|
|
879
|
+
getAllChannels(agentsPerChannel?: number): Promise<Channel[]>;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* The clean data model for a Peek Pro resource pool (e.g. guides, equipment).
|
|
884
|
+
*/
|
|
885
|
+
/** Filter mode for which resource pools to return. */
|
|
886
|
+
type ResourcePoolMode = "ACTIVITY" | "ALL";
|
|
887
|
+
/** A resource pool on a Peek Pro account. */
|
|
888
|
+
interface ResourcePool {
|
|
889
|
+
/** Unique identifier. */
|
|
890
|
+
id: string;
|
|
891
|
+
/** Display name. */
|
|
892
|
+
name: string;
|
|
893
|
+
/** Image URL, or null. */
|
|
894
|
+
imageUrl: string | null;
|
|
895
|
+
/** Allocation mode reported by Peek. */
|
|
896
|
+
mode: string;
|
|
897
|
+
/** Display color as a hex string, or null. */
|
|
898
|
+
colorHex: string | null;
|
|
899
|
+
/** Configured quantity, or null when not set. */
|
|
900
|
+
quantity: number | null;
|
|
901
|
+
/** Category (e.g. `"guide"`). */
|
|
902
|
+
category: string;
|
|
903
|
+
/** Capacity, or null when not set. */
|
|
904
|
+
capacity: number | null;
|
|
905
|
+
/** How the resource is tracked, or null. */
|
|
906
|
+
resourceTrackingMode: string | null;
|
|
907
|
+
/** The account user backing this pool (e.g. for guides), or null. */
|
|
908
|
+
accountUser: ResourcePoolAccountUser | null;
|
|
909
|
+
}
|
|
910
|
+
/** Minimal account-user reference attached to a {@link ResourcePool}. */
|
|
911
|
+
interface ResourcePoolAccountUser {
|
|
912
|
+
id: string;
|
|
913
|
+
name: string;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
declare class ResourcePoolService {
|
|
917
|
+
private readonly client;
|
|
918
|
+
constructor(client: GraphQLClient);
|
|
919
|
+
/**
|
|
920
|
+
* Returns all resource pools for the given mode filter (defaults to `"ALL"`).
|
|
921
|
+
*/
|
|
922
|
+
getAll(mode?: ResourcePoolMode): Promise<ResourcePool[]>;
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
/**
|
|
926
|
+
* The clean data model for Peek Pro timeslots and timeslot operations.
|
|
927
|
+
*/
|
|
928
|
+
/** A bookable timeslot for an activity. */
|
|
929
|
+
interface Timeslot {
|
|
930
|
+
/** Unique identifier. */
|
|
931
|
+
id: string;
|
|
932
|
+
/** The activity (product) id this timeslot belongs to. */
|
|
933
|
+
productId: string;
|
|
934
|
+
/** Total capacity of the timeslot. */
|
|
935
|
+
totalCapacity: number;
|
|
936
|
+
/** Remaining available capacity. */
|
|
937
|
+
availableCapacity: number;
|
|
938
|
+
/** Maximum party size per booking. */
|
|
939
|
+
maxPartySize: number;
|
|
940
|
+
/** Number of bookings on the timeslot. */
|
|
941
|
+
bookingCount: number;
|
|
942
|
+
/** Number of checked-in guests. */
|
|
943
|
+
checkedInCount: number;
|
|
944
|
+
/** Status reported by Peek (e.g. open/closed). */
|
|
945
|
+
status: string;
|
|
946
|
+
/** Manifest notes, or null. */
|
|
947
|
+
notes: string | null;
|
|
948
|
+
/** Duration in minutes. */
|
|
949
|
+
durationMin: number;
|
|
950
|
+
/** Date (YYYY-MM-DD). */
|
|
951
|
+
date: string;
|
|
952
|
+
/** Start time, or null. */
|
|
953
|
+
startTime: string | null;
|
|
954
|
+
/** Resources (e.g. guides, equipment) allocated to this timeslot. */
|
|
955
|
+
assignedResources: AssignedResource[];
|
|
956
|
+
}
|
|
957
|
+
/** A resource allocated to a {@link Timeslot}. */
|
|
958
|
+
interface AssignedResource {
|
|
959
|
+
/** Resource pool id. */
|
|
960
|
+
id: string;
|
|
961
|
+
/** Resource pool name. */
|
|
962
|
+
name: string;
|
|
963
|
+
/** Resource pool capacity. */
|
|
964
|
+
capacity: number;
|
|
965
|
+
/** Resource pool category (e.g. `"guide"`). */
|
|
966
|
+
category: string;
|
|
967
|
+
/** Allocated quantity. */
|
|
968
|
+
quantity: number;
|
|
969
|
+
/** Backing account user id, or null. */
|
|
970
|
+
accountUserId: string | null;
|
|
971
|
+
}
|
|
972
|
+
/** Booking filter for {@link Timeslot} day queries. */
|
|
973
|
+
type TimeslotFilter = "all" | "withBookings" | "withoutBookings";
|
|
974
|
+
/** Result of a timeslot update (set availability / notes). */
|
|
975
|
+
interface UpdateTimeslotResult {
|
|
976
|
+
manifestNotes: string | null;
|
|
977
|
+
status: string | null;
|
|
978
|
+
}
|
|
979
|
+
/** Input describing a guide (un)assignment across timeslots. */
|
|
980
|
+
interface GuideAssignment {
|
|
981
|
+
/** Timeslots to (un)assign. */
|
|
982
|
+
timeslotIds: string[];
|
|
983
|
+
/** Guides to (un)assign — matched by resource-pool id, account-user id, or name. */
|
|
984
|
+
guideIds: string[];
|
|
985
|
+
/** Whether to assign or unassign. */
|
|
986
|
+
action: "assign" | "unassign";
|
|
987
|
+
}
|
|
988
|
+
/** Result of a guide (un)assignment request. */
|
|
989
|
+
interface AssignGuideResult {
|
|
990
|
+
status: "success" | "error";
|
|
991
|
+
/** The created allocation request id on success, else null. */
|
|
992
|
+
resourceAllocationRequestId: string | null;
|
|
993
|
+
/** Error details on failure, else null. */
|
|
994
|
+
errors: Array<{
|
|
995
|
+
message: string;
|
|
996
|
+
}> | null;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
/**
|
|
1000
|
+
* Timeslot operations against the Peek gateway.
|
|
1001
|
+
*
|
|
1002
|
+
* Obtain an instance via {@link PeekAccessService.getTimeslotService}. The
|
|
1003
|
+
* `assignGuide` operation composes the resource-pool and account-user services
|
|
1004
|
+
* to resolve guides before issuing the allocation request.
|
|
1005
|
+
*/
|
|
1006
|
+
|
|
1007
|
+
/** Dependencies the {@link TimeslotService} composes for guide assignment. */
|
|
1008
|
+
interface TimeslotServiceDeps {
|
|
1009
|
+
resourcePoolService: ResourcePoolService;
|
|
1010
|
+
accountUserService: AccountUserService;
|
|
1011
|
+
}
|
|
1012
|
+
declare class TimeslotService {
|
|
1013
|
+
private readonly client;
|
|
1014
|
+
private readonly deps;
|
|
1015
|
+
constructor(client: GraphQLClient, deps: TimeslotServiceDeps);
|
|
1016
|
+
/** Returns the timeslots for an activity on a given date. */
|
|
1017
|
+
getForDay(productId: string, date: string, filter?: TimeslotFilter): Promise<Timeslot[]>;
|
|
1018
|
+
/** Returns a single timeslot by id, or null when not found. */
|
|
1019
|
+
getById(timeslotId: string): Promise<Timeslot | null>;
|
|
1020
|
+
/** Sets the timeslot's status (e.g. open/closed). */
|
|
1021
|
+
setAvailability(timeslotId: string, status: string): Promise<UpdateTimeslotResult>;
|
|
1022
|
+
/** Sets the timeslot's manifest notes. */
|
|
1023
|
+
setNotes(timeslotId: string, manifestNotes: string): Promise<UpdateTimeslotResult>;
|
|
1024
|
+
/**
|
|
1025
|
+
* Assigns or unassigns guides across timeslots. Guides are resolved to
|
|
1026
|
+
* resource pools (by pool id, account-user id, or name) before the bulk
|
|
1027
|
+
* allocation request is issued.
|
|
1028
|
+
*
|
|
1029
|
+
* @example
|
|
1030
|
+
* ```ts
|
|
1031
|
+
* await peek.getTimeslotService().assignGuide({
|
|
1032
|
+
* timeslotIds: ["ts_2026_06_20_0900"],
|
|
1033
|
+
* guideIds: ["Alex Guide"], // pool id, account-user id, or name
|
|
1034
|
+
* action: "assign",
|
|
1035
|
+
* });
|
|
1036
|
+
* ```
|
|
1037
|
+
*/
|
|
1038
|
+
assignGuide(assignment: GuideAssignment): Promise<AssignGuideResult>;
|
|
1039
|
+
private updateTimeslot;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
/**
|
|
1043
|
+
* The clean data model for Peek Pro promo codes.
|
|
1044
|
+
*/
|
|
1045
|
+
/** A promo code on a Peek Pro account. */
|
|
1046
|
+
interface PromoCode {
|
|
1047
|
+
/** Unique identifier. */
|
|
1048
|
+
id: string;
|
|
1049
|
+
/** Display name. */
|
|
1050
|
+
name: string;
|
|
1051
|
+
/** Percentage discount (0–100), or null for a fixed-amount code. */
|
|
1052
|
+
percentAmount: number | null;
|
|
1053
|
+
/** Whether the discount applies per ticket. */
|
|
1054
|
+
perTicketDiscount: boolean;
|
|
1055
|
+
/** The code guests redeem. */
|
|
1056
|
+
redemptionCode: string;
|
|
1057
|
+
/** Fixed-amount discount, or null for a percentage code. */
|
|
1058
|
+
fixedAmount: PromoCodeFixedAmount | null;
|
|
1059
|
+
}
|
|
1060
|
+
/** A fixed monetary discount on a {@link PromoCode}. */
|
|
1061
|
+
interface PromoCodeFixedAmount {
|
|
1062
|
+
/** Amount in the currency's minor/major unit as reported by Peek. */
|
|
1063
|
+
amount: number;
|
|
1064
|
+
/** ISO currency code. */
|
|
1065
|
+
currency: string;
|
|
1066
|
+
/** Human-formatted amount (e.g. `"$10.00"`). */
|
|
1067
|
+
formatted: string;
|
|
1068
|
+
}
|
|
1069
|
+
/** Input for creating a promo code. */
|
|
1070
|
+
interface CreatePromoCodeInput {
|
|
1071
|
+
/** Display name. */
|
|
1072
|
+
name: string;
|
|
1073
|
+
/** The redemption code. */
|
|
1074
|
+
code: string;
|
|
1075
|
+
/** Discount amount as a string (percentage or fixed value). */
|
|
1076
|
+
amount: string;
|
|
1077
|
+
/** Whether `amount` is a percentage or a fixed monetary value. */
|
|
1078
|
+
discountType: "percent" | "fixed";
|
|
1079
|
+
/** Optional cap on total redemptions. */
|
|
1080
|
+
maxRedemptions?: number;
|
|
1081
|
+
/** ISO currency code for fixed discounts. Defaults to `"USD"`. */
|
|
1082
|
+
currency?: string;
|
|
1083
|
+
}
|
|
1084
|
+
/** The result of creating a promo code (the mutation returns id + name). */
|
|
1085
|
+
interface CreatedPromoCode {
|
|
1086
|
+
id: string;
|
|
1087
|
+
name: string;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
/** Tuning options for a {@link PromoCodeService}. */
|
|
1091
|
+
interface PromoCodeServiceOptions {
|
|
1092
|
+
/** Page size for cursor pagination. Default: 50. */
|
|
1093
|
+
pageSize?: number;
|
|
1094
|
+
}
|
|
1095
|
+
declare class PromoCodeService {
|
|
1096
|
+
private readonly client;
|
|
1097
|
+
private readonly pageSize;
|
|
1098
|
+
constructor(client: GraphQLClient, options?: PromoCodeServiceOptions);
|
|
1099
|
+
/** Returns all promo codes, walking the cursor pagination to the end. */
|
|
1100
|
+
getAll(): Promise<PromoCode[]>;
|
|
1101
|
+
/**
|
|
1102
|
+
* Creates a promo code. Throws on invalid input or when Peek returns an
|
|
1103
|
+
* InvalidDataError.
|
|
1104
|
+
*/
|
|
1105
|
+
create(input: CreatePromoCodeInput): Promise<CreatedPromoCode>;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
/**
|
|
1109
|
+
* Authenticated root entry point to the Peek backoffice GraphQL gateway.
|
|
1110
|
+
*
|
|
1111
|
+
* Configure one instance per install with everything needed to authenticate and
|
|
1112
|
+
* reach the gateway. The access service owns the shared, authenticated
|
|
1113
|
+
* transport (it mints and caches tokens on demand) and hands out per-resource
|
|
1114
|
+
* service objects — e.g. {@link PeekAccessService.getProductService} — that
|
|
1115
|
+
* carry the resource-specific business logic.
|
|
1116
|
+
*/
|
|
1117
|
+
|
|
1118
|
+
/** Configuration for a {@link PeekAccessService} instance. */
|
|
1119
|
+
interface PeekAccessServiceConfig {
|
|
1120
|
+
/** Peek install ID. Becomes the JWT subject. */
|
|
1121
|
+
installId: string;
|
|
1122
|
+
/** HMAC secret used to sign the JWT (the Peek internal secret). */
|
|
1123
|
+
jwtSecret: string;
|
|
1124
|
+
/** JWT issuer — the app name. */
|
|
1125
|
+
issuer: string;
|
|
1126
|
+
/** Peek app ID, used in the gateway endpoint path. */
|
|
1127
|
+
appId: string;
|
|
1128
|
+
/** API gateway key, sent as the `pk-api-key` header. */
|
|
1129
|
+
gatewayKey: string;
|
|
1130
|
+
/** Override the gateway base URL. Default: Peek production gateway. */
|
|
1131
|
+
baseUrl?: string;
|
|
1132
|
+
/** JWT lifetime in seconds. Default: 3600. */
|
|
1133
|
+
tokenTtlSeconds?: number;
|
|
1134
|
+
/** Re-mint the cached token this many seconds before expiry. Default: 60. */
|
|
1135
|
+
tokenRefreshLeewaySeconds?: number;
|
|
1136
|
+
/** Backoff delays (ms) for HTTP 429 retries. Default: [1000, 2000, 4000]. */
|
|
1137
|
+
retryDelaysMs?: number[];
|
|
1138
|
+
/** Optional logger. Default: no-op (silent). */
|
|
1139
|
+
logger?: Logger;
|
|
1140
|
+
/** Custom `fetch` implementation. Default: the global `fetch`. */
|
|
1141
|
+
fetch?: typeof fetch;
|
|
1142
|
+
/** Page size for cursor-paginated item options. Default: 50. */
|
|
1143
|
+
itemOptionsPageSize?: number;
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* Authenticated root entry point to the Peek backoffice GraphQL gateway.
|
|
1147
|
+
*
|
|
1148
|
+
* Construct one instance per install, then call the `get<Resource>Service()`
|
|
1149
|
+
* accessors to reach the resource-specific operations. Each accessor returns a
|
|
1150
|
+
* memoized service bound to the shared, authenticated transport — the access
|
|
1151
|
+
* service mints and caches a short-lived JWT on demand.
|
|
1152
|
+
*
|
|
1153
|
+
* @example Configure once, then call resource services
|
|
1154
|
+
* ```ts
|
|
1155
|
+
* import { PeekAccessService, type Product } from "@peektravel/app-utilities";
|
|
1156
|
+
*
|
|
1157
|
+
* const peek = new PeekAccessService({
|
|
1158
|
+
* installId: "install-123", // JWT subject
|
|
1159
|
+
* jwtSecret: process.env.PEEK_INTERNAL_SECRET!, // signs the JWT
|
|
1160
|
+
* issuer: process.env.APP_NAME!, // JWT issuer
|
|
1161
|
+
* appId: process.env.PEEK_APP_ID!, // gateway path segment
|
|
1162
|
+
* gatewayKey: process.env.PEEK_GATEWAY_KEY!, // pk-api-key header
|
|
1163
|
+
* });
|
|
1164
|
+
*
|
|
1165
|
+
* const products: Product[] = await peek.getProductService().getAllProducts();
|
|
1166
|
+
* const booking = await peek.getBookingService().getById("b_abc123");
|
|
1167
|
+
* ```
|
|
1168
|
+
*
|
|
1169
|
+
* @throws {Error} from the constructor when any required config field
|
|
1170
|
+
* (`installId`, `jwtSecret`, `issuer`, `appId`, `gatewayKey`) is empty.
|
|
1171
|
+
*/
|
|
1172
|
+
declare class PeekAccessService {
|
|
1173
|
+
private readonly client;
|
|
1174
|
+
private readonly productServiceOptions;
|
|
1175
|
+
private productService?;
|
|
1176
|
+
private accountUserService?;
|
|
1177
|
+
private resourcePoolService?;
|
|
1178
|
+
private timeslotService?;
|
|
1179
|
+
private resellerService?;
|
|
1180
|
+
private promoCodeService?;
|
|
1181
|
+
private dailyNoteService?;
|
|
1182
|
+
private availabilityService?;
|
|
1183
|
+
private membershipService?;
|
|
1184
|
+
private bookingService?;
|
|
1185
|
+
constructor(config: PeekAccessServiceConfig);
|
|
1186
|
+
/**
|
|
1187
|
+
* Returns the {@link ProductService} for this install, bound to the shared
|
|
1188
|
+
* authenticated transport. The instance is created lazily and reused.
|
|
1189
|
+
*/
|
|
1190
|
+
getProductService(): ProductService;
|
|
1191
|
+
/**
|
|
1192
|
+
* Returns the {@link AccountUserService} for this install, bound to the shared
|
|
1193
|
+
* authenticated transport. The instance is created lazily and reused.
|
|
1194
|
+
*/
|
|
1195
|
+
getAccountUserService(): AccountUserService;
|
|
1196
|
+
/**
|
|
1197
|
+
* Returns the {@link ResourcePoolService} for this install, bound to the
|
|
1198
|
+
* shared authenticated transport. The instance is created lazily and reused.
|
|
1199
|
+
*/
|
|
1200
|
+
getResourcePoolService(): ResourcePoolService;
|
|
1201
|
+
/**
|
|
1202
|
+
* Returns the {@link TimeslotService} for this install, bound to the shared
|
|
1203
|
+
* authenticated transport. The instance is created lazily and reused; its
|
|
1204
|
+
* guide assignment composes the resource-pool and account-user services.
|
|
1205
|
+
*/
|
|
1206
|
+
getTimeslotService(): TimeslotService;
|
|
1207
|
+
/**
|
|
1208
|
+
* Returns the {@link ResellerService} for this install, bound to the shared
|
|
1209
|
+
* authenticated transport. The instance is created lazily and reused.
|
|
1210
|
+
*/
|
|
1211
|
+
getResellerService(): ResellerService;
|
|
1212
|
+
/**
|
|
1213
|
+
* Returns the {@link PromoCodeService} for this install, bound to the shared
|
|
1214
|
+
* authenticated transport. The instance is created lazily and reused.
|
|
1215
|
+
*/
|
|
1216
|
+
getPromoCodeService(): PromoCodeService;
|
|
1217
|
+
/**
|
|
1218
|
+
* Returns the {@link DailyNoteService} for this install, bound to the shared
|
|
1219
|
+
* authenticated transport. The instance is created lazily and reused.
|
|
1220
|
+
*/
|
|
1221
|
+
getDailyNoteService(): DailyNoteService;
|
|
1222
|
+
/**
|
|
1223
|
+
* Returns the {@link AvailabilityService} for this install, bound to the
|
|
1224
|
+
* shared authenticated transport. The instance is created lazily and reused.
|
|
1225
|
+
*/
|
|
1226
|
+
getAvailabilityService(): AvailabilityService;
|
|
1227
|
+
/**
|
|
1228
|
+
* Returns the {@link MembershipService} for this install, bound to the shared
|
|
1229
|
+
* authenticated transport. The instance is created lazily and reused.
|
|
1230
|
+
*/
|
|
1231
|
+
getMembershipService(): MembershipService;
|
|
1232
|
+
/**
|
|
1233
|
+
* Returns the {@link BookingService} for this install, bound to the shared
|
|
1234
|
+
* authenticated transport. The instance is created lazily and reused.
|
|
1235
|
+
*/
|
|
1236
|
+
getBookingService(): BookingService;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
/**
|
|
1240
|
+
* Typed errors thrown by the package. Each mirrors a failure mode of the Peek
|
|
1241
|
+
* GraphQL gateway so callers can branch on the error type rather than parsing
|
|
1242
|
+
* messages.
|
|
1243
|
+
*/
|
|
1244
|
+
/**
|
|
1245
|
+
* Thrown when the gateway responds with HTTP 418, indicating the install is not
|
|
1246
|
+
* permitted to perform the request because an admin account is required.
|
|
1247
|
+
*/
|
|
1248
|
+
declare class AdminAccountRequiredError extends Error {
|
|
1249
|
+
/** The HTTP status that triggered this error. */
|
|
1250
|
+
readonly statusCode = 418;
|
|
1251
|
+
constructor(message?: string);
|
|
1252
|
+
}
|
|
1253
|
+
/**
|
|
1254
|
+
* Thrown when the gateway responds with HTTP 429 and all configured retries
|
|
1255
|
+
* have been exhausted.
|
|
1256
|
+
*/
|
|
1257
|
+
declare class RateLimitError extends Error {
|
|
1258
|
+
/** The HTTP status that triggered this error. */
|
|
1259
|
+
readonly statusCode = 429;
|
|
1260
|
+
constructor(message?: string);
|
|
1261
|
+
}
|
|
1262
|
+
/**
|
|
1263
|
+
* Thrown when a GraphQL response contains an `errors` array. The raw errors are
|
|
1264
|
+
* preserved on {@link PeekGraphQLError.graphqlErrors} for inspection.
|
|
1265
|
+
*/
|
|
1266
|
+
declare class PeekGraphQLError extends Error {
|
|
1267
|
+
/** The raw `errors` array returned by the GraphQL endpoint. */
|
|
1268
|
+
readonly graphqlErrors: unknown[];
|
|
1269
|
+
constructor(graphqlErrors: unknown[], message?: string);
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
export { ADD_ON_PRODUCT_TYPE, type AccountUser, AccountUserService, type AccountUserServiceOptions, type AddAddonInput, AdminAccountRequiredError, type Agent, type AssignGuideResult, type AssignedActivity, type AssignedResource, type Availability, AvailabilityService, type AvailabilityTime, type AvailabilityTimesQuery, type Booking, type BookingAddon, type BookingAddonMoney, type BookingAddonOption, type BookingAddons, type BookingAddonsMutationResult, type BookingPaymentsOnFile, type BookingReadOptions, type BookingSearchBy, BookingService, type BookingServiceOptions, type BookingTimeRangeSearch, type CancelBookingResult, type Channel, type CreateBookingGuest, type CreateBookingInput, type CreateBookingTicket, type CreatePromoCodeInput, type CreatedBooking, type CreatedPromoCode, type CustomQuestionAnswer, type DailyNote, DailyNoteService, type Duration, type Guest, type GuestMetadata, type GuideAssignment, type InvoiceLinkResult, type Logger, type MakePaymentInput, type MakePaymentResult, type Membership, type MembershipPurchaseInput, MembershipService, type NoteMode, type Payment, type PaymentSource, PeekAccessService, type PeekAccessServiceConfig, PeekGraphQLError, type Price, type Product, ProductService, type ProductServiceOptions, type ProductTicket, type PromoCode, type PromoCodeFixedAmount, PromoCodeService, type PromoCodeServiceOptions, type PurchasedMembership, RateLimitError, type RefundInput, type RefundResult, ResellerService, type Resource, type ResourceOptionQuantity, type ResourcePool, type ResourcePoolAccountUser, type ResourcePoolAssignment, type ResourcePoolMode, ResourcePoolService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateTimeslotResult, noopLogger };
|