@bitrix24/b24jssdk
Version:
Bitrix24 REST API JavaScript SDK
1 lines • 38.5 kB
Source Map (JSON)
{"version":3,"file":"deferred-batch.cjs","sources":["../../../../../src/core/actions/v3/deferred-batch.ts"],"sourcesContent":["import type { BatchCommandsUniversal, CommandObject, CommandTuple } from '../../../types/http'\nimport type { AjaxResult } from '../../http/ajax-result'\nimport { AbstractAction } from '../abstract-action'\nimport { ApiVersion } from '../../../types/b24'\nimport { Result } from '../../result'\nimport { SdkError } from '../../sdk-error'\nimport { ParseRow } from '../../interaction/batch/parse-row'\n\n/**\n * Where a deferred batch job is. `pending` and `processing` are still running;\n * `done` and `error` are final. All four are observed live (#570). Any other\n * value is treated as still running until `timeout`.\n */\nexport type DeferredBatchStatus = 'pending' | 'processing' | 'done' | 'error'\n\n/**\n * A deferred batch job as the portal describes it (`bitrix.rest.deferredbatchdto`).\n */\nexport interface DeferredBatchJob {\n id: number\n status: DeferredBatchStatus\n /** The commands as the portal stored them: `{ method, query }` each. */\n /** Not included by `list`. An empty query comes back as `[]` (a PHP empty array). */\n commands?: Array<{ method: string, query: Record<string, unknown> | unknown[] }>\n createdAt?: string\n updatedAt?: string\n /** Set once the job is `done`: the disk file that holds the results. */\n resultFileId?: number | null\n /** Set when the job is `error`. */\n errorMessage?: string | null\n}\n\n/**\n * Commands for a deferred batch: `[['method', params], …]`, `[{ method, params }, …]`,\n * or the two mixed. Named commands are not supported: the result file is an\n * array in command order.\n */\nexport type DeferredBatchCalls = BatchCommandsUniversal\n\nexport type ActionDeferredBatchAddV3 = {\n calls: DeferredBatchCalls\n /**\n * `Idempotency-Key` for the `add` call. `add` is a create call, so the\n * portal's idempotency rules apply (a repeat with the same key and body\n * replays the first answer) — observed only as far as the key being echoed;\n * a repeat was not measured for deferred batches. Give each run its own key:\n * by the same contract, a key reused after the job was deleted would replay\n * the id of a job that no longer exists.\n */\n idempotencyKey?: string\n requestId?: string\n}\n\nexport type ActionDeferredBatchWaitV3 = {\n /** Milliseconds between two `get` calls. Default `2000`, minimum `250`. */\n pollInterval?: number\n /** Milliseconds to wait for a final status before giving up. Default `600000` (10 minutes). */\n timeout?: number\n /** Stops waiting when aborted. The job itself keeps running on the portal. */\n signal?: AbortSignal\n /** Called with the job every time its status changes, the first status included. */\n onStatus?: (job: DeferredBatchJob) => void\n}\n\nexport type ActionDeferredBatchV3 = ActionDeferredBatchAddV3 & ActionDeferredBatchWaitV3 & {\n /**\n * Delete the job — and with it the result file — once its rows are read.\n * Default `true`. Set `false` to keep it, e.g. to download the file again.\n */\n deleteAfter?: boolean\n}\n\nconst DEFAULT_POLL_INTERVAL = 2_000\nconst MIN_POLL_INTERVAL = 250\nconst DEFAULT_TIMEOUT = 600_000\nconst MAX_TIMER_DELAY = 2_147_483_647\n\n/**\n * Deferred (background) batch for large command sets. `restApi:v3`\n *\n * The portal takes all commands in one `rest.deferredbatch.add` call — thousands\n * of them, well past the 50 of a synchronous `batch` — runs them in the\n * background, and stores the results as a gzip-compressed JSON file. This action\n * wraps the `rest.deferredbatch.*` family:\n *\n * - {@link DeferredBatchV3.make} does everything in one call: add, wait with a\n * status callback, download, decode, delete — and resolves with the rows.\n * - {@link DeferredBatchV3.add}, {@link DeferredBatchV3.get},\n * {@link DeferredBatchV3.waitFor}, {@link DeferredBatchV3.download},\n * {@link DeferredBatchV3.delete} and {@link DeferredBatchV3.list} are the\n * single steps, for when you run the flow yourself (a job started in one\n * request and collected in another, a queue worker, a UI with its own polling).\n * - {@link DeferredBatchV3.decode} turns the downloaded bytes into rows.\n *\n * A row is what that command returned, in command order — the same shape as\n * one entry of a synchronous v3 `batch` result (`{ item }`, `{ items }`, …).\n *\n * Measured on the portal (#570):\n * - **v3 methods only.** A v2 or unknown method is refused at `add` with\n * `INVALID_METHOD`, and no job is created.\n * - **All or nothing.** One failing command (a `get` of a missing record)\n * ends the whole job in `error` with no result file — there are no partial\n * rows. Build commands that cannot fail on data, e.g. list pages rather than\n * a `get` per id.\n * - **Duration depends on the method.** 5000 cheap `get`s took seconds; 500\n * `rest.scope.list` took over 15 minutes.\n * - **A running job cannot be deleted** (`BATCH_PROCESSING`).\n *\n * Needs a portal plan that includes deferred batches; on other plans every\n * call answers `FEATURE_NOT_AVAILABLE_ON_CURRENT_PLAN`. The whole result file is\n * held in memory while it is decoded.\n */\nexport class DeferredBatchV3 extends AbstractAction {\n /**\n * Runs a deferred batch end to end and resolves with its rows.\n *\n * Adds the job, polls it until it is `done` or `error` (calling `onStatus` on\n * every change), downloads and decodes the result file, and deletes the job\n * unless `deleteAfter: false`. Never throws for what the portal answered:\n * check `isSuccess` on the returned `Result`. Throws only for malformed\n * `calls`, before anything is sent.\n *\n * @template T - The type of one row (one command's result).\n *\n * @param {ActionDeferredBatchV3} options\n * - `calls` - the commands, `[['method', params], …]` or `[{ method, params }, …]`.\n * - `idempotencyKey?` - sent with `add`; use one per run, so that — per the portal's\n * idempotency contract, not measured for deferred batches — a retry of an interrupted\n * `make()` does not start a second job.\n * - `requestId?` - sent as `bx24_request_id` on the `add` call.\n * - `pollInterval?` - ms between status checks (default 2000).\n * - `timeout?` - ms to wait for a final status (default 600000).\n * - `signal?` - `AbortSignal` that stops waiting.\n * - `onStatus?` - `(job) => void`, called on every status change.\n * - `deleteAfter?` - delete the job after reading it (default `true`).\n *\n * @returns {Promise<Result<T[]>>} The rows in command order. On failure the\n * `Result` carries the errors, each naming the job id:\n * - `JSSDK_DEFERRED_BATCH_FAILED` when the job ended in `error` — the\n * portal's `errorMessage` is logged and the job is deleted unless\n * `deleteAfter: false`;\n * - `JSSDK_DEFERRED_BATCH_TIMEOUT` / `JSSDK_DEFERRED_BATCH_ABORTED` when\n * waiting stopped — the job keeps running (and cannot be deleted while\n * it does), so collect it later with {@link DeferredBatchV3.waitFor};\n * - a download error.\n * `onStatus` also receives the job as soon as `add` returns it. An\n * already-aborted `signal` adds nothing.\n * @throws {SdkError} `JSSDK_DEFERRED_BATCH_EMPTY` for an empty `calls`,\n * `JSSDK_INTERACTION_BATCH_ROW_FAIL` for a command that is neither a\n * tuple nor a `{ method, params }` object.\n *\n * @example\n * import type { BatchCommandsArrayUniversal } from '@bitrix24/b24jssdk'\n *\n * // 200 pages of 50 tasks: a list page cannot fail on a missing record the\n * // way a `get` per id can, and one failing command fails the whole job.\n * const calls: BatchCommandsArrayUniversal = Array.from({ length: 200 }, (_, i) =>\n * ['tasks.task.list', { select: ['id', 'title'], order: { id: 'ASC' }, pagination: { page: i + 1, limit: 50 } }]\n * )\n *\n * const response = await $b24.actions.v3.deferredBatch.make<{ items: Array<{ id: number, title: string }> }>({\n * calls,\n * onStatus: job => console.log(`deferred batch #${job.id}: ${job.status}`)\n * })\n *\n * if (!response.isSuccess) {\n * throw new Error(response.getErrorMessages().join('; '))\n * }\n * const titles = response.getData()!.flatMap(row => row.items.map(task => task.title))\n * console.log(`${titles.length} tasks read`)\n */\n public override async make<T = unknown>(options: ActionDeferredBatchV3): Promise<Result<T[]>> {\n const result = new Result<T[]>()\n\n // Malformed `calls` throw first, whatever the signal says: that is a bug in\n // the caller, and an abort must not hide it. Then nothing is added once the\n // caller has given up already.\n this.#toCommands(options.calls)\n if (options.signal?.aborted) {\n return result.addError(abortedError(), 'base-error')\n }\n\n const added = await this.add(options)\n if (!added.isSuccess) {\n return this.#carryErrors(added, result)\n }\n const job = added.getData()!\n const id = job.id\n\n // The new job goes to `onStatus` at once, so its id reaches the caller even\n // if waiting ends before the first status check — an abort, a failed `get`.\n this.#reportStatus(options.onStatus, job, id)\n\n const finished = await this.#wait(id, options, job.status)\n if (!finished.isSuccess) {\n // A job that ended in `error` is final and has no result file, so it can\n // be deleted like a finished one; the portal's reason is logged, since\n // the `Result` here carries no job. A timed-out or aborted job is still\n // running and cannot be deleted — its id is in the error.\n if (finished.getData()?.status === 'error') {\n this._logger.warning('deferredBatch: the job ended with status \"error\"', {\n id,\n errorMessage: finished.getData()?.errorMessage\n }).catch(() => {})\n if (options.deleteAfter !== false) {\n await this.#deleteQuietly(id)\n }\n }\n return this.#carryErrors(finished, result)\n }\n\n const rows = await this.download<T>(id)\n if (!rows.isSuccess) {\n return this.#carryErrors(rows, result)\n }\n\n if (options.deleteAfter !== false) {\n await this.#deleteQuietly(id)\n }\n\n return result.setData(rows.getData())\n }\n\n /** A failed delete does not spoil the outcome already known: it is logged. */\n async #deleteQuietly(id: number): Promise<void> {\n const deleted = await this.delete(id)\n if (!deleted.isSuccess) {\n this._logger.warning('deferredBatch: the job could not be deleted', {\n id,\n errors: deleted.getErrorMessages()\n }).catch(() => {})\n }\n }\n\n /**\n * Adds a deferred batch job (`rest.deferredbatch.add`). The portal starts it\n * in the background; read its progress with {@link DeferredBatchV3.get} or\n * wait for it with {@link DeferredBatchV3.waitFor}.\n *\n * @param {ActionDeferredBatchAddV3} options - `calls`, and optionally `idempotencyKey` and `requestId`.\n * @returns {Promise<Result<DeferredBatchJob>>} The new job, usually `pending`.\n *\n * @example\n * const added = await $b24.actions.v3.deferredBatch.add({\n * calls: [\n * ['tasks.task.list', { select: ['id'], pagination: { page: 1, limit: 50 } }],\n * ['tasks.task.list', { select: ['id'], pagination: { page: 2, limit: 50 } }]\n * ],\n * idempotencyKey: 'nightly-export-2026-09-26'\n * })\n * const jobId = added.getData()!.id // keep it, e.g. in your queue\n */\n public async add(options: ActionDeferredBatchAddV3): Promise<Result<DeferredBatchJob>> {\n const commands = this.#toCommands(options.calls)\n return this.#call<{ item: DeferredBatchJob }, DeferredBatchJob>(\n 'rest.deferredbatch.add',\n { fields: { commands } },\n payload => payload.item,\n options.requestId,\n options.idempotencyKey\n )\n }\n\n /**\n * Reads one job (`rest.deferredbatch.get`).\n *\n * @param {number} id - The job id from {@link DeferredBatchV3.add}.\n * @returns {Promise<Result<DeferredBatchJob>>}\n *\n * @example\n * declare const jobId: number\n * const job = (await $b24.actions.v3.deferredBatch.get(jobId)).getData()!\n * if (job.status === 'done') {\n * // ready to download\n * }\n */\n public async get(id: number): Promise<Result<DeferredBatchJob>> {\n return this.#call<{ item: DeferredBatchJob }, DeferredBatchJob>('rest.deferredbatch.get', { id }, payload => payload.item)\n }\n\n /**\n * Lists the caller's deferred batch jobs (`rest.deferredbatch.list`).\n * Measured: `{ items }`, whose items carry no `commands`. Which jobs it\n * includes is the portal's rule.\n *\n * @returns {Promise<Result<DeferredBatchJob[]>>}\n */\n public async list(): Promise<Result<DeferredBatchJob[]>> {\n // Measured as `{ items }` (and once, empty, as `[]`). Both are read, and\n // anything else is an error rather than an empty list.\n return this.#call<DeferredBatchJob[] | { items?: DeferredBatchJob[] }, DeferredBatchJob[]>(\n 'rest.deferredbatch.list',\n {},\n payload => Array.isArray(payload) ? payload : (Array.isArray(payload.items) ? payload.items : undefined)\n )\n }\n\n /**\n * Polls a job until it is `done` or `error`.\n *\n * Resolves successfully only for `done`. For `error` the `Result` carries\n * `JSSDK_DEFERRED_BATCH_FAILED` with the portal's `errorMessage`, and the job\n * as data. A timeout or an aborted `signal` stops waiting — not the job.\n *\n * @param {number} id - The job id.\n * @param {ActionDeferredBatchWaitV3} options - `pollInterval`, `timeout`, `signal`, `onStatus`.\n * @returns {Promise<Result<DeferredBatchJob>>} The job in its final state.\n *\n * @example\n * declare const jobId: number\n * declare const progressBar: { setLabel(text: string): void }\n * const controller = new AbortController()\n * const finished = await $b24.actions.v3.deferredBatch.waitFor(jobId, {\n * pollInterval: 5_000,\n * signal: controller.signal,\n * onStatus: job => progressBar.setLabel(job.status)\n * })\n */\n public async waitFor(id: number, options: ActionDeferredBatchWaitV3 = {}): Promise<Result<DeferredBatchJob>> {\n return this.#wait(id, options, undefined)\n }\n\n async #wait(\n id: number,\n options: ActionDeferredBatchWaitV3,\n reportedStatus: DeferredBatchStatus | undefined\n ): Promise<Result<DeferredBatchJob>> {\n // Capped too: `setTimeout` wraps a delay above 2^31-1 ms to about 1 ms.\n const pollInterval = Math.min(MAX_TIMER_DELAY, Math.max(MIN_POLL_INTERVAL, finiteOr(options.pollInterval, DEFAULT_POLL_INTERVAL)))\n // `Infinity` is allowed (wait until `signal` aborts); only NaN falls back.\n const timeout = Math.max(0, typeof options.timeout === 'number' && !Number.isNaN(options.timeout) ? options.timeout : DEFAULT_TIMEOUT)\n const deadline = Date.now() + timeout\n const result = new Result<DeferredBatchJob>()\n let lastStatus = reportedStatus\n\n for (;;) {\n if (options.signal?.aborted) {\n return result.addError(abortedError(id), 'base-error')\n }\n\n const current = await this.get(id)\n if (!current.isSuccess) {\n return this.#carryErrors(current, result)\n }\n const job = current.getData()!\n\n if (job.status !== lastStatus) {\n lastStatus = job.status\n this.#reportStatus(options.onStatus, job, id)\n }\n\n if (job.status === 'done') {\n return result.setData(job)\n }\n if (job.status === 'error') {\n result.setData(job)\n return result.addError(new SdkError({\n code: 'JSSDK_DEFERRED_BATCH_FAILED',\n // Static text: the portal's own `errorMessage` stays on the job\n // (`getData().errorMessage`), since an `SdkError` description is not\n // redacted and that message is free text.\n description: `deferredBatch: job #${id} ended with status \"error\"; see the job's errorMessage (waitFor / get).`,\n status: 500\n }), 'base-error')\n }\n if (Date.now() + pollInterval > deadline) {\n return result.addError(new SdkError({\n code: 'JSSDK_DEFERRED_BATCH_TIMEOUT',\n description: `deferredBatch: job #${id} reached no final status within ${timeout} ms; it keeps running on the portal.`,\n status: 408\n }), 'base-error')\n }\n\n await this.#sleep(pollInterval, options.signal)\n }\n }\n\n /**\n * Gets the result file's download link (`rest.deferredbatch.downloadresult`).\n *\n * **The link is a credential**: on a webhook it contains the webhook secret,\n * on OAuth (per the portal's code, not yet measured) an access token. Do not log it or send it anywhere you would not\n * send those. Most callers want {@link DeferredBatchV3.download} instead.\n *\n * @param {number} id - The job id. The job must be `done`.\n * @returns {Promise<Result<string>>} The absolute URL of the `.json.gz` file.\n */\n public async getDownloadUrl(id: number): Promise<Result<string>> {\n return this.#call<{ downloadUrl: string }, string>('rest.deferredbatch.downloadresult', { id }, payload => payload.downloadUrl)\n }\n\n /**\n * Downloads a finished job's result file and decodes it into rows.\n *\n * @template T - The type of one row.\n * @param {number} id - The job id. The job must be `done`.\n * @returns {Promise<Result<T[]>>} The rows in command order.\n *\n * @example\n * declare const jobId: number\n * const rows = await $b24.actions.v3.deferredBatch.download<{ item: { id: number } }>(jobId)\n * console.log(rows.getData()!.length)\n */\n public async download<T = unknown>(id: number): Promise<Result<T[]>> {\n const result = new Result<T[]>()\n const link = await this.getDownloadUrl(id)\n if (!link.isSuccess) {\n return this.#carryErrors(link, result)\n }\n\n let bytes: ArrayBuffer\n try {\n // Through the SDK's own HTTP client, so a caller's proxy / agent settings\n // apply. `maxRedirects: 0`: the URL is a credential and must not be\n // carried to wherever a redirect points.\n const response = await this._b24.getHttpClient(ApiVersion.v3).ajaxClient.get<ArrayBuffer>(link.getData()!, {\n responseType: 'arraybuffer',\n maxRedirects: 0\n })\n // A refused redirect on the fetch adapter is an opaque response with\n // status 0, which axios resolves instead of rejecting.\n if (!response.status) {\n return result.addError(new SdkError({\n code: 'JSSDK_DEFERRED_BATCH_DOWNLOAD_FAILED',\n description: 'deferredBatch: the result file could not be downloaded (no status: a refused redirect or a dropped connection).',\n status: 0\n }), 'base-error')\n }\n bytes = response.data\n } catch (error) {\n // The URL is deliberately left out of the error: it carries the secret.\n const status = Number((error as { response?: { status?: number } })?.response?.status ?? 0)\n return result.addError(new SdkError({\n code: 'JSSDK_DEFERRED_BATCH_DOWNLOAD_FAILED',\n description: `deferredBatch: the result file could not be downloaded (HTTP ${status || 'no response'}).`,\n status: status || 500\n }), 'base-error')\n }\n\n try {\n return result.setData(await this.decode(bytes) as T[])\n } catch (error) {\n return result.addError(error instanceof Error ? error : new Error(String(error)), 'base-error')\n }\n }\n\n /**\n * Decodes the bytes of a result file into rows: gunzips them (the file is\n * `application/gzip`) and parses the JSON array inside. Bytes that are not\n * gzip — a proxy that already inflated them — are parsed as they are.\n *\n * Uses the standard `DecompressionStream`, available in Node.js 18+ and every\n * current browser.\n *\n * @param {ArrayBuffer | Uint8Array} bytes - The file contents.\n * @returns {Promise<unknown[]>} The rows.\n * @throws {SdkError} `JSSDK_DEFERRED_BATCH_DECODE_FAILED` when the content is\n * not a JSON array, `JSSDK_DEFERRED_BATCH_GZIP_UNSUPPORTED` when the\n * runtime has no `DecompressionStream`.\n *\n * @example\n * declare const bytes: Uint8Array\n * // The file was fetched some other way, e.g. by a separate worker. If you\n * // fetch the link yourself, refuse redirects (`redirect: 'error'`): the link\n * // is a credential.\n * const rows = await $b24.actions.v3.deferredBatch.decode(bytes)\n */\n public async decode(bytes: ArrayBuffer | Uint8Array): Promise<unknown[]> {\n const data = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes)\n const isGzip = data.length >= 2 && data[0] === 0x1F && data[1] === 0x8B\n const text = new TextDecoder().decode(isGzip ? await gunzip(data) : data)\n\n let parsed: unknown\n try {\n parsed = JSON.parse(text)\n } catch {\n parsed = undefined\n }\n if (!Array.isArray(parsed)) {\n throw new SdkError({\n code: 'JSSDK_DEFERRED_BATCH_DECODE_FAILED',\n description: 'deferredBatch: the result file is not a JSON array.',\n status: 500\n })\n }\n return parsed\n }\n\n /**\n * Deletes a job and its result file (`rest.deferredbatch.delete`). The\n * download link stops working. A job that is still `processing` cannot be\n * deleted: the portal answers `BATCH_PROCESSING`.\n *\n * @param {number} id - The job id.\n * @returns {Promise<Result<boolean>>}\n */\n public async delete(id: number): Promise<Result<boolean>> {\n // Measured: `{ result: true }`. Any success counts, so a shape change on the\n // portal side does not turn a completed delete into a reported failure.\n return this.#call<unknown, boolean>('rest.deferredbatch.delete', { id }, () => true, undefined, undefined, false)\n }\n\n #toCommands(calls: DeferredBatchCalls): Array<{ method: string, query: Record<string, unknown> }> {\n if (!Array.isArray(calls) || calls.length === 0) {\n throw new SdkError({\n code: 'JSSDK_DEFERRED_BATCH_EMPTY',\n description: 'deferredBatch: `calls` must be a non-empty array of commands.',\n status: 400\n })\n }\n return (calls as Array<CommandObject | CommandTuple>).map((row) => {\n const command = ParseRow.getBatchCommand(row, { parallelDefaultValue: false })\n return { method: command.method, query: (command.query ?? {}) as Record<string, unknown> }\n })\n }\n\n /**\n * One `rest.deferredbatch.*` call, as a `Result`. A portal refusal on v3 (a\n * 403 for a plan without the feature) already comes back as a failed\n * `AjaxResult`; anything the transport throws instead — a key it refuses\n * before sending, a network error after its retries — becomes an error on\n * the `Result` too, so `make()` and the steps never throw for either.\n */\n async #call<P, D>(\n method: string,\n params: Record<string, unknown>,\n pick: (payload: P) => D | undefined,\n requestId?: string,\n idempotencyKey?: string,\n requireResult = true\n ): Promise<Result<D>> {\n const result = new Result<D>()\n let response: AjaxResult<P>\n try {\n response = await this._b24.getHttpClient(ApiVersion.v3).call<P>(\n method,\n params,\n requestId,\n undefined === idempotencyKey ? undefined : { idempotencyKey }\n )\n } catch (error) {\n return result.addError(error instanceof Error ? error : new Error(String(error)), 'base-error')\n }\n if (!response.isSuccess) {\n return this.#carryErrors(response, result)\n }\n const data = response.getData()?.result\n const picked = data === undefined || data === null ? (requireResult ? undefined : pick(data as P)) : pick(data)\n if (picked === undefined || picked === null) {\n return result.addError(new SdkError({\n code: 'JSSDK_DEFERRED_BATCH_UNEXPECTED_RESPONSE',\n description: `deferredBatch: ${method} answered without the expected data.`,\n status: 500\n }), 'base-error')\n }\n return result.setData(picked)\n }\n\n /**\n * Calls `onStatus`. A throwing callback — or an async one that rejects — must\n * not stop the wait, lose the job, or surface as an unhandled rejection.\n */\n #reportStatus(onStatus: ((job: DeferredBatchJob) => void) | undefined, job: DeferredBatchJob, id: number): void {\n const report = (error: unknown) => {\n this._logger.warning('deferredBatch: onStatus threw', { id, error: String(error) }).catch(() => {})\n }\n try {\n const returned: unknown = onStatus?.(job)\n if (returned && typeof (returned as PromiseLike<unknown>).then === 'function') {\n Promise.resolve(returned).catch(report)\n }\n } catch (error) {\n report(error)\n }\n }\n\n #carryErrors<D>(from: Result<unknown>, to: Result<D>): Result<D> {\n for (const [key, error] of from.errors) {\n to.addError(error, key)\n }\n return to\n }\n\n #sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n if (signal?.aborted) {\n resolve()\n return\n }\n const timer = setTimeout(done, ms)\n function done() {\n clearTimeout(timer)\n signal?.removeEventListener('abort', done)\n resolve()\n }\n signal?.addEventListener('abort', done, { once: true })\n })\n }\n}\n\nfunction abortedError(id?: number): SdkError {\n return new SdkError({\n code: 'JSSDK_DEFERRED_BATCH_ABORTED',\n description: undefined === id\n ? 'deferredBatch: aborted before anything was added.'\n : `deferredBatch: waiting for job #${id} was aborted; it keeps running on the portal.`,\n status: 499\n })\n}\n\nfunction finiteOr(value: number | undefined, fallback: number): number {\n return typeof value === 'number' && Number.isFinite(value) ? value : fallback\n}\n\nasync function gunzip(data: Uint8Array): Promise<Uint8Array> {\n if (typeof DecompressionStream !== 'function') {\n throw new SdkError({\n code: 'JSSDK_DEFERRED_BATCH_GZIP_UNSUPPORTED',\n description: 'deferredBatch: this runtime has no DecompressionStream, so the gzip result file cannot be decoded. Use Node.js 18+ or a current browser.',\n status: 500\n })\n }\n try {\n const stream = new Blob([data as BlobPart]).stream().pipeThrough(new DecompressionStream('gzip'))\n return new Uint8Array(await new Response(stream).arrayBuffer())\n } catch {\n throw new SdkError({\n code: 'JSSDK_DEFERRED_BATCH_DECODE_FAILED',\n description: 'deferredBatch: the result file is not valid gzip.',\n status: 500\n })\n }\n}\n"],"names":["AbstractAction","result","Result","SdkError","ApiVersion","ParseRow"],"mappings":"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"}