@peektravel/app-utilities 0.5.2 → 0.5.4

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.d.cts CHANGED
@@ -1797,6 +1797,36 @@ interface PeekAuthTokenClaims {
1797
1797
  /** Authenticated user context. */
1798
1798
  user: PeekAuthTokenUser;
1799
1799
  }
1800
+ /** The Peek account an install belongs to, as reported on an install webhook. */
1801
+ interface InstallWebhookAccount {
1802
+ /** Peek account ID that owns the install. */
1803
+ id: string;
1804
+ }
1805
+ /**
1806
+ * Claims returned by `verifyInstallWebhook` — the decoded, signature-verified
1807
+ * install-status webhook token.
1808
+ *
1809
+ * Shares the `app_registry_v2` token family with {@link PeekAuthTokenClaims},
1810
+ * but is emitted by the app registry itself for install lifecycle events
1811
+ * (installed / uninstalled / status changed) rather than for a user session —
1812
+ * so {@link InstallWebhookClaims.user} is `null` for system-initiated events
1813
+ * that no user triggered.
1814
+ */
1815
+ interface InstallWebhookClaims {
1816
+ /** Install ID — the JWT subject (`sub`). Peek-assigned UUID. */
1817
+ installId: string;
1818
+ /** The account the install belongs to. */
1819
+ account: InstallWebhookAccount;
1820
+ /** Install lifecycle status (e.g. `"installed"`, `"uninstalled"`). */
1821
+ status: string;
1822
+ /** App display version at time of issuance. Empty string when absent. */
1823
+ displayVersion: string;
1824
+ /**
1825
+ * The user that triggered the event, or `null` for system-initiated events
1826
+ * (the whole point of a distinct type from {@link PeekAuthTokenClaims}).
1827
+ */
1828
+ user: PeekAuthTokenUser | null;
1829
+ }
1800
1830
 
1801
1831
  /**
1802
1832
  * Configuration for a {@link PeekAccessService} instance. Extends the shared
@@ -2054,8 +2084,6 @@ declare class RestClient$1 {
2054
2084
  * @throws {CngApiError} on any other non-2xx response
2055
2085
  */
2056
2086
  get<T>(path: string): Promise<T>;
2057
- /** Reads the response body as JSON, falling back to raw text when unparseable. */
2058
- private parseBody;
2059
2087
  private endpoint;
2060
2088
  private buildHeaders;
2061
2089
  }
@@ -2183,8 +2211,6 @@ declare class RestClient {
2183
2211
  * @throws {AcmeApiError} on any other non-2xx response
2184
2212
  */
2185
2213
  get<T>(path: string): Promise<T>;
2186
- /** Reads the response body as JSON, falling back to raw text when unparseable. */
2187
- private parseBody;
2188
2214
  private endpoint;
2189
2215
  private buildHeaders;
2190
2216
  }
@@ -2366,6 +2392,29 @@ interface Waiver {
2366
2392
  */
2367
2393
  declare function parseWaiverWebhook(payload: unknown, options?: AccessOptions): Waiver;
2368
2394
 
2395
+ /**
2396
+ * Verifies an install-status webhook token and returns its clean claims.
2397
+ *
2398
+ * Validates the HMAC signature (with `secret`), the token expiry, the
2399
+ * `"app_registry_v2"` issuer, and the `"Joken"` audience — the same checks as
2400
+ * {@link PeekAccessService.verifyPeekAuthToken} — then maps the payload to
2401
+ * {@link InstallWebhookClaims}, tolerating a `null` `user` (system events).
2402
+ * Throws from the `jsonwebtoken` library on any verification failure, so callers
2403
+ * can branch on the error kind:
2404
+ *
2405
+ * - `JsonWebTokenError` — signature invalid, wrong issuer/audience, or malformed
2406
+ * - `TokenExpiredError` — past `exp`
2407
+ * - `NotBeforeError` — before `nbf`
2408
+ *
2409
+ * @param token the raw JWT delivered by the install webhook (no `Bearer` prefix)
2410
+ * @param secret the app's HMAC signing secret (the `jwtSecret` you construct
2411
+ * `PeekAccessService` with)
2412
+ * @throws {JsonWebTokenError} signature invalid or token malformed
2413
+ * @throws {TokenExpiredError} token has expired
2414
+ * @throws {NotBeforeError} token not yet valid
2415
+ */
2416
+ declare function verifyInstallWebhook(token: string, secret: string): InstallWebhookClaims;
2417
+
2369
2418
  /**
2370
2419
  * Typed errors thrown by the package. Each mirrors a failure mode of the Peek
2371
2420
  * GraphQL gateway (or the CNG REST gateway) so callers can branch on the error
@@ -2402,6 +2451,28 @@ declare class PeekGraphQLError extends Error {
2402
2451
  readonly graphqlErrors: unknown[];
2403
2452
  constructor(graphqlErrors: unknown[], message?: string);
2404
2453
  }
2454
+ /**
2455
+ * Thrown when the Peek GraphQL gateway returns a non-2xx HTTP response that is
2456
+ * not one of the specifically-handled statuses (418/429) and does not carry a
2457
+ * GraphQL `errors` array. This is the transport-level failure — a `401`
2458
+ * (auth/secret wrong), `404` (wrong app id / not provisioned), `5xx`, etc. —
2459
+ * as opposed to {@link PeekGraphQLError}, which is a resolver-level failure
2460
+ * reported inside an otherwise-successful HTTP response.
2461
+ *
2462
+ * The offending status is preserved on {@link PeekHttpError.statusCode}, the
2463
+ * request URL on {@link PeekHttpError.url}, and the raw response body (parsed
2464
+ * JSON when possible, otherwise the raw text) on {@link PeekHttpError.body} — so
2465
+ * callers can tell "which config is wrong" without disassembling the bundle.
2466
+ */
2467
+ declare class PeekHttpError extends Error {
2468
+ /** The HTTP status that triggered this error. */
2469
+ readonly statusCode: number;
2470
+ /** The request URL that produced the failing response. */
2471
+ readonly url: string;
2472
+ /** The raw response body (parsed JSON when possible, otherwise text). */
2473
+ readonly body: unknown;
2474
+ constructor(statusCode: number, url: string, body: unknown, message?: string);
2475
+ }
2405
2476
  /**
2406
2477
  * Thrown when a payment or booking-modification operation is called on an
2407
2478
  * access service that was constructed without `fullCustomerAccess` (PII access
@@ -2442,4 +2513,4 @@ declare class AcmeApiError extends Error {
2442
2513
  constructor(statusCode: number, body: unknown, message?: string);
2443
2514
  }
2444
2515
 
2445
- export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, type AccessOptions, type AccountUser, AccountUserService, type AccountUserServiceOptions, AcmeAccessService, type AcmeAccessServiceConfig, type AcmeActivity, type AcmeActivityTicket, AcmeApiError, AcmeProductService, type Activity, type ActivityOverrides, type ActivityTicket, 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 ClearOverridesInput, CngAccessService, type CngAccessServiceConfig, CngApiError, CngProductService, type CreateBookingGuest, type CreateBookingInput, type CreateBookingTicket, type CreateEngineInput, type CreatePromoCodeInput, type CreatedBooking, type CreatedPricingEngine, type CreatedPromoCode, type CustomQuestionAnswer, type DailyNote, DailyNoteService, type Duration, type Guest, type GuestMetadata, type Guide, type GuideAssignment, type InvoiceLinkResult, type Logger, type MakePaymentInput, type MakePaymentResult, type Membership, type MembershipPurchaseInput, MembershipService, type NoteMode, type Payment, type PaymentSource, PeekAccessService, type PeekAccessServiceConfig, type PeekAuthTokenClaims, type PeekAuthTokenUser, PeekGraphQLError, type PeekPlatform, PiiAccessDisabledError, type Price, type PricingActivityContext, type PricingEngine, type PricingMoney, type PricingNamedRef, type PricingOverride, type PricingOverrideFilter, PricingService, type Product, ProductService, type ProductServiceOptions, type ProductTicket, type PromoCode, type PromoCodeFixedAmount, PromoCodeService, type PromoCodeServiceOptions, type PurchasedMembership, RENTAL_PRODUCT_TYPE, RateLimitError, type RefundInput, type RefundResult, ResellerService, type ResolvedOverride, type ResolvedPricingOverride, type ResolvedResourceOption, type Resource, type ResourceOptionOverride, type ResourceOptionQuantity, type ResourcePool, type ResourcePoolAccountUser, type ResourcePoolAssignment, type ResourcePoolMode, ResourcePoolService, type Review, ReviewService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateEngineInput, type UpdateTimeslotResult, type UpsertOverridesInput, type UpsertOverridesResult, type Waiver, noopLogger, parseBookingWebhook, parseWaiverWebhook };
2516
+ export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, type AccessOptions, type AccountUser, AccountUserService, type AccountUserServiceOptions, AcmeAccessService, type AcmeAccessServiceConfig, type AcmeActivity, type AcmeActivityTicket, AcmeApiError, AcmeProductService, type Activity, type ActivityOverrides, type ActivityTicket, 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 ClearOverridesInput, CngAccessService, type CngAccessServiceConfig, CngApiError, CngProductService, type CreateBookingGuest, type CreateBookingInput, type CreateBookingTicket, type CreateEngineInput, type CreatePromoCodeInput, type CreatedBooking, type CreatedPricingEngine, type CreatedPromoCode, type CustomQuestionAnswer, type DailyNote, DailyNoteService, type Duration, type Guest, type GuestMetadata, type Guide, type GuideAssignment, type InstallWebhookAccount, type InstallWebhookClaims, type InvoiceLinkResult, type Logger, type MakePaymentInput, type MakePaymentResult, type Membership, type MembershipPurchaseInput, MembershipService, type NoteMode, type Payment, type PaymentSource, PeekAccessService, type PeekAccessServiceConfig, type PeekAuthTokenClaims, type PeekAuthTokenUser, PeekGraphQLError, PeekHttpError, type PeekPlatform, PiiAccessDisabledError, type Price, type PricingActivityContext, type PricingEngine, type PricingMoney, type PricingNamedRef, type PricingOverride, type PricingOverrideFilter, PricingService, type Product, ProductService, type ProductServiceOptions, type ProductTicket, type PromoCode, type PromoCodeFixedAmount, PromoCodeService, type PromoCodeServiceOptions, type PurchasedMembership, RENTAL_PRODUCT_TYPE, RateLimitError, type RefundInput, type RefundResult, ResellerService, type ResolvedOverride, type ResolvedPricingOverride, type ResolvedResourceOption, type Resource, type ResourceOptionOverride, type ResourceOptionQuantity, type ResourcePool, type ResourcePoolAccountUser, type ResourcePoolAssignment, type ResourcePoolMode, ResourcePoolService, type Review, ReviewService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateEngineInput, type UpdateTimeslotResult, type UpsertOverridesInput, type UpsertOverridesResult, type Waiver, noopLogger, parseBookingWebhook, parseWaiverWebhook, verifyInstallWebhook };
package/dist/index.d.ts CHANGED
@@ -1797,6 +1797,36 @@ interface PeekAuthTokenClaims {
1797
1797
  /** Authenticated user context. */
1798
1798
  user: PeekAuthTokenUser;
1799
1799
  }
1800
+ /** The Peek account an install belongs to, as reported on an install webhook. */
1801
+ interface InstallWebhookAccount {
1802
+ /** Peek account ID that owns the install. */
1803
+ id: string;
1804
+ }
1805
+ /**
1806
+ * Claims returned by `verifyInstallWebhook` — the decoded, signature-verified
1807
+ * install-status webhook token.
1808
+ *
1809
+ * Shares the `app_registry_v2` token family with {@link PeekAuthTokenClaims},
1810
+ * but is emitted by the app registry itself for install lifecycle events
1811
+ * (installed / uninstalled / status changed) rather than for a user session —
1812
+ * so {@link InstallWebhookClaims.user} is `null` for system-initiated events
1813
+ * that no user triggered.
1814
+ */
1815
+ interface InstallWebhookClaims {
1816
+ /** Install ID — the JWT subject (`sub`). Peek-assigned UUID. */
1817
+ installId: string;
1818
+ /** The account the install belongs to. */
1819
+ account: InstallWebhookAccount;
1820
+ /** Install lifecycle status (e.g. `"installed"`, `"uninstalled"`). */
1821
+ status: string;
1822
+ /** App display version at time of issuance. Empty string when absent. */
1823
+ displayVersion: string;
1824
+ /**
1825
+ * The user that triggered the event, or `null` for system-initiated events
1826
+ * (the whole point of a distinct type from {@link PeekAuthTokenClaims}).
1827
+ */
1828
+ user: PeekAuthTokenUser | null;
1829
+ }
1800
1830
 
1801
1831
  /**
1802
1832
  * Configuration for a {@link PeekAccessService} instance. Extends the shared
@@ -2054,8 +2084,6 @@ declare class RestClient$1 {
2054
2084
  * @throws {CngApiError} on any other non-2xx response
2055
2085
  */
2056
2086
  get<T>(path: string): Promise<T>;
2057
- /** Reads the response body as JSON, falling back to raw text when unparseable. */
2058
- private parseBody;
2059
2087
  private endpoint;
2060
2088
  private buildHeaders;
2061
2089
  }
@@ -2183,8 +2211,6 @@ declare class RestClient {
2183
2211
  * @throws {AcmeApiError} on any other non-2xx response
2184
2212
  */
2185
2213
  get<T>(path: string): Promise<T>;
2186
- /** Reads the response body as JSON, falling back to raw text when unparseable. */
2187
- private parseBody;
2188
2214
  private endpoint;
2189
2215
  private buildHeaders;
2190
2216
  }
@@ -2366,6 +2392,29 @@ interface Waiver {
2366
2392
  */
2367
2393
  declare function parseWaiverWebhook(payload: unknown, options?: AccessOptions): Waiver;
2368
2394
 
2395
+ /**
2396
+ * Verifies an install-status webhook token and returns its clean claims.
2397
+ *
2398
+ * Validates the HMAC signature (with `secret`), the token expiry, the
2399
+ * `"app_registry_v2"` issuer, and the `"Joken"` audience — the same checks as
2400
+ * {@link PeekAccessService.verifyPeekAuthToken} — then maps the payload to
2401
+ * {@link InstallWebhookClaims}, tolerating a `null` `user` (system events).
2402
+ * Throws from the `jsonwebtoken` library on any verification failure, so callers
2403
+ * can branch on the error kind:
2404
+ *
2405
+ * - `JsonWebTokenError` — signature invalid, wrong issuer/audience, or malformed
2406
+ * - `TokenExpiredError` — past `exp`
2407
+ * - `NotBeforeError` — before `nbf`
2408
+ *
2409
+ * @param token the raw JWT delivered by the install webhook (no `Bearer` prefix)
2410
+ * @param secret the app's HMAC signing secret (the `jwtSecret` you construct
2411
+ * `PeekAccessService` with)
2412
+ * @throws {JsonWebTokenError} signature invalid or token malformed
2413
+ * @throws {TokenExpiredError} token has expired
2414
+ * @throws {NotBeforeError} token not yet valid
2415
+ */
2416
+ declare function verifyInstallWebhook(token: string, secret: string): InstallWebhookClaims;
2417
+
2369
2418
  /**
2370
2419
  * Typed errors thrown by the package. Each mirrors a failure mode of the Peek
2371
2420
  * GraphQL gateway (or the CNG REST gateway) so callers can branch on the error
@@ -2402,6 +2451,28 @@ declare class PeekGraphQLError extends Error {
2402
2451
  readonly graphqlErrors: unknown[];
2403
2452
  constructor(graphqlErrors: unknown[], message?: string);
2404
2453
  }
2454
+ /**
2455
+ * Thrown when the Peek GraphQL gateway returns a non-2xx HTTP response that is
2456
+ * not one of the specifically-handled statuses (418/429) and does not carry a
2457
+ * GraphQL `errors` array. This is the transport-level failure — a `401`
2458
+ * (auth/secret wrong), `404` (wrong app id / not provisioned), `5xx`, etc. —
2459
+ * as opposed to {@link PeekGraphQLError}, which is a resolver-level failure
2460
+ * reported inside an otherwise-successful HTTP response.
2461
+ *
2462
+ * The offending status is preserved on {@link PeekHttpError.statusCode}, the
2463
+ * request URL on {@link PeekHttpError.url}, and the raw response body (parsed
2464
+ * JSON when possible, otherwise the raw text) on {@link PeekHttpError.body} — so
2465
+ * callers can tell "which config is wrong" without disassembling the bundle.
2466
+ */
2467
+ declare class PeekHttpError extends Error {
2468
+ /** The HTTP status that triggered this error. */
2469
+ readonly statusCode: number;
2470
+ /** The request URL that produced the failing response. */
2471
+ readonly url: string;
2472
+ /** The raw response body (parsed JSON when possible, otherwise text). */
2473
+ readonly body: unknown;
2474
+ constructor(statusCode: number, url: string, body: unknown, message?: string);
2475
+ }
2405
2476
  /**
2406
2477
  * Thrown when a payment or booking-modification operation is called on an
2407
2478
  * access service that was constructed without `fullCustomerAccess` (PII access
@@ -2442,4 +2513,4 @@ declare class AcmeApiError extends Error {
2442
2513
  constructor(statusCode: number, body: unknown, message?: string);
2443
2514
  }
2444
2515
 
2445
- export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, type AccessOptions, type AccountUser, AccountUserService, type AccountUserServiceOptions, AcmeAccessService, type AcmeAccessServiceConfig, type AcmeActivity, type AcmeActivityTicket, AcmeApiError, AcmeProductService, type Activity, type ActivityOverrides, type ActivityTicket, 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 ClearOverridesInput, CngAccessService, type CngAccessServiceConfig, CngApiError, CngProductService, type CreateBookingGuest, type CreateBookingInput, type CreateBookingTicket, type CreateEngineInput, type CreatePromoCodeInput, type CreatedBooking, type CreatedPricingEngine, type CreatedPromoCode, type CustomQuestionAnswer, type DailyNote, DailyNoteService, type Duration, type Guest, type GuestMetadata, type Guide, type GuideAssignment, type InvoiceLinkResult, type Logger, type MakePaymentInput, type MakePaymentResult, type Membership, type MembershipPurchaseInput, MembershipService, type NoteMode, type Payment, type PaymentSource, PeekAccessService, type PeekAccessServiceConfig, type PeekAuthTokenClaims, type PeekAuthTokenUser, PeekGraphQLError, type PeekPlatform, PiiAccessDisabledError, type Price, type PricingActivityContext, type PricingEngine, type PricingMoney, type PricingNamedRef, type PricingOverride, type PricingOverrideFilter, PricingService, type Product, ProductService, type ProductServiceOptions, type ProductTicket, type PromoCode, type PromoCodeFixedAmount, PromoCodeService, type PromoCodeServiceOptions, type PurchasedMembership, RENTAL_PRODUCT_TYPE, RateLimitError, type RefundInput, type RefundResult, ResellerService, type ResolvedOverride, type ResolvedPricingOverride, type ResolvedResourceOption, type Resource, type ResourceOptionOverride, type ResourceOptionQuantity, type ResourcePool, type ResourcePoolAccountUser, type ResourcePoolAssignment, type ResourcePoolMode, ResourcePoolService, type Review, ReviewService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateEngineInput, type UpdateTimeslotResult, type UpsertOverridesInput, type UpsertOverridesResult, type Waiver, noopLogger, parseBookingWebhook, parseWaiverWebhook };
2516
+ export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, type AccessOptions, type AccountUser, AccountUserService, type AccountUserServiceOptions, AcmeAccessService, type AcmeAccessServiceConfig, type AcmeActivity, type AcmeActivityTicket, AcmeApiError, AcmeProductService, type Activity, type ActivityOverrides, type ActivityTicket, 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 ClearOverridesInput, CngAccessService, type CngAccessServiceConfig, CngApiError, CngProductService, type CreateBookingGuest, type CreateBookingInput, type CreateBookingTicket, type CreateEngineInput, type CreatePromoCodeInput, type CreatedBooking, type CreatedPricingEngine, type CreatedPromoCode, type CustomQuestionAnswer, type DailyNote, DailyNoteService, type Duration, type Guest, type GuestMetadata, type Guide, type GuideAssignment, type InstallWebhookAccount, type InstallWebhookClaims, type InvoiceLinkResult, type Logger, type MakePaymentInput, type MakePaymentResult, type Membership, type MembershipPurchaseInput, MembershipService, type NoteMode, type Payment, type PaymentSource, PeekAccessService, type PeekAccessServiceConfig, type PeekAuthTokenClaims, type PeekAuthTokenUser, PeekGraphQLError, PeekHttpError, type PeekPlatform, PiiAccessDisabledError, type Price, type PricingActivityContext, type PricingEngine, type PricingMoney, type PricingNamedRef, type PricingOverride, type PricingOverrideFilter, PricingService, type Product, ProductService, type ProductServiceOptions, type ProductTicket, type PromoCode, type PromoCodeFixedAmount, PromoCodeService, type PromoCodeServiceOptions, type PurchasedMembership, RENTAL_PRODUCT_TYPE, RateLimitError, type RefundInput, type RefundResult, ResellerService, type ResolvedOverride, type ResolvedPricingOverride, type ResolvedResourceOption, type Resource, type ResourceOptionOverride, type ResourceOptionQuantity, type ResourcePool, type ResourcePoolAccountUser, type ResourcePoolAssignment, type ResourcePoolMode, ResourcePoolService, type Review, ReviewService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateEngineInput, type UpdateTimeslotResult, type UpsertOverridesInput, type UpsertOverridesResult, type Waiver, noopLogger, parseBookingWebhook, parseWaiverWebhook, verifyInstallWebhook };
package/dist/index.js CHANGED
@@ -1,7 +1,5 @@
1
- import * as jwt from 'jsonwebtoken';
2
1
  import { randomUUID } from 'crypto';
3
-
4
- // src/peek-access-service.ts
2
+ import * as jwt from 'jsonwebtoken';
5
3
 
6
4
  // src/internal/peek/gateway-endpoints.ts
7
5
  var SALES_ENDPOINT = "sales";
@@ -212,6 +210,21 @@ var PeekGraphQLError = class extends Error {
212
210
  this.graphqlErrors = graphqlErrors;
213
211
  }
214
212
  };
213
+ var PeekHttpError = class extends Error {
214
+ /** The HTTP status that triggered this error. */
215
+ statusCode;
216
+ /** The request URL that produced the failing response. */
217
+ url;
218
+ /** The raw response body (parsed JSON when possible, otherwise text). */
219
+ body;
220
+ constructor(statusCode, url, body, message) {
221
+ super(message ?? `Peek request failed with HTTP ${statusCode}`);
222
+ this.name = "PeekHttpError";
223
+ this.statusCode = statusCode;
224
+ this.url = url;
225
+ this.body = body;
226
+ }
227
+ };
215
228
  var PiiAccessDisabledError = class extends Error {
216
229
  /** The name of the operation that was blocked (e.g. `"makePayment"`). */
217
230
  operation;
@@ -1922,6 +1935,14 @@ function createTokenManager(config) {
1922
1935
  var RATE_LIMIT_STATUS = 429;
1923
1936
  var ADMIN_ACCOUNT_REQUIRED_STATUS = 418;
1924
1937
  var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
1938
+ async function parseBody(response) {
1939
+ const text = await response.text();
1940
+ try {
1941
+ return JSON.parse(text);
1942
+ } catch {
1943
+ return text;
1944
+ }
1945
+ }
1925
1946
  async function requestWithRetry(http, url, init, label, onResponse) {
1926
1947
  const { retryDelaysMs, logger, fetchFn } = http;
1927
1948
  for (let attempt = 0; attempt <= retryDelaysMs.length; attempt++) {
@@ -1948,6 +1969,7 @@ async function requestWithRetry(http, url, init, label, onResponse) {
1948
1969
  }
1949
1970
 
1950
1971
  // src/internal/peek/graphql-client.ts
1972
+ var isObject = (value) => typeof value === "object" && value !== null;
1951
1973
  var GraphQLClient = class {
1952
1974
  constructor(options) {
1953
1975
  this.options = options;
@@ -1973,7 +1995,8 @@ var GraphQLClient = class {
1973
1995
  },
1974
1996
  endpointName,
1975
1997
  async (response) => {
1976
- const body = await response.json();
1998
+ const raw = await parseBody(response);
1999
+ const body = isObject(raw) ? raw : {};
1977
2000
  if (body.errors) {
1978
2001
  logger.error(`GraphQL errors for ${endpointName}`, {
1979
2002
  url,
@@ -1983,7 +2006,7 @@ var GraphQLClient = class {
1983
2006
  }
1984
2007
  if (!response.ok) {
1985
2008
  logger.error(`GraphQL request failed with HTTP ${response.status}`, { url });
1986
- throw new Error(`GraphQL request failed with HTTP ${response.status}`);
2009
+ throw new PeekHttpError(response.status, url, raw);
1987
2010
  }
1988
2011
  return body;
1989
2012
  }
@@ -2005,6 +2028,24 @@ var GraphQLClient = class {
2005
2028
  return headers;
2006
2029
  }
2007
2030
  };
2031
+ var PEEK_TOKEN_ISSUER = "app_registry_v2";
2032
+ var PEEK_TOKEN_AUDIENCE = "Joken";
2033
+ function verifyPeekJwt(token, secret) {
2034
+ return jwt.verify(token, secret, {
2035
+ issuer: PEEK_TOKEN_ISSUER,
2036
+ audience: PEEK_TOKEN_AUDIENCE
2037
+ });
2038
+ }
2039
+ function mapPeekTokenUser(u) {
2040
+ return {
2041
+ email: u.email,
2042
+ id: u.id,
2043
+ isAdmin: u.is_admin,
2044
+ locale: u.locale,
2045
+ name: u.name,
2046
+ platform: u.platform
2047
+ };
2048
+ }
2008
2049
 
2009
2050
  // src/internal/peek/memberships/membership-converter.ts
2010
2051
  function fromMembershipsResponse(response) {
@@ -2473,10 +2514,17 @@ function fromTimeslotNode(node, productId) {
2473
2514
  durationMin: node.minuteLength ?? 0,
2474
2515
  date: node.date || "",
2475
2516
  startTime: node.start ?? null,
2476
- assignedResources: mapAssignedResources(node.inheritedResourceAllocations)
2517
+ assignedResources: mapAssignedResources(selectResourceAllocations(node))
2477
2518
  };
2478
2519
  }
2479
2520
  var ACTIVE_ALLOCATION_STATUS = "ACTIVE";
2521
+ function selectResourceAllocations(node) {
2522
+ const inherited = node.inheritedResourceAllocations;
2523
+ if (Array.isArray(inherited) && inherited.length > 0) {
2524
+ return inherited;
2525
+ }
2526
+ return node.resourceAllocations;
2527
+ }
2480
2528
  function mapAssignedResources(allocations) {
2481
2529
  if (!Array.isArray(allocations) || allocations.length === 0) {
2482
2530
  return [];
@@ -2563,9 +2611,24 @@ var TIMESLOTS_QUERY = `
2563
2611
  status
2564
2612
  date
2565
2613
  inheritedResourceAllocations {
2614
+ id
2615
+ status
2616
+ quantity
2617
+ resourcePool {
2618
+ id
2619
+ name
2620
+ category
2621
+ capacity
2622
+ accountUser {
2623
+ id
2624
+ }
2625
+ }
2626
+ }
2627
+ resourceAllocations {
2566
2628
  quantity
2567
2629
  status
2568
2630
  resourcePool {
2631
+ id
2569
2632
  name
2570
2633
  category
2571
2634
  capacity
@@ -2601,9 +2664,24 @@ var TIMESLOT_BY_ID_QUERY = `
2601
2664
  status
2602
2665
  date
2603
2666
  inheritedResourceAllocations {
2667
+ id
2668
+ status
2669
+ quantity
2670
+ resourcePool {
2671
+ id
2672
+ name
2673
+ category
2674
+ capacity
2675
+ accountUser {
2676
+ id
2677
+ }
2678
+ }
2679
+ }
2680
+ resourceAllocations {
2604
2681
  quantity
2605
2682
  status
2606
2683
  resourcePool {
2684
+ id
2607
2685
  name
2608
2686
  category
2609
2687
  capacity
@@ -3408,7 +3486,6 @@ var noopLogger = {
3408
3486
  // src/peek-access-service.ts
3409
3487
  var DEFAULT_BASE_URL = "https://apps.peekapis.com/backoffice-gql";
3410
3488
  var DEFAULT_V2_BASE_URL = "https://app-registry.peeklabs.com/installations-api";
3411
- var PEEK_TOKEN_ISSUER = "app_registry_v2";
3412
3489
  var PeekAccessService = class {
3413
3490
  client;
3414
3491
  productServiceOptions;
@@ -3471,21 +3548,11 @@ var PeekAccessService = class {
3471
3548
  * @throws {NotBeforeError} token not yet valid
3472
3549
  */
3473
3550
  verifyPeekAuthToken(token) {
3474
- const payload = jwt.verify(token, this.jwtSecret, {
3475
- issuer: PEEK_TOKEN_ISSUER
3476
- });
3477
- const { user: u } = payload;
3551
+ const payload = verifyPeekJwt(token, this.jwtSecret);
3478
3552
  return {
3479
3553
  installId: payload.sub,
3480
3554
  displayVersion: payload.display_version,
3481
- user: {
3482
- email: u.email,
3483
- id: u.id,
3484
- isAdmin: u.is_admin,
3485
- locale: u.locale,
3486
- name: u.name,
3487
- platform: u.platform
3488
- }
3555
+ user: mapPeekTokenUser(payload.user)
3489
3556
  };
3490
3557
  }
3491
3558
  /**
@@ -3869,7 +3936,7 @@ var RestClient = class {
3869
3936
  { method: "GET", headers: this.buildHeaders() },
3870
3937
  path,
3871
3938
  async (response) => {
3872
- const body = await this.parseBody(response);
3939
+ const body = await parseBody(response);
3873
3940
  if (!response.ok) {
3874
3941
  logger.error(`CNG request failed with HTTP ${response.status}`, { url });
3875
3942
  throw new CngApiError(response.status, body);
@@ -3878,15 +3945,6 @@ var RestClient = class {
3878
3945
  }
3879
3946
  );
3880
3947
  }
3881
- /** Reads the response body as JSON, falling back to raw text when unparseable. */
3882
- async parseBody(response) {
3883
- const text = await response.text();
3884
- try {
3885
- return JSON.parse(text);
3886
- } catch {
3887
- return text;
3888
- }
3889
- }
3890
3948
  endpoint(path) {
3891
3949
  const { baseUrl, appId, extendableSlug } = this.options;
3892
3950
  return `${baseUrl}/${appId}/${extendableSlug}/${path}`;
@@ -4009,7 +4067,7 @@ var RestClient2 = class {
4009
4067
  { method: "GET", headers: this.buildHeaders() },
4010
4068
  path,
4011
4069
  async (response) => {
4012
- const body = await this.parseBody(response);
4070
+ const body = await parseBody(response);
4013
4071
  if (!response.ok) {
4014
4072
  logger.error(`ACME request failed with HTTP ${response.status}`, { url });
4015
4073
  throw new AcmeApiError(response.status, body);
@@ -4018,15 +4076,6 @@ var RestClient2 = class {
4018
4076
  }
4019
4077
  );
4020
4078
  }
4021
- /** Reads the response body as JSON, falling back to raw text when unparseable. */
4022
- async parseBody(response) {
4023
- const text = await response.text();
4024
- try {
4025
- return JSON.parse(text);
4026
- } catch {
4027
- return text;
4028
- }
4029
- }
4030
4079
  endpoint(path) {
4031
4080
  const { baseUrl, appId, extendableSlug } = this.options;
4032
4081
  return `${baseUrl}/${appId}/${extendableSlug}/${path}`;
@@ -4167,6 +4216,18 @@ function extractWaiverNode(payload) {
4167
4216
  return record;
4168
4217
  }
4169
4218
 
4170
- export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, AccountUserService, AcmeAccessService, AcmeApiError, AcmeProductService, AdminAccountRequiredError, AvailabilityService, BookingService, CngAccessService, CngApiError, CngProductService, DailyNoteService, MembershipService, PeekAccessService, PeekGraphQLError, PiiAccessDisabledError, PricingService, ProductService, PromoCodeService, RENTAL_PRODUCT_TYPE, RateLimitError, ResellerService, ResourcePoolService, ReviewService, TimeslotService, noopLogger, parseBookingWebhook, parseWaiverWebhook };
4219
+ // src/internal/peek/installs/install-webhook.ts
4220
+ function verifyInstallWebhook(token, secret) {
4221
+ const payload = verifyPeekJwt(token, secret);
4222
+ return {
4223
+ installId: payload.sub ?? "",
4224
+ account: { id: payload.account?.id ?? "" },
4225
+ status: payload.status ?? "",
4226
+ displayVersion: payload.display_version ?? "",
4227
+ user: payload.user ? mapPeekTokenUser(payload.user) : null
4228
+ };
4229
+ }
4230
+
4231
+ export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, AccountUserService, AcmeAccessService, AcmeApiError, AcmeProductService, AdminAccountRequiredError, AvailabilityService, BookingService, CngAccessService, CngApiError, CngProductService, DailyNoteService, MembershipService, PeekAccessService, PeekGraphQLError, PeekHttpError, PiiAccessDisabledError, PricingService, ProductService, PromoCodeService, RENTAL_PRODUCT_TYPE, RateLimitError, ResellerService, ResourcePoolService, ReviewService, TimeslotService, noopLogger, parseBookingWebhook, parseWaiverWebhook, verifyInstallWebhook };
4171
4232
  //# sourceMappingURL=index.js.map
4172
4233
  //# sourceMappingURL=index.js.map