@viu/emporix-sdk 2.31.1 → 2.32.0
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/CHANGELOG.md +48 -0
- package/dist/availability.cjs +44 -10
- package/dist/availability.cjs.map +1 -1
- package/dist/availability.d.cts +2 -1
- package/dist/availability.d.ts +2 -1
- package/dist/availability.js +2 -1
- package/dist/cart.d.cts +1 -1
- package/dist/cart.d.ts +1 -1
- package/dist/category.cjs +82 -28
- package/dist/category.cjs.map +1 -1
- package/dist/category.d.cts +10 -1
- package/dist/category.d.ts +10 -1
- package/dist/category.js +3 -2
- package/dist/checkout.d.cts +1 -1
- package/dist/checkout.d.ts +1 -1
- package/dist/{chunk-W2KBVWJ2.js → chunk-3G5KROEC.js} +8 -2
- package/dist/chunk-3G5KROEC.js.map +1 -0
- package/dist/{chunk-7W22KLUL.js → chunk-JQWUGGRV.js} +32 -17
- package/dist/chunk-JQWUGGRV.js.map +1 -0
- package/dist/chunk-LKHKFF7B.js +30 -0
- package/dist/chunk-LKHKFF7B.js.map +1 -0
- package/dist/{chunk-D7HBM2DQ.js → chunk-MSQ3GEIW.js} +59 -31
- package/dist/chunk-MSQ3GEIW.js.map +1 -0
- package/dist/{chunk-P7G4LOOV.js → chunk-P3RANRGB.js} +47 -25
- package/dist/chunk-P3RANRGB.js.map +1 -0
- package/dist/{chunk-OTG2S2L4.js → chunk-TI56QENX.js} +14 -14
- package/dist/chunk-TI56QENX.js.map +1 -0
- package/dist/{chunk-GWJ2U2CP.js → chunk-W6SLZNRX.js} +2 -2
- package/dist/chunk-W6SLZNRX.js.map +1 -0
- package/dist/{chunk-V3275BA7.js → chunk-XQAOHHXL.js} +20 -12
- package/dist/chunk-XQAOHHXL.js.map +1 -0
- package/dist/companies.d.cts +1 -1
- package/dist/companies.d.ts +1 -1
- package/dist/contacts.d.cts +1 -1
- package/dist/contacts.d.ts +1 -1
- package/dist/{context-CpLIDl0P.d.cts → context-DK8jg6y5.d.cts} +48 -2
- package/dist/{context-CpLIDl0P.d.ts → context-DK8jg6y5.d.ts} +48 -2
- package/dist/{customer-groups-DJVbdrEP.d.cts → customer-groups-D0OCm8kJ.d.cts} +1 -1
- package/dist/{customer-groups-DhpCTCTg.d.ts → customer-groups-WSt4aT62.d.ts} +1 -1
- package/dist/customer-groups.d.cts +2 -2
- package/dist/customer-groups.d.ts +2 -2
- package/dist/customer.d.cts +1 -1
- package/dist/customer.d.ts +1 -1
- package/dist/index.cjs +343 -146
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -7
- package/dist/index.d.ts +62 -7
- package/dist/index.js +169 -72
- package/dist/index.js.map +1 -1
- package/dist/locations.d.cts +1 -1
- package/dist/locations.d.ts +1 -1
- package/dist/media.cjs +38 -12
- package/dist/media.cjs.map +1 -1
- package/dist/media.d.cts +7 -2
- package/dist/media.d.ts +7 -2
- package/dist/media.js +2 -1
- package/dist/orders.cjs +71 -23
- package/dist/orders.cjs.map +1 -1
- package/dist/orders.d.cts +7 -1
- package/dist/orders.d.ts +7 -1
- package/dist/orders.js +2 -1
- package/dist/payment.d.cts +1 -1
- package/dist/payment.d.ts +1 -1
- package/dist/price.d.cts +1 -1
- package/dist/price.d.ts +1 -1
- package/dist/product.cjs +55 -14
- package/dist/product.cjs.map +1 -1
- package/dist/product.d.cts +4 -1
- package/dist/product.d.ts +4 -1
- package/dist/product.js +3 -2
- package/dist/segment.cjs +6 -0
- package/dist/segment.cjs.map +1 -1
- package/dist/segment.d.cts +1 -1
- package/dist/segment.d.ts +1 -1
- package/dist/segment.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-7W22KLUL.js.map +0 -1
- package/dist/chunk-D7HBM2DQ.js.map +0 -1
- package/dist/chunk-GWJ2U2CP.js.map +0 -1
- package/dist/chunk-OTG2S2L4.js.map +0 -1
- package/dist/chunk-P7G4LOOV.js.map +0 -1
- package/dist/chunk-V3275BA7.js.map +0 -1
- package/dist/chunk-W2KBVWJ2.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
# @viu/emporix-sdk
|
|
2
2
|
|
|
3
|
+
## 2.32.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#252](https://github.com/viuteam/emporix-sdk/pull/252) [`27623a1`](https://github.com/viuteam/emporix-sdk/commit/27623a1dc14ebfc24b973fb71e75e0d99c9f6fe6) Thanks [@amnael1](https://github.com/amnael1)! - feat(sdk): expose response headers to facades
|
|
8
|
+
|
|
9
|
+
`HttpClient.requestWithMeta` returns the parsed body together with the response
|
|
10
|
+
`Headers`, and `PaginatedItems` gains optional `totalCount`, `nextCursor` and
|
|
11
|
+
`prevCursor`. Nothing surfaces them yet; this is the groundwork that lets the
|
|
12
|
+
facades read Emporix's `X-Total-Count` and cursor headers at all.
|
|
13
|
+
|
|
14
|
+
`RequestOptions.query` also widens to accept booleans, so a facade can pass one
|
|
15
|
+
through instead of stringifying it at the call site.
|
|
16
|
+
|
|
17
|
+
- [#254](https://github.com/viuteam/emporix-sdk/pull/254) [`47570cd`](https://github.com/viuteam/emporix-sdk/commit/47570cdf2a5ab10bd17c385610367daef7aa73ee) Thanks [@amnael1](https://github.com/amnael1)! - feat(sdk): opt into absolute match counts on the list facades
|
|
18
|
+
|
|
19
|
+
Pass `totalCount: true` to any list facade to get `X-Total-Count` back as
|
|
20
|
+
`page.totalCount`, and an exact `hasNextPage` instead of the page-size guess.
|
|
21
|
+
Off by default: Emporix computes the count with a second query, so turning it
|
|
22
|
+
on for every list would be a silent cost on every storefront.
|
|
23
|
+
|
|
24
|
+
From React the four single-page list hooks accept the same flag — `useProducts`,
|
|
25
|
+
`useProductSearch`, `useCategories`, `useCategorySearch`. It is part of the query
|
|
26
|
+
key, so a totals request is never served a cached page without them. The
|
|
27
|
+
`*Infinite` hooks do not offer it: `hasNextPage` already terminates them.
|
|
28
|
+
|
|
29
|
+
Three facades deliberately keep the guess — `categories.productsIn`,
|
|
30
|
+
`segments.listMyProducts` and `segments.listMyCategories`. They page over an
|
|
31
|
+
assignments list and hydrate the hits in a second call, so a total there would
|
|
32
|
+
count assignments rather than the items returned.
|
|
33
|
+
|
|
34
|
+
- [#253](https://github.com/viuteam/emporix-sdk/pull/253) [`4aa20c0`](https://github.com/viuteam/emporix-sdk/commit/4aa20c00e854adb4cbf54ce9714adf5bc26120b7) Thanks [@amnael1](https://github.com/amnael1)! - feat(sdk): support cursor pagination on schema custom instances
|
|
35
|
+
|
|
36
|
+
`listInstances` and `searchInstances` now declare `next` / `prev`, return the
|
|
37
|
+
cursors the server sends back, and `searchInstances` finally forwards
|
|
38
|
+
`pageNumber`, `pageSize` and `sort` — it forwarded none of them and always
|
|
39
|
+
claimed `hasNextPage: false`, so a search could only ever return the server's
|
|
40
|
+
default first page. New `listAllInstances` iterates a whole type by cursor.
|
|
41
|
+
|
|
42
|
+
Note: `searchInstances` gained a third `query` parameter, so a positional `auth`
|
|
43
|
+
argument moves to fourth.
|
|
44
|
+
|
|
45
|
+
### Patch Changes
|
|
46
|
+
|
|
47
|
+
- [#250](https://github.com/viuteam/emporix-sdk/pull/250) [`9094d8e`](https://github.com/viuteam/emporix-sdk/commit/9094d8e447b45644f5c46f765efd8dfc77cc44a7) Thanks [@viu-release-bot](https://github.com/apps/viu-release-bot)! - chore(sdk): sync generated types with upstream Emporix API specs
|
|
48
|
+
|
|
49
|
+
Updated services: schema
|
|
50
|
+
|
|
3
51
|
## 2.31.1
|
|
4
52
|
|
|
5
53
|
### Patch Changes
|
package/dist/availability.cjs
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// src/core/paged.ts
|
|
4
|
+
function intHeader(headers, name) {
|
|
5
|
+
const raw = headers.get(name);
|
|
6
|
+
if (raw === null || raw.trim() === "") return void 0;
|
|
7
|
+
const n = Number(raw);
|
|
8
|
+
return Number.isInteger(n) && n >= 0 ? n : void 0;
|
|
9
|
+
}
|
|
10
|
+
async function requestPage(http, o, page) {
|
|
11
|
+
const { data, headers } = await http.requestWithMeta(
|
|
12
|
+
page.totalCount === true ? { ...o, headers: { ...o.headers ?? {}, "X-Total-Count": "true" } } : o
|
|
13
|
+
);
|
|
14
|
+
const items = data ?? [];
|
|
15
|
+
const totalCount = intHeader(headers, "X-Total-Count");
|
|
16
|
+
const nextCursor = headers.get("X-Next-Cursor") ?? void 0;
|
|
17
|
+
const prevCursor = headers.get("X-Prev-Cursor") ?? void 0;
|
|
18
|
+
const hasNextPage = nextCursor !== void 0 ? true : totalCount !== void 0 ? page.pageNumber * page.pageSize < totalCount : items.length === page.pageSize;
|
|
19
|
+
return {
|
|
20
|
+
items,
|
|
21
|
+
pageNumber: page.pageNumber,
|
|
22
|
+
pageSize: page.pageSize,
|
|
23
|
+
hasNextPage,
|
|
24
|
+
...totalCount === void 0 ? {} : { totalCount },
|
|
25
|
+
...nextCursor === void 0 ? {} : { nextCursor },
|
|
26
|
+
...prevCursor === void 0 ? {} : { prevCursor }
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
3
30
|
// src/core/errors.ts
|
|
4
31
|
var REDACTED_BODY_KEYS = /* @__PURE__ */ new Set([
|
|
5
32
|
"access_token",
|
|
@@ -105,18 +132,25 @@ var AvailabilityService = class {
|
|
|
105
132
|
async listForSite(siteCode, params = {}, auth = ANON) {
|
|
106
133
|
const pageNumber = params.pageNumber ?? 1;
|
|
107
134
|
const pageSize = params.pageSize ?? 50;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
135
|
+
return requestPage(
|
|
136
|
+
this.ctx.http,
|
|
137
|
+
{
|
|
138
|
+
method: "GET",
|
|
139
|
+
path: `/availability/${this.ctx.tenant}/availability/site/${encodeURIComponent(siteCode)}`,
|
|
140
|
+
query: {
|
|
141
|
+
pageNumber,
|
|
142
|
+
pageSize,
|
|
143
|
+
...params.q === void 0 ? {} : { q: params.q },
|
|
144
|
+
...params.sort === void 0 ? {} : { sort: params.sort }
|
|
145
|
+
},
|
|
146
|
+
auth
|
|
147
|
+
},
|
|
148
|
+
{
|
|
112
149
|
pageNumber,
|
|
113
150
|
pageSize,
|
|
114
|
-
...params.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
auth
|
|
118
|
-
});
|
|
119
|
-
return { items, pageNumber, pageSize, hasNextPage: items.length === pageSize };
|
|
151
|
+
...params.totalCount === void 0 ? {} : { totalCount: params.totalCount }
|
|
152
|
+
}
|
|
153
|
+
);
|
|
120
154
|
}
|
|
121
155
|
// --- Admin writes. Default auth: service. ---
|
|
122
156
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/errors.ts","../src/services/availability.ts"],"names":[],"mappings":"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","file":"availability.cjs","sourcesContent":["/** Keys whose values are stripped from any serialised error body. */\nconst REDACTED_BODY_KEYS = new Set([\n \"access_token\", \"refresh_token\", \"token\", \"customertoken\", \"saastoken\",\n \"secret\", \"client_secret\", \"authorization\", \"password\",\n]);\n\nfunction scrub(body: unknown): unknown {\n if (Array.isArray(body)) return body.map(scrub);\n if (body && typeof body === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(body as Record<string, unknown>)) {\n out[k] = REDACTED_BODY_KEYS.has(k.toLowerCase()) ? \"***redacted***\" : scrub(v);\n }\n return out;\n }\n return body;\n}\n\n/** Base class for every error thrown by the SDK. */\nexport class EmporixError extends Error {\n readonly status: number | undefined;\n readonly body: unknown;\n constructor(message: string, status?: number, body?: unknown) {\n super(message);\n this.name = new.target.name;\n this.status = status;\n this.body = body;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n /** Safe serialisation — token-like body fields are redacted. */\n toJSON(): Record<string, unknown> {\n return { name: this.name, message: this.message, status: this.status, body: scrub(this.body) };\n }\n}\n\n/** 401 — authentication failed or token expired. */\nexport class EmporixAuthError extends EmporixError {}\n/** 403 — authenticated but not permitted. */\nexport class EmporixForbiddenError extends EmporixError {}\n/** 404 — resource not found. */\nexport class EmporixNotFoundError extends EmporixError {}\n/** 400/422 — request validation failed. */\nexport class EmporixValidationError extends EmporixError {}\n/** 5xx — server-side failure. */\nexport class EmporixServerError extends EmporixError {}\n/** Request aborted by the configured connect/read timeout. No HTTP status. */\nexport class EmporixTimeoutError extends EmporixError {}\n/** DNS/TLS/connection-level failure before or during the exchange. No HTTP status. */\nexport class EmporixNetworkError extends EmporixError {}\n\n/**\n * 403 with a `missing scope: <name>` hint in the body's `details` array.\n * Subclasses {@link EmporixForbiddenError} so existing 403 catches still work.\n */\nexport class EmporixInsufficientScopeError extends EmporixForbiddenError {\n readonly requiredScope: string | undefined;\n constructor(message: string, status: number, body: unknown, requiredScope?: string) {\n super(message, status, body);\n this.requiredScope = requiredScope;\n }\n}\n\nconst SCOPE_HINT_RE = /missing scope[: ]+([a-z0-9._-]+)/i;\n\nfunction extractRequiredScope(body: unknown): string | undefined {\n if (body && typeof body === \"object\" && \"details\" in body) {\n const details = (body as { details?: unknown }).details;\n if (Array.isArray(details)) {\n for (const d of details) {\n if (typeof d === \"string\") {\n const m = d.match(SCOPE_HINT_RE);\n if (m) return m[1];\n }\n }\n }\n }\n return undefined;\n}\n\n/** Maps an HTTP status to the matching {@link EmporixError} subclass. */\nexport function errorFromResponse(status: number, message: string, body: unknown): EmporixError {\n if (status === 401) return new EmporixAuthError(message, status, body);\n if (status === 403) {\n const scope = extractRequiredScope(body);\n if (scope) return new EmporixInsufficientScopeError(message, status, body, scope);\n return new EmporixForbiddenError(message, status, body);\n }\n if (status === 404) return new EmporixNotFoundError(message, status, body);\n if (status === 400 || status === 422) return new EmporixValidationError(message, status, body);\n if (status >= 500) return new EmporixServerError(message, status, body);\n return new EmporixError(message, status, body);\n}\n","import type { ClientContext, PaginatedItems } from \"../core/context\";\nimport type { AuthContext } from \"../core/auth\";\nimport { EmporixNotFoundError } from \"../core/errors\";\nimport type {\n Availability,\n AvailabilityInput,\n AvailabilityCreated,\n AvailabilityBulkInput,\n AvailabilityBulkDeleteInput,\n AvailabilityBulkResult,\n} from \"./availability-types\";\n\nexport type {\n Availability,\n AvailabilityInput,\n AvailabilityCreated,\n AvailabilityBulkInput,\n AvailabilityBulkDeleteInput,\n AvailabilityBulkResult,\n} from \"./availability-types\";\n\n/** Shared options for {@link AvailabilityService} reads. */\nexport interface AvailabilityOptions {\n /**\n * When `true`, a product with no availability record resolves to a default\n * `{ available: true }` instead of throwing (single `get`) / being marked\n * unavailable (`getMany`). Off by default — opt in for tenants that sell\n * without stock management.\n */\n defaultAvailableOnNotFound?: boolean;\n}\n\nconst ANON: AuthContext = { kind: \"anonymous\" };\nconst SERVICE: AuthContext = { kind: \"service\" };\n\n/**\n * Reads product availability per site. Default auth is anonymous (like\n * `PriceService.matchByContext`); pass a customer/raw/service context to use a\n * different token. Requires the `availability.availability_view` scope on\n * whichever token is used.\n */\nexport class AvailabilityService {\n static readonly channel = \"availability\" as const;\n constructor(private readonly ctx: ClientContext) {}\n\n /**\n * Single product. Resolves the availability record, or — when\n * `opts.defaultAvailableOnNotFound` is set — a default available record on 404.\n */\n async get(\n productId: string,\n siteCode: string,\n auth: AuthContext = ANON,\n opts: AvailabilityOptions = {},\n ): Promise<Availability> {\n try {\n return await this.ctx.http.request<Availability>({\n method: \"GET\",\n path: `/availability/${this.ctx.tenant}/availability/${encodeURIComponent(\n productId,\n )}/${encodeURIComponent(siteCode)}`,\n auth,\n });\n } catch (err) {\n if (err instanceof EmporixNotFoundError && opts.defaultAvailableOnNotFound) {\n return { productId, site: siteCode, available: true };\n }\n throw err;\n }\n }\n\n /**\n * Batch read via `POST .../availability/search` (one request). Products with\n * no availability record are absent from the response; each is synthesized as\n * `{ available: false }` (or `{ available: true }` when\n * `opts.defaultAvailableOnNotFound` is set). The result preserves input order\n * and length. An empty `productIds` resolves to `[]` without a request.\n */\n async getMany(\n productIds: string[],\n siteCode: string,\n auth: AuthContext = ANON,\n opts: AvailabilityOptions = {},\n ): Promise<Availability[]> {\n if (productIds.length === 0) return [];\n const found = await this.ctx.http.request<Availability[]>({\n method: \"POST\",\n path: `/availability/${this.ctx.tenant}/availability/search`,\n auth,\n query: { site: siteCode, pageSize: productIds.length },\n body: productIds,\n idempotent: true, // pure read over POST — safe to replay on 5xx/429\n });\n const byId = new Map<string, Availability>();\n for (const a of found) if (a.productId) byId.set(a.productId, a);\n return productIds.map(\n (id) =>\n byId.get(id) ?? {\n productId: id,\n site: siteCode,\n available: Boolean(opts.defaultAvailableOnNotFound),\n },\n );\n }\n\n /**\n * Lists every availability record for a site (`GET /availability/site/{site}`),\n * wrapped into `PaginatedItems`. Default auth: anonymous.\n */\n async listForSite(\n siteCode: string,\n params: { pageNumber?: number; pageSize?: number; q?: string; sort?: string } = {},\n auth: AuthContext = ANON,\n ): Promise<PaginatedItems<Availability>> {\n const pageNumber = params.pageNumber ?? 1;\n const pageSize = params.pageSize ?? 50;\n const items = await this.ctx.http.request<Availability[]>({\n method: \"GET\",\n path: `/availability/${this.ctx.tenant}/availability/site/${encodeURIComponent(siteCode)}`,\n query: {\n pageNumber,\n pageSize,\n ...(params.q === undefined ? {} : { q: params.q }),\n ...(params.sort === undefined ? {} : { sort: params.sort }),\n },\n auth,\n });\n return { items, pageNumber, pageSize, hasNextPage: items.length === pageSize };\n }\n\n // --- Admin writes. Default auth: service. ---\n\n /**\n * Creates an availability record for a product on a site\n * (`POST /availability/{productId}/{site}`). Responds 409 when the record\n * already exists — use {@link update} to upsert. Default auth: service.\n */\n async create(\n productId: string,\n siteCode: string,\n input: AvailabilityInput,\n auth: AuthContext = SERVICE,\n ): Promise<AvailabilityCreated> {\n return this.ctx.http.request<AvailabilityCreated>({\n method: \"POST\",\n path: `/availability/${this.ctx.tenant}/availability/${encodeURIComponent(\n productId,\n )}/${encodeURIComponent(siteCode)}`,\n body: input,\n auth,\n });\n }\n\n /**\n * Upserts a product's availability on a site\n * (`PUT /availability/{productId}/{site}`). Returns the created record's id\n * on 201 and nothing on 204. This endpoint has no PATCH counterpart.\n * Default auth: service.\n */\n async update(\n productId: string,\n siteCode: string,\n input: AvailabilityInput,\n auth: AuthContext = SERVICE,\n ): Promise<AvailabilityCreated | void> {\n return this.ctx.http.request<AvailabilityCreated | void>({\n method: \"PUT\",\n path: `/availability/${this.ctx.tenant}/availability/${encodeURIComponent(\n productId,\n )}/${encodeURIComponent(siteCode)}`,\n body: input,\n auth,\n });\n }\n\n /**\n * Deletes a product's availability on a site\n * (`DELETE /availability/{productId}/{site}`). Default auth: service.\n */\n async delete(productId: string, siteCode: string, auth: AuthContext = SERVICE): Promise<void> {\n await this.ctx.http.request<void>({\n method: \"DELETE\",\n path: `/availability/${this.ctx.tenant}/availability/${encodeURIComponent(\n productId,\n )}/${encodeURIComponent(siteCode)}`,\n auth,\n });\n }\n\n /**\n * Bulk-creates availability records (`POST /availability/bulk`). Responds 207\n * Multi-Status: partial failures do **not** throw — inspect each entry.\n *\n * `options.vendorId` limits the operation to a vendor's products. It is sent\n * as the `vendor-id` header. **Note:** the OpenAPI schema spells this header\n * `venodr-id`, which is an evident upstream typo (the body field is\n * `vendorId`); the SDK sends the corrected name. Unverified against the live\n * API — if the service really expects the misspelling, the filter silently\n * has no effect.\n *\n * Default auth: service.\n */\n async bulkCreate(\n input: AvailabilityBulkInput[],\n options: { vendorId?: string } = {},\n auth: AuthContext = SERVICE,\n ): Promise<AvailabilityBulkResult[]> {\n return this.ctx.http.request<AvailabilityBulkResult[]>({\n method: \"POST\",\n path: `/availability/${this.ctx.tenant}/availability/bulk`,\n ...(options.vendorId === undefined ? {} : { headers: { \"vendor-id\": options.vendorId } }),\n body: input,\n auth,\n });\n }\n\n /**\n * Bulk-updates availability records (`PUT /availability/bulk`). Responds 207\n * Multi-Status: partial failures do **not** throw — inspect each entry. See\n * {@link bulkCreate} for the `vendorId` header caveat. Default auth: service.\n */\n async bulkUpdate(\n input: AvailabilityBulkInput[],\n options: { vendorId?: string } = {},\n auth: AuthContext = SERVICE,\n ): Promise<AvailabilityBulkResult[]> {\n return this.ctx.http.request<AvailabilityBulkResult[]>({\n method: \"PUT\",\n path: `/availability/${this.ctx.tenant}/availability/bulk`,\n ...(options.vendorId === undefined ? {} : { headers: { \"vendor-id\": options.vendorId } }),\n body: input,\n auth,\n });\n }\n\n /**\n * Bulk-deletes availability records (`DELETE /availability/bulk`). Unusually\n * for a DELETE, this endpoint takes a body listing the records to remove.\n * Responds 207 Multi-Status: partial failures do **not** throw — inspect each\n * entry. See {@link bulkCreate} for the `vendorId` header caveat. Default\n * auth: service.\n */\n async bulkDelete(\n input: AvailabilityBulkDeleteInput[],\n options: { vendorId?: string } = {},\n auth: AuthContext = SERVICE,\n ): Promise<AvailabilityBulkResult[]> {\n return this.ctx.http.request<AvailabilityBulkResult[]>({\n method: \"DELETE\",\n path: `/availability/${this.ctx.tenant}/availability/bulk`,\n ...(options.vendorId === undefined ? {} : { headers: { \"vendor-id\": options.vendorId } }),\n body: input,\n auth,\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/paged.ts","../src/core/errors.ts","../src/services/availability.ts"],"names":[],"mappings":"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","file":"availability.cjs","sourcesContent":["import type { PaginatedItems } from \"./context\";\nimport type { HttpClient, RequestOptions } from \"./http\";\n\n/** Pagination inputs for {@link requestPage}. */\nexport interface PageParams {\n /** 1-based, as Emporix counts. */\n pageNumber: number;\n pageSize: number;\n /**\n * Ask Emporix for the absolute match count via the `X-Total-Count: true`\n * request header.\n *\n * Off by default and opt-in per call, not a client-wide setting: the count\n * costs the server a second query, and defaulting it on would put that cost\n * on every list every storefront issues.\n */\n totalCount?: boolean;\n}\n\n/**\n * Reads a non-negative integer header, or `undefined` when it is missing or is\n * not one. A malformed value must not reach the `hasNextPage` arithmetic —\n * `Number(\"lots\")` is `NaN`, and every comparison against `NaN` is `false`,\n * which would silently report \"last page\" on every page.\n */\nfunction intHeader(headers: Headers, name: string): number | undefined {\n const raw = headers.get(name);\n if (raw === null || raw.trim() === \"\") return undefined;\n const n = Number(raw);\n return Number.isInteger(n) && n >= 0 ? n : undefined;\n}\n\n/**\n * Issues one page of a list endpoint and assembles {@link PaginatedItems} from\n * the body plus Emporix's pagination response headers.\n *\n * Cursors travel in opposite directions: the caller sends one as the `next` or\n * `prev` **query parameter** (so it belongs in `o.query`), and the server\n * returns the following one as the `X-Next-Cursor` **response header**. This\n * helper only ever reads them.\n */\nexport async function requestPage<T>(\n http: HttpClient,\n o: RequestOptions,\n page: PageParams,\n): Promise<PaginatedItems<T>> {\n const { data, headers } = await http.requestWithMeta<T[]>(\n page.totalCount === true\n ? { ...o, headers: { ...(o.headers ?? {}), \"X-Total-Count\": \"true\" } }\n : o,\n );\n\n // A 204 or empty body parses to `undefined`. Facades used to index straight\n // into the result and would throw; an empty page is the honest answer.\n const items = data ?? [];\n const totalCount = intHeader(headers, \"X-Total-Count\");\n const nextCursor = headers.get(\"X-Next-Cursor\") ?? undefined;\n const prevCursor = headers.get(\"X-Prev-Cursor\") ?? undefined;\n\n // Three tiers, most precise first. Tier 1 is ONE-DIRECTIONAL on purpose: only\n // two endpoints in the whole API emit a cursor header, so its absence says\n // nothing at all and has to fall through to the other two.\n const hasNextPage =\n nextCursor !== undefined\n ? true\n : totalCount !== undefined\n ? page.pageNumber * page.pageSize < totalCount\n : items.length === page.pageSize;\n\n // Spread conditionally — `exactOptionalPropertyTypes` rejects an explicit\n // `undefined` for an optional property.\n return {\n items,\n pageNumber: page.pageNumber,\n pageSize: page.pageSize,\n hasNextPage,\n ...(totalCount === undefined ? {} : { totalCount }),\n ...(nextCursor === undefined ? {} : { nextCursor }),\n ...(prevCursor === undefined ? {} : { prevCursor }),\n };\n}\n","/** Keys whose values are stripped from any serialised error body. */\nconst REDACTED_BODY_KEYS = new Set([\n \"access_token\", \"refresh_token\", \"token\", \"customertoken\", \"saastoken\",\n \"secret\", \"client_secret\", \"authorization\", \"password\",\n]);\n\nfunction scrub(body: unknown): unknown {\n if (Array.isArray(body)) return body.map(scrub);\n if (body && typeof body === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(body as Record<string, unknown>)) {\n out[k] = REDACTED_BODY_KEYS.has(k.toLowerCase()) ? \"***redacted***\" : scrub(v);\n }\n return out;\n }\n return body;\n}\n\n/** Base class for every error thrown by the SDK. */\nexport class EmporixError extends Error {\n readonly status: number | undefined;\n readonly body: unknown;\n constructor(message: string, status?: number, body?: unknown) {\n super(message);\n this.name = new.target.name;\n this.status = status;\n this.body = body;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n /** Safe serialisation — token-like body fields are redacted. */\n toJSON(): Record<string, unknown> {\n return { name: this.name, message: this.message, status: this.status, body: scrub(this.body) };\n }\n}\n\n/** 401 — authentication failed or token expired. */\nexport class EmporixAuthError extends EmporixError {}\n/** 403 — authenticated but not permitted. */\nexport class EmporixForbiddenError extends EmporixError {}\n/** 404 — resource not found. */\nexport class EmporixNotFoundError extends EmporixError {}\n/** 400/422 — request validation failed. */\nexport class EmporixValidationError extends EmporixError {}\n/** 5xx — server-side failure. */\nexport class EmporixServerError extends EmporixError {}\n/** Request aborted by the configured connect/read timeout. No HTTP status. */\nexport class EmporixTimeoutError extends EmporixError {}\n/** DNS/TLS/connection-level failure before or during the exchange. No HTTP status. */\nexport class EmporixNetworkError extends EmporixError {}\n\n/**\n * 403 with a `missing scope: <name>` hint in the body's `details` array.\n * Subclasses {@link EmporixForbiddenError} so existing 403 catches still work.\n */\nexport class EmporixInsufficientScopeError extends EmporixForbiddenError {\n readonly requiredScope: string | undefined;\n constructor(message: string, status: number, body: unknown, requiredScope?: string) {\n super(message, status, body);\n this.requiredScope = requiredScope;\n }\n}\n\nconst SCOPE_HINT_RE = /missing scope[: ]+([a-z0-9._-]+)/i;\n\nfunction extractRequiredScope(body: unknown): string | undefined {\n if (body && typeof body === \"object\" && \"details\" in body) {\n const details = (body as { details?: unknown }).details;\n if (Array.isArray(details)) {\n for (const d of details) {\n if (typeof d === \"string\") {\n const m = d.match(SCOPE_HINT_RE);\n if (m) return m[1];\n }\n }\n }\n }\n return undefined;\n}\n\n/** Maps an HTTP status to the matching {@link EmporixError} subclass. */\nexport function errorFromResponse(status: number, message: string, body: unknown): EmporixError {\n if (status === 401) return new EmporixAuthError(message, status, body);\n if (status === 403) {\n const scope = extractRequiredScope(body);\n if (scope) return new EmporixInsufficientScopeError(message, status, body, scope);\n return new EmporixForbiddenError(message, status, body);\n }\n if (status === 404) return new EmporixNotFoundError(message, status, body);\n if (status === 400 || status === 422) return new EmporixValidationError(message, status, body);\n if (status >= 500) return new EmporixServerError(message, status, body);\n return new EmporixError(message, status, body);\n}\n","import type { ClientContext, PaginatedItems } from \"../core/context\";\nimport { requestPage } from \"../core/paged\";\nimport type { AuthContext } from \"../core/auth\";\nimport { EmporixNotFoundError } from \"../core/errors\";\nimport type {\n Availability,\n AvailabilityInput,\n AvailabilityCreated,\n AvailabilityBulkInput,\n AvailabilityBulkDeleteInput,\n AvailabilityBulkResult,\n} from \"./availability-types\";\n\nexport type {\n Availability,\n AvailabilityInput,\n AvailabilityCreated,\n AvailabilityBulkInput,\n AvailabilityBulkDeleteInput,\n AvailabilityBulkResult,\n} from \"./availability-types\";\n\n/** Shared options for {@link AvailabilityService} reads. */\nexport interface AvailabilityOptions {\n /**\n * When `true`, a product with no availability record resolves to a default\n * `{ available: true }` instead of throwing (single `get`) / being marked\n * unavailable (`getMany`). Off by default — opt in for tenants that sell\n * without stock management.\n */\n defaultAvailableOnNotFound?: boolean;\n}\n\nconst ANON: AuthContext = { kind: \"anonymous\" };\nconst SERVICE: AuthContext = { kind: \"service\" };\n\n/**\n * Reads product availability per site. Default auth is anonymous (like\n * `PriceService.matchByContext`); pass a customer/raw/service context to use a\n * different token. Requires the `availability.availability_view` scope on\n * whichever token is used.\n */\nexport class AvailabilityService {\n static readonly channel = \"availability\" as const;\n constructor(private readonly ctx: ClientContext) {}\n\n /**\n * Single product. Resolves the availability record, or — when\n * `opts.defaultAvailableOnNotFound` is set — a default available record on 404.\n */\n async get(\n productId: string,\n siteCode: string,\n auth: AuthContext = ANON,\n opts: AvailabilityOptions = {},\n ): Promise<Availability> {\n try {\n return await this.ctx.http.request<Availability>({\n method: \"GET\",\n path: `/availability/${this.ctx.tenant}/availability/${encodeURIComponent(\n productId,\n )}/${encodeURIComponent(siteCode)}`,\n auth,\n });\n } catch (err) {\n if (err instanceof EmporixNotFoundError && opts.defaultAvailableOnNotFound) {\n return { productId, site: siteCode, available: true };\n }\n throw err;\n }\n }\n\n /**\n * Batch read via `POST .../availability/search` (one request). Products with\n * no availability record are absent from the response; each is synthesized as\n * `{ available: false }` (or `{ available: true }` when\n * `opts.defaultAvailableOnNotFound` is set). The result preserves input order\n * and length. An empty `productIds` resolves to `[]` without a request.\n */\n async getMany(\n productIds: string[],\n siteCode: string,\n auth: AuthContext = ANON,\n opts: AvailabilityOptions = {},\n ): Promise<Availability[]> {\n if (productIds.length === 0) return [];\n const found = await this.ctx.http.request<Availability[]>({\n method: \"POST\",\n path: `/availability/${this.ctx.tenant}/availability/search`,\n auth,\n query: { site: siteCode, pageSize: productIds.length },\n body: productIds,\n idempotent: true, // pure read over POST — safe to replay on 5xx/429\n });\n const byId = new Map<string, Availability>();\n for (const a of found) if (a.productId) byId.set(a.productId, a);\n return productIds.map(\n (id) =>\n byId.get(id) ?? {\n productId: id,\n site: siteCode,\n available: Boolean(opts.defaultAvailableOnNotFound),\n },\n );\n }\n\n /**\n * Lists every availability record for a site (`GET /availability/site/{site}`),\n * wrapped into `PaginatedItems`. Default auth: anonymous.\n */\n async listForSite(\n siteCode: string,\n params: { pageNumber?: number; pageSize?: number; q?: string; sort?: string; totalCount?: boolean } = {},\n auth: AuthContext = ANON,\n ): Promise<PaginatedItems<Availability>> {\n const pageNumber = params.pageNumber ?? 1;\n const pageSize = params.pageSize ?? 50;\n return requestPage<Availability>(\n this.ctx.http,\n {\n method: \"GET\",\n path: `/availability/${this.ctx.tenant}/availability/site/${encodeURIComponent(siteCode)}`,\n query: {\n pageNumber,\n pageSize,\n ...(params.q === undefined ? {} : { q: params.q }),\n ...(params.sort === undefined ? {} : { sort: params.sort }),\n },\n auth,\n },\n {\n pageNumber,\n pageSize,\n ...(params.totalCount === undefined ? {} : { totalCount: params.totalCount }),\n },\n );\n }\n\n // --- Admin writes. Default auth: service. ---\n\n /**\n * Creates an availability record for a product on a site\n * (`POST /availability/{productId}/{site}`). Responds 409 when the record\n * already exists — use {@link update} to upsert. Default auth: service.\n */\n async create(\n productId: string,\n siteCode: string,\n input: AvailabilityInput,\n auth: AuthContext = SERVICE,\n ): Promise<AvailabilityCreated> {\n return this.ctx.http.request<AvailabilityCreated>({\n method: \"POST\",\n path: `/availability/${this.ctx.tenant}/availability/${encodeURIComponent(\n productId,\n )}/${encodeURIComponent(siteCode)}`,\n body: input,\n auth,\n });\n }\n\n /**\n * Upserts a product's availability on a site\n * (`PUT /availability/{productId}/{site}`). Returns the created record's id\n * on 201 and nothing on 204. This endpoint has no PATCH counterpart.\n * Default auth: service.\n */\n async update(\n productId: string,\n siteCode: string,\n input: AvailabilityInput,\n auth: AuthContext = SERVICE,\n ): Promise<AvailabilityCreated | void> {\n return this.ctx.http.request<AvailabilityCreated | void>({\n method: \"PUT\",\n path: `/availability/${this.ctx.tenant}/availability/${encodeURIComponent(\n productId,\n )}/${encodeURIComponent(siteCode)}`,\n body: input,\n auth,\n });\n }\n\n /**\n * Deletes a product's availability on a site\n * (`DELETE /availability/{productId}/{site}`). Default auth: service.\n */\n async delete(productId: string, siteCode: string, auth: AuthContext = SERVICE): Promise<void> {\n await this.ctx.http.request<void>({\n method: \"DELETE\",\n path: `/availability/${this.ctx.tenant}/availability/${encodeURIComponent(\n productId,\n )}/${encodeURIComponent(siteCode)}`,\n auth,\n });\n }\n\n /**\n * Bulk-creates availability records (`POST /availability/bulk`). Responds 207\n * Multi-Status: partial failures do **not** throw — inspect each entry.\n *\n * `options.vendorId` limits the operation to a vendor's products. It is sent\n * as the `vendor-id` header. **Note:** the OpenAPI schema spells this header\n * `venodr-id`, which is an evident upstream typo (the body field is\n * `vendorId`); the SDK sends the corrected name. Unverified against the live\n * API — if the service really expects the misspelling, the filter silently\n * has no effect.\n *\n * Default auth: service.\n */\n async bulkCreate(\n input: AvailabilityBulkInput[],\n options: { vendorId?: string } = {},\n auth: AuthContext = SERVICE,\n ): Promise<AvailabilityBulkResult[]> {\n return this.ctx.http.request<AvailabilityBulkResult[]>({\n method: \"POST\",\n path: `/availability/${this.ctx.tenant}/availability/bulk`,\n ...(options.vendorId === undefined ? {} : { headers: { \"vendor-id\": options.vendorId } }),\n body: input,\n auth,\n });\n }\n\n /**\n * Bulk-updates availability records (`PUT /availability/bulk`). Responds 207\n * Multi-Status: partial failures do **not** throw — inspect each entry. See\n * {@link bulkCreate} for the `vendorId` header caveat. Default auth: service.\n */\n async bulkUpdate(\n input: AvailabilityBulkInput[],\n options: { vendorId?: string } = {},\n auth: AuthContext = SERVICE,\n ): Promise<AvailabilityBulkResult[]> {\n return this.ctx.http.request<AvailabilityBulkResult[]>({\n method: \"PUT\",\n path: `/availability/${this.ctx.tenant}/availability/bulk`,\n ...(options.vendorId === undefined ? {} : { headers: { \"vendor-id\": options.vendorId } }),\n body: input,\n auth,\n });\n }\n\n /**\n * Bulk-deletes availability records (`DELETE /availability/bulk`). Unusually\n * for a DELETE, this endpoint takes a body listing the records to remove.\n * Responds 207 Multi-Status: partial failures do **not** throw — inspect each\n * entry. See {@link bulkCreate} for the `vendorId` header caveat. Default\n * auth: service.\n */\n async bulkDelete(\n input: AvailabilityBulkDeleteInput[],\n options: { vendorId?: string } = {},\n auth: AuthContext = SERVICE,\n ): Promise<AvailabilityBulkResult[]> {\n return this.ctx.http.request<AvailabilityBulkResult[]>({\n method: \"DELETE\",\n path: `/availability/${this.ctx.tenant}/availability/bulk`,\n ...(options.vendorId === undefined ? {} : { headers: { \"vendor-id\": options.vendorId } }),\n body: input,\n auth,\n });\n }\n}\n"]}
|
package/dist/availability.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-DK8jg6y5.cjs';
|
|
2
2
|
|
|
3
3
|
type AvailabilityDto = {
|
|
4
4
|
/**
|
|
@@ -292,6 +292,7 @@ declare class AvailabilityService {
|
|
|
292
292
|
pageSize?: number;
|
|
293
293
|
q?: string;
|
|
294
294
|
sort?: string;
|
|
295
|
+
totalCount?: boolean;
|
|
295
296
|
}, auth?: AuthContext): Promise<PaginatedItems<Availability>>;
|
|
296
297
|
/**
|
|
297
298
|
* Creates an availability record for a product on a site
|
package/dist/availability.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-DK8jg6y5.js';
|
|
2
2
|
|
|
3
3
|
type AvailabilityDto = {
|
|
4
4
|
/**
|
|
@@ -292,6 +292,7 @@ declare class AvailabilityService {
|
|
|
292
292
|
pageSize?: number;
|
|
293
293
|
q?: string;
|
|
294
294
|
sort?: string;
|
|
295
|
+
totalCount?: boolean;
|
|
295
296
|
}, auth?: AuthContext): Promise<PaginatedItems<Availability>>;
|
|
296
297
|
/**
|
|
297
298
|
* Creates an availability record for a product on a site
|
package/dist/availability.js
CHANGED
package/dist/cart.d.cts
CHANGED
package/dist/cart.d.ts
CHANGED
package/dist/category.cjs
CHANGED
|
@@ -11,6 +11,33 @@ async function* iterateAll(fetchPage, start = 1) {
|
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
// src/core/paged.ts
|
|
15
|
+
function intHeader(headers, name) {
|
|
16
|
+
const raw = headers.get(name);
|
|
17
|
+
if (raw === null || raw.trim() === "") return void 0;
|
|
18
|
+
const n = Number(raw);
|
|
19
|
+
return Number.isInteger(n) && n >= 0 ? n : void 0;
|
|
20
|
+
}
|
|
21
|
+
async function requestPage(http, o, page) {
|
|
22
|
+
const { data, headers } = await http.requestWithMeta(
|
|
23
|
+
page.totalCount === true ? { ...o, headers: { ...o.headers ?? {}, "X-Total-Count": "true" } } : o
|
|
24
|
+
);
|
|
25
|
+
const items = data ?? [];
|
|
26
|
+
const totalCount = intHeader(headers, "X-Total-Count");
|
|
27
|
+
const nextCursor = headers.get("X-Next-Cursor") ?? void 0;
|
|
28
|
+
const prevCursor = headers.get("X-Prev-Cursor") ?? void 0;
|
|
29
|
+
const hasNextPage = nextCursor !== void 0 ? true : totalCount !== void 0 ? page.pageNumber * page.pageSize < totalCount : items.length === page.pageSize;
|
|
30
|
+
return {
|
|
31
|
+
items,
|
|
32
|
+
pageNumber: page.pageNumber,
|
|
33
|
+
pageSize: page.pageSize,
|
|
34
|
+
hasNextPage,
|
|
35
|
+
...totalCount === void 0 ? {} : { totalCount },
|
|
36
|
+
...nextCursor === void 0 ? {} : { nextCursor },
|
|
37
|
+
...prevCursor === void 0 ? {} : { prevCursor }
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
14
41
|
// src/core/query.ts
|
|
15
42
|
function resolveQuery(q, cap) {
|
|
16
43
|
if (typeof q === "string") return q;
|
|
@@ -43,13 +70,20 @@ var CategoryService = class {
|
|
|
43
70
|
async list(params = {}, auth = ANON) {
|
|
44
71
|
const pageNumber = params.pageNumber ?? 1;
|
|
45
72
|
const pageSize = params.pageSize ?? 50;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
73
|
+
return requestPage(
|
|
74
|
+
this.ctx.http,
|
|
75
|
+
{
|
|
76
|
+
method: "GET",
|
|
77
|
+
path: `/category/${this.ctx.tenant}/categories`,
|
|
78
|
+
query: { pageNumber, pageSize },
|
|
79
|
+
auth
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
pageNumber,
|
|
83
|
+
pageSize,
|
|
84
|
+
...params.totalCount === void 0 ? {} : { totalCount: params.totalCount }
|
|
85
|
+
}
|
|
86
|
+
);
|
|
53
87
|
}
|
|
54
88
|
/**
|
|
55
89
|
* Searches categories by a `q` filter — a raw Emporix DSL string or a built
|
|
@@ -60,13 +94,20 @@ var CategoryService = class {
|
|
|
60
94
|
const q = resolveQuery(query, { compoundLogicalQuery: false });
|
|
61
95
|
const pageNumber = params.pageNumber ?? 1;
|
|
62
96
|
const pageSize = params.pageSize ?? 50;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
97
|
+
return requestPage(
|
|
98
|
+
this.ctx.http,
|
|
99
|
+
{
|
|
100
|
+
method: "GET",
|
|
101
|
+
path: `/category/${this.ctx.tenant}/categories`,
|
|
102
|
+
query: { q, pageNumber, pageSize },
|
|
103
|
+
auth
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
pageNumber,
|
|
107
|
+
pageSize,
|
|
108
|
+
...params.totalCount === void 0 ? {} : { totalCount: params.totalCount }
|
|
109
|
+
}
|
|
110
|
+
);
|
|
70
111
|
}
|
|
71
112
|
/** Async-iterates every category across pages. */
|
|
72
113
|
listAll(params = {}, auth = ANON) {
|
|
@@ -136,6 +177,12 @@ var CategoryService = class {
|
|
|
136
177
|
* references, and resolves them to full products via `/products/search`.
|
|
137
178
|
* `hasNextPage` reflects the assignments page (the source of truth for
|
|
138
179
|
* pagination).
|
|
180
|
+
*
|
|
181
|
+
* No `totalCount` opt-in here, deliberately. `X-Total-Count` on the
|
|
182
|
+
* assignments request would count **assignments** — including the `CATEGORY`
|
|
183
|
+
* references filtered out below — not the products this returns. A number
|
|
184
|
+
* that is wrong in the way that is hardest to notice. Same reason
|
|
185
|
+
* `segments.listMyProducts` stays on the guess.
|
|
139
186
|
*/
|
|
140
187
|
async productsIn(categoryId, params = {}, auth = ANON) {
|
|
141
188
|
const pageNumber = params.pageNumber ?? 1;
|
|
@@ -277,22 +324,29 @@ var CategoryService = class {
|
|
|
277
324
|
const q = resolveQuery(query, { compoundLogicalQuery: false });
|
|
278
325
|
const pageNumber = params.pageNumber ?? 1;
|
|
279
326
|
const pageSize = params.pageSize ?? 50;
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
327
|
+
return requestPage(
|
|
328
|
+
this.ctx.http,
|
|
329
|
+
{
|
|
330
|
+
method: "POST",
|
|
331
|
+
path: `/category/${this.ctx.tenant}/categories/search`,
|
|
332
|
+
query: {
|
|
333
|
+
pageNumber,
|
|
334
|
+
pageSize,
|
|
335
|
+
...params.sort === void 0 ? {} : { sort: params.sort },
|
|
336
|
+
...params.showRoots === void 0 ? {} : { showRoots: String(params.showRoots) },
|
|
337
|
+
...params.showUnpublished === void 0 ? {} : { showUnpublished: String(params.showUnpublished) }
|
|
338
|
+
},
|
|
339
|
+
body: { q },
|
|
340
|
+
idempotent: true,
|
|
341
|
+
// pure read over POST — safe to replay on 5xx/429
|
|
342
|
+
auth
|
|
343
|
+
},
|
|
344
|
+
{
|
|
284
345
|
pageNumber,
|
|
285
346
|
pageSize,
|
|
286
|
-
...params.
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
},
|
|
290
|
-
body: { q },
|
|
291
|
-
idempotent: true,
|
|
292
|
-
// pure read over POST — safe to replay on 5xx/429
|
|
293
|
-
auth
|
|
294
|
-
});
|
|
295
|
-
return { items, pageNumber, pageSize, hasNextPage: items.length === pageSize };
|
|
347
|
+
...params.totalCount === void 0 ? {} : { totalCount: params.totalCount }
|
|
348
|
+
}
|
|
349
|
+
);
|
|
296
350
|
}
|
|
297
351
|
/**
|
|
298
352
|
* Searches category trees via `POST /category-trees/search` — returns the
|