UNPKG

@bitrix24/b24jssdk

Version:

Bitrix24 REST API JavaScript SDK

113 lines (109 loc) 5.73 kB
/** * @package @bitrix24/b24jssdk * @version 2.0.0 * @copyright (c) 2026 Bitrix24 * @license MIT * @see https://github.com/bitrix24/b24jssdk * @see https://bitrix24.github.io/b24jssdk/ */ 'use strict'; const abstractAction = require('../abstract-action.cjs'); const sdkError = require('../../sdk-error.cjs'); const _keysetPaginate = require('./_keyset-paginate.cjs'); var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); class FetchTailV3 extends abstractAction.AbstractAction { static { __name(this, "FetchTailV3"); } /** * Streams every record of a `tail` method as chunks, advancing the keyset * cursor between requests. * * @template T - The type of items in the returned arrays (default is `unknown`). * * @param {ActionFetchTailV3} options - parameters for executing the request. * - `method: string` - A REST API `tail` method name (for example: `main.eventlog.tail`). * - `params?: Omit<TypeCallParams, 'pagination' | 'order' | 'cursor'>` - Request parameters. * Use `filter` and `select` to control the selection. `pagination`, `order` and `cursor` * are managed by this helper and must not be passed. The cursor field must NOT be used in `filter`. * - `cursorField?: string` - The DTO field that drives the cursor. Must be monotonic and * preferably unique, and present in `select`. Default is `id`. * - `order?: 'ASC' | 'DESC'` - Cursor direction. Default is `ASC`. For `DESC` you MUST pass * `initialValue` (the server pages by `field < value`, so the default `0` returns nothing). * - `customKeyForResult?: string` - The key the response groups rows under. Default is `items`. * - `requestId?: string` - Unique request identifier for tracking. * - `limit?: number` - How many records to retrieve at a time. Default is `50`. Maximum is `1000`. * - `initialValue?: number | string` - Cursor start value for the first page. Default is `0` * (valid for ascending numeric fields); required for `DESC` and for non-numeric fields. * * @returns {AsyncGenerator<T[]>} An async generator that yields chunks of data as arrays of type `T`. * * @example * const generator = b24.actions.v3.fetchTail.make<{ id: string }>({ * method: 'main.eventlog.tail', * params: { select: ['id', 'auditType'] }, * cursorField: 'id', * customKeyForResult: 'items' * }) * for await (const chunk of generator) { * console.log(`Processing ${chunk.length} items`) * } */ async *make(options) { const batchSize = options?.limit ?? 50; const cursorField = options?.cursorField ?? "id"; const order = options?.order ?? "ASC"; const customKeyForResult = options?.customKeyForResult ?? "items"; const params = options?.params ?? {}; if (/desc/i.test(order) && options?.initialValue === void 0) { throw new sdkError.SdkError({ code: "JSSDK_CORE_B24_FETCH_TAIL_DESC_REQUIRES_INITIAL_VALUE", description: 'fetchTail.make: order "DESC" requires an explicit `initialValue` (the server pages by `field < value`, so the default 0 returns nothing). Pass `initialValue` set to the type maximum / newest value.', status: 500 }); } if (Array.isArray(params["filter"]) && params["filter"].some((c) => Array.isArray(c) && c[0] === cursorField)) { this._logger.warning(`fetchTail.make: the cursor field "${cursorField}" must not appear in \`filter\` \u2014 the server orders and pages by it and will reject a filter on the same field (INVALIDFILTEREXCEPTION). Remove it from \`filter\`.`); } let select = params["select"]; if (Array.isArray(select)) { if (!select.includes(cursorField)) { select = [...select, cursorField]; } } else if (cursorField !== "id") { this._logger.warning(`fetchTail.make: no \`select\` provided with a non-default cursorField "${cursorField}" \u2014 make sure it is in the server's default field set, otherwise pass \`select\` including "${cursorField}" so the cursor can advance.`); } const { select: _ignoredSelect, ...restParams } = params; try { yield* _keysetPaginate.keysetPaginate(this._b24, this._logger, { method: options.method, requestId: options.requestId, customKeyForResult, initialCursor: options?.initialValue ?? 0, // Native keyset: drive the server's `cursor: { field, value, order, limit }`. buildParams: /* @__PURE__ */ __name((cursor) => ({ ...restParams, ...select ? { select } : {}, cursor: { field: cursorField, value: cursor, order, limit: batchSize } }), "buildParams"), // Advance by the raw cursor-field value from the last item; a missing // value (cursorField not selected / wrong name) stops the walk. readNextCursor: /* @__PURE__ */ __name((lastItem) => lastItem[cursorField] ?? null, "readNextCursor"), noCursorWarning: `fetchTail.make: pagination stops here \u2014 no value could be read from the returned items via cursorField "${cursorField}". Make sure cursorField matches a field present in the response (and in \`select\`).`, errorLabel: "fetchTailMethod" }); } catch (error) { if (error instanceof _keysetPaginate.KeysetPaginationError) { throw new sdkError.SdkError({ code: "JSSDK_CORE_B24_FETCH_TAIL_METHOD_API_V3", description: `API Error: ${error.messages.join("; ")}`, status: 500 }); } throw error; } } } exports.FetchTailV3 = FetchTailV3; //# sourceMappingURL=fetch-tail.cjs.map