@peektravel/app-utilities 0.9.0 → 0.9.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/dist/index.d.cts CHANGED
@@ -1,3 +1,24 @@
1
+ /**
2
+ * A platform's tiny map of **API endpoint key → relative path** (the "slug"
3
+ * inserted between the install's base API URL and the endpoint's own path).
4
+ *
5
+ * The base API URL is the install's app endpoint with no routing segment — the
6
+ * install webhook's `apiUrl` (with any slug stripped back off), or
7
+ * `baseUrl/appId` when built from the deprecated defaults. Each service class
8
+ * resolves *its own* slug through this lookup, so two services on the same
9
+ * platform can route through different slugs. Adding a new API — even one on a
10
+ * different slug than its siblings — is a single entry here.
11
+ *
12
+ * An empty-string path means the endpoint sits directly on the base with no
13
+ * slug (e.g. the legacy Peek v1 GraphQL gateway, which has no extendable slug).
14
+ */
15
+ declare class ApiEndpoints<Key extends string = string> {
16
+ private readonly paths;
17
+ constructor(paths: Readonly<Record<Key, string>>);
18
+ /** The relative path (slug) for `endpoint`, appended to the base API URL. */
19
+ pathFor(endpoint: Key): string;
20
+ }
21
+
1
22
  /**
2
23
  * Minimal structured logger interface the package can write diagnostics to.
3
24
  *
@@ -20,19 +41,13 @@ interface GraphQLBody<T> {
20
41
  }
21
42
  interface GraphQLClientOptions {
22
43
  /**
23
- * The install's app endpoint URL (the install webhook's `apiUrl`). When set it
24
- * is the **sole request URL** — every GraphQL call POSTs to it unmodified, and
25
- * `baseUrl`/`appId`/`endpointPathPrefix`/`endpointName` are ignored for URL
26
- * construction. Takes precedence over `baseUrl`.
44
+ * The install's **base API URL** (no trailing slash, no routing slug). Every
45
+ * GraphQL call POSTs to `baseApiUrl/<slug>`, where the slug comes from
46
+ * {@link endpoints} for the request's endpoint name.
27
47
  */
28
- apiUrl?: string;
29
- /**
30
- * Base URL of the backoffice GraphQL gateway (no trailing slash). Used only
31
- * when `apiUrl` is not set; the URL is `baseUrl/appId/[prefix/]endpointName`.
32
- */
33
- baseUrl?: string;
34
- /** Peek app ID, used in the endpoint path (legacy `baseUrl` mode only). */
35
- appId?: string;
48
+ baseApiUrl: string;
49
+ /** Maps an endpoint name to the relative slug appended to {@link baseApiUrl}. */
50
+ endpoints: ApiEndpoints;
36
51
  /** API gateway key sent as the `pk-api-key` header. Omitted from headers when absent (v2 mode). */
37
52
  gatewayKey?: string;
38
53
  /** Supplies a valid bearer token for each request. */
@@ -43,11 +58,6 @@ interface GraphQLClientOptions {
43
58
  logger: Logger;
44
59
  /** `fetch` implementation to use. */
45
60
  fetchFn: typeof fetch;
46
- /**
47
- * Optional fixed path segment inserted between `appId` and the endpoint name.
48
- * Used in v2 mode: `baseUrl/appId/endpointPathPrefix/endpointName`.
49
- */
50
- endpointPathPrefix?: string;
51
61
  }
52
62
  declare class GraphQLClient {
53
63
  private readonly options;
@@ -1671,13 +1681,17 @@ interface BaseAccessServiceConfig {
1671
1681
  /** JWT issuer — the app name / app ID. */
1672
1682
  issuer: string;
1673
1683
  /**
1674
- * The install's **app endpoint URL** — persist the install webhook's `apiUrl`
1675
- * and pass it here. When set it is used **as given**: for Peek it is the sole
1676
- * request URL (every call POSTs to it); for CNG/ACME it is the base and the
1677
- * REST path is appended. No app-id/gateway segment is inserted, so `appId` is
1678
- * not required. This is the forward-looking way to target an install — prefer
1679
- * it over `baseUrl`/`appId`, which are deprecated (the hardcoded base-URL
1680
- * fallbacks will be removed and a URL will become required in a future release).
1684
+ * The install's **base API URL** — persist the install webhook's `apiUrl` and
1685
+ * pass it here. It is the app endpoint with no per-platform routing slug; each
1686
+ * service class appends its own slug (e.g. `peek_backoffice_api-v1`, via that
1687
+ * platform's endpoint lookup) when it makes a call, so different services can
1688
+ * route through different slugs. If the URL you pass still carries this
1689
+ * platform's slug it is stripped back off to recover the base; a URL carrying a
1690
+ * *different* platform's slug makes the constructor throw. No app-id/gateway
1691
+ * segment is inserted, so `appId` is not required. This is the forward-looking
1692
+ * way to target an install — prefer it over `baseUrl`/`appId`, which are
1693
+ * deprecated (the hardcoded base-URL fallbacks will be removed and a URL will
1694
+ * become required in a future release).
1681
1695
  */
1682
1696
  apiUrl?: string;
1683
1697
  /**
@@ -2266,21 +2280,13 @@ declare class PeekAccessService {
2266
2280
 
2267
2281
  interface RestClientOptions$1 {
2268
2282
  /**
2269
- * The install's app endpoint URL (the install webhook's `apiUrl`). When set it
2270
- * is the **base URL** and only the REST path is appended (`apiUrl/path`) —
2271
- * `baseUrl`/`appId`/`extendableSlug` are ignored. Takes precedence over
2272
- * `baseUrl`.
2283
+ * The install's **base API URL** (no trailing slash, no routing slug). Each
2284
+ * request builds `baseApiUrl/<slug>/<path>`, where the slug comes from
2285
+ * {@link endpoints} for the request's endpoint key.
2273
2286
  */
2274
- apiUrl?: string;
2275
- /**
2276
- * Base URL of the backoffice gateway (no trailing slash). Used only when
2277
- * `apiUrl` is not set; the URL is `baseUrl/appId/extendableSlug/path`.
2278
- */
2279
- baseUrl?: string;
2280
- /** App ID, used in the endpoint path (legacy `baseUrl` mode only). */
2281
- appId?: string;
2282
- /** Fixed extendable slug inserted between `appId` and the REST path (legacy mode). */
2283
- extendableSlug?: string;
2287
+ baseApiUrl: string;
2288
+ /** Maps an endpoint key to the relative slug appended to {@link baseApiUrl}. */
2289
+ endpoints: ApiEndpoints;
2284
2290
  /** Supplies a valid bearer token for each request. */
2285
2291
  getToken: () => string;
2286
2292
  /** Backoff delays (ms) applied on successive HTTP 429 responses. */
@@ -2303,7 +2309,7 @@ declare class RestClient$1 {
2303
2309
  * @throws {CngPermissionError} on HTTP 403 (app missing a permission)
2304
2310
  * @throws {CngApiError} on any other non-2xx response
2305
2311
  */
2306
- get<T>(path: string): Promise<T>;
2312
+ get<T>(endpoint: string, path: string): Promise<T>;
2307
2313
  private endpoint;
2308
2314
  private buildHeaders;
2309
2315
  }
@@ -2411,21 +2417,13 @@ declare class CngAccessService {
2411
2417
 
2412
2418
  interface RestClientOptions {
2413
2419
  /**
2414
- * The install's app endpoint URL (the install webhook's `apiUrl`). When set it
2415
- * is the **base URL** and only the REST path is appended (`apiUrl/path`) —
2416
- * `baseUrl`/`appId`/`extendableSlug` are ignored. Takes precedence over
2417
- * `baseUrl`.
2418
- */
2419
- apiUrl?: string;
2420
- /**
2421
- * Base URL of the backoffice gateway (no trailing slash). Used only when
2422
- * `apiUrl` is not set; the URL is `baseUrl/appId/extendableSlug/path`.
2420
+ * The install's **base API URL** (no trailing slash, no routing slug). Each
2421
+ * request builds `baseApiUrl/<slug>/<path>`, where the slug comes from
2422
+ * {@link endpoints} for the request's endpoint key.
2423
2423
  */
2424
- baseUrl?: string;
2425
- /** App ID, used in the endpoint path (legacy `baseUrl` mode only). */
2426
- appId?: string;
2427
- /** Fixed extendable slug inserted between `appId` and the REST path (legacy mode). */
2428
- extendableSlug?: string;
2424
+ baseApiUrl: string;
2425
+ /** Maps an endpoint key to the relative slug appended to {@link baseApiUrl}. */
2426
+ endpoints: ApiEndpoints;
2429
2427
  /** Supplies a valid bearer token for each request. */
2430
2428
  getToken: () => string;
2431
2429
  /** Backoff delays (ms) applied on successive HTTP 429 responses. */
@@ -2447,7 +2445,7 @@ declare class RestClient {
2447
2445
  * @throws {RateLimitError} on HTTP 429 after retries are exhausted
2448
2446
  * @throws {AcmeApiError} on any other non-2xx response
2449
2447
  */
2450
- get<T>(path: string): Promise<T>;
2448
+ get<T>(endpoint: string, path: string): Promise<T>;
2451
2449
  private endpoint;
2452
2450
  private buildHeaders;
2453
2451
  }
@@ -2565,7 +2563,12 @@ declare class AcmeAccessService {
2565
2563
  interface InstallAccessTarget {
2566
2564
  /** Which platform serves the install (the install webhook's `platform`). */
2567
2565
  platform: PeekPlatform | null;
2568
- /** The install's app endpoint URL (the install webhook's `apiUrl`), used as given. */
2566
+ /**
2567
+ * The install's base API URL (the install webhook's `apiUrl`). The chosen
2568
+ * access service's service classes append their own backoffice slug when they
2569
+ * call; a URL already carrying this platform's slug is stripped back to the
2570
+ * base, and one carrying a different platform's slug throws.
2571
+ */
2569
2572
  apiUrl: string;
2570
2573
  /** The install id (the install webhook's `installId`) — becomes the JWT subject. */
2571
2574
  installId: string;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,24 @@
1
+ /**
2
+ * A platform's tiny map of **API endpoint key → relative path** (the "slug"
3
+ * inserted between the install's base API URL and the endpoint's own path).
4
+ *
5
+ * The base API URL is the install's app endpoint with no routing segment — the
6
+ * install webhook's `apiUrl` (with any slug stripped back off), or
7
+ * `baseUrl/appId` when built from the deprecated defaults. Each service class
8
+ * resolves *its own* slug through this lookup, so two services on the same
9
+ * platform can route through different slugs. Adding a new API — even one on a
10
+ * different slug than its siblings — is a single entry here.
11
+ *
12
+ * An empty-string path means the endpoint sits directly on the base with no
13
+ * slug (e.g. the legacy Peek v1 GraphQL gateway, which has no extendable slug).
14
+ */
15
+ declare class ApiEndpoints<Key extends string = string> {
16
+ private readonly paths;
17
+ constructor(paths: Readonly<Record<Key, string>>);
18
+ /** The relative path (slug) for `endpoint`, appended to the base API URL. */
19
+ pathFor(endpoint: Key): string;
20
+ }
21
+
1
22
  /**
2
23
  * Minimal structured logger interface the package can write diagnostics to.
3
24
  *
@@ -20,19 +41,13 @@ interface GraphQLBody<T> {
20
41
  }
21
42
  interface GraphQLClientOptions {
22
43
  /**
23
- * The install's app endpoint URL (the install webhook's `apiUrl`). When set it
24
- * is the **sole request URL** — every GraphQL call POSTs to it unmodified, and
25
- * `baseUrl`/`appId`/`endpointPathPrefix`/`endpointName` are ignored for URL
26
- * construction. Takes precedence over `baseUrl`.
44
+ * The install's **base API URL** (no trailing slash, no routing slug). Every
45
+ * GraphQL call POSTs to `baseApiUrl/<slug>`, where the slug comes from
46
+ * {@link endpoints} for the request's endpoint name.
27
47
  */
28
- apiUrl?: string;
29
- /**
30
- * Base URL of the backoffice GraphQL gateway (no trailing slash). Used only
31
- * when `apiUrl` is not set; the URL is `baseUrl/appId/[prefix/]endpointName`.
32
- */
33
- baseUrl?: string;
34
- /** Peek app ID, used in the endpoint path (legacy `baseUrl` mode only). */
35
- appId?: string;
48
+ baseApiUrl: string;
49
+ /** Maps an endpoint name to the relative slug appended to {@link baseApiUrl}. */
50
+ endpoints: ApiEndpoints;
36
51
  /** API gateway key sent as the `pk-api-key` header. Omitted from headers when absent (v2 mode). */
37
52
  gatewayKey?: string;
38
53
  /** Supplies a valid bearer token for each request. */
@@ -43,11 +58,6 @@ interface GraphQLClientOptions {
43
58
  logger: Logger;
44
59
  /** `fetch` implementation to use. */
45
60
  fetchFn: typeof fetch;
46
- /**
47
- * Optional fixed path segment inserted between `appId` and the endpoint name.
48
- * Used in v2 mode: `baseUrl/appId/endpointPathPrefix/endpointName`.
49
- */
50
- endpointPathPrefix?: string;
51
61
  }
52
62
  declare class GraphQLClient {
53
63
  private readonly options;
@@ -1671,13 +1681,17 @@ interface BaseAccessServiceConfig {
1671
1681
  /** JWT issuer — the app name / app ID. */
1672
1682
  issuer: string;
1673
1683
  /**
1674
- * The install's **app endpoint URL** — persist the install webhook's `apiUrl`
1675
- * and pass it here. When set it is used **as given**: for Peek it is the sole
1676
- * request URL (every call POSTs to it); for CNG/ACME it is the base and the
1677
- * REST path is appended. No app-id/gateway segment is inserted, so `appId` is
1678
- * not required. This is the forward-looking way to target an install — prefer
1679
- * it over `baseUrl`/`appId`, which are deprecated (the hardcoded base-URL
1680
- * fallbacks will be removed and a URL will become required in a future release).
1684
+ * The install's **base API URL** — persist the install webhook's `apiUrl` and
1685
+ * pass it here. It is the app endpoint with no per-platform routing slug; each
1686
+ * service class appends its own slug (e.g. `peek_backoffice_api-v1`, via that
1687
+ * platform's endpoint lookup) when it makes a call, so different services can
1688
+ * route through different slugs. If the URL you pass still carries this
1689
+ * platform's slug it is stripped back off to recover the base; a URL carrying a
1690
+ * *different* platform's slug makes the constructor throw. No app-id/gateway
1691
+ * segment is inserted, so `appId` is not required. This is the forward-looking
1692
+ * way to target an install — prefer it over `baseUrl`/`appId`, which are
1693
+ * deprecated (the hardcoded base-URL fallbacks will be removed and a URL will
1694
+ * become required in a future release).
1681
1695
  */
1682
1696
  apiUrl?: string;
1683
1697
  /**
@@ -2266,21 +2280,13 @@ declare class PeekAccessService {
2266
2280
 
2267
2281
  interface RestClientOptions$1 {
2268
2282
  /**
2269
- * The install's app endpoint URL (the install webhook's `apiUrl`). When set it
2270
- * is the **base URL** and only the REST path is appended (`apiUrl/path`) —
2271
- * `baseUrl`/`appId`/`extendableSlug` are ignored. Takes precedence over
2272
- * `baseUrl`.
2283
+ * The install's **base API URL** (no trailing slash, no routing slug). Each
2284
+ * request builds `baseApiUrl/<slug>/<path>`, where the slug comes from
2285
+ * {@link endpoints} for the request's endpoint key.
2273
2286
  */
2274
- apiUrl?: string;
2275
- /**
2276
- * Base URL of the backoffice gateway (no trailing slash). Used only when
2277
- * `apiUrl` is not set; the URL is `baseUrl/appId/extendableSlug/path`.
2278
- */
2279
- baseUrl?: string;
2280
- /** App ID, used in the endpoint path (legacy `baseUrl` mode only). */
2281
- appId?: string;
2282
- /** Fixed extendable slug inserted between `appId` and the REST path (legacy mode). */
2283
- extendableSlug?: string;
2287
+ baseApiUrl: string;
2288
+ /** Maps an endpoint key to the relative slug appended to {@link baseApiUrl}. */
2289
+ endpoints: ApiEndpoints;
2284
2290
  /** Supplies a valid bearer token for each request. */
2285
2291
  getToken: () => string;
2286
2292
  /** Backoff delays (ms) applied on successive HTTP 429 responses. */
@@ -2303,7 +2309,7 @@ declare class RestClient$1 {
2303
2309
  * @throws {CngPermissionError} on HTTP 403 (app missing a permission)
2304
2310
  * @throws {CngApiError} on any other non-2xx response
2305
2311
  */
2306
- get<T>(path: string): Promise<T>;
2312
+ get<T>(endpoint: string, path: string): Promise<T>;
2307
2313
  private endpoint;
2308
2314
  private buildHeaders;
2309
2315
  }
@@ -2411,21 +2417,13 @@ declare class CngAccessService {
2411
2417
 
2412
2418
  interface RestClientOptions {
2413
2419
  /**
2414
- * The install's app endpoint URL (the install webhook's `apiUrl`). When set it
2415
- * is the **base URL** and only the REST path is appended (`apiUrl/path`) —
2416
- * `baseUrl`/`appId`/`extendableSlug` are ignored. Takes precedence over
2417
- * `baseUrl`.
2418
- */
2419
- apiUrl?: string;
2420
- /**
2421
- * Base URL of the backoffice gateway (no trailing slash). Used only when
2422
- * `apiUrl` is not set; the URL is `baseUrl/appId/extendableSlug/path`.
2420
+ * The install's **base API URL** (no trailing slash, no routing slug). Each
2421
+ * request builds `baseApiUrl/<slug>/<path>`, where the slug comes from
2422
+ * {@link endpoints} for the request's endpoint key.
2423
2423
  */
2424
- baseUrl?: string;
2425
- /** App ID, used in the endpoint path (legacy `baseUrl` mode only). */
2426
- appId?: string;
2427
- /** Fixed extendable slug inserted between `appId` and the REST path (legacy mode). */
2428
- extendableSlug?: string;
2424
+ baseApiUrl: string;
2425
+ /** Maps an endpoint key to the relative slug appended to {@link baseApiUrl}. */
2426
+ endpoints: ApiEndpoints;
2429
2427
  /** Supplies a valid bearer token for each request. */
2430
2428
  getToken: () => string;
2431
2429
  /** Backoff delays (ms) applied on successive HTTP 429 responses. */
@@ -2447,7 +2445,7 @@ declare class RestClient {
2447
2445
  * @throws {RateLimitError} on HTTP 429 after retries are exhausted
2448
2446
  * @throws {AcmeApiError} on any other non-2xx response
2449
2447
  */
2450
- get<T>(path: string): Promise<T>;
2448
+ get<T>(endpoint: string, path: string): Promise<T>;
2451
2449
  private endpoint;
2452
2450
  private buildHeaders;
2453
2451
  }
@@ -2565,7 +2563,12 @@ declare class AcmeAccessService {
2565
2563
  interface InstallAccessTarget {
2566
2564
  /** Which platform serves the install (the install webhook's `platform`). */
2567
2565
  platform: PeekPlatform | null;
2568
- /** The install's app endpoint URL (the install webhook's `apiUrl`), used as given. */
2566
+ /**
2567
+ * The install's base API URL (the install webhook's `apiUrl`). The chosen
2568
+ * access service's service classes append their own backoffice slug when they
2569
+ * call; a URL already carrying this platform's slug is stripped back to the
2570
+ * base, and one carrying a different platform's slug throws.
2571
+ */
2569
2572
  apiUrl: string;
2570
2573
  /** The install id (the install webhook's `installId`) — becomes the JWT subject. */
2571
2574
  installId: string;
package/dist/index.js CHANGED
@@ -1,9 +1,29 @@
1
1
  import { randomUUID } from 'crypto';
2
2
  import * as jwt from 'jsonwebtoken';
3
3
 
4
+ // src/internal/api-endpoints.ts
5
+ var ApiEndpoints = class {
6
+ constructor(paths) {
7
+ this.paths = paths;
8
+ }
9
+ paths;
10
+ /** The relative path (slug) for `endpoint`, appended to the base API URL. */
11
+ pathFor(endpoint) {
12
+ return this.paths[endpoint];
13
+ }
14
+ };
15
+ function joinUrl(...parts) {
16
+ return parts.filter((part) => part.length > 0).join("/");
17
+ }
18
+
4
19
  // src/internal/peek/gateway-endpoints.ts
5
20
  var SALES_ENDPOINT = "sales";
6
21
  var V2_EXTENDABLE_SLUG = "peek_backoffice_api-v1";
22
+ function peekApiEndpoints(useRegistrySlug) {
23
+ return new ApiEndpoints({
24
+ [SALES_ENDPOINT]: useRegistrySlug ? V2_EXTENDABLE_SLUG : SALES_ENDPOINT
25
+ });
26
+ }
7
27
 
8
28
  // src/internal/peek/account-users/account-user-converter.ts
9
29
  var ACTIVE_STATUS = "ACTIVE";
@@ -2077,6 +2097,21 @@ function requireNonEmpty(value, name, serviceName) {
2077
2097
  throw new Error(`${serviceName}: "${name}" is required`);
2078
2098
  }
2079
2099
  }
2100
+ var EXTENDABLE_SLUG_RE = /^([a-z0-9]+)[-_]backoffice[-_]api[-_]v1$/i;
2101
+ function resolveBaseApiUrl(apiUrl, platformSlug, serviceName) {
2102
+ const trimmed = apiUrl.replace(/\/+$/, "");
2103
+ const lastSegment = trimmed.slice(trimmed.lastIndexOf("/") + 1);
2104
+ const found = EXTENDABLE_SLUG_RE.exec(lastSegment);
2105
+ if (!found) return trimmed;
2106
+ const foundPlatform = found[1].toLowerCase();
2107
+ const expectedPlatform = EXTENDABLE_SLUG_RE.exec(platformSlug)[1].toLowerCase();
2108
+ if (foundPlatform !== expectedPlatform) {
2109
+ throw new Error(
2110
+ `${serviceName}: "apiUrl" carries a "${foundPlatform}" backoffice slug but this service targets "${expectedPlatform}" \u2014 pass the install's ${expectedPlatform} app endpoint`
2111
+ );
2112
+ }
2113
+ return trimmed.slice(0, trimmed.lastIndexOf("/"));
2114
+ }
2080
2115
  function createTokenManager(config) {
2081
2116
  return new TokenManager({
2082
2117
  secret: config.jwtSecret,
@@ -2127,7 +2162,7 @@ async function requestWithRetry(http, url, init, label, onResponse) {
2127
2162
  // src/internal/sdk-headers.ts
2128
2163
  var SDK_HEADER_NAME = "x-peek-sdk";
2129
2164
  var SDK_PLATFORM = "js";
2130
- var SDK_VERSION = "0.9.0";
2165
+ var SDK_VERSION = "0.9.1";
2131
2166
  var SDK_HEADER_VALUE = `${SDK_PLATFORM}-${SDK_VERSION}`;
2132
2167
 
2133
2168
  // src/internal/peek/graphql-client.ts
@@ -2175,10 +2210,8 @@ var GraphQLClient = class {
2175
2210
  );
2176
2211
  }
2177
2212
  endpoint(endpointName) {
2178
- const { apiUrl, baseUrl, appId, endpointPathPrefix } = this.options;
2179
- if (apiUrl) return apiUrl;
2180
- const prefix = endpointPathPrefix ? `${endpointPathPrefix}/` : "";
2181
- return `${baseUrl}/${appId}/${prefix}${endpointName}`;
2213
+ const { baseApiUrl, endpoints } = this.options;
2214
+ return joinUrl(baseApiUrl, endpoints.pathFor(endpointName));
2182
2215
  }
2183
2216
  buildHeaders() {
2184
2217
  const headers = {
@@ -3801,17 +3834,17 @@ var PeekAccessService = class {
3801
3834
  this.jwtSecret = config.jwtSecret;
3802
3835
  const logger = config.logger ?? noopLogger;
3803
3836
  const tokens = createTokenManager(config);
3837
+ const useRegistrySlug = hasApiUrl || isV2;
3804
3838
  const defaultBaseUrl = isV2 ? DEFAULT_V2_BASE_URL : DEFAULT_BASE_URL;
3839
+ const baseApiUrl = hasApiUrl ? resolveBaseApiUrl(config.apiUrl, V2_EXTENDABLE_SLUG, "PeekAccessService") : `${config.baseUrl ?? defaultBaseUrl}/${config.appId}`;
3805
3840
  this.client = new GraphQLClient({
3806
- apiUrl: config.apiUrl,
3807
- baseUrl: hasApiUrl ? void 0 : config.baseUrl ?? defaultBaseUrl,
3808
- appId: hasApiUrl ? void 0 : config.appId,
3841
+ baseApiUrl,
3842
+ endpoints: peekApiEndpoints(useRegistrySlug),
3809
3843
  gatewayKey: config.gatewayKey,
3810
3844
  getToken: () => tokens.getToken(),
3811
3845
  retryDelaysMs: config.retryDelaysMs ?? DEFAULT_RETRY_DELAYS_MS,
3812
3846
  logger,
3813
- fetchFn: config.fetch ?? globalThis.fetch,
3814
- endpointPathPrefix: !hasApiUrl && isV2 ? V2_EXTENDABLE_SLUG : void 0
3847
+ fetchFn: config.fetch ?? globalThis.fetch
3815
3848
  });
3816
3849
  this.productServiceOptions = {
3817
3850
  itemOptionsPageSize: config.itemOptionsPageSize
@@ -4165,7 +4198,11 @@ var PeekAccessService = class {
4165
4198
 
4166
4199
  // src/internal/cng/endpoints.ts
4167
4200
  var CNG_EXTENDABLE_SLUG = "cng_backoffice_api-v1";
4201
+ var CNG_PRODUCTS_ENDPOINT = "products";
4168
4202
  var PRODUCTS_PATH = "api/v2/app-registry/products?active=1";
4203
+ var CNG_API_ENDPOINTS = new ApiEndpoints({
4204
+ [CNG_PRODUCTS_ENDPOINT]: CNG_EXTENDABLE_SLUG
4205
+ });
4169
4206
 
4170
4207
  // src/models/cng/product.ts
4171
4208
  var ACTIVITY_PRODUCT_TYPE2 = "ACTIVITY";
@@ -4199,7 +4236,10 @@ var CngProductService = class {
4199
4236
  * ```
4200
4237
  */
4201
4238
  async getAllActivities() {
4202
- const body = await this.client.get(PRODUCTS_PATH);
4239
+ const body = await this.client.get(
4240
+ CNG_PRODUCTS_ENDPOINT,
4241
+ PRODUCTS_PATH
4242
+ );
4203
4243
  return fromProductNodes(body?.data ?? []);
4204
4244
  }
4205
4245
  };
@@ -4221,9 +4261,9 @@ var RestClient = class {
4221
4261
  * @throws {CngPermissionError} on HTTP 403 (app missing a permission)
4222
4262
  * @throws {CngApiError} on any other non-2xx response
4223
4263
  */
4224
- async get(path) {
4264
+ async get(endpoint, path) {
4225
4265
  const { logger } = this.options;
4226
- const url = this.endpoint(path);
4266
+ const url = this.endpoint(endpoint, path);
4227
4267
  logger.info("Making CNG request", { url, path });
4228
4268
  return requestWithRetry(
4229
4269
  this.options,
@@ -4245,10 +4285,9 @@ var RestClient = class {
4245
4285
  }
4246
4286
  );
4247
4287
  }
4248
- endpoint(path) {
4249
- const { apiUrl, baseUrl, appId, extendableSlug } = this.options;
4250
- if (apiUrl) return `${apiUrl}/${path}`;
4251
- return `${baseUrl}/${appId}/${extendableSlug}/${path}`;
4288
+ endpoint(endpoint, path) {
4289
+ const { baseApiUrl, endpoints } = this.options;
4290
+ return joinUrl(baseApiUrl, endpoints.pathFor(endpoint), path);
4252
4291
  }
4253
4292
  buildHeaders() {
4254
4293
  return {
@@ -4278,11 +4317,10 @@ var CngAccessService = class {
4278
4317
  if (!hasApiUrl) requireNonEmpty(config.appId ?? "", "appId", "CngAccessService");
4279
4318
  const logger = config.logger ?? noopLogger;
4280
4319
  const tokens = createTokenManager(config);
4320
+ const baseApiUrl = hasApiUrl ? resolveBaseApiUrl(config.apiUrl, CNG_EXTENDABLE_SLUG, "CngAccessService") : `${config.baseUrl ?? DEFAULT_BASE_URL2}/${config.appId}`;
4281
4321
  this.client = new RestClient({
4282
- apiUrl: config.apiUrl,
4283
- baseUrl: hasApiUrl ? void 0 : config.baseUrl ?? DEFAULT_BASE_URL2,
4284
- appId: hasApiUrl ? void 0 : config.appId,
4285
- extendableSlug: CNG_EXTENDABLE_SLUG,
4322
+ baseApiUrl,
4323
+ endpoints: CNG_API_ENDPOINTS,
4286
4324
  getToken: () => tokens.getToken(),
4287
4325
  retryDelaysMs: config.retryDelaysMs ?? DEFAULT_RETRY_DELAYS_MS,
4288
4326
  logger,
@@ -4307,7 +4345,11 @@ var CngAccessService = class {
4307
4345
 
4308
4346
  // src/internal/acme/endpoints.ts
4309
4347
  var ACME_EXTENDABLE_SLUG = "acme_backoffice_api-v1";
4348
+ var ACME_TEMPLATES_ENDPOINT = "templates";
4310
4349
  var TEMPLATES_PATH = "v2/b2b/event/templates/names?pageSize=-1&page=1";
4350
+ var ACME_API_ENDPOINTS = new ApiEndpoints({
4351
+ [ACME_TEMPLATES_ENDPOINT]: ACME_EXTENDABLE_SLUG
4352
+ });
4311
4353
 
4312
4354
  // src/models/acme/product.ts
4313
4355
  var ACME_ACTIVITY_TYPE = "standard";
@@ -4345,6 +4387,7 @@ var AcmeProductService = class {
4345
4387
  */
4346
4388
  async getAllActivities() {
4347
4389
  const body = await this.client.get(
4390
+ ACME_TEMPLATES_ENDPOINT,
4348
4391
  TEMPLATES_PATH
4349
4392
  );
4350
4393
  const nodes = Array.isArray(body) ? body : body?.list ?? [];
@@ -4367,9 +4410,9 @@ var RestClient2 = class {
4367
4410
  * @throws {RateLimitError} on HTTP 429 after retries are exhausted
4368
4411
  * @throws {AcmeApiError} on any other non-2xx response
4369
4412
  */
4370
- async get(path) {
4413
+ async get(endpoint, path) {
4371
4414
  const { logger } = this.options;
4372
- const url = this.endpoint(path);
4415
+ const url = this.endpoint(endpoint, path);
4373
4416
  logger.info("Making ACME request", { url, path });
4374
4417
  return requestWithRetry(
4375
4418
  this.options,
@@ -4386,10 +4429,9 @@ var RestClient2 = class {
4386
4429
  }
4387
4430
  );
4388
4431
  }
4389
- endpoint(path) {
4390
- const { apiUrl, baseUrl, appId, extendableSlug } = this.options;
4391
- if (apiUrl) return `${apiUrl}/${path}`;
4392
- return `${baseUrl}/${appId}/${extendableSlug}/${path}`;
4432
+ endpoint(endpoint, path) {
4433
+ const { baseApiUrl, endpoints } = this.options;
4434
+ return joinUrl(baseApiUrl, endpoints.pathFor(endpoint), path);
4393
4435
  }
4394
4436
  buildHeaders() {
4395
4437
  return {
@@ -4413,11 +4455,10 @@ var AcmeAccessService = class {
4413
4455
  if (!hasApiUrl) requireNonEmpty(config.appId ?? "", "appId", "AcmeAccessService");
4414
4456
  const logger = config.logger ?? noopLogger;
4415
4457
  const tokens = createTokenManager(config);
4458
+ const baseApiUrl = hasApiUrl ? resolveBaseApiUrl(config.apiUrl, ACME_EXTENDABLE_SLUG, "AcmeAccessService") : `${config.baseUrl ?? DEFAULT_BASE_URL3}/${config.appId}`;
4416
4459
  this.client = new RestClient2({
4417
- apiUrl: config.apiUrl,
4418
- baseUrl: hasApiUrl ? void 0 : config.baseUrl ?? DEFAULT_BASE_URL3,
4419
- appId: hasApiUrl ? void 0 : config.appId,
4420
- extendableSlug: ACME_EXTENDABLE_SLUG,
4460
+ baseApiUrl,
4461
+ endpoints: ACME_API_ENDPOINTS,
4421
4462
  getToken: () => tokens.getToken(),
4422
4463
  retryDelaysMs: config.retryDelaysMs ?? DEFAULT_RETRY_DELAYS_MS,
4423
4464
  logger,