@viu/emporix-sdk 2.0.0 → 2.2.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +13 -1
  3. package/dist/availability.cjs +101 -0
  4. package/dist/availability.cjs.map +1 -0
  5. package/dist/availability.d.cts +87 -0
  6. package/dist/availability.d.ts +87 -0
  7. package/dist/availability.js +4 -0
  8. package/dist/availability.js.map +1 -0
  9. package/dist/cart.d.cts +1 -1
  10. package/dist/cart.d.ts +1 -1
  11. package/dist/category.d.cts +1 -1
  12. package/dist/category.d.ts +1 -1
  13. package/dist/checkout.d.cts +1 -1
  14. package/dist/checkout.d.ts +1 -1
  15. package/dist/{chunk-QDABAMVN.js → chunk-5JHTZBOC.js} +65 -2
  16. package/dist/chunk-5JHTZBOC.js.map +1 -0
  17. package/dist/chunk-SCI7D74B.js +91 -0
  18. package/dist/chunk-SCI7D74B.js.map +1 -0
  19. package/dist/chunk-XMEP74BU.js +60 -0
  20. package/dist/chunk-XMEP74BU.js.map +1 -0
  21. package/dist/companies.d.cts +1 -1
  22. package/dist/companies.d.ts +1 -1
  23. package/dist/contacts.d.cts +1 -1
  24. package/dist/contacts.d.ts +1 -1
  25. package/dist/{context-mMTqsW1Z.d.cts → context-Bs5ZSwds.d.cts} +1 -1
  26. package/dist/{context-mMTqsW1Z.d.ts → context-Bs5ZSwds.d.ts} +1 -1
  27. package/dist/customer-groups.d.cts +1 -1
  28. package/dist/customer-groups.d.ts +1 -1
  29. package/dist/customer.d.cts +1 -1
  30. package/dist/customer.d.ts +1 -1
  31. package/dist/index.cjs +295 -6
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.cts +125 -4
  34. package/dist/index.d.ts +125 -4
  35. package/dist/index.js +137 -11
  36. package/dist/index.js.map +1 -1
  37. package/dist/locations.d.cts +1 -1
  38. package/dist/locations.d.ts +1 -1
  39. package/dist/media.d.cts +1 -1
  40. package/dist/media.d.ts +1 -1
  41. package/dist/orders.d.cts +1 -1
  42. package/dist/orders.d.ts +1 -1
  43. package/dist/payment.d.cts +1 -1
  44. package/dist/payment.d.ts +1 -1
  45. package/dist/price.cjs +44 -0
  46. package/dist/price.cjs.map +1 -1
  47. package/dist/price.d.cts +27 -2
  48. package/dist/price.d.ts +27 -2
  49. package/dist/price.js +1 -1
  50. package/dist/product.cjs +63 -0
  51. package/dist/product.cjs.map +1 -1
  52. package/dist/product.d.cts +31 -1
  53. package/dist/product.d.ts +31 -1
  54. package/dist/product.js +1 -1
  55. package/dist/segment.d.cts +1 -1
  56. package/dist/segment.d.ts +1 -1
  57. package/package.json +6 -1
  58. package/dist/chunk-HEO34WLO.js +0 -47
  59. package/dist/chunk-HEO34WLO.js.map +0 -1
  60. package/dist/chunk-QDABAMVN.js.map +0 -1
@@ -0,0 +1,60 @@
1
+ import { EmporixNotFoundError } from './chunk-KTODT6DV.js';
2
+
3
+ // src/services/availability.ts
4
+ var ANON = { kind: "anonymous" };
5
+ var AvailabilityService = class {
6
+ constructor(ctx) {
7
+ this.ctx = ctx;
8
+ }
9
+ ctx;
10
+ /**
11
+ * Single product. Resolves the availability record, or — when
12
+ * `opts.defaultAvailableOnNotFound` is set — a default available record on 404.
13
+ */
14
+ async get(productId, siteCode, auth = ANON, opts = {}) {
15
+ try {
16
+ return await this.ctx.http.request({
17
+ method: "GET",
18
+ path: `/availability/${this.ctx.tenant}/availability/${encodeURIComponent(
19
+ productId
20
+ )}/${encodeURIComponent(siteCode)}`,
21
+ auth
22
+ });
23
+ } catch (err) {
24
+ if (err instanceof EmporixNotFoundError && opts.defaultAvailableOnNotFound) {
25
+ return { productId, site: siteCode, available: true };
26
+ }
27
+ throw err;
28
+ }
29
+ }
30
+ /**
31
+ * Batch read via `POST .../availability/search` (one request). Products with
32
+ * no availability record are absent from the response; each is synthesized as
33
+ * `{ available: false }` (or `{ available: true }` when
34
+ * `opts.defaultAvailableOnNotFound` is set). The result preserves input order
35
+ * and length. An empty `productIds` resolves to `[]` without a request.
36
+ */
37
+ async getMany(productIds, siteCode, auth = ANON, opts = {}) {
38
+ if (productIds.length === 0) return [];
39
+ const found = await this.ctx.http.request({
40
+ method: "POST",
41
+ path: `/availability/${this.ctx.tenant}/availability/search`,
42
+ auth,
43
+ query: { site: siteCode, pageSize: productIds.length },
44
+ body: productIds
45
+ });
46
+ const byId = /* @__PURE__ */ new Map();
47
+ for (const a of found) if (a.productId) byId.set(a.productId, a);
48
+ return productIds.map(
49
+ (id) => byId.get(id) ?? {
50
+ productId: id,
51
+ site: siteCode,
52
+ available: Boolean(opts.defaultAvailableOnNotFound)
53
+ }
54
+ );
55
+ }
56
+ };
57
+
58
+ export { AvailabilityService };
59
+ //# sourceMappingURL=chunk-XMEP74BU.js.map
60
+ //# sourceMappingURL=chunk-XMEP74BU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/availability.ts"],"names":[],"mappings":";;;AAuBA,IAAM,IAAA,GAAoB,EAAE,IAAA,EAAM,WAAA,EAAY;AAQvC,IAAM,sBAAN,MAA0B;AAAA,EAC/B,YAA6B,GAAA,EAAoB;AAApB,IAAA,IAAA,CAAA,GAAA,GAAA,GAAA;AAAA,EAAqB;AAAA,EAArB,GAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM7B,MAAM,IACJ,SAAA,EACA,QAAA,EACA,OAAoB,IAAA,EACpB,IAAA,GAA4B,EAAC,EACN;AACvB,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,OAAA,CAAsB;AAAA,QAC/C,MAAA,EAAQ,KAAA;AAAA,QACR,IAAA,EAAM,CAAA,cAAA,EAAiB,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA,cAAA,EAAiB,kBAAA;AAAA,UACrD;AAAA,SACD,CAAA,CAAA,EAAI,kBAAA,CAAmB,QAAQ,CAAC,CAAA,CAAA;AAAA,QACjC;AAAA,OACD,CAAA;AAAA,IACH,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,GAAA,YAAe,oBAAA,IAAwB,IAAA,CAAK,0BAAA,EAA4B;AAC1E,QAAA,OAAO,EAAE,SAAA,EAAW,IAAA,EAAM,QAAA,EAAU,WAAW,IAAA,EAAK;AAAA,MACtD;AACA,MAAA,MAAM,GAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QACJ,UAAA,EACA,QAAA,EACA,OAAoB,IAAA,EACpB,IAAA,GAA4B,EAAC,EACJ;AACzB,IAAA,IAAI,UAAA,CAAW,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AACrC,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,GAAA,CAAI,KAAK,OAAA,CAAwB;AAAA,MACxD,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,CAAA,cAAA,EAAiB,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA,oBAAA,CAAA;AAAA,MACtC,IAAA;AAAA,MACA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,QAAA,EAAU,WAAW,MAAA,EAAO;AAAA,MACrD,IAAA,EAAM;AAAA,KACP,CAAA;AACD,IAAA,MAAM,IAAA,uBAAW,GAAA,EAA0B;AAC3C,IAAA,KAAA,MAAW,CAAA,IAAK,OAAO,IAAI,CAAA,CAAE,WAAW,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,SAAA,EAAW,CAAC,CAAA;AAC/D,IAAA,OAAO,UAAA,CAAW,GAAA;AAAA,MAChB,CAAC,EAAA,KACC,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA,IAAK;AAAA,QACd,SAAA,EAAW,EAAA;AAAA,QACX,IAAA,EAAM,QAAA;AAAA,QACN,SAAA,EAAW,OAAA,CAAQ,IAAA,CAAK,0BAA0B;AAAA;AACpD,KACJ;AAAA,EACF;AACF","file":"chunk-XMEP74BU.js","sourcesContent":["import type { ClientContext } from \"../core/context\";\nimport type { AuthContext } from \"../core/auth\";\nimport { EmporixNotFoundError } from \"../core/errors\";\nimport type { AvailabilityWithBundle } from \"../generated/availability\";\n\n/**\n * Site-aware product availability. Mirrors the Emporix Availability Service\n * `AvailabilityWithBundle` shape (the single-product GET and the batch search\n * both return the bundle-aware variant). There is no restock-date field.\n */\nexport type Availability = AvailabilityWithBundle;\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\" };\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 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 });\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"]}
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-mMTqsW1Z.cjs';
1
+ import { C as ClientContext, b as AuthContext } from './context-Bs5ZSwds.cjs';
2
2
  import { L as LegalEntity, f as LegalEntityCreate, h as LegalEntityUpdate } from './types.gen-D1QuqPLs.cjs';
3
3
  export { A as AccountLimit, e as CustomerGroupRef, g as LegalEntityType, i as LegalInfo } from './types.gen-D1QuqPLs.cjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-mMTqsW1Z.js';
1
+ import { C as ClientContext, b as AuthContext } from './context-Bs5ZSwds.js';
2
2
  import { L as LegalEntity, f as LegalEntityCreate, h as LegalEntityUpdate } from './types.gen-D1QuqPLs.js';
3
3
  export { A as AccountLimit, e as CustomerGroupRef, g as LegalEntityType, i as LegalInfo } from './types.gen-D1QuqPLs.js';
4
4
 
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-mMTqsW1Z.cjs';
1
+ import { C as ClientContext, b as AuthContext } from './context-Bs5ZSwds.cjs';
2
2
  import { C as ContactAssignment, a as ContactAssignmentCreate, c as ContactAssignmentUpdate } from './types.gen-D1QuqPLs.cjs';
3
3
  export { b as ContactAssignmentType } from './types.gen-D1QuqPLs.cjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-mMTqsW1Z.js';
1
+ import { C as ClientContext, b as AuthContext } from './context-Bs5ZSwds.js';
2
2
  import { C as ContactAssignment, a as ContactAssignmentCreate, c as ContactAssignmentUpdate } from './types.gen-D1QuqPLs.js';
3
3
  export { b as ContactAssignmentType } from './types.gen-D1QuqPLs.js';
4
4
 
@@ -3,7 +3,7 @@ type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "silent";
3
3
  /** Numeric ordering used for fast comparison. */
4
4
  declare const LEVEL: Record<LogLevel, number>;
5
5
  /** Services that bind their own logger and are independently level-controllable. */
6
- type ServiceName = "customer" | "product" | "category" | "cart" | "checkout" | "payment" | "price" | "media" | "segment" | "site" | "session-context" | "customer-management" | "iam" | "orders" | "sales-orders" | "http" | "auth";
6
+ type ServiceName = "customer" | "product" | "category" | "cart" | "checkout" | "payment" | "price" | "media" | "segment" | "site" | "session-context" | "customer-management" | "iam" | "orders" | "sales-orders" | "availability" | "configuration" | "http" | "auth";
7
7
  /** Arbitrary structured fields attached to a log line. */
8
8
  interface LogFields {
9
9
  [key: string]: unknown;
@@ -3,7 +3,7 @@ type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "silent";
3
3
  /** Numeric ordering used for fast comparison. */
4
4
  declare const LEVEL: Record<LogLevel, number>;
5
5
  /** Services that bind their own logger and are independently level-controllable. */
6
- type ServiceName = "customer" | "product" | "category" | "cart" | "checkout" | "payment" | "price" | "media" | "segment" | "site" | "session-context" | "customer-management" | "iam" | "orders" | "sales-orders" | "http" | "auth";
6
+ type ServiceName = "customer" | "product" | "category" | "cart" | "checkout" | "payment" | "price" | "media" | "segment" | "site" | "session-context" | "customer-management" | "iam" | "orders" | "sales-orders" | "availability" | "configuration" | "http" | "auth";
7
7
  /** Arbitrary structured fields attached to a log line. */
8
8
  interface LogFields {
9
9
  [key: string]: unknown;
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-mMTqsW1Z.cjs';
1
+ import { C as ClientContext, b as AuthContext } from './context-Bs5ZSwds.cjs';
2
2
 
3
3
  /**
4
4
  * Hand-written mirror of the minimal IAM Service group shape needed for
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, b as AuthContext } from './context-mMTqsW1Z.js';
1
+ import { C as ClientContext, b as AuthContext } from './context-Bs5ZSwds.js';
2
2
 
3
3
  /**
4
4
  * Hand-written mirror of the minimal IAM Service group shape needed for
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, A as AnonymousSession, b as AuthContext } from './context-mMTqsW1Z.cjs';
1
+ import { C as ClientContext, A as AnonymousSession, b as AuthContext } from './context-Bs5ZSwds.cjs';
2
2
 
3
3
  type AccountId = {
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { C as ClientContext, A as AnonymousSession, b as AuthContext } from './context-mMTqsW1Z.js';
1
+ import { C as ClientContext, A as AnonymousSession, b as AuthContext } from './context-Bs5ZSwds.js';
2
2
 
3
3
  type AccountId = {
4
4
  /**
package/dist/index.cjs CHANGED
@@ -996,6 +996,69 @@ var ProductService = class {
996
996
  );
997
997
  return pages.flat();
998
998
  }
999
+ /**
1000
+ * Bulk fetch by code. POSTs `/products/search` with `q="code:(c1,c2,…)"`,
1001
+ * chunking when the list is larger than `options.chunkSize` (default 100).
1002
+ * Duplicate codes are de-duplicated. Codes containing query-delimiter
1003
+ * characters (`(`, `)`, `,`, whitespace, `"`) are dropped with a logged
1004
+ * warning, because the Emporix `q` syntax uses them as delimiters and does
1005
+ * not support escaping them in a plain IN-list. An empty list — or one with
1006
+ * no safe codes — short-circuits with no HTTP call. **Order is not
1007
+ * guaranteed** across chunks — re-index by `code` if order matters.
1008
+ */
1009
+ async searchByCodes(codes, options = {}, auth2 = ANON) {
1010
+ const unique = [...new Set(codes)];
1011
+ const unsafe = /[(),"\s]/;
1012
+ const safe = unique.filter((c) => !unsafe.test(c));
1013
+ const dropped = unique.filter((c) => unsafe.test(c));
1014
+ if (dropped.length > 0) {
1015
+ this.ctx.logger.warn(
1016
+ "products.searchByCodes: dropped codes containing query-delimiter characters",
1017
+ { dropped }
1018
+ );
1019
+ }
1020
+ if (safe.length === 0) return [];
1021
+ const chunkSize = options.chunkSize ?? 100;
1022
+ const chunks = [];
1023
+ for (let i = 0; i < safe.length; i += chunkSize) {
1024
+ chunks.push(safe.slice(i, i + chunkSize));
1025
+ }
1026
+ const pages = await Promise.all(
1027
+ chunks.map(
1028
+ (chunk) => this.ctx.http.request({
1029
+ method: "POST",
1030
+ path: `/product/${this.ctx.tenant}/products/search`,
1031
+ query: { pageSize: chunk.length },
1032
+ auth: auth2,
1033
+ body: { q: `code:(${chunk.join(",")})` }
1034
+ })
1035
+ )
1036
+ );
1037
+ return pages.flat();
1038
+ }
1039
+ /**
1040
+ * Streams the VARIANT children of a PARENT_VARIANT product, page by page,
1041
+ * via the search query `productType:VARIANT parentVariantId:<id>`. Default
1042
+ * pageSize 200. The query syntax (space-separated fields = implicit AND) is
1043
+ * encapsulated here so consumers don't build it themselves.
1044
+ */
1045
+ listVariantChildrenAll(parentVariantId, params = {}, auth2 = ANON) {
1046
+ const pageSize = params.pageSize ?? 200;
1047
+ const q = `productType:VARIANT parentVariantId:${parentVariantId}`;
1048
+ return iterateAll((pageNumber) => this.search(q, { pageNumber, pageSize }, auth2));
1049
+ }
1050
+ /**
1051
+ * Resolves ALL VARIANT children of a PARENT_VARIANT product into a flat
1052
+ * array (loads every page). Default pageSize 200. Returns `[]` when there are
1053
+ * no children — never throws.
1054
+ */
1055
+ async listVariantChildren(parentVariantId, params = {}, auth2 = ANON) {
1056
+ const out = [];
1057
+ for await (const child of this.listVariantChildrenAll(parentVariantId, params, auth2)) {
1058
+ out.push(child);
1059
+ }
1060
+ return out;
1061
+ }
999
1062
  };
1000
1063
 
1001
1064
  // src/services/category.ts
@@ -1362,6 +1425,50 @@ var PriceService = class {
1362
1425
  body: input
1363
1426
  });
1364
1427
  }
1428
+ /**
1429
+ * Chunked variant of {@link matchByContext} for large `items` arrays. The
1430
+ * Emporix backend handles only a limited number of items per request
1431
+ * (production limit ~50), so this splits `input.items` into chunks and runs
1432
+ * `matchByContext` with bounded concurrency.
1433
+ *
1434
+ * By default a failing chunk is skipped (its items are absent from the
1435
+ * result) and `opts.onChunkError` is called once for it; pass
1436
+ * `throwOnAnyChunkError: true` to reject on the first failure instead.
1437
+ *
1438
+ * **Result order is not guaranteed** — match entries back to your items by
1439
+ * `priceId` / `itemRef.id`.
1440
+ */
1441
+ async matchByContextChunked(input, opts = {}, auth2) {
1442
+ const chunkSize = opts.chunkSize ?? 50;
1443
+ const concurrency = opts.concurrency ?? 4;
1444
+ if (chunkSize < 1) throw new Error("chunkSize must be >= 1");
1445
+ if (concurrency < 1) throw new Error("concurrency must be >= 1");
1446
+ const items = input.items ?? [];
1447
+ if (items.length === 0) return [];
1448
+ const chunks = [];
1449
+ for (let i = 0; i < items.length; i += chunkSize) {
1450
+ chunks.push({ ...input, items: items.slice(i, i + chunkSize) });
1451
+ }
1452
+ const results = new Array(chunks.length);
1453
+ let cursor = 0;
1454
+ const worker = async () => {
1455
+ for (; ; ) {
1456
+ const idx = cursor++;
1457
+ const chunk = chunks[idx];
1458
+ if (chunk === void 0) return;
1459
+ try {
1460
+ results[idx] = await this.matchByContext(chunk, auth2);
1461
+ } catch (err) {
1462
+ if (opts.throwOnAnyChunkError) throw err;
1463
+ results[idx] = [];
1464
+ opts.onChunkError?.(err, idx);
1465
+ }
1466
+ }
1467
+ };
1468
+ const workerCount = Math.min(concurrency, chunks.length);
1469
+ await Promise.all(Array.from({ length: workerCount }, () => worker()));
1470
+ return results.flat();
1471
+ }
1365
1472
  };
1366
1473
 
1367
1474
  // src/services/media.ts
@@ -1813,12 +1920,12 @@ var SessionContextService = class {
1813
1920
  * update). Non-404 errors propagate.
1814
1921
  */
1815
1922
  async patch(input, authCtx = ANON5) {
1816
- let version = input.version;
1817
- if (version === void 0) {
1923
+ let version2 = input.version;
1924
+ if (version2 === void 0) {
1818
1925
  const current = await this.get(authCtx);
1819
1926
  if (current === null) return false;
1820
- version = current.metadata?.version;
1821
- if (version === void 0) {
1927
+ version2 = current.metadata?.version;
1928
+ if (version2 === void 0) {
1822
1929
  throw new Error(
1823
1930
  "SessionContextService.patch: no metadata.version in server response"
1824
1931
  );
@@ -1830,7 +1937,7 @@ var SessionContextService = class {
1830
1937
  path: `/session-context/${this.ctx.tenant}/me/context`,
1831
1938
  body: {
1832
1939
  ...fields,
1833
- metadata: { version }
1940
+ metadata: { version: version2 }
1834
1941
  },
1835
1942
  auth: authCtx
1836
1943
  });
@@ -2110,8 +2217,181 @@ var SalesOrdersService = class {
2110
2217
  }
2111
2218
  };
2112
2219
 
2220
+ // src/services/availability.ts
2221
+ var ANON6 = { kind: "anonymous" };
2222
+ var AvailabilityService = class {
2223
+ constructor(ctx) {
2224
+ this.ctx = ctx;
2225
+ }
2226
+ ctx;
2227
+ /**
2228
+ * Single product. Resolves the availability record, or — when
2229
+ * `opts.defaultAvailableOnNotFound` is set — a default available record on 404.
2230
+ */
2231
+ async get(productId, siteCode, auth2 = ANON6, opts = {}) {
2232
+ try {
2233
+ return await this.ctx.http.request({
2234
+ method: "GET",
2235
+ path: `/availability/${this.ctx.tenant}/availability/${encodeURIComponent(
2236
+ productId
2237
+ )}/${encodeURIComponent(siteCode)}`,
2238
+ auth: auth2
2239
+ });
2240
+ } catch (err) {
2241
+ if (err instanceof EmporixNotFoundError && opts.defaultAvailableOnNotFound) {
2242
+ return { productId, site: siteCode, available: true };
2243
+ }
2244
+ throw err;
2245
+ }
2246
+ }
2247
+ /**
2248
+ * Batch read via `POST .../availability/search` (one request). Products with
2249
+ * no availability record are absent from the response; each is synthesized as
2250
+ * `{ available: false }` (or `{ available: true }` when
2251
+ * `opts.defaultAvailableOnNotFound` is set). The result preserves input order
2252
+ * and length. An empty `productIds` resolves to `[]` without a request.
2253
+ */
2254
+ async getMany(productIds, siteCode, auth2 = ANON6, opts = {}) {
2255
+ if (productIds.length === 0) return [];
2256
+ const found = await this.ctx.http.request({
2257
+ method: "POST",
2258
+ path: `/availability/${this.ctx.tenant}/availability/search`,
2259
+ auth: auth2,
2260
+ query: { site: siteCode, pageSize: productIds.length },
2261
+ body: productIds
2262
+ });
2263
+ const byId = /* @__PURE__ */ new Map();
2264
+ for (const a of found) if (a.productId) byId.set(a.productId, a);
2265
+ return productIds.map(
2266
+ (id) => byId.get(id) ?? {
2267
+ productId: id,
2268
+ site: siteCode,
2269
+ available: Boolean(opts.defaultAvailableOnNotFound)
2270
+ }
2271
+ );
2272
+ }
2273
+ };
2274
+
2275
+ // src/services/tenant-config.ts
2276
+ var SERVICE3 = { kind: "service" };
2277
+ var TenantConfigService = class {
2278
+ constructor(ctx) {
2279
+ this.ctx = ctx;
2280
+ }
2281
+ ctx;
2282
+ base() {
2283
+ return `/configuration/${this.ctx.tenant}/configurations`;
2284
+ }
2285
+ /** List tenant configurations, optionally filtered by `keys`. */
2286
+ async list(opts = {}, auth2 = SERVICE3) {
2287
+ const query = opts.keys && opts.keys.length > 0 ? { keys: opts.keys.join(",") } : void 0;
2288
+ return this.ctx.http.request({
2289
+ method: "GET",
2290
+ path: this.base(),
2291
+ auth: auth2,
2292
+ ...query ? { query } : {}
2293
+ });
2294
+ }
2295
+ /** Retrieve one tenant configuration by key. */
2296
+ async get(key, auth2 = SERVICE3) {
2297
+ return this.ctx.http.request({
2298
+ method: "GET",
2299
+ path: `${this.base()}/${encodeURIComponent(key)}`,
2300
+ auth: auth2
2301
+ });
2302
+ }
2303
+ /** Create one or more tenant configurations (array in, array out). */
2304
+ async create(drafts, auth2 = SERVICE3) {
2305
+ return this.ctx.http.request({
2306
+ method: "POST",
2307
+ path: this.base(),
2308
+ auth: auth2,
2309
+ body: drafts
2310
+ });
2311
+ }
2312
+ /** Update one tenant configuration by key. */
2313
+ async update(key, draft, auth2 = SERVICE3) {
2314
+ return this.ctx.http.request({
2315
+ method: "PUT",
2316
+ path: `${this.base()}/${encodeURIComponent(key)}`,
2317
+ auth: auth2,
2318
+ body: draft
2319
+ });
2320
+ }
2321
+ /** Delete one tenant configuration by key. */
2322
+ async delete(key, auth2 = SERVICE3) {
2323
+ await this.ctx.http.request({
2324
+ method: "DELETE",
2325
+ path: `${this.base()}/${encodeURIComponent(key)}`,
2326
+ auth: auth2
2327
+ });
2328
+ }
2329
+ };
2330
+
2331
+ // src/services/client-config.ts
2332
+ var SERVICE4 = { kind: "service" };
2333
+ var ClientConfigService = class {
2334
+ constructor(ctx) {
2335
+ this.ctx = ctx;
2336
+ }
2337
+ ctx;
2338
+ base(client) {
2339
+ return `/configuration/${this.ctx.tenant}/clients/${encodeURIComponent(client)}/configurations`;
2340
+ }
2341
+ /** List a client's configurations, optionally filtered by `keys`. */
2342
+ async list(client, opts = {}, auth2 = SERVICE4) {
2343
+ const query = opts.keys && opts.keys.length > 0 ? { keys: opts.keys.join(",") } : void 0;
2344
+ return this.ctx.http.request({
2345
+ method: "GET",
2346
+ path: this.base(client),
2347
+ auth: auth2,
2348
+ ...query ? { query } : {}
2349
+ });
2350
+ }
2351
+ /** Retrieve one client configuration by key. */
2352
+ async get(client, key, auth2 = SERVICE4) {
2353
+ return this.ctx.http.request({
2354
+ method: "GET",
2355
+ path: `${this.base(client)}/${encodeURIComponent(key)}`,
2356
+ auth: auth2
2357
+ });
2358
+ }
2359
+ /** Create one or more client configurations. Injects `client` into each item. */
2360
+ async create(client, drafts, auth2 = SERVICE4) {
2361
+ const body = drafts.map((d) => ({ ...d, client }));
2362
+ return this.ctx.http.request({
2363
+ method: "POST",
2364
+ path: this.base(client),
2365
+ auth: auth2,
2366
+ body
2367
+ });
2368
+ }
2369
+ /** Update one client configuration by key. Injects `client` into the body. */
2370
+ async update(client, key, draft, auth2 = SERVICE4) {
2371
+ return this.ctx.http.request({
2372
+ method: "PUT",
2373
+ path: `${this.base(client)}/${encodeURIComponent(key)}`,
2374
+ auth: auth2,
2375
+ body: { ...draft, client }
2376
+ });
2377
+ }
2378
+ /** Delete one client configuration by key. */
2379
+ async delete(client, key, auth2 = SERVICE4) {
2380
+ await this.ctx.http.request({
2381
+ method: "DELETE",
2382
+ path: `${this.base(client)}/${encodeURIComponent(key)}`,
2383
+ auth: auth2
2384
+ });
2385
+ }
2386
+ };
2387
+
2388
+ // package.json
2389
+ var version = "2.2.0";
2390
+
2391
+ // src/version.ts
2392
+ var SDK_VERSION = version;
2393
+
2113
2394
  // src/client.ts
2114
- var SDK_VERSION = "0.0.0";
2115
2395
  var EmporixClient = class {
2116
2396
  customers;
2117
2397
  products;
@@ -2130,6 +2410,9 @@ var EmporixClient = class {
2130
2410
  customerGroups;
2131
2411
  orders;
2132
2412
  salesOrders;
2413
+ availability;
2414
+ tenantConfig;
2415
+ clientConfig;
2133
2416
  /** The validated tenant this client is bound to. */
2134
2417
  tenant;
2135
2418
  /**
@@ -2199,6 +2482,9 @@ var EmporixClient = class {
2199
2482
  this.customerGroups = new CustomerGroupsService(mk("iam"));
2200
2483
  this.orders = new OrdersService(mk("orders"));
2201
2484
  this.salesOrders = new SalesOrdersService(mk("sales-orders"));
2485
+ this.availability = new AvailabilityService(mk("availability"));
2486
+ this.tenantConfig = new TenantConfigService(mk("configuration"));
2487
+ this.clientConfig = new ClientConfigService(mk("configuration"));
2202
2488
  }
2203
2489
  /** Sets the runtime log level globally or for one service. */
2204
2490
  setLogLevel(level, opts = {}) {
@@ -2210,9 +2496,11 @@ var EmporixClient = class {
2210
2496
  }
2211
2497
  };
2212
2498
 
2499
+ exports.AvailabilityService = AvailabilityService;
2213
2500
  exports.CartService = CartService;
2214
2501
  exports.CategoryService = CategoryService;
2215
2502
  exports.CheckoutService = CheckoutService;
2503
+ exports.ClientConfigService = ClientConfigService;
2216
2504
  exports.CompaniesService = CompaniesService;
2217
2505
  exports.ContactsService = ContactsService;
2218
2506
  exports.CustomerGroupsService = CustomerGroupsService;
@@ -2240,6 +2528,7 @@ exports.SalesOrdersService = SalesOrdersService;
2240
2528
  exports.SegmentService = SegmentService;
2241
2529
  exports.SessionContextService = SessionContextService;
2242
2530
  exports.SiteService = SiteService;
2531
+ exports.TenantConfigService = TenantConfigService;
2243
2532
  exports.auth = auth;
2244
2533
  exports.createConsoleLogger = createConsoleLogger;
2245
2534
  exports.createNoopLogger = createNoopLogger;