@viu/emporix-sdk 1.0.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 (132) hide show
  1. package/CHANGELOG.md +407 -0
  2. package/LICENSE +21 -0
  3. package/README.md +115 -0
  4. package/dist/cart.cjs +214 -0
  5. package/dist/cart.cjs.map +1 -0
  6. package/dist/cart.d.cts +1807 -0
  7. package/dist/cart.d.ts +1807 -0
  8. package/dist/cart.js +4 -0
  9. package/dist/cart.js.map +1 -0
  10. package/dist/category.cjs +97 -0
  11. package/dist/category.cjs.map +1 -0
  12. package/dist/category.d.cts +313 -0
  13. package/dist/category.d.ts +313 -0
  14. package/dist/category.js +4 -0
  15. package/dist/category.js.map +1 -0
  16. package/dist/checkout.cjs +98 -0
  17. package/dist/checkout.cjs.map +1 -0
  18. package/dist/checkout.d.cts +252 -0
  19. package/dist/checkout.d.ts +252 -0
  20. package/dist/checkout.js +4 -0
  21. package/dist/checkout.js.map +1 -0
  22. package/dist/chunk-4BJUCCKJ.js +86 -0
  23. package/dist/chunk-4BJUCCKJ.js.map +1 -0
  24. package/dist/chunk-6UNFMCHZ.js +95 -0
  25. package/dist/chunk-6UNFMCHZ.js.map +1 -0
  26. package/dist/chunk-B56JZNI7.js +49 -0
  27. package/dist/chunk-B56JZNI7.js.map +1 -0
  28. package/dist/chunk-BFQ732VZ.js +11 -0
  29. package/dist/chunk-BFQ732VZ.js.map +1 -0
  30. package/dist/chunk-F3WAQH2E.js +120 -0
  31. package/dist/chunk-F3WAQH2E.js.map +1 -0
  32. package/dist/chunk-GWJ2U2CP.js +14 -0
  33. package/dist/chunk-GWJ2U2CP.js.map +1 -0
  34. package/dist/chunk-HEO34WLO.js +47 -0
  35. package/dist/chunk-HEO34WLO.js.map +1 -0
  36. package/dist/chunk-HKPZI7Y5.js +30 -0
  37. package/dist/chunk-HKPZI7Y5.js.map +1 -0
  38. package/dist/chunk-IEZHGU7F.js +171 -0
  39. package/dist/chunk-IEZHGU7F.js.map +1 -0
  40. package/dist/chunk-KTODT6DV.js +86 -0
  41. package/dist/chunk-KTODT6DV.js.map +1 -0
  42. package/dist/chunk-NM7VDXBR.js +57 -0
  43. package/dist/chunk-NM7VDXBR.js.map +1 -0
  44. package/dist/chunk-OMYVOOSX.js +57 -0
  45. package/dist/chunk-OMYVOOSX.js.map +1 -0
  46. package/dist/chunk-QDABAMVN.js +89 -0
  47. package/dist/chunk-QDABAMVN.js.map +1 -0
  48. package/dist/chunk-RXVVFNYN.js +56 -0
  49. package/dist/chunk-RXVVFNYN.js.map +1 -0
  50. package/dist/chunk-SKX7KCMH.js +23 -0
  51. package/dist/chunk-SKX7KCMH.js.map +1 -0
  52. package/dist/chunk-TLH6SLAF.js +215 -0
  53. package/dist/chunk-TLH6SLAF.js.map +1 -0
  54. package/dist/chunk-Z6PNI5VT.js +142 -0
  55. package/dist/chunk-Z6PNI5VT.js.map +1 -0
  56. package/dist/companies.cjs +58 -0
  57. package/dist/companies.cjs.map +1 -0
  58. package/dist/companies.d.cts +31 -0
  59. package/dist/companies.d.ts +31 -0
  60. package/dist/companies.js +3 -0
  61. package/dist/companies.js.map +1 -0
  62. package/dist/contacts.cjs +51 -0
  63. package/dist/contacts.cjs.map +1 -0
  64. package/dist/contacts.d.cts +28 -0
  65. package/dist/contacts.d.ts +28 -0
  66. package/dist/contacts.js +3 -0
  67. package/dist/contacts.js.map +1 -0
  68. package/dist/context-vKgzZ-5f.d.cts +329 -0
  69. package/dist/context-vKgzZ-5f.d.ts +329 -0
  70. package/dist/customer-groups.cjs +25 -0
  71. package/dist/customer-groups.cjs.map +1 -0
  72. package/dist/customer-groups.d.cts +36 -0
  73. package/dist/customer-groups.d.ts +36 -0
  74. package/dist/customer-groups.js +3 -0
  75. package/dist/customer-groups.js.map +1 -0
  76. package/dist/customer.cjs +262 -0
  77. package/dist/customer.cjs.map +1 -0
  78. package/dist/customer.d.cts +386 -0
  79. package/dist/customer.d.ts +386 -0
  80. package/dist/customer.js +5 -0
  81. package/dist/customer.js.map +1 -0
  82. package/dist/index.cjs +2075 -0
  83. package/dist/index.cjs.map +1 -0
  84. package/dist/index.d.cts +218 -0
  85. package/dist/index.d.ts +218 -0
  86. package/dist/index.js +791 -0
  87. package/dist/index.js.map +1 -0
  88. package/dist/locations.cjs +59 -0
  89. package/dist/locations.cjs.map +1 -0
  90. package/dist/locations.d.cts +30 -0
  91. package/dist/locations.d.ts +30 -0
  92. package/dist/locations.js +3 -0
  93. package/dist/locations.js.map +1 -0
  94. package/dist/media.cjs +123 -0
  95. package/dist/media.cjs.map +1 -0
  96. package/dist/media.d.cts +219 -0
  97. package/dist/media.d.ts +219 -0
  98. package/dist/media.js +3 -0
  99. package/dist/media.js.map +1 -0
  100. package/dist/orders.cjs +98 -0
  101. package/dist/orders.cjs.map +1 -0
  102. package/dist/orders.d.cts +167 -0
  103. package/dist/orders.d.ts +167 -0
  104. package/dist/orders.js +3 -0
  105. package/dist/orders.js.map +1 -0
  106. package/dist/payment.cjs +77 -0
  107. package/dist/payment.cjs.map +1 -0
  108. package/dist/payment.d.cts +110 -0
  109. package/dist/payment.d.ts +110 -0
  110. package/dist/payment.js +5 -0
  111. package/dist/payment.js.map +1 -0
  112. package/dist/price.cjs +88 -0
  113. package/dist/price.cjs.map +1 -0
  114. package/dist/price.d.cts +445 -0
  115. package/dist/price.d.ts +445 -0
  116. package/dist/price.js +4 -0
  117. package/dist/price.js.map +1 -0
  118. package/dist/product.cjs +100 -0
  119. package/dist/product.cjs.map +1 -0
  120. package/dist/product.d.cts +400 -0
  121. package/dist/product.d.ts +400 -0
  122. package/dist/product.js +4 -0
  123. package/dist/product.js.map +1 -0
  124. package/dist/segment.cjs +189 -0
  125. package/dist/segment.cjs.map +1 -0
  126. package/dist/segment.d.cts +241 -0
  127. package/dist/segment.d.ts +241 -0
  128. package/dist/segment.js +5 -0
  129. package/dist/segment.js.map +1 -0
  130. package/dist/types.gen-D1QuqPLs.d.cts +166 -0
  131. package/dist/types.gen-D1QuqPLs.d.ts +166 -0
  132. package/package.json +141 -0
@@ -0,0 +1,400 @@
1
+ import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-vKgzZ-5f.js';
2
+
3
+ /**
4
+ * Localized value which can have different structure which depends on provided `Content-Language` header.
5
+ */
6
+ type LocalizedValue = string | {
7
+ [key: string]: string;
8
+ };
9
+ /**
10
+ * Indicates the product type, which is immutable. Once the product type is set, it cannot be updated.
11
+ *
12
+ */
13
+ type ProductType = 'BASIC' | 'BUNDLE' | 'PARENT_VARIANT' | 'VARIANT' | 'DYNAMIC_VARIANT';
14
+ /**
15
+ * Indicates the product type, which is immutable. This property is taken into account only for insert operations.
16
+ *
17
+ */
18
+ type ProductTypeUpdate = 'BASIC' | 'BUNDLE' | 'PARENT_VARIANT' | 'VARIANT' | 'DYNAMIC_VARIANT';
19
+ /**
20
+ * Indicates the template that has been used during the product creation. After assigning a template to the product, the new attributes can be defined under the `productTemplateAttributes` key in the `mixins` field. In case of variant attributes, the attributes should be defined under `productVariantAttributes`. The attributes are then validated in accordance with their definition in the template.
21
+ *
22
+ * **Note:** The template with defined variant attributes can be used only in PARENT_VARIANT and VARIANT types of product.
23
+ *
24
+ */
25
+ type Template = {
26
+ /**
27
+ * Identifier of the product template.
28
+ */
29
+ id: string;
30
+ /**
31
+ * Product template version.
32
+ */
33
+ version: string;
34
+ };
35
+ /**
36
+ * List of bundled products
37
+ */
38
+ type BundledProducts = Array<{
39
+ /**
40
+ * Identifier of the bundled product.
41
+ */
42
+ productId: string;
43
+ /**
44
+ * Amount of bundled products. Must be a positive number.
45
+ */
46
+ amount: number;
47
+ }>;
48
+ type Value = {
49
+ key?: string | number | boolean;
50
+ };
51
+ type Values = Array<Value>;
52
+ /**
53
+ * This field contains all information about attributes and their values that are used for creating variants. It is presented in the form of a map, where 'key' is the name of the attribute and 'value' is the list of values of that attribute. The attributes and their values are based on their definitions in the `template` element assigned to the parent variant. Each attribute defined in the product template is flagged as a `variantAttribute`. Only the attributes that have this flag set as `true` can be used in the `variantAttributes` field.
54
+ */
55
+ type VariantAttributes = {
56
+ [key: string]: Values;
57
+ };
58
+ /**
59
+ * In YaaS, a global resource identifier is a Uniform Resource Name (URN) with a custom YaaS schema and is called a YaaS Resource Name, or YRN.
60
+ *
61
+ * It is a unique identifier, which stores information about a resource, such as its type, ID or name of the tenant.
62
+ */
63
+ type Yrn = string;
64
+ /**
65
+ * Map of key-value pairs that associates tax classes with locations (countries). The key of the map should be specified as the existing location/country identifier (see the country-service). The value of the map entry should contain a tax class code (see the tax-service).
66
+ * Information about the association is required for price matching mechanism (see the price-service#MatchPrice).
67
+ */
68
+ type TaxClasses = {
69
+ [key: string]: string;
70
+ };
71
+ /**
72
+ * Flag indicating whether the product has been published or not.
73
+ */
74
+ type Published = boolean;
75
+ /**
76
+ * Mixins request.
77
+ */
78
+ type ProductMixins = {
79
+ [key: string]: unknown;
80
+ };
81
+ /**
82
+ * Metadata request.
83
+ */
84
+ type ProductMetadataCore = {
85
+ /**
86
+ * Links to the mixin schemas.
87
+ */
88
+ mixins?: {
89
+ [key: string]: unknown;
90
+ };
91
+ };
92
+ /**
93
+ * Metadata with the version information.
94
+ */
95
+ type ProductMetadataWithVersion = ProductMetadataCore & {
96
+ /**
97
+ * Version of the document
98
+ */
99
+ version?: number;
100
+ };
101
+ /**
102
+ * Metadata for GET requests.
103
+ */
104
+ type ProductMetadataGet = ProductMetadataWithVersion & {
105
+ /**
106
+ * List of mixin schemas used for classification.
107
+ */
108
+ classificationMixins?: Array<{
109
+ /**
110
+ * Name of the mixin
111
+ */
112
+ name?: string;
113
+ /**
114
+ * The mixins path that should be used when defining attributes on a product. It's built based on the following pattern - `class_<sourceCategory.code>_<name>`.
115
+ */
116
+ mixinPath?: string;
117
+ /**
118
+ * URL of the mixin schema defined on the category level.
119
+ */
120
+ schemaUrl?: string;
121
+ /**
122
+ * If given mixin has been already used in the product, then this field contains the URL of the used mixin schema.
123
+ */
124
+ usedSchemaUrl?: string;
125
+ /**
126
+ * Indicates whether the used mixin schema is obsolete - `usedSchemaUrl` differs from `schemaUrl`.
127
+ */
128
+ obsoleteSchemaUrlUsed?: boolean;
129
+ /**
130
+ * Indicates whether the mixin is required.
131
+ */
132
+ required?: boolean;
133
+ /**
134
+ * Unique identifier of the category from which the mixin comes from. Can be this category ID or one of the parent categories IDs.
135
+ */
136
+ sourceCategoryId?: string;
137
+ }>;
138
+ /**
139
+ * Creation date in the ISO 8601 standard.
140
+ */
141
+ createdAt?: string;
142
+ /**
143
+ * Modification date in the ISO 8601 standard.
144
+ */
145
+ modifiedAt?: string;
146
+ };
147
+ /**
148
+ * Unique resource identifier.
149
+ */
150
+ type Id = string;
151
+ /**
152
+ * Media files attached to the product.
153
+ */
154
+ type ProductMedia = Array<{
155
+ id?: string;
156
+ yrn?: Yrn;
157
+ contentType?: string;
158
+ createdAt?: string;
159
+ uploadLink?: string;
160
+ url?: string;
161
+ cloudinaryUrl?: string;
162
+ uncommittedMedia?: boolean;
163
+ tags?: Array<string>;
164
+ customAttributes?: {
165
+ [key: string]: unknown;
166
+ };
167
+ }>;
168
+ type ProductCore = {
169
+ name?: LocalizedValue;
170
+ /**
171
+ * Unique product identifier, defined by the user.
172
+ */
173
+ code?: string;
174
+ description?: LocalizedValue;
175
+ vendor?: Vendor;
176
+ taxClasses?: TaxClasses;
177
+ published?: Published;
178
+ /**
179
+ * Mark the product as weight-dependent if the line item price could change after packaging, as this is necessary to ensure that credit card payments can be authorized.
180
+ */
181
+ weightDependent?: boolean;
182
+ mixins?: ProductMixins;
183
+ /**
184
+ * List of items in a relationship with the main product. Assuming that in the system the following relation types are defined: `ACCESSORY` and `CONSUMABLE`, the two products: `Printer` and `Ink` exist, then the `Ink` product can be used as a related item with type `CONSUMABLE` for the Printer product.
185
+ * In order to find all printers for which the ink is defined as a `CONSUMABLE` then `q-param` can be used:
186
+ * `products?q=relatedItems.type:CONSUMABLE relatedItems.refId:Ink_Id`
187
+ *
188
+ */
189
+ relatedItems?: Array<RelatedItem>;
190
+ /**
191
+ * ID of brand.
192
+ */
193
+ brandId?: string;
194
+ brand?: Brand;
195
+ /**
196
+ * Collection of label IDs.
197
+ */
198
+ labelIds?: Array<string>;
199
+ labels?: Array<Label>;
200
+ };
201
+ /**
202
+ * Brand data expanded from `brandId`.
203
+ */
204
+ type Brand = {
205
+ id?: string;
206
+ name?: string;
207
+ description?: string;
208
+ localizedName?: {
209
+ [key: string]: string;
210
+ };
211
+ localizedDescription?: {
212
+ [key: string]: string;
213
+ };
214
+ image?: string;
215
+ cloudinaryUrl?: string;
216
+ mediaId?: string;
217
+ };
218
+ /**
219
+ * Overlay metadata for a label.
220
+ */
221
+ type LabelOverlay = {
222
+ isTrue?: boolean;
223
+ position?: number;
224
+ };
225
+ /**
226
+ * Label data expanded from `labelIds`.
227
+ */
228
+ type Label = {
229
+ id?: string;
230
+ name?: string;
231
+ description?: LocalizedValue;
232
+ image?: string;
233
+ cloudinaryUrl?: string;
234
+ mediaId?: string;
235
+ overlay?: LabelOverlay;
236
+ };
237
+ /**
238
+ * Products of the BASIC type.
239
+ */
240
+ type BasicProduct = ProductCore & {
241
+ metadata?: ProductMetadataCore;
242
+ template?: Template;
243
+ };
244
+ /**
245
+ * Creating products of the BASIC type.
246
+ */
247
+ type BasicProductCreation = BasicProduct & {
248
+ /**
249
+ * Custom product identifier. If not provided, it is automatically generated.
250
+ */
251
+ id?: string;
252
+ productType?: ProductType;
253
+ };
254
+ /**
255
+ * Products of the BASIC type.
256
+ */
257
+ type BasicProductWithId = BasicProductCreation & {
258
+ id?: Id;
259
+ yrn?: Yrn;
260
+ media?: ProductMedia;
261
+ metadata?: ProductMetadataGet;
262
+ /**
263
+ * Customer segment IDs assigned to the product.
264
+ */
265
+ customerSegmentIds?: Array<string>;
266
+ /**
267
+ * Category IDs assigned to the product.
268
+ */
269
+ categoryIds?: Array<string>;
270
+ };
271
+ /**
272
+ * Products of the BUNDLE type.
273
+ */
274
+ type BundleProduct = ProductCore & {
275
+ metadata?: ProductMetadataCore;
276
+ template?: Template;
277
+ bundledProducts: BundledProducts;
278
+ productType: ProductTypeUpdate;
279
+ };
280
+ /**
281
+ * Creating products of the BUNDLE type.
282
+ */
283
+ type BundleProductCreation = BundleProduct & {
284
+ /**
285
+ * Custom product identifier. If not provided, it is automatically generated.
286
+ */
287
+ id?: string;
288
+ productType?: ProductType;
289
+ };
290
+ /**
291
+ * Products of the BUNDLE type.
292
+ */
293
+ type BundleProductWithId = BundleProductCreation & {
294
+ id?: Id;
295
+ yrn?: Yrn;
296
+ media?: ProductMedia;
297
+ metadata?: ProductMetadataGet;
298
+ /**
299
+ * Customer segment IDs assigned to the product.
300
+ */
301
+ customerSegmentIds?: Array<string>;
302
+ /**
303
+ * Category IDs assigned to the product.
304
+ */
305
+ categoryIds?: Array<string>;
306
+ };
307
+ /**
308
+ * Products of the PARENT_VARIANT type.
309
+ */
310
+ type ParentVariantProduct = ProductCore & {
311
+ metadata?: ProductMetadataCore;
312
+ template: Template;
313
+ variantAttributes: VariantAttributes;
314
+ };
315
+ /**
316
+ * Creating products of the PARENT_VARIANT type.
317
+ */
318
+ type ParentVariantProductCreation = ParentVariantProduct & {
319
+ /**
320
+ * Custom product identifier. If not provided, it is automatically generated.
321
+ */
322
+ id?: string;
323
+ productType?: ProductType;
324
+ };
325
+ /**
326
+ * Products of the PARENT_VARIANT type.
327
+ */
328
+ type ParentVariantProductWithId = ParentVariantProductCreation & {
329
+ id?: Id;
330
+ yrn?: Yrn;
331
+ media?: ProductMedia;
332
+ metadata?: ProductMetadataGet;
333
+ /**
334
+ * Customer segment IDs assigned to the product.
335
+ */
336
+ customerSegmentIds?: Array<string>;
337
+ /**
338
+ * Category IDs assigned to the product.
339
+ */
340
+ categoryIds?: Array<string>;
341
+ };
342
+ type Vendor = {
343
+ /**
344
+ * An identifier of a vendor to whom the product belongs.
345
+ */
346
+ id: string;
347
+ /**
348
+ * Vendor name.
349
+ */
350
+ name?: string;
351
+ };
352
+ type RelatedItem = {
353
+ /**
354
+ * Identifier of a product which is in the relationship with the main product. The product identifier has to exist.
355
+ */
356
+ refId: string;
357
+ /**
358
+ * A relation type. The type has to exist in the system. All relation types are defined in configuration service under `relation_types` key.
359
+ */
360
+ type: string;
361
+ };
362
+
363
+ /** A product as returned by the Product service (all generated fields). */
364
+ type Product = BasicProductWithId | BundleProductWithId | ParentVariantProductWithId;
365
+ /** A single product media entry (generated; `ProductMedia` is the list type). */
366
+ type Media = ProductMedia[number];
367
+ /** Catalog reads. Default auth: anonymous; pass customer for personalized pricing. */
368
+ declare class ProductService {
369
+ private readonly ctx;
370
+ constructor(ctx: ClientContext);
371
+ /** Fetches one product by id. */
372
+ get(productId: string, _opts?: Record<string, never>, auth?: AuthContext): Promise<Product>;
373
+ /** Fetches one product by its code. */
374
+ getByCode(code: string, auth?: AuthContext): Promise<Product>;
375
+ /** One page of products. */
376
+ list(params?: {
377
+ pageNumber?: number;
378
+ pageSize?: number;
379
+ }, auth?: AuthContext): Promise<PaginatedItems<Product>>;
380
+ /** Async-iterates every product across pages. */
381
+ listAll(params?: {
382
+ pageSize?: number;
383
+ }, auth?: AuthContext): AsyncIterable<Product>;
384
+ /** Searches products by free-text query. */
385
+ search(query: string, params?: {
386
+ pageNumber?: number;
387
+ pageSize?: number;
388
+ }, auth?: AuthContext): Promise<PaginatedItems<Product>>;
389
+ /**
390
+ * Bulk fetch by id. POSTs `/products/search` with `q="id:(id1,id2,…)"`,
391
+ * chunking when the list is larger than `options.chunkSize` (default
392
+ * 100). An empty list short-circuits with no HTTP call. **Order is not
393
+ * guaranteed** across chunks — re-index by `id` if order matters.
394
+ */
395
+ searchByIds(ids: string[], options?: {
396
+ chunkSize?: number;
397
+ }, auth?: AuthContext): Promise<Product[]>;
398
+ }
399
+
400
+ export { type Media, type Product, ProductService };
@@ -0,0 +1,4 @@
1
+ export { ProductService } from './chunk-QDABAMVN.js';
2
+ import './chunk-GWJ2U2CP.js';
3
+ //# sourceMappingURL=product.js.map
4
+ //# sourceMappingURL=product.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"product.js"}
@@ -0,0 +1,189 @@
1
+ 'use strict';
2
+
3
+ // src/core/errors.ts
4
+ var REDACTED_BODY_KEYS = /* @__PURE__ */ new Set([
5
+ "access_token",
6
+ "refresh_token",
7
+ "token",
8
+ "customertoken",
9
+ "saastoken",
10
+ "secret",
11
+ "client_secret",
12
+ "authorization",
13
+ "password"
14
+ ]);
15
+ function scrub(body) {
16
+ if (Array.isArray(body)) return body.map(scrub);
17
+ if (body && typeof body === "object") {
18
+ const out = {};
19
+ for (const [k, v] of Object.entries(body)) {
20
+ out[k] = REDACTED_BODY_KEYS.has(k.toLowerCase()) ? "***redacted***" : scrub(v);
21
+ }
22
+ return out;
23
+ }
24
+ return body;
25
+ }
26
+ var EmporixError = class extends Error {
27
+ status;
28
+ body;
29
+ constructor(message, status, body) {
30
+ super(message);
31
+ this.name = new.target.name;
32
+ this.status = status;
33
+ this.body = body;
34
+ Object.setPrototypeOf(this, new.target.prototype);
35
+ }
36
+ /** Safe serialisation — token-like body fields are redacted. */
37
+ toJSON() {
38
+ return { name: this.name, message: this.message, status: this.status, body: scrub(this.body) };
39
+ }
40
+ };
41
+ var EmporixAuthError = class extends EmporixError {
42
+ };
43
+
44
+ // src/core/require-customer.ts
45
+ function requireCustomer(auth) {
46
+ if (auth && (auth.kind === "customer" || auth.kind === "raw")) return auth;
47
+ throw new EmporixAuthError("This operation requires a customer or raw AuthContext");
48
+ }
49
+
50
+ // src/services/segment.ts
51
+ function setIfDefined(q, key, value) {
52
+ if (value !== void 0 && value !== "") {
53
+ q[key] = value;
54
+ }
55
+ }
56
+ var SegmentService = class {
57
+ constructor(ctx, deps) {
58
+ this.ctx = ctx;
59
+ this.deps = deps;
60
+ }
61
+ ctx;
62
+ deps;
63
+ base() {
64
+ return `/customer-segment/${this.ctx.tenant}/segments`;
65
+ }
66
+ /** Lists segments the caller belongs to (with `segment_read_own`). */
67
+ async list(query = {}, auth) {
68
+ const q = {};
69
+ setIfDefined(q, "q", query.q);
70
+ setIfDefined(q, "pageNumber", query.pageNumber);
71
+ setIfDefined(q, "pageSize", query.pageSize);
72
+ return this.ctx.http.request({
73
+ method: "GET",
74
+ path: this.base(),
75
+ auth: requireCustomer(auth),
76
+ ...Object.keys(q).length ? { query: q } : {}
77
+ });
78
+ }
79
+ /** Fetches a single segment by id. */
80
+ async get(segmentId, auth) {
81
+ return this.ctx.http.request({
82
+ method: "GET",
83
+ path: `${this.base()}/${segmentId}`,
84
+ auth: requireCustomer(auth)
85
+ });
86
+ }
87
+ /** Item assignments (PRODUCT + CATEGORY) across all the caller's active segments. */
88
+ async listItems(query = {}, auth) {
89
+ const q = {};
90
+ setIfDefined(q, "q", query.q);
91
+ setIfDefined(q, "siteCode", query.siteCode);
92
+ setIfDefined(q, "legalEntityId", query.legalEntityId);
93
+ setIfDefined(q, "pageNumber", query.pageNumber);
94
+ setIfDefined(q, "pageSize", query.pageSize);
95
+ if (query.onlyActive !== void 0) q.onlyActive = String(query.onlyActive);
96
+ return this.ctx.http.request({
97
+ method: "GET",
98
+ path: `${this.base()}/items`,
99
+ auth: requireCustomer(auth),
100
+ ...Object.keys(q).length ? { query: q } : {}
101
+ });
102
+ }
103
+ /** Item assignments of one specific segment. */
104
+ async listSegmentItems(segmentId, query = {}, auth) {
105
+ const q = {};
106
+ setIfDefined(q, "q", query.q);
107
+ setIfDefined(q, "legalEntityId", query.legalEntityId);
108
+ setIfDefined(q, "pageNumber", query.pageNumber);
109
+ setIfDefined(q, "pageSize", query.pageSize);
110
+ return this.ctx.http.request({
111
+ method: "GET",
112
+ path: `${this.base()}/${segmentId}/items`,
113
+ auth: requireCustomer(auth),
114
+ ...Object.keys(q).length ? { query: q } : {}
115
+ });
116
+ }
117
+ /** Category tree built only from the caller's active segments. */
118
+ async getCategoryTree(query = {}, auth) {
119
+ const q = {};
120
+ setIfDefined(q, "siteCode", query.siteCode);
121
+ setIfDefined(q, "legalEntityId", query.legalEntityId);
122
+ return this.ctx.http.request({
123
+ method: "GET",
124
+ path: `${this.base()}/items/category-trees`,
125
+ auth: requireCustomer(auth),
126
+ ...Object.keys(q).length ? { query: q } : {}
127
+ });
128
+ }
129
+ async pickItemIds(kind, query, auth) {
130
+ const rows = await this.listItems(query, auth);
131
+ const ids = [];
132
+ for (const r of rows) {
133
+ const id = r.item?.id;
134
+ if (r.type === kind && typeof id === "string") ids.push(id);
135
+ }
136
+ return ids;
137
+ }
138
+ /** Product ids assigned to the caller's active segments. */
139
+ async listMyProductIds(query, auth) {
140
+ return this.pickItemIds("PRODUCT", query ?? {}, auth);
141
+ }
142
+ /** Category ids assigned to the caller's active segments. */
143
+ async listMyCategoryIds(query, auth) {
144
+ return this.pickItemIds("CATEGORY", query ?? {}, auth);
145
+ }
146
+ /**
147
+ * Hydrates `listMyProductIds` via `ProductService.get` in parallel.
148
+ * Resolves in the same order as the id list. Any single failure rejects
149
+ * the whole batch (`Promise.all`); use the id-list method + your own
150
+ * tolerance strategy if partial success matters.
151
+ */
152
+ async listMyProducts(query, auth) {
153
+ const pageNumber = query?.pageNumber ?? 1;
154
+ const pageSize = query?.pageSize ?? 20;
155
+ const sourceItems = await this.listItems(
156
+ { ...query ?? {}, pageNumber, pageSize },
157
+ auth
158
+ );
159
+ const ids = [];
160
+ for (const r of sourceItems) {
161
+ if (r.type === "PRODUCT" && typeof r.item?.id === "string") ids.push(r.item.id);
162
+ }
163
+ const items = await this.deps.products.searchByIds(ids, void 0, auth);
164
+ return { items, pageNumber, pageSize, hasNextPage: sourceItems.length === pageSize };
165
+ }
166
+ /**
167
+ * Hydrates a page of the caller's segment CATEGORY assignments into
168
+ * real categories via one bulk `categories.searchByIds` call. Same
169
+ * `hasNextPage` semantic as `listMyProducts`.
170
+ */
171
+ async listMyCategories(query, auth) {
172
+ const pageNumber = query?.pageNumber ?? 1;
173
+ const pageSize = query?.pageSize ?? 20;
174
+ const sourceItems = await this.listItems(
175
+ { ...query ?? {}, pageNumber, pageSize },
176
+ auth
177
+ );
178
+ const ids = [];
179
+ for (const r of sourceItems) {
180
+ if (r.type === "CATEGORY" && typeof r.item?.id === "string") ids.push(r.item.id);
181
+ }
182
+ const items = await this.deps.categories.searchByIds(ids, void 0, auth);
183
+ return { items, pageNumber, pageSize, hasNextPage: sourceItems.length === pageSize };
184
+ }
185
+ };
186
+
187
+ exports.SegmentService = SegmentService;
188
+ //# sourceMappingURL=segment.cjs.map
189
+ //# sourceMappingURL=segment.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/errors.ts","../src/core/require-customer.ts","../src/services/segment.ts"],"names":[],"mappings":"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","file":"segment.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 { AuthContext } from \"./auth\";\nimport { EmporixAuthError } from \"./errors\";\n\n/**\n * Enforces a caller-owned customer or raw token. Throws `EmporixAuthError`\n * for any other `AuthContext` kind (or when `auth` is missing). Shared by\n * services whose endpoints require a customer scope (`/me`, payments,\n * customer-segments…).\n */\nexport function requireCustomer(auth: AuthContext | undefined): AuthContext {\n if (auth && (auth.kind === \"customer\" || auth.kind === \"raw\")) return auth;\n throw new EmporixAuthError(\"This operation requires a customer or raw AuthContext\");\n}\n","import type { ClientContext, PaginatedItems } from \"../core/context\";\nimport type { AuthContext } from \"../core/auth\";\nimport { requireCustomer } from \"../core/require-customer\";\nimport type { ProductService } from \"./product\";\nimport type { CategoryService } from \"./category\";\nimport type {\n SegmentResponse,\n ItemAssignmentResponse,\n CategoryTreeResponse,\n} from \"../generated/customer-segment\";\n\n/** Generated segment types (read shapes — storefront `segment_read_own`). */\nexport type Segment = SegmentResponse;\nexport type SegmentItem = ItemAssignmentResponse;\nexport type SegmentCategoryTree = CategoryTreeResponse;\nexport type SegmentCategoryTreeNode = CategoryTreeResponse[number];\n\n/** Cross-service hydrate dependencies, injected from `EmporixClient`. */\nexport interface SegmentServiceDeps {\n products: ProductService;\n categories: CategoryService;\n}\n\nfunction setIfDefined<V>(\n q: Record<string, string | number | undefined>,\n key: string,\n value: V | undefined,\n): void {\n if (value !== undefined && value !== \"\") {\n q[key] = value as unknown as string | number;\n }\n}\n\n/**\n * Customer-segment reads. Every method requires a customer/raw\n * `AuthContext` — the `segment_read_own` scope is on the customer token.\n * The standard product/category endpoints do **not** auto-filter by\n * segment; the storefront uses these reads to discover what to fetch.\n */\nexport class SegmentService {\n constructor(\n private readonly ctx: ClientContext,\n private readonly deps: SegmentServiceDeps,\n ) {}\n\n private base(): string {\n return `/customer-segment/${this.ctx.tenant}/segments`;\n }\n\n /** Lists segments the caller belongs to (with `segment_read_own`). */\n async list(\n query: { q?: string; pageNumber?: number; pageSize?: number } = {},\n auth?: AuthContext,\n ): Promise<Segment[]> {\n const q: Record<string, string | number | undefined> = {};\n setIfDefined(q, \"q\", query.q);\n setIfDefined(q, \"pageNumber\", query.pageNumber);\n setIfDefined(q, \"pageSize\", query.pageSize);\n return this.ctx.http.request<Segment[]>({\n method: \"GET\",\n path: this.base(),\n auth: requireCustomer(auth),\n ...(Object.keys(q).length ? { query: q } : {}),\n });\n }\n\n /** Fetches a single segment by id. */\n async get(segmentId: string, auth?: AuthContext): Promise<Segment> {\n return this.ctx.http.request<Segment>({\n method: \"GET\",\n path: `${this.base()}/${segmentId}`,\n auth: requireCustomer(auth),\n });\n }\n\n /** Item assignments (PRODUCT + CATEGORY) across all the caller's active segments. */\n async listItems(\n query: {\n q?: string;\n siteCode?: string;\n legalEntityId?: string;\n onlyActive?: boolean;\n pageNumber?: number;\n pageSize?: number;\n } = {},\n auth?: AuthContext,\n ): Promise<SegmentItem[]> {\n const q: Record<string, string | number | undefined> = {};\n setIfDefined(q, \"q\", query.q);\n setIfDefined(q, \"siteCode\", query.siteCode);\n setIfDefined(q, \"legalEntityId\", query.legalEntityId);\n setIfDefined(q, \"pageNumber\", query.pageNumber);\n setIfDefined(q, \"pageSize\", query.pageSize);\n if (query.onlyActive !== undefined) q.onlyActive = String(query.onlyActive);\n return this.ctx.http.request<SegmentItem[]>({\n method: \"GET\",\n path: `${this.base()}/items`,\n auth: requireCustomer(auth),\n ...(Object.keys(q).length ? { query: q } : {}),\n });\n }\n\n /** Item assignments of one specific segment. */\n async listSegmentItems(\n segmentId: string,\n query: {\n q?: string;\n legalEntityId?: string;\n pageNumber?: number;\n pageSize?: number;\n } = {},\n auth?: AuthContext,\n ): Promise<SegmentItem[]> {\n const q: Record<string, string | number | undefined> = {};\n setIfDefined(q, \"q\", query.q);\n setIfDefined(q, \"legalEntityId\", query.legalEntityId);\n setIfDefined(q, \"pageNumber\", query.pageNumber);\n setIfDefined(q, \"pageSize\", query.pageSize);\n return this.ctx.http.request<SegmentItem[]>({\n method: \"GET\",\n path: `${this.base()}/${segmentId}/items`,\n auth: requireCustomer(auth),\n ...(Object.keys(q).length ? { query: q } : {}),\n });\n }\n\n /** Category tree built only from the caller's active segments. */\n async getCategoryTree(\n query: { siteCode?: string; legalEntityId?: string } = {},\n auth?: AuthContext,\n ): Promise<SegmentCategoryTree> {\n const q: Record<string, string | number | undefined> = {};\n setIfDefined(q, \"siteCode\", query.siteCode);\n setIfDefined(q, \"legalEntityId\", query.legalEntityId);\n return this.ctx.http.request<SegmentCategoryTree>({\n method: \"GET\",\n path: `${this.base()}/items/category-trees`,\n auth: requireCustomer(auth),\n ...(Object.keys(q).length ? { query: q } : {}),\n });\n }\n\n private async pickItemIds(\n kind: \"PRODUCT\" | \"CATEGORY\",\n query: Parameters<SegmentService[\"listItems\"]>[0],\n auth: AuthContext | undefined,\n ): Promise<string[]> {\n const rows = await this.listItems(query, auth);\n const ids: string[] = [];\n for (const r of rows) {\n const id = r.item?.id;\n if (r.type === kind && typeof id === \"string\") ids.push(id);\n }\n return ids;\n }\n\n /** Product ids assigned to the caller's active segments. */\n async listMyProductIds(\n query?: Parameters<SegmentService[\"listItems\"]>[0],\n auth?: AuthContext,\n ): Promise<string[]> {\n return this.pickItemIds(\"PRODUCT\", query ?? {}, auth);\n }\n\n /** Category ids assigned to the caller's active segments. */\n async listMyCategoryIds(\n query?: Parameters<SegmentService[\"listItems\"]>[0],\n auth?: AuthContext,\n ): Promise<string[]> {\n return this.pickItemIds(\"CATEGORY\", query ?? {}, auth);\n }\n\n /**\n * Hydrates `listMyProductIds` via `ProductService.get` in parallel.\n * Resolves in the same order as the id list. Any single failure rejects\n * the whole batch (`Promise.all`); use the id-list method + your own\n * tolerance strategy if partial success matters.\n */\n async listMyProducts(\n query?: Parameters<SegmentService[\"listItems\"]>[0],\n auth?: AuthContext,\n ): Promise<PaginatedItems<Awaited<ReturnType<ProductService[\"get\"]>>>> {\n const pageNumber = query?.pageNumber ?? 1;\n const pageSize = query?.pageSize ?? 20;\n const sourceItems = await this.listItems(\n { ...(query ?? {}), pageNumber, pageSize },\n auth,\n );\n const ids: string[] = [];\n for (const r of sourceItems) {\n if (r.type === \"PRODUCT\" && typeof r.item?.id === \"string\") ids.push(r.item.id);\n }\n const items = await this.deps.products.searchByIds(ids, undefined, auth);\n return { items, pageNumber, pageSize, hasNextPage: sourceItems.length === pageSize };\n }\n\n /**\n * Hydrates a page of the caller's segment CATEGORY assignments into\n * real categories via one bulk `categories.searchByIds` call. Same\n * `hasNextPage` semantic as `listMyProducts`.\n */\n async listMyCategories(\n query?: Parameters<SegmentService[\"listItems\"]>[0],\n auth?: AuthContext,\n ): Promise<PaginatedItems<Awaited<ReturnType<CategoryService[\"get\"]>>>> {\n const pageNumber = query?.pageNumber ?? 1;\n const pageSize = query?.pageSize ?? 20;\n const sourceItems = await this.listItems(\n { ...(query ?? {}), pageNumber, pageSize },\n auth,\n );\n const ids: string[] = [];\n for (const r of sourceItems) {\n if (r.type === \"CATEGORY\" && typeof r.item?.id === \"string\") ids.push(r.item.id);\n }\n const items = await this.deps.categories.searchByIds(ids, undefined, auth);\n return { items, pageNumber, pageSize, hasNextPage: sourceItems.length === pageSize };\n }\n}\n"]}