idosell 0.4.47 → 0.4.49

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.
package/changelog.md CHANGED
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.4.49] - 2026-07-02
9
+ ### Fixed
10
+ - Fixed looping / pagination errors
11
+
12
+ ### Added
13
+ - Added utils.getPaginnation and utils.hasNext function for pagination
14
+ - Added infinite loop detection
15
+ - Updated types
16
+
8
17
  ## [0.4.47] - 2026-06-24
9
18
  ### Added
10
19
  - Added optional OAuth2 authentication instead of API key authentication
package/dist/app.d.ts CHANGED
@@ -48,8 +48,9 @@ export type GatewayRequestProxyObject = {
48
48
  },
49
49
  custom?: Record<string, (..._: any) => false | Record<string, any>>,
50
50
  snakeCase?: boolean,
51
- paginationObject?: boolean,
51
+ // paginationObject?: boolean,
52
52
  next?: boolean,
53
+ prev?: Record<string,any>,
53
54
  rootparams?: string | boolean,
54
55
  arrays?: string[],
55
56
  req?: RequirementType[],
@@ -3484,10 +3484,7 @@ export interface DeleteProductsSizesRequest extends AppendableGateway<DeleteProd
3484
3484
  sizes: (sizes: Array<JSObject>) => this
3485
3485
  }
3486
3486
 
3487
- export interface GetProductsSizesRequest extends Gateway<GetProductsSizesResponse> {
3488
- /** Allows to change offset and number of records returned */
3489
- page: (pagenumber: number, pageSize?: number) => this;
3490
- }
3487
+ export interface GetProductsSizesRequest extends Gateway<GetProductsSizesResponse> {}
3491
3488
 
3492
3489
  export interface PutProductsSizesRequest extends AppendableGateway<PutProductsSizesRequest, PutProductsSizesResponse, RequestParams.PutProductsSizesParams> {
3493
3490
  /** Edition mode */
@@ -3946,7 +3943,7 @@ export interface GetResponsibilityEntitiesRequest extends PagableGateway<GetResp
3946
3943
  /** List of codes */
3947
3944
  code: (value: string|string[]) => this;
3948
3945
  /** Type of entity */
3949
- type: (value: string) => this;
3946
+ type: (value: "producer" | "person") => this;
3950
3947
  /** Page with results number. Numeration starts from 0 */
3951
3948
  resultsPage: (value: number|string) => this;
3952
3949
  /** Number of results on page. Value from 1 to 100 */
@@ -1,8 +1,5 @@
1
1
  import { paramsProxy } from "../params.js";
2
2
  export default (object) => {
3
3
  object.gate = { method: 'get', node: '/products/sizes' };
4
- object.custom = {
5
- page: (page = 0, limit = null) => ({ "result::page": page, "result::pageNumber": limit ?? 100 })
6
- };
7
4
  return new Proxy(object, paramsProxy);
8
5
  };
@@ -9,6 +9,5 @@ export default (object) => {
9
9
  shops: nest("shops", "filter", {}, true),
10
10
  archivedDate: nest("archivedDate", "filter", {}, false)
11
11
  };
12
- object.paginationObject = true;
13
12
  return new Proxy(object, paramsProxy);
14
13
  };
@@ -10,6 +10,5 @@ export default (object) => {
10
10
  types: nest("types", "filter", {}, true),
11
11
  promotionIds: nest("promotionIds", "filter", {}, true)
12
12
  };
13
- object.paginationObject = true;
14
13
  return new Proxy(object, paramsProxy);
15
14
  };
@@ -7,7 +7,6 @@ export default (object) => {
7
7
  page: paginationObject,
8
8
  promotionId: nest("promotionId", "filter", {}, false)
9
9
  };
10
- object.paginationObject = true;
11
10
  object.req = ["filter"];
12
11
  return new Proxy(object, paramsProxy);
13
12
  };
@@ -16,6 +16,5 @@ export default (object) => {
16
16
  dateRange: nest("dateRange", "filter", {}, false),
17
17
  productsNotInPromotion: nest("productsNotInPromotion", "filter", {}, true)
18
18
  };
19
- object.paginationObject = true;
20
19
  return new Proxy(object, paramsProxy);
21
20
  };
@@ -7300,4 +7300,11 @@ export type DeletePackagesParams = {
7300
7300
  packageId: number;
7301
7301
  };
7302
7302
 
7303
+ export type GetEntriesParams = {
7304
+ /** @description Entry ID */
7305
+ entryId: number;
7306
+ /** @description Language ID */
7307
+ langId: LangId;
7308
+ };
7309
+
7303
7310
  export { };
package/dist/request.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import axios from "axios";
2
- import { page } from "./helpers.js";
3
2
  import { IdosellFaultStringError } from "./errors.js";
3
+ import utils from "./utils.js";
4
4
  const DECODE_TABLE = [
5
5
  ['Å\x82', "ł"],
6
6
  ['Ä\x99', 'ę']
@@ -40,6 +40,26 @@ const catchIdosellError = (err) => {
40
40
  }
41
41
  throw new Error(`${err.response.status}: ${message}`, { cause: err.response.status });
42
42
  };
43
+ function deepEqual(obj1, obj2) {
44
+ if (obj1 === obj2)
45
+ return true;
46
+ if (obj1 && obj2 && typeof obj1 === 'object' && typeof obj2 === 'object') {
47
+ const keys1 = Object.keys(obj1);
48
+ const keys2 = Object.keys(obj2);
49
+ if (keys1.length !== keys2.length)
50
+ return false;
51
+ for (let i = 0; i < keys1.length; i++) {
52
+ const key = keys1[i];
53
+ // If B doesn't have the key, or the values aren't deeply equal, fail early
54
+ if (!Object.prototype.hasOwnProperty.call(obj2, key) || !deepEqual(obj1[key], obj2[key])) {
55
+ return false;
56
+ }
57
+ }
58
+ return true;
59
+ }
60
+ // Handles cases where one is an object and the other is a primitive
61
+ return false;
62
+ }
43
63
  const checkNext = (request, response, logPage) => {
44
64
  if (logPage === true)
45
65
  logPage = DEFAULT_LOG_FUNCTION;
@@ -52,29 +72,24 @@ const checkNext = (request, response, logPage) => {
52
72
  };
53
73
  throw new IdosellFaultStringError(response.errors.faultString, faultStructure);
54
74
  }
55
- function handlePagination(currentPage, totalPages, limit, request) {
56
- const nextPage = currentPage + 1;
57
- request.next = nextPage < totalPages;
75
+ const pagination = utils.getPagination(response);
76
+ if (pagination) {
77
+ const nextPage = pagination.currentPage + 1;
78
+ request.next = nextPage < pagination.totalPages;
79
+ if (request.prev) {
80
+ const deq = deepEqual(request.prev, request.params);
81
+ if (deq)
82
+ throw new Error("Infinite loop detected - reevaluate your request");
83
+ }
84
+ request.prev = { ...request.params };
58
85
  if (typeof logPage === 'function') {
59
- logPage('Page: ' + currentPage + ' / ' + totalPages);
86
+ logPage('Page: ' + pagination.currentPage + ' / ' + pagination.totalPages);
60
87
  }
61
88
  if (request.custom && request.custom.page) {
62
- const pageObj = request.custom.page(nextPage, limit);
89
+ const pageObj = request.custom.page(nextPage, pagination.limit);
63
90
  Object.assign(request.params, pageObj);
64
91
  }
65
92
  }
66
- if (response.resultsNumberPage) {
67
- handlePagination(response.resultsPage, response.resultsNumberPage, response.resultsLimit, request);
68
- }
69
- else if (response.results_number_page) {
70
- handlePagination(response.results_page, response.results_number_page, response.results_limit, request);
71
- }
72
- else if (response.pagination) {
73
- handlePagination(response.pagination.resultsPage, response.pagination.resultsNumberPage, response.pagination.resultsLimit, request);
74
- }
75
- else if (response.data?.pagination) {
76
- handlePagination(response.data.pagination.resultsPage, response.data.pagination.resultsNumberPage, response.data.pagination.resultsLimit, request);
77
- }
78
93
  return response;
79
94
  };
80
95
  export const queryfy = (params) => {
@@ -175,9 +190,11 @@ export const sendRequest = async (request, options = {}) => {
175
190
  let token = request.auth.apiKey.token;
176
191
  if (!token) {
177
192
  const base64 = Buffer.from(`${login}:${password}`).toString('base64');
178
- const response = await axios.post(`${request.auth.url}/api/authorize/1/authorize/accessToken`, { scope: scope ?? ['admin'] }, { headers: {
193
+ const response = await axios.post(`${request.auth.url}/api/authorize/1/authorize/accessToken`, { scope: scope ?? ['admin'] }, {
194
+ headers: {
179
195
  authorization: `Basic ${base64}`,
180
- } });
196
+ }
197
+ });
181
198
  if (response.data.access_token) {
182
199
  token = response.data.access_token;
183
200
  request.auth.apiKey.token = response.data.access_token;
@@ -222,17 +239,17 @@ export const sendRequest = async (request, options = {}) => {
222
239
  }
223
240
  };
224
241
  export const countResults = async (request, options) => {
225
- const pageData = page(0, 1, request.snakeCase);
242
+ if (!request.custom?.page)
243
+ throw new Error("This request is not countable");
244
+ const pageData = request.custom.page(0, 1);
226
245
  Object.assign(request.params, pageData);
227
246
  const response = await sendRequest(request, options);
228
247
  if (!response)
229
248
  return 0;
230
- if (request.snakeCase)
231
- return parseInt(response.results_number_all);
232
- else if (request.paginationObject)
233
- return response.pagination.resultsNumberAll;
234
- else
235
- return response.resultsNumberAll;
249
+ const pagination = utils.getPagination(response);
250
+ if (pagination)
251
+ return pagination.totalPages;
252
+ return 0;
236
253
  };
237
254
  export const getParams = (request) => JSON.parse(JSON.stringify(request.params));
238
255
  export const checkParams = (request) => {
@@ -7201,39 +7201,39 @@ export type GetSystemShopsDataResponse = {
7201
7201
  /** @description Shop ID */
7202
7202
  shop_id: number;
7203
7203
  /** @description Determines whether inheritance is active. */
7204
- shop_inherit_on: "y" | "n";
7204
+ shop_inherit_on: "y" | "n" | null;
7205
7205
  /** @description Shop ID from which the settings are inherited. */
7206
- shop_inherit_from: number;
7206
+ shop_inherit_from?: number;
7207
7207
  /** @description Determines whether inheritance in enabled for offers. */
7208
- shop_inherit_offer: "y" | "n";
7208
+ shop_inherit_offer?: "y" | "n";
7209
7209
  /** @description Determines whether inheritance in enabled for navigation descriptions. */
7210
- shop_inherit_navdescs: "y" | "n";
7210
+ shop_inherit_navdescs?: "y" | "n";
7211
7211
  /** @description Determines whether inheritance in enabled for configuration. */
7212
- shop_inherit_config: "y" | "n";
7212
+ shop_inherit_config?: "y" | "n";
7213
7213
  /** @description Determines whether inheritance in enabled for country and locale settings. */
7214
- shop_inherit_country: "y" | "n";
7214
+ shop_inherit_country?: "y" | "n";
7215
7215
  /** @description Determines whether inheritance in enabled for banners. */
7216
- shop_inherit_banners: "y" | "n";
7216
+ shop_inherit_banners?: "y" | "n";
7217
7217
  /** @description Determines whether inheritance in enabled for HTML and JS snippets. */
7218
- shop_inherit_snippets: "y" | "n";
7218
+ shop_inherit_snippets?: "y" | "n";
7219
7219
  /** @description Determines whether inheritance in enabled for toplayer settings. */
7220
- shop_inherit_toplayers: "y" | "n";
7220
+ shop_inherit_toplayers?: "y" | "n";
7221
7221
  /** @description Determines whether inheritance in enabled for site masks. */
7222
- shop_inherit_masks: "y" | "n";
7222
+ shop_inherit_masks?: "y" | "n";
7223
7223
  /** @description Determines whether inheritance in enabled for CMS pages. */
7224
- shop_inherit_cms: "y" | "n";
7224
+ shop_inherit_cms?: "y" | "n";
7225
7225
  /** @description Determines whether inheritance in enabled for CPA programs. */
7226
- shop_inherit_cpa: "y" | "n";
7226
+ shop_inherit_cpa?: "y" | "n";
7227
7227
  /** @description Determines whether inheritance in enabled for affiliate programs. */
7228
- shop_inherit_affiliate: "y" | "n";
7228
+ shop_inherit_affiliate?: "y" | "n";
7229
7229
  /** @description Determines whether inheritance in enabled for rebate programs. */
7230
- shop_inherit_rebates: "y" | "n";
7230
+ shop_inherit_rebates?: "y" | "n";
7231
7231
  /** @description Determines whether inheritance in enabled for prices. */
7232
- shop_inherit_prices: "y" | "n";
7232
+ shop_inherit_prices?: "y" | "n";
7233
7233
  /** @description Determines whether inheritance in enabled for sale and shipment documents. */
7234
- shop_inherit_invoices: "y" | "n";
7234
+ shop_inherit_invoices?: "y" | "n";
7235
7235
  /** @description Determines whether inheritance in enabled for process automation. */
7236
- shop_inherit_automats: "y" | "n";
7236
+ shop_inherit_automats?: "y" | "n";
7237
7237
  }[];
7238
7238
  };
7239
7239
 
package/dist/utils.d.ts CHANGED
@@ -21,6 +21,13 @@ type MappedParameter = {
21
21
  values: MappedParameterValue[];
22
22
  };
23
23
  type MapProductParametersFunction = (_product: IdosellProduct, _langId?: string) => MappedParameter[];
24
+ interface PaginationInfo {
25
+ currentPage: number;
26
+ totalPages: number;
27
+ totalRecords: number;
28
+ limit: number;
29
+ }
30
+ type GetPaginationFunction = (_response: any) => PaginationInfo | null;
24
31
  declare const _default: {
25
32
  /** @description The method allows you to build an IAI code from the product ID and size ID. */
26
33
  getIaiCode: GetIaICodeFunction;
@@ -42,5 +49,9 @@ declare const _default: {
42
49
  removeRmaAttachments: (rmaResponse: GetRmaResponse) => GetRmaResponse;
43
50
  /** @description Maps product parameters to a simplified structure for a given language. Skips parameters with no values. */
44
51
  mapProductParameters: MapProductParametersFunction;
52
+ /** @description ormalizes pagination data from inconsistent API response shapes (top-level vs. nested, camelCase vs. snake_case) into a single type */
53
+ getPagination: GetPaginationFunction;
54
+ /** @description Check if request has next page based on raw response */
55
+ hasNext: (response: any) => boolean | null;
45
56
  };
46
57
  export default _default;
package/dist/utils.js CHANGED
@@ -286,6 +286,42 @@ const mapProductParameters = (product, langId = 'pol') => {
286
286
  return acc;
287
287
  }, []);
288
288
  };
289
+ const getPagination = (response) => {
290
+ // 1. Check snake_case on the top-level response before checking candidates
291
+ if (response?.results_number_page !== undefined) {
292
+ return {
293
+ currentPage: response.results_page,
294
+ totalPages: response.results_number_page,
295
+ totalRecords: response.results_number_all,
296
+ limit: response.results_limit,
297
+ };
298
+ }
299
+ // 2. Define candidates including response.results
300
+ const candidates = [
301
+ response,
302
+ response?.pagination,
303
+ response?.data?.pagination,
304
+ response?.results,
305
+ ];
306
+ // 3. Loop through candidates for camelCase options
307
+ for (const c of candidates) {
308
+ if (!c)
309
+ continue;
310
+ if (c.resultsNumberPage !== undefined) {
311
+ return {
312
+ currentPage: c.resultsPage,
313
+ totalPages: c.resultsNumberPage,
314
+ totalRecords: c.resultsNumberAll,
315
+ limit: c.resultsLimit,
316
+ };
317
+ }
318
+ }
319
+ return null;
320
+ };
321
+ const hasNext = (response) => {
322
+ const pagination = getPagination(response);
323
+ return pagination && (pagination.currentPage + 1 < pagination.totalPages);
324
+ };
289
325
  export default {
290
326
  /** @description The method allows you to build an IAI code from the product ID and size ID. */
291
327
  getIaiCode,
@@ -307,4 +343,8 @@ export default {
307
343
  removeRmaAttachments,
308
344
  /** @description Maps product parameters to a simplified structure for a given language. Skips parameters with no values. */
309
345
  mapProductParameters,
346
+ /** @description ormalizes pagination data from inconsistent API response shapes (top-level vs. nested, camelCase vs. snake_case) into a single type */
347
+ getPagination,
348
+ /** @description Check if request has next page based on raw response */
349
+ hasNext
310
350
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "idosell",
3
- "version": "0.4.47",
3
+ "version": "0.4.49",
4
4
  "description": "Idosell 3 REST connector",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/gateways.d.ts",