@viu/emporix-sdk 4.0.1 → 4.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 (67) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/README.md +1 -0
  3. package/dist/cart.cjs +85 -0
  4. package/dist/cart.cjs.map +1 -1
  5. package/dist/cart.d.cts +352 -1
  6. package/dist/cart.d.ts +352 -1
  7. package/dist/cart.js +1 -1
  8. package/dist/{chunk-QQMLN76U.js → chunk-2OTFVTG6.js} +7 -4
  9. package/dist/chunk-2OTFVTG6.js.map +1 -0
  10. package/dist/{chunk-CSYXGTOH.js → chunk-5MPL4XBD.js} +68 -4
  11. package/dist/chunk-5MPL4XBD.js.map +1 -0
  12. package/dist/{chunk-P3RANRGB.js → chunk-IYNT5BQW.js} +16 -2
  13. package/dist/chunk-IYNT5BQW.js.map +1 -0
  14. package/dist/{chunk-ZOFGDNSX.js → chunk-K4KXT6NX.js} +12 -6
  15. package/dist/chunk-K4KXT6NX.js.map +1 -0
  16. package/dist/{chunk-XJJDCK2Z.js → chunk-N2CE3J4M.js} +12 -7
  17. package/dist/chunk-N2CE3J4M.js.map +1 -0
  18. package/dist/{chunk-YVZ6GOLE.js → chunk-S2ERKGYL.js} +48 -3
  19. package/dist/chunk-S2ERKGYL.js.map +1 -0
  20. package/dist/{chunk-5XZ6MSXW.js → chunk-VXORPTMP.js} +19 -2
  21. package/dist/chunk-VXORPTMP.js.map +1 -0
  22. package/dist/chunk-ZWJUDXTK.js +15 -0
  23. package/dist/chunk-ZWJUDXTK.js.map +1 -0
  24. package/dist/companies.cjs +15 -2
  25. package/dist/companies.cjs.map +1 -1
  26. package/dist/companies.d.cts +5 -3
  27. package/dist/companies.d.ts +5 -3
  28. package/dist/companies.js +2 -1
  29. package/dist/customer-groups.cjs +17 -0
  30. package/dist/customer-groups.cjs.map +1 -1
  31. package/dist/customer-groups.js +1 -1
  32. package/dist/index.cjs +259 -58
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +150 -28
  35. package/dist/index.d.ts +150 -28
  36. package/dist/index.js +99 -59
  37. package/dist/index.js.map +1 -1
  38. package/dist/media.cjs +66 -2
  39. package/dist/media.cjs.map +1 -1
  40. package/dist/media.d.cts +184 -5
  41. package/dist/media.d.ts +184 -5
  42. package/dist/media.js +1 -1
  43. package/dist/orders.cjs +14 -0
  44. package/dist/orders.cjs.map +1 -1
  45. package/dist/orders.d.cts +6 -0
  46. package/dist/orders.d.ts +6 -0
  47. package/dist/orders.js +1 -1
  48. package/dist/price.cjs +20 -4
  49. package/dist/price.cjs.map +1 -1
  50. package/dist/price.d.cts +12 -4
  51. package/dist/price.d.ts +12 -4
  52. package/dist/price.js +2 -1
  53. package/dist/search-DU6tE356.d.cts +15 -0
  54. package/dist/search-DU6tE356.d.ts +15 -0
  55. package/dist/segment.cjs +21 -5
  56. package/dist/segment.cjs.map +1 -1
  57. package/dist/segment.d.cts +16 -6
  58. package/dist/segment.d.ts +16 -6
  59. package/dist/segment.js +2 -1
  60. package/package.json +1 -1
  61. package/dist/chunk-5XZ6MSXW.js.map +0 -1
  62. package/dist/chunk-CSYXGTOH.js.map +0 -1
  63. package/dist/chunk-P3RANRGB.js.map +0 -1
  64. package/dist/chunk-QQMLN76U.js.map +0 -1
  65. package/dist/chunk-XJJDCK2Z.js.map +0 -1
  66. package/dist/chunk-YVZ6GOLE.js.map +0 -1
  67. package/dist/chunk-ZOFGDNSX.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1242,7 +1242,7 @@ var HttpClient = class {
1242
1242
  };
1243
1243
 
1244
1244
  // package.json
1245
- var version = "4.0.1";
1245
+ var version = "4.2.0";
1246
1246
 
1247
1247
  // src/version.ts
1248
1248
  var SDK_VERSION = version;
@@ -2865,6 +2865,51 @@ var CartService = class {
2865
2865
  auth: requireCartAuth(auth2)
2866
2866
  });
2867
2867
  }
2868
+ /**
2869
+ * Runs up to 10 cart commands on this cart in one request, in order
2870
+ * (`POST /carts/{cartId}/execute`). The typical chain is `AddCartItem` then
2871
+ * `GetCart`: the calculated cart comes back without a second round trip.
2872
+ *
2873
+ * - `onError: "fail"` (default) stops at the first command that does not
2874
+ * answer 2xx and **throws the error that command's REST call would have
2875
+ * thrown** — an `EmporixNotFoundError` for a 404, … — with the command's
2876
+ * error body. The commands before it **have already been applied**.
2877
+ * - `onError: "resume"` runs every command and resolves with all results;
2878
+ * check each `code`.
2879
+ * - A `400` for the whole request (no commands or more than 10, an unknown
2880
+ * type, `versioning: "explicit"` without a `resourceVersion`) means no
2881
+ * command ran.
2882
+ *
2883
+ * The request takes about as long as its commands together — size the
2884
+ * client's `timeouts.readMs` for long chains. It is never retried: a replay
2885
+ * would apply the writes twice.
2886
+ *
2887
+ * `auth` is forwarded unguarded: a customer or anonymous token works on the
2888
+ * shopper's own cart; a service token needs `cart.cart_manage`, plus
2889
+ * `cart.cart_manage_external_prices` when a command carries an external
2890
+ * price, product, fee or discount.
2891
+ */
2892
+ async execute(cartId, commands, auth2, opts = {}) {
2893
+ const path = `${this.base()}/${encodeURIComponent(cartId)}/execute`;
2894
+ const res = await this.ctx.http.request({
2895
+ method: "POST",
2896
+ path,
2897
+ auth: auth2,
2898
+ query: { ...opts },
2899
+ body: { commands }
2900
+ });
2901
+ if (opts.onError !== "resume") {
2902
+ const failed = res.results.find((r) => r.code < 200 || r.code > 299);
2903
+ if (failed) {
2904
+ throw errorFromResponse(
2905
+ failed.code,
2906
+ `POST ${path} \u2192 command ${failed.index} (${failed.type}) \u2192 ${failed.code}`,
2907
+ failed.data
2908
+ );
2909
+ }
2910
+ }
2911
+ return res;
2912
+ }
2868
2913
  };
2869
2914
 
2870
2915
  // src/services/checkout.ts
@@ -3075,6 +3120,18 @@ var PaymentGatewayService = class {
3075
3120
  };
3076
3121
  };
3077
3122
 
3123
+ // src/core/search.ts
3124
+ var SEARCH_PAGING = ["pageNumber", "pageSize", "sort", "fields"];
3125
+ function splitQuery(input, queryKeys) {
3126
+ const body = {};
3127
+ const query = {};
3128
+ for (const [key, value] of Object.entries(input)) {
3129
+ if (queryKeys.includes(key)) query[key] = value;
3130
+ else body[key] = value;
3131
+ }
3132
+ return { body, query };
3133
+ }
3134
+
3078
3135
  // src/services/price.ts
3079
3136
  function normalizeMatch(raw) {
3080
3137
  const itemId = raw.itemId ?? raw.itemRef;
@@ -3220,13 +3277,16 @@ var PriceService = class {
3220
3277
  auth: authCtx
3221
3278
  });
3222
3279
  }
3223
- /** Searches flat prices (POST body query). Default auth: service. */
3280
+ /**
3281
+ * Searches flat prices: the criteria go in the body, `expand` in the query
3282
+ * string. Default auth: service.
3283
+ */
3224
3284
  async search(query, authCtx = SERVICE4) {
3225
3285
  return this.ctx.http.request({
3226
3286
  method: "POST",
3227
3287
  path: `/price/${this.ctx.tenant}/prices/search`,
3228
3288
  auth: authCtx,
3229
- body: query
3289
+ ...splitQuery(query, ["expand"])
3230
3290
  });
3231
3291
  }
3232
3292
  /** Creates multiple flat prices in one request. Default auth: service. */
@@ -3294,11 +3354,12 @@ var PriceService = class {
3294
3354
  auth: authCtx,
3295
3355
  body: input
3296
3356
  }),
3357
+ /** `q` in the body; `pageNumber`, `pageSize` and `sort` in the query string. */
3297
3358
  search: async (query, authCtx = SERVICE4) => this.ctx.http.request({
3298
3359
  method: "POST",
3299
3360
  path: `/price/${this.ctx.tenant}/price-lists/search`,
3300
3361
  auth: authCtx,
3301
- body: query
3362
+ ...splitQuery(query, ["pageNumber", "pageSize", "sort"])
3302
3363
  }),
3303
3364
  get: async (listId, authCtx = SERVICE4) => this.ctx.http.request({
3304
3365
  method: "GET",
@@ -3348,11 +3409,12 @@ var PriceService = class {
3348
3409
  auth: authCtx
3349
3410
  });
3350
3411
  },
3412
+ /** `q` in the body; `pageNumber`, `pageSize` and `sort` in the query string. */
3351
3413
  searchPrices: async (listId, query, authCtx = SERVICE4) => this.ctx.http.request({
3352
3414
  method: "POST",
3353
3415
  path: `/price/${this.ctx.tenant}/price-lists/${listId}/prices/search`,
3354
3416
  auth: authCtx,
3355
- body: query
3417
+ ...splitQuery(query, ["pageNumber", "pageSize", "sort"])
3356
3418
  }),
3357
3419
  bulkCreatePrices: async (listId, inputs, authCtx = SERVICE4) => this.ctx.http.request({
3358
3420
  method: "POST",
@@ -3389,7 +3451,10 @@ var MediaService = class {
3389
3451
  base() {
3390
3452
  return `/media/${this.ctx.tenant}/assets`;
3391
3453
  }
3392
- /** Create an asset. BLOB uploads via multipart; LINK via JSON. */
3454
+ /**
3455
+ * Create an asset. BLOB uploads via multipart (max 30 MB); LINK via JSON.
3456
+ * {@link startUploadSession} sends the file straight to storage instead.
3457
+ */
3393
3458
  async create(input, auth2 = SERVICE5) {
3394
3459
  if (input.kind === "blob") {
3395
3460
  const fd = new FormData();
@@ -3447,7 +3512,7 @@ var MediaService = class {
3447
3512
  * Sends `application/json`. Used for `refIds`, `details`, `metadata`,
3448
3513
  * or `url` changes.
3449
3514
  * - `{ kind: "blob", file, body }` — replaces the BLOB file content
3450
- * (max 10MB) AND patches metadata in the same request. Sends
3515
+ * (max 30 MB) AND patches metadata in the same request. Sends
3451
3516
  * `multipart/form-data`.
3452
3517
  *
3453
3518
  * `type` and `access` are immutable per Emporix — they must match the
@@ -3521,6 +3586,12 @@ var MediaService = class {
3521
3586
  * an `ArrayBuffer` transparently; binary Content-Types are passed
3522
3587
  * through verbatim.
3523
3588
  *
3589
+ * Emporix recommends {@link getDownloadUrl} for every download: here the file
3590
+ * passes through the Media API. A `413` means the asset's known size exceeds
3591
+ * the streaming limit (30 MB by default) — only {@link getDownloadUrl} can
3592
+ * serve it. A `409` means the asset is still `PENDING` from a direct upload
3593
+ * whose file has not reached storage.
3594
+ *
3524
3595
  * Implementation note: uses `redirect: "manual"` so the redirect-location
3525
3596
  * is observable. In Node.js this works; in a browser the redirect Location
3526
3597
  * is intentionally hidden by fetch — there, `PUBLIC` downloads will
@@ -3576,6 +3647,61 @@ var MediaService = class {
3576
3647
  }
3577
3648
  throw errorFromResponse(res.status, `GET ${path} \u2192 ${res.status}`, parsed);
3578
3649
  }
3650
+ /**
3651
+ * Get a URL that serves the stored file straight from storage
3652
+ * (`GET /assets/{assetId}/download-url`). Emporix recommends it for every
3653
+ * download: the file never passes through the Media API, there is no size
3654
+ * limit, and the URL can be handed to a browser as it is.
3655
+ *
3656
+ * - `PRIVATE` BLOB → `provider: "GCS"`, a signed Google Cloud Storage URL that
3657
+ * works without an Emporix token until `expiresAt` (15 minutes by default).
3658
+ * - `PUBLIC` BLOB → `provider: "CLOUDINARY"`, the permanent URL.
3659
+ * - `LINK` → `provider: "LINK"`, the stored URL.
3660
+ *
3661
+ * `disposition` (`attachment` by default, or `inline`) affects private URLs
3662
+ * only. Unlike {@link startUploadSession}, this works whether or not direct
3663
+ * upload is enabled for the tenant. A `409` means a direct upload is still
3664
+ * `PENDING` and its file has not reached storage; once it has, this call
3665
+ * completes the asset before answering.
3666
+ */
3667
+ async getDownloadUrl(assetId, query = {}, auth2 = SERVICE5) {
3668
+ return this.ctx.http.request({
3669
+ method: "GET",
3670
+ path: `${this.base()}/${encodeURIComponent(assetId)}/download-url`,
3671
+ auth: auth2,
3672
+ query: { ...query }
3673
+ });
3674
+ }
3675
+ /**
3676
+ * Start a direct upload of a `BLOB` asset (`POST /assets/upload-session`,
3677
+ * `201`). Emporix creates the asset as `PENDING` — `id` is its id — and
3678
+ * returns where to send the file. **This method does not send it**:
3679
+ *
3680
+ * - `upload.method === "PUT"` (a `PRIVATE` asset, `uploadType: "put"` or
3681
+ * omitted): `PUT` the file to `upload.url` with every `upload.headers` entry.
3682
+ * - `upload.method === "POST"` (every `PUBLIC` asset, or `uploadType: "form"`):
3683
+ * a multipart `POST` to `upload.url` with every `upload.fields` entry
3684
+ * unchanged and the file part last.
3685
+ *
3686
+ * That request goes to Google Cloud Storage or Cloudinary, not to Emporix, so
3687
+ * it must not carry the Emporix token — which is also why a browser can make
3688
+ * it. The asset turns `READY` once storage confirms; until then, calls that
3689
+ * need the file answer `409`. The instruction is valid for 15 minutes (GCS) or
3690
+ * an hour (Cloudinary), and an unused session expires at `expiresAt`.
3691
+ *
3692
+ * Direct upload is enabled per tenant by Emporix Support. Without it the call
3693
+ * throws an `EmporixForbiddenError` whose `body.message` is `direct upload is
3694
+ * not enabled for this tenant`, and nothing is created — the same status as a
3695
+ * missing scope, so read the message.
3696
+ */
3697
+ async startUploadSession(input, auth2 = SERVICE5) {
3698
+ return this.ctx.http.request({
3699
+ method: "POST",
3700
+ path: `${this.base()}/upload-session`,
3701
+ auth: auth2,
3702
+ body: input
3703
+ });
3704
+ }
3579
3705
  /** Multipart upload sugar: builds `AssetCreateBlob` from input. */
3580
3706
  async uploadFile(input, auth2 = SERVICE5) {
3581
3707
  const body = {
@@ -3820,13 +3946,17 @@ var SegmentService = class {
3820
3946
  async create(input, authCtx = SERVICE6) {
3821
3947
  return this.ctx.http.request({ method: "POST", path: this.base(), auth: authCtx, body: input });
3822
3948
  }
3823
- /** Searches segments (POST body). Default auth: service. */
3949
+ /**
3950
+ * Searches segments: `q` in the body; paging, sort, fields, `legalEntityId`
3951
+ * and `customerId` in the query string. `customerId` returns that customer's
3952
+ * segments and needs `customersegment.segment_read`. Default auth: service.
3953
+ */
3824
3954
  async search(query, authCtx = SERVICE6) {
3825
3955
  return this.ctx.http.request({
3826
3956
  method: "POST",
3827
3957
  path: `${this.base()}/search`,
3828
3958
  auth: authCtx,
3829
- body: query
3959
+ ...splitQuery(query, [...SEARCH_PAGING, "legalEntityId", "customerId"])
3830
3960
  });
3831
3961
  }
3832
3962
  /** Full-replaces a segment (PUT). Default auth: service. */
@@ -3903,7 +4033,7 @@ var SegmentService = class {
3903
4033
  method: "POST",
3904
4034
  path: `${this.base()}/${segmentId}/customers/search`,
3905
4035
  auth: authCtx,
3906
- body: query
4036
+ ...splitQuery(query, SEARCH_PAGING)
3907
4037
  }),
3908
4038
  get: async (segmentId, customerId, authCtx = SERVICE6) => this.ctx.http.request({
3909
4039
  method: "GET",
@@ -3978,7 +4108,7 @@ var SegmentService = class {
3978
4108
  method: "POST",
3979
4109
  path: `${this.base()}/${encodeURIComponent(segmentId)}/groups/search`,
3980
4110
  auth: authCtx,
3981
- body: query
4111
+ ...splitQuery(query, SEARCH_PAGING)
3982
4112
  }),
3983
4113
  get: async (segmentId, groupId, authCtx = SERVICE6) => this.ctx.http.request({
3984
4114
  method: "GET",
@@ -4012,7 +4142,7 @@ var SegmentService = class {
4012
4142
  method: "POST",
4013
4143
  path: `${this.base()}/${segmentId}/items/search`,
4014
4144
  auth: authCtx,
4015
- body: query
4145
+ ...splitQuery(query, [...SEARCH_PAGING, "legalEntityId"])
4016
4146
  }),
4017
4147
  get: async (segmentId, type, itemId, authCtx = SERVICE6) => this.ctx.http.request({
4018
4148
  method: "GET",
@@ -4336,14 +4466,15 @@ var CompaniesService = class {
4336
4466
  }
4337
4467
  /**
4338
4468
  * Searches legal entities via `POST /legal-entities/search` with an Emporix
4339
- * `q`-syntax filter body. Requires the same read scope as {@link listMine}.
4469
+ * `q`-syntax filter body; paging, sort and fields go in the query string.
4470
+ * Requires the same read scope as {@link listMine}.
4340
4471
  */
4341
4472
  async search(query, auth2) {
4342
4473
  return this.ctx.http.request({
4343
4474
  method: "POST",
4344
4475
  path: `${this.base()}/search`,
4345
4476
  auth: auth2,
4346
- body: query,
4477
+ ...splitQuery(query, SEARCH_PAGING),
4347
4478
  idempotent: true
4348
4479
  // pure read over POST — safe to replay on 5xx/429
4349
4480
  });
@@ -4529,11 +4660,28 @@ var IamService = class {
4529
4660
  auth: auth2
4530
4661
  });
4531
4662
  },
4663
+ /**
4664
+ * Lists one vendor's Management Dashboard users, with their groups
4665
+ * (`GET /users/vendors/{vendorId}`).
4666
+ */
4667
+ listForVendor: async (vendorId, auth2) => this.ctx.http.request({
4668
+ method: "GET",
4669
+ path: `${this.base()}/users/vendors/${encodeURIComponent(vendorId)}`,
4670
+ auth: auth2
4671
+ }),
4532
4672
  getGroups: async (userId, auth2) => this.ctx.http.request({
4533
4673
  method: "GET",
4534
4674
  path: `${this.base()}/users/${userId}/groups`,
4535
4675
  auth: auth2
4536
4676
  }),
4677
+ /** Removes a user from every group at once (`DELETE /users/{userId}/groups`, `204`). */
4678
+ removeFromAllGroups: async (userId, auth2) => {
4679
+ await this.ctx.http.request({
4680
+ method: "DELETE",
4681
+ path: `${this.base()}/users/${encodeURIComponent(userId)}/groups`,
4682
+ auth: auth2
4683
+ });
4684
+ },
4537
4685
  /**
4538
4686
  * Reads one of a user's groups (`GET /users/{userId}/groups/{groupId}`).
4539
4687
  * The collection read above returns the same shape per entry; this exists
@@ -4772,6 +4920,20 @@ var OrdersService = class {
4772
4920
  ...headers ? { headers } : {}
4773
4921
  });
4774
4922
  }
4923
+ /**
4924
+ * The status transitions the customer may trigger on one of their orders
4925
+ * (`GET /orders/{orderId}/transitions`) — for example whether it can still be
4926
+ * cancelled, before offering {@link cancel}.
4927
+ */
4928
+ async listTransitions(orderId, auth2, opts = {}) {
4929
+ const headers = this.saasHeader(opts.saasToken);
4930
+ return this.ctx.http.request({
4931
+ method: "GET",
4932
+ path: `${this.base()}/${encodeURIComponent(orderId)}/transitions`,
4933
+ auth: auth2,
4934
+ ...headers ? { headers } : {}
4935
+ });
4936
+ }
4775
4937
  /** Transitions an order to a new status. Server enforces legal transitions. */
4776
4938
  async transition(orderId, status, auth2, opts = {}) {
4777
4939
  const body = { status };
@@ -5317,6 +5479,21 @@ var ClientConfigService = class {
5317
5479
 
5318
5480
  // src/services/shopping-list.ts
5319
5481
  var RESERVED = /* @__PURE__ */ new Set(["customerId", "metadata"]);
5482
+ function toLists(env) {
5483
+ const out = [];
5484
+ for (const [key, value] of Object.entries(env)) {
5485
+ if (RESERVED.has(key) || value === null || typeof value !== "object") continue;
5486
+ const v = value;
5487
+ out.push({
5488
+ key,
5489
+ name: v.name ?? key,
5490
+ items: v.items ?? [],
5491
+ ...v.mixins ? { mixins: v.mixins } : {},
5492
+ ...v.metadata ? { metadata: v.metadata } : {}
5493
+ });
5494
+ }
5495
+ return out;
5496
+ }
5320
5497
  var ShoppingListService = class {
5321
5498
  constructor(ctx) {
5322
5499
  this.ctx = ctx;
@@ -5326,7 +5503,11 @@ var ShoppingListService = class {
5326
5503
  base() {
5327
5504
  return `/shoppinglist/${this.ctx.tenant}/shopping-lists`;
5328
5505
  }
5329
- /** The caller's lists (or, with employee scope, all), normalized to an array. */
5506
+ /**
5507
+ * The caller's lists, normalized to an array. With employee scope Emporix
5508
+ * returns **every customer's** lists and ignores `name` — read one customer's
5509
+ * with {@link getForCustomer} instead.
5510
+ */
5330
5511
  async list(auth2, opts = {}) {
5331
5512
  const envelopes = await this.ctx.http.request({
5332
5513
  method: "GET",
@@ -5334,21 +5515,20 @@ var ShoppingListService = class {
5334
5515
  auth: auth2,
5335
5516
  ...opts.name ? { query: { name: opts.name } } : {}
5336
5517
  });
5337
- const out = [];
5338
- for (const env of envelopes ?? []) {
5339
- for (const [key, value] of Object.entries(env)) {
5340
- if (RESERVED.has(key) || value === null || typeof value !== "object") continue;
5341
- const v = value;
5342
- out.push({
5343
- key,
5344
- name: v.name ?? key,
5345
- items: v.items ?? [],
5346
- ...v.mixins ? { mixins: v.mixins } : {},
5347
- ...v.metadata ? { metadata: v.metadata } : {}
5348
- });
5349
- }
5350
- }
5351
- return out;
5518
+ return (envelopes ?? []).flatMap(toLists);
5519
+ }
5520
+ /**
5521
+ * One customer's lists (`GET /shopping-lists/{customerId}`), normalized to an
5522
+ * array — the employee read; `name` narrows it to one list.
5523
+ */
5524
+ async getForCustomer(customerId, auth2, opts = {}) {
5525
+ const envelope = await this.ctx.http.request({
5526
+ method: "GET",
5527
+ path: `${this.base()}/${encodeURIComponent(customerId)}`,
5528
+ auth: auth2,
5529
+ ...opts.name ? { query: { name: opts.name } } : {}
5530
+ });
5531
+ return envelope ? toLists(envelope) : [];
5352
5532
  }
5353
5533
  /** Create a list; returns the new list id. */
5354
5534
  async create(draft, auth2) {
@@ -5377,8 +5557,8 @@ var ShoppingListService = class {
5377
5557
  ...opts.name ? { query: { name: opts.name } } : {}
5378
5558
  });
5379
5559
  }
5380
- async loadList(listName, auth2) {
5381
- const lists = await this.list(auth2, { name: listName });
5560
+ async loadList(customerId, listName, auth2) {
5561
+ const lists = auth2.kind === "service" ? await this.getForCustomer(customerId, auth2, { name: listName }) : await this.list(auth2, { name: listName });
5382
5562
  const found = lists.find((l) => l.name === listName);
5383
5563
  if (!found) throw new EmporixNotFoundError(`Shopping list "${listName}" not found`, 404);
5384
5564
  return found;
@@ -5392,20 +5572,20 @@ var ShoppingListService = class {
5392
5572
  }
5393
5573
  /** Add/replace an item by `productId` (read-modify-write, last-write-wins). */
5394
5574
  async addItem(customerId, listName, item, auth2) {
5395
- const list = await this.loadList(listName, auth2);
5575
+ const list = await this.loadList(customerId, listName, auth2);
5396
5576
  const items = [...list.items.filter((i) => i.productId !== item.productId), item];
5397
5577
  await this.put(customerId, list, items, auth2);
5398
5578
  }
5399
5579
  /** Remove an item by `productId` (no-op if absent). */
5400
5580
  async removeItem(customerId, listName, productId, auth2) {
5401
- const list = await this.loadList(listName, auth2);
5581
+ const list = await this.loadList(customerId, listName, auth2);
5402
5582
  const items = list.items.filter((i) => i.productId !== productId);
5403
5583
  await this.put(customerId, list, items, auth2);
5404
5584
  }
5405
5585
  /** Set an item's quantity; `quantity <= 0` removes it. Adds the item if absent. */
5406
5586
  async setItemQuantity(customerId, listName, productId, quantity, auth2) {
5407
5587
  if (quantity <= 0) return this.removeItem(customerId, listName, productId, auth2);
5408
- const list = await this.loadList(listName, auth2);
5588
+ const list = await this.loadList(customerId, listName, auth2);
5409
5589
  let items = list.items.map((i) => i.productId === productId ? { ...i, quantity } : i);
5410
5590
  if (!items.some((i) => i.productId === productId)) items = [...items, { productId, quantity }];
5411
5591
  await this.put(customerId, list, items, auth2);
@@ -5738,13 +5918,14 @@ var FeeService = class {
5738
5918
  * Finds item fees for several products on one site
5739
5919
  * (`POST /itemFees/searchByProductIds`). Note the upstream asymmetry:
5740
5920
  * `productIds` is a comma-separated **string** and `siteCode` is singular.
5921
+ * `siteFallback` goes in the query string, everything else in the body.
5741
5922
  */
5742
5923
  async searchItemFeesByProductIds(search, auth2 = SERVICE13) {
5743
5924
  return this.ctx.http.request({
5744
5925
  method: "POST",
5745
5926
  path: `${this.itemFeesBase()}/searchByProductIds`,
5746
5927
  auth: auth2,
5747
- body: search,
5928
+ ...splitQuery(search, ["siteFallback"]),
5748
5929
  idempotent: true
5749
5930
  // pure read over POST — safe to replay on 5xx/429
5750
5931
  });
@@ -6350,9 +6531,9 @@ var AgenticCrudResource = class {
6350
6531
  list(query = {}, auth2 = SERVICE16) {
6351
6532
  return this.ctx.http.request({ method: "GET", path: this.path, auth: auth2, query: { ...query } });
6352
6533
  }
6353
- /** Structured search (`POST {path}/search`). Body is `{ q? }`. */
6534
+ /** Structured search (`POST {path}/search`): `q` in the body, paging/sort/fields in the query. */
6354
6535
  search(query, auth2 = SERVICE16) {
6355
- return this.ctx.http.request({ method: "POST", path: `${this.path}/search`, auth: auth2, body: query });
6536
+ return this.ctx.http.request({ method: "POST", path: `${this.path}/search`, auth: auth2, ...splitQuery(query, SEARCH_PAGING) });
6356
6537
  }
6357
6538
  /** Retrieve one entry by id (`GET {path}/{id}`). */
6358
6539
  get(id, opts = {}, auth2 = SERVICE16) {
@@ -6402,7 +6583,7 @@ var JobsResource = class {
6402
6583
  }
6403
6584
  /** Structured job search (`POST /jobs/search`). */
6404
6585
  search(query, auth2 = SERVICE16) {
6405
- return this.ctx.http.request({ method: "POST", path: `${this.base}/jobs/search`, auth: auth2, body: query });
6586
+ return this.ctx.http.request({ method: "POST", path: `${this.base}/jobs/search`, auth: auth2, ...splitQuery(query, SEARCH_PAGING) });
6406
6587
  }
6407
6588
  /** Retrieve one job (`GET /jobs/{jobId}`). */
6408
6589
  get(jobId, auth2 = SERVICE16) {
@@ -6426,7 +6607,7 @@ var TemplatesResource = class {
6426
6607
  }
6427
6608
  /** Structured template search (`POST /agentic/templates/search`). */
6428
6609
  search(query, auth2 = SERVICE16) {
6429
- return this.ctx.http.request({ method: "POST", path: `${this.path}/search`, auth: auth2, body: query });
6610
+ return this.ctx.http.request({ method: "POST", path: `${this.path}/search`, auth: auth2, ...splitQuery(query, SEARCH_PAGING) });
6430
6611
  }
6431
6612
  /**
6432
6613
  * Instantiate a new agent from a template
@@ -6459,7 +6640,7 @@ var LogsResource = class {
6459
6640
  }
6460
6641
  /** Structured request-log search (`POST /agentic/logs/requests/search`). */
6461
6642
  searchRequests(query, auth2 = SERVICE16) {
6462
- return this.ctx.http.request({ method: "POST", path: `${this.path}/requests/search`, auth: auth2, body: query });
6643
+ return this.ctx.http.request({ method: "POST", path: `${this.path}/requests/search`, auth: auth2, ...splitQuery(query, SEARCH_PAGING) });
6463
6644
  }
6464
6645
  /** List session logs (`GET /agentic/logs/sessions`). */
6465
6646
  listSessions(query = {}, auth2 = SERVICE16) {
@@ -6471,7 +6652,7 @@ var LogsResource = class {
6471
6652
  }
6472
6653
  /** Structured session-log search (`POST /agentic/logs/sessions/search`). */
6473
6654
  searchSessions(query, auth2 = SERVICE16) {
6474
- return this.ctx.http.request({ method: "POST", path: `${this.path}/sessions/search`, auth: auth2, body: query });
6655
+ return this.ctx.http.request({ method: "POST", path: `${this.path}/sessions/search`, auth: auth2, ...splitQuery(query, SEARCH_PAGING) });
6475
6656
  }
6476
6657
  };
6477
6658
  var AnalyticsResource = class {
@@ -6503,6 +6684,10 @@ function assertChatOptions(opts, method) {
6503
6684
  function sessionHeader(opts) {
6504
6685
  return opts.sessionId ? { headers: { "session-id": opts.sessionId } } : {};
6505
6686
  }
6687
+ var AUTH_KINDS = /* @__PURE__ */ new Set(["service", "anonymous", "customer", "raw"]);
6688
+ function isAuthContext(value) {
6689
+ return AUTH_KINDS.has(String(value.kind));
6690
+ }
6506
6691
  var AiService = class {
6507
6692
  constructor(ctx) {
6508
6693
  this.ctx = ctx;
@@ -6571,12 +6756,13 @@ var AiService = class {
6571
6756
  body: input
6572
6757
  });
6573
6758
  }
6574
- /** List all agentic agents. */
6575
- async listAgents(auth2 = SERVICE17) {
6759
+ async listAgents(queryOrAuth = {}, auth2 = SERVICE17) {
6760
+ const [query, ctx] = isAuthContext(queryOrAuth) ? [{}, queryOrAuth] : [queryOrAuth, auth2];
6576
6761
  return this.ctx.http.request({
6577
6762
  method: "GET",
6578
6763
  path: `${this.base()}/agentic/agents`,
6579
- auth: auth2
6764
+ auth: ctx,
6765
+ query: { ...query }
6580
6766
  });
6581
6767
  }
6582
6768
  /** Retrieve one agent by id. */
@@ -6621,13 +6807,16 @@ var AiService = class {
6621
6807
  ...opts.force ? { query: { force: "true" } } : {}
6622
6808
  });
6623
6809
  }
6624
- /** Server-side agent search (`POST /agentic/agents/search`). */
6810
+ /**
6811
+ * Server-side agent search (`POST /agentic/agents/search`). `q` goes in the
6812
+ * body; `pageNumber`, `pageSize`, `sort` and `fields` in the query string.
6813
+ */
6625
6814
  async searchAgents(query, auth2 = SERVICE17) {
6626
6815
  return this.ctx.http.request({
6627
6816
  method: "POST",
6628
6817
  path: `${this.base()}/agentic/agents/search`,
6629
6818
  auth: auth2,
6630
- body: query
6819
+ ...splitQuery(query, SEARCH_PAGING)
6631
6820
  });
6632
6821
  }
6633
6822
  /**
@@ -6680,21 +6869,22 @@ var AiService = class {
6680
6869
  });
6681
6870
  for await (const ev of events) yield ev.data;
6682
6871
  }
6683
- /** List stored agentic conversations (`GET /agentic/conversations`). */
6684
- async listConversations(auth2 = SERVICE17) {
6872
+ async listConversations(queryOrAuth = {}, auth2 = SERVICE17) {
6873
+ const [query, ctx] = isAuthContext(queryOrAuth) ? [{}, queryOrAuth] : [queryOrAuth, auth2];
6685
6874
  return this.ctx.http.request({
6686
6875
  method: "GET",
6687
6876
  path: `${this.base()}/agentic/conversations`,
6688
- auth: auth2
6877
+ auth: ctx,
6878
+ query: { ...query }
6689
6879
  });
6690
6880
  }
6691
- /** Server-side conversation search (`POST /agentic/conversations/search`). */
6881
+ /** Server-side conversation search (`POST /agentic/conversations/search`), paged like {@link searchAgents}. */
6692
6882
  async searchConversations(query, auth2 = SERVICE17) {
6693
6883
  return this.ctx.http.request({
6694
6884
  method: "POST",
6695
6885
  path: `${this.base()}/agentic/conversations/search`,
6696
6886
  auth: auth2,
6697
- body: query
6887
+ ...splitQuery(query, SEARCH_PAGING)
6698
6888
  });
6699
6889
  }
6700
6890
  // --- Standalone agentic reads / bulk operations ------------------------
@@ -8890,14 +9080,17 @@ var VendorService = class {
8890
9080
  auth: auth2
8891
9081
  });
8892
9082
  }
8893
- /** Search vendors (`POST /vendors/search`). A built filter in `q` is resolved to a string. */
9083
+ /**
9084
+ * Search vendors (`POST /vendors/search`). A built filter in `q` is resolved to
9085
+ * a string; paging, sort and fields go in the query string.
9086
+ */
8894
9087
  async searchVendors(query, auth2 = SERVICE33) {
8895
- const body = query.q !== void 0 ? { ...query, q: resolveQuery(query.q, { compoundLogicalQuery: false }) } : query;
9088
+ const input = query.q !== void 0 ? { ...query, q: resolveQuery(query.q, { compoundLogicalQuery: false }) } : query;
8896
9089
  return this.ctx.http.request({
8897
9090
  method: "POST",
8898
9091
  path: `${this.base()}/vendors/search`,
8899
9092
  auth: auth2,
8900
- body
9093
+ ...splitQuery(input, SEARCH_PAGING)
8901
9094
  });
8902
9095
  }
8903
9096
  /** Create a vendor. */
@@ -8992,10 +9185,18 @@ var CustomerAdminService = class {
8992
9185
  ...Object.keys(query).length ? { query } : {}
8993
9186
  });
8994
9187
  }
8995
- /** Search customers (`POST /customers/search`). A built filter in `q` is resolved to a string. */
9188
+ /**
9189
+ * Search customers (`POST /customers/search`). A built filter in `q` is resolved
9190
+ * to a string; `pageNumber`, `pageSize`, `sort` and `expand` go in the query string.
9191
+ */
8996
9192
  async searchCustomers(query, auth2 = SERVICE34) {
8997
- const body = query.q !== void 0 ? { ...query, q: resolveQuery(query.q, { compoundLogicalQuery: false }) } : query;
8998
- return this.ctx.http.request({ method: "POST", path: `${this.base()}/search`, auth: auth2, body });
9193
+ const input = query.q !== void 0 ? { ...query, q: resolveQuery(query.q, { compoundLogicalQuery: false }) } : query;
9194
+ return this.ctx.http.request({
9195
+ method: "POST",
9196
+ path: `${this.base()}/search`,
9197
+ auth: auth2,
9198
+ ...splitQuery(input, ["pageNumber", "pageSize", "sort", "expand"])
9199
+ });
8999
9200
  }
9000
9201
  /** Retrieve a customer profile by number. */
9001
9202
  async getCustomer(customerNumber, auth2 = SERVICE34) {