@peektravel/app-utilities 0.1.6 → 0.2.3

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
@@ -23,8 +23,8 @@ interface GraphQLClientOptions {
23
23
  baseUrl: string;
24
24
  /** Peek app ID, used in the endpoint path. */
25
25
  appId: string;
26
- /** API gateway key sent as the `pk-api-key` header. */
27
- gatewayKey: string;
26
+ /** API gateway key sent as the `pk-api-key` header. Omitted from headers when absent (v2 mode). */
27
+ gatewayKey?: string;
28
28
  /** Supplies a valid bearer token for each request. */
29
29
  getToken: () => string;
30
30
  /** Backoff delays (ms) applied on successive HTTP 429 responses. */
@@ -33,6 +33,11 @@ interface GraphQLClientOptions {
33
33
  logger: Logger;
34
34
  /** `fetch` implementation to use. */
35
35
  fetchFn: typeof fetch;
36
+ /**
37
+ * Optional fixed path segment inserted between `appId` and the endpoint name.
38
+ * Used in v2 mode: `baseUrl/appId/endpointPathPrefix/endpointName`.
39
+ */
40
+ endpointPathPrefix?: string;
36
41
  }
37
42
  declare class GraphQLClient {
38
43
  private readonly options;
@@ -1179,15 +1184,28 @@ declare class PromoCodeService {
1179
1184
  create(input: CreatePromoCodeInput): Promise<CreatedPromoCode>;
1180
1185
  }
1181
1186
 
1182
- /**
1183
- * Authenticated root entry point to the Peek backoffice GraphQL gateway.
1184
- *
1185
- * Configure one instance per install with everything needed to authenticate and
1186
- * reach the gateway. The access service owns the shared, authenticated
1187
- * transport (it mints and caches tokens on demand) and hands out per-resource
1188
- * service objects e.g. {@link PeekAccessService.getProductService} — that
1189
- * carry the resource-specific business logic.
1190
- */
1187
+ /** User context embedded in a Peek auth token. */
1188
+ interface PeekAuthTokenUser {
1189
+ /** User's email address. */
1190
+ email: string;
1191
+ /** User's Peek account ID */
1192
+ id: string;
1193
+ /** Whether the user has admin privileges. */
1194
+ isAdmin: boolean;
1195
+ /** User's locale (e.g. `"en"`). */
1196
+ locale: string;
1197
+ /** User's display name. */
1198
+ name: string;
1199
+ }
1200
+ /** Claims returned by {@link PeekAccessService.verifyPeekAuthToken}. */
1201
+ interface PeekAuthTokenClaims {
1202
+ /** Install ID — the JWT subject (`sub`). Peek-assigned UUID. */
1203
+ installId: string;
1204
+ /** App display version at time of issuance. */
1205
+ displayVersion: string;
1206
+ /** Authenticated user context. */
1207
+ user: PeekAuthTokenUser;
1208
+ }
1191
1209
 
1192
1210
  /** Configuration for a {@link PeekAccessService} instance. */
1193
1211
  interface PeekAccessServiceConfig {
@@ -1199,9 +1217,16 @@ interface PeekAccessServiceConfig {
1199
1217
  issuer: string;
1200
1218
  /** Peek app ID, used in the gateway endpoint path. */
1201
1219
  appId: string;
1202
- /** API gateway key, sent as the `pk-api-key` header. */
1203
- gatewayKey: string;
1204
- /** Override the gateway base URL. Default: Peek production gateway. */
1220
+ /** API gateway key, sent as the `pk-api-key` header. Required in v1 mode; not used in v2. */
1221
+ gatewayKey?: string;
1222
+ /**
1223
+ * Gateway mode. `"v2"` routes through the app-registry installations API
1224
+ * (`baseUrl/appId/peek_backoffice_api-v1/endpointName`) and defaults to the
1225
+ * app-registry sandbox base URL. `"v1"` (default) uses the standard backoffice
1226
+ * GraphQL gateway.
1227
+ */
1228
+ mode?: "v2";
1229
+ /** Override the gateway base URL. Default: Peek production gateway (v1) or app-registry sandbox (v2). */
1205
1230
  baseUrl?: string;
1206
1231
  /** JWT lifetime in seconds. Default: 3600. */
1207
1232
  tokenTtlSeconds?: number;
@@ -1246,6 +1271,7 @@ interface PeekAccessServiceConfig {
1246
1271
  declare class PeekAccessService {
1247
1272
  private readonly client;
1248
1273
  private readonly productServiceOptions;
1274
+ private readonly jwtSecret;
1249
1275
  private productService?;
1250
1276
  private accountUserService?;
1251
1277
  private resourcePoolService?;
@@ -1258,6 +1284,25 @@ declare class PeekAccessService {
1258
1284
  private bookingService?;
1259
1285
  private reviewService?;
1260
1286
  constructor(config: PeekAccessServiceConfig);
1287
+ /**
1288
+ * Verifies a Peek auth token issued by the app registry and returns the
1289
+ * decoded claims.
1290
+ *
1291
+ * Validates the HMAC signature (using this service's `jwtSecret`), the token
1292
+ * expiry, the `"app_registry_v2"` issuer, and the `"Joken"` audience. Throws
1293
+ * from the `jsonwebtoken` library on any failure — callers should catch to
1294
+ * distinguish error kinds:
1295
+ *
1296
+ * - `JsonWebTokenError` — signature invalid, wrong issuer/audience, or token
1297
+ * malformed
1298
+ * - `TokenExpiredError` — past `exp`
1299
+ * - `NotBeforeError` — before `nbf`
1300
+ *
1301
+ * @throws {JsonWebTokenError} signature invalid or token malformed
1302
+ * @throws {TokenExpiredError} token has expired
1303
+ * @throws {NotBeforeError} token not yet valid
1304
+ */
1305
+ verifyPeekAuthToken(token: string): PeekAuthTokenClaims;
1261
1306
  /**
1262
1307
  * Returns the {@link ProductService} for this install, bound to the shared
1263
1308
  * authenticated transport. The instance is created lazily and reused.
@@ -1429,4 +1474,4 @@ declare class PeekGraphQLError extends Error {
1429
1474
  constructor(graphqlErrors: unknown[], message?: string);
1430
1475
  }
1431
1476
 
1432
- 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 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, 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 Review, ReviewService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateTimeslotResult, type Waiver, noopLogger, parseBookingWebhook, parseWaiverWebhook };
1477
+ 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 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 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 Review, ReviewService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateTimeslotResult, type Waiver, noopLogger, parseBookingWebhook, parseWaiverWebhook };
package/dist/index.d.ts CHANGED
@@ -23,8 +23,8 @@ interface GraphQLClientOptions {
23
23
  baseUrl: string;
24
24
  /** Peek app ID, used in the endpoint path. */
25
25
  appId: string;
26
- /** API gateway key sent as the `pk-api-key` header. */
27
- gatewayKey: string;
26
+ /** API gateway key sent as the `pk-api-key` header. Omitted from headers when absent (v2 mode). */
27
+ gatewayKey?: string;
28
28
  /** Supplies a valid bearer token for each request. */
29
29
  getToken: () => string;
30
30
  /** Backoff delays (ms) applied on successive HTTP 429 responses. */
@@ -33,6 +33,11 @@ interface GraphQLClientOptions {
33
33
  logger: Logger;
34
34
  /** `fetch` implementation to use. */
35
35
  fetchFn: typeof fetch;
36
+ /**
37
+ * Optional fixed path segment inserted between `appId` and the endpoint name.
38
+ * Used in v2 mode: `baseUrl/appId/endpointPathPrefix/endpointName`.
39
+ */
40
+ endpointPathPrefix?: string;
36
41
  }
37
42
  declare class GraphQLClient {
38
43
  private readonly options;
@@ -1179,15 +1184,28 @@ declare class PromoCodeService {
1179
1184
  create(input: CreatePromoCodeInput): Promise<CreatedPromoCode>;
1180
1185
  }
1181
1186
 
1182
- /**
1183
- * Authenticated root entry point to the Peek backoffice GraphQL gateway.
1184
- *
1185
- * Configure one instance per install with everything needed to authenticate and
1186
- * reach the gateway. The access service owns the shared, authenticated
1187
- * transport (it mints and caches tokens on demand) and hands out per-resource
1188
- * service objects e.g. {@link PeekAccessService.getProductService} — that
1189
- * carry the resource-specific business logic.
1190
- */
1187
+ /** User context embedded in a Peek auth token. */
1188
+ interface PeekAuthTokenUser {
1189
+ /** User's email address. */
1190
+ email: string;
1191
+ /** User's Peek account ID */
1192
+ id: string;
1193
+ /** Whether the user has admin privileges. */
1194
+ isAdmin: boolean;
1195
+ /** User's locale (e.g. `"en"`). */
1196
+ locale: string;
1197
+ /** User's display name. */
1198
+ name: string;
1199
+ }
1200
+ /** Claims returned by {@link PeekAccessService.verifyPeekAuthToken}. */
1201
+ interface PeekAuthTokenClaims {
1202
+ /** Install ID — the JWT subject (`sub`). Peek-assigned UUID. */
1203
+ installId: string;
1204
+ /** App display version at time of issuance. */
1205
+ displayVersion: string;
1206
+ /** Authenticated user context. */
1207
+ user: PeekAuthTokenUser;
1208
+ }
1191
1209
 
1192
1210
  /** Configuration for a {@link PeekAccessService} instance. */
1193
1211
  interface PeekAccessServiceConfig {
@@ -1199,9 +1217,16 @@ interface PeekAccessServiceConfig {
1199
1217
  issuer: string;
1200
1218
  /** Peek app ID, used in the gateway endpoint path. */
1201
1219
  appId: string;
1202
- /** API gateway key, sent as the `pk-api-key` header. */
1203
- gatewayKey: string;
1204
- /** Override the gateway base URL. Default: Peek production gateway. */
1220
+ /** API gateway key, sent as the `pk-api-key` header. Required in v1 mode; not used in v2. */
1221
+ gatewayKey?: string;
1222
+ /**
1223
+ * Gateway mode. `"v2"` routes through the app-registry installations API
1224
+ * (`baseUrl/appId/peek_backoffice_api-v1/endpointName`) and defaults to the
1225
+ * app-registry sandbox base URL. `"v1"` (default) uses the standard backoffice
1226
+ * GraphQL gateway.
1227
+ */
1228
+ mode?: "v2";
1229
+ /** Override the gateway base URL. Default: Peek production gateway (v1) or app-registry sandbox (v2). */
1205
1230
  baseUrl?: string;
1206
1231
  /** JWT lifetime in seconds. Default: 3600. */
1207
1232
  tokenTtlSeconds?: number;
@@ -1246,6 +1271,7 @@ interface PeekAccessServiceConfig {
1246
1271
  declare class PeekAccessService {
1247
1272
  private readonly client;
1248
1273
  private readonly productServiceOptions;
1274
+ private readonly jwtSecret;
1249
1275
  private productService?;
1250
1276
  private accountUserService?;
1251
1277
  private resourcePoolService?;
@@ -1258,6 +1284,25 @@ declare class PeekAccessService {
1258
1284
  private bookingService?;
1259
1285
  private reviewService?;
1260
1286
  constructor(config: PeekAccessServiceConfig);
1287
+ /**
1288
+ * Verifies a Peek auth token issued by the app registry and returns the
1289
+ * decoded claims.
1290
+ *
1291
+ * Validates the HMAC signature (using this service's `jwtSecret`), the token
1292
+ * expiry, the `"app_registry_v2"` issuer, and the `"Joken"` audience. Throws
1293
+ * from the `jsonwebtoken` library on any failure — callers should catch to
1294
+ * distinguish error kinds:
1295
+ *
1296
+ * - `JsonWebTokenError` — signature invalid, wrong issuer/audience, or token
1297
+ * malformed
1298
+ * - `TokenExpiredError` — past `exp`
1299
+ * - `NotBeforeError` — before `nbf`
1300
+ *
1301
+ * @throws {JsonWebTokenError} signature invalid or token malformed
1302
+ * @throws {TokenExpiredError} token has expired
1303
+ * @throws {NotBeforeError} token not yet valid
1304
+ */
1305
+ verifyPeekAuthToken(token: string): PeekAuthTokenClaims;
1261
1306
  /**
1262
1307
  * Returns the {@link ProductService} for this install, bound to the shared
1263
1308
  * authenticated transport. The instance is created lazily and reused.
@@ -1429,4 +1474,4 @@ declare class PeekGraphQLError extends Error {
1429
1474
  constructor(graphqlErrors: unknown[], message?: string);
1430
1475
  }
1431
1476
 
1432
- 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 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, 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 Review, ReviewService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateTimeslotResult, type Waiver, noopLogger, parseBookingWebhook, parseWaiverWebhook };
1477
+ 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 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 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 Review, ReviewService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateTimeslotResult, type Waiver, noopLogger, parseBookingWebhook, parseWaiverWebhook };
package/dist/index.js CHANGED
@@ -1,8 +1,11 @@
1
- import { randomUUID } from 'crypto';
2
1
  import * as jwt from 'jsonwebtoken';
2
+ import { randomUUID } from 'crypto';
3
+
4
+ // src/peek-access-service.ts
3
5
 
4
6
  // src/internal/gateway-endpoints.ts
5
7
  var SALES_ENDPOINT = "sales";
8
+ var V2_EXTENDABLE_SLUG = "peek_backoffice_api-v1";
6
9
 
7
10
  // src/internal/account-users/account-user-converter.ts
8
11
  var ACTIVE_STATUS = "ACTIVE";
@@ -1819,14 +1822,19 @@ var GraphQLClient = class {
1819
1822
  throw new RateLimitError();
1820
1823
  }
1821
1824
  endpoint(endpointName) {
1822
- return `${this.options.baseUrl}/${this.options.appId}/${endpointName}`;
1825
+ const { baseUrl, appId, endpointPathPrefix } = this.options;
1826
+ const prefix = endpointPathPrefix ? `${endpointPathPrefix}/` : "";
1827
+ return `${baseUrl}/${appId}/${prefix}${endpointName}`;
1823
1828
  }
1824
1829
  buildHeaders() {
1825
- return {
1830
+ const headers = {
1826
1831
  "X-Peek-Auth": `Bearer ${this.options.getToken()}`,
1827
- "pk-api-key": this.options.gatewayKey,
1828
1832
  "Content-Type": "application/json"
1829
1833
  };
1834
+ if (this.options.gatewayKey) {
1835
+ headers["pk-api-key"] = this.options.gatewayKey;
1836
+ }
1837
+ return headers;
1830
1838
  }
1831
1839
  };
1832
1840
 
@@ -2886,12 +2894,15 @@ var noopLogger = {
2886
2894
 
2887
2895
  // src/peek-access-service.ts
2888
2896
  var DEFAULT_BASE_URL = "https://apps.peekapis.com/backoffice-gql";
2897
+ var DEFAULT_V2_BASE_URL = "https://app-registry.peeklabs.com/installations-api";
2889
2898
  var DEFAULT_TOKEN_TTL_SECONDS = 3600;
2890
2899
  var DEFAULT_TOKEN_REFRESH_LEEWAY_SECONDS = 60;
2891
2900
  var DEFAULT_RETRY_DELAYS_MS = [1e3, 2e3, 4e3];
2901
+ var PEEK_TOKEN_ISSUER = "app_registry_v2";
2892
2902
  var PeekAccessService = class {
2893
2903
  client;
2894
2904
  productServiceOptions;
2905
+ jwtSecret;
2895
2906
  productService;
2896
2907
  accountUserService;
2897
2908
  resourcePoolService;
@@ -2904,11 +2915,13 @@ var PeekAccessService = class {
2904
2915
  bookingService;
2905
2916
  reviewService;
2906
2917
  constructor(config) {
2918
+ const isV2 = config.mode === "v2";
2907
2919
  requireNonEmpty(config.installId, "installId");
2908
2920
  requireNonEmpty(config.jwtSecret, "jwtSecret");
2909
2921
  requireNonEmpty(config.issuer, "issuer");
2910
2922
  requireNonEmpty(config.appId, "appId");
2911
- requireNonEmpty(config.gatewayKey, "gatewayKey");
2923
+ if (!isV2) requireNonEmpty(config.gatewayKey ?? "", "gatewayKey");
2924
+ this.jwtSecret = config.jwtSecret;
2912
2925
  const logger = config.logger ?? noopLogger;
2913
2926
  const tokens = new TokenManager({
2914
2927
  secret: config.jwtSecret,
@@ -2917,19 +2930,56 @@ var PeekAccessService = class {
2917
2930
  ttlSeconds: config.tokenTtlSeconds ?? DEFAULT_TOKEN_TTL_SECONDS,
2918
2931
  leewaySeconds: config.tokenRefreshLeewaySeconds ?? DEFAULT_TOKEN_REFRESH_LEEWAY_SECONDS
2919
2932
  });
2933
+ const defaultBaseUrl = isV2 ? DEFAULT_V2_BASE_URL : DEFAULT_BASE_URL;
2920
2934
  this.client = new GraphQLClient({
2921
- baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,
2935
+ baseUrl: config.baseUrl ?? defaultBaseUrl,
2922
2936
  appId: config.appId,
2923
2937
  gatewayKey: config.gatewayKey,
2924
2938
  getToken: () => tokens.getToken(),
2925
2939
  retryDelaysMs: config.retryDelaysMs ?? DEFAULT_RETRY_DELAYS_MS,
2926
2940
  logger,
2927
- fetchFn: config.fetch ?? globalThis.fetch
2941
+ fetchFn: config.fetch ?? globalThis.fetch,
2942
+ endpointPathPrefix: isV2 ? V2_EXTENDABLE_SLUG : void 0
2928
2943
  });
2929
2944
  this.productServiceOptions = {
2930
2945
  itemOptionsPageSize: config.itemOptionsPageSize
2931
2946
  };
2932
2947
  }
2948
+ /**
2949
+ * Verifies a Peek auth token issued by the app registry and returns the
2950
+ * decoded claims.
2951
+ *
2952
+ * Validates the HMAC signature (using this service's `jwtSecret`), the token
2953
+ * expiry, the `"app_registry_v2"` issuer, and the `"Joken"` audience. Throws
2954
+ * from the `jsonwebtoken` library on any failure — callers should catch to
2955
+ * distinguish error kinds:
2956
+ *
2957
+ * - `JsonWebTokenError` — signature invalid, wrong issuer/audience, or token
2958
+ * malformed
2959
+ * - `TokenExpiredError` — past `exp`
2960
+ * - `NotBeforeError` — before `nbf`
2961
+ *
2962
+ * @throws {JsonWebTokenError} signature invalid or token malformed
2963
+ * @throws {TokenExpiredError} token has expired
2964
+ * @throws {NotBeforeError} token not yet valid
2965
+ */
2966
+ verifyPeekAuthToken(token) {
2967
+ const payload = jwt.verify(token, this.jwtSecret, {
2968
+ issuer: PEEK_TOKEN_ISSUER
2969
+ });
2970
+ const { user: u } = payload;
2971
+ return {
2972
+ installId: payload.sub,
2973
+ displayVersion: payload.display_version,
2974
+ user: {
2975
+ email: u.email,
2976
+ id: u.id,
2977
+ isAdmin: u.is_admin,
2978
+ locale: u.locale,
2979
+ name: u.name
2980
+ }
2981
+ };
2982
+ }
2933
2983
  /**
2934
2984
  * Returns the {@link ProductService} for this install, bound to the shared
2935
2985
  * authenticated transport. The instance is created lazily and reused.