@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/README.md +6 -3
- package/dist/index.cjs +72 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -55
- package/dist/index.d.ts +58 -55
- package/dist/index.js +72 -31
- package/dist/index.js.map +1 -1
- package/docs/webhooks.md +11 -8
- package/llms.txt +15 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -317,9 +317,12 @@ event data**; the fields it shares with the token (`installId` / `accountId` /
|
|
|
317
317
|
the body omits them. The token authenticates the whole delivery, so the body is
|
|
318
318
|
trusted within a verified request. This webhook is the only source of
|
|
319
319
|
`accountId`, `timezone`, and `apiUrl` in the package, since no GraphQL read
|
|
320
|
-
returns them — **persist them per install**. `apiUrl` is the install's
|
|
321
|
-
|
|
322
|
-
|
|
320
|
+
returns them — **persist them per install**. `apiUrl` is the install's **base API
|
|
321
|
+
URL**: pass it straight through (don't reconstruct it from `appId`) as the access
|
|
322
|
+
service's `apiUrl` — each service class appends its own backoffice slug (e.g.
|
|
323
|
+
`peek_backoffice_api-v1`) when it makes a call, stripping the slug back off if the
|
|
324
|
+
URL you pass already carries it and throwing if it carries a different platform's
|
|
325
|
+
slug — or hand the whole install to
|
|
323
326
|
`createAccessServiceForInstall(install, { jwtSecret, issuer })`, which picks the
|
|
324
327
|
service by `platform` and wires the endpoint for you. Every event is a **full
|
|
325
328
|
snapshot** — an `update_installed` carries the same fields as the original
|
package/dist/index.cjs
CHANGED
|
@@ -23,9 +23,29 @@ function _interopNamespace(e) {
|
|
|
23
23
|
|
|
24
24
|
var jwt__namespace = /*#__PURE__*/_interopNamespace(jwt);
|
|
25
25
|
|
|
26
|
+
// src/internal/api-endpoints.ts
|
|
27
|
+
var ApiEndpoints = class {
|
|
28
|
+
constructor(paths) {
|
|
29
|
+
this.paths = paths;
|
|
30
|
+
}
|
|
31
|
+
paths;
|
|
32
|
+
/** The relative path (slug) for `endpoint`, appended to the base API URL. */
|
|
33
|
+
pathFor(endpoint) {
|
|
34
|
+
return this.paths[endpoint];
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
function joinUrl(...parts) {
|
|
38
|
+
return parts.filter((part) => part.length > 0).join("/");
|
|
39
|
+
}
|
|
40
|
+
|
|
26
41
|
// src/internal/peek/gateway-endpoints.ts
|
|
27
42
|
var SALES_ENDPOINT = "sales";
|
|
28
43
|
var V2_EXTENDABLE_SLUG = "peek_backoffice_api-v1";
|
|
44
|
+
function peekApiEndpoints(useRegistrySlug) {
|
|
45
|
+
return new ApiEndpoints({
|
|
46
|
+
[SALES_ENDPOINT]: useRegistrySlug ? V2_EXTENDABLE_SLUG : SALES_ENDPOINT
|
|
47
|
+
});
|
|
48
|
+
}
|
|
29
49
|
|
|
30
50
|
// src/internal/peek/account-users/account-user-converter.ts
|
|
31
51
|
var ACTIVE_STATUS = "ACTIVE";
|
|
@@ -2099,6 +2119,21 @@ function requireNonEmpty(value, name, serviceName) {
|
|
|
2099
2119
|
throw new Error(`${serviceName}: "${name}" is required`);
|
|
2100
2120
|
}
|
|
2101
2121
|
}
|
|
2122
|
+
var EXTENDABLE_SLUG_RE = /^([a-z0-9]+)[-_]backoffice[-_]api[-_]v1$/i;
|
|
2123
|
+
function resolveBaseApiUrl(apiUrl, platformSlug, serviceName) {
|
|
2124
|
+
const trimmed = apiUrl.replace(/\/+$/, "");
|
|
2125
|
+
const lastSegment = trimmed.slice(trimmed.lastIndexOf("/") + 1);
|
|
2126
|
+
const found = EXTENDABLE_SLUG_RE.exec(lastSegment);
|
|
2127
|
+
if (!found) return trimmed;
|
|
2128
|
+
const foundPlatform = found[1].toLowerCase();
|
|
2129
|
+
const expectedPlatform = EXTENDABLE_SLUG_RE.exec(platformSlug)[1].toLowerCase();
|
|
2130
|
+
if (foundPlatform !== expectedPlatform) {
|
|
2131
|
+
throw new Error(
|
|
2132
|
+
`${serviceName}: "apiUrl" carries a "${foundPlatform}" backoffice slug but this service targets "${expectedPlatform}" \u2014 pass the install's ${expectedPlatform} app endpoint`
|
|
2133
|
+
);
|
|
2134
|
+
}
|
|
2135
|
+
return trimmed.slice(0, trimmed.lastIndexOf("/"));
|
|
2136
|
+
}
|
|
2102
2137
|
function createTokenManager(config) {
|
|
2103
2138
|
return new TokenManager({
|
|
2104
2139
|
secret: config.jwtSecret,
|
|
@@ -2149,7 +2184,7 @@ async function requestWithRetry(http, url, init, label, onResponse) {
|
|
|
2149
2184
|
// src/internal/sdk-headers.ts
|
|
2150
2185
|
var SDK_HEADER_NAME = "x-peek-sdk";
|
|
2151
2186
|
var SDK_PLATFORM = "js";
|
|
2152
|
-
var SDK_VERSION = "0.9.
|
|
2187
|
+
var SDK_VERSION = "0.9.1";
|
|
2153
2188
|
var SDK_HEADER_VALUE = `${SDK_PLATFORM}-${SDK_VERSION}`;
|
|
2154
2189
|
|
|
2155
2190
|
// src/internal/peek/graphql-client.ts
|
|
@@ -2197,10 +2232,8 @@ var GraphQLClient = class {
|
|
|
2197
2232
|
);
|
|
2198
2233
|
}
|
|
2199
2234
|
endpoint(endpointName) {
|
|
2200
|
-
const {
|
|
2201
|
-
|
|
2202
|
-
const prefix = endpointPathPrefix ? `${endpointPathPrefix}/` : "";
|
|
2203
|
-
return `${baseUrl}/${appId}/${prefix}${endpointName}`;
|
|
2235
|
+
const { baseApiUrl, endpoints } = this.options;
|
|
2236
|
+
return joinUrl(baseApiUrl, endpoints.pathFor(endpointName));
|
|
2204
2237
|
}
|
|
2205
2238
|
buildHeaders() {
|
|
2206
2239
|
const headers = {
|
|
@@ -3823,17 +3856,17 @@ var PeekAccessService = class {
|
|
|
3823
3856
|
this.jwtSecret = config.jwtSecret;
|
|
3824
3857
|
const logger = config.logger ?? noopLogger;
|
|
3825
3858
|
const tokens = createTokenManager(config);
|
|
3859
|
+
const useRegistrySlug = hasApiUrl || isV2;
|
|
3826
3860
|
const defaultBaseUrl = isV2 ? DEFAULT_V2_BASE_URL : DEFAULT_BASE_URL;
|
|
3861
|
+
const baseApiUrl = hasApiUrl ? resolveBaseApiUrl(config.apiUrl, V2_EXTENDABLE_SLUG, "PeekAccessService") : `${config.baseUrl ?? defaultBaseUrl}/${config.appId}`;
|
|
3827
3862
|
this.client = new GraphQLClient({
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
appId: hasApiUrl ? void 0 : config.appId,
|
|
3863
|
+
baseApiUrl,
|
|
3864
|
+
endpoints: peekApiEndpoints(useRegistrySlug),
|
|
3831
3865
|
gatewayKey: config.gatewayKey,
|
|
3832
3866
|
getToken: () => tokens.getToken(),
|
|
3833
3867
|
retryDelaysMs: config.retryDelaysMs ?? DEFAULT_RETRY_DELAYS_MS,
|
|
3834
3868
|
logger,
|
|
3835
|
-
fetchFn: config.fetch ?? globalThis.fetch
|
|
3836
|
-
endpointPathPrefix: !hasApiUrl && isV2 ? V2_EXTENDABLE_SLUG : void 0
|
|
3869
|
+
fetchFn: config.fetch ?? globalThis.fetch
|
|
3837
3870
|
});
|
|
3838
3871
|
this.productServiceOptions = {
|
|
3839
3872
|
itemOptionsPageSize: config.itemOptionsPageSize
|
|
@@ -4187,7 +4220,11 @@ var PeekAccessService = class {
|
|
|
4187
4220
|
|
|
4188
4221
|
// src/internal/cng/endpoints.ts
|
|
4189
4222
|
var CNG_EXTENDABLE_SLUG = "cng_backoffice_api-v1";
|
|
4223
|
+
var CNG_PRODUCTS_ENDPOINT = "products";
|
|
4190
4224
|
var PRODUCTS_PATH = "api/v2/app-registry/products?active=1";
|
|
4225
|
+
var CNG_API_ENDPOINTS = new ApiEndpoints({
|
|
4226
|
+
[CNG_PRODUCTS_ENDPOINT]: CNG_EXTENDABLE_SLUG
|
|
4227
|
+
});
|
|
4191
4228
|
|
|
4192
4229
|
// src/models/cng/product.ts
|
|
4193
4230
|
var ACTIVITY_PRODUCT_TYPE2 = "ACTIVITY";
|
|
@@ -4221,7 +4258,10 @@ var CngProductService = class {
|
|
|
4221
4258
|
* ```
|
|
4222
4259
|
*/
|
|
4223
4260
|
async getAllActivities() {
|
|
4224
|
-
const body = await this.client.get(
|
|
4261
|
+
const body = await this.client.get(
|
|
4262
|
+
CNG_PRODUCTS_ENDPOINT,
|
|
4263
|
+
PRODUCTS_PATH
|
|
4264
|
+
);
|
|
4225
4265
|
return fromProductNodes(body?.data ?? []);
|
|
4226
4266
|
}
|
|
4227
4267
|
};
|
|
@@ -4243,9 +4283,9 @@ var RestClient = class {
|
|
|
4243
4283
|
* @throws {CngPermissionError} on HTTP 403 (app missing a permission)
|
|
4244
4284
|
* @throws {CngApiError} on any other non-2xx response
|
|
4245
4285
|
*/
|
|
4246
|
-
async get(path) {
|
|
4286
|
+
async get(endpoint, path) {
|
|
4247
4287
|
const { logger } = this.options;
|
|
4248
|
-
const url = this.endpoint(path);
|
|
4288
|
+
const url = this.endpoint(endpoint, path);
|
|
4249
4289
|
logger.info("Making CNG request", { url, path });
|
|
4250
4290
|
return requestWithRetry(
|
|
4251
4291
|
this.options,
|
|
@@ -4267,10 +4307,9 @@ var RestClient = class {
|
|
|
4267
4307
|
}
|
|
4268
4308
|
);
|
|
4269
4309
|
}
|
|
4270
|
-
endpoint(path) {
|
|
4271
|
-
const {
|
|
4272
|
-
|
|
4273
|
-
return `${baseUrl}/${appId}/${extendableSlug}/${path}`;
|
|
4310
|
+
endpoint(endpoint, path) {
|
|
4311
|
+
const { baseApiUrl, endpoints } = this.options;
|
|
4312
|
+
return joinUrl(baseApiUrl, endpoints.pathFor(endpoint), path);
|
|
4274
4313
|
}
|
|
4275
4314
|
buildHeaders() {
|
|
4276
4315
|
return {
|
|
@@ -4300,11 +4339,10 @@ var CngAccessService = class {
|
|
|
4300
4339
|
if (!hasApiUrl) requireNonEmpty(config.appId ?? "", "appId", "CngAccessService");
|
|
4301
4340
|
const logger = config.logger ?? noopLogger;
|
|
4302
4341
|
const tokens = createTokenManager(config);
|
|
4342
|
+
const baseApiUrl = hasApiUrl ? resolveBaseApiUrl(config.apiUrl, CNG_EXTENDABLE_SLUG, "CngAccessService") : `${config.baseUrl ?? DEFAULT_BASE_URL2}/${config.appId}`;
|
|
4303
4343
|
this.client = new RestClient({
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
appId: hasApiUrl ? void 0 : config.appId,
|
|
4307
|
-
extendableSlug: CNG_EXTENDABLE_SLUG,
|
|
4344
|
+
baseApiUrl,
|
|
4345
|
+
endpoints: CNG_API_ENDPOINTS,
|
|
4308
4346
|
getToken: () => tokens.getToken(),
|
|
4309
4347
|
retryDelaysMs: config.retryDelaysMs ?? DEFAULT_RETRY_DELAYS_MS,
|
|
4310
4348
|
logger,
|
|
@@ -4329,7 +4367,11 @@ var CngAccessService = class {
|
|
|
4329
4367
|
|
|
4330
4368
|
// src/internal/acme/endpoints.ts
|
|
4331
4369
|
var ACME_EXTENDABLE_SLUG = "acme_backoffice_api-v1";
|
|
4370
|
+
var ACME_TEMPLATES_ENDPOINT = "templates";
|
|
4332
4371
|
var TEMPLATES_PATH = "v2/b2b/event/templates/names?pageSize=-1&page=1";
|
|
4372
|
+
var ACME_API_ENDPOINTS = new ApiEndpoints({
|
|
4373
|
+
[ACME_TEMPLATES_ENDPOINT]: ACME_EXTENDABLE_SLUG
|
|
4374
|
+
});
|
|
4333
4375
|
|
|
4334
4376
|
// src/models/acme/product.ts
|
|
4335
4377
|
var ACME_ACTIVITY_TYPE = "standard";
|
|
@@ -4367,6 +4409,7 @@ var AcmeProductService = class {
|
|
|
4367
4409
|
*/
|
|
4368
4410
|
async getAllActivities() {
|
|
4369
4411
|
const body = await this.client.get(
|
|
4412
|
+
ACME_TEMPLATES_ENDPOINT,
|
|
4370
4413
|
TEMPLATES_PATH
|
|
4371
4414
|
);
|
|
4372
4415
|
const nodes = Array.isArray(body) ? body : body?.list ?? [];
|
|
@@ -4389,9 +4432,9 @@ var RestClient2 = class {
|
|
|
4389
4432
|
* @throws {RateLimitError} on HTTP 429 after retries are exhausted
|
|
4390
4433
|
* @throws {AcmeApiError} on any other non-2xx response
|
|
4391
4434
|
*/
|
|
4392
|
-
async get(path) {
|
|
4435
|
+
async get(endpoint, path) {
|
|
4393
4436
|
const { logger } = this.options;
|
|
4394
|
-
const url = this.endpoint(path);
|
|
4437
|
+
const url = this.endpoint(endpoint, path);
|
|
4395
4438
|
logger.info("Making ACME request", { url, path });
|
|
4396
4439
|
return requestWithRetry(
|
|
4397
4440
|
this.options,
|
|
@@ -4408,10 +4451,9 @@ var RestClient2 = class {
|
|
|
4408
4451
|
}
|
|
4409
4452
|
);
|
|
4410
4453
|
}
|
|
4411
|
-
endpoint(path) {
|
|
4412
|
-
const {
|
|
4413
|
-
|
|
4414
|
-
return `${baseUrl}/${appId}/${extendableSlug}/${path}`;
|
|
4454
|
+
endpoint(endpoint, path) {
|
|
4455
|
+
const { baseApiUrl, endpoints } = this.options;
|
|
4456
|
+
return joinUrl(baseApiUrl, endpoints.pathFor(endpoint), path);
|
|
4415
4457
|
}
|
|
4416
4458
|
buildHeaders() {
|
|
4417
4459
|
return {
|
|
@@ -4435,11 +4477,10 @@ var AcmeAccessService = class {
|
|
|
4435
4477
|
if (!hasApiUrl) requireNonEmpty(config.appId ?? "", "appId", "AcmeAccessService");
|
|
4436
4478
|
const logger = config.logger ?? noopLogger;
|
|
4437
4479
|
const tokens = createTokenManager(config);
|
|
4480
|
+
const baseApiUrl = hasApiUrl ? resolveBaseApiUrl(config.apiUrl, ACME_EXTENDABLE_SLUG, "AcmeAccessService") : `${config.baseUrl ?? DEFAULT_BASE_URL3}/${config.appId}`;
|
|
4438
4481
|
this.client = new RestClient2({
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
appId: hasApiUrl ? void 0 : config.appId,
|
|
4442
|
-
extendableSlug: ACME_EXTENDABLE_SLUG,
|
|
4482
|
+
baseApiUrl,
|
|
4483
|
+
endpoints: ACME_API_ENDPOINTS,
|
|
4443
4484
|
getToken: () => tokens.getToken(),
|
|
4444
4485
|
retryDelaysMs: config.retryDelaysMs ?? DEFAULT_RETRY_DELAYS_MS,
|
|
4445
4486
|
logger,
|