UNPKG

@bitrix24/b24jssdk

Version:

Bitrix24 REST API JavaScript SDK

118 lines (115 loc) • 4.81 kB
/** * @package @bitrix24/b24jssdk * @version 3.0.0 * @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 { Result } from '../../result.mjs'; import { SdkError } from '../../sdk-error.mjs'; var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); const AGGREGATE_FUNCTIONS = ["sum", "avg", "min", "max", "count", "countDistinct"]; class AggregateV3 extends AbstractAction { static { __name(this, "AggregateV3"); } /** * @param {ActionAggregateV3} options * - `method: string` - an `*.aggregate` method name. * - `select: AggregateSelectV3` - per-function field selection (`sum`/`avg`/`min`/`max`/`count`/`countDistinct`). * - `params?: { filter }` - optional v3 filter (array-of-triples; use `FilterV3` to build it). * - `requestId?: string` - tracking id. * * @returns {Promise<Result<AggregateResultV3>>} buckets keyed by function then field name. * * @check-ignore: `some.entity.aggregate` is a placeholder, not a portal method * * @example * import { FilterV3, Text } from '@bitrix24/b24jssdk' * * const response = await b24.actions.v3.aggregate.make({ * method: 'some.entity.aggregate', * select: { sum: ['amount'], count: ['id'] }, * params: { filter: FilterV3.build(FilterV3.eq('status', 'NEW')) } * }) * if (response.isSuccess) { * // Buckets are keyed by function then FIELD name — an alias, if you pass * // one, never appears in the answer. * const rows = Text.toNumber(response.getData()?.count?.id ?? 0) * // `sum` is a string, and `null` when the filter matched nothing. Convert * // deliberately: a money total through a float is a rounding you cannot undo. * const rawTotal = response.getData()?.sum?.amount ?? null * } */ async make(options) { const result = new Result(); const select = options?.select ?? {}; const functions = Object.keys(select); let columns = 0; for (const fn of functions) { if (!AGGREGATE_FUNCTIONS.includes(fn)) { throw new SdkError({ code: "JSSDK_AGGREGATE_V3_INVALID_FUNCTION", description: `AggregateV3: "${fn}" is not an aggregate function \u2014 use one of ${AGGREGATE_FUNCTIONS.join(" ")}.`, status: 400 }); } const fields = select[fn]; if (!Array.isArray(fields) && (typeof fields !== "object" || fields === null)) { throw new SdkError({ code: "JSSDK_AGGREGATE_V3_INVALID_SELECT", description: `AggregateV3: select.${fn} must be a string[] (default alias) or a { field: alias } map.`, status: 400 }); } columns += Array.isArray(fields) ? fields.length : Object.keys(fields).length; } if (columns === 0) { throw new SdkError({ code: "JSSDK_AGGREGATE_V3_EMPTY_SELECT", description: "AggregateV3: `select` names no field to aggregate, e.g. { count: ['id'] }. The portal answers such a request with a 500 that says nothing, so it is refused here.", status: 400 }); } const params = { select }; if (options?.params?.filter) { params.filter = options.params.filter; } const response = await this._b24.actions.v3.call.make({ method: options.method, params, requestId: options.requestId }); if (!response.isSuccess) { this._logger.error("aggregateMethod", { method: options.method, requestId: options.requestId, messages: response.getErrorMessages() }).catch(() => { }); for (const [index, error] of response.errors) { result.addError(error, index); } return result; } const payload = response.getData()?.result; let buckets; if (payload && typeof payload === "object" && "result" in payload) { buckets = payload.result ?? {}; } else if (payload && typeof payload === "object") { this._logger.warning(`aggregate.make: response has no nested 'result.result' envelope, which is what a portal was measured to send and what the v3 reference \xA77 specifies; falling back to the top-level 'result'. method=${options.method}`).catch(() => { }); buckets = payload; } else { this._logger.warning(`aggregate.make: response carried no usable 'result' object \u2014 returning empty buckets, which is not the same as an aggregate over no rows (that answers null per function). method=${options.method}`).catch(() => { }); buckets = {}; } return result.setData(buckets); } } export { AggregateV3 }; //# sourceMappingURL=aggregate.mjs.map