@bitrix24/b24jssdk
Version:
Bitrix24 REST API JavaScript SDK
1 lines • 84.8 kB
Source Map (JSON)
{"version":3,"file":"abstract-http.mjs","sources":["../../../../src/core/http/abstract-http.ts"],"sourcesContent":["import type { LoggerInterface } from '../../logger'\nimport type {\n AjaxIdempotency,\n TypeCallOptions,\n TypeCallParams,\n TypeHttp,\n ICallBatchOptions,\n BatchCommandsArrayUniversal,\n BatchCommandsObjectUniversal,\n BatchNamedCommandsUniversal,\n ICallBatchResult\n} from '../../types/http'\nimport type { RestrictionManagerStats, RestrictionParams } from '../../types/limiters'\nimport type { AuthActions, AuthData } from '../../types/auth'\nimport type { AxiosInstance, AxiosRequestConfig } from 'axios'\nimport type { Result } from '../result'\nimport type { SuccessPayload } from '../../types/payloads'\nimport axios, { AxiosError } from 'axios'\nimport { LoggerFactory } from '../../logger'\nimport { RequestIdGenerator } from '../request-id-generator'\nimport { ParamsFactory } from './limiters/params-factory'\nimport { RestrictionManager } from './limiters/manager'\nimport { AjaxError } from './ajax-error'\nimport { parseErrorPayload } from './parse-error-payload'\nimport { AjaxResult } from './ajax-result'\nimport { redactSensitiveParams } from './redact'\nimport { HTTP_OPTION_KEYS, pickHttpOptions } from './http-options'\nimport { Type } from '../../tools/type'\nimport { isBrowserLikeRuntime } from '../../tools/environment'\nimport { ApiVersion } from '../../types/b24'\nimport { SdkError } from '../sdk-error'\n\n// Logger payloads are truncated so a large params / result / error body can't\n// flood a wired logger sink. Shared by the post/send, post/response, and\n// post/catchError log callsites (#236).\n// `value` is deliberately `unknown` rather than `string`: every callsite feeds it\n// `JSON.stringify(...)`, whose return type is a lying `string` — it actually\n// returns the VALUE `undefined` for `undefined`, a function, or a symbol. A\n// success body with no `result` key (`rest.documentation.openapi`) and an\n// AxiosError with no `response` (network failure, timeout, CORS) both hit that\n// case, and reading `.length` off it threw a `TypeError` from inside the logging\n// call — which the request path then re-wrapped as `JSSDK_UNKNOWN_ERROR` /\n// status 0, destroying the real error. Coercing here keeps the guarantee at the\n// one place all three callsites share, so a new callsite can't reintroduce it. (#338)\nconst LOG_MAX_LENGTH = 300\nconst LOG_SLICE_LENGTH = 100\nexport function truncateForLog(value: unknown): string {\n const text = typeof value === 'string' ? value : String(value)\n return text.length > LOG_MAX_LENGTH\n ? text.slice(0, LOG_SLICE_LENGTH) + '...'\n : text\n}\n\n/**\n * Header for a per-request idempotency key on `restApi:v3`. Sent in this\n * casing; read back case-insensitively, because the portal answers lowercased\n * and axios normalises differently per adapter.\n */\nexport const IDEMPOTENCY_KEY_HEADER = 'Idempotency-Key'\nconst IDEMPOTENCY_KEY_HEADER_LOWER = 'idempotency-key'\nconst IDEMPOTENT_REPLAYED_HEADER_LOWER = 'idempotent-replayed'\n\n/**\n * A valid idempotency key: 1-255 printable ASCII characters, no whitespace and\n * no control characters, as the portal's reference states.\n *\n * Checked before the key reaches axios so a malformed one fails as a readable\n * SDK error rather than as an opaque `ERR_INVALID_CHAR` out of Node's HTTP\n * client (or a silent rejection in a browser). The bound is the documented\n * one; a portal that later widens it would need this widened with it.\n */\nconst IDEMPOTENCY_KEY_RE = /^[\\u0021-\\u007E]{1,255}$/\n\n/**\n * Picks the two idempotency headers out of a response header bag, by\n * lowercased name.\n *\n * Deliberately two named headers rather than the whole bag: putting arbitrary\n * response headers on a public result object would also put them into every\n * wired logger sink, and the SDK does not know what a portal or a proxy in\n * front of it may add there.\n *\n * Returns `undefined` when neither header is present, so an ordinary response\n * carries no extra field at all.\n */\nexport function readIdempotencyHeaders(headers: unknown): AjaxIdempotency | undefined {\n if (null === headers || typeof headers !== 'object') {\n return undefined\n }\n\n let key: string | undefined\n let replayed: boolean | undefined\n\n for (const [name, rawValue] of Object.entries(headers as Record<string, unknown>)) {\n const lowerName = name.toLowerCase()\n\n // A repeated header name reaches us as an array through Node's http\n // adapter. Bitrix24 does not send either of these twice, but a proxy in\n // front of it may — and reading the array itself would stringify to\n // `true,true`, which matches nothing and would swallow a real replay.\n const value = Array.isArray(rawValue) ? rawValue[0] : rawValue\n\n if (IDEMPOTENCY_KEY_HEADER_LOWER === lowerName && typeof value === 'string') {\n key = value\n } else if (IDEMPOTENT_REPLAYED_HEADER_LOWER === lowerName) {\n // The portal sends the string `true`; accept the boolean too, since an\n // adapter or a test double may have parsed it already.\n replayed = true === value || 'true' === String(value).trim().toLowerCase()\n }\n }\n\n if (undefined === key && undefined === replayed) {\n return undefined\n }\n\n return { key, replayed: replayed ?? false }\n}\n\nexport type AjaxResponse<T = unknown> = {\n status: number\n payload: SuccessPayload<T>\n /** Present only when the response carried an idempotency header. */\n idempotency?: AjaxIdempotency\n}\n\nexport type TypePrepareParams = TypeCallParams & {\n data?: Record<string, any>\n auth?: string\n}\n\n/**\n * Does this runtime apply CORS to an outbound request?\n *\n * One question, one predicate: {@link isBrowserLikeRuntime}, which is true for a\n * browser and for all three worker kinds. This wrapper exists so the call sites\n * below read as the question they are actually asking — a credential decision —\n * rather than as a runtime check whose relevance the reader has to reconstruct.\n *\n * It used to probe `WorkerGlobalScope` here, beside a `getEnvironment()` that\n * called a worker a server. Two near-identical predicates invited exactly the\n * \"simplification\" that would have reopened the worker case, in a code path\n * whose failure mode is a request that never leaves the browser (#505). The\n * worker now has a name of its own, and this is a rename of that name.\n */\nfunction isCorsEnforcedRuntime(): boolean {\n return isBrowserLikeRuntime()\n}\n\n/**\n * Which axios adapter to ask for, when there is a reason to ask at all.\n *\n * Axios walks its default `['xhr', 'http', 'fetch']` and takes the first\n * supported* entry, so anywhere `XMLHttpRequest` exists — a window, a dedicated\n * worker, a shared worker — it picks **XHR** and never reaches `fetch`. That is a\n * 1999 API chosen by ordering rather than by merit: no streaming, no\n * `AbortSignal` beyond `abort()`, and headers that arrive as one folded string.\n *\n * So in a browser-like runtime this asks for `fetch` instead. Everywhere else —\n * Node, most obviously — nothing is returned and axios decides for itself: there\n * XHR does not exist, the `http` adapter is already what gets picked, and it is\n * the better one for that runtime.\n *\n * Guarded on `fetch` actually being there rather than on a version check, since\n * the point is to reach it, not to assert an era.\n *\n * **One behaviour moves with it.** The fetch adapter reads `maxRedirects`, as\n * `redirect: 'manual'`; the XHR adapter ignores it outright. The only branch that\n * sets it in a browser is the query-auth one below, which exists to stop an\n * access token following a redirect — so the change is that the guard now bites\n * where it used to be inert: a redirecting deployment gets an opaque response\n * (status 0, empty body) instead of a silent hop carrying the credential.\n *\n * Opaque is not the same as rejected. `settle` resolves any response whose\n * status is falsy *before* `validateStatus` is consulted, and unlike the XHR\n * adapter — which rejects `status === 0` as `ECONNABORTED` on its own — the\n * fetch adapter has no such guard, so that blocked redirect would otherwise\n * reach the caller as an empty **success**. `_makeAxiosRequest` states it\n * instead, on the branch that asked for `maxRedirects: 0` and nowhere else.\n *\n * Returned as a spread-able object rather than a value so \"no opinion\" and\n * \"`undefined` on purpose\" stay distinguishable, and placed **before** the\n * caller's `options` so an explicit `adapter` always wins.\n */\n/**\n * Options objects whose dropped keys have already been reported, so the second\n * transport built from the same object stays quiet. Weak, so nothing here keeps\n * a caller's config alive.\n */\nconst reportedHttpOptions = new WeakSet<object>()\n\nfunction preferredAdapter(): { adapter?: 'fetch' } {\n // `isBrowserLikeRuntime`, not `isCorsEnforcedRuntime`: the two are the same\n // predicate today, and this is not a credential decision — it asks which\n // adapter belongs in this runtime. Naming the question it asks is what keeps\n // the two free to diverge.\n if (!isBrowserLikeRuntime()) {\n return {}\n }\n\n return 'function' === typeof globalThis.fetch ? { adapter: 'fetch' } : {}\n}\n\n/**\n * Abstract base class for all Bitrix24 REST API HTTP transports.\n *\n * Provides shared infrastructure used by {@link HttpV2} and {@link HttpV3}: Axios instance\n * lifecycle, auth token management (including coalesced refresh on 401), rate/operating/adaptive\n * limiting via {@link RestrictionManager}, request-id generation, structured logging with\n * payload truncation, and request metrics. Concrete subclasses implement version-specific\n * batch strategies.\n *\n * @link https://bitrix24.github.io/b24jssdk/\n */\nexport abstract class AbstractHttp implements TypeHttp {\n protected _clientAxios: AxiosInstance\n protected _authActions: AuthActions\n protected _requestIdGenerator: RequestIdGenerator\n protected _restrictionManager: RestrictionManager\n\n /**\n * In-flight token refresh, shared so concurrent 401s coalesce into a single\n * `refreshAuth()` round-trip — avoids OAuth refresh-token reuse errors when a\n * burst of requests expires together. (#182)\n */\n protected _pendingRefresh: Promise<AuthData> | null = null\n\n protected _logger: LoggerInterface\n\n protected _isClientSideWarning: boolean = false\n protected _clientSideWarningMessage: string = ''\n\n protected _version: ApiVersion\n\n protected _metrics = {\n totalRequests: 0,\n successfulRequests: 0,\n failedRequests: 0,\n totalDuration: 0,\n byMethod: new Map<string, { count: number, totalDuration: number }>(),\n lastErrors: [] as Array<{ method: string, error: string, timestamp: number }>\n }\n\n constructor(\n authActions: AuthActions,\n options?: null | object,\n restrictionParams?: Partial<RestrictionParams>\n ) {\n this._version = ApiVersion.v2\n\n this._logger = LoggerFactory.createNullLogger()\n\n const defaultHeaders: Record<string, string> = {}\n\n if (this.isServerSide()) {\n defaultHeaders['User-Agent'] = '__SDK_USER_AGENT__/__SDK_VERSION__'\n }\n\n this._authActions = authActions\n this._requestIdGenerator = new RequestIdGenerator()\n\n // Filtered rather than spread as given: `TypeHttpOptions` names the keys a\n // caller may set, but a type cannot enforce that. Excess-property checking\n // fires only on a direct object literal with no overlapping key, so one\n // allowed key beside `transformRequest` — or a variable, or a call from\n // plain JavaScript — used to carry anything straight into axios. See\n // `pickHttpOptions`, which is also where the key list lives.\n const { picked: httpOptions, dropped: droppedHttpOptions } = pickHttpOptions(options)\n\n this._clientAxios = axios.create({\n timeout: 30_000,\n timeoutErrorMessage: 'Request timeout exceeded',\n ...preferredAdapter(),\n ...httpOptions,\n // headers last so the merged default + caller headers aren't wiped by an\n // `options.headers` (or the previous `headers: undefined`) spread (#144).\n // Read from `options` rather than from the filtered config: the merge\n // predates `TypeHttpOptions` and is left as it was. The SDK's own\n // `Content-Type` is decided per request and beats anything set here\n // (measured, lowercase spelling included); `Authorization` is per-request\n // only on the OAuth header branch, so on a webhook an instance header of\n // that name does reach the wire — which is one more reason the type does\n // not offer this key.\n headers: {\n ...defaultHeaders,\n ...((options as any)?.headers ?? {})\n }\n })\n\n // Once per options object, not once per transport: a `B24Hook` builds\n // `HttpV2` and `HttpV3` from the same object, and two identical warnings\n // naming neither transport read as a bug in the warning.\n if (droppedHttpOptions.length > 0 && !reportedHttpOptions.has(options as object)) {\n reportedHttpOptions.add(options as object)\n\n // Names only, never values: a `headers` entry a caller tried to set here\n // can carry an `Authorization` token, and this reaches whatever sink the\n // app wired up. Forced, because the default logger is silent and a\n // silently ignored option is the failure this guard exists to prevent.\n LoggerFactory.forcedLog(\n this._logger,\n 'warning',\n 'httpOptions: keys not accepted at construction were dropped',\n {\n dropped: droppedHttpOptions.join(', '),\n accepted: HTTP_OPTION_KEYS.join(', '),\n hint: 'set them on getHttpClient(version).ajaxClient.defaults instead'\n }\n ).catch(() => {})\n }\n\n /**\n * Basic parameters of restrictions\n */\n const params: RestrictionParams = {\n ...ParamsFactory.getDefault(),\n ...restrictionParams\n }\n\n this._restrictionManager = new RestrictionManager(params)\n }\n\n get apiVersion(): ApiVersion {\n return this._version\n }\n\n get ajaxClient(): AxiosInstance {\n return this._clientAxios\n }\n\n // region Logger ////\n public setLogger(logger: LoggerInterface): void {\n this._logger = logger\n this._restrictionManager.setLogger(this._logger)\n }\n\n public getLogger(): LoggerInterface {\n return this._logger\n }\n // endregion ////\n\n // region RestrictionManager ////\n public async setRestrictionManagerParams(params: RestrictionParams): Promise<void> {\n await this._restrictionManager.setConfig(params)\n }\n\n public getRestrictionManagerParams(): RestrictionParams {\n return this._restrictionManager.getParams()\n }\n\n /**\n * @inheritDoc\n */\n public getStats(): RestrictionManagerStats & {\n adaptiveDelayAvg: number\n errorCounts: Record<string, number>\n totalRequests: number\n successfulRequests: number\n failedRequests: number\n totalDuration: number\n byMethod: Map<string, { count: number, totalDuration: number }>\n lastErrors: { method: string, error: string, timestamp: number }[]\n } {\n return {\n ...this._restrictionManager.getStats(),\n totalRequests: this._metrics.totalRequests,\n successfulRequests: this._metrics.successfulRequests,\n failedRequests: this._metrics.failedRequests,\n totalDuration: this._metrics.totalDuration,\n byMethod: this._metrics.byMethod,\n lastErrors: this._metrics.lastErrors\n }\n }\n\n /**\n * @inheritDoc\n */\n public async reset(): Promise<void> {\n this._metrics.totalRequests = 0\n this._metrics.successfulRequests = 0\n this._metrics.failedRequests = 0\n this._metrics.totalDuration = 0\n this._metrics.byMethod.clear()\n this._metrics.lastErrors = []\n\n return this._restrictionManager.reset()\n }\n // endregion ////\n\n // region Metrics ////\n protected _updateMetrics(\n method: string,\n isSuccess: boolean,\n duration: number,\n error?: unknown\n ): void {\n this._metrics.totalRequests++\n\n if (isSuccess) {\n this._metrics.successfulRequests++\n } else {\n this._metrics.failedRequests++\n\n if (error instanceof AjaxError) {\n this._metrics.lastErrors.push({\n method,\n error: error.message,\n timestamp: Date.now()\n })\n\n if (this._metrics.lastErrors.length > 100) {\n this._metrics.lastErrors = this._metrics.lastErrors.slice(-100)\n }\n }\n }\n\n // Metrics by Method\n if (!this._metrics.byMethod.has(method)) {\n this._metrics.byMethod.set(method, { count: 0, totalDuration: 0 })\n }\n\n const methodMetrics = this._metrics.byMethod.get(method)!\n methodMetrics.count++\n methodMetrics.totalDuration += duration\n }\n // endregion ////\n\n // region Actions Call ////\n // region batch ////\n public abstract batch<T = unknown>(\n calls: BatchCommandsArrayUniversal | BatchCommandsObjectUniversal | BatchNamedCommandsUniversal,\n options?: ICallBatchOptions\n ): Promise<Result<ICallBatchResult<T>>>\n // endregion ////\n\n protected _validateParams(requestId: string, method: string, params: TypeCallParams): void {\n // Checking for cyclic references (especially important when logging)\n try {\n JSON.stringify(params)\n } catch (error) {\n throw new AjaxError({\n code: 'JSSDK_INVALID_PARAMS',\n description: 'Parameters contain circular references',\n status: 400,\n requestInfo: { method, params, requestId },\n originalError: error\n })\n }\n\n // Size check (It is especially important for batch)\n // const paramsSize = JSON.stringify(params).length\n // if (paramsSize > 1024 * 1024) { // 1MB\n // throw new AjaxError({\n // code: 'JSSDK_PARAMS_TOO_LARGE',\n // description: `Parameters too large: ${(paramsSize / 1024 / 1024).toFixed(2)}MB`,\n // status: 400,\n // requestInfo: { method, params, requestId },\n // originalError: null\n // })\n // }\n }\n\n /**\n * Calling the RestApi function\n * @param method - REST API method name\n * @param params - Parameters for the method.\n * @param requestId - Request id\n * @param options - Per-request transport options (currently `idempotencyKey`)\n * @returns Promise with AjaxResult\n */\n public async call<T = unknown>(method: string, params: TypeCallParams, requestId?: string, options?: TypeCallOptions): Promise<AjaxResult<T>> {\n requestId = requestId ?? this._requestIdGenerator.getRequestId()\n const maxRetries = this._restrictionManager.getParams().maxRetries!\n\n this._validateParams(requestId, method, params)\n this._logRequest(requestId, method, params)\n\n // Built once, before the retry loop, and threaded down as config rather\n // than as options. Three reasons, all of them found the hard way:\n // a malformed key must fail as `JSSDK_HTTP_INVALID_IDEMPOTENCY_KEY` — built\n // inside the loop it was thrown inside the try, converted by\n // `_convertToAjaxError`, and reached the caller as `JSSDK_UNKNOWN_ERROR`;\n // `HttpV2`'s dropped-key warning belongs to the call, not to each attempt;\n // and the same config must go out on every attempt, since a retry of one\n // operation has to carry the same key. (#462)\n const requestConfig = this._prepareRequestConfig(requestId, method, options)\n\n let lastError: AjaxError | null = null\n const startTime = Date.now()\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n this._logAttempt(requestId, method, attempt + 1, maxRetries)\n\n // Apply operating limits via the manager\n await this._restrictionManager.applyOperatingLimits(requestId, method, params)\n\n // 3. We execute the request taking into account authorization, rate limit, and update operating statistics.\n const result = await this._executeSingleCall<T>(requestId, method, params, requestConfig)\n const duration = Date.now() - startTime\n\n // 6. Updating statistics\n this._restrictionManager.resetErrors(method)\n this._updateMetrics(method, true, duration)\n\n // Log the results\n this._logSuccessfulRequest(requestId, method, duration)\n return result\n } catch (error: unknown) {\n lastError = this._convertToAjaxError(requestId, error, method, params)\n\n const duration = Date.now() - startTime\n\n this._restrictionManager.incrementError(method)\n this._updateMetrics(method, false, duration, lastError)\n\n // Log the results\n this._logFailedRequest(requestId, method, attempt + 1, maxRetries, lastError)\n\n if (attempt + 1 < maxRetries) {\n const waitTime = await this._restrictionManager.handleError(requestId, method, params, lastError, attempt)\n // We don't repeat if waitTime === 0\n if (waitTime > 0) {\n this._restrictionManager.incrementStats('limitHits')\n\n this._logAttemptRetryWaiteDelay(requestId, method, waitTime, attempt + 1, maxRetries)\n await this._restrictionManager.waiteDelay(waitTime)\n\n this._restrictionManager.incrementStats('retries')\n\n continue\n }\n }\n\n if (attempt + 1 === maxRetries) {\n this._logAllAttemptsExhausted(requestId, method, attempt + 1, maxRetries)\n }\n\n /**\n * We decide whether to return the error inside an `AjaxResult` or throw.\n *\n * Delegated to the manager rather than tested here against one list:\n * the decision now also has a category branch for `restApi:v3`, and\n * splitting it across two files is how the payload parsing came to\n * disagree with itself (#423, #460).\n */\n if (this._restrictionManager.isSoftError(lastError)) {\n return this._createAjaxResultWithErrorFromResponse<T>(lastError, requestId, method, params)\n }\n throw lastError\n }\n }\n\n // Unreachable on normal exhaustion — the final attempt throws `lastError` (its\n // real code) above. Only reached when maxRetries < 1: the loop never runs and\n // there is no lastError to surface. (#143)\n throw new AjaxError({\n code: 'JSSDK_CALL_ALL_ATTEMPTS_EXHAUSTED',\n description: 'All attempts exhausted',\n status: lastError?.status || 500,\n requestInfo: { method, params, requestId },\n originalError: lastError?.originalError || null\n })\n }\n\n protected _convertToAjaxError(requestId: string, error: unknown, method: string, params: TypeCallParams): AjaxError {\n if (error instanceof AjaxError) {\n return error\n }\n\n if (error instanceof AxiosError) {\n return this._convertAxiosErrorToAjaxError(requestId, error, method, params)\n }\n\n return this._convertUnknownErrorToAjaxError(requestId, error, method, params)\n }\n\n protected _convertAxiosErrorToAjaxError(requestId: string, axiosError: AxiosError, method: string, params: TypeCallParams): AjaxError {\n const errorCode = `${axiosError.code || 'JSSDK_AXIOS_ERROR'}`\n const errorDescription = axiosError.message\n const status = axiosError.response?.status || 0\n\n // Handling network errors\n if (errorCode === 'ERR_NETWORK') {\n return new AjaxError({\n code: 'NETWORK_ERROR',\n description: 'Network connection failed',\n status: 0,\n requestInfo: { method, params, requestId },\n originalError: axiosError\n })\n }\n\n // Handling timeout\n if (errorCode === 'ECONNABORTED' || axiosError.message.includes('timeout')) {\n return new AjaxError({\n code: 'REQUEST_TIMEOUT',\n description: 'Request timeout exceeded',\n status: 408,\n requestInfo: { method, params, requestId },\n originalError: axiosError\n })\n }\n\n // Shared with `AjaxResult.#processErrors()`. Which of the two runs depends on\n // whether the code is soft or hard — not something a caller controls — so\n // they have to agree, and when this was written out in both places they did\n // not: neither read `validation[].field` (#423).\n const parsed = parseErrorPayload(axiosError.response?.data, errorCode, errorDescription)\n\n return new AjaxError({\n code: parsed?.code ?? errorCode,\n description: parsed?.description ?? errorDescription,\n status,\n validation: parsed?.validation,\n isV3Envelope: parsed?.isV3Envelope,\n requestInfo: { method, params, requestId },\n originalError: axiosError\n })\n }\n\n protected _convertUnknownErrorToAjaxError(requestId: string, error: unknown, method: string, params: TypeCallParams): AjaxError {\n return new AjaxError({\n code: 'JSSDK_UNKNOWN_ERROR',\n description: error instanceof Error ? error.message : String(error),\n status: 0,\n requestInfo: { method, params, requestId },\n originalError: error\n })\n }\n\n // region Execute Single Call ////\n /**\n * Performs a single call with\n * - 401 error handling\n * - rate limit check\n * - updating operating statistics\n */\n protected async _executeSingleCall<T = unknown>(requestId: string, method: string, params: TypeCallParams, requestConfig?: AxiosRequestConfig): Promise<AjaxResult<T>> {\n this._checkClientSideWarning(requestId)\n const authData = await this._ensureAuth(requestId)\n const response = await this._makeRequestWithAuthRetry<T>(requestId, method, params, authData, requestConfig)\n\n return this._createAjaxResultFromResponse<T>(response, requestId, method, params)\n }\n\n // Get/update authorization\n protected async _ensureAuth(requestId: string): Promise<AuthData> {\n let authData = this._authActions.getAuthData()\n if (authData === false) {\n this._logRefreshingAuthToken(requestId)\n authData = await this._refreshAuth()\n }\n return authData\n }\n\n /**\n * Refresh the auth token, coalescing concurrent callers onto a single\n * in-flight `refreshAuth()` so a burst of 401s triggers exactly one refresh\n * round-trip. The slot clears once the refresh settles. (#182)\n */\n protected _refreshAuth(): Promise<AuthData> {\n if (this._pendingRefresh) {\n return this._pendingRefresh\n }\n const refresh = this._authActions.refreshAuth()\n this._pendingRefresh = refresh\n // Clear the slot once settled; the extra no-op catch keeps this cleanup\n // chain from surfacing as an unhandled rejection — callers still receive\n // the rejection through the returned promise.\n refresh.finally(() => {\n this._pendingRefresh = null\n }).catch(() => {})\n return refresh\n }\n\n // Execute the request with 401 error handling\n protected async _makeRequestWithAuthRetry<T>(requestId: string, method: string, params: TypeCallParams, authData: AuthData, requestConfig?: AxiosRequestConfig): Promise<AjaxResponse<T>> {\n try {\n // 4. Apply the rate limit through the manager\n await this._restrictionManager.checkRateLimit(requestId, method)\n\n return await this._makeAxiosRequest<T>(requestId, method, params, authData, requestConfig)\n } catch (error) {\n if (error instanceof AxiosError) {\n this.getLogger().info(\n `post/catchError`, {\n requestId,\n status: error.status,\n // Redact in case a future portal response embeds credentials in\n // the error body (today it doesn't, but the channel is open) (#39),\n // and cap the length so a large error body can't flood the sink (#236).\n responseData: truncateForLog(JSON.stringify(redactSensitiveParams(error?.response?.data), null, 0))\n }\n ).catch(() => {})\n }\n\n // Normalize to AjaxError first: axios throws a raw AxiosError here, whose\n // Bitrix `code` (e.g. `expired_token`) is only populated by conversion. The\n // 401 auth-retry check must run against the converted error — otherwise the\n // `instanceof AjaxError` guard in `_isAuthError` is always false and the\n // refresh-and-retry branch below is dead code. (#182)\n const ajaxError = this._convertToAjaxError(requestId, error, method, params)\n\n // If this is an authorization error (401), then we try to update the token and repeat\n if (this._isAuthError(ajaxError)) {\n this._logAuthErrorDetected(requestId)\n this._logRefreshingAuthToken(requestId)\n\n const refreshedAuthData = await this._refreshAuth()\n\n // 4. Apply the rate limit through the manager\n await this._restrictionManager.checkRateLimit(requestId, method)\n\n return await this._makeAxiosRequest<T>(requestId, method, params, refreshedAuthData, requestConfig)\n }\n\n // Non-auth error: rethrow the already-converted AjaxError (idempotent in\n // `call()`'s catch) instead of the raw AxiosError. (#182)\n throw ajaxError\n }\n }\n\n protected async _makeAxiosRequest<T>(requestId: string, method: string, params: TypeCallParams, authData: AuthData, requestConfig?: AxiosRequestConfig): Promise<AjaxResponse<T>> {\n let methodFormatted = this._prepareMethod(requestId, method, this.getBaseUrl())\n\n // A `restApi:v3` batch sends its commands AS the request body — a bare\n // top-level array, no envelope (see `HttpV3.batch`). Everything else sends an\n // object, and `_prepareParams` is built for that: it spreads `params` into a\n // fresh object, which turns an array into `{ '0': …, '1': … }`, and then adds\n // the OAuth `auth` as one more top-level entry.\n //\n // The portal iterates every top-level entry of a batch body and demands\n // `method` and `query` on each, so that extra entry rejects the whole batch\n // with `INVALIDSELECTEXCEPTION` before a command runs. Three cases follow,\n // decided by where the credential can live:\n //\n // 1. A webhook authenticates through the URL, so the body can be the array\n // the portal's grammar describes. Measured live: accepted.\n // 2. A non-hook transport on a server sends the token in the standard\n // header, which the portal accepts and prefers over any body or query\n // parameter (`rest/lib/oauth/auth.php`, `getAuthKey()`).\n // 3. A non-hook transport **where CORS applies** cannot use that header: the\n // portal answers the preflight with `Access-Control-Allow-Headers: origin,\n // content-type, accept` (`CRestUtil::sendHeaders()`), so asking for\n // `Authorization` fails the preflight and the request never leaves. The\n // credential goes in the **query string** instead — `?auth=<token>`,\n // which the portal reads through the same dictionary as a body `auth`\n // (`CRestUtil::getRequestData()` merges GET and POST with\n // `array_replace`, so `getAuthKey()` cannot tell the two apart). Measured\n // accepted on a live portal. A query parameter costs nothing on a\n // preflight the request is already making for its `Content-Type`.\n //\n // This is the one place the SDK puts an OAuth token in a URL, so the\n // reasoning is worth keeping: in a frame app the token is in the page's\n // JavaScript already — devtools, the body of every non-batch call — so\n // the query string reveals it to nobody who could not already read it.\n // What it does add is a server-side record: `?auth=` reaches the portal's\n // access log and, when an administrator switches the module's diagnostic\n // logger on, its `REQUEST_URI` field. That was weighed and accepted; the\n // alternative was leaving every browser app unable to batch on v3 at all,\n // since this SDK is the only official one that runs in a browser.\n //\n // Delete this branch the day `authorization` appears in the portal's\n // `Access-Control-Allow-Headers` — then a browser takes the same header\n // path as a server and nothing else here needs to change.\n //\n // Case 3 asks about CORS rather than about \"is this a server\", because those\n // are not the same question. Both are answered by `isBrowserLikeRuntime()`,\n // which counts a worker as browser-like: a worker has no `window.document`,\n // so the older DOM test read it as a server and would have given it the\n // header — in a context where CORS applies exactly as it does on the main\n // thread. See {@link isCorsEnforcedRuntime}.\n //\n // The webhook case is not conditioned on any of this: it adds no header, so\n // there is no preflight to fail. Its body does change shape everywhere,\n // browser included — from `{ '0': … }` to the array — which the portal reads\n // identically, because PHP's `json_decode` cannot tell a list from a map with\n // sequential integer keys.\n //\n // Gated on the version AND the method, not merely on the body being an array.\n // `TypeCallParams` carries an index signature, so an array satisfies it, and\n // `getHttpClient(ApiVersion.v2).call('task.commentitem.getlist', [taskId, …])`\n // — the documented positional shape for the legacy `task.*` family — reaches\n // this function with an array on `restApi:v2`. Everything reasoned about\n // above is about a v3 batch; on v2 the body would change shape AND the\n // credential would move to a header whose acceptance nothing here has\n // established. The comment describes one case, so the code tests for that\n // one case.\n const isV3Batch = ApiVersion.v3 === this._version && 'batch' === method\n const isBareArrayBody = isV3Batch && Array.isArray(params)\n // Load-bearing, not defensive: `AuthHookManager` returns the webhook secret\n // as `access_token` (`hook/auth.ts`), so dropping this term would put a\n // portal-wide secret into an `Authorization` header.\n const isHook = 'hook' === authData.refresh_token\n // An absent or empty token would go out as the literal `Bearer undefined`.\n // `_prepareParams` used to drop it silently — `JSON.stringify` omits an\n // `undefined` value — so require a real one rather than put a nonsense\n // credential on the wire. Trimmed, because a token of blanks is not a token\n // and `Bearer ` is a malformed header rather than a failed authentication:\n // it earns a portal error that names neither the header nor the token, where\n // the body fallback at least fails the way this transport already fails.\n const hasAccessToken = 'string' === typeof authData.access_token && authData.access_token.trim().length > 0\n // An idempotent call needs the token out of the body too: the portal\n // fingerprints the raw body for `Idempotency-Key`, so a token in it makes a\n // retry after the token rotates look like a different request (422\n // `IDEMPOTENCYKEYREUSED`) instead of a replay. Measured in #570.\n const hasIdempotencyKey = ApiVersion.v3 === this._version\n && 'string' === typeof (requestConfig?.headers as Record<string, unknown> | undefined)?.[IDEMPOTENCY_KEY_HEADER]\n const authOutOfBody = (isBareArrayBody || hasIdempotencyKey) && !isHook && hasAccessToken\n const canSendAuthHeader = authOutOfBody && !isCorsEnforcedRuntime()\n // Same conditions as the header, on the other side of the CORS question: a\n // browser cannot send `Authorization`, so the token rides in the query\n // string. A hook is excluded for the same reason it is excluded above — its\n // credential is already in the URL path, and `_prepareParams` skips it.\n //\n // This branch takes `maxRedirects: 0` as well, for a narrower reason than\n // the header does. A credential in a query string does not follow a redirect\n // the way a header does: `follow-redirects` re-sends `Authorization` to a\n // same-host or subdomain hop, whereas a redirect target is whatever\n // `Location` names and carries the original query only if the server echoes\n // it back. Some do — an nginx or Apache rule built from `$request_uri` on a\n // scheme or trailing-slash hop preserves the query string, and the hop is\n // then a token handed to whatever serves the target.\n //\n // Whether the option bites depends on the adapter, and that is not decided\n // by \"is this a browser\". `getAdapter()` walks the default\n // `['xhr', 'http', 'fetch']` and takes the first *supported* entry. XHR is\n // supported wherever `XMLHttpRequest` exists — a window, a dedicated worker,\n // a shared worker — and the XHR adapter ignores `maxRedirects` outright. A\n // **service worker** has no `XMLHttpRequest`, so the list falls through\n // `http` (Node only) to `fetch`, and the fetch adapter does read it, as\n // `redirect: 'manual'`. Inert on the common path, load-bearing on that one:\n // reason enough to set it rather than reason to leave it out.\n const useQueryAuth = authOutOfBody && isCorsEnforcedRuntime()\n const sendBareArray = isBareArrayBody && (isHook || canSendAuthHeader || useQueryAuth)\n\n const paramsFormatted = sendBareArray\n ? params as unknown as TypePrepareParams\n : this._prepareParams(authData, params)\n\n if (authOutOfBody && !sendBareArray) {\n delete paramsFormatted.auth\n }\n\n // Merged into whatever the caller's own config already carries — today the\n // `Idempotency-Key` header — rather than replacing it.\n //\n // `maxRedirects: 0` comes with a credential outside the body — the header or\n // the query string — and only with it. A credential in\n // the body was safe across a redirect by accident: a 301/302 turns POST into\n // GET and drops the body, so the old `auth` never travelled. A header does —\n // `follow-redirects` strips `Authorization` when the host changes, but keeps\n // it for the same host and for a **subdomain**, so a portal answering\n // `301 Location: https://cdn.<portal>/…` would hand the token to whatever\n // serves that name.\n //\n // Set here rather than on the axios instance because the instance carries\n // every request the SDK makes, and a redirect somewhere in that traffic may\n // be load-bearing for someone. This branch is different: it is reached only\n // by a v3 batch or an idempotent v3 call on a non-hook transport. For the\n // batch there was no working behaviour to preserve; an idempotent call did\n // follow a redirect before, with its token in a body the redirect dropped,\n // so it failed there anyway — now it fails legibly. A deployment that does\n // redirect gets an error instead of a silent hop with a credential attached —\n // a legible 301 through `validateStatus` on the Node adapter, and on `fetch`,\n // where `redirect: 'manual'` is what `maxRedirects: 0` becomes and the\n // response carries no status of its own, the explicit status-0 check after\n // the `post` below (axios resolves an opaque response rather than rejecting\n // it).\n //\n // Before the spread, not after, so it is a default rather than a lock: a\n // transport that overrides `_prepareRequestConfig` — `HttpV2` already does —\n // can hand back a `maxRedirects` and win. `TypeCallOptions` carries no such\n // field today, so there is no way for an ordinary caller to reopen it, which\n // is the right way round for a credential.\n // The portal reads a `filter` value as a boolean only when the body is JSON.\n // Under `application/x-www-form-urlencoded`, `ACTIVE: false` arrives as the\n // string `\"false\"`, the condition is dropped, and the call answers with rows\n // it should have excluded — no error on either side. Measured on\n // `user.get` (`filter: { ACTIVE: false }` → 0 rows as JSON, 1 as form data,\n // against the same portal in the same minute).\n //\n // The SDK has always sent JSON, but never asked for it: axios picks\n // `application/json` on its own for a plain-object body. That default is\n // reachable — `ajaxClient` is public and the docs encourage touching it to\n // raise `defaults.timeout` — so one header on the instance silently breaks\n // every boolean filter portal-wide.\n //\n // Per request rather than on the instance, deliberately: a caller who posts\n // `FormData` through `ajaxClient` themselves still gets the multipart\n // boundary axios computes for them. This states what the SDK's own traffic\n // depends on without deciding anything for traffic it does not own.\n //\n // Spread first inside `headers`, so anything a transport puts in\n // `requestConfig.headers` overrides it; none does today. What this does not\n // reach is a request interceptor installed on the public `ajaxClient` — that\n // runs after the config is assembled and can still replace the header (and\n // with it the encoding). Documented rather than defended: the instance is\n // public on purpose.\n const jsonBody = { 'Content-Type': 'application/json' }\n\n const effectiveConfig: AxiosRequestConfig | undefined = canSendAuthHeader\n ? {\n maxRedirects: 0,\n ...requestConfig,\n headers: {\n ...jsonBody,\n ...requestConfig?.headers,\n Authorization: `Bearer ${authData.access_token}`\n }\n }\n : useQueryAuth\n ? {\n maxRedirects: 0,\n ...requestConfig,\n headers: { ...jsonBody, ...requestConfig?.headers }\n }\n : {\n ...requestConfig,\n headers: { ...jsonBody, ...requestConfig?.headers }\n }\n\n // `paramsFormatted` carries the OAuth `auth` (access_token) for non-hook flows;\n // log a redacted copy so the secret never enters logger context, while axios\n // still receives the original below. (#39)\n // The `Authorization` header is deliberately NOT logged, and nothing here may\n // start logging it: `redactSensitiveParams` walks `params` and never touches\n // headers, so a token put into logger context would arrive in the clear —\n // the #39 defect, in a channel neither the redactor nor the local\n // `no-credential-in-logger` rule can see. Pinned by a test rather than left\n // to this comment.\n const paramsFormattedForLog = JSON.stringify(redactSensitiveParams(paramsFormatted), null, 0)\n\n this.getLogger().info(\n `post/send`, {\n requestId,\n method,\n params: truncateForLog(paramsFormattedForLog)\n }\n ).catch(() => {})\n\n if (useQueryAuth) {\n // `_prepareMethod` may or may not have emitted a query string already\n // (an idempotent non-batch call on a server, if a caller forced the fetch\n // adapter's CORS mode, would too), so ask.\n const separator = methodFormatted.includes('?') ? '&' : '?'\n methodFormatted += `${separator}auth=${encodeURIComponent(authData.access_token)}`\n }\n\n const response = await this._clientAxios.post<SuccessPayload<T>>(methodFormatted, paramsFormatted, effectiveConfig)\n\n // A blocked redirect is not an error on every adapter, so say so here.\n // `settle` resolves any response with a falsy status before `validateStatus`\n // runs, and the fetch adapter — what a browser now gets — turns\n // `redirect: 'manual'` into an opaque response: status 0, empty body, no\n // headers. The XHR adapter rejected that shape itself (`ECONNABORTED`);\n // fetch does not, so without this the caller gets a successful, silently\n // empty answer to a request the SDK deliberately refused to follow.\n //\n // The **effective** value, not only the per-request one: `maxRedirects` is\n // an allowed `httpOptions` key, and an instance-level `0` makes every\n // request `redirect: 'manual'` on the fetch adapter — where the per-request\n // config is absent, which left a blocked redirect resolving as an empty\n // success on an ordinary call.\n //\n // That scope is wider than the SDK's own branch, and deliberately so: an\n // opaque response carries nothing to tell a blocked redirect from a dropped\n // connection, and a request that asked not to follow redirects is better\n // answered with an error than with a silently empty success. The cost is\n // that a caller who sets `maxRedirects: 0` themselves puts every status-0\n // answer in this bucket, retries included — stated in the error text and on\n // the Http page rather than left to be discovered. A caller who does not set\n // it is unaffected: the only branches that set it are a `restApi:v3` batch\n // and an idempotent `restApi:v3` call, both on a non-hook transport.\n const effectiveMaxRedirects = effectiveConfig?.maxRedirects\n ?? this._clientAxios.defaults.maxRedirects\n\n if (0 === effectiveMaxRedirects && 0 === response.status) {\n throw new AjaxError({\n code: 'JSSDK_HTTP_REDIRECT_BLOCKED',\n description: 'This request does not follow redirects (`maxRedirects: 0`) and the answer carried no status of its own — '\n + 'which is what a refused redirect looks like on the fetch adapter, and what a dropped connection can look like too. '\n + 'The SDK sets `maxRedirects: 0` on a `restApi:v3` batch and on a `restApi:v3` call with `idempotencyKey`, both on a '\n + 'non-hook transport, because they carry an access token a redirect would take along. Point the SDK at the final URL instead.',\n status: 0,\n requestInfo: { method, params, requestId }\n })\n }\n\n // Redact the log-bound copy only; callers still receive the untouched\n // `response.data` below. First-party success bodies don't embed credentials\n // today, but an OAuth-relay method (or a future method returning a canonical\n // key) would otherwise leak `access_token` / `refresh_token` / etc. into any\n // wired logger sink — mirror the `post/send` redaction on the success path. (#69)\n // A v3 method outside the `result` envelope (e.g. `rest.documentation.openapi`)\n // makes this `undefined` rather than a string; `truncateForLog` coerces it. (#338)\n // `?.` on the body itself, not only on `.result`: a success is not always an\n // object. An HTTP 200 whose body is `null` made this line throw, and the\n // request path then re-wrapped that `TypeError` as `JSSDK_UNKNOWN_ERROR` —\n // a fine response reaching the caller as an unrecognisable failure, the same\n // shape as #338 and #456 one field over.\n const resultFormattedForLog = JSON.stringify(redactSensitiveParams(response.data?.result), null, 0)\n this.getLogger().info(\n `post/response`, {\n requestId,\n // responseFull: JSON.stringify(response.data, null, 2),\n result: truncateForLog(resultFormattedForLog),\n time: JSON.stringify(response.data?.time, null, 0)\n }\n ).catch(() => {})\n\n const idempotency = readIdempotencyHeaders(response.headers)\n\n return {\n status: response.status,\n payload: response.data,\n ...(idempotency ? { idempotency } : {})\n }\n }\n\n /**\n * Builds the per-request axios config for one call, or `undefined` when the\n * call needs none.\n *\n * A `protected` hook rather than a branch inside `_makeAxiosRequest` because\n * the two transports genuinely disagree about one option: `HttpV2` overrides\n * it to drop `idempotencyKey`, since the v2 endpoint ignores the header and a\n * key that is silently dropped leaves a caller believing a retry is\n * deduplicated when it is not. It is the mechanism for that disagreement, not\n * a speculative extension point — a subclass overriding it owes the same\n * contract: return per-request axios config, or `undefined` for none.\n *\n * @throws {SdkError} `JSSDK_HTTP_INVALID_IDEMPOTENCY_KEY` when the key is not\n * 1-255 printable ASCII characters.\n * @throws {SdkError} `JSSDK_HTTP_IDEMPOTENCY_KEY_BROWSER` when a v3 call with a\n * key runs where CORS applies (#573).\n */\n protected _prepareRequestConfig(_requestId: string, _method: string, options?: TypeCallOptions): AxiosRequestConfig | undefined {\n const idempotencyKey = options?.idempotencyKey\n\n if (undefined === idempotencyKey) {\n return undefined\n }\n\n if (!IDEMPOTENCY_KEY_RE.test(idempotencyKey)) {\n // Static text only — never the key itself. `SdkError` does not run its\n // description through `redactSensitiveParams`, and a caller is free to\n // build a key out of business identifiers.\n throw new SdkError({\n code: 'JSSDK_HTTP_INVALID_IDEMPOTENCY_KEY',\n description: '`idempotencyKey` must be 1-255 printable ASCII characters with no whitespace or control characters. '\n + 'A `crypto.randomUUID()` value satisfies this. See https://apidocs.bitrix24.ru/api-reference/rest-v3.html',\n status: 500\n })\n }\n\n // A browser never sends it: the portal's CORS preflight allows only\n // `origin, content-type, accept`, and no query or body form is honoured\n // (measured, #573). Fail here, before anything is sent, instead of as a\n // network error the retry loop would repeat.\n if (ApiVersion.v3 === this._version && isCorsEnforcedRuntime()) {\n throw new SdkError({\n code: 'JSSDK_HTTP_IDEMPOTENCY_KEY_BROWSER',\n description: '`idempotencyKey` cannot be used from a browser: the portal\\'s CORS preflight does not allow the '\n + '`Idempotency-Key` header, so a cross-origin request carrying it is refused. Make idempotent writes from a server. See https://github.com/bitrix24/b24jssdk/issues/573',\n status: 500\n })\n }\n\n return { headers: { [IDEMPOTENCY_KEY_HEADER]: idempotencyKey } }\n }\n\n protected _isAuthError(error: unknown): boolean {\n if (!(error instanceof AjaxError)) {\n return false\n }\n\n return (\n error.status === 401\n && ['expired_token', 'invalid_token'].includes(error.code)\n )\n }\n\n protected async _createAjaxResultFromResponse<T>(response: AjaxResponse<T>, requestId: string, method: string, params: TypeCallParams): Promise<AjaxResult<T>> {\n const result = new AjaxResult<T>({\n answer: response.payload,\n query: { method, params, requestId },\n status: response.status,\n idempotency: response.idempotency\n })\n\n // 5. Update operating statistics — only when the portal sent a `time` block.\n // It does not always: `rest.documentation.openapi` answers with the OpenAPI\n // document at the top level, with neither a `result` envelope nor `time`.\n // The `time!` assertion that used to stand here claimed otherwise, and\n // `OperatingLimiter.updateStats()` destructured the absent block — so a\n // perfectly good HTTP 200 came back to the caller as an exception.\n if (result.isSuccess) {\n const time = result.getData()?.time\n if (time) {\n await this._restrictionManager.updateStats(requestId, method, time)\n }\n }\n\n return result\n }\n\n /**\n * Turns an error the transport already built into the soft `AjaxResult` a\n * caller receives, for the codes in `RestrictionManager.exceptionCodeForSoft`.\n *\n * It used to rebuild the error from a synthetic answer holding only `code` and\n * `message`, so the portal's real body was discarded here — which is why\n * `validation` was unreachable even though `_convertAxiosErrorToAjaxError` had\n * just parsed it (#423).\n *\n * The error is now **carried** rather than re-derived: the synthetic `answer`\n * is kept so `_data` still describes the failure for anything reading it, but\n * it is no longer what produces the error — which also means the two can no\n * longer disagree. `validation` is deliberately not copied into that synthetic\n * answer: nothing parses it back out, so it would be dead weight that a future\n * refactor could mistake for the source of truth.\n *\n * The carried error keeps its `originalError` — the raw `AxiosError`, whose\n * `config.url` holds the webhook secret. It is non-enumerable (see\n * `SdkError`), so spreads and `JSON.stringify` still cannot reach it, but it\n * is now readable via `result.getErrors()` on this path as well as on the\n * throwing one. That is deliberate: the two paths differ only in how the error\n * is delivered, and a caller debugging one should not find less on the other.\n */\n protected _createAjaxResultWithErrorFromResponse<T>(ajaxError: AjaxError, requestId: string, method: string, params: TypeCallParams): AjaxResult<T> {\n return new AjaxResult<T>({\n answer: {\n error: {\n code: ajaxError.code,\n message: ajaxError.message\n }\n },\n query: { method, params, requestId },\n status: ajaxError.status,\n // The error itself, not a reconstruction: it was parsed from the portal's\n // body a moment ago, and re-deriving it here would fold the validation\n // messages onto a description that already holds them (#423).\n error: ajaxError\n })\n }\n // endregion ////\n // endregion ////\n\n // region Prepare ////\n /**\n * Builds the request URL: the method path plus the SDK telemetry query params\n * (`bx24_request_id` / `bx24_sdk_ver` / `bx24_sdk_type` — request tracing and\n * SDK identification, not auth material).\n *\n * Carve-out for the legacy positional `task.*` methods (`task.commentitem.*`,\n * `task.checklistitem.*`, `task.elapseditem.*`, …): these read the request\n * **query string positionally**, so appending the telemetry params shifts\n * `Param #0` and the server rejects the call —\n * `WRONG_ARGUMENTS: Param #0 (taskId) ... expected integer, but given\n * something else`. Verified live against a portal: the same\n * `task.commentitem.getlist` / `task.checklistitem.getlist` call succeeds\n * without the telemetry params and fails with them; modern `tasks.task.*`\n * (named params) is unaffected. So telemetry is omitted only for methods whose\n * name STARTS WITH `task.`.\n *\n * Shared by v2 and v3 (rather than per-transport): once the v3 method\n * allowlist was dropped (#259) a positional `task.*` method can be routed via\n * `actions.v3.*` too, so v3 needs the same suppression — keeping the rule in\n * one place stops the two transports drifting apart again (#207).\n *\n * The match is anchored (`^task\\.`): only legacy positional `task.*` methods\n * are suppressed. Modern named-param methods `tasks.task.*` / `bizproc.task.*`\n * do NOT start with `task.`, so they KEEP telemetry and stay traceable — the\n * boundary was pinned live in #271/#272 (`tasks.task.list` works WITH\n * telemetry; legacy `task.*` breaks WITH it). Bitrix24 method names are\n * lowercase by convention, so the case-sensitive match is sufficient.\n *\n * @see https://apidocs.bitrix24.com/settings/how-to-call-rest-api/data-encoding.html#order-of-parameters\n */\n protected _prepareMethod(requestId: string, method: string, baseUrl: string): string {\n const methodUrl = `/${encodeURIComponent(method)}`\n\n if (/^task\\./.test(method)) {\n return `${baseUrl}${methodUrl}`\n }\n\n const queryParams = new URLSearchParams({\n [this._requestIdGenerator.getQueryStringParameterName()]: requestId,\n [this._requestIdGenerator.getQueryStringSdkParameterName()]: '__SDK_VERSION__',\n [this._requestIdGenerator.getQueryStringSdkTypeParameterName()]: '__SDK_USER_AGENT__'\n })\n return `${baseUrl}${methodUrl}?${queryParams.toString()}`\n }\n\n /**\n * Processes function parameters and adds authorization\n */\n protected _prepareParams(authData: AuthData, params: TypeCallParams): TypePrepareParams {\n const result: TypePrepareParams = { ...params }\n\n /** @memo we skip auth for hook */\n if (authData.refresh_token !== 'hook') {\n result.auth = authData.access_token\n }\n\n if (result?.data && 'start' in result.data) {\n const { start, ...dataWithoutStart } = result.data\n result.data = dataWithoutStart\n }\n\n return result\n }\n\n /**\n * @inheritDoc\n */\n public setClientSideWarning(\n value: boolean,\n message: string\n ): void {\n this._isClientSideWarning = value\n this._clientSideWarningMessage = message\n }\n // endregion ////\n\n // region Tools ////\n /**\n * Tests whether the code is running outside a browser-like runtime — that is,\n * on a server. The inverse of {@link isBrowserLikeRuntime}, and a worker is\n * **not** server-side: it has no DOM, but the browser's rules apply to it.\n *\n * @return {boolean}\n * @protected\n */\n protected isServerSide(): boolean {\n return !isBrowserLikeRuntime()\n }\n\n /**\n * Get the BX24 account address with the path based on the API version\n */\n public getBaseUrl(): string {\n return this._authActions.getTargetOriginWithPath().get(this._version)!\n }\n // endregion ////\n\n // region Log ////\n /**\n * Redaction contract: runs caller params through {@link redactSensitiveParams}\n * (see `redact.ts`) so credential-bearing keys are masked before they reach any\n * logger context. (#39, #73)\n * @see redactSensitiveParams\n */\n protected _sanitizeParams(params: TypeCallParams): Record<string, unknown> {\n return redactSensitiveParams(params)\n }\n\n /**\n * Redaction contract: params are redacted via {@link _sanitizeParams} →\n * {@link redactSensitiveParams} before logging. (#73)\n * @see redactSensitiveParams\n */\n protected _logRequest(requestId: string, method: string, params: TypeCallParams): void {\n this.getLogger().debug(`http request starting`, {\n requestId,\n method,\n params: this._sanitizeParams(params),\n api: this.apiVersion,\n timestamp: Date.now()\n }).catch(() => {})\n }\n\n protected _logAttempt(requestId: string, method: string, attempt: number, maxRetries: number): void {\n this.getLogger().info(`http request attempt`, {\n requestId,\n method,\n api: this.apiVersion,\n attempt: {\n current: attempt,\n max: maxRetries\n }\n }).catch(() => {})\n }\n\n protected _logRefreshingAuthToken(requestId: string): void {\n this.getLogger().info(`http refreshing auth token`, {\n requestId,\n api: this.apiVersion\n }).catch(() => {})\n }\n\n protected _logAuthErrorDetected(requestId: string): void {\n this.getLogger().info(`http auth error detected`, {\n requestId,\n api: this.apiVersion\n }).catch(() => {})\n }\n\n protected _logSuccessfulRequest(requestId: string, method: string, duration: number): void {\n this.getLogger().debug(`http request successful`, {\n requestId,\n method,\n api: this.apiVersion,\n duration: {\n ms: duration,\n sec: Number.parseFloat((duration / 1000).toFixed(2))\n }\n }).catch(() => {})\n }\n\n protected _logFailedRequest(\n requestId: string,\n method: string,\n attempt: number,\n maxRetries: number,\n error: AjaxError\n ): void {\n this.getLogger().debug(`http request failed`, {\n requestId,\n method,\n api: this.apiVersion,\n attempt: {\n current: attempt,\n max: maxRetries\n },\n error: {\n code: error.code,\n message: error.message,\n status: error.status\n }\n }).catch(() => {})\n }\n\n protected _logAttemptRetryWaiteDelay(\n requestId: string,\n method: string,\n wait: number,\n attempt: number,\n maxRetries: number\n ): void {\n this.getLogger().debug(\n `http wait ${(wait / 1000).toFixed(2)} sec.`,\n {\n requestId,\n method,\n api: this.apiVersion,\n wait: wait,\n attempt: {\n current: attempt,\n max: maxRetries\n }\n }\n ).catch(() => {})\n }\n\n protected _logAllAttemptsExhausted(requestId: string, method: string, attempt: number, maxRetries: number): void {\n this.getLogger().warning(`http all retry attempts exhausted`, {\n requestId,\n method,\n api: this.apiVersion,\n attempt: {\n current: attempt,\n max: maxRetries\n }\n }).catch(() => {})\n }\n\n protected _logBatchStart(\n requestId: string,\n calls: BatchCommandsArrayUniversal | BatchCommandsObjectUniversal | BatchNamedCommandsUniversal,\n options: ICallBatchOptions\n ): void {\n const callCount = Array.isArray(calls)\n ? calls.length\n : Object.keys(calls).length\n\n this.getLogger().debug(`http batch request starting `, {\n requestId,\n callCount,\n api: this.apiVersion,\n isHaltOnError: options.isHaltOnError,\n timestamp: Date.now()\n }).catch(() => {})\n }\n\n protected _logBatchCompletion(requestId: string, total: number, errors: number): void {\n this.getLogger().debug(`http batch request completed`, {\n requestId,\n api: this.apiVersion,\n totalCalls: total,\n successful: total - errors,\n failed: errors,\n successRate: total > 0 ? ((total - errors) / (total) * 100).toFixed(1) + '%' : '??'\n }).catch(() => {})\n }\n\n // Check client-side warnings\n protected _checkClientSideWarning(requestId: string): void {\n if (\n this._isClientSideWarning\n && !this.isServerSide()\n && Type.isStringFilled(this._clientSideWarningMessage)\n ) {\n LoggerFactory.forcedLog(\n this.getLogger(),\n 'warning',\n this._clientSideWarningMessage,\n {\n requestId,\n code: 'JSSDK_CLIENT_SIDE_WARNING'\n }\n )\n }\n }\n // endregion ////\n}\n"],"names":[],"mappings":"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"}