oneentry 1.0.156 → 1.0.158

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 (49) hide show
  1. package/changelog.md +143 -0
  2. package/dist/attribute-sets/attributeSetsApi.d.ts +2 -2
  3. package/dist/attribute-sets/attributeSetsApi.js +5 -5
  4. package/dist/attribute-sets/attributeSetsInterfaces.d.ts +20 -8
  5. package/dist/auth-provider/authProviderSchemas.d.ts +2 -0
  6. package/dist/auth-provider/authProviderSchemas.js +2 -0
  7. package/dist/auth-provider/authProvidersInterfaces.d.ts +4 -0
  8. package/dist/base/asyncModules.d.ts +18 -2
  9. package/dist/base/asyncModules.js +32 -8
  10. package/dist/base/syncModules.d.ts +37 -36
  11. package/dist/base/syncModules.js +69 -82
  12. package/dist/base/timeIntervals.js +6 -5
  13. package/dist/base/utils.d.ts +14 -10
  14. package/dist/blocks/blocksApi.d.ts +21 -21
  15. package/dist/blocks/blocksApi.js +10 -10
  16. package/dist/blocks/blocksInterfaces.d.ts +20 -20
  17. package/dist/blocks/blocksSchemas.d.ts +2 -0
  18. package/dist/discounts/discountsInterfaces.d.ts +4 -4
  19. package/dist/events/eventsApi.d.ts +3 -3
  20. package/dist/events/eventsApi.js +1 -1
  21. package/dist/events/eventsInterfaces.d.ts +16 -5
  22. package/dist/forms/formsApi.js +2 -2
  23. package/dist/forms/formsInterfaces.d.ts +23 -21
  24. package/dist/forms-data/formsDataApi.js +2 -2
  25. package/dist/forms-data/formsDataInterfaces.d.ts +4 -4
  26. package/dist/integration-collections/integrationCollectionsApi.js +6 -6
  27. package/dist/integration-collections/integrationCollectionsInterfaces.d.ts +4 -0
  28. package/dist/integration-collections/integrationCollectionsSchemas.d.ts +4 -0
  29. package/dist/integration-collections/integrationCollectionsSchemas.js +2 -0
  30. package/dist/menus/menusApi.js +1 -1
  31. package/dist/orders/ordersInterfaces.d.ts +21 -3
  32. package/dist/orders/ordersSchemas.d.ts +10 -0
  33. package/dist/orders/ordersSchemas.js +12 -0
  34. package/dist/pages/pagesApi.d.ts +4 -4
  35. package/dist/pages/pagesApi.js +10 -9
  36. package/dist/pages/pagesInterfaces.d.ts +14 -4
  37. package/dist/pages/pagesSchemas.d.ts +15 -0
  38. package/dist/pages/pagesSchemas.js +13 -1
  39. package/dist/products/productsApi.d.ts +6 -6
  40. package/dist/products/productsApi.js +13 -11
  41. package/dist/products/productsInterfaces.d.ts +39 -19
  42. package/dist/products/productsSchemas.d.ts +18 -0
  43. package/dist/products/productsSchemas.js +15 -1
  44. package/dist/subscriptions/subscriptionsApi.d.ts +4 -4
  45. package/dist/subscriptions/subscriptionsApi.js +3 -3
  46. package/dist/subscriptions/subscriptionsInterfaces.d.ts +26 -5
  47. package/dist/subscriptions/subscriptionsSchemas.d.ts +27 -1
  48. package/dist/subscriptions/subscriptionsSchemas.js +20 -2
  49. package/package.json +1 -1
package/changelog.md CHANGED
@@ -1,5 +1,148 @@
1
1
  # SDK Change Log
2
2
 
3
+ ## v.1.0.158
4
+
5
+ ### What's New
6
+
7
+ - Orders > `IOrderStatus` — four fields the API already returns on every status are now declared (all optional, like the rest of the interface): `axis` (status pipeline, e.g. `"payment"`), `isCancelFinal`, `isFinalSuccess`, `isMapped`.
8
+
9
+ - Base > `ILocalizeInfo` — `plainContent?: string | null` is now declared: pages and menus return it as the plain-text counterpart of `htmlContent`.
10
+
11
+ - Events > `IFormSubscriptionsResponse` — new exported type describing the container returned by `getFormSubscriptions`: `{ items: IListFormSubscription[]; total: number }`.
12
+
13
+ - Products > `IProductsResponse` — `totalFound?: number` is now declared (and validated by `ProductsResponseSchema`): block product endpoints (`similarProducts` inside blocks, cart/wishlist recommendations, frequently ordered) return it alongside `items`/`total`; the `Products.getProducts*` endpoints do not, hence optional.
14
+
15
+ - Products > `IProductBlockSimilarRule` — rewritten to match the real shape of `customSettings.similarProductRules[]` returned by `getProductBlockById`: `{ id, title, attributeMarker, conditionMarker, conditionValue, statusMarker, pageUrls }`. The previously declared fields (`property`, `includes`, `keywords`, `strict`) never occurred in real data.
16
+
17
+ - AttributeSets > `IAttributeSchemaItem` — six fields the API already returns on schema items are now declared (all optional):
18
+ - `position` — sort position of the field inside the set;
19
+ - `listTitles` (`IListTitle[]`) — options for `list`/`radioButton`/`entity` fields, with extended data or linked-entity values;
20
+ - `listType` — for `entity` fields, how the option list is organized (e.g. `"nested"`);
21
+ - `moduleIdentifier` — for `entity` fields, the module the linked entities are taken from (e.g. `"catalog"`);
22
+ - `parentId` — parent field id, `null` for top-level;
23
+ - `splitParts` (`number[] | boolean`) — for split-price fields, ids of the schema fields the price is split into, `false` when the field does not split.
24
+
25
+ ### What's Changed
26
+
27
+ - **Breaking** — Blocks > the ten recommendation methods (`getCartComplement`, `getCartComplementByProductIds`, `getCartSimilar`, `getCartSimilarByProductIds`, `getWishlistSimilar`, `getWishlistSimilarByProductIds`, `getTrending`, `getPersonalRecommendations`, `getRecentlyViewed`, `getRepeatPurchase`) — the declared return type is corrected from `IProductsEntity[]` to `IProductsResponse`: the endpoints actually return a container `{ items, total, totalFound? }`, and the SDK does not unwrap it. Type-level fix only; the response itself is unchanged — code that (incorrectly) called `res.map(...)` never worked on real data.
28
+
29
+ - **Breaking** — Products > `getProductsByVectorSearch` — the declared return type is corrected from `IProductsEntity[]` to `IProductsResponse`: the endpoint returns `{ items, total }`. Type-level fix only.
30
+
31
+ - **Breaking** — Events > `getFormSubscriptions` — the declared return type is corrected from `IListFormSubscription[]` to the new `IFormSubscriptionsResponse`: the endpoint returns `{ items, total }`. Type-level fix only.
32
+
33
+ - Orders > `IBaseOrdersEntity.totalSum` — type corrected from `string` to `number`: `createOrder` and `updateOrderByMarkerAndId` return a number (e.g. `285`), which the Zod schemas (`CreateOrderResponseSchema` / `UpdateOrderResponseSchema`) already declared. `IOrderByMarkerEntity.totalSum` stays `string` — the by-marker endpoints really return `"300.00"`.
34
+
35
+ - Forms > `IFormAttribute` — the seven auth/notification flags (`isLogin`, `isSignUp`, `isPassword`, `isSignUpRequired`, `isNotificationEmail`, `isNotificationPhonePush`, `isNotificationPhoneSMS`) are now optional: the API returns them only on attributes of sign-in/sign-up forms.
36
+
37
+ - Forms > `IFormLocalizeInfo` — `title` is now optional: the API returns an empty `localizeInfos` object when the form has no localization for the requested language (all list responses on the test project). Same for attribute localization: Base > `IAttributeLocalizeInfo.title` is now optional too.
38
+
39
+ - Forms > `IFormAttributeAdditionalField.marker` — now optional: entries of `additionalFields` arrive as `{ type, value }`, the marker is the map key.
40
+
41
+ - Forms > a form with no attributes now returns `attributes: []`: the API sends an empty **object** (`{}`) in that case, and the SDK normalizes it to an empty array in `_normalizeAttr`, so `attributes` is always `IFormAttribute[]` and `form.attributes.map(...)` is safe on every form.
42
+
43
+ - Events > `IContentApiEvent.module` — now optional: system events not bound to a module (e.g. `send_code`, `registration_event`) come without it.
44
+
45
+ - Discounts > `IDiscountsEntity.attributeSetId` and `IDiscountValue.maxAmount` — type widened to `number | null`: both arrive as `null` when not configured.
46
+
47
+ - Products > `IProductBlockProductConfig` — `quantity` and `countElementsPerRow` are now optional: `customSettings.productConfig` arrives as an empty object when the block is not configured.
48
+
49
+ - Base > `ITimeIntervalRange.period` — type corrected to `number | null`: ranges that are not sliced into slots carry `period: null`. The runtime (`expandTimeIntervals`) already guarded against it; only the type (and the internal narrowing in `_addSlotsFromRanges`) changed.
50
+
51
+ - AttributeSets > `getAttributesByMarker` — the declared return type is corrected from `IAttributeSetsEntity[]` (the attribute **set** entity: `id`, `schema`, `createdDate`, …) to `IAttributesSetsEntity[]` — the attribute entities the endpoint actually returns (`marker`, `type`, `value`, `listTitles`, `validators`, `localizeInfos`, `additionalFields`, …). Type-level fix only; runtime behavior and the response itself are unchanged.
52
+
53
+ - AttributeSets > `IAttributeSchemaItem` — `initialValue` and `isPrice` are now optional: the API omits them on some fields (`isPrice` is returned only on product attribute sets).
54
+
55
+ - Base > `ITimeIntervalSchedule` — `fullMonth` and `selectedYear` are now optional: the API returns them only when the schedule is pinned to a month/year rather than an explicit date `range`.
56
+
57
+ ## v.1.0.157
58
+
59
+ ### What's New
60
+
61
+ - Subscriptions > `ISubscriptionEntity` — new exported type describing an available subscription: `id`, `identifier`, `localizeInfos` (`ILocalizeInfo`), `productIds`, `periodInDays`, `paymentAccountId`, `isUsed`. It backs the corrected return type of `getAllSubscriptions` (see below) and has a matching Zod schema (`SubscriptionEntitySchema` / `SubscriptionsListSchema`).
62
+
63
+ - Orders > `IOrderByMarkerEntity` — four fields the API already returns are now declared: `fulfillmentStatusIdentifier`, `fulfillmentStatusLocalizeInfos`, `paymentStatusIdentifier`, `paymentStatusLocalizeInfos` (each `null` until the corresponding status is assigned). Response validation drops every key its schema does not describe, so with `validation.enabled` these four were silently stripped from `getOrderByMarkerAndId` and `getAllOrdersByMarker` before reaching the consumer:
64
+
65
+ ```ts
66
+ const order = await Orders.getOrderByMarkerAndId('my_order', 179);
67
+ order.paymentStatusIdentifier; // "inProgress-payment"
68
+ order.paymentStatusLocalizeInfos; // { title: "In progress" }
69
+ ```
70
+
71
+ - Orders > `IBaseOrdersEntity` — `statusLocalizeInfos` (localized name of the status assigned to the order) is now declared on the `createOrder` / `updateOrderByMarkerAndId` response, which returned it but had it stripped by validation.
72
+
73
+ - IntegrationCollections > `ICollectionRow` — `langCode` and `formIdentifier` are now declared. Both are returned by the create/update row endpoints (`formIdentifier` on update) and were stripped by validation.
74
+
75
+ - AuthProvider > `ISignUpEntity` — `attributeSetId` and `attributesSets` are now declared on the `signUp` response, which returned them but had them stripped by validation.
76
+
77
+ - Products > `IProductSearchResult` and Pages > `IPageSearchResult` — new exported types describing the short card the quick search endpoints return: `{ id, title, pageId }` for products and `{ id, title }` for pages. Both have matching Zod schemas (`ProductSearchResultSchema` / `ProductSearchResponseSchema`, `PageSearchResultSchema` / `PageSearchResponseSchema`), so the quick search response is validated like every other response.
78
+
79
+ ### What's Changed
80
+
81
+ - **Breaking** — single-file `image` attributes are now unwrapped in **every** module, not only in the few that ran the extra post-processing step. When an `image` attribute holds exactly one file, its `value` is the file object itself (`[img]` → `img`); values with two or more files stay an array, as before.
82
+
83
+ Previously the unwrapping lived in `_clearArray`, which ran only after `_dataPostProcess` (products, menus, forms, forms-data, attribute-sets, integration-collections and `Pages.searchPage`) and only looked at the `attributeValues` key. Everywhere else — blocks, all other pages methods, `Products.getProductsEmptyPage`, `Products.getProductBlockById`, admins, discounts, templates, orders, users — the same attribute arrived as a one-element array, so consumers had to branch on the shape. Form `attributes`, form-data fields and nested `additionalFields` were never unwrapped at all.
84
+
85
+ The logic now lives in `_normalizeAttr`, which runs on every attribute of every response:
86
+
87
+ ```ts
88
+ const block = await Blocks.getBlockByMarker('promo');
89
+ // before: block.attributeValues.img.value[0].downloadLink
90
+ // now: block.attributeValues.img.value.downloadLink
91
+ ```
92
+
93
+ Code that reads `value[0]` from products or menus is unaffected — those modules already returned the object. Code that reads `value[0]` from blocks, pages, users or orders must drop the index.
94
+
95
+ - **Breaking** — a single-file `file` attribute is unwrapped like `image`: `value` is the file object itself, and an array only when several files are attached. `groupOfImages` is a collection by definition and always stays an array. `IBodyTypeFile.value` is widened to `IFileValue | IFileValue[]` accordingly.
96
+
97
+ - **Breaking** — `real` attributes are cast to a number. `integer` and `float` were already normalized, `real` was not, so the same numeric field reached the consumer as `10` or as `"10"` depending on which of the three types it was declared with:
98
+
99
+ ```ts
100
+ const page = await Pages.getPageByUrl('catalog');
101
+ // before: page.attributeValues.amount.value // "5"
102
+ // now: page.attributeValues.amount.value // 5
103
+ ```
104
+
105
+ - **Breaking** — numeric normalization now also runs on form attributes and on form-data fields, which were skipped entirely. A `rating` field of an `integer` form attribute is a `number`, not a string. `IBodyTypeStringNumberFloat.value` is widened to `string | number | null` (send a string; responses come back normalized).
106
+
107
+ - **Breaking** — an attribute with no value is always `null`. The API returns an empty localization map (`{}`) for an unset value, and the SDK passed it through for text-like types while numeric types became `null` — the same "no value" state had three representations. As a side effect, an unset `integer`/`float` no longer becomes `0`: `Number(null)` is `0`, so an explicit `null` from the API used to be reported as a real zero.
108
+
109
+ - **Breaking** — form `attributes` are sorted by `position`, the way `attributeValues` always were. The API returns form fields unordered (a field with `position: 10` could arrive after `position: 14`), so rendering a form in CMS order required sorting on the consumer side.
110
+
111
+ - **Breaking** — Subscriptions > `getAllSubscriptions` returns `ISubscriptionEntity[]` instead of `string[]`. The signature was taken from swagger, which declares `GET /api/content/subscriptions` as an array of markers; the endpoint actually returns full subscription objects, so response validation reported `expected string, received object` on every call and the declared type never matched the data. Callers that read markers should switch from the array element to its `identifier` field:
112
+
113
+ ```ts
114
+ const subscriptions = await Subscriptions.getAllSubscriptions();
115
+ // before: subscriptions // string[]
116
+ // now: subscriptions.map((s) => s.identifier)
117
+ ```
118
+
119
+ `getActiveSubscriptions` is unchanged (`string[]`).
120
+
121
+ - **Breaking (types only)** — `Products.searchProduct` returns `IProductsEntity[] | IProductSearchResult[] | IError` and `Pages.searchPage` returns `IPagesEntity[] | IPageSearchResult[] | IError`. With `traficLimit: true` both methods return the raw quick search response — a short card without `attributeValues`, `localizeInfos`, `blocks` and the rest of the entity — while the signature promised a full entity in both modes, so a consumer reading `attributeValues` in traficLimit mode got `undefined` with no type error. Runtime behaviour is unchanged; narrow by config or by field:
122
+
123
+ ```ts
124
+ const found = await Products.searchProduct('cos');
125
+ if (Array.isArray(found) && found.length && 'attributeValues' in found[0]) {
126
+ // IProductsEntity[] — traficLimit is off
127
+ }
128
+ ```
129
+
130
+ - `Pages.searchPage` no longer runs the template lookup over the traficLimit response. Short cards carry no `templateIdentifier`, so the step could never attach anything; the result is identical, minus the pointless pass.
131
+
132
+ ### Bug Fixes
133
+
134
+ - Methods whose result is just success-or-failure no longer report `true` when the API rejected the request: `Subscriptions.cancelSubscription`, `Subscriptions.recoverSubscriptions`, `Events.subscribeByMarker`, `Events.unsubscribeByMarker`, `Events.subscribeToForm`, `Events.unsubscribeFromForm`.
135
+
136
+ With `errors.isShell` enabled — the default — the SDK **returns** the API error instead of throwing it. The shared helper behind these six methods only had a `try/catch`, so nothing ever reached its `catch` and every failure was reported as a success: `cancelSubscription` answered `true` while the API replied `404 "Subscription already inactive"`, and the `IError` half of the declared `Promise<boolean | IError>` was unreachable. The helper now also inspects the returned value and passes the error through:
137
+
138
+ ```ts
139
+ const cancelled = await Subscriptions.cancelSubscription({ marker: 'premium' });
140
+ // before: true — on 404 and 403 alike
141
+ // now: { statusCode: 404, message: 'Subscription already inactive', ... }
142
+ ```
143
+
144
+ The success path is unchanged (`true`), and `isShell: false` still throws. Code that checks these results with `if (result)` must switch to `if (result === true)` — an error object is truthy.
145
+
3
146
  ## v.1.0.156
4
147
 
5
148
  ### What's New
@@ -38,11 +38,11 @@ export default class AttributesSetsApi extends AsyncModules implements IAttribut
38
38
  * @handleName getAttributesByMarker
39
39
  * @param {string} marker - Attribute marker. Example: "productAttributes".
40
40
  * @param {string} [langCode] - Language code. Default: "en_US".
41
- * @returns {Promise<IAttributeSetsEntity[] | IError>} Returns an array of Attributes objects.
41
+ * @returns {Promise<IAttributesSetsEntity[] | IError>} Returns an array of Attributes objects.
42
42
  * @throws {IError} When isShell=false and an error occurs during the fetch
43
43
  * @see {@link https://js-sdk.oneentry.cloud/docs/attribute-sets/getAttributesByMarker getAttributesByMarker} documentation.
44
44
  */
45
- getAttributesByMarker(marker: string, langCode?: string): Promise<IAttributeSetsEntity[] | IError>;
45
+ getAttributesByMarker(marker: string, langCode?: string): Promise<IAttributesSetsEntity[] | IError>;
46
46
  /**
47
47
  * Get a single attribute with data from the attribute sets.
48
48
  * @handleName getSingleAttributeByMarkerSet
@@ -50,14 +50,14 @@ class AttributesSetsApi extends asyncModules_1.default {
50
50
  const result = await this._fetchGet(`?` + this._queryParamsToString(query));
51
51
  // Validate response if validation is enabled
52
52
  const validated = this._validateResponse(result, attributeSetsSchemas_1.AttributeSetsResponseSchema);
53
- return this._dataPostProcess(validated, langCode);
53
+ return this._normalizeData(validated, langCode);
54
54
  }
55
55
  /**
56
56
  * Getting all attributes with data from the attribute set.
57
57
  * @handleName getAttributesByMarker
58
58
  * @param {string} marker - Attribute marker. Example: "productAttributes".
59
59
  * @param {string} [langCode] - Language code. Default: "en_US".
60
- * @returns {Promise<IAttributeSetsEntity[] | IError>} Returns an array of Attributes objects.
60
+ * @returns {Promise<IAttributesSetsEntity[] | IError>} Returns an array of Attributes objects.
61
61
  * @throws {IError} When isShell=false and an error occurs during the fetch
62
62
  * @see {@link https://js-sdk.oneentry.cloud/docs/attribute-sets/getAttributesByMarker getAttributesByMarker} documentation.
63
63
  */
@@ -65,7 +65,7 @@ class AttributesSetsApi extends asyncModules_1.default {
65
65
  const result = await this._fetchGet(`/${marker}/attributes?langCode=${langCode}`);
66
66
  // Validate response if validation is enabled
67
67
  const validated = this._validateResponse(result, attributeSetsSchemas_1.AttributesArrayResponseSchema);
68
- return this._dataPostProcess(validated, langCode);
68
+ return this._normalizeData(validated, langCode);
69
69
  }
70
70
  /**
71
71
  * Get a single attribute with data from the attribute sets.
@@ -81,7 +81,7 @@ class AttributesSetsApi extends asyncModules_1.default {
81
81
  const result = await this._fetchGet(`/${setMarker}/attributes/${attributeMarker}?langCode=${langCode}`);
82
82
  // Validate response if validation is enabled
83
83
  const validated = this._validateResponse(result, attributeSetsSchemas_1.AttributeEntitySchema);
84
- return this._dataPostProcess(validated, langCode);
84
+ return this._normalizeData(validated, langCode);
85
85
  }
86
86
  /**
87
87
  * Getting a single object from a set of attributes by marker.
@@ -96,7 +96,7 @@ class AttributesSetsApi extends asyncModules_1.default {
96
96
  const result = await this._fetchGet(`/marker/${marker}?langCode=${langCode}`);
97
97
  // Validate response if validation is enabled
98
98
  const validated = this._validateResponse(result, attributeSetsSchemas_1.AttributeSetEntitySchema);
99
- return this._dataPostProcess(validated, langCode);
99
+ return this._normalizeData(validated, langCode);
100
100
  }
101
101
  }
102
102
  exports.default = AttributesSetsApi;
@@ -10,11 +10,11 @@ interface IAttributesSets {
10
10
  * @handleName getAttributesByMarker
11
11
  * @param {string} marker - The marker used to identify the attribute set. Example: "productAttributes".
12
12
  * @param {string} [langCode] - The language code for localization purposes. Default: 'en_US'.
13
- * @returns {IAttributeSetsEntity[]} A promise that resolves to an array of attribute set entities or an error.
13
+ * @returns {IAttributesSetsEntity[]} A promise that resolves to an array of attribute entities or an error.
14
14
  * @throws {IError} - If there is an error during the fetch operation, it will return an error object.
15
15
  * @description This method fetches attributes by a specific marker.
16
16
  */
17
- getAttributesByMarker(marker: string, langCode: string): Promise<IAttributeSetsEntity[] | IError>;
17
+ getAttributesByMarker(marker: string, langCode: string): Promise<IAttributesSetsEntity[] | IError>;
18
18
  /**
19
19
  * Fetches a single attribute by its marker and the set marker.
20
20
  * @handleName getSingleAttributeByMarkerSet
@@ -82,7 +82,7 @@ type AttributeType = 'string' | 'text' | 'textWithHeader' | 'integer' | 'real' |
82
82
  * Represents an attribute set entity.
83
83
  * @interface IAttributesSetsEntity
84
84
  * @property {AttributeType} type - Attribute type. Example: "string", "text", "integer", "etc".
85
- * @property {unknown} [value] - Value of the attribute, which can be of any type.
85
+ * @property {unknown} [value] - Value of the attribute, normalized the same way as an entity attribute value: `number | null` for numeric types, the file object itself for a single-file `image`/`file`, `null` when the attribute carries no value.
86
86
  * @property {unknown} initialValue - Initial value of the attribute.
87
87
  * @property {string} marker - Textual identifier of the attribute (marker). Example: "color", "size", "etc".
88
88
  * @property {number} position - Position number for sorting. Example: 1.
@@ -137,35 +137,47 @@ interface IAttributesSetsEntity {
137
137
  * @interface IAttributeSchemaItem
138
138
  * @property {number} id - Unique identifier of the schema item. Example: 1.
139
139
  * @property {string} identifier - Field marker (machine name) within the schema. Example: "name".
140
- * @property {unknown} initialValue - Default value applied when the field is not filled.
141
- * @property {boolean} isPrice - Whether the field's numeric value is treated as the price for product entities. Example: false.
140
+ * @property {unknown} [initialValue] - Default value applied when the field is not filled. Optional — absent on some fields.
141
+ * @property {boolean} [isPrice] - Whether the field's numeric value is treated as the price for product entities. Optional — present on product (`forProducts`) attribute sets. Example: false.
142
142
  * @property {boolean} isVisible - Whether the field is exposed in the public API/UI. Example: true.
143
143
  * @property {IAttributeLocalizeInfo} localizeInfos - Localized labels for the field.
144
144
  * @property {boolean} original - Whether the field is part of the original (system) schema, not a user extension. Example: true.
145
145
  * @property {AttributeType} type - Attribute data type (e.g. "string", "file").
146
+ * @property {number} [position] - Sort position of the field inside the set. Optional. Example: 1.
147
+ * @property {IListTitle[]} [listTitles] - Options for `list`/`radioButton`/`entity` fields (with extended data or linked-entity values). Optional.
148
+ * @property {string} [listType] - For `entity` fields — how the option list is organized. Optional. Example: "nested".
149
+ * @property {string} [moduleIdentifier] - For `entity` fields — identifier of the module the linked entities are taken from. Optional. Example: "catalog".
150
+ * @property {number | null} [parentId] - Identifier of the parent field, `null` for top-level. Optional, seen on `groupOfImages` fields.
146
151
  * @property {Record<string, IAttributeSchemaItem>} [additionalFields] - Nested sub-fields keyed by marker. Optional.
147
152
  * @property {IAttributeValidators} [validators] - Validation rules for the field. Optional.
148
153
  * @property {boolean | string} [splitUnit] - Splitting unit configuration; `false` when disabled, otherwise the unit name (e.g. "percent"). Optional, used by numeric fields.
154
+ * @property {number[] | boolean} [splitParts] - For split-price fields — ids of the schema fields the price is split into (e.g. [2, 3]); `false` when the field does not split. Optional.
149
155
  * @property {boolean} [isCurrency] - Whether the field stores currency values. Optional.
150
156
  * @property {boolean} [splitPrice] - Whether the price is split between several fields. Optional.
151
157
  * @property {boolean} [isCompress] - Whether uploaded images are compressed. Optional, used by `image`/`groupOfImages` fields.
152
158
  * @property {boolean} [receiveValues] - For `timeInterval` fields — whether the field receives precomputed values. Optional.
153
159
  * @property {ITimeIntervalSchedule[]} [intervals] - For `timeInterval` fields — top-level schedule definition (separate from `localizeInfos.intervals`). Optional.
154
- * @property {unknown} [value] - For `timeInterval` fields current value/state of the schedule. Optional.
160
+ * @property {unknown} [value] - Current value of the field: `null` on numeric fields without a value, an array of schedule groups on `timeInterval` fields. Optional.
155
161
  * @description Definition of a single field inside an attribute set's schema.
156
162
  */
157
163
  interface IAttributeSchemaItem {
158
164
  id: number;
159
165
  identifier: string;
160
- initialValue: unknown;
161
- isPrice: boolean;
166
+ initialValue?: unknown;
167
+ isPrice?: boolean;
162
168
  isVisible: boolean;
163
169
  localizeInfos: IAttributeLocalizeInfo;
164
170
  original: boolean;
165
171
  type: AttributeType;
172
+ position?: number;
173
+ listTitles?: IListTitle[];
174
+ listType?: string;
175
+ moduleIdentifier?: string;
176
+ parentId?: number | null;
166
177
  additionalFields?: Record<string, IAttributeSchemaItem>;
167
178
  validators?: IAttributeValidators;
168
179
  splitUnit?: boolean | string;
180
+ splitParts?: number[] | boolean;
169
181
  isCurrency?: boolean;
170
182
  splitPrice?: boolean;
171
183
  isCompress?: boolean;
@@ -26,6 +26,8 @@ export declare const SignUpResponseSchema: z.ZodObject<{
26
26
  isDeleted: z.ZodOptional<z.ZodBoolean>;
27
27
  state: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
28
28
  rating: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
29
+ attributeSetId: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
30
+ attributesSets: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
29
31
  }, z.core.$strip>;
30
32
  /**
31
33
  * Auth response schema (login/refresh)
@@ -30,6 +30,8 @@ exports.SignUpResponseSchema = zod_1.z.object({
30
30
  isDeleted: zod_1.z.boolean().optional(),
31
31
  state: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional(),
32
32
  rating: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
33
+ attributeSetId: zod_1.z.number().nullable().optional(),
34
+ attributesSets: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
33
35
  });
34
36
  /**
35
37
  * Auth response schema (login/refresh)
@@ -268,6 +268,8 @@ interface IOauthData {
268
268
  * @property {boolean} [isDeleted] - Whether the entity is deleted. Example: false.
269
269
  * @property {Record<string, unknown>} [state] - Additional state information. Example: {}.
270
270
  * @property {IRating} [rating] - Rating data.
271
+ * @property {number | null} [attributeSetId] - Identifier of the attribute set attached to the user, or null when none is attached. Example: null.
272
+ * @property {Record<string, unknown>} [attributesSets] - Attribute sets attached to the user, keyed by marker; empty object when none. Example: {}.
271
273
  * @description This interface defines the structure of a sign-up entity.
272
274
  */
273
275
  interface ISignUpEntity {
@@ -285,6 +287,8 @@ interface ISignUpEntity {
285
287
  isDeleted?: boolean;
286
288
  state?: Record<string, unknown>;
287
289
  rating?: IRating;
290
+ attributeSetId?: number | null;
291
+ attributesSets?: Record<string, unknown>;
288
292
  }
289
293
  /**
290
294
  * Interface representing a code entity used for user registration or verification processes.
@@ -15,6 +15,17 @@ export default abstract class AsyncModules extends SyncModules {
15
15
  * @description Constructor initializes the AsyncModules with a given state.
16
16
  */
17
17
  protected constructor(state: StateModule);
18
+ /**
19
+ * Detects an API error returned as a value instead of being thrown.
20
+ *
21
+ * With `isShell` enabled (the default) `browserResponse` returns the error
22
+ * body — and a caught exception — instead of throwing, so a failed request
23
+ * is indistinguishable from a successful one by control flow alone.
24
+ * @param {unknown} value - Value returned by a request.
25
+ * @returns {boolean} True when the value is an API error (statusCode >= 400) or a thrown error object.
26
+ * @description Recognizes both the OneEntry error body and errors caught by browserResponse (e.g. a network failure).
27
+ */
28
+ protected _isErrorResponse(value: unknown): value is IError;
18
29
  /**
19
30
  * Validates API response against a Zod schema (optional)
20
31
  * @param {unknown} data - The data to validate
@@ -59,8 +70,13 @@ export default abstract class AsyncModules extends SyncModules {
59
70
  *
60
71
  * Several endpoints (cancel/recover subscription, subscribe/unsubscribe to
61
72
  * events) return no useful body — callers only care whether the request
62
- * succeeded. This helper resolves to `true` on success and to the caught
63
- * error (as IError) on failure, centralizing the repeated try/catch.
73
+ * succeeded. This helper resolves to `true` on success and to the error
74
+ * (as IError) on failure, centralizing the repeated try/catch.
75
+ *
76
+ * The returned value has to be inspected as well: with `isShell` enabled
77
+ * (the default) browserResponse returns the API error instead of throwing
78
+ * it, so relying on the catch alone would report every failed call — a 404
79
+ * from cancelSubscription, a 403 from recoverSubscriptions — as a success.
64
80
  * @param {() => Promise<unknown>} request - Thunk performing the fetch call.
65
81
  * @returns {Promise<boolean | IError>} `true` on success, IError on failure.
66
82
  */
@@ -20,6 +20,26 @@ class AsyncModules extends syncModules_1.default {
20
20
  this.state = state;
21
21
  this._url = this.state.url;
22
22
  }
23
+ /**
24
+ * Detects an API error returned as a value instead of being thrown.
25
+ *
26
+ * With `isShell` enabled (the default) `browserResponse` returns the error
27
+ * body — and a caught exception — instead of throwing, so a failed request
28
+ * is indistinguishable from a successful one by control flow alone.
29
+ * @param {unknown} value - Value returned by a request.
30
+ * @returns {boolean} True when the value is an API error (statusCode >= 400) or a thrown error object.
31
+ * @description Recognizes both the OneEntry error body and errors caught by browserResponse (e.g. a network failure).
32
+ */
33
+ _isErrorResponse(value) {
34
+ if (value instanceof Error) {
35
+ return true;
36
+ }
37
+ return (value !== null &&
38
+ typeof value === 'object' &&
39
+ 'statusCode' in value &&
40
+ typeof value.statusCode === 'number' &&
41
+ value.statusCode >= 400);
42
+ }
23
43
  /**
24
44
  * Validates API response against a Zod schema (optional)
25
45
  * @param {unknown} data - The data to validate
@@ -33,11 +53,7 @@ class AsyncModules extends syncModules_1.default {
33
53
  return data;
34
54
  }
35
55
  // Skip validation for error responses (statusCode indicates API error)
36
- if (data !== null &&
37
- typeof data === 'object' &&
38
- 'statusCode' in data &&
39
- typeof data.statusCode === 'number' &&
40
- data.statusCode >= 400) {
56
+ if (this._isErrorResponse(data)) {
41
57
  return data;
42
58
  }
43
59
  // Use strict or safe validation based on config
@@ -109,14 +125,22 @@ class AsyncModules extends syncModules_1.default {
109
125
  *
110
126
  * Several endpoints (cancel/recover subscription, subscribe/unsubscribe to
111
127
  * events) return no useful body — callers only care whether the request
112
- * succeeded. This helper resolves to `true` on success and to the caught
113
- * error (as IError) on failure, centralizing the repeated try/catch.
128
+ * succeeded. This helper resolves to `true` on success and to the error
129
+ * (as IError) on failure, centralizing the repeated try/catch.
130
+ *
131
+ * The returned value has to be inspected as well: with `isShell` enabled
132
+ * (the default) browserResponse returns the API error instead of throwing
133
+ * it, so relying on the catch alone would report every failed call — a 404
134
+ * from cancelSubscription, a 403 from recoverSubscriptions — as a success.
114
135
  * @param {() => Promise<unknown>} request - Thunk performing the fetch call.
115
136
  * @returns {Promise<boolean | IError>} `true` on success, IError on failure.
116
137
  */
117
138
  async _fetchBoolean(request) {
118
139
  try {
119
- await request();
140
+ const result = await request();
141
+ if (this._isErrorResponse(result)) {
142
+ return result;
143
+ }
120
144
  return true;
121
145
  }
122
146
  catch (e) {
@@ -88,27 +88,33 @@ export default abstract class SyncModules {
88
88
  */
89
89
  protected _normalizePostBody(body: any, langCode?: string): any;
90
90
  /**
91
- * Clears arrays within the data structure.
91
+ * Normalizes the value of a single attribute in place.
92
92
  *
93
- * Traverses the data and fixes a specific edge case with image attributes:
94
- * when an `image` attribute has a single-element array in `value`,
95
- * the API returns an array but consumers expect a plain object.
96
- * In that case `value` is unwrapped: `[img]` → `img`.
93
+ * Applies the three type-driven fixes the API response needs, so that an
94
+ * attribute of a given type always reaches the consumer in the same shape,
95
+ * no matter which collection it arrived in:
97
96
  *
98
- * For all other keys the method recursively copies the structure unchanged.
99
- * @param {Record<string, any>} data - The data to clear.
100
- * @returns {any} Cleared data.
97
+ * 1. **Single-file values** (`image`, `file`) — the API always sends an array,
98
+ * even for one file: `[img]` → `img`. Multi-file values and `groupOfImages`
99
+ * (a collection by definition) stay an array.
100
+ * 2. **Empty values** — an attribute with no value comes back as an empty
101
+ * localization map `{}`; it is replaced with `null`, the same marker the
102
+ * numeric branch already produced.
103
+ * 3. **Numbers** (`integer`, `float`, `real`) — cast to a JS number; anything
104
+ * that is not a number (including an empty value) becomes `null`.
105
+ * @param {any} attr - The attribute object to normalize in place.
101
106
  */
102
- protected _clearArray(data: Record<string, any>): any;
107
+ private _normalizeAttrValue;
103
108
  /**
104
109
  * Sorts attributes by their positions.
105
110
  *
106
- * The API returns attributes as an object `{ marker: AttrObject }`.
107
- * Each attribute has a `position` field. The method rebuilds the object
108
- * with keys sorted by ascending `position` so that the display order
109
- * matches the order defined in the CMS.
110
- * @param {any} data - The data containing attributes.
111
- * @returns {any} Sorted attributes.
111
+ * Each attribute has a `position` field, and the API returns them in no
112
+ * particular order. The method rebuilds the collection sorted by ascending
113
+ * `position`, so the display order matches the order defined in the CMS.
114
+ * Both container shapes the API uses are handled: an object keyed by marker
115
+ * (`attributeValues`) and an array (form `attributes`).
116
+ * @param {any} data - The attributes collection to sort.
117
+ * @returns {any} Sorted attributes, in the same container shape.
112
118
  */
113
119
  protected _sortAttributes: (data: any) => any;
114
120
  /**
@@ -127,18 +133,24 @@ export default abstract class SyncModules {
127
133
  *
128
134
  * Handles three different attribute formats returned by the API:
129
135
  *
130
- * **1. `attributeValues`** attributes of pages, products and other entities.
131
- * Contains an object `{ marker: AttrObject }`. For each attribute:
132
- * - `_normalizeAdditionalFields` is called;
133
- * - numeric types (`integer`, `float`) are cast to a JS number (or `null`);
134
- * - the whole object is re-sorted by `position`.
136
+ * All three go through the same steps, so an attribute of a given type looks
137
+ * the same whichever collection it arrived in:
138
+ * - `_normalizeAdditionalFields` turns nested fields into a marker map;
139
+ * - `_normalizeAttrValue` unwraps single-file values, empties to `null` and
140
+ * casts numbers;
141
+ * - the collection is re-sorted by `position`.
135
142
  *
136
- * **2. `attributes`** — form attributes (different API structure).
137
- * Same `additionalFields` processing,
138
- * but numbers are not normalized here (commented out — logic differs).
143
+ * **1. `attributeValues`** — attributes of pages, products and other entities,
144
+ * an object `{ marker: AttrObject }`.
139
145
  *
140
- * **3. `type`** — a single attribute from an attribute set.
141
- * Same transformations as in case 1, but without sorting.
146
+ * **2. `attributes`** — form attributes, an array (or a marker map on some
147
+ * endpoints); form-only boolean flags (`isLogin`, `isSignUp`, notifications)
148
+ * are additionally coerced from `null` to `false`. A form with no attributes
149
+ * arrives as an empty object `{}` — it is normalized to an empty array.
150
+ *
151
+ * **3. `type`** — a standalone attribute: an attribute-set entry, a form-data
152
+ * field or a nested `additionalFields` entry. Same transformations, but there
153
+ * is no collection to sort.
142
154
  *
143
155
  * `timeInterval` attributes are left exactly as the API returned them — a
144
156
  * compact recurrence rule. Resolving one into concrete slots is the caller's
@@ -150,17 +162,6 @@ export default abstract class SyncModules {
150
162
  * @returns {any} Normalized attributes.
151
163
  */
152
164
  protected _normalizeAttr(data: any): any;
153
- /**
154
- * Processes data after fetching or receiving it.
155
- *
156
- * Final post-processing of the API response: first unwraps localized fields
157
- * (`_normalizeData`), then fixes single-element image attributes
158
- * (`_clearArray`). Called at the end of every fetch method.
159
- * @param {any} data - The data to process.
160
- * @param {any} [langCode] - The language code for processing.
161
- * @returns {any} Processed data.
162
- */
163
- protected _dataPostProcess(data: any, langCode?: string): any;
164
165
  /**
165
166
  * Sets the access token in the state.
166
167
  * @param {string} accessToken - The access token to set.