oneentry 1.0.176 → 1.0.178

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 (199) hide show
  1. package/README.md +12 -5
  2. package/changelog.md +116 -0
  3. package/dist/admins/adminsApi.js +2 -9
  4. package/dist/admins/adminsInterfaces.d.ts +5 -5
  5. package/dist/admins/adminsSchemas.d.ts +4 -4
  6. package/dist/admins/adminsSchemas.js +2 -2
  7. package/dist/attribute-sets/attributeSetsApi.d.ts +1 -1
  8. package/dist/attribute-sets/attributeSetsApi.js +4 -4
  9. package/dist/attribute-sets/attributeSetsInterfaces.d.ts +65 -14
  10. package/dist/attribute-sets/attributeSetsSchemas.d.ts +8 -6
  11. package/dist/attribute-sets/attributeSetsSchemas.js +6 -9
  12. package/dist/auth-provider/authProviderApi.d.ts +4 -4
  13. package/dist/auth-provider/authProviderApi.js +90 -23
  14. package/dist/auth-provider/authProviderSchemas.d.ts +1 -0
  15. package/dist/auth-provider/authProviderSchemas.js +1 -0
  16. package/dist/auth-provider/authProvidersInterfaces.d.ts +8 -6
  17. package/dist/base/asyncModules.d.ts +62 -1
  18. package/dist/base/asyncModules.js +219 -37
  19. package/dist/base/stateModule.d.ts +2 -0
  20. package/dist/base/stateModule.js +22 -12
  21. package/dist/base/syncModules.d.ts +18 -10
  22. package/dist/base/syncModules.js +100 -29
  23. package/dist/base/utils.d.ts +26 -21
  24. package/dist/base/validation.d.ts +3 -3
  25. package/dist/base/validation.js +6 -7
  26. package/dist/blocks/blocksApi.d.ts +20 -17
  27. package/dist/blocks/blocksApi.js +82 -64
  28. package/dist/blocks/blocksInterfaces.d.ts +8 -8
  29. package/dist/discounts/discountsApi.d.ts +9 -7
  30. package/dist/discounts/discountsApi.js +16 -13
  31. package/dist/discounts/discountsInterfaces.d.ts +14 -10
  32. package/dist/events/eventsApi.d.ts +3 -3
  33. package/dist/events/eventsApi.js +3 -3
  34. package/dist/events/eventsInterfaces.d.ts +10 -14
  35. package/dist/file-uploading/fileUploadingApi.d.ts +4 -4
  36. package/dist/file-uploading/fileUploadingApi.js +13 -5
  37. package/dist/file-uploading/fileUploadingInterfaces.d.ts +5 -6
  38. package/dist/filters/filtersApi.js +2 -2
  39. package/dist/forms/formsApi.js +2 -2
  40. package/dist/forms/formsInterfaces.d.ts +1 -3
  41. package/dist/forms/formsSchemas.d.ts +3 -6
  42. package/dist/forms/formsSchemas.js +2 -4
  43. package/dist/forms-data/formsDataApi.d.ts +27 -1
  44. package/dist/forms-data/formsDataApi.js +119 -68
  45. package/dist/forms-data/formsDataInterfaces.d.ts +17 -13
  46. package/dist/general-types/generalTypesInterfaces.d.ts +1 -1
  47. package/dist/index.d.ts +7 -6
  48. package/dist/index.js +50 -7
  49. package/dist/integration-collections/integrationCollectionsApi.d.ts +15 -4
  50. package/dist/integration-collections/integrationCollectionsApi.js +41 -14
  51. package/dist/integration-collections/integrationCollectionsInterfaces.d.ts +8 -9
  52. package/dist/integration-collections/integrationCollectionsSchemas.d.ts +0 -2
  53. package/dist/integration-collections/integrationCollectionsSchemas.js +0 -1
  54. package/dist/menus/menusApi.js +1 -1
  55. package/dist/orders/ordersApi.d.ts +1 -13
  56. package/dist/orders/ordersApi.js +21 -42
  57. package/dist/orders/ordersInterfaces.d.ts +21 -14
  58. package/dist/pages/pagesApi.d.ts +8 -6
  59. package/dist/pages/pagesApi.js +48 -33
  60. package/dist/pages/pagesInterfaces.d.ts +20 -16
  61. package/dist/pages/pagesSchemas.d.ts +0 -3
  62. package/dist/pages/pagesSchemas.js +0 -1
  63. package/dist/payments/paymentsApi.d.ts +10 -11
  64. package/dist/payments/paymentsApi.js +22 -18
  65. package/dist/payments/paymentsInterfaces.d.ts +12 -14
  66. package/dist/payments/paymentsSchemas.d.ts +21 -20
  67. package/dist/payments/paymentsSchemas.js +5 -8
  68. package/dist/product-statuses/productStatusesApi.d.ts +1 -1
  69. package/dist/product-statuses/productStatusesApi.js +3 -3
  70. package/dist/product-statuses/productStatusesInterfaces.d.ts +1 -4
  71. package/dist/products/productsApi.d.ts +50 -64
  72. package/dist/products/productsApi.js +79 -80
  73. package/dist/products/productsInterfaces.d.ts +59 -90
  74. package/dist/search/searchApi.d.ts +3 -2
  75. package/dist/search/searchApi.js +7 -4
  76. package/dist/search/searchInterfaces.d.ts +2 -1
  77. package/dist/sitemap/sitemapInterfaces.d.ts +10 -6
  78. package/dist/subscriptions/subscriptionsApi.d.ts +1 -1
  79. package/dist/subscriptions/subscriptionsApi.js +1 -1
  80. package/dist/subscriptions/subscriptionsInterfaces.d.ts +1 -1
  81. package/dist/system/systemApi.d.ts +2 -0
  82. package/dist/system/systemApi.js +2 -0
  83. package/dist/system/systemInterfaces.d.ts +2 -0
  84. package/dist/templates/templatesApi.d.ts +2 -2
  85. package/dist/templates/templatesApi.js +12 -11
  86. package/dist/templates/templatesInterfaces.d.ts +2 -2
  87. package/dist/templates-preview/templatesPreviewApi.js +2 -2
  88. package/dist/templates-preview/templatesPreviewInterfaces.d.ts +23 -13
  89. package/dist/templates-preview/templatesPreviewSchemas.d.ts +7 -0
  90. package/dist/templates-preview/templatesPreviewSchemas.js +2 -0
  91. package/dist/user-groups/userGroupsApi.js +5 -5
  92. package/dist/user-groups/userGroupsSchemas.d.ts +4 -4
  93. package/dist/users/usersApi.d.ts +1 -1
  94. package/dist/users/usersApi.js +28 -15
  95. package/dist/users/usersInterfaces.d.ts +2 -9
  96. package/dist/web-socket/lazySocket.d.ts +6 -5
  97. package/dist/web-socket/lazySocket.js +212 -15
  98. package/dist/web-socket/wsApi.d.ts +7 -4
  99. package/dist/web-socket/wsApi.js +49 -12
  100. package/dist/web-socket/wsInterfaces.d.ts +41 -4
  101. package/esm/admins/adminsApi.js +2 -9
  102. package/esm/admins/adminsInterfaces.d.ts +5 -5
  103. package/esm/admins/adminsSchemas.d.ts +4 -4
  104. package/esm/admins/adminsSchemas.js +2 -2
  105. package/esm/attribute-sets/attributeSetsApi.d.ts +1 -1
  106. package/esm/attribute-sets/attributeSetsApi.js +4 -4
  107. package/esm/attribute-sets/attributeSetsInterfaces.d.ts +65 -14
  108. package/esm/attribute-sets/attributeSetsSchemas.d.ts +8 -6
  109. package/esm/attribute-sets/attributeSetsSchemas.js +6 -9
  110. package/esm/auth-provider/authProviderApi.d.ts +4 -4
  111. package/esm/auth-provider/authProviderApi.js +90 -23
  112. package/esm/auth-provider/authProviderSchemas.d.ts +1 -0
  113. package/esm/auth-provider/authProviderSchemas.js +1 -0
  114. package/esm/auth-provider/authProvidersInterfaces.d.ts +8 -6
  115. package/esm/base/asyncModules.d.ts +62 -1
  116. package/esm/base/asyncModules.js +219 -37
  117. package/esm/base/stateModule.d.ts +2 -0
  118. package/esm/base/stateModule.js +22 -12
  119. package/esm/base/syncModules.d.ts +18 -10
  120. package/esm/base/syncModules.js +99 -29
  121. package/esm/base/utils.d.ts +26 -21
  122. package/esm/base/validation.d.ts +3 -3
  123. package/esm/base/validation.js +6 -7
  124. package/esm/blocks/blocksApi.d.ts +20 -17
  125. package/esm/blocks/blocksApi.js +82 -64
  126. package/esm/blocks/blocksInterfaces.d.ts +8 -8
  127. package/esm/discounts/discountsApi.d.ts +9 -7
  128. package/esm/discounts/discountsApi.js +16 -13
  129. package/esm/discounts/discountsInterfaces.d.ts +14 -10
  130. package/esm/events/eventsApi.d.ts +3 -3
  131. package/esm/events/eventsApi.js +3 -3
  132. package/esm/events/eventsInterfaces.d.ts +10 -14
  133. package/esm/file-uploading/fileUploadingApi.d.ts +4 -4
  134. package/esm/file-uploading/fileUploadingApi.js +13 -5
  135. package/esm/file-uploading/fileUploadingInterfaces.d.ts +5 -6
  136. package/esm/filters/filtersApi.js +2 -2
  137. package/esm/forms/formsApi.js +2 -2
  138. package/esm/forms/formsInterfaces.d.ts +1 -3
  139. package/esm/forms/formsSchemas.d.ts +3 -6
  140. package/esm/forms/formsSchemas.js +2 -4
  141. package/esm/forms-data/formsDataApi.d.ts +27 -1
  142. package/esm/forms-data/formsDataApi.js +119 -68
  143. package/esm/forms-data/formsDataInterfaces.d.ts +17 -13
  144. package/esm/general-types/generalTypesInterfaces.d.ts +1 -1
  145. package/esm/index.d.ts +7 -6
  146. package/esm/index.js +50 -7
  147. package/esm/integration-collections/integrationCollectionsApi.d.ts +15 -4
  148. package/esm/integration-collections/integrationCollectionsApi.js +41 -14
  149. package/esm/integration-collections/integrationCollectionsInterfaces.d.ts +8 -9
  150. package/esm/integration-collections/integrationCollectionsSchemas.d.ts +0 -2
  151. package/esm/integration-collections/integrationCollectionsSchemas.js +0 -1
  152. package/esm/menus/menusApi.js +1 -1
  153. package/esm/orders/ordersApi.d.ts +1 -13
  154. package/esm/orders/ordersApi.js +21 -42
  155. package/esm/orders/ordersInterfaces.d.ts +21 -14
  156. package/esm/pages/pagesApi.d.ts +8 -6
  157. package/esm/pages/pagesApi.js +48 -33
  158. package/esm/pages/pagesInterfaces.d.ts +20 -16
  159. package/esm/pages/pagesSchemas.d.ts +0 -3
  160. package/esm/pages/pagesSchemas.js +0 -1
  161. package/esm/payments/paymentsApi.d.ts +10 -11
  162. package/esm/payments/paymentsApi.js +22 -18
  163. package/esm/payments/paymentsInterfaces.d.ts +12 -14
  164. package/esm/payments/paymentsSchemas.d.ts +21 -20
  165. package/esm/payments/paymentsSchemas.js +5 -8
  166. package/esm/product-statuses/productStatusesApi.d.ts +1 -1
  167. package/esm/product-statuses/productStatusesApi.js +3 -3
  168. package/esm/product-statuses/productStatusesInterfaces.d.ts +1 -4
  169. package/esm/products/productsApi.d.ts +50 -64
  170. package/esm/products/productsApi.js +79 -80
  171. package/esm/products/productsInterfaces.d.ts +59 -90
  172. package/esm/search/searchApi.d.ts +3 -2
  173. package/esm/search/searchApi.js +7 -4
  174. package/esm/search/searchInterfaces.d.ts +2 -1
  175. package/esm/sitemap/sitemapInterfaces.d.ts +10 -6
  176. package/esm/subscriptions/subscriptionsApi.d.ts +1 -1
  177. package/esm/subscriptions/subscriptionsApi.js +1 -1
  178. package/esm/subscriptions/subscriptionsInterfaces.d.ts +1 -1
  179. package/esm/system/systemApi.d.ts +2 -0
  180. package/esm/system/systemApi.js +2 -0
  181. package/esm/system/systemInterfaces.d.ts +2 -0
  182. package/esm/templates/templatesApi.d.ts +2 -2
  183. package/esm/templates/templatesApi.js +11 -10
  184. package/esm/templates/templatesInterfaces.d.ts +2 -2
  185. package/esm/templates-preview/templatesPreviewApi.js +2 -2
  186. package/esm/templates-preview/templatesPreviewInterfaces.d.ts +23 -13
  187. package/esm/templates-preview/templatesPreviewSchemas.d.ts +7 -0
  188. package/esm/templates-preview/templatesPreviewSchemas.js +2 -0
  189. package/esm/user-groups/userGroupsApi.js +5 -5
  190. package/esm/user-groups/userGroupsSchemas.d.ts +4 -4
  191. package/esm/users/usersApi.d.ts +1 -1
  192. package/esm/users/usersApi.js +28 -15
  193. package/esm/users/usersInterfaces.d.ts +2 -9
  194. package/esm/web-socket/lazySocket.d.ts +6 -5
  195. package/esm/web-socket/lazySocket.js +212 -15
  196. package/esm/web-socket/wsApi.d.ts +7 -4
  197. package/esm/web-socket/wsApi.js +49 -12
  198. package/esm/web-socket/wsInterfaces.d.ts +41 -4
  199. package/package.json +2 -2
@@ -9,31 +9,46 @@ const _persistentIds = {};
9
9
  *
10
10
  * Prefers a cryptographically secure source (Web Crypto, exposed as
11
11
  * `globalThis.crypto` in browsers and Node.js >= 18): `randomUUID()` when
12
- * available, otherwise random bytes rendered as a base-36 string. Falls back to
13
- * a timestamp + `Math.random()` only when no CSPRNG exists (e.g. very old Node).
14
- *
15
- * The result contains no special characters, so it is safe to use both in
16
- * localStorage and in HTTP headers.
17
- * @returns {string} A freshly generated identifier.
12
+ * available, otherwise a UUID v4 built from `getRandomValues`, and from
13
+ * `Math.random()` only when no CSPRNG exists (e.g. very old Node).
14
+ * @returns {string} A freshly generated UUID v4.
18
15
  */
19
16
  function _generateId() {
20
17
  const cryptoObj = typeof globalThis !== 'undefined' ? globalThis.crypto : undefined;
21
18
  if (cryptoObj === null || cryptoObj === void 0 ? void 0 : cryptoObj.randomUUID) {
22
19
  return cryptoObj.randomUUID();
23
20
  }
21
+ // `randomUUID` is missing on pages served over plain http (not a secure context): the id
22
+ // must still be a UUID v4 — the platform silently replaces any other guest id on every
23
+ // request, and the guest cart was lost
24
+ const bytes = new Uint8Array(16);
24
25
  if (cryptoObj === null || cryptoObj === void 0 ? void 0 : cryptoObj.getRandomValues) {
25
- const bytes = cryptoObj.getRandomValues(new Uint8Array(18));
26
- let result = '';
26
+ cryptoObj.getRandomValues(bytes);
27
+ }
28
+ else {
29
+ // Last-resort fallback for environments without Web Crypto: non-cryptographic.
27
30
  for (let i = 0; i < bytes.length; i++) {
28
- result += bytes[i].toString(36).padStart(2, '0');
31
+ bytes[i] = Math.floor(Math.random() * 256);
29
32
  }
30
- return result;
31
33
  }
32
- // Last-resort fallback for environments without Web Crypto.
33
- // Non-cryptographic, but adequate when nothing better is available.
34
- return (Date.now().toString(36) +
35
- Math.random().toString(36).substring(2, 15) +
36
- Math.random().toString(36).substring(2, 15));
34
+ bytes[6] = (bytes[6] & 0x0f) | 0x40;
35
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
36
+ const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
37
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
38
+ }
39
+ /**
40
+ * The UUID v4 shape the platform requires of a guest id (it replaces any other value).
41
+ */
42
+ const _UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
43
+ /**
44
+ * Warns about a caller's guest id the platform will not keep.
45
+ * @param {string | undefined} guestId - The id passed in config or to `setGuestId`.
46
+ */
47
+ export function _warnGuestId(guestId) {
48
+ if (guestId && !_UUID.test(guestId)) {
49
+ // eslint-disable-next-line no-undef, no-console
50
+ console.warn('OneEntry SDK: guestId must be a UUID v4 — the platform replaces any other value on every request, and the guest cart is lost');
51
+ }
37
52
  }
38
53
  /**
39
54
  * Returns a stable identifier for the browser environment, persisted in localStorage.
@@ -57,7 +72,9 @@ function _getPersistentBrowserId(storageKey) {
57
72
  return _persistentIds[storageKey];
58
73
  try {
59
74
  const stored = win.localStorage.getItem(storageKey);
60
- if (stored) {
75
+ // A guest id stored by an older SDK may not be a UUID: replace it, the platform ignores it
76
+ if (stored &&
77
+ (storageKey !== _GUEST_ID_STORAGE_KEY || _UUID.test(stored))) {
61
78
  _persistentIds[storageKey] = stored;
62
79
  return _persistentIds[storageKey];
63
80
  }
@@ -77,6 +94,21 @@ function _getPersistentBrowserId(storageKey) {
77
94
  }
78
95
  return _persistentIds[storageKey];
79
96
  }
97
+ /**
98
+ * Attribute types for which the API's `""` means "not set": none of them has an empty-string value.
99
+ */
100
+ const EMPTY_STRING_UNSET_TYPES = new Set([
101
+ 'image',
102
+ 'groupOfImages',
103
+ 'file',
104
+ 'timeInterval',
105
+ 'date',
106
+ 'dateTime',
107
+ 'time',
108
+ 'list',
109
+ 'radioButton',
110
+ 'entity',
111
+ ]);
80
112
  /**
81
113
  * Abstract class representing synchronization modules.
82
114
  */
@@ -102,7 +134,12 @@ export default class SyncModules {
102
134
  : Object.fromEntries(Object.entries(data).sort(([, a], [, b]) => a.position - b.position));
103
135
  this.state = state;
104
136
  this._url = state.url;
105
- this._nodeDeviceId = _generateId();
137
+ // Fallback device ID for Node.js and cases where localStorage is unavailable.
138
+ // Kept on the shared state, so every module of one client sends the same one:
139
+ // generated per module, the token issued by AuthProvider was refreshed from
140
+ // another module with another fingerprint and answered `400 Provided token is incorrect`.
141
+ if (!state.nodeDeviceId)
142
+ state.nodeDeviceId = _generateId();
106
143
  }
107
144
  /**
108
145
  * Resolves the guest identifier for the current request, or `undefined`.
@@ -266,9 +303,26 @@ export default class SyncModules {
266
303
  * numeric branch already produced.
267
304
  * 3. **Numbers** (`integer`, `float`, `real`) — cast to a JS number; anything
268
305
  * that is not a number (including an empty value) becomes `null`.
306
+ * 4. **Empty strings** of non-text types (`image`, `groupOfImages`, `file`,
307
+ * `timeInterval`, `date`, `dateTime`, `time`) — the API sends an unset value as
308
+ * `""`; it is replaced with `null`. For text types `""` is a real value and stays.
269
309
  * @param {any} attr - The attribute object to normalize in place.
310
+ * @param {boolean} [isEntityValue] - The attribute is a value of an entity (`attributeValues`): one without a `value` key is unset and gets `null`. Form fields and attribute-set schemas describe a field and get no key.
270
311
  */
271
- _normalizeAttrValue(attr) {
312
+ _normalizeAttrValue(attr, isEntityValue = false) {
313
+ // A non-object entry is not an attribute: leave it as it is instead of throwing
314
+ if (!attr || typeof attr !== 'object')
315
+ return;
316
+ // Only an attribute (it has a `type`): a locale map left by a missing translation is not one
317
+ if (isEntityValue && 'type' in attr && !('value' in attr)) {
318
+ attr.value = null;
319
+ }
320
+ // Only for entity values: form data of orders and users types these fields without `null`
321
+ if (isEntityValue &&
322
+ attr.value === '' &&
323
+ EMPTY_STRING_UNSET_TYPES.has(attr.type)) {
324
+ attr.value = null;
325
+ }
272
326
  if ((attr.type === 'image' || attr.type === 'file') &&
273
327
  Array.isArray(attr.value) &&
274
328
  attr.value.length === 1) {
@@ -281,9 +335,11 @@ export default class SyncModules {
281
335
  Object.keys(attr.value).length === 0) {
282
336
  attr.value = null;
283
337
  }
284
- if (attr.type === 'integer' ||
338
+ if ((attr.type === 'integer' ||
285
339
  attr.type === 'float' ||
286
- attr.type === 'real') {
340
+ attr.type === 'real') &&
341
+ // A form attribute describes a field and carries no `value` key — don't add one
342
+ 'value' in attr) {
287
343
  // Number(null) is 0 and Number('') is 0 — an empty value must stay empty.
288
344
  const isEmpty = attr.value === null || attr.value === undefined || attr.value === '';
289
345
  const numValue = isEmpty ? NaN : Number(attr.value);
@@ -301,7 +357,7 @@ export default class SyncModules {
301
357
  * @param {any} attr - The attribute object that may contain additionalFields.
302
358
  */
303
359
  _normalizeAdditionalFields(attr) {
304
- if (!this.state.rawData && Array.isArray(attr.additionalFields)) {
360
+ if (attr && !this.state.rawData && Array.isArray(attr.additionalFields)) {
305
361
  attr.additionalFields = Object.fromEntries(attr.additionalFields.map((field) => [field.marker, field]));
306
362
  }
307
363
  }
@@ -341,10 +397,17 @@ export default class SyncModules {
341
397
  _normalizeAttr(data) {
342
398
  // For regular attributes collections - pages, products, etc.
343
399
  if ('attributeValues' in data) {
400
+ // `null` (or any non-object) is not a collection: `Object.keys(null)` threw past
401
+ // isShell and took a whole list down with one record
402
+ if (!data.attributeValues ||
403
+ typeof data.attributeValues !== 'object' ||
404
+ Array.isArray(data.attributeValues)) {
405
+ return data;
406
+ }
344
407
  Object.keys(data.attributeValues).forEach((attr) => {
345
408
  const d = data.attributeValues[attr];
346
409
  this._normalizeAdditionalFields(d);
347
- this._normalizeAttrValue(d);
410
+ this._normalizeAttrValue(d, true);
348
411
  });
349
412
  return {
350
413
  ...data,
@@ -361,6 +424,9 @@ export default class SyncModules {
361
424
  // for forms attributes - forms attributes collections
362
425
  if ('attributes' in data) {
363
426
  const d = data.attributes;
427
+ if (!d || typeof d !== 'object') {
428
+ return data;
429
+ }
364
430
  // A form with no attributes arrives as an empty object `{}` — normalize
365
431
  // it to an empty array, the container every non-empty form uses.
366
432
  if (d &&
@@ -373,7 +439,10 @@ export default class SyncModules {
373
439
  this._normalizeAdditionalFields(d[attr]);
374
440
  this._normalizeAttrValue(d[attr]);
375
441
  for (const field of booleanFields) {
376
- if (field in d[attr] && d[attr][field] === null) {
442
+ if (d[attr] &&
443
+ typeof d[attr] === 'object' &&
444
+ field in d[attr] &&
445
+ d[attr][field] === null) {
377
446
  d[attr][field] = false;
378
447
  }
379
448
  }
@@ -395,7 +464,7 @@ export default class SyncModules {
395
464
  /**
396
465
  * Sets the access token in the state.
397
466
  * @param {string} accessToken - The access token to set.
398
- * @returns {any} The instance of SyncModules for chaining.
467
+ * @returns {this} The same module, for chaining.
399
468
  */
400
469
  setAccessToken(accessToken) {
401
470
  this.state.accessToken = accessToken;
@@ -404,7 +473,7 @@ export default class SyncModules {
404
473
  /**
405
474
  * Sets the refresh token in the state.
406
475
  * @param {string} refreshToken - The refresh token to set.
407
- * @returns {any} The instance of SyncModules for chaining.
476
+ * @returns {this} The same module, for chaining.
408
477
  */
409
478
  setRefreshToken(refreshToken) {
410
479
  this.state.refreshToken = refreshToken;
@@ -418,9 +487,10 @@ export default class SyncModules {
418
487
  * (the SDK then falls back to the localStorage-backed id in the browser, or to
419
488
  * no guest id at all on the server).
420
489
  * @param {string} guestId - The guest identifier to set (empty string clears it).
421
- * @returns {any} The instance of SyncModules for chaining.
490
+ * @returns {this} The same module, for chaining.
422
491
  */
423
492
  setGuestId(guestId) {
493
+ _warnGuestId(guestId);
424
494
  this.state.guestId = guestId || undefined;
425
495
  return this;
426
496
  }
@@ -434,7 +504,7 @@ export default class SyncModules {
434
504
  * browser's string (obtained there via `getDeviceMetadata`). Pass an empty
435
505
  * string to clear the override and fall back to the computed fingerprint.
436
506
  * @param {string} deviceMetadata - The metadata string to send (empty string clears the override).
437
- * @returns {any} The instance of SyncModules for chaining.
507
+ * @returns {this} The same module, for chaining.
438
508
  */
439
509
  setDeviceMetadata(deviceMetadata) {
440
510
  this.state.deviceMetadata = deviceMetadata || undefined;
@@ -475,7 +545,7 @@ export default class SyncModules {
475
545
  *
476
546
  * **instanceId strategy:**
477
547
  * - Browser: `_getPersistentBrowserId('oneentry_device_id')` — read from localStorage, stable across sessions.
478
- * - Node.js / no localStorage: `_nodeDeviceId` — generated at instance creation,
548
+ * - Node.js / no localStorage: `state.nodeDeviceId` — generated once per client (shared by its modules),
479
549
  * lives until the process restarts.
480
550
  *
481
551
  * In a Node.js environment (no `window`) returns a simplified object without screen/navigator.
@@ -497,7 +567,7 @@ export default class SyncModules {
497
567
  }
498
568
  // Access navigator through globalThis.window object to avoid direct reference
499
569
  const win = globalThis.window;
500
- const instanceId = (_a = _getPersistentBrowserId(_DEVICE_ID_STORAGE_KEY)) !== null && _a !== void 0 ? _a : this._nodeDeviceId;
570
+ const instanceId = (_a = _getPersistentBrowserId(_DEVICE_ID_STORAGE_KEY)) !== null && _a !== void 0 ? _a : this.state.nodeDeviceId;
501
571
  // Node.js environment
502
572
  if (!win) {
503
573
  return JSON.stringify({
@@ -1,21 +1,26 @@
1
1
  /**
2
2
  * @interface IConfig
3
- * @property {string} [token] - If your project is protected by a token, specify this token in this parameter.
4
- * @property {string} [guestId] - Guest identifier sent as the `x-guest-id` header on unauthenticated requests. Lets cart/wishlist/activity endpoints work for a guest. In the browser a stable id is auto-generated (localStorage) when omitted; on the server pass a per-visitor id. Can also be set later via `setGuestId`.
3
+ * @property {string} token - App token of the project. Required: `defineOneEntry` throws without it.
4
+ * @property {string} [guestId] - Guest identifier sent as the `x-guest-id` header on unauthenticated requests. Must be a UUID v4 — the platform replaces any other value with a new id on every request, so a guest cart is silently lost. Lets cart/wishlist/activity endpoints work for a guest. In the browser a stable id is auto-generated (localStorage) when omitted; on the server pass a per-visitor id. Can also be set later via `setGuestId`.
5
5
  * @property {string} [deviceMetadata] - Device-metadata string sent as the `x-device-metadata` header on POST requests and token refresh, overriding the environment-derived fingerprint. The API binds refresh tokens to this header, so server-side flows that issue tokens on behalf of a browser (e.g. an OAuth code exchange) must pass the browser's string here — otherwise the token is bound to the server's fingerprint and cannot be refreshed from the browser. Obtain the string in the browser via `getDeviceMetadata()`. Can also be set later via `setDeviceMetadata`.
6
- * @property {string} [langCode] - specify the default language to avoid specifying it in every request.
6
+ * @property {string} [langCode] - specify the default language to avoid specifying it in every request. Default: 'en_US' (an empty string counts as not set).
7
7
  * @property {boolean} [traficLimit] - Some methods use multiple queries to make it easier to work with the API. Set it to `true` to save traffic and decide for yourself what data you need: the SDK then skips its follow-up requests (full pages behind quick search results, products of page blocks), and some results change shape — e.g. `searchPage` returns short `{ id, title }` cards. Default: false.
8
8
  * @property {boolean} [rawData] - Set to true to keep an attribute's nested `additionalFields` as the
9
9
  * array the API sends, instead of the marker-keyed map the SDK builds by default. It turns off only that
10
10
  * transformation — locale unwrapping, sorting by `position`, single-file unwrapping and number casting
11
11
  * still apply. `getAdditionalFields` returns the same marker map in either mode.
12
- * @property {object} [validation] - Validation settings for API responses.
13
- * @property {boolean} [auth] - An object with authorization settings.
12
+ * @property {object} [validation] - Validation of API responses against the SDK's Zod schemas. Off by default; Zod is loaded only when it is on.
13
+ * @property {boolean} [validation.enabled] - Turns validation on. Default: false. `strictMode` and `logErrors` take effect only together with it.
14
+ * @property {boolean} [validation.strictMode] - With validation enabled, a response that does not match its schema is returned as an `IError` with `statusCode: 422` instead of the data. Default: false (mismatches are only logged). The data itself is never altered by validation.
15
+ * @property {boolean} [validation.logErrors] - With validation enabled, logs schema mismatches to the console. Default: true.
16
+ * @property {object} [auth] - An object with authorization settings.
14
17
  * @property {boolean} [auth.customAuth] - Set this flag to true if you want to configure the authorization process yourself. Set the flag to false, or do not pass it at all to have automatic authorization and token renewal.
15
- * @property {boolean} [auth.refreshToken] - Transfer the refresh token here, for example from the local storage, to resume the user's session. Otherwise, the user will need to log in every time a new session is created.
16
- * @property {boolean} [auth.providerMarker] - The marker of the provider, for example, email, google, facebook, etc. Default 'email';
17
- * @property {boolean} [auth.saveFunction] - If you want to store the token between sessions, for example in local storage, create a custom function that takes refreshToken as a parameter and executes the necessary instructions. This function will be called every time the tokens are updated.
18
+ * @property {string | null} [auth.refreshToken] - Transfer the refresh token here, for example from the local storage, to resume the user's session. Otherwise, the user will need to log in every time a new session is created. The API binds a refresh token to the device fingerprint sent in `x-device-metadata`: on the server (Node.js, SSR) every `defineOneEntry` call gets a new random fingerprint, so store `getDeviceMetadata()` next to the refresh token and pass it back as `deviceMetadata`, or the refresh is rejected with `400 Provided token is incorrect`.
19
+ * @property {string} [auth.providerMarker] - The marker of the provider used to refresh a restored session, for example, email, google, facebook, etc. Default 'email'. After `AuthProvider.auth`/`oauth`/`refresh` the marker of that call is used.
20
+ * @property {function(string): void} [auth.saveFunction] - If you want to store the token between sessions, for example in local storage, create a custom function that takes refreshToken as a parameter and executes the necessary instructions. This function will be called every time the tokens are updated.
18
21
  * @property {object} [errors] - Error handling settings.
22
+ * @property {boolean} [errors.isShell] - `true` (default): a failed request resolves to an `IError` object instead of throwing. `false`: the `IError` is thrown (a request that got no answer throws an `IError` with `statusCode: 0` and the original error in `cause`).
23
+ * @property {object} [errors.customErrors] - Handlers called with the `IError` of a failed request, keyed by HTTP status. Supported codes: 400, 401, 403, 404, 429, 500, 502, 503, 504. A handler may be async (it is awaited); an exception it throws (e.g. Next.js `redirect()`/`notFound()`) reaches the caller.
19
24
  * @example
20
25
  * ```ts
21
26
  * const saveToken = (token) => {
@@ -46,7 +51,7 @@
46
51
  * ```
47
52
  */
48
53
  interface IConfig {
49
- token?: string;
54
+ token: string;
50
55
  guestId?: string;
51
56
  deviceMetadata?: string;
52
57
  langCode?: string;
@@ -59,22 +64,22 @@ interface IConfig {
59
64
  };
60
65
  auth?: {
61
66
  customAuth?: boolean;
62
- refreshToken?: string;
67
+ refreshToken?: string | null;
63
68
  providerMarker?: string;
64
69
  saveFunction?: (refreshToken: string) => void;
65
70
  };
66
71
  errors?: {
67
72
  isShell?: boolean;
68
73
  customErrors?: {
69
- 400?: (data?: IError) => unknown;
70
- 401?: (data?: IError) => unknown;
71
- 403?: (data?: IError) => unknown;
72
- 404?: (data?: IError) => unknown;
73
- 429?: (data?: IError) => unknown;
74
- 500?: (data?: IError) => unknown;
75
- 502?: (data?: IError) => unknown;
76
- 503?: (data?: IError) => unknown;
77
- 504?: (data?: IError) => unknown;
74
+ 400?: (data: IError) => unknown;
75
+ 401?: (data: IError) => unknown;
76
+ 403?: (data: IError) => unknown;
77
+ 404?: (data: IError) => unknown;
78
+ 429?: (data: IError) => unknown;
79
+ 500?: (data: IError) => unknown;
80
+ 502?: (data: IError) => unknown;
81
+ 503?: (data: IError) => unknown;
82
+ 504?: (data: IError) => unknown;
78
83
  };
79
84
  };
80
85
  }
@@ -399,7 +404,7 @@ interface IRating {
399
404
  /**
400
405
  * @interface IError
401
406
  * @property {string} message - Error message.
402
- * @property {unknown} pageData - Page data.
407
+ * @property {unknown} [pageData] - Page data; `null` on most errors. Absent on the errors of the subscriptions module and of `/files/search` (CMS-1177).
403
408
  * @property {number} statusCode - Status code.
404
409
  * @property {string} timestamp - Timestamp.
405
410
  * @property {string} [localizeMessage] - Human-readable localized error message; populated by the SDK when response validation fails. Optional.
@@ -408,7 +413,7 @@ interface IRating {
408
413
  */
409
414
  interface IError {
410
415
  message: string;
411
- pageData: unknown;
416
+ pageData?: unknown;
412
417
  statusCode: number;
413
418
  timestamp: string;
414
419
  localizeMessage?: string;
@@ -17,7 +17,7 @@ export declare const ErrorSchema: z.ZodObject<{
17
17
  export declare const LocalizeInfoSchema: z.ZodObject<{
18
18
  title: z.ZodString;
19
19
  content: z.ZodOptional<z.ZodString>;
20
- menuTitle: z.ZodOptional<z.ZodString>;
20
+ menuTitle: z.ZodOptional<z.ZodNullable<z.ZodString>>;
21
21
  }, z.core.$strip>;
22
22
  /**
23
23
  * Attribute schema
@@ -32,7 +32,7 @@ export declare const AttributeSchema: z.ZodObject<{
32
32
  localizeInfos: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
33
33
  title: z.ZodString;
34
34
  content: z.ZodOptional<z.ZodString>;
35
- menuTitle: z.ZodOptional<z.ZodString>;
35
+ menuTitle: z.ZodOptional<z.ZodNullable<z.ZodString>>;
36
36
  }, z.core.$strip>>>;
37
37
  value: z.ZodOptional<z.ZodAny>;
38
38
  }, z.core.$strip>;
@@ -125,6 +125,6 @@ export declare function validateResponse<T>(schema: z.ZodSchema<T>, data: unknow
125
125
  * @param {z.ZodSchema<T>} schema - Zod schema to validate against
126
126
  * @param {unknown} data - Data to validate
127
127
  * @param {boolean} logErrors - Whether to log errors
128
- * @returns {T} Validated data or original data if validation fails in non-strict mode
128
+ * @returns {T} The original data, whether or not it passed validation
129
129
  */
130
130
  export declare function validateResponseSafe<T>(schema: z.ZodSchema<T>, data: unknown, logErrors?: boolean): T;
@@ -18,7 +18,8 @@ export const ErrorSchema = z.object({
18
18
  export const LocalizeInfoSchema = z.object({
19
19
  title: z.string(),
20
20
  content: z.string().optional(),
21
- menuTitle: z.string().optional(),
21
+ // `string | null` as in ILocalizeInfo
22
+ menuTitle: z.string().nullable().optional(),
22
23
  });
23
24
  /**
24
25
  * Attribute schema
@@ -205,13 +206,11 @@ export function validateResponse(schema, data, options) {
205
206
  * @param {z.ZodSchema<T>} schema - Zod schema to validate against
206
207
  * @param {unknown} data - Data to validate
207
208
  * @param {boolean} logErrors - Whether to log errors
208
- * @returns {T} Validated data or original data if validation fails in non-strict mode
209
+ * @returns {T} The original data, whether or not it passed validation
209
210
  */
210
211
  export function validateResponseSafe(schema, data, logErrors = false) {
211
- const result = validateResponse(schema, data, { logErrors });
212
- if (result.success) {
213
- return result.data;
214
- }
215
- // Return original data if validation fails in non-strict mode
212
+ validateResponse(schema, data, { logErrors });
213
+ // Always return the original data: Zod objects strip keys the schema does
214
+ // not describe, and the result must not depend on whether validation is on
216
215
  return data;
217
216
  }
@@ -21,7 +21,7 @@ export default class BlocksApi extends AsyncModules implements IBlocks {
21
21
  /**
22
22
  * Get blocks by parameters.
23
23
  * @handleName getBlocks
24
- * @param {BlockType} [type] - Optional block type to filter by. Available values: "product" | "error_page" | "catalog_page" | "product_preview" | "similar_products_block" | "product_block" | "frequently_ordered_block" | "trending_block" | "recently_viewed_block" | "repeat_purchase_block" | "slider_block" | "personal_recommendations_block" | "cart_complement_block" | "cart_similar_block" | "wishlist_similar_block" | "form" | "common_page" | "common_block" | "order" | "service" | "external_page" | "discount" (see BlockType). When omitted, blocks of all types are returned. Example: 'product'.
24
+ * @param {BlockType} [type] - Optional block type to filter by. Available values: "product" | "error_page" | "catalog_page" | "product_preview" | "similar_products_block" | "product_block" | "frequently_ordered_block" | "trending_block" | "recently_viewed_block" | "repeat_purchase_block" | "slider_block" | "personal_recommendations_block" | "cart_complement_block" | "cart_similar_block" | "wishlist_similar_block" | "form" | "common_page" | "common_block" | "order" | "service" | "external_page" | "discount" (see BlockType). When omitted, blocks of all types are returned. A type no block has (e.g. "product", which is a product type, not a block type) gives an empty list, not an error. Example: 'product_block'.
25
25
  * @param {string} [langCode] - Language code. Default: "en_US".
26
26
  * @param {number} [offset] - Number of records to skip. Default: 0.
27
27
  * @param {number} [limit] - Maximum number of records to return. Default: 30.
@@ -44,21 +44,26 @@ export default class BlocksApi extends AsyncModules implements IBlocks {
44
44
  */
45
45
  getBlockByMarker(marker: string, langCode?: string, offset?: number, limit?: number): Promise<IBlockEntity | IError>;
46
46
  /**
47
- * Enrich a single block in place.
48
- *
49
- * Lifts product display settings from `customSettings.productConfig` to
50
- * numeric top-level fields, strips internal-only fields, and — when
51
- * `loadProducts` is true — fetches the related products for
52
- * `similar_products_block` / `product_block` blocks. Shared by `getBlocks`
53
- * (array) and `getBlockByMarker` (single block). Mutates `block` in place.
54
- * @param {any} block - Normalized block to enrich (mutated in place).
55
- * @param {string} langCode - Language code passed to product sub-requests.
56
- * @param {number} offset - Pagination offset for product sub-requests.
57
- * @param {number} limit - Pagination limit for product sub-requests.
58
- * @param {boolean} loadProducts - Whether to fetch related products.
59
- * @returns {Promise<void>} Resolves when enrichment (incl. sub-requests) is done.
47
+ * Lifts the product display settings of a block to top-level fields and drops internal ones.
48
+ * @param {any} block - A block as the API sent it.
49
+ * @description `customSettings.productConfig` holds `countElementsPerRow` and `quantity`
50
+ * as strings; they become numbers on the block. `customSettings`, `attributeSetIdentifier`
51
+ * and `productPageUrls` are internal and removed — in traffic-saving mode as well, which
52
+ * used to return them as they came; the set marker was misspelt (`attributesSetIdentifier`)
53
+ * and stayed in every block.
60
54
  */
61
- private _enrichBlock;
55
+ private _liftBlockSettings;
56
+ /**
57
+ * Attaches the products of a product or similar-products block.
58
+ * @param {any} block - A normalized block.
59
+ * @param {string} langCode - Language of the products.
60
+ * @param {number} [offset] - Products to skip.
61
+ * @param {number} [limit] - Products to return.
62
+ * @description A failed sub-request leaves an empty value of the declared type —
63
+ * `{ items: [], total: 0 }` for `similarProducts`, `[]` for `products` — instead of
64
+ * the error object or an array where a container is declared.
65
+ */
66
+ private _loadBlockProducts;
62
67
  /**
63
68
  * Get similar products by block marker.
64
69
  * @handleName getSimilarProducts
@@ -71,7 +76,6 @@ export default class BlocksApi extends AsyncModules implements IBlocks {
71
76
  * @param {number} [productId] - Optional product id to find similar products for.
72
77
  * @returns {Promise<IProductsResponse | IError>} Returns the total count and an array of product items in object by specified block marker.
73
78
  * @throws {IError} When isShell=false and an error occurs during the fetch
74
- * @see {@link https://js-sdk.oneentry.cloud/docs/blocks/getSimilarProducts getSimilarProducts} documentation.
75
79
  */
76
80
  private getSimilarProducts;
77
81
  /**
@@ -85,7 +89,6 @@ export default class BlocksApi extends AsyncModules implements IBlocks {
85
89
  * @see {@link https://js-sdk.oneentry.cloud/docs/blocks/#Fixing-the-price-signPrice Fixing the price} documentation.
86
90
  * @returns {Promise<IProductsEntity[] | IError>} Return array of BlocksEntity object.
87
91
  * @throws {IError} When isShell=false and an error occurs during the fetch
88
- * @see {@link https://js-sdk.oneentry.cloud/docs/blocks/getProductsByBlockMarker getProductsByBlockMarker} documentation.
89
92
  */
90
93
  private getProductsByBlockMarker;
91
94
  /**