@viu/emporix-sdk 1.0.0 → 2.1.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 +56 -0
- package/README.md +26 -1
- package/dist/availability.cjs +101 -0
- package/dist/availability.cjs.map +1 -0
- package/dist/availability.d.cts +87 -0
- package/dist/availability.d.ts +87 -0
- package/dist/availability.js +4 -0
- package/dist/availability.js.map +1 -0
- package/dist/cart.d.cts +1 -1
- package/dist/cart.d.ts +1 -1
- package/dist/category.d.cts +1 -1
- package/dist/category.d.ts +1 -1
- package/dist/checkout.d.cts +1 -1
- package/dist/checkout.d.ts +1 -1
- package/dist/{chunk-QDABAMVN.js → chunk-JTJV7WUW.js} +25 -2
- package/dist/chunk-JTJV7WUW.js.map +1 -0
- package/dist/chunk-SCI7D74B.js +91 -0
- package/dist/chunk-SCI7D74B.js.map +1 -0
- package/dist/chunk-WSXRUYBE.js +248 -0
- package/dist/chunk-WSXRUYBE.js.map +1 -0
- package/dist/chunk-XMEP74BU.js +60 -0
- package/dist/chunk-XMEP74BU.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-vKgzZ-5f.d.cts → context-CGuxSb56.d.cts} +16 -1
- package/dist/{context-vKgzZ-5f.d.ts → context-CGuxSb56.d.ts} +16 -1
- package/dist/customer-groups.d.cts +1 -1
- package/dist/customer-groups.d.ts +1 -1
- package/dist/customer.d.cts +1 -1
- package/dist/customer.d.ts +1 -1
- package/dist/index.cjs +311 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -5
- package/dist/index.d.ts +8 -5
- package/dist/index.js +61 -6
- 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 +218 -9
- package/dist/media.cjs.map +1 -1
- package/dist/media.d.cts +103 -7
- package/dist/media.d.ts +103 -7
- package/dist/media.js +2 -1
- package/dist/orders.d.cts +1 -1
- package/dist/orders.d.ts +1 -1
- package/dist/payment.d.cts +1 -1
- package/dist/payment.d.ts +1 -1
- package/dist/price.cjs +44 -0
- package/dist/price.cjs.map +1 -1
- package/dist/price.d.cts +27 -2
- package/dist/price.d.ts +27 -2
- package/dist/price.js +1 -1
- package/dist/product.cjs +23 -0
- package/dist/product.cjs.map +1 -1
- package/dist/product.d.cts +18 -1
- package/dist/product.d.ts +18 -1
- package/dist/product.js +1 -1
- package/dist/segment.d.cts +1 -1
- package/dist/segment.d.ts +1 -1
- package/package.json +7 -2
- package/dist/chunk-F3WAQH2E.js +0 -120
- package/dist/chunk-F3WAQH2E.js.map +0 -1
- package/dist/chunk-HEO34WLO.js +0 -47
- package/dist/chunk-HEO34WLO.js.map +0 -1
- package/dist/chunk-QDABAMVN.js.map +0 -1
package/dist/media.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-CGuxSb56.js';
|
|
2
2
|
|
|
3
3
|
type MetadataUpdate = {
|
|
4
4
|
/**
|
|
@@ -156,9 +156,44 @@ type AssetUpdateBlob = Asset$1 & {
|
|
|
156
156
|
/** Generated media types (caller sends the exact wire shape). */
|
|
157
157
|
type AssetCreateBlobInput = AssetCreateBlob;
|
|
158
158
|
type AssetCreateLinkInput = AssetCreateLink;
|
|
159
|
+
type AssetUpdateBlobInput = AssetUpdateBlob;
|
|
160
|
+
type AssetUpdateLinkInput = AssetUpdateLink;
|
|
159
161
|
type AssetUpdateInput = AssetUpdateBlob | AssetUpdateLink;
|
|
160
162
|
type Asset = GetAsset;
|
|
161
163
|
type AssetRefId = RefId;
|
|
164
|
+
/**
|
|
165
|
+
* Filter / pagination options for {@link MediaService.list}. The explicit
|
|
166
|
+
* fields are typed for autocomplete; the index signature stays open so
|
|
167
|
+
* Emporix `q`-syntax filters like `"refIds.id"` can be passed verbatim.
|
|
168
|
+
*/
|
|
169
|
+
interface ListAssetsQuery {
|
|
170
|
+
pageNumber?: number;
|
|
171
|
+
pageSize?: number;
|
|
172
|
+
/** Emporix sort syntax, e.g. `"name,metadata.createdAt:desc"`. */
|
|
173
|
+
sort?: string;
|
|
174
|
+
/** Emporix `q`-syntax filter, e.g. `"name:hero"`. */
|
|
175
|
+
q?: string;
|
|
176
|
+
[key: string]: string | number | undefined;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Result of {@link MediaService.download}. The endpoint's behaviour depends
|
|
180
|
+
* on the asset's `access`:
|
|
181
|
+
* - `PUBLIC` assets respond with a 30x redirect whose `Location` header
|
|
182
|
+
* carries the externally-cacheable storage URL — useful when the
|
|
183
|
+
* storefront wants to send the user there directly.
|
|
184
|
+
* - `PRIVATE` assets respond with the raw bytes (plus an `ETag` header
|
|
185
|
+
* for caching). The asset is delivered through Cloudinary behind the
|
|
186
|
+
* server-side service token, never publicly addressable.
|
|
187
|
+
*/
|
|
188
|
+
type DownloadResult = {
|
|
189
|
+
kind: "redirect";
|
|
190
|
+
url: string;
|
|
191
|
+
} | {
|
|
192
|
+
kind: "bytes";
|
|
193
|
+
data: ArrayBuffer;
|
|
194
|
+
etag?: string;
|
|
195
|
+
contentType?: string;
|
|
196
|
+
};
|
|
162
197
|
declare function isProductRef(r: AssetRefId, productId: string): boolean;
|
|
163
198
|
/**
|
|
164
199
|
* Media assets (BLOB/LINK). All endpoints require a backend-only scope
|
|
@@ -179,14 +214,61 @@ declare class MediaService {
|
|
|
179
214
|
}, auth?: AuthContext): Promise<{
|
|
180
215
|
id: string;
|
|
181
216
|
}>;
|
|
182
|
-
/**
|
|
183
|
-
|
|
217
|
+
/**
|
|
218
|
+
* List assets, wrapped in the shared {@link PaginatedItems} envelope so
|
|
219
|
+
* callers can iterate over pages consistently with the rest of the SDK.
|
|
220
|
+
* `hasNextPage` is the standard SDK heuristic: `true` when the returned
|
|
221
|
+
* page is full (`items.length === requested pageSize`). Pagination
|
|
222
|
+
* defaults match Emporix's server defaults (`pageNumber: 1`,
|
|
223
|
+
* `pageSize: 60`) so an empty `query` produces stable expectations.
|
|
224
|
+
*/
|
|
225
|
+
list(query?: ListAssetsQuery, auth?: AuthContext): Promise<PaginatedItems<Asset>>;
|
|
184
226
|
/** Fetch an asset by id. */
|
|
185
227
|
get(assetId: string, auth?: AuthContext): Promise<Asset>;
|
|
186
|
-
/**
|
|
187
|
-
|
|
228
|
+
/**
|
|
229
|
+
* Update an asset. The input is a discriminated union mirroring
|
|
230
|
+
* {@link create}:
|
|
231
|
+
* - `{ kind: "json", body }` — metadata-only patch (BLOB or LINK).
|
|
232
|
+
* Sends `application/json`. Used for `refIds`, `details`, `metadata`,
|
|
233
|
+
* or `url` changes.
|
|
234
|
+
* - `{ kind: "blob", file, body }` — replaces the BLOB file content
|
|
235
|
+
* (max 10MB) AND patches metadata in the same request. Sends
|
|
236
|
+
* `multipart/form-data`.
|
|
237
|
+
*
|
|
238
|
+
* `type` and `access` are immutable per Emporix — they must match the
|
|
239
|
+
* existing asset's values. Optimistic-locking is via `body.metadata.version`;
|
|
240
|
+
* the server returns 409 Conflict on a stale version.
|
|
241
|
+
*/
|
|
242
|
+
update(assetId: string, input: {
|
|
243
|
+
kind: "json";
|
|
244
|
+
body: AssetUpdateInput;
|
|
245
|
+
} | {
|
|
246
|
+
kind: "blob";
|
|
247
|
+
file: Blob;
|
|
248
|
+
body: AssetUpdateBlobInput;
|
|
249
|
+
}, auth?: AuthContext): Promise<Asset>;
|
|
188
250
|
/** Remove an asset. */
|
|
189
251
|
remove(assetId: string, auth?: AuthContext): Promise<void>;
|
|
252
|
+
/**
|
|
253
|
+
* Download an asset by id. Returns a discriminated union:
|
|
254
|
+
* - `{ kind: "redirect", url }` for `PUBLIC` assets (server-side 30x with
|
|
255
|
+
* the storage URL in `Location`).
|
|
256
|
+
* - `{ kind: "bytes", data }` for `PRIVATE` assets (server-side 200 with
|
|
257
|
+
* the asset bytes; `etag` + `contentType` headers are exposed for
|
|
258
|
+
* caching). When the server reports `text/plain` Content-Type (the
|
|
259
|
+
* OpenAPI-documented format), the SDK decodes the base64 stream into
|
|
260
|
+
* an `ArrayBuffer` transparently; binary Content-Types are passed
|
|
261
|
+
* through verbatim.
|
|
262
|
+
*
|
|
263
|
+
* Implementation note: uses `redirect: "manual"` so the redirect-location
|
|
264
|
+
* is observable. In Node.js this works; in a browser the redirect Location
|
|
265
|
+
* is intentionally hidden by fetch — there, `PUBLIC` downloads will
|
|
266
|
+
* surface as an opaque-redirect and the SDK throws. Browser code should
|
|
267
|
+
* use the asset's `url` field from `get()` for `LINK` assets, or the
|
|
268
|
+
* direct storage URL for `PUBLIC` `BLOB` assets (typically delivered via
|
|
269
|
+
* an `<img>` tag rather than `download()`).
|
|
270
|
+
*/
|
|
271
|
+
download(assetId: string, auth?: AuthContext): Promise<DownloadResult>;
|
|
190
272
|
/** Multipart upload sugar: builds `AssetCreateBlob` from input. */
|
|
191
273
|
uploadFile(input: {
|
|
192
274
|
file: Blob;
|
|
@@ -197,6 +279,20 @@ declare class MediaService {
|
|
|
197
279
|
}, auth?: AuthContext): Promise<{
|
|
198
280
|
id: string;
|
|
199
281
|
}>;
|
|
282
|
+
/**
|
|
283
|
+
* Replace the file content of an existing BLOB asset. Sugar over
|
|
284
|
+
* {@link update} with `kind: "blob"`. `access` is required because the
|
|
285
|
+
* field is immutable and the server validates that the patch matches.
|
|
286
|
+
* Pass `version` from `asset.metadata.version` if you want optimistic
|
|
287
|
+
* locking (recommended when concurrent writers are possible).
|
|
288
|
+
*/
|
|
289
|
+
replaceFile(assetId: string, input: {
|
|
290
|
+
file: Blob;
|
|
291
|
+
access: "PUBLIC" | "PRIVATE";
|
|
292
|
+
filename?: string;
|
|
293
|
+
mimeType?: string;
|
|
294
|
+
version?: number;
|
|
295
|
+
}, auth?: AuthContext): Promise<Asset>;
|
|
200
296
|
/** External-URL sugar: builds `AssetCreateLink`. */
|
|
201
297
|
link(input: {
|
|
202
298
|
url: string;
|
|
@@ -210,10 +306,10 @@ declare class MediaService {
|
|
|
210
306
|
/** Remove a PRODUCT refId from an asset (no-op if absent). */
|
|
211
307
|
detachFromProduct(assetId: string, productId: string, auth?: AuthContext): Promise<Asset>;
|
|
212
308
|
/** Convenience: list assets attached to a product (server-side filter). */
|
|
213
|
-
listForProduct(productId: string, auth?: AuthContext): Promise<Asset
|
|
309
|
+
listForProduct(productId: string, auth?: AuthContext): Promise<PaginatedItems<Asset>>;
|
|
214
310
|
}
|
|
215
311
|
declare const _internalMedia: {
|
|
216
312
|
isProductRef: typeof isProductRef;
|
|
217
313
|
};
|
|
218
314
|
|
|
219
|
-
export { type Asset, type AssetCreateBlobInput, type AssetCreateLinkInput, type AssetRefId, type AssetUpdateInput, MediaService, _internalMedia };
|
|
315
|
+
export { type Asset, type AssetCreateBlobInput, type AssetCreateLinkInput, type AssetRefId, type AssetUpdateBlobInput, type AssetUpdateInput, type AssetUpdateLinkInput, type DownloadResult, type ListAssetsQuery, MediaService, _internalMedia };
|
package/dist/media.js
CHANGED
package/dist/orders.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-CGuxSb56.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Hand-written mirror of the Emporix Order-v2 schemas (storefront-relevant
|
package/dist/orders.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-CGuxSb56.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Hand-written mirror of the Emporix Order-v2 schemas (storefront-relevant
|
package/dist/payment.d.cts
CHANGED
package/dist/payment.d.ts
CHANGED
package/dist/price.cjs
CHANGED
|
@@ -81,6 +81,50 @@ var PriceService = class {
|
|
|
81
81
|
body: input
|
|
82
82
|
});
|
|
83
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Chunked variant of {@link matchByContext} for large `items` arrays. The
|
|
86
|
+
* Emporix backend handles only a limited number of items per request
|
|
87
|
+
* (production limit ~50), so this splits `input.items` into chunks and runs
|
|
88
|
+
* `matchByContext` with bounded concurrency.
|
|
89
|
+
*
|
|
90
|
+
* By default a failing chunk is skipped (its items are absent from the
|
|
91
|
+
* result) and `opts.onChunkError` is called once for it; pass
|
|
92
|
+
* `throwOnAnyChunkError: true` to reject on the first failure instead.
|
|
93
|
+
*
|
|
94
|
+
* **Result order is not guaranteed** — match entries back to your items by
|
|
95
|
+
* `priceId` / `itemRef.id`.
|
|
96
|
+
*/
|
|
97
|
+
async matchByContextChunked(input, opts = {}, auth) {
|
|
98
|
+
const chunkSize = opts.chunkSize ?? 50;
|
|
99
|
+
const concurrency = opts.concurrency ?? 4;
|
|
100
|
+
if (chunkSize < 1) throw new Error("chunkSize must be >= 1");
|
|
101
|
+
if (concurrency < 1) throw new Error("concurrency must be >= 1");
|
|
102
|
+
const items = input.items ?? [];
|
|
103
|
+
if (items.length === 0) return [];
|
|
104
|
+
const chunks = [];
|
|
105
|
+
for (let i = 0; i < items.length; i += chunkSize) {
|
|
106
|
+
chunks.push({ ...input, items: items.slice(i, i + chunkSize) });
|
|
107
|
+
}
|
|
108
|
+
const results = new Array(chunks.length);
|
|
109
|
+
let cursor = 0;
|
|
110
|
+
const worker = async () => {
|
|
111
|
+
for (; ; ) {
|
|
112
|
+
const idx = cursor++;
|
|
113
|
+
const chunk = chunks[idx];
|
|
114
|
+
if (chunk === void 0) return;
|
|
115
|
+
try {
|
|
116
|
+
results[idx] = await this.matchByContext(chunk, auth);
|
|
117
|
+
} catch (err) {
|
|
118
|
+
if (opts.throwOnAnyChunkError) throw err;
|
|
119
|
+
results[idx] = [];
|
|
120
|
+
opts.onChunkError?.(err, idx);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
const workerCount = Math.min(concurrency, chunks.length);
|
|
125
|
+
await Promise.all(Array.from({ length: workerCount }, () => worker()));
|
|
126
|
+
return results.flat();
|
|
127
|
+
}
|
|
84
128
|
};
|
|
85
129
|
|
|
86
130
|
exports.PriceService = PriceService;
|
package/dist/price.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/errors.ts","../src/services/price.ts"],"names":[],"mappings":"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","file":"price.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\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 } from \"../core/context\";\nimport type { AuthContext } from \"../core/auth\";\nimport { EmporixAuthError } from \"../core/errors\";\nimport type { Match, MatchByContext, MatchResponse } from \"../generated/price\";\n\n/** Session-context match request body (generated). */\nexport type PriceMatchByContextInput = MatchByContext;\n\n/** Explicit-context match request body (generated). */\nexport type PriceMatchInput = Match;\n\n/** A resolved price (full generated match-response schema). */\nexport type PriceMatch = MatchResponse;\n\nconst ANON: AuthContext = { kind: \"anonymous\" };\nconst SERVICE: AuthContext = { kind: \"service\" };\n\nfunction requireContextAuth(auth: AuthContext | undefined): AuthContext {\n const a = auth ?? ANON;\n if (a.kind === \"anonymous\" || a.kind === \"customer\" || a.kind === \"raw\") return a;\n throw new EmporixAuthError(\n \"match-prices-by-context requires an anonymous, customer, or raw AuthContext\",\n );\n}\n\n/**\n * Price matching. The Cart service does not resolve prices — call this\n * explicitly before rendering money and again right before placing an order.\n * The SDK is stateless: it never caches or revalidates prices.\n */\nexport class PriceService {\n constructor(private readonly ctx: ClientContext) {}\n\n /**\n * Resolves prices using the session context bound to the bearer token\n * (currency/site/country were set at anonymous-login time). Default auth:\n * anonymous; pass a customer/raw context for personalized pricing.\n */\n async matchByContext(\n input: PriceMatchByContextInput,\n auth?: AuthContext,\n ): Promise<PriceMatch[]> {\n return this.ctx.http.request<PriceMatch[]>({\n method: \"POST\",\n path: `/price/${this.ctx.tenant}/match-prices-by-context`,\n auth: requireContextAuth(auth),\n body: input,\n });\n }\n\n /**\n * Resolves prices from an explicit context. Default auth: service\n * (requires `price.price_read` / `price.price_manage`).\n */\n async match(input: PriceMatchInput, auth: AuthContext = SERVICE): Promise<PriceMatch[]> {\n return this.ctx.http.request<PriceMatch[]>({\n method: \"POST\",\n path: `/price/${this.ctx.tenant}/match-prices`,\n auth,\n body: input,\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/errors.ts","../src/services/price.ts"],"names":[],"mappings":"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","file":"price.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\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 } from \"../core/context\";\nimport type { AuthContext } from \"../core/auth\";\nimport { EmporixAuthError } from \"../core/errors\";\nimport type { Match, MatchByContext, MatchResponse } from \"../generated/price\";\n\n/** Session-context match request body (generated). */\nexport type PriceMatchByContextInput = MatchByContext;\n\n/** Explicit-context match request body (generated). */\nexport type PriceMatchInput = Match;\n\n/** A resolved price (full generated match-response schema). */\nexport type PriceMatch = MatchResponse;\n\n/** Options for {@link PriceService.matchByContextChunked}. */\nexport interface MatchByContextChunkedOptions {\n /** Items per request. Default 50. Must be >= 1. */\n chunkSize?: number;\n /** Maximum number of requests in flight at once. Default 4. Must be >= 1. */\n concurrency?: number;\n /** Invoked once per failed chunk (default mode only — not when throwing). */\n onChunkError?: (err: unknown, chunkIndex: number) => void;\n /** When true, the first failing chunk rejects the whole call. Default false. */\n throwOnAnyChunkError?: boolean;\n}\n\nconst ANON: AuthContext = { kind: \"anonymous\" };\nconst SERVICE: AuthContext = { kind: \"service\" };\n\nfunction requireContextAuth(auth: AuthContext | undefined): AuthContext {\n const a = auth ?? ANON;\n if (a.kind === \"anonymous\" || a.kind === \"customer\" || a.kind === \"raw\") return a;\n throw new EmporixAuthError(\n \"match-prices-by-context requires an anonymous, customer, or raw AuthContext\",\n );\n}\n\n/**\n * Price matching. The Cart service does not resolve prices — call this\n * explicitly before rendering money and again right before placing an order.\n * The SDK is stateless: it never caches or revalidates prices.\n */\nexport class PriceService {\n constructor(private readonly ctx: ClientContext) {}\n\n /**\n * Resolves prices using the session context bound to the bearer token\n * (currency/site/country were set at anonymous-login time). Default auth:\n * anonymous; pass a customer/raw context for personalized pricing.\n */\n async matchByContext(\n input: PriceMatchByContextInput,\n auth?: AuthContext,\n ): Promise<PriceMatch[]> {\n return this.ctx.http.request<PriceMatch[]>({\n method: \"POST\",\n path: `/price/${this.ctx.tenant}/match-prices-by-context`,\n auth: requireContextAuth(auth),\n body: input,\n });\n }\n\n /**\n * Resolves prices from an explicit context. Default auth: service\n * (requires `price.price_read` / `price.price_manage`).\n */\n async match(input: PriceMatchInput, auth: AuthContext = SERVICE): Promise<PriceMatch[]> {\n return this.ctx.http.request<PriceMatch[]>({\n method: \"POST\",\n path: `/price/${this.ctx.tenant}/match-prices`,\n auth,\n body: input,\n });\n }\n\n /**\n * Chunked variant of {@link matchByContext} for large `items` arrays. The\n * Emporix backend handles only a limited number of items per request\n * (production limit ~50), so this splits `input.items` into chunks and runs\n * `matchByContext` with bounded concurrency.\n *\n * By default a failing chunk is skipped (its items are absent from the\n * result) and `opts.onChunkError` is called once for it; pass\n * `throwOnAnyChunkError: true` to reject on the first failure instead.\n *\n * **Result order is not guaranteed** — match entries back to your items by\n * `priceId` / `itemRef.id`.\n */\n async matchByContextChunked(\n input: PriceMatchByContextInput,\n opts: MatchByContextChunkedOptions = {},\n auth?: AuthContext,\n ): Promise<PriceMatch[]> {\n const chunkSize = opts.chunkSize ?? 50;\n const concurrency = opts.concurrency ?? 4;\n if (chunkSize < 1) throw new Error(\"chunkSize must be >= 1\");\n if (concurrency < 1) throw new Error(\"concurrency must be >= 1\");\n\n const items = input.items ?? [];\n if (items.length === 0) return [];\n\n const chunks: PriceMatchByContextInput[] = [];\n for (let i = 0; i < items.length; i += chunkSize) {\n chunks.push({ ...input, items: items.slice(i, i + chunkSize) });\n }\n\n const results: PriceMatch[][] = new Array(chunks.length);\n let cursor = 0;\n\n const worker = async (): Promise<void> => {\n for (;;) {\n const idx = cursor++;\n const chunk = chunks[idx];\n if (chunk === undefined) return; // past the end\n try {\n results[idx] = await this.matchByContext(chunk, auth);\n } catch (err) {\n if (opts.throwOnAnyChunkError) throw err;\n results[idx] = [];\n opts.onChunkError?.(err, idx);\n }\n }\n };\n\n const workerCount = Math.min(concurrency, chunks.length);\n await Promise.all(Array.from({ length: workerCount }, () => worker()));\n\n return results.flat();\n }\n}\n"]}
|
package/dist/price.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext } from './context-CGuxSb56.cjs';
|
|
2
2
|
|
|
3
3
|
type Metadata = {
|
|
4
4
|
/**
|
|
@@ -421,6 +421,17 @@ type PriceMatchByContextInput = MatchByContext;
|
|
|
421
421
|
type PriceMatchInput = Match;
|
|
422
422
|
/** A resolved price (full generated match-response schema). */
|
|
423
423
|
type PriceMatch = MatchResponse;
|
|
424
|
+
/** Options for {@link PriceService.matchByContextChunked}. */
|
|
425
|
+
interface MatchByContextChunkedOptions {
|
|
426
|
+
/** Items per request. Default 50. Must be >= 1. */
|
|
427
|
+
chunkSize?: number;
|
|
428
|
+
/** Maximum number of requests in flight at once. Default 4. Must be >= 1. */
|
|
429
|
+
concurrency?: number;
|
|
430
|
+
/** Invoked once per failed chunk (default mode only — not when throwing). */
|
|
431
|
+
onChunkError?: (err: unknown, chunkIndex: number) => void;
|
|
432
|
+
/** When true, the first failing chunk rejects the whole call. Default false. */
|
|
433
|
+
throwOnAnyChunkError?: boolean;
|
|
434
|
+
}
|
|
424
435
|
/**
|
|
425
436
|
* Price matching. The Cart service does not resolve prices — call this
|
|
426
437
|
* explicitly before rendering money and again right before placing an order.
|
|
@@ -440,6 +451,20 @@ declare class PriceService {
|
|
|
440
451
|
* (requires `price.price_read` / `price.price_manage`).
|
|
441
452
|
*/
|
|
442
453
|
match(input: PriceMatchInput, auth?: AuthContext): Promise<PriceMatch[]>;
|
|
454
|
+
/**
|
|
455
|
+
* Chunked variant of {@link matchByContext} for large `items` arrays. The
|
|
456
|
+
* Emporix backend handles only a limited number of items per request
|
|
457
|
+
* (production limit ~50), so this splits `input.items` into chunks and runs
|
|
458
|
+
* `matchByContext` with bounded concurrency.
|
|
459
|
+
*
|
|
460
|
+
* By default a failing chunk is skipped (its items are absent from the
|
|
461
|
+
* result) and `opts.onChunkError` is called once for it; pass
|
|
462
|
+
* `throwOnAnyChunkError: true` to reject on the first failure instead.
|
|
463
|
+
*
|
|
464
|
+
* **Result order is not guaranteed** — match entries back to your items by
|
|
465
|
+
* `priceId` / `itemRef.id`.
|
|
466
|
+
*/
|
|
467
|
+
matchByContextChunked(input: PriceMatchByContextInput, opts?: MatchByContextChunkedOptions, auth?: AuthContext): Promise<PriceMatch[]>;
|
|
443
468
|
}
|
|
444
469
|
|
|
445
|
-
export { type PriceMatch, type PriceMatchByContextInput, type PriceMatchInput, PriceService };
|
|
470
|
+
export { type MatchByContextChunkedOptions, type PriceMatch, type PriceMatchByContextInput, type PriceMatchInput, PriceService };
|
package/dist/price.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext } from './context-CGuxSb56.js';
|
|
2
2
|
|
|
3
3
|
type Metadata = {
|
|
4
4
|
/**
|
|
@@ -421,6 +421,17 @@ type PriceMatchByContextInput = MatchByContext;
|
|
|
421
421
|
type PriceMatchInput = Match;
|
|
422
422
|
/** A resolved price (full generated match-response schema). */
|
|
423
423
|
type PriceMatch = MatchResponse;
|
|
424
|
+
/** Options for {@link PriceService.matchByContextChunked}. */
|
|
425
|
+
interface MatchByContextChunkedOptions {
|
|
426
|
+
/** Items per request. Default 50. Must be >= 1. */
|
|
427
|
+
chunkSize?: number;
|
|
428
|
+
/** Maximum number of requests in flight at once. Default 4. Must be >= 1. */
|
|
429
|
+
concurrency?: number;
|
|
430
|
+
/** Invoked once per failed chunk (default mode only — not when throwing). */
|
|
431
|
+
onChunkError?: (err: unknown, chunkIndex: number) => void;
|
|
432
|
+
/** When true, the first failing chunk rejects the whole call. Default false. */
|
|
433
|
+
throwOnAnyChunkError?: boolean;
|
|
434
|
+
}
|
|
424
435
|
/**
|
|
425
436
|
* Price matching. The Cart service does not resolve prices — call this
|
|
426
437
|
* explicitly before rendering money and again right before placing an order.
|
|
@@ -440,6 +451,20 @@ declare class PriceService {
|
|
|
440
451
|
* (requires `price.price_read` / `price.price_manage`).
|
|
441
452
|
*/
|
|
442
453
|
match(input: PriceMatchInput, auth?: AuthContext): Promise<PriceMatch[]>;
|
|
454
|
+
/**
|
|
455
|
+
* Chunked variant of {@link matchByContext} for large `items` arrays. The
|
|
456
|
+
* Emporix backend handles only a limited number of items per request
|
|
457
|
+
* (production limit ~50), so this splits `input.items` into chunks and runs
|
|
458
|
+
* `matchByContext` with bounded concurrency.
|
|
459
|
+
*
|
|
460
|
+
* By default a failing chunk is skipped (its items are absent from the
|
|
461
|
+
* result) and `opts.onChunkError` is called once for it; pass
|
|
462
|
+
* `throwOnAnyChunkError: true` to reject on the first failure instead.
|
|
463
|
+
*
|
|
464
|
+
* **Result order is not guaranteed** — match entries back to your items by
|
|
465
|
+
* `priceId` / `itemRef.id`.
|
|
466
|
+
*/
|
|
467
|
+
matchByContextChunked(input: PriceMatchByContextInput, opts?: MatchByContextChunkedOptions, auth?: AuthContext): Promise<PriceMatch[]>;
|
|
443
468
|
}
|
|
444
469
|
|
|
445
|
-
export { type PriceMatch, type PriceMatchByContextInput, type PriceMatchInput, PriceService };
|
|
470
|
+
export { type MatchByContextChunkedOptions, type PriceMatch, type PriceMatchByContextInput, type PriceMatchInput, PriceService };
|
package/dist/price.js
CHANGED
package/dist/product.cjs
CHANGED
|
@@ -93,6 +93,29 @@ var ProductService = class {
|
|
|
93
93
|
);
|
|
94
94
|
return pages.flat();
|
|
95
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Streams the VARIANT children of a PARENT_VARIANT product, page by page,
|
|
98
|
+
* via the search query `productType:VARIANT parentVariantId:<id>`. Default
|
|
99
|
+
* pageSize 200. The query syntax (space-separated fields = implicit AND) is
|
|
100
|
+
* encapsulated here so consumers don't build it themselves.
|
|
101
|
+
*/
|
|
102
|
+
listVariantChildrenAll(parentVariantId, params = {}, auth = ANON) {
|
|
103
|
+
const pageSize = params.pageSize ?? 200;
|
|
104
|
+
const q = `productType:VARIANT parentVariantId:${parentVariantId}`;
|
|
105
|
+
return iterateAll((pageNumber) => this.search(q, { pageNumber, pageSize }, auth));
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Resolves ALL VARIANT children of a PARENT_VARIANT product into a flat
|
|
109
|
+
* array (loads every page). Default pageSize 200. Returns `[]` when there are
|
|
110
|
+
* no children — never throws.
|
|
111
|
+
*/
|
|
112
|
+
async listVariantChildren(parentVariantId, params = {}, auth = ANON) {
|
|
113
|
+
const out = [];
|
|
114
|
+
for await (const child of this.listVariantChildrenAll(parentVariantId, params, auth)) {
|
|
115
|
+
out.push(child);
|
|
116
|
+
}
|
|
117
|
+
return out;
|
|
118
|
+
}
|
|
96
119
|
};
|
|
97
120
|
|
|
98
121
|
exports.ProductService = ProductService;
|
package/dist/product.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/context.ts","../src/services/product.ts"],"names":[],"mappings":"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","file":"product.cjs","sourcesContent":["import type { HttpClient } from \"./http\";\nimport type { TokenProvider, AuthContext } from \"./auth\";\nimport type { Logger } from \"./logger\";\n\n/** Shared dependencies every service facade receives. */\nexport interface ClientContext {\n tenant: string;\n http: HttpClient;\n tokenProvider: TokenProvider;\n logger: Logger;\n}\n\n/**\n * A cursor-paged collection — `pageNumber`/`pageSize` indexing with a\n * `hasNextPage` signal driven by the source page being full. Used by all\n * paginated services and hooks across the SDK.\n */\nexport interface PaginatedItems<T> {\n items: T[];\n pageNumber: number;\n pageSize: number;\n hasNextPage: boolean;\n}\n\n/** Default `AuthContext` applied by a service when the caller passes none. */\nexport type DefaultAuth = AuthContext | undefined;\n\n/**\n * Async-iterates every item across pages of a `PaginatedItems<T>` source.\n * Stops when the source reports `hasNextPage: false`.\n *\n * @param fetchPage - given a 1-based page number, returns the page.\n * @param start - first page to fetch (default `1`).\n */\nexport async function* iterateAll<T>(\n fetchPage: (pageNumber: number) => Promise<PaginatedItems<T>>,\n start = 1,\n): AsyncIterable<T> {\n let p = start;\n for (;;) {\n const page = await fetchPage(p);\n for (const it of page.items) yield it;\n if (!page.hasNextPage) return;\n p += 1;\n }\n}\n\n","import type { ClientContext, PaginatedItems } from \"../core/context\";\nimport { iterateAll } from \"../core/context\";\nimport type { AuthContext } from \"../core/auth\";\nimport type {\n BasicProductWithId,\n BundleProductWithId,\n ParentVariantProductWithId,\n ProductMedia,\n} from \"../generated/product\";\n\nconst ANON: AuthContext = { kind: \"anonymous\" };\n\n/** A product as returned by the Product service (all generated fields). */\nexport type Product = BasicProductWithId | BundleProductWithId | ParentVariantProductWithId;\n\n/** A single product media entry (generated; `ProductMedia` is the list type). */\nexport type Media = ProductMedia[number];\n\n/** Catalog reads. Default auth: anonymous; pass customer for personalized pricing. */\nexport class ProductService {\n constructor(private readonly ctx: ClientContext) {}\n\n /** Fetches one product by id. */\n async get(\n productId: string,\n _opts?: Record<string, never>,\n auth: AuthContext = ANON,\n ): Promise<Product> {\n return this.ctx.http.request<Product>({\n method: \"GET\",\n path: `/product/${this.ctx.tenant}/products/${productId}`,\n auth,\n });\n }\n\n /** Fetches one product by its code. */\n async getByCode(code: string, auth: AuthContext = ANON): Promise<Product> {\n const rows = await this.ctx.http.request<Product[]>({\n method: \"GET\",\n path: `/product/${this.ctx.tenant}/products`,\n query: { q: `code:${code}` },\n auth,\n });\n const first = rows[0];\n if (!first) throw new Error(`No product with code \"${code}\"`);\n return first;\n }\n\n /** One page of products. */\n async list(\n params: { pageNumber?: number; pageSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<PaginatedItems<Product>> {\n const pageNumber = params.pageNumber ?? 1;\n const pageSize = params.pageSize ?? 50;\n const items = await this.ctx.http.request<Product[]>({\n method: \"GET\",\n path: `/product/${this.ctx.tenant}/products`,\n query: { pageNumber, pageSize },\n auth,\n });\n return { items, pageNumber, pageSize, hasNextPage: items.length === pageSize };\n }\n\n /** Async-iterates every product across pages. */\n listAll(params: { pageSize?: number } = {}, auth: AuthContext = ANON): AsyncIterable<Product> {\n const pageSize = params.pageSize ?? 50;\n return iterateAll<Product>((pageNumber) => this.list({ pageNumber, pageSize }, auth));\n }\n\n /** Searches products by free-text query. */\n async search(\n query: string,\n params: { pageNumber?: number; pageSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<PaginatedItems<Product>> {\n const pageNumber = params.pageNumber ?? 1;\n const pageSize = params.pageSize ?? 50;\n const items = await this.ctx.http.request<Product[]>({\n method: \"GET\",\n path: `/product/${this.ctx.tenant}/products`,\n query: { q: query, pageNumber, pageSize },\n auth,\n });\n return { items, pageNumber, pageSize, hasNextPage: items.length === pageSize };\n }\n\n /**\n * Bulk fetch by id. POSTs `/products/search` with `q=\"id:(id1,id2,…)\"`,\n * chunking when the list is larger than `options.chunkSize` (default\n * 100). An empty list short-circuits with no HTTP call. **Order is not\n * guaranteed** across chunks — re-index by `id` if order matters.\n */\n async searchByIds(\n ids: string[],\n options: { chunkSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<Product[]> {\n if (ids.length === 0) return [];\n const chunkSize = options.chunkSize ?? 100;\n const chunks: string[][] = [];\n for (let i = 0; i < ids.length; i += chunkSize) {\n chunks.push(ids.slice(i, i + chunkSize));\n }\n const pages = await Promise.all(\n chunks.map((chunk) =>\n this.ctx.http.request<Product[]>({\n method: \"POST\",\n path: `/product/${this.ctx.tenant}/products/search`,\n query: { pageSize: chunk.length },\n auth,\n body: { q: `id:(${chunk.join(\",\")})` },\n }),\n ),\n );\n return pages.flat();\n }\n\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/context.ts","../src/services/product.ts"],"names":[],"mappings":"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","file":"product.cjs","sourcesContent":["import type { HttpClient } from \"./http\";\nimport type { TokenProvider, AuthContext } from \"./auth\";\nimport type { Logger } from \"./logger\";\n\n/** Shared dependencies every service facade receives. */\nexport interface ClientContext {\n tenant: string;\n http: HttpClient;\n tokenProvider: TokenProvider;\n logger: Logger;\n}\n\n/**\n * A cursor-paged collection — `pageNumber`/`pageSize` indexing with a\n * `hasNextPage` signal driven by the source page being full. Used by all\n * paginated services and hooks across the SDK.\n */\nexport interface PaginatedItems<T> {\n items: T[];\n pageNumber: number;\n pageSize: number;\n hasNextPage: boolean;\n}\n\n/** Default `AuthContext` applied by a service when the caller passes none. */\nexport type DefaultAuth = AuthContext | undefined;\n\n/**\n * Async-iterates every item across pages of a `PaginatedItems<T>` source.\n * Stops when the source reports `hasNextPage: false`.\n *\n * @param fetchPage - given a 1-based page number, returns the page.\n * @param start - first page to fetch (default `1`).\n */\nexport async function* iterateAll<T>(\n fetchPage: (pageNumber: number) => Promise<PaginatedItems<T>>,\n start = 1,\n): AsyncIterable<T> {\n let p = start;\n for (;;) {\n const page = await fetchPage(p);\n for (const it of page.items) yield it;\n if (!page.hasNextPage) return;\n p += 1;\n }\n}\n\n","import type { ClientContext, PaginatedItems } from \"../core/context\";\nimport { iterateAll } from \"../core/context\";\nimport type { AuthContext } from \"../core/auth\";\nimport type {\n BasicProductWithId,\n BundleProductWithId,\n ParentVariantProductWithId,\n ProductMedia,\n} from \"../generated/product\";\n\nconst ANON: AuthContext = { kind: \"anonymous\" };\n\n/** A product as returned by the Product service (all generated fields). */\nexport type Product = BasicProductWithId | BundleProductWithId | ParentVariantProductWithId;\n\n/** A single product media entry (generated; `ProductMedia` is the list type). */\nexport type Media = ProductMedia[number];\n\n/** Catalog reads. Default auth: anonymous; pass customer for personalized pricing. */\nexport class ProductService {\n constructor(private readonly ctx: ClientContext) {}\n\n /** Fetches one product by id. */\n async get(\n productId: string,\n _opts?: Record<string, never>,\n auth: AuthContext = ANON,\n ): Promise<Product> {\n return this.ctx.http.request<Product>({\n method: \"GET\",\n path: `/product/${this.ctx.tenant}/products/${productId}`,\n auth,\n });\n }\n\n /** Fetches one product by its code. */\n async getByCode(code: string, auth: AuthContext = ANON): Promise<Product> {\n const rows = await this.ctx.http.request<Product[]>({\n method: \"GET\",\n path: `/product/${this.ctx.tenant}/products`,\n query: { q: `code:${code}` },\n auth,\n });\n const first = rows[0];\n if (!first) throw new Error(`No product with code \"${code}\"`);\n return first;\n }\n\n /** One page of products. */\n async list(\n params: { pageNumber?: number; pageSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<PaginatedItems<Product>> {\n const pageNumber = params.pageNumber ?? 1;\n const pageSize = params.pageSize ?? 50;\n const items = await this.ctx.http.request<Product[]>({\n method: \"GET\",\n path: `/product/${this.ctx.tenant}/products`,\n query: { pageNumber, pageSize },\n auth,\n });\n return { items, pageNumber, pageSize, hasNextPage: items.length === pageSize };\n }\n\n /** Async-iterates every product across pages. */\n listAll(params: { pageSize?: number } = {}, auth: AuthContext = ANON): AsyncIterable<Product> {\n const pageSize = params.pageSize ?? 50;\n return iterateAll<Product>((pageNumber) => this.list({ pageNumber, pageSize }, auth));\n }\n\n /** Searches products by free-text query. */\n async search(\n query: string,\n params: { pageNumber?: number; pageSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<PaginatedItems<Product>> {\n const pageNumber = params.pageNumber ?? 1;\n const pageSize = params.pageSize ?? 50;\n const items = await this.ctx.http.request<Product[]>({\n method: \"GET\",\n path: `/product/${this.ctx.tenant}/products`,\n query: { q: query, pageNumber, pageSize },\n auth,\n });\n return { items, pageNumber, pageSize, hasNextPage: items.length === pageSize };\n }\n\n /**\n * Bulk fetch by id. POSTs `/products/search` with `q=\"id:(id1,id2,…)\"`,\n * chunking when the list is larger than `options.chunkSize` (default\n * 100). An empty list short-circuits with no HTTP call. **Order is not\n * guaranteed** across chunks — re-index by `id` if order matters.\n */\n async searchByIds(\n ids: string[],\n options: { chunkSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<Product[]> {\n if (ids.length === 0) return [];\n const chunkSize = options.chunkSize ?? 100;\n const chunks: string[][] = [];\n for (let i = 0; i < ids.length; i += chunkSize) {\n chunks.push(ids.slice(i, i + chunkSize));\n }\n const pages = await Promise.all(\n chunks.map((chunk) =>\n this.ctx.http.request<Product[]>({\n method: \"POST\",\n path: `/product/${this.ctx.tenant}/products/search`,\n query: { pageSize: chunk.length },\n auth,\n body: { q: `id:(${chunk.join(\",\")})` },\n }),\n ),\n );\n return pages.flat();\n }\n\n /**\n * Streams the VARIANT children of a PARENT_VARIANT product, page by page,\n * via the search query `productType:VARIANT parentVariantId:<id>`. Default\n * pageSize 200. The query syntax (space-separated fields = implicit AND) is\n * encapsulated here so consumers don't build it themselves.\n */\n listVariantChildrenAll(\n parentVariantId: string,\n params: { pageSize?: number } = {},\n auth: AuthContext = ANON,\n ): AsyncIterable<Product> {\n const pageSize = params.pageSize ?? 200;\n const q = `productType:VARIANT parentVariantId:${parentVariantId}`;\n return iterateAll<Product>((pageNumber) => this.search(q, { pageNumber, pageSize }, auth));\n }\n\n /**\n * Resolves ALL VARIANT children of a PARENT_VARIANT product into a flat\n * array (loads every page). Default pageSize 200. Returns `[]` when there are\n * no children — never throws.\n */\n async listVariantChildren(\n parentVariantId: string,\n params: { pageSize?: number } = {},\n auth: AuthContext = ANON,\n ): Promise<Product[]> {\n const out: Product[] = [];\n for await (const child of this.listVariantChildrenAll(parentVariantId, params, auth)) {\n out.push(child);\n }\n return out;\n }\n}\n"]}
|
package/dist/product.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-CGuxSb56.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Localized value which can have different structure which depends on provided `Content-Language` header.
|
|
@@ -395,6 +395,23 @@ declare class ProductService {
|
|
|
395
395
|
searchByIds(ids: string[], options?: {
|
|
396
396
|
chunkSize?: number;
|
|
397
397
|
}, auth?: AuthContext): Promise<Product[]>;
|
|
398
|
+
/**
|
|
399
|
+
* Streams the VARIANT children of a PARENT_VARIANT product, page by page,
|
|
400
|
+
* via the search query `productType:VARIANT parentVariantId:<id>`. Default
|
|
401
|
+
* pageSize 200. The query syntax (space-separated fields = implicit AND) is
|
|
402
|
+
* encapsulated here so consumers don't build it themselves.
|
|
403
|
+
*/
|
|
404
|
+
listVariantChildrenAll(parentVariantId: string, params?: {
|
|
405
|
+
pageSize?: number;
|
|
406
|
+
}, auth?: AuthContext): AsyncIterable<Product>;
|
|
407
|
+
/**
|
|
408
|
+
* Resolves ALL VARIANT children of a PARENT_VARIANT product into a flat
|
|
409
|
+
* array (loads every page). Default pageSize 200. Returns `[]` when there are
|
|
410
|
+
* no children — never throws.
|
|
411
|
+
*/
|
|
412
|
+
listVariantChildren(parentVariantId: string, params?: {
|
|
413
|
+
pageSize?: number;
|
|
414
|
+
}, auth?: AuthContext): Promise<Product[]>;
|
|
398
415
|
}
|
|
399
416
|
|
|
400
417
|
export { type Media, type Product, ProductService };
|
package/dist/product.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-CGuxSb56.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Localized value which can have different structure which depends on provided `Content-Language` header.
|
|
@@ -395,6 +395,23 @@ declare class ProductService {
|
|
|
395
395
|
searchByIds(ids: string[], options?: {
|
|
396
396
|
chunkSize?: number;
|
|
397
397
|
}, auth?: AuthContext): Promise<Product[]>;
|
|
398
|
+
/**
|
|
399
|
+
* Streams the VARIANT children of a PARENT_VARIANT product, page by page,
|
|
400
|
+
* via the search query `productType:VARIANT parentVariantId:<id>`. Default
|
|
401
|
+
* pageSize 200. The query syntax (space-separated fields = implicit AND) is
|
|
402
|
+
* encapsulated here so consumers don't build it themselves.
|
|
403
|
+
*/
|
|
404
|
+
listVariantChildrenAll(parentVariantId: string, params?: {
|
|
405
|
+
pageSize?: number;
|
|
406
|
+
}, auth?: AuthContext): AsyncIterable<Product>;
|
|
407
|
+
/**
|
|
408
|
+
* Resolves ALL VARIANT children of a PARENT_VARIANT product into a flat
|
|
409
|
+
* array (loads every page). Default pageSize 200. Returns `[]` when there are
|
|
410
|
+
* no children — never throws.
|
|
411
|
+
*/
|
|
412
|
+
listVariantChildren(parentVariantId: string, params?: {
|
|
413
|
+
pageSize?: number;
|
|
414
|
+
}, auth?: AuthContext): Promise<Product[]>;
|
|
398
415
|
}
|
|
399
416
|
|
|
400
417
|
export { type Media, type Product, ProductService };
|
package/dist/product.js
CHANGED
package/dist/segment.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-CGuxSb56.cjs';
|
|
2
2
|
import { ProductService } from './product.cjs';
|
|
3
3
|
import { CategoryService } from './category.cjs';
|
|
4
4
|
|
package/dist/segment.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-CGuxSb56.js';
|
|
2
2
|
import { ProductService } from './product.js';
|
|
3
3
|
import { CategoryService } from './category.js';
|
|
4
4
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@viu/emporix-sdk",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "TypeScript SDK for the Emporix Commerce Engine",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -110,11 +110,16 @@
|
|
|
110
110
|
"types": "./dist/orders.d.ts",
|
|
111
111
|
"import": "./dist/orders.js",
|
|
112
112
|
"require": "./dist/orders.cjs"
|
|
113
|
+
},
|
|
114
|
+
"./availability": {
|
|
115
|
+
"types": "./dist/availability.d.ts",
|
|
116
|
+
"import": "./dist/availability.js",
|
|
117
|
+
"require": "./dist/availability.cjs"
|
|
113
118
|
}
|
|
114
119
|
},
|
|
115
120
|
"publishConfig": {
|
|
116
121
|
"access": "public",
|
|
117
|
-
"provenance":
|
|
122
|
+
"provenance": true
|
|
118
123
|
},
|
|
119
124
|
"devDependencies": {
|
|
120
125
|
"@hey-api/openapi-ts": "^0.64.0",
|