@bitrix24/b24jssdk 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/README-AI.md +3 -3
  2. package/dist/esm/_virtual/_commonjsHelpers.mjs +1 -1
  3. package/dist/esm/_virtual/protobuf.mjs +1 -1
  4. package/dist/esm/_virtual/protobuf2.mjs +1 -1
  5. package/dist/esm/core/abstract-b24.mjs +1 -1
  6. package/dist/esm/core/actions/abstract-action.mjs +1 -1
  7. package/dist/esm/core/actions/abstract-batch.mjs +1 -1
  8. package/dist/esm/core/actions/manager.mjs +1 -1
  9. package/dist/esm/core/actions/v2/batch-by-chunk.mjs +1 -1
  10. package/dist/esm/core/actions/v2/batch.mjs +1 -1
  11. package/dist/esm/core/actions/v2/call-list.mjs +17 -10
  12. package/dist/esm/core/actions/v2/call-list.mjs.map +1 -1
  13. package/dist/esm/core/actions/v2/call.mjs +1 -1
  14. package/dist/esm/core/actions/v2/fetch-list.mjs +17 -10
  15. package/dist/esm/core/actions/v2/fetch-list.mjs.map +1 -1
  16. package/dist/esm/core/actions/v2/manager-v2.mjs +6 -6
  17. package/dist/esm/core/actions/v2/manager-v2.mjs.map +1 -1
  18. package/dist/esm/core/actions/v3/batch-by-chunk.mjs +1 -1
  19. package/dist/esm/core/actions/v3/batch.mjs +1 -1
  20. package/dist/esm/core/actions/v3/call-list.mjs +16 -9
  21. package/dist/esm/core/actions/v3/call-list.mjs.map +1 -1
  22. package/dist/esm/core/actions/v3/call.mjs +1 -1
  23. package/dist/esm/core/actions/v3/fetch-list.mjs +16 -9
  24. package/dist/esm/core/actions/v3/fetch-list.mjs.map +1 -1
  25. package/dist/esm/core/actions/v3/manager-v3.mjs +6 -6
  26. package/dist/esm/core/actions/v3/manager-v3.mjs.map +1 -1
  27. package/dist/esm/core/http/abstract-http.mjs +30 -6
  28. package/dist/esm/core/http/abstract-http.mjs.map +1 -1
  29. package/dist/esm/core/http/ajax-error.mjs +1 -1
  30. package/dist/esm/core/http/ajax-result.mjs +1 -1
  31. package/dist/esm/core/http/limiters/adaptive-delayer.mjs +1 -1
  32. package/dist/esm/core/http/limiters/manager.mjs +2 -1
  33. package/dist/esm/core/http/limiters/manager.mjs.map +1 -1
  34. package/dist/esm/core/http/limiters/operating-limiter.mjs +1 -1
  35. package/dist/esm/core/http/limiters/params-factory.mjs +1 -1
  36. package/dist/esm/core/http/limiters/rate-limiter.mjs +1 -1
  37. package/dist/esm/core/http/redact.mjs +1 -1
  38. package/dist/esm/core/http/v2.mjs +2 -2
  39. package/dist/esm/core/http/v3.mjs +2 -2
  40. package/dist/esm/core/interaction/batch/abstract-interaction-batch.mjs +1 -1
  41. package/dist/esm/core/interaction/batch/parse-row.mjs +1 -1
  42. package/dist/esm/core/interaction/batch/processing/interface-strategy.mjs +1 -1
  43. package/dist/esm/core/interaction/batch/processing/v2/abstract-processing.mjs +1 -1
  44. package/dist/esm/core/interaction/batch/processing/v2/as-array.mjs +1 -1
  45. package/dist/esm/core/interaction/batch/processing/v2/as-object.mjs +1 -1
  46. package/dist/esm/core/interaction/batch/processing/v3/abstract-processing.mjs +1 -1
  47. package/dist/esm/core/interaction/batch/processing/v3/as-array.mjs +1 -1
  48. package/dist/esm/core/interaction/batch/processing/v3/as-object.mjs +1 -1
  49. package/dist/esm/core/interaction/batch/v2.mjs +1 -1
  50. package/dist/esm/core/interaction/batch/v3.mjs +1 -1
  51. package/dist/esm/core/language/list.mjs +1 -1
  52. package/dist/esm/core/request-id-generator.mjs +1 -1
  53. package/dist/esm/core/result.mjs +28 -1
  54. package/dist/esm/core/result.mjs.map +1 -1
  55. package/dist/esm/core/sdk-error.mjs +1 -1
  56. package/dist/esm/core/tools/abstract-tool.mjs +1 -1
  57. package/dist/esm/core/tools/healthcheck.mjs +1 -1
  58. package/dist/esm/core/tools/manager.mjs +3 -3
  59. package/dist/esm/core/tools/manager.mjs.map +1 -1
  60. package/dist/esm/core/tools/ping.mjs +1 -1
  61. package/dist/esm/core/version-manager.mjs +89 -12
  62. package/dist/esm/core/version-manager.mjs.map +1 -1
  63. package/dist/esm/frame/auth.mjs +1 -1
  64. package/dist/esm/frame/b24.mjs +1 -1
  65. package/dist/esm/frame/dialog.mjs +1 -1
  66. package/dist/esm/frame/frame.mjs +1 -1
  67. package/dist/esm/frame/message/commands.mjs +1 -1
  68. package/dist/esm/frame/message/controller.mjs +1 -1
  69. package/dist/esm/frame/options.mjs +1 -1
  70. package/dist/esm/frame/parent.mjs +6 -2
  71. package/dist/esm/frame/parent.mjs.map +1 -1
  72. package/dist/esm/frame/placement.mjs +1 -1
  73. package/dist/esm/frame/slider.mjs +5 -1
  74. package/dist/esm/frame/slider.mjs.map +1 -1
  75. package/dist/esm/helper/abstract-helper.mjs +1 -1
  76. package/dist/esm/helper/app-manager.mjs +1 -1
  77. package/dist/esm/helper/currency-manager.mjs +1 -1
  78. package/dist/esm/helper/helper-manager.mjs +1 -1
  79. package/dist/esm/helper/license-manager.mjs +1 -1
  80. package/dist/esm/helper/options-manager.mjs +1 -1
  81. package/dist/esm/helper/payment-manager.mjs +1 -1
  82. package/dist/esm/helper/profile-manager.mjs +1 -1
  83. package/dist/esm/helper/use-b24-helper.mjs +1 -1
  84. package/dist/esm/hook/auth.mjs +1 -1
  85. package/dist/esm/hook/b24.mjs +1 -1
  86. package/dist/esm/index.d.mts +95 -16
  87. package/dist/esm/index.d.ts +95 -16
  88. package/dist/esm/index.mjs +1 -1
  89. package/dist/esm/loader-b24frame.mjs +1 -1
  90. package/dist/esm/logger/abstract-logger.mjs +1 -1
  91. package/dist/esm/logger/browser.mjs +1 -1
  92. package/dist/esm/logger/formatter/abstract-formatter.mjs +1 -1
  93. package/dist/esm/logger/formatter/json-formatter.mjs +1 -1
  94. package/dist/esm/logger/formatter/line-formatter.mjs +1 -1
  95. package/dist/esm/logger/formatter/telegram-formatter.mjs +1 -1
  96. package/dist/esm/logger/handler/abstract-handler.mjs +1 -1
  97. package/dist/esm/logger/handler/consola-adapter.mjs +1 -1
  98. package/dist/esm/logger/handler/console-handler.mjs +1 -1
  99. package/dist/esm/logger/handler/console-v2-handler.mjs +1 -1
  100. package/dist/esm/logger/handler/memory-handler.mjs +1 -1
  101. package/dist/esm/logger/handler/stream-handler.mjs +1 -1
  102. package/dist/esm/logger/handler/telegram-handler.mjs +1 -1
  103. package/dist/esm/logger/handler/winston-adapter.mjs +1 -1
  104. package/dist/esm/logger/logger-factory.mjs +1 -1
  105. package/dist/esm/logger/logger.mjs +1 -1
  106. package/dist/esm/logger/null-logger.mjs +1 -1
  107. package/dist/esm/logger/processor/memory-usage-processor.mjs +1 -1
  108. package/dist/esm/logger/processor/pid-processor.mjs +1 -1
  109. package/dist/esm/oauth/auth.mjs +1 -1
  110. package/dist/esm/oauth/b24.mjs +1 -1
  111. package/dist/esm/oauth/refresh-token-error.mjs +1 -1
  112. package/dist/esm/pullClient/abstract-connector.mjs +1 -1
  113. package/dist/esm/pullClient/channel-manager.mjs +1 -1
  114. package/dist/esm/pullClient/client.mjs +1 -1
  115. package/dist/esm/pullClient/errors.mjs +1 -1
  116. package/dist/esm/pullClient/json-rpc.mjs +1 -1
  117. package/dist/esm/pullClient/long-polling-connector.mjs +1 -1
  118. package/dist/esm/pullClient/protobuf/index.mjs +1 -1
  119. package/dist/esm/pullClient/protobuf/model.mjs +1 -1
  120. package/dist/esm/pullClient/protobuf/protobuf.mjs +1 -1
  121. package/dist/esm/pullClient/shared-config.mjs +1 -1
  122. package/dist/esm/pullClient/storage-manager.mjs +1 -1
  123. package/dist/esm/pullClient/web-socket-connector.mjs +1 -1
  124. package/dist/esm/tools/browser.mjs +1 -1
  125. package/dist/esm/tools/environment.mjs +1 -1
  126. package/dist/esm/tools/formatters/iban.mjs +1 -1
  127. package/dist/esm/tools/formatters/numbers.mjs +1 -1
  128. package/dist/esm/tools/index.mjs +1 -1
  129. package/dist/esm/tools/scroll-size.mjs +1 -1
  130. package/dist/esm/tools/text.mjs +1 -1
  131. package/dist/esm/tools/type.mjs +1 -1
  132. package/dist/esm/tools/use-formatters.mjs +1 -1
  133. package/dist/esm/tools/uuidv7.mjs +1 -1
  134. package/dist/esm/types/b24-helper.mjs +1 -1
  135. package/dist/esm/types/b24.mjs +1 -1
  136. package/dist/esm/types/bizproc/index.mjs +1 -1
  137. package/dist/esm/types/catalog/index.mjs +1 -1
  138. package/dist/esm/types/common.mjs +1 -1
  139. package/dist/esm/types/crm/entity-type.mjs +1 -1
  140. package/dist/esm/types/crm/productrow.mjs +1 -1
  141. package/dist/esm/types/logger.mjs +1 -1
  142. package/dist/esm/types/pull.mjs +1 -1
  143. package/dist/umd/index.js +231 -66
  144. package/dist/umd/index.js.map +1 -1
  145. package/dist/umd/index.min.js +24 -24
  146. package/dist/umd/index.min.js.map +1 -1
  147. package/package.json +1 -1
package/README-AI.md CHANGED
@@ -15,7 +15,7 @@
15
15
  Purpose: give AI agents a precise, code-oriented overview of the SDK to generate working Bitrix24 apps. This SDK lets you:
16
16
 
17
17
  - Call Bitrix24 REST API from apps embedded in Bitrix24 (iframe) and from backend services
18
- - Interact with Bitrix24 UI: open sliders, dialogs, resize frame, set page title, IM integrations, etc.
18
+ - Interact with Bitrix24 UI: open sliders, dialogs, resize frame, set in-app page title (`#pagetitle`, not the browser tab), IM integrations, etc.
19
19
  - Manage app/user options via the parent portal
20
20
  - Use helpers (profile/app/options/currencies/licenses/payments) and Pull client
21
21
 
@@ -264,7 +264,7 @@ Parent window and IM integrations
264
264
 
265
265
  ```ts
266
266
  await $b24.parent.fitWindow()
267
- await $b24.parent.setTitle('My Page')
267
+ await $b24.parent.setTitle('My Page') // in-page #pagetitle, not the browser tab
268
268
  await $b24.parent.scrollParentWindow(0)
269
269
  await $b24.parent.imCallTo(5, true) // video call to user 5
270
270
  await $b24.parent.imOpenMessenger('chat12') // open messenger
@@ -362,7 +362,7 @@ Core REST utilities live in AbstractB24 and Http:
362
362
  - callMethod(method, params[, start]) => `Promise<AjaxResult>`
363
363
  - callBatch(calls, isHaltOnError = true, returnAjaxResult = false) => `Promise<Result>`
364
364
  - calls can be object { key: { method, params } } or array [ [method, params], ... ]
365
- - If isHaltOnError=false, Result accumulates errors; otherwise rejects on first error
365
+ - If isHaltOnError=false, Result accumulates errors (object-form calls are keyed by request label — read via getErrorsByKey()/getErrorMessagesByKey()); otherwise rejects on first error
366
366
  - If returnAjaxResult=true, you receive AjaxResult objects per command
367
367
  - callListMethod(method, params, progress?, customKey?) => `Promise<Result>` (auto-paging)
368
368
  - fetchListMethod(method, params, idKey='ID', customKey?) => `AsyncGenerator<any[]>`
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -22,12 +22,16 @@ class CallListV2 extends AbstractAction {
22
22
  *
23
23
  * @param {ActionCallListV2} options - parameters for executing the request.
24
24
  * - `method: string` - The name of the REST API method that returns a list of data (for example: `crm.item.list`, `tasks.task.list`)
25
- * - `params?: Omit<TypeCallParams, 'start'>` - Request parameters, excluding the `start` parameter,
25
+ * - `params?: Omit<TypeCallParams, 'start' | 'order'>` - Request parameters, excluding the `start` and `order` parameters,
26
26
  * since the method is designed to obtain all data in one call.
27
27
  * Note: Use `filter`, `order`, and `select` to control the selection.
28
- * - `idKey?: string` - The name of the field containing the unique identifier of the element.
29
- * Default is 'ID' (uppercase). Alternatively, it can be 'id' (lowercase).
30
- * or another field, depending on the REST API data structure.
28
+ * - `idKey?: string` - The name of the id field as it appears in each RESPONSE item; its value
29
+ * drives the cursor. Default is 'ID' (uppercase). For methods that return a lowercase /
30
+ * camelCase id (for example `tasks.task.list` returns `id`), set `idKey: 'id'`.
31
+ * - `cursorIdKey?: string` - The field name used in the REQUEST for `order` and the `>` page
32
+ * filter. Defaults to `idKey`. Set it only when the sortable / filterable field name differs
33
+ * from the response field name — e.g. `tasks.task.list` sorts and filters by `ID` (uppercase)
34
+ * but returns `id` (lowercase): pass `idKey: 'id', cursorIdKey: 'ID'`.
31
35
  * - `customKeyForResult?: string` - A custom key indicating that the response REST API will be
32
36
  * grouped by this field.
33
37
  * Example: `items` to group a list of CRM items.
@@ -66,16 +70,17 @@ class CallListV2 extends AbstractAction {
66
70
  const batchSize = 50;
67
71
  const result = new Result();
68
72
  const idKey = options?.idKey ?? "ID";
73
+ const cursorIdKey = options?.cursorIdKey ?? idKey;
69
74
  const customKeyForResult = options?.customKeyForResult ?? null;
70
75
  const params = options?.params ?? {};
71
76
  if ("order" in params && params["order"]) {
72
- this._logger.warning("callList.make: user-provided `order` parameter is ignored because cursor-based pagination requires ordering by idKey. Use `filter` to narrow results instead.");
77
+ this._logger.warning("callList.make: user-provided `order` parameter is ignored because cursor-based pagination requires ordering by cursorIdKey. Use `filter` to narrow results instead.");
73
78
  }
74
- const moreIdKey = `>${idKey}`;
79
+ const moreIdKey = `>${cursorIdKey}`;
75
80
  const { order: _ignoredOrder, ...restParams } = params;
76
81
  const requestParams = {
77
82
  ...restParams,
78
- order: { [idKey]: "ASC" },
83
+ order: { [cursorIdKey]: "ASC" },
79
84
  filter: { ...params["filter"] || {}, [moreIdKey]: 0 },
80
85
  start: -1
81
86
  };
@@ -120,9 +125,11 @@ class CallListV2 extends AbstractAction {
120
125
  break;
121
126
  }
122
127
  const lastItem = resultData[resultData.length - 1];
123
- if (lastItem && typeof lastItem[idKey] !== "undefined") {
124
- requestParams.filter[moreIdKey] = Number.parseInt(lastItem[idKey]);
128
+ const cursorValue = lastItem ? Number.parseInt(lastItem[idKey], 10) : Number.NaN;
129
+ if (Number.isFinite(cursorValue)) {
130
+ requestParams.filter[moreIdKey] = cursorValue;
125
131
  } else {
132
+ this._logger.warning(`callList.make: pagination stops here \u2014 no numeric id could be read from the returned items via idKey "${idKey}". Make sure idKey matches the id field in the response; if the sortable field name differs from it, also set cursorIdKey (e.g. idKey: 'id', cursorIdKey: 'ID').`);
126
133
  isContinue = false;
127
134
  break;
128
135
  }
@@ -1 +1 @@
1
- {"version":3,"file":"call-list.mjs","sources":["../../../../../src/core/actions/v2/call-list.ts"],"sourcesContent":["import type { ActionOptions } from '../abstract-action'\nimport type { TypeCallParams } from '../../../types/http'\nimport type { AjaxResult } from '../../http/ajax-result'\nimport { AbstractAction } from '../abstract-action'\nimport { Result } from '../../result'\n\nexport type ActionCallListV2 = ActionOptions & {\n method: string\n params?: Omit<TypeCallParams, 'start' | 'order'>\n idKey?: string\n customKeyForResult?: string\n requestId?: string\n}\n\n/**\n * Fast data retrieval without counting the total number of records. `restApi:v2`\n *\n * @todo add docs\n */\nexport class CallListV2 extends AbstractAction {\n /**\n * Fast data retrieval without counting the total number of records.\n *\n * @template T - The type of the elements of the returned array (default is `unknown`).\n *\n * @param {ActionCallListV2} options - parameters for executing the request.\n * - `method: string` - The name of the REST API method that returns a list of data (for example: `crm.item.list`, `tasks.task.list`)\n * - `params?: Omit<TypeCallParams, 'start'>` - Request parameters, excluding the `start` parameter,\n * since the method is designed to obtain all data in one call.\n * Note: Use `filter`, `order`, and `select` to control the selection.\n * - `idKey?: string` - The name of the field containing the unique identifier of the element.\n * Default is 'ID' (uppercase). Alternatively, it can be 'id' (lowercase).\n * or another field, depending on the REST API data structure.\n * - `customKeyForResult?: string` - A custom key indicating that the response REST API will be\n * grouped by this field.\n * Example: `items` to group a list of CRM items.\n * - `requestId?: string` - Unique request identifier for tracking. Used for query deduplication and debugging.\n *\n * @returns {Promise<Result<T[]>>} A promise that resolves to the result of an REST API call.\n *\n * @example\n * import { EnumCrmEntityTypeId, Text } from '@bitrix24/b24jssdk'\n *\n * interface CrmItem { id: number, title: string }\n * const sixMonthAgo = new Date()\n * sixMonthAgo.setMonth((new Date()).getMonth() - 6)\n * sixMonthAgo.setHours(0, 0, 0)\n * const response = await b24.actions.v2.callList.make<CrmItem>({\n * method: 'crm.item.list',\n * params: {\n * entityTypeId: EnumCrmEntityTypeId.company,\n * filter: {\n * '=%title': 'A%',\n * '>=createdTime': Text.toB24Format(sixMonthAgo) // created at least 6 months ago\n * },\n * select: ['id', 'title']\n * },\n * idKey: 'id',\n * customKeyForResult: 'items',\n * requestId: 'list-123'\n * })\n * if (!response.isSuccess) {\n * throw new Error(`Problem: ${response.getErrorMessages().join('; ')}`)\n * }\n * const list = response.getData()\n * console.log(`Result: ${list?.length}`) // Number of items received\n */\n public override async make<T = unknown>(options: ActionCallListV2): Promise<Result<T[]>> {\n const batchSize = 50\n const result: Result<T[]> = new Result()\n\n const idKey = options?.idKey ?? 'ID'\n const customKeyForResult = options?.customKeyForResult ?? null\n const params = options?.params ?? {}\n\n // Warn and strip user-provided `order` — cursor pagination requires ordering by idKey only\n if ('order' in params && params['order']) {\n this._logger.warning('callList.make: user-provided `order` parameter is ignored because cursor-based pagination requires ordering by idKey. Use `filter` to narrow results instead.')\n }\n\n const moreIdKey = `>${idKey}`\n const { order: _ignoredOrder, ...restParams } = params as TypeCallParams\n const requestParams: TypeCallParams = {\n ...restParams,\n order: { [idKey]: 'ASC' },\n filter: { ...(params['filter'] || {}), [moreIdKey]: 0 },\n start: -1\n }\n\n let allItems: T[] = []\n let isContinue = true\n\n do {\n const response: AjaxResult<T> = await this._b24.actions.v2.call.make<T>({\n method: options.method,\n params: requestParams,\n requestId: options.requestId\n })\n\n if (!response.isSuccess) {\n this._logger.error('callFastListMethod', {\n method: options.method,\n requestId: options.requestId,\n messages: response.getErrorMessages()\n })\n for (const [index, error] of response.errors) {\n result.addError(error, index)\n }\n isContinue = false\n break\n }\n const responseData = response.getData()\n if (!responseData) {\n isContinue = false\n break\n }\n\n let resultData: T[] = []\n if (null === customKeyForResult) {\n resultData = responseData.result as T[]\n } else {\n resultData = (responseData.result as any)[customKeyForResult] as T[]\n }\n\n if (resultData.length === 0) {\n isContinue = false\n break\n }\n\n allItems = [...allItems, ...resultData]\n\n if (resultData.length < batchSize) {\n isContinue = false\n break\n }\n\n // Update the filter for the next iteration\n const lastItem = resultData[resultData.length - 1] as Record<string, any>\n if (\n lastItem\n && typeof lastItem[idKey] !== 'undefined'\n ) {\n requestParams.filter[moreIdKey] = Number.parseInt(lastItem[idKey])\n } else {\n isContinue = false\n break\n }\n } while (isContinue)\n\n return result.setData(allItems)\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"call-list.mjs","sources":["../../../../../src/core/actions/v2/call-list.ts"],"sourcesContent":["import type { ActionOptions } from '../abstract-action'\nimport type { TypeCallParams } from '../../../types/http'\nimport type { AjaxResult } from '../../http/ajax-result'\nimport { AbstractAction } from '../abstract-action'\nimport { Result } from '../../result'\n\nexport type ActionCallListV2 = ActionOptions & {\n method: string\n params?: Omit<TypeCallParams, 'start' | 'order'>\n idKey?: string\n cursorIdKey?: string\n customKeyForResult?: string\n requestId?: string\n}\n\n/**\n * Fast data retrieval without counting the total number of records. `restApi:v2`\n *\n * @todo add docs\n */\nexport class CallListV2 extends AbstractAction {\n /**\n * Fast data retrieval without counting the total number of records.\n *\n * @template T - The type of the elements of the returned array (default is `unknown`).\n *\n * @param {ActionCallListV2} options - parameters for executing the request.\n * - `method: string` - The name of the REST API method that returns a list of data (for example: `crm.item.list`, `tasks.task.list`)\n * - `params?: Omit<TypeCallParams, 'start' | 'order'>` - Request parameters, excluding the `start` and `order` parameters,\n * since the method is designed to obtain all data in one call.\n * Note: Use `filter`, `order`, and `select` to control the selection.\n * - `idKey?: string` - The name of the id field as it appears in each RESPONSE item; its value\n * drives the cursor. Default is 'ID' (uppercase). For methods that return a lowercase /\n * camelCase id (for example `tasks.task.list` returns `id`), set `idKey: 'id'`.\n * - `cursorIdKey?: string` - The field name used in the REQUEST for `order` and the `>` page\n * filter. Defaults to `idKey`. Set it only when the sortable / filterable field name differs\n * from the response field name — e.g. `tasks.task.list` sorts and filters by `ID` (uppercase)\n * but returns `id` (lowercase): pass `idKey: 'id', cursorIdKey: 'ID'`.\n * - `customKeyForResult?: string` - A custom key indicating that the response REST API will be\n * grouped by this field.\n * Example: `items` to group a list of CRM items.\n * - `requestId?: string` - Unique request identifier for tracking. Used for query deduplication and debugging.\n *\n * @returns {Promise<Result<T[]>>} A promise that resolves to the result of an REST API call.\n *\n * @example\n * import { EnumCrmEntityTypeId, Text } from '@bitrix24/b24jssdk'\n *\n * interface CrmItem { id: number, title: string }\n * const sixMonthAgo = new Date()\n * sixMonthAgo.setMonth((new Date()).getMonth() - 6)\n * sixMonthAgo.setHours(0, 0, 0)\n * const response = await b24.actions.v2.callList.make<CrmItem>({\n * method: 'crm.item.list',\n * params: {\n * entityTypeId: EnumCrmEntityTypeId.company,\n * filter: {\n * '=%title': 'A%',\n * '>=createdTime': Text.toB24Format(sixMonthAgo) // created at least 6 months ago\n * },\n * select: ['id', 'title']\n * },\n * idKey: 'id',\n * customKeyForResult: 'items',\n * requestId: 'list-123'\n * })\n * if (!response.isSuccess) {\n * throw new Error(`Problem: ${response.getErrorMessages().join('; ')}`)\n * }\n * const list = response.getData()\n * console.log(`Result: ${list?.length}`) // Number of items received\n */\n public override async make<T = unknown>(options: ActionCallListV2): Promise<Result<T[]>> {\n const batchSize = 50\n const result: Result<T[]> = new Result()\n\n const idKey = options?.idKey ?? 'ID'\n const cursorIdKey = options?.cursorIdKey ?? idKey\n const customKeyForResult = options?.customKeyForResult ?? null\n const params = options?.params ?? {}\n\n // Warn and strip user-provided `order` — cursor pagination requires ordering by cursorIdKey only\n if ('order' in params && params['order']) {\n this._logger.warning('callList.make: user-provided `order` parameter is ignored because cursor-based pagination requires ordering by cursorIdKey. Use `filter` to narrow results instead.')\n }\n\n const moreIdKey = `>${cursorIdKey}`\n const { order: _ignoredOrder, ...restParams } = params as TypeCallParams\n const requestParams: TypeCallParams = {\n ...restParams,\n order: { [cursorIdKey]: 'ASC' },\n filter: { ...(params['filter'] || {}), [moreIdKey]: 0 },\n start: -1\n }\n\n let allItems: T[] = []\n let isContinue = true\n\n do {\n const response: AjaxResult<T> = await this._b24.actions.v2.call.make<T>({\n method: options.method,\n params: requestParams,\n requestId: options.requestId\n })\n\n if (!response.isSuccess) {\n this._logger.error('callFastListMethod', {\n method: options.method,\n requestId: options.requestId,\n messages: response.getErrorMessages()\n })\n for (const [index, error] of response.errors) {\n result.addError(error, index)\n }\n isContinue = false\n break\n }\n const responseData = response.getData()\n if (!responseData) {\n isContinue = false\n break\n }\n\n let resultData: T[] = []\n if (null === customKeyForResult) {\n resultData = responseData.result as T[]\n } else {\n resultData = (responseData.result as any)[customKeyForResult] as T[]\n }\n\n if (resultData.length === 0) {\n isContinue = false\n break\n }\n\n allItems = [...allItems, ...resultData]\n\n if (resultData.length < batchSize) {\n isContinue = false\n break\n }\n\n // Update the filter for the next iteration\n const lastItem = resultData[resultData.length - 1] as Record<string, any>\n const cursorValue = lastItem ? Number.parseInt(lastItem[idKey], 10) : Number.NaN\n if (Number.isFinite(cursorValue)) {\n requestParams.filter[moreIdKey] = cursorValue\n } else {\n // A full page came back, yet no usable numeric cursor id could be read from\n // its items via `idKey` — almost always an `idKey` that doesn't match the\n // response field (e.g. a request that sorts by `ID` while the response\n // carries a lowercase `id`). Without a cursor we can't advance, so stop and\n // tell the caller how to fix it instead of silently truncating.\n this._logger.warning(`callList.make: pagination stops here — no numeric id could be read from the returned items via idKey \"${idKey}\". Make sure idKey matches the id field in the response; if the sortable field name differs from it, also set cursorIdKey (e.g. idKey: 'id', cursorIdKey: 'ID').`)\n isContinue = false\n break\n }\n } while (isContinue)\n\n return result.setData(allItems)\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -23,12 +23,16 @@ class FetchListV2 extends AbstractAction {
23
23
  *
24
24
  * @param {ActionFetchListV2} options - parameters for executing the request.
25
25
  * - `method: string` - The name of the REST API method that returns a list of data (for example: `crm.item.list`, `tasks.task.list`)
26
- * - `params?: Omit<TypeCallParams, 'start'>` - Request parameters, excluding the `start` parameter,
26
+ * - `params?: Omit<TypeCallParams, 'start' | 'order'>` - Request parameters, excluding the `start` and `order` parameters,
27
27
  * since the method is designed to obtain all data in one call.
28
28
  * Note: Use `filter`, `order`, and `select` to control the selection.
29
- * - `idKey?: string` - The name of the field containing the unique identifier of the element.
30
- * Default is 'ID' (uppercase). Alternatively, it can be 'id' (lowercase).
31
- * or another field, depending on the REST API data structure.
29
+ * - `idKey?: string` - The name of the id field as it appears in each RESPONSE item; its value
30
+ * drives the cursor. Default is 'ID' (uppercase). For methods that return a lowercase /
31
+ * camelCase id (for example `tasks.task.list` returns `id`), set `idKey: 'id'`.
32
+ * - `cursorIdKey?: string` - The field name used in the REQUEST for `order` and the `>` page
33
+ * filter. Defaults to `idKey`. Set it only when the sortable / filterable field name differs
34
+ * from the response field name — e.g. `tasks.task.list` sorts and filters by `ID` (uppercase)
35
+ * but returns `id` (lowercase): pass `idKey: 'id', cursorIdKey: 'ID'`.
32
36
  * - `customKeyForResult?: string` - A custom key indicating that the response REST API will be
33
37
  * grouped by this field.
34
38
  * Example: `items` to group a list of CRM items.
@@ -69,16 +73,17 @@ class FetchListV2 extends AbstractAction {
69
73
  async *make(options) {
70
74
  const batchSize = 50;
71
75
  const idKey = options?.idKey ?? "ID";
76
+ const cursorIdKey = options?.cursorIdKey ?? idKey;
72
77
  const customKeyForResult = options?.customKeyForResult ?? null;
73
78
  const params = options?.params ?? {};
74
79
  if ("order" in params && params["order"]) {
75
- this._logger.warning("fetchList.make: user-provided `order` parameter is ignored because cursor-based pagination requires ordering by idKey. Use `filter` to narrow results instead.");
80
+ this._logger.warning("fetchList.make: user-provided `order` parameter is ignored because cursor-based pagination requires ordering by cursorIdKey. Use `filter` to narrow results instead.");
76
81
  }
77
- const moreIdKey = `>${idKey}`;
82
+ const moreIdKey = `>${cursorIdKey}`;
78
83
  const { order: _ignoredOrder, ...restParams } = params;
79
84
  const requestParams = {
80
85
  ...restParams,
81
- order: { [idKey]: "ASC" },
86
+ order: { [cursorIdKey]: "ASC" },
82
87
  filter: { ...params["filter"] || {}, [moreIdKey]: 0 },
83
88
  start: -1
84
89
  };
@@ -122,9 +127,11 @@ class FetchListV2 extends AbstractAction {
122
127
  break;
123
128
  }
124
129
  const lastItem = resultData[resultData.length - 1];
125
- if (lastItem && typeof lastItem[idKey] !== "undefined") {
126
- requestParams.filter[moreIdKey] = Number.parseInt(lastItem[idKey]);
130
+ const cursorValue = lastItem ? Number.parseInt(lastItem[idKey], 10) : Number.NaN;
131
+ if (Number.isFinite(cursorValue)) {
132
+ requestParams.filter[moreIdKey] = cursorValue;
127
133
  } else {
134
+ this._logger.warning(`fetchList.make: pagination stops here \u2014 no numeric id could be read from the returned items via idKey "${idKey}". Make sure idKey matches the id field in the response; if the sortable field name differs from it, also set cursorIdKey (e.g. idKey: 'id', cursorIdKey: 'ID').`);
128
135
  isContinue = false;
129
136
  break;
130
137
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-list.mjs","sources":["../../../../../src/core/actions/v2/fetch-list.ts"],"sourcesContent":["import type { ActionOptions } from '../abstract-action'\nimport type { TypeCallParams } from '../../../types/http'\nimport type { AjaxResult } from '../../http/ajax-result'\nimport { AbstractAction } from '../abstract-action'\nimport { SdkError } from '../../sdk-error'\n\nexport type ActionFetchListV2 = ActionOptions & {\n method: string\n params?: Omit<TypeCallParams, 'start' | 'order'>\n idKey?: string\n customKeyForResult?: string\n requestId?: string\n}\n\n/**\n * Calls a REST API list method and returns an async generator for efficient large data retrieval. `restApi:v2`\n *\n * @todo add docs\n */\nexport class FetchListV2 extends AbstractAction {\n /**\n * Calls a REST API list method and returns an async generator for efficient large data retrieval.\n * Implements the fast algorithm for iterating over large datasets without loading all data into memory at once.\n *\n * @template T - The type of items in the returned arrays (default is `unknown`).\n *\n * @param {ActionFetchListV2} options - parameters for executing the request.\n * - `method: string` - The name of the REST API method that returns a list of data (for example: `crm.item.list`, `tasks.task.list`)\n * - `params?: Omit<TypeCallParams, 'start'>` - Request parameters, excluding the `start` parameter,\n * since the method is designed to obtain all data in one call.\n * Note: Use `filter`, `order`, and `select` to control the selection.\n * - `idKey?: string` - The name of the field containing the unique identifier of the element.\n * Default is 'ID' (uppercase). Alternatively, it can be 'id' (lowercase).\n * or another field, depending on the REST API data structure.\n * - `customKeyForResult?: string` - A custom key indicating that the response REST API will be\n * grouped by this field.\n * Example: `items` to group a list of CRM items.\n * - `requestId?: string` - Unique request identifier for tracking. Used for query deduplication and debugging.\n *\n * @returns {AsyncGenerator<T[]>} An async generator that yields chunks of data as arrays of type `T`.\n * Each iteration returns the next page/batch of results until all data is fetched.\n *\n * @example\n * import { EnumCrmEntityTypeId, Text } from '@bitrix24/b24jssdk'\n *\n * interface CrmItem { id: number, title: string }\n * const sixMonthAgo = new Date()\n * sixMonthAgo.setMonth((new Date()).getMonth() - 6)\n * sixMonthAgo.setHours(0, 0, 0)\n * const generator = b24.actions.v2.fetchList.make<CrmItem>({\n * method: 'crm.item.list',\n * params: {\n * entityTypeId: EnumCrmEntityTypeId.company,\n * filter: {\n * '=%title': 'A%',\n * '>=createdTime': Text.toB24Format(sixMonthAgo) // created at least 6 months ago\n * },\n * select: ['id', 'title']\n * },\n * idKey: 'id',\n * customKeyForResult: 'items',\n * requestId: 'list-123'\n * })\n *\n * for await (const chunk of generator) {\n * // Process chunk (e.g., save to database, analyze, etc.)\n * console.log(`Processing ${chunk.length} items`)\n * }\n *\n * @see {@link https://apidocs.bitrix24.com/settings/performance/huge-data.html Bitrix24: Fast algorithm for large data}\n */\n public override async* make<T = unknown>(options: ActionFetchListV2): AsyncGenerator<T[]> {\n const batchSize = 50\n\n const idKey = options?.idKey ?? 'ID'\n const customKeyForResult = options?.customKeyForResult ?? null\n const params = options?.params ?? {}\n\n // Warn and strip user-provided `order` — cursor pagination requires ordering by idKey only\n if ('order' in params && params['order']) {\n this._logger.warning('fetchList.make: user-provided `order` parameter is ignored because cursor-based pagination requires ordering by idKey. Use `filter` to narrow results instead.')\n }\n\n const moreIdKey = `>${idKey}`\n const { order: _ignoredOrder, ...restParams } = params as TypeCallParams\n const requestParams: TypeCallParams = {\n ...restParams,\n order: { [idKey]: 'ASC' },\n filter: { ...(params['filter'] || {}), [moreIdKey]: 0 },\n start: -1\n }\n\n let isContinue = true\n\n do {\n const response: AjaxResult<T> = await this._b24.actions.v2.call.make<T>({\n method: options.method,\n params: requestParams,\n requestId: options.requestId\n })\n\n if (!response.isSuccess) {\n this._logger.error('fetchListMethod', {\n method: options.method,\n requestId: options.requestId,\n messages: response.getErrorMessages()\n })\n throw new SdkError({\n code: 'JSSDK_CORE_B24_FETCH_LIST_METHOD_API_V2',\n description: `API Error: ${response.getErrorMessages().join('; ')}`,\n status: 500\n })\n }\n const responseData = response.getData()\n if (!responseData) {\n isContinue = false\n break\n }\n\n let resultData: T[] = []\n if (null === customKeyForResult) {\n resultData = responseData.result as T[]\n } else {\n resultData = (responseData.result as any)[customKeyForResult] as T[]\n }\n\n if (resultData.length === 0) {\n isContinue = false\n break\n }\n\n yield resultData\n\n if (resultData.length < batchSize) {\n isContinue = false\n break\n }\n\n // Update the filter for the next iteration\n const lastItem = resultData[resultData.length - 1] as Record<string, any>\n if (\n lastItem\n && typeof lastItem[idKey] !== 'undefined'\n ) {\n requestParams.filter[moreIdKey] = Number.parseInt(lastItem[idKey])\n } else {\n isContinue = false\n break\n }\n } while (isContinue)\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fetch-list.mjs","sources":["../../../../../src/core/actions/v2/fetch-list.ts"],"sourcesContent":["import type { ActionOptions } from '../abstract-action'\nimport type { TypeCallParams } from '../../../types/http'\nimport type { AjaxResult } from '../../http/ajax-result'\nimport { AbstractAction } from '../abstract-action'\nimport { SdkError } from '../../sdk-error'\n\nexport type ActionFetchListV2 = ActionOptions & {\n method: string\n params?: Omit<TypeCallParams, 'start' | 'order'>\n idKey?: string\n cursorIdKey?: string\n customKeyForResult?: string\n requestId?: string\n}\n\n/**\n * Calls a REST API list method and returns an async generator for efficient large data retrieval. `restApi:v2`\n *\n * @todo add docs\n */\nexport class FetchListV2 extends AbstractAction {\n /**\n * Calls a REST API list method and returns an async generator for efficient large data retrieval.\n * Implements the fast algorithm for iterating over large datasets without loading all data into memory at once.\n *\n * @template T - The type of items in the returned arrays (default is `unknown`).\n *\n * @param {ActionFetchListV2} options - parameters for executing the request.\n * - `method: string` - The name of the REST API method that returns a list of data (for example: `crm.item.list`, `tasks.task.list`)\n * - `params?: Omit<TypeCallParams, 'start' | 'order'>` - Request parameters, excluding the `start` and `order` parameters,\n * since the method is designed to obtain all data in one call.\n * Note: Use `filter`, `order`, and `select` to control the selection.\n * - `idKey?: string` - The name of the id field as it appears in each RESPONSE item; its value\n * drives the cursor. Default is 'ID' (uppercase). For methods that return a lowercase /\n * camelCase id (for example `tasks.task.list` returns `id`), set `idKey: 'id'`.\n * - `cursorIdKey?: string` - The field name used in the REQUEST for `order` and the `>` page\n * filter. Defaults to `idKey`. Set it only when the sortable / filterable field name differs\n * from the response field name — e.g. `tasks.task.list` sorts and filters by `ID` (uppercase)\n * but returns `id` (lowercase): pass `idKey: 'id', cursorIdKey: 'ID'`.\n * - `customKeyForResult?: string` - A custom key indicating that the response REST API will be\n * grouped by this field.\n * Example: `items` to group a list of CRM items.\n * - `requestId?: string` - Unique request identifier for tracking. Used for query deduplication and debugging.\n *\n * @returns {AsyncGenerator<T[]>} An async generator that yields chunks of data as arrays of type `T`.\n * Each iteration returns the next page/batch of results until all data is fetched.\n *\n * @example\n * import { EnumCrmEntityTypeId, Text } from '@bitrix24/b24jssdk'\n *\n * interface CrmItem { id: number, title: string }\n * const sixMonthAgo = new Date()\n * sixMonthAgo.setMonth((new Date()).getMonth() - 6)\n * sixMonthAgo.setHours(0, 0, 0)\n * const generator = b24.actions.v2.fetchList.make<CrmItem>({\n * method: 'crm.item.list',\n * params: {\n * entityTypeId: EnumCrmEntityTypeId.company,\n * filter: {\n * '=%title': 'A%',\n * '>=createdTime': Text.toB24Format(sixMonthAgo) // created at least 6 months ago\n * },\n * select: ['id', 'title']\n * },\n * idKey: 'id',\n * customKeyForResult: 'items',\n * requestId: 'list-123'\n * })\n *\n * for await (const chunk of generator) {\n * // Process chunk (e.g., save to database, analyze, etc.)\n * console.log(`Processing ${chunk.length} items`)\n * }\n *\n * @see {@link https://apidocs.bitrix24.com/settings/performance/huge-data.html Bitrix24: Fast algorithm for large data}\n */\n public override async* make<T = unknown>(options: ActionFetchListV2): AsyncGenerator<T[]> {\n const batchSize = 50\n\n const idKey = options?.idKey ?? 'ID'\n const cursorIdKey = options?.cursorIdKey ?? idKey\n const customKeyForResult = options?.customKeyForResult ?? null\n const params = options?.params ?? {}\n\n // Warn and strip user-provided `order` — cursor pagination requires ordering by cursorIdKey only\n if ('order' in params && params['order']) {\n this._logger.warning('fetchList.make: user-provided `order` parameter is ignored because cursor-based pagination requires ordering by cursorIdKey. Use `filter` to narrow results instead.')\n }\n\n const moreIdKey = `>${cursorIdKey}`\n const { order: _ignoredOrder, ...restParams } = params as TypeCallParams\n const requestParams: TypeCallParams = {\n ...restParams,\n order: { [cursorIdKey]: 'ASC' },\n filter: { ...(params['filter'] || {}), [moreIdKey]: 0 },\n start: -1\n }\n\n let isContinue = true\n\n do {\n const response: AjaxResult<T> = await this._b24.actions.v2.call.make<T>({\n method: options.method,\n params: requestParams,\n requestId: options.requestId\n })\n\n if (!response.isSuccess) {\n this._logger.error('fetchListMethod', {\n method: options.method,\n requestId: options.requestId,\n messages: response.getErrorMessages()\n })\n throw new SdkError({\n code: 'JSSDK_CORE_B24_FETCH_LIST_METHOD_API_V2',\n description: `API Error: ${response.getErrorMessages().join('; ')}`,\n status: 500\n })\n }\n const responseData = response.getData()\n if (!responseData) {\n isContinue = false\n break\n }\n\n let resultData: T[] = []\n if (null === customKeyForResult) {\n resultData = responseData.result as T[]\n } else {\n resultData = (responseData.result as any)[customKeyForResult] as T[]\n }\n\n if (resultData.length === 0) {\n isContinue = false\n break\n }\n\n yield resultData\n\n if (resultData.length < batchSize) {\n isContinue = false\n break\n }\n\n // Update the filter for the next iteration\n const lastItem = resultData[resultData.length - 1] as Record<string, any>\n const cursorValue = lastItem ? Number.parseInt(lastItem[idKey], 10) : Number.NaN\n if (Number.isFinite(cursorValue)) {\n requestParams.filter[moreIdKey] = cursorValue\n } else {\n // A full page came back, yet no usable numeric cursor id could be read from\n // its items via `idKey` — almost always an `idKey` that doesn't match the\n // response field (e.g. a request that sorts by `ID` while the response\n // carries a lowercase `id`). Without a cursor we can't advance, so stop and\n // tell the caller how to fix it instead of silently truncating.\n this._logger.warning(`fetchList.make: pagination stops here — no numeric id could be read from the returned items via idKey \"${idKey}\". Make sure idKey matches the id field in the response; if the sortable field name differs from it, also set cursorIdKey (e.g. idKey: 'id', cursorIdKey: 'ID').`)\n isContinue = false\n break\n }\n } while (isContinue)\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -15,11 +15,11 @@ import { LoggerFactory } from '../../../logger/logger-factory.mjs';
15
15
 
16
16
  var __defProp = Object.defineProperty;
17
17
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
18
- const callName = Symbol("call_V2");
19
- const callListName = Symbol("callList_V2");
20
- const fetchListName = Symbol("fetchList_V2");
21
- const batchName = Symbol("batch_V2");
22
- const batchByChunkName = Symbol("batchByChunk_V2");
18
+ const callName = /* @__PURE__ */ Symbol("call_V2");
19
+ const callListName = /* @__PURE__ */ Symbol("callList_V2");
20
+ const fetchListName = /* @__PURE__ */ Symbol("fetchList_V2");
21
+ const batchName = /* @__PURE__ */ Symbol("batch_V2");
22
+ const batchByChunkName = /* @__PURE__ */ Symbol("batchByChunk_V2");
23
23
  class ActionsManagerV2 {
24
24
  static {
25
25
  __name(this, "ActionsManagerV2");
@@ -1 +1 @@
1
- {"version":3,"file":"manager-v2.mjs","sources":["../../../../../src/core/actions/v2/manager-v2.ts"],"sourcesContent":["import type { TypeB24 } from '../../../types/b24'\nimport type { LoggerInterface } from '../../../types/logger'\nimport type { AbstractAction } from '../abstract-action'\nimport { LoggerFactory } from '../../../logger'\nimport { CallV2 } from './call'\nimport { CallListV2 } from './call-list'\nimport { FetchListV2 } from './fetch-list'\nimport { BatchV2 } from './batch'\nimport { BatchByChunkV2 } from './batch-by-chunk'\n\nconst callName = Symbol('call_V2')\nconst callListName = Symbol('callList_V2')\nconst fetchListName = Symbol('fetchList_V2')\nconst batchName = Symbol('batch_V2')\nconst batchByChunkName = Symbol('batchByChunk_V2')\n\n/**\n * Some actions for TypeB24 by Api:v2\n */\nexport class ActionsManagerV2 {\n protected _b24: TypeB24\n protected _logger: LoggerInterface\n\n protected _mapActions: Map<symbol, AbstractAction>\n\n constructor(b24: TypeB24) {\n this._b24 = b24\n this._logger = LoggerFactory.createNullLogger()\n\n this._mapActions = new Map()\n }\n\n public setLogger(logger: LoggerInterface): void {\n this._logger = logger\n }\n\n public getLogger(): LoggerInterface {\n return this._logger\n }\n\n get call(): CallV2 {\n if (!this._mapActions.has(callName)) {\n this._mapActions.set(callName, new CallV2(this._b24, this._logger))\n }\n return this._mapActions.get(callName)! as CallV2\n }\n\n get callList(): CallListV2 {\n if (!this._mapActions.has(callListName)) {\n this._mapActions.set(callListName, new CallListV2(this._b24, this._logger))\n }\n return this._mapActions.get(callListName)! as CallListV2\n }\n\n get fetchList(): FetchListV2 {\n if (!this._mapActions.has(fetchListName)) {\n this._mapActions.set(fetchListName, new FetchListV2(this._b24, this._logger))\n }\n return this._mapActions.get(fetchListName)! as FetchListV2\n }\n\n get batch(): BatchV2 {\n if (!this._mapActions.has(batchName)) {\n this._mapActions.set(batchName, new BatchV2(this._b24, this._logger))\n }\n return this._mapActions.get(batchName)! as BatchV2\n }\n\n get batchByChunk(): BatchByChunkV2 {\n if (!this._mapActions.has(batchByChunkName)) {\n this._mapActions.set(batchByChunkName, new BatchByChunkV2(this._b24, this._logger))\n }\n return this._mapActions.get(batchByChunkName)! as BatchByChunkV2\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAUA,MAAM,QAAA,GAAW,OAAO,SAAS,CAAA;AACjC,MAAM,YAAA,GAAe,OAAO,aAAa,CAAA;AACzC,MAAM,aAAA,GAAgB,OAAO,cAAc,CAAA;AAC3C,MAAM,SAAA,GAAY,OAAO,UAAU,CAAA;AACnC,MAAM,gBAAA,GAAmB,OAAO,iBAAiB,CAAA;AAK1C,MAAM,gBAAA,CAAiB;AAAA,EAnB9B;AAmB8B,IAAA,MAAA,CAAA,IAAA,EAAA,kBAAA,CAAA;AAAA;AAAA,EAClB,IAAA;AAAA,EACA,OAAA;AAAA,EAEA,WAAA;AAAA,EAEV,YAAY,GAAA,EAAc;AACxB,IAAA,IAAA,CAAK,IAAA,GAAO,GAAA;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,cAAc,gBAAA,EAAiB;AAE9C,IAAA,IAAA,CAAK,WAAA,uBAAkB,GAAA,EAAI;AAAA,EAC7B;AAAA,EAEO,UAAU,MAAA,EAA+B;AAC9C,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AAAA,EACjB;AAAA,EAEO,SAAA,GAA6B;AAClC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA,EAEA,IAAI,IAAA,GAAe;AACjB,IAAA,IAAI,CAAC,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,QAAQ,CAAA,EAAG;AACnC,MAAA,IAAA,CAAK,WAAA,CAAY,IAAI,QAAA,EAAU,IAAI,OAAO,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,IACpE;AACA,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,QAAQ,CAAA;AAAA,EACtC;AAAA,EAEA,IAAI,QAAA,GAAuB;AACzB,IAAA,IAAI,CAAC,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,YAAY,CAAA,EAAG;AACvC,MAAA,IAAA,CAAK,WAAA,CAAY,IAAI,YAAA,EAAc,IAAI,WAAW,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,IAC5E;AACA,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,YAAY,CAAA;AAAA,EAC1C;AAAA,EAEA,IAAI,SAAA,GAAyB;AAC3B,IAAA,IAAI,CAAC,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,aAAa,CAAA,EAAG;AACxC,MAAA,IAAA,CAAK,WAAA,CAAY,IAAI,aAAA,EAAe,IAAI,YAAY,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,IAC9E;AACA,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,aAAa,CAAA;AAAA,EAC3C;AAAA,EAEA,IAAI,KAAA,GAAiB;AACnB,IAAA,IAAI,CAAC,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,SAAS,CAAA,EAAG;AACpC,MAAA,IAAA,CAAK,WAAA,CAAY,IAAI,SAAA,EAAW,IAAI,QAAQ,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,IACtE;AACA,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,SAAS,CAAA;AAAA,EACvC;AAAA,EAEA,IAAI,YAAA,GAA+B;AACjC,IAAA,IAAI,CAAC,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,gBAAgB,CAAA,EAAG;AAC3C,MAAA,IAAA,CAAK,WAAA,CAAY,IAAI,gBAAA,EAAkB,IAAI,eAAe,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,IACpF;AACA,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,gBAAgB,CAAA;AAAA,EAC9C;AACF;;;;"}
1
+ {"version":3,"file":"manager-v2.mjs","sources":["../../../../../src/core/actions/v2/manager-v2.ts"],"sourcesContent":["import type { TypeB24 } from '../../../types/b24'\nimport type { LoggerInterface } from '../../../types/logger'\nimport type { AbstractAction } from '../abstract-action'\nimport { LoggerFactory } from '../../../logger'\nimport { CallV2 } from './call'\nimport { CallListV2 } from './call-list'\nimport { FetchListV2 } from './fetch-list'\nimport { BatchV2 } from './batch'\nimport { BatchByChunkV2 } from './batch-by-chunk'\n\nconst callName = Symbol('call_V2')\nconst callListName = Symbol('callList_V2')\nconst fetchListName = Symbol('fetchList_V2')\nconst batchName = Symbol('batch_V2')\nconst batchByChunkName = Symbol('batchByChunk_V2')\n\n/**\n * Some actions for TypeB24 by Api:v2\n */\nexport class ActionsManagerV2 {\n protected _b24: TypeB24\n protected _logger: LoggerInterface\n\n protected _mapActions: Map<symbol, AbstractAction>\n\n constructor(b24: TypeB24) {\n this._b24 = b24\n this._logger = LoggerFactory.createNullLogger()\n\n this._mapActions = new Map()\n }\n\n public setLogger(logger: LoggerInterface): void {\n this._logger = logger\n }\n\n public getLogger(): LoggerInterface {\n return this._logger\n }\n\n get call(): CallV2 {\n if (!this._mapActions.has(callName)) {\n this._mapActions.set(callName, new CallV2(this._b24, this._logger))\n }\n return this._mapActions.get(callName)! as CallV2\n }\n\n get callList(): CallListV2 {\n if (!this._mapActions.has(callListName)) {\n this._mapActions.set(callListName, new CallListV2(this._b24, this._logger))\n }\n return this._mapActions.get(callListName)! as CallListV2\n }\n\n get fetchList(): FetchListV2 {\n if (!this._mapActions.has(fetchListName)) {\n this._mapActions.set(fetchListName, new FetchListV2(this._b24, this._logger))\n }\n return this._mapActions.get(fetchListName)! as FetchListV2\n }\n\n get batch(): BatchV2 {\n if (!this._mapActions.has(batchName)) {\n this._mapActions.set(batchName, new BatchV2(this._b24, this._logger))\n }\n return this._mapActions.get(batchName)! as BatchV2\n }\n\n get batchByChunk(): BatchByChunkV2 {\n if (!this._mapActions.has(batchByChunkName)) {\n this._mapActions.set(batchByChunkName, new BatchByChunkV2(this._b24, this._logger))\n }\n return this._mapActions.get(batchByChunkName)! as BatchByChunkV2\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAUA,MAAM,QAAA,0BAAkB,SAAS,CAAA;AACjC,MAAM,YAAA,0BAAsB,aAAa,CAAA;AACzC,MAAM,aAAA,0BAAuB,cAAc,CAAA;AAC3C,MAAM,SAAA,0BAAmB,UAAU,CAAA;AACnC,MAAM,gBAAA,0BAA0B,iBAAiB,CAAA;AAK1C,MAAM,gBAAA,CAAiB;AAAA,EAnB9B;AAmB8B,IAAA,MAAA,CAAA,IAAA,EAAA,kBAAA,CAAA;AAAA;AAAA,EAClB,IAAA;AAAA,EACA,OAAA;AAAA,EAEA,WAAA;AAAA,EAEV,YAAY,GAAA,EAAc;AACxB,IAAA,IAAA,CAAK,IAAA,GAAO,GAAA;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,cAAc,gBAAA,EAAiB;AAE9C,IAAA,IAAA,CAAK,WAAA,uBAAkB,GAAA,EAAI;AAAA,EAC7B;AAAA,EAEO,UAAU,MAAA,EAA+B;AAC9C,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AAAA,EACjB;AAAA,EAEO,SAAA,GAA6B;AAClC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA,EAEA,IAAI,IAAA,GAAe;AACjB,IAAA,IAAI,CAAC,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,QAAQ,CAAA,EAAG;AACnC,MAAA,IAAA,CAAK,WAAA,CAAY,IAAI,QAAA,EAAU,IAAI,OAAO,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,IACpE;AACA,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,QAAQ,CAAA;AAAA,EACtC;AAAA,EAEA,IAAI,QAAA,GAAuB;AACzB,IAAA,IAAI,CAAC,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,YAAY,CAAA,EAAG;AACvC,MAAA,IAAA,CAAK,WAAA,CAAY,IAAI,YAAA,EAAc,IAAI,WAAW,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,IAC5E;AACA,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,YAAY,CAAA;AAAA,EAC1C;AAAA,EAEA,IAAI,SAAA,GAAyB;AAC3B,IAAA,IAAI,CAAC,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,aAAa,CAAA,EAAG;AACxC,MAAA,IAAA,CAAK,WAAA,CAAY,IAAI,aAAA,EAAe,IAAI,YAAY,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,IAC9E;AACA,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,aAAa,CAAA;AAAA,EAC3C;AAAA,EAEA,IAAI,KAAA,GAAiB;AACnB,IAAA,IAAI,CAAC,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,SAAS,CAAA,EAAG;AACpC,MAAA,IAAA,CAAK,WAAA,CAAY,IAAI,SAAA,EAAW,IAAI,QAAQ,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,IACtE;AACA,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,SAAS,CAAA;AAAA,EACvC;AAAA,EAEA,IAAI,YAAA,GAA+B;AACjC,IAAA,IAAI,CAAC,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,gBAAgB,CAAA,EAAG;AAC3C,MAAA,IAAA,CAAK,WAAA,CAAY,IAAI,gBAAA,EAAkB,IAAI,eAAe,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,IACpF;AACA,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,gBAAgB,CAAA;AAAA,EAC9C;AACF;;;;"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk
@@ -22,11 +22,15 @@ class CallListV3 extends AbstractAction {
22
22
  *
23
23
  * @param {ActionCallListV3} options - parameters for executing the request.
24
24
  * - `method: string` - The name of the REST API method that returns a list of data (for example: `crm.item.list`, `tasks.task.list`)
25
- * - `params?: Omit<TypeCallParams, 'pagination'>` - Request parameters, excluding the `pagination` parameter,
25
+ * - `params?: Omit<TypeCallParams, 'pagination' | 'order'>` - Request parameters, excluding the `pagination` and `order` parameters,
26
26
  * since the method is designed to obtain all data in one call.
27
27
  * Note: Use `filter`, `order`, and `select` to control the selection.
28
- * - `idKey?: string` - The name of the field containing the unique identifier of the element.
29
- * Default is 'id'. Alternatively, it can be another field, depending on the REST API data structure.
28
+ * - `idKey?: string` - The name of the id field as it appears in each RESPONSE item; its value
29
+ * drives the cursor. Default is 'id'. Set it to match the id field the method returns.
30
+ * - `cursorIdKey?: string` - The field name used in the REQUEST for `order` and the
31
+ * `[field, '>', n]` page filter. Defaults to `idKey`. Set it only when the sortable /
32
+ * filterable field name differs from the response field name (e.g. an uppercase request
33
+ * field but a lowercase response id): pass `idKey: 'id', cursorIdKey: 'ID'`.
30
34
  * - `customKeyForResult: string` - A custom key indicating that the response REST API will be
31
35
  * grouped by this field.
32
36
  * Example: `items` to group a list of CRM items.
@@ -65,15 +69,16 @@ class CallListV3 extends AbstractAction {
65
69
  const batchSize = options?.limit ?? 50;
66
70
  const result = new Result();
67
71
  const idKey = options?.idKey ?? "id";
72
+ const cursorIdKey = options?.cursorIdKey ?? idKey;
68
73
  const customKeyForResult = options?.customKeyForResult ?? null;
69
74
  const params = options?.params ?? {};
70
75
  if ("order" in params && params["order"]) {
71
- this._logger.warning("callList.make: user-provided `order` parameter is ignored because cursor-based pagination requires ordering by idKey. Use `filter` to narrow results instead.");
76
+ this._logger.warning("callList.make: user-provided `order` parameter is ignored because cursor-based pagination requires ordering by cursorIdKey. Use `filter` to narrow results instead.");
72
77
  }
73
78
  const { order: _ignoredOrder, ...restParams } = params;
74
79
  const requestParams = {
75
80
  ...restParams,
76
- order: { [idKey]: "ASC" },
81
+ order: { [cursorIdKey]: "ASC" },
77
82
  filter: [...params["filter"] || []],
78
83
  pagination: { page: 0, limit: batchSize }
79
84
  };
@@ -82,7 +87,7 @@ class CallListV3 extends AbstractAction {
82
87
  let nextId = 0;
83
88
  do {
84
89
  const sendParams = { ...requestParams, filter: [...requestParams.filter] };
85
- sendParams.filter.push([idKey, ">", nextId]);
90
+ sendParams.filter.push([cursorIdKey, ">", nextId]);
86
91
  const response = await this._b24.actions.v3.call.make({
87
92
  method: options.method,
88
93
  params: sendParams,
@@ -116,9 +121,11 @@ class CallListV3 extends AbstractAction {
116
121
  break;
117
122
  }
118
123
  const lastItem = resultData[resultData.length - 1];
119
- if (lastItem && typeof lastItem[idKey] !== "undefined") {
120
- nextId = Number.parseInt(lastItem[idKey]);
124
+ const cursorValue = lastItem ? Number.parseInt(lastItem[idKey], 10) : Number.NaN;
125
+ if (Number.isFinite(cursorValue)) {
126
+ nextId = cursorValue;
121
127
  } else {
128
+ this._logger.warning(`callList.make: pagination stops here \u2014 no numeric id could be read from the returned items via idKey "${idKey}". Make sure idKey matches the id field in the response; if the sortable field name differs from it, also set cursorIdKey (e.g. idKey: 'id', cursorIdKey: 'ID').`);
122
129
  isContinue = false;
123
130
  break;
124
131
  }
@@ -1 +1 @@
1
- {"version":3,"file":"call-list.mjs","sources":["../../../../../src/core/actions/v3/call-list.ts"],"sourcesContent":["import type { ActionOptions } from '../abstract-action'\nimport type { TypeCallParams } from '../../../types/http'\nimport type { AjaxResult } from '../../http/ajax-result'\nimport { AbstractAction } from '../abstract-action'\nimport { Result } from '../../result'\n\nexport type ActionCallListV3 = ActionOptions & {\n method: string\n params?: Omit<TypeCallParams, 'pagination' | 'order'>\n idKey?: string\n customKeyForResult: string\n requestId?: string\n limit?: number\n}\n\n/**\n * Fast data retrieval without counting the total number of records. `restApi:v3`\n *\n * @todo add docs\n */\nexport class CallListV3 extends AbstractAction {\n /**\n * Fast data retrieval without counting the total number of records.\n *\n * @template T - The type of the elements of the returned array (default is `unknown`).\n *\n * @param {ActionCallListV3} options - parameters for executing the request.\n * - `method: string` - The name of the REST API method that returns a list of data (for example: `crm.item.list`, `tasks.task.list`)\n * - `params?: Omit<TypeCallParams, 'pagination'>` - Request parameters, excluding the `pagination` parameter,\n * since the method is designed to obtain all data in one call.\n * Note: Use `filter`, `order`, and `select` to control the selection.\n * - `idKey?: string` - The name of the field containing the unique identifier of the element.\n * Default is 'id'. Alternatively, it can be another field, depending on the REST API data structure.\n * - `customKeyForResult: string` - A custom key indicating that the response REST API will be\n * grouped by this field.\n * Example: `items` to group a list of CRM items.\n * - `requestId?: string` - Unique request identifier for tracking. Used for query deduplication and debugging.\n * - `limit?: number` - How many records to retrieve at a time. Default is `50`. Maximum is `1000`.\n *\n * @returns {Promise<Result<T[]>>} A promise that resolves to the result of an REST API call.\n *\n * @example\n * import { Text } from '@bitrix24/b24jssdk'\n *\n * interface MainEventLogItem { id: number, userId: number }\n * const sixMonthAgo = new Date()\n * sixMonthAgo.setMonth((new Date()).getMonth() - 6)\n * sixMonthAgo.setHours(0, 0, 0)\n * const response = await b24.actions.v3.callList.make<MainEventLogItem>({\n * method: 'main.eventlog.list',\n * params: {\n * filter: [\n * ['timestampX', '>=', Text.toB24Format(sixMonthAgo)] // created at least 6 months ago\n * ],\n * select: ['id', 'userId']\n * },\n * idKey: 'id',\n * customKeyForResult: 'items',\n * requestId: 'eventlog-123',\n * limit: 60\n * })\n * if (!response.isSuccess) {\n * throw new Error(`Problem: ${response.getErrorMessages().join('; ')}`)\n * }\n * const list = response.getData()\n * console.log(`Result: ${list?.length}`) // Number of items received\n */\n public override async make<T = unknown>(options: ActionCallListV3): Promise<Result<T[]>> {\n const batchSize = options?.limit ?? 50\n const result: Result<T[]> = new Result()\n\n const idKey = options?.idKey ?? 'id'\n const customKeyForResult = options?.customKeyForResult ?? null\n const params = options?.params ?? {}\n\n // Warn and strip user-provided `order` — cursor pagination requires ordering by idKey only\n if ('order' in params && params['order']) {\n this._logger.warning('callList.make: user-provided `order` parameter is ignored because cursor-based pagination requires ordering by idKey. Use `filter` to narrow results instead.')\n }\n\n const { order: _ignoredOrder, ...restParams } = params as TypeCallParams\n const requestParams: TypeCallParams = {\n ...restParams,\n order: { [idKey]: 'ASC' },\n filter: [...(params['filter'] || [])],\n pagination: { page: 0, limit: batchSize }\n }\n\n let allItems: T[] = []\n let isContinue = true\n let nextId = 0\n do {\n const sendParams = { ...requestParams, filter: [...requestParams.filter] }\n sendParams.filter.push([idKey, '>', nextId])\n const response: AjaxResult<T> = await this._b24.actions.v3.call.make<T>({\n method: options.method,\n params: sendParams,\n requestId: options.requestId\n })\n\n if (!response.isSuccess) {\n this._logger.error('callFastListMethod', {\n method: options.method,\n requestId: options.requestId,\n messages: response.getErrorMessages()\n })\n for (const [index, error] of response.errors) {\n result.addError(error, index)\n }\n isContinue = false\n break\n }\n const responseData = response.getData()\n if (!responseData) {\n isContinue = false\n break\n }\n\n const resultData = (responseData.result as any)[customKeyForResult] as T[]\n if (resultData.length === 0) {\n isContinue = false\n break\n }\n\n allItems = [...allItems, ...resultData]\n\n if (resultData.length < batchSize) {\n isContinue = false\n break\n }\n\n // Update the filter for the next iteration\n const lastItem = resultData[resultData.length - 1] as Record<string, any>\n if (lastItem && typeof lastItem[idKey] !== 'undefined') {\n nextId = Number.parseInt(lastItem[idKey] as string)\n } else {\n isContinue = false\n break\n }\n } while (isContinue)\n\n return result.setData(allItems)\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;AAoBO,MAAM,mBAAmB,cAAA,CAAe;AAAA,EApB/C;AAoB+C,IAAA,MAAA,CAAA,IAAA,EAAA,YAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+C7C,MAAsB,KAAkB,OAAA,EAAiD;AACvF,IAAA,MAAM,SAAA,GAAY,SAAS,KAAA,IAAS,EAAA;AACpC,IAAA,MAAM,MAAA,GAAsB,IAAI,MAAA,EAAO;AAEvC,IAAA,MAAM,KAAA,GAAQ,SAAS,KAAA,IAAS,IAAA;AAChC,IAAA,MAAM,kBAAA,GAAqB,SAAS,kBAAA,IAAsB,IAAA;AAC1D,IAAA,MAAM,MAAA,GAAS,OAAA,EAAS,MAAA,IAAU,EAAC;AAGnC,IAAA,IAAI,OAAA,IAAW,MAAA,IAAU,MAAA,CAAO,OAAO,CAAA,EAAG;AACxC,MAAA,IAAA,CAAK,OAAA,CAAQ,QAAQ,+JAA+J,CAAA;AAAA,IACtL;AAEA,IAAA,MAAM,EAAE,KAAA,EAAO,aAAA,EAAe,GAAG,YAAW,GAAI,MAAA;AAChD,IAAA,MAAM,aAAA,GAAgC;AAAA,MACpC,GAAG,UAAA;AAAA,MACH,KAAA,EAAO,EAAE,CAAC,KAAK,GAAG,KAAA,EAAM;AAAA,MACxB,QAAQ,CAAC,GAAI,OAAO,QAAQ,CAAA,IAAK,EAAG,CAAA;AAAA,MACpC,UAAA,EAAY,EAAE,IAAA,EAAM,CAAA,EAAG,OAAO,SAAA;AAAU,KAC1C;AAEA,IAAA,IAAI,WAAgB,EAAC;AACrB,IAAA,IAAI,UAAA,GAAa,IAAA;AACjB,IAAA,IAAI,MAAA,GAAS,CAAA;AACb,IAAA,GAAG;AACD,MAAA,MAAM,UAAA,GAAa,EAAE,GAAG,aAAA,EAAe,QAAQ,CAAC,GAAG,aAAA,CAAc,MAAM,CAAA,EAAE;AACzE,MAAA,UAAA,CAAW,OAAO,IAAA,CAAK,CAAC,KAAA,EAAO,GAAA,EAAK,MAAM,CAAC,CAAA;AAC3C,MAAA,MAAM,WAA0B,MAAM,IAAA,CAAK,KAAK,OAAA,CAAQ,EAAA,CAAG,KAAK,IAAA,CAAQ;AAAA,QACtE,QAAQ,OAAA,CAAQ,MAAA;AAAA,QAChB,MAAA,EAAQ,UAAA;AAAA,QACR,WAAW,OAAA,CAAQ;AAAA,OACpB,CAAA;AAED,MAAA,IAAI,CAAC,SAAS,SAAA,EAAW;AACvB,QAAA,IAAA,CAAK,OAAA,CAAQ,MAAM,oBAAA,EAAsB;AAAA,UACvC,QAAQ,OAAA,CAAQ,MAAA;AAAA,UAChB,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,QAAA,EAAU,SAAS,gBAAA;AAAiB,SACrC,CAAA;AACD,QAAA,KAAA,MAAW,CAAC,KAAA,EAAO,KAAK,CAAA,IAAK,SAAS,MAAA,EAAQ;AAC5C,UAAA,MAAA,CAAO,QAAA,CAAS,OAAO,KAAK,CAAA;AAAA,QAC9B;AACA,QAAA,UAAA,GAAa,KAAA;AACb,QAAA;AAAA,MACF;AACA,MAAA,MAAM,YAAA,GAAe,SAAS,OAAA,EAAQ;AACtC,MAAA,IAAI,CAAC,YAAA,EAAc;AACjB,QAAA,UAAA,GAAa,KAAA;AACb,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,UAAA,GAAc,YAAA,CAAa,MAAA,CAAe,kBAAkB,CAAA;AAClE,MAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC3B,QAAA,UAAA,GAAa,KAAA;AACb,QAAA;AAAA,MACF;AAEA,MAAA,QAAA,GAAW,CAAC,GAAG,QAAA,EAAU,GAAG,UAAU,CAAA;AAEtC,MAAA,IAAI,UAAA,CAAW,SAAS,SAAA,EAAW;AACjC,QAAA,UAAA,GAAa,KAAA;AACb,QAAA;AAAA,MACF;AAGA,MAAA,MAAM,QAAA,GAAW,UAAA,CAAW,UAAA,CAAW,MAAA,GAAS,CAAC,CAAA;AACjD,MAAA,IAAI,QAAA,IAAY,OAAO,QAAA,CAAS,KAAK,MAAM,WAAA,EAAa;AACtD,QAAA,MAAA,GAAS,MAAA,CAAO,QAAA,CAAS,QAAA,CAAS,KAAK,CAAW,CAAA;AAAA,MACpD,CAAA,MAAO;AACL,QAAA,UAAA,GAAa,KAAA;AACb,QAAA;AAAA,MACF;AAAA,IACF,CAAA,QAAS,UAAA;AAET,IAAA,OAAO,MAAA,CAAO,QAAQ,QAAQ,CAAA;AAAA,EAChC;AACF;;;;"}
1
+ {"version":3,"file":"call-list.mjs","sources":["../../../../../src/core/actions/v3/call-list.ts"],"sourcesContent":["import type { ActionOptions } from '../abstract-action'\nimport type { TypeCallParams } from '../../../types/http'\nimport type { AjaxResult } from '../../http/ajax-result'\nimport { AbstractAction } from '../abstract-action'\nimport { Result } from '../../result'\n\nexport type ActionCallListV3 = ActionOptions & {\n method: string\n params?: Omit<TypeCallParams, 'pagination' | 'order'>\n idKey?: string\n cursorIdKey?: string\n customKeyForResult: string\n requestId?: string\n limit?: number\n}\n\n/**\n * Fast data retrieval without counting the total number of records. `restApi:v3`\n *\n * @todo add docs\n */\nexport class CallListV3 extends AbstractAction {\n /**\n * Fast data retrieval without counting the total number of records.\n *\n * @template T - The type of the elements of the returned array (default is `unknown`).\n *\n * @param {ActionCallListV3} options - parameters for executing the request.\n * - `method: string` - The name of the REST API method that returns a list of data (for example: `crm.item.list`, `tasks.task.list`)\n * - `params?: Omit<TypeCallParams, 'pagination' | 'order'>` - Request parameters, excluding the `pagination` and `order` parameters,\n * since the method is designed to obtain all data in one call.\n * Note: Use `filter`, `order`, and `select` to control the selection.\n * - `idKey?: string` - The name of the id field as it appears in each RESPONSE item; its value\n * drives the cursor. Default is 'id'. Set it to match the id field the method returns.\n * - `cursorIdKey?: string` - The field name used in the REQUEST for `order` and the\n * `[field, '>', n]` page filter. Defaults to `idKey`. Set it only when the sortable /\n * filterable field name differs from the response field name (e.g. an uppercase request\n * field but a lowercase response id): pass `idKey: 'id', cursorIdKey: 'ID'`.\n * - `customKeyForResult: string` - A custom key indicating that the response REST API will be\n * grouped by this field.\n * Example: `items` to group a list of CRM items.\n * - `requestId?: string` - Unique request identifier for tracking. Used for query deduplication and debugging.\n * - `limit?: number` - How many records to retrieve at a time. Default is `50`. Maximum is `1000`.\n *\n * @returns {Promise<Result<T[]>>} A promise that resolves to the result of an REST API call.\n *\n * @example\n * import { Text } from '@bitrix24/b24jssdk'\n *\n * interface MainEventLogItem { id: number, userId: number }\n * const sixMonthAgo = new Date()\n * sixMonthAgo.setMonth((new Date()).getMonth() - 6)\n * sixMonthAgo.setHours(0, 0, 0)\n * const response = await b24.actions.v3.callList.make<MainEventLogItem>({\n * method: 'main.eventlog.list',\n * params: {\n * filter: [\n * ['timestampX', '>=', Text.toB24Format(sixMonthAgo)] // created at least 6 months ago\n * ],\n * select: ['id', 'userId']\n * },\n * idKey: 'id',\n * customKeyForResult: 'items',\n * requestId: 'eventlog-123',\n * limit: 60\n * })\n * if (!response.isSuccess) {\n * throw new Error(`Problem: ${response.getErrorMessages().join('; ')}`)\n * }\n * const list = response.getData()\n * console.log(`Result: ${list?.length}`) // Number of items received\n */\n public override async make<T = unknown>(options: ActionCallListV3): Promise<Result<T[]>> {\n const batchSize = options?.limit ?? 50\n const result: Result<T[]> = new Result()\n\n const idKey = options?.idKey ?? 'id'\n const cursorIdKey = options?.cursorIdKey ?? idKey\n const customKeyForResult = options?.customKeyForResult ?? null\n const params = options?.params ?? {}\n\n // Warn and strip user-provided `order` — cursor pagination requires ordering by cursorIdKey only\n if ('order' in params && params['order']) {\n this._logger.warning('callList.make: user-provided `order` parameter is ignored because cursor-based pagination requires ordering by cursorIdKey. Use `filter` to narrow results instead.')\n }\n\n const { order: _ignoredOrder, ...restParams } = params as TypeCallParams\n const requestParams: TypeCallParams = {\n ...restParams,\n order: { [cursorIdKey]: 'ASC' },\n filter: [...(params['filter'] || [])],\n pagination: { page: 0, limit: batchSize }\n }\n\n let allItems: T[] = []\n let isContinue = true\n let nextId = 0\n do {\n const sendParams = { ...requestParams, filter: [...requestParams.filter] }\n sendParams.filter.push([cursorIdKey, '>', nextId])\n const response: AjaxResult<T> = await this._b24.actions.v3.call.make<T>({\n method: options.method,\n params: sendParams,\n requestId: options.requestId\n })\n\n if (!response.isSuccess) {\n this._logger.error('callFastListMethod', {\n method: options.method,\n requestId: options.requestId,\n messages: response.getErrorMessages()\n })\n for (const [index, error] of response.errors) {\n result.addError(error, index)\n }\n isContinue = false\n break\n }\n const responseData = response.getData()\n if (!responseData) {\n isContinue = false\n break\n }\n\n const resultData = (responseData.result as any)[customKeyForResult] as T[]\n if (resultData.length === 0) {\n isContinue = false\n break\n }\n\n allItems = [...allItems, ...resultData]\n\n if (resultData.length < batchSize) {\n isContinue = false\n break\n }\n\n // Update the filter for the next iteration\n const lastItem = resultData[resultData.length - 1] as Record<string, any>\n const cursorValue = lastItem ? Number.parseInt(lastItem[idKey], 10) : Number.NaN\n if (Number.isFinite(cursorValue)) {\n nextId = cursorValue\n } else {\n // A full page came back, yet no usable numeric cursor id could be read from\n // its items via `idKey` almost always an `idKey` that doesn't match the\n // response field (e.g. a request that sorts by `ID` while the response\n // carries a lowercase `id`). Without a cursor we can't advance, so stop and\n // tell the caller how to fix it instead of silently truncating.\n this._logger.warning(`callList.make: pagination stops here — no numeric id could be read from the returned items via idKey \"${idKey}\". Make sure idKey matches the id field in the response; if the sortable field name differs from it, also set cursorIdKey (e.g. idKey: 'id', cursorIdKey: 'ID').`)\n isContinue = false\n break\n }\n } while (isContinue)\n\n return result.setData(allItems)\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @package @bitrix24/b24jssdk
3
- * @version 1.2.0
3
+ * @version 1.3.0
4
4
  * @copyright (c) 2026 Bitrix24
5
5
  * @license MIT
6
6
  * @see https://github.com/bitrix24/b24jssdk