@bitrix24/b24jssdk
Version:
Bitrix24 REST API JavaScript SDK
133 lines (130 loc) • 5.07 kB
JavaScript
/**
* @package @bitrix24/b24jssdk
* @version 1.0.5
* @copyright (c) 2026 Bitrix24
* @license MIT
* @see https://github.com/bitrix24/b24jssdk
* @see https://bitrix24.github.io/b24jssdk/
*/
import { AbstractAction } from '../abstract-action.mjs';
import { SdkError } from '../../sdk-error.mjs';
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
class FetchListV2 extends AbstractAction {
static {
__name(this, "FetchListV2");
}
/**
* Calls a REST API list method and returns an async generator for efficient large data retrieval.
* Implements the fast algorithm for iterating over large datasets without loading all data into memory at once.
*
* @template T - The type of items in the returned arrays (default is `unknown`).
*
* @param {ActionFetchListV2} options - parameters for executing the request.
* - `method: string` - The name of the REST API method that returns a list of data (for example: `crm.item.list`, `tasks.task.list`)
* - `params?: Omit<TypeCallParams, 'start'>` - Request parameters, excluding the `start` parameter,
* since the method is designed to obtain all data in one call.
* Note: Use `filter`, `order`, and `select` to control the selection.
* - `idKey?: string` - The name of the field containing the unique identifier of the element.
* Default is 'ID' (uppercase). Alternatively, it can be 'id' (lowercase).
* or another field, depending on the REST API data structure.
* - `customKeyForResult?: string` - A custom key indicating that the response REST API will be
* grouped by this field.
* Example: `items` to group a list of CRM items.
* - `requestId?: string` - Unique request identifier for tracking. Used for query deduplication and debugging.
*
* @returns {AsyncGenerator<T[]>} An async generator that yields chunks of data as arrays of type `T`.
* Each iteration returns the next page/batch of results until all data is fetched.
*
* @example
* import { EnumCrmEntityTypeId, Text } from '@bitrix24/b24jssdk'
*
* interface CrmItem { id: number, title: string }
* const sixMonthAgo = new Date()
* sixMonthAgo.setMonth((new Date()).getMonth() - 6)
* sixMonthAgo.setHours(0, 0, 0)
* const generator = b24.actions.v2.fetchList.make<CrmItem>({
* method: 'crm.item.list',
* params: {
* entityTypeId: EnumCrmEntityTypeId.company,
* filter: {
* '=%title': 'A%',
* '>=createdTime': Text.toB24Format(sixMonthAgo) // created at least 6 months ago
* },
* select: ['id', 'title']
* },
* idKey: 'id',
* customKeyForResult: 'items',
* requestId: 'list-123'
* })
*
* for await (const chunk of generator) {
* // Process chunk (e.g., save to database, analyze, etc.)
* console.log(`Processing ${chunk.length} items`)
* }
*
* @see {@link https://apidocs.bitrix24.com/settings/performance/huge-data.html Bitrix24: Fast algorithm for large data}
*/
async *make(options) {
const batchSize = 50;
const idKey = options?.idKey ?? "ID";
const customKeyForResult = options?.customKeyForResult ?? null;
const params = options?.params ?? {};
const moreIdKey = `>${idKey}`;
const requestParams = {
...params,
order: { ...params["order"] || {}, [idKey]: "ASC" },
filter: { ...params["filter"] || {}, [moreIdKey]: 0 },
start: -1
};
let isContinue = true;
do {
const response = await this._b24.actions.v2.call.make({
method: options.method,
params: requestParams,
requestId: options.requestId
});
if (!response.isSuccess) {
this._logger.error("fetchListMethod", {
method: options.method,
requestId: options.requestId,
messages: response.getErrorMessages()
});
throw new SdkError({
code: "JSSDK_CORE_B24_FETCH_LIST_METHOD_API_V2",
description: `API Error: ${response.getErrorMessages().join("; ")}`,
status: 500
});
}
const responseData = response.getData();
if (!responseData) {
isContinue = false;
break;
}
let resultData = [];
if (null === customKeyForResult) {
resultData = responseData.result;
} else {
resultData = responseData.result[customKeyForResult];
}
if (resultData.length === 0) {
isContinue = false;
break;
}
yield resultData;
if (resultData.length < batchSize) {
isContinue = false;
break;
}
const lastItem = resultData[resultData.length - 1];
if (lastItem && typeof lastItem[idKey] !== "undefined") {
requestParams.filter[moreIdKey] = Number.parseInt(lastItem[idKey]);
} else {
isContinue = false;
break;
}
} while (isContinue);
}
}
export { FetchListV2 };
//# sourceMappingURL=fetch-list.mjs.map