Skip to content

Commit 8d466b9

Browse files
committed
feat: hide services from top-level
1 parent aaf75d7 commit 8d466b9

6 files changed

Lines changed: 515 additions & 3 deletions

File tree

docs/internal/ARCHITECTURE.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ point (`PeekAccessService`) that hands out per-resource services returning clean
77
plain-object data models.
88

99
Consumers never see GraphQL. They construct one access service per install and
10-
call typed methods like `peek.getProductService().getAllProducts()`.
10+
call typed methods like `peek.getProductService().getAllProducts()` or directly
11+
via the top-level short-forms like `peek.getAllProducts()` and
12+
`peek.getAllActivities()`.
1113

1214
## Layers
1315

@@ -44,6 +46,8 @@ call typed methods like `peek.getProductService().getAllProducts()`.
4446
- Constructs a single shared `TokenManager` and `GraphQLClient`.
4547
- Exposes one `get<Resource>Service()` accessor per resource. Each is **lazily
4648
created and memoized** — repeated calls return the same instance.
49+
- Exposes **top-level short-form methods** that delegate directly to the
50+
underlying service, e.g. `peek.getAllProducts()``peek.getProductService().getAllProducts()`. Every public service method has a named proxy on `PeekAccessService`; the names are prefixed with the resource noun where disambiguation is needed (e.g. `getBookingById`, `getTimeslotById`).
4751
- Exposes `verifyPeekAuthToken(token)` to verify HMAC-signed JWTs issued by
4852
the Peek app registry (`iss: "app_registry_v2"`), returning
4953
a fully typed `PeekAuthTokenClaims` (including the nested `PeekAuthTokenUser`
@@ -108,6 +112,10 @@ Resources: `products`, `account-users`, `resource-pools`, `timeslots`,
108112
`resellers`, `promo-codes`, `daily-notes`, `availability`, `memberships`,
109113
`bookings`, `reviews`. Clean data shapes live in `src/models/`.
110114

115+
`ProductService` exposes three top-level product filters in addition to the combined `getAllProducts()`:
116+
- `getAllActivities()` — fetches only the `activities` connection (one request, no add-on pagination).
117+
- `getAllAddons()` — fetches only the `itemOptions` connection, paginated.
118+
111119
`waivers` is a **webhook-only resource**: it has no GraphQL reads (so no
112120
queries/service/converter triad), just `src/internal/waivers/waiver-webhook.ts`
113121
and the `src/models/waiver.ts` model. See the webhook notes below.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@peektravel/app-utilities",
3-
"version": "0.2.3",
3+
"version": "0.2.4",
44
"description": "GraphQL JS mapping utilities extracted from the Peek Pro Autopilot connector.",
55
"license": "MIT",
66
"repository": {

src/internal/products/product-service.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,18 @@ export class ProductService {
6060
return [...fromActivities(activities), ...fromItemOptionNodes(itemOptionNodes)];
6161
}
6262

63+
/** Returns only activity products (excludes add-ons). */
64+
async getAllActivities(): Promise<Product[]> {
65+
const activities = await this.fetchActivities();
66+
return fromActivities(activities);
67+
}
68+
69+
/** Returns only add-on products. */
70+
async getAllAddons(): Promise<Product[]> {
71+
const nodes = await this.fetchAllItemOptionNodes();
72+
return fromItemOptionNodes(nodes);
73+
}
74+
6375
private async fetchActivities(): Promise<ProductsResponse["activities"]> {
6476
const body: GraphQLBody<ProductsResponse> =
6577
await this.client.request<ProductsResponse>(

src/peek-access-service.ts

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,19 @@ import { V2_EXTENDABLE_SLUG } from "./internal/gateway-endpoints.js";
2727
import { TokenManager } from "./internal/token-manager.js";
2828
import { noopLogger, type Logger } from "./logger.js";
2929
import type { PeekAuthTokenClaims } from "./models/auth-token.js";
30+
import type { AvailabilityTimesQuery } from "./models/availability-time.js";
31+
import type {
32+
BookingReadOptions,
33+
BookingTimeRangeSearch,
34+
CreateBookingInput,
35+
NoteMode,
36+
} from "./models/booking.js";
37+
import type { MakePaymentInput, RefundInput } from "./models/booking-payment.js";
38+
import type { MembershipPurchaseInput } from "./models/membership.js";
39+
import type { CreatePromoCodeInput } from "./models/promo-code.js";
40+
import type { ResourcePoolMode } from "./models/resource-pool.js";
41+
import type { GuideAssignment, TimeslotFilter } from "./models/timeslot.js";
42+
import type { AddAddonInput } from "./internal/bookings/booking-service.js";
3043

3144
/** Default backoffice GraphQL gateway base URL (v1). */
3245
const DEFAULT_BASE_URL = "https://apps.peekapis.com/backoffice-gql";
@@ -331,6 +344,169 @@ export class PeekAccessService {
331344
}
332345
return this.reviewService;
333346
}
347+
348+
// ─── Product short-forms ─────────────────────────────────────────────────
349+
350+
/** All products (activities + add-ons). Delegates to {@link ProductService.getAllProducts}. */
351+
getAllProducts() { return this.getProductService().getAllProducts(); }
352+
353+
/** All activity products (excludes add-ons). Delegates to {@link ProductService.getAllActivities}. */
354+
getAllActivities() { return this.getProductService().getAllActivities(); }
355+
356+
/** All add-on products. Delegates to {@link ProductService.getAllAddons}. */
357+
getAllAddons() { return this.getProductService().getAllAddons(); }
358+
359+
// ─── Account-user short-forms ─────────────────────────────────────────────
360+
361+
/** All active account users. Delegates to {@link AccountUserService.getAll}. */
362+
getAllAccountUsers() { return this.getAccountUserService().getAll(); }
363+
364+
/** Account user by id, or null. Delegates to {@link AccountUserService.getById}. */
365+
getAccountUserById(userId: string) { return this.getAccountUserService().getById(userId); }
366+
367+
// ─── Resource-pool short-forms ────────────────────────────────────────────
368+
369+
/** All resource pools. Delegates to {@link ResourcePoolService.getAll}. */
370+
getAllResourcePools(mode?: ResourcePoolMode) { return this.getResourcePoolService().getAll(mode); }
371+
372+
// ─── Timeslot short-forms ─────────────────────────────────────────────────
373+
374+
/** Timeslots for an activity on a given date. Delegates to {@link TimeslotService.getForDay}. */
375+
getTimeslotsForDay(productId: string, date: string, filter?: TimeslotFilter) {
376+
return this.getTimeslotService().getForDay(productId, date, filter);
377+
}
378+
379+
/** Single timeslot by id. Delegates to {@link TimeslotService.getById}. */
380+
getTimeslotById(timeslotId: string) { return this.getTimeslotService().getById(timeslotId); }
381+
382+
/** Set timeslot status. Delegates to {@link TimeslotService.setAvailability}. */
383+
setTimeslotAvailability(timeslotId: string, status: string) {
384+
return this.getTimeslotService().setAvailability(timeslotId, status);
385+
}
386+
387+
/** Set timeslot manifest notes. Delegates to {@link TimeslotService.setNotes}. */
388+
setTimeslotNotes(timeslotId: string, manifestNotes: string) {
389+
return this.getTimeslotService().setNotes(timeslotId, manifestNotes);
390+
}
391+
392+
/** Assign or unassign guides on timeslots. Delegates to {@link TimeslotService.assignGuide}. */
393+
assignTimeslotGuide(assignment: GuideAssignment) {
394+
return this.getTimeslotService().assignGuide(assignment);
395+
}
396+
397+
// ─── Reseller short-forms ─────────────────────────────────────────────────
398+
399+
/** All reseller channels. Delegates to {@link ResellerService.getAllChannels}. */
400+
getAllChannels(agentsPerChannel?: number) {
401+
return this.getResellerService().getAllChannels(agentsPerChannel);
402+
}
403+
404+
// ─── Promo-code short-forms ───────────────────────────────────────────────
405+
406+
/** All promo codes. Delegates to {@link PromoCodeService.getAll}. */
407+
getAllPromoCodes() { return this.getPromoCodeService().getAll(); }
408+
409+
/** Create a promo code. Delegates to {@link PromoCodeService.create}. */
410+
createPromoCode(input: CreatePromoCodeInput) { return this.getPromoCodeService().create(input); }
411+
412+
// ─── Daily-note short-forms ───────────────────────────────────────────────
413+
414+
/** Today's daily note. Delegates to {@link DailyNoteService.getToday}. */
415+
getDailyNoteToday() { return this.getDailyNoteService().getToday(); }
416+
417+
/** Update today's daily note. Delegates to {@link DailyNoteService.update}. */
418+
updateDailyNote(note: string) { return this.getDailyNoteService().update(note); }
419+
420+
// ─── Availability short-forms ─────────────────────────────────────────────
421+
422+
/** Availability times for an activity. Delegates to {@link AvailabilityService.getAvailabilityTimes}. */
423+
getAvailabilityTimes(query: AvailabilityTimesQuery) {
424+
return this.getAvailabilityService().getAvailabilityTimes(query);
425+
}
426+
427+
// ─── Membership short-forms ───────────────────────────────────────────────
428+
429+
/** All memberships. Delegates to {@link MembershipService.getAll}. */
430+
getAllMemberships() { return this.getMembershipService().getAll(); }
431+
432+
/** Purchase a membership. Delegates to {@link MembershipService.purchase}. */
433+
purchaseMembership(input: MembershipPurchaseInput) {
434+
return this.getMembershipService().purchase(input);
435+
}
436+
437+
// ─── Booking short-forms ──────────────────────────────────────────────────
438+
439+
/** Booking by id. Delegates to {@link BookingService.getById}. */
440+
getBookingById(bookingId: string, options?: BookingReadOptions) {
441+
return this.getBookingService().getById(bookingId, options);
442+
}
443+
444+
/** Bookings by time range. Delegates to {@link BookingService.searchByTimeRange}. */
445+
searchBookingsByTimeRange(input: BookingTimeRangeSearch) {
446+
return this.getBookingService().searchByTimeRange(input);
447+
}
448+
449+
/** Bookings on a timeslot. Delegates to {@link BookingService.searchByTimeslot}. */
450+
searchBookingsByTimeslot(timeslotId: string, options?: BookingReadOptions) {
451+
return this.getBookingService().searchByTimeslot(timeslotId, options);
452+
}
453+
454+
/** Guests on a booking. Delegates to {@link BookingService.getGuests}. */
455+
getBookingGuests(bookingId: string) { return this.getBookingService().getGuests(bookingId); }
456+
457+
/** Payments on file for a booking. Delegates to {@link BookingService.getPaymentsOnFile}. */
458+
getBookingPaymentsOnFile(bookingId: string) {
459+
return this.getBookingService().getPaymentsOnFile(bookingId);
460+
}
461+
462+
/** Append or overwrite operator notes. Delegates to {@link BookingService.appendNote}. */
463+
appendBookingNote(bookingId: string, note: string, mode?: NoteMode) {
464+
return this.getBookingService().appendNote(bookingId, note, mode);
465+
}
466+
467+
/** Set booking check-in status. Delegates to {@link BookingService.setCheckinStatus}. */
468+
setBookingCheckinStatus(bookingId: string, checkedIn: boolean) {
469+
return this.getBookingService().setCheckinStatus(bookingId, checkedIn);
470+
}
471+
472+
/** Cancel a booking. Delegates to {@link BookingService.cancel}. */
473+
cancelBooking(bookingId: string, notes?: string) {
474+
return this.getBookingService().cancel(bookingId, notes);
475+
}
476+
477+
/** Charge a booking. Delegates to {@link BookingService.makePayment}. */
478+
makeBookingPayment(input: MakePaymentInput) { return this.getBookingService().makePayment(input); }
479+
480+
/** Refund a booking payment. Delegates to {@link BookingService.refund}. */
481+
refundBooking(input: RefundInput) { return this.getBookingService().refund(input); }
482+
483+
/** Create an invoice link. Delegates to {@link BookingService.createInvoiceLink}. */
484+
createBookingInvoiceLink(bookingId: string) {
485+
return this.getBookingService().createInvoiceLink(bookingId);
486+
}
487+
488+
/** List add-ons on a booking. Delegates to {@link BookingService.listAddons}. */
489+
listBookingAddons(bookingId: string) { return this.getBookingService().listAddons(bookingId); }
490+
491+
/** Add an add-on to a booking. Delegates to {@link BookingService.addAddon}. */
492+
addBookingAddon(bookingId: string, input: AddAddonInput) {
493+
return this.getBookingService().addAddon(bookingId, input);
494+
}
495+
496+
/** Remove an add-on from a booking. Delegates to {@link BookingService.removeAddon}. */
497+
removeBookingAddon(bookingId: string, input: AddAddonInput) {
498+
return this.getBookingService().removeAddon(bookingId, input);
499+
}
500+
501+
/** Create a booking. Delegates to {@link BookingService.create}. */
502+
createBooking(input: CreateBookingInput) { return this.getBookingService().create(input); }
503+
504+
// ─── Review short-forms ───────────────────────────────────────────────────
505+
506+
/** Reviews for an activity. Delegates to {@link ReviewService.getReviews}. */
507+
getReviews(productId: string, reviewCount?: number, reviewOffset?: number) {
508+
return this.getReviewService().getReviews(productId, reviewCount, reviewOffset);
509+
}
334510
}
335511

336512
function requireNonEmpty(value: string, name: string): void {

0 commit comments

Comments
 (0)