UNPKG

@bitrix24/b24jssdk

Version:

Bitrix24 REST API JavaScript SDK

1 lines • 41.7 kB
{"version":3,"file":"manager.mjs","sources":["../../../../../src/core/http/limiters/manager.ts"],"sourcesContent":["import type {\n AdaptiveConfig,\n OperatingLimitConfig,\n RateLimitConfig,\n RestrictionManagerStats,\n RestrictionParams\n} from '../../../types/limiters'\nimport type { LoggerInterface } from '../../../types/logger'\nimport type { PayloadTime } from '../../../types/payloads'\nimport { LoggerFactory } from '../../../logger'\nimport { RateLimiter } from './rate-limiter'\nimport { OperatingLimiter } from './operating-limiter'\nimport { AdaptiveDelayer } from './adaptive-delayer'\nimport { ParamsFactory } from './params-factory'\nimport { SdkError } from '../../sdk-error'\n\nconst RATE_LIMIT_FIELDS = ['burstLimit', 'drainRate', 'adaptiveEnabled'] as const\nconst OPERATING_LIMIT_FIELDS = ['windowMs', 'limitMs', 'heavyPercent'] as const\nconst ADAPTIVE_CONFIG_FIELDS = ['thresholdPercent', 'coefficient', 'maxDelay', 'enabled'] as const\n\n/**\n * Drops keys whose value is explicitly `undefined`.\n *\n * Object spread copies an own key even when its value is `undefined`, so\n * `{ ...config, ...{ maxRetries: undefined } }` erases `maxRetries` rather than\n * keeping it — the natural spelling of an optional override\n * (`maxRetries: fromEnv ? Number(fromEnv) : undefined`) silently emptied the\n * field, and `maxRetries` reaching the retry loop as `undefined` made\n * `attempt < undefined` false on the first pass, so every call failed as\n * \"all attempts exhausted\" without one request going out.\n *\n * With this, \"omitted\" and \"explicitly undefined\" mean the same thing, which is\n * what the merge promises and what the block guards below already assumed.\n */\nfunction definedOnly(params: RestrictionParams): RestrictionParams {\n return Object.fromEntries(\n Object.entries(params).filter(([, value]) => value !== undefined)\n ) as RestrictionParams\n}\n\n/**\n * Copies the nested blocks and the code arrays, not just the top level.\n *\n * A sub-limiter stores the block it is given by reference and rewrites it in\n * place — `RateLimiter` lowers `drainRate` and `burstLimit` as it throttles\n * adaptively. A shallow spread therefore handed a caller the live enforcement\n * state: reading the policy showed values changing underneath, and pushing onto\n * the returned `hardErrorCodes` reconfigured the manager without ever calling\n * the setter.\n */\nfunction cloneParams(params: RestrictionParams): RestrictionParams {\n return {\n ...params,\n ...(params.rateLimit ? { rateLimit: { ...params.rateLimit } } : {}),\n ...(params.operatingLimit ? { operatingLimit: { ...params.operatingLimit } } : {}),\n ...(params.adaptiveConfig ? { adaptiveConfig: { ...params.adaptiveConfig } } : {}),\n ...(params.hardErrorCodes ? { hardErrorCodes: [...params.hardErrorCodes] } : {}),\n ...(params.softErrorCodes ? { softErrorCodes: [...params.softErrorCodes] } : {})\n }\n}\n\n/**\n * Refuses a limiter block that is not whole.\n *\n * The blocks are replaced rather than deep-merged, and their types carry no\n * optional fields — so for a TypeScript caller a half-specified block is\n * already a compile error. JavaScript has no such gate, and neither does a\n * cast: `{ rateLimit: { burstLimit: 7 } }` used to reach `RateLimiter`, where\n * `1000 / undefined` is `NaN`, `while (waitTime > 0)` is false on `NaN`, and\n * rate limiting was simply off for the rest of the process — no error, nothing\n * logged. That is the failure class this whole change exists to remove, so it\n * is not acceptable one layer down.\n *\n * @throws {SdkError} `JSSDK_LIMITER_INVALID_CONFIG_BLOCK`\n */\nfunction assertBlock(\n block: object | undefined,\n name: string,\n fields: readonly string[]\n): void {\n if (block === undefined) {\n return\n }\n\n const present = block as Record<string, unknown> | null\n const missing = present === null\n ? [...fields]\n : fields.filter(field => present[field] === undefined)\n\n if (missing.length === 0) {\n return\n }\n\n // Static text plus the block and field names only — never a caller value.\n throw new SdkError({\n code: 'JSSDK_LIMITER_INVALID_CONFIG_BLOCK',\n description: `setRestrictionManagerParams: \\`${name}\\` is replaced whole, not merged, so it must carry every field. `\n + `Missing: ${missing.join(', ')}. Spread the current block if you mean to change one value.`,\n status: 500\n })\n}\n\n/**\n * Central coordinator for all outbound request throttling.\n *\n * Composes a {@link RateLimiter} (requests-per-second cap), an\n * {@link OperatingLimiter} (Bitrix24 operating-time budget), and an\n * {@link AdaptiveDelayer} (back-off based on observed server load) into a\n * single façade consumed by {@link AbstractHttp}. Tracks aggregate stats\n * (retries, consecutive errors, limit hits) and propagates a shared logger\n * to all three sub-limiters.\n */\nexport class RestrictionManager {\n #rateLimiter: RateLimiter\n #operatingLimiter: OperatingLimiter\n #adaptiveDelayer: AdaptiveDelayer\n #config: RestrictionParams\n #stats: Pick<RestrictionManagerStats, 'retries' | 'consecutiveErrors' | 'limitHits'> = {\n /** Retry attempts */\n retries: 0,\n /** Consecutive errors */\n consecutiveErrors: 0,\n /** Limit triggers */\n limitHits: 0\n }\n\n #errorCounts = new Map<string, number>()\n\n private _logger: LoggerInterface\n\n /**\n * `RestrictionManager` is exported from the package root and every field of\n * `RestrictionParams` is optional, so `new RestrictionManager({ maxRetries: 5 })`\n * is a call TypeScript accepts. It used to throw from inside `RateLimiter`,\n * because the defaulting lived one class away in `AbstractHttp` and the\n * assertions here claimed a caller always sends every block. Merging against\n * the defaults makes the class safe on its own terms, and makes the promise\n * this file documents true here as well as in the setter. (#479)\n */\n constructor(params: RestrictionParams) {\n this._logger = LoggerFactory.createNullLogger()\n\n const patch = definedOnly(params)\n\n // The same gate as `setConfig`. A block replaces the default whole, so a\n // half-specified one here reaches `RateLimiter` exactly as it would through\n // the setter — and this door is open from `B24Hook`'s `restrictionParams`\n // option as well as from the exported class.\n assertBlock(patch.rateLimit, 'rateLimit', RATE_LIMIT_FIELDS)\n assertBlock(patch.operatingLimit, 'operatingLimit', OPERATING_LIMIT_FIELDS)\n assertBlock(patch.adaptiveConfig, 'adaptiveConfig', ADAPTIVE_CONFIG_FIELDS)\n\n this.#config = cloneParams({ ...ParamsFactory.getDefault(), ...patch })\n this.#rateLimiter = new RateLimiter(this.#config.rateLimit as RateLimitConfig)\n this.#operatingLimiter = new OperatingLimiter(this.#config.operatingLimit as OperatingLimitConfig)\n this.#adaptiveDelayer = new AdaptiveDelayer(this.#config.adaptiveConfig as AdaptiveConfig, this.#operatingLimiter)\n }\n\n // region Logger ////\n setLogger(logger: LoggerInterface): void {\n this._logger = logger\n this.#rateLimiter.setLogger(this._logger)\n this.#operatingLimiter.setLogger(this._logger)\n this.#adaptiveDelayer.setLogger(this._logger)\n }\n\n getLogger(): LoggerInterface {\n return this._logger\n }\n // endregion ////\n\n async applyOperatingLimits(requestId: string, method: string, params?: any): Promise<void> {\n // 1. Check operating limit\n const operatingWait = await this.#operatingLimiter.waitIfNeeded(requestId, method, params)\n if (operatingWait > 0) {\n this.incrementStats('limitHits')\n this.#logMethodBlocked(this.#operatingLimiter.getTitle(), requestId, method, operatingWait)\n await this.#delay(operatingWait)\n } else {\n // 2. Apply adaptive delay\n const adaptiveDelay = await this.#adaptiveDelayer.waitIfNeeded(requestId, method, params)\n if (adaptiveDelay > 0) {\n this.incrementStats('limitHits')\n this.#logMethodBlocked(this.#adaptiveDelayer.getTitle(), requestId, method, adaptiveDelay)\n await this.#delay(adaptiveDelay)\n }\n }\n }\n\n /**\n * Checks and waits for the rate limit\n * The loop is needed for parallel requests (Promise.all())\n */\n async checkRateLimit(requestId: string, method: string): Promise<void> {\n // 3. Apply rate limit\n let waitTime\n let times = 1\n do {\n waitTime = await this.#rateLimiter.waitIfNeeded(requestId, method)\n if (waitTime > 0) {\n this.incrementStats('limitHits')\n this.#logMethodBlockedWithTimes(this.#rateLimiter.getTitle(), requestId, method, waitTime, times)\n await this.#delay(waitTime)\n times++\n }\n } while (waitTime > 0)\n }\n\n /**\n * Fans the response's `time` block out to all three limiters.\n *\n * `timeData` is `undefined` when the portal sent no `time` block at all, which\n * a success legitimately can — `rest.documentation.openapi` answers with the\n * OpenAPI document at the top level. The transport already skips this call in\n * that case; the parameter stays optional because `updateStats` is on the\n * public {@link ILimiter} contract and the transport is not its only caller.\n */\n async updateStats(\n requestId: string,\n method: string,\n timeData: PayloadTime | undefined\n ): Promise<void> {\n await this.#operatingLimiter.updateStats(requestId, method, timeData)\n await this.#adaptiveDelayer.updateStats(requestId, method, timeData)\n await this.#rateLimiter.updateStats(requestId, method, timeData)\n }\n\n async handleError(\n requestId: string,\n method: string,\n params: any,\n error: any,\n attempt: number\n ): Promise<number> {\n // Rate limit exceeded\n if (this.#isRateLimitError(error)) {\n // Since this is error handling, we take into account the number of attempts\n const wait = (await this.#handleRateLimitExceeded(requestId)) * Math.pow(1.5, attempt)\n this.#logError(this.#rateLimiter.getTitle(), requestId, 'QUERY_LIMIT_EXCEEDED', error.message, method, wait)\n return wait\n }\n\n // Operating limit exceeded\n if (this.#isOperatingLimitError(error)) {\n // Since this is error handling, we will increase the minimum to 10 seconds.\n const wait = Math.max(10_000, await this.#handleOperatingLimitError(requestId, method, params, error))\n this.#logError(this.#operatingLimiter.getTitle(), requestId, 'OPERATION_TIME_LIMIT', error.message, method, wait)\n return wait\n }\n\n // Client errors (HTTP 4xx) are deterministic — retrying cannot change the\n // outcome, so fail fast regardless of whether the error code is enumerated.\n // 429 (rate/operating limit) is handled above; 408 (timeout) stays retryable.\n if (this.#isNonRetryableClientError(error)) {\n this.#logNonRetryableClientError(requestId, error?.code ? `${error.code}` : '?', error?.message ?? '', method, Number(error?.status ?? 0))\n return 0\n }\n\n // Other exceptions\n if (!this.#isNeedThrowError(error)) {\n // Since this is error handling, we take into account the number of attempts\n const baseDelay = await this.#getErrorBackoff(requestId)\n const maxDelay = Math.max(30_000, baseDelay)\n const delay = Math.min(maxDelay, baseDelay * Math.pow(2, attempt))\n\n // Add jitter to prevent thundering herd\n const jitter = delay * 0.1 * (Math.random() * 2 - 1) // ±10% jitter\n const wait = Math.max(100, delay + jitter)\n\n this.#logSomeError(requestId, error?.code ? `${error.code}` : '?', error.message, method, wait)\n\n return wait\n }\n\n return 0 // We don't repeat\n }\n\n /**\n * Checks if the error is a rate limit\n */\n #isRateLimitError(error: any): boolean {\n return error.status === 503\n || error.code === 'QUERY_LIMIT_EXCEEDED'\n }\n\n /**\n * Delay when exceeding the rate limit\n */\n async #handleRateLimitExceeded(requestId: string): Promise<number> {\n return this.#rateLimiter.handleExceeded(requestId)\n }\n\n /**\n * Checks if the error is an operating limit\n *\n * @memo `OPERATION_TIME_LIMIT` && `429` - obtained through practical means\n * @memo This doesn't work for `batch` queries.\n */\n #isOperatingLimitError(error: any): boolean {\n return error.status === 429\n || error.code === 'OPERATION_TIME_LIMIT'\n }\n\n /**\n * Operating limit error delay\n *\n * @memo Currently, the errors don't include timings for operations.\n * For this reason, we will take data from the previous request\n */\n async #handleOperatingLimitError(requestId: string, method: string, params?: any, _error?: any): Promise<number> {\n return this.#operatingLimiter.getTimeToFree(requestId, method, params, _error)\n }\n\n /**\n * Checks if the error is a non-retryable client error (HTTP 4xx).\n *\n * `429` is excluded — it is handled as a rate/operating limit and is retried\n * with backoff. `408` (request timeout) is excluded — it is transient and is\n * governed by `retryOnNetworkError`.\n */\n #isNonRetryableClientError(error: any): boolean {\n const status = Number(error?.status ?? 0)\n if (Number.isNaN(status)) {\n return false\n }\n return status >= 400 && status < 500 && status !== 408 && status !== 429\n }\n\n /**\n * Checks whether attempts should be stopped if errors are encountered that are unclear.\n */\n #isNeedThrowError(error: any): boolean {\n const answerError = {\n code: error?.code ?? '-1',\n description: error?.message ?? ''\n }\n\n return [\n ...this.exceptionCodeForHard,\n ...this.exceptionCodeForSoft\n ].includes(answerError.code)\n || (answerError.description ?? '').includes('Could not find value for parameter')\n }\n\n /**\n * Built-in hard error codes (always throw, never retry).\n *\n * Includes authorization and fatal codes that must never be silently retried.\n * Use `RestrictionParams.hardErrorCodes` to extend this list with custom codes.\n */\n static readonly BUILT_IN_HARD_ERROR_CODES: readonly string[] = [\n 'ERR_BAD_REQUEST',\n 'JSSDK_UNKNOWN_ERROR',\n '100',\n 'INTERNAL_SERVER_ERROR', 'ERROR_UNEXPECTED_ANSWER', 'PORTAL_DELETED',\n 'ERROR_BATCH_METHOD_NOT_ALLOWED', 'ERROR_BATCH_LENGTH_EXCEEDED',\n 'NO_AUTH_FOUND',\n 'INVALID_REQUEST',\n 'OVERLOAD_LIMIT', 'expired_token', 'invalid_token',\n 'ACCESS_DENIED', 'INVALID_CREDENTIALS', 'user_access_error', 'insufficient_scope',\n // The `restApi:v3` spelling of `insufficient_scope`, pinned so the same\n // condition is delivered the same way on both versions. Without it the v3\n // form matches nothing — it is a different string — and the category rule\n // would soften it at 403 while the v2 form kept throwing. This is a missing\n // OAuth grant, a configuration fault rather than a per-record ACL check, so\n // it stays loud; the neighbouring `…ACCESSDENIEDEXCEPTION` is a permission\n // check and stays soft. (#460)\n 'BITRIX_REST_V3_EXCEPTION_INSUFFICIENTSCOPEEXCEPTION',\n // A refused redirect is deterministic: the portal will answer the next\n // attempt the same way, and every retry re-sends a request carrying an\n // access token to a host that wants to redirect it. Measured before this\n // line existed: three POSTs of the token-bearing batch before the error\n // surfaced, because the code arrives with `status: 0` and so misses the\n // non-retryable-4xx branch.\n 'JSSDK_HTTP_REDIRECT_BLOCKED',\n 'ERROR_MANIFEST_IS_NOT_AVAILABLE',\n 'allowed_only_intranet_user',\n 'NOT_FOUND',\n 'INVALID_ARG_VALUE'\n ]\n\n /**\n * Built-in soft error codes (returned as `AjaxResult` with error, never thrown).\n *\n * Use `RestrictionParams.softErrorCodes` to extend this list with custom codes.\n */\n static readonly BUILT_IN_SOFT_ERROR_CODES: readonly string[] = [\n 'ERROR_ENTITY_NOT_FOUND',\n 'BITRIX_REST_V3_EXCEPTION_ACCESSDENIEDEXCEPTION',\n 'BITRIX_REST_V3_EXCEPTION_INVALIDJSONEXCEPTION',\n 'BITRIX_REST_V3_EXCEPTION_INVALIDFILTEREXCEPTION',\n 'BITRIX_REST_V3_EXCEPTION_INVALIDSELECTEXCEPTION',\n 'BITRIX_REST_V3_EXCEPTION_ENTITYNOTFOUNDEXCEPTION',\n 'BITRIX_REST_V3_EXCEPTION_METHODNOTFOUNDEXCEPTION',\n 'BITRIX_REST_V3_EXCEPTION_UNKNOWNDTOPROPERTYEXCEPTION',\n 'BITRIX_REST_V3_EXCEPTION_VALIDATION_REQUESTVALIDATIONEXCEPTION',\n 'BITRIX_REST_V3_EXCEPTION_VALIDATION_DTOVALIDATIONEXCEPTION'\n ]\n\n /**\n * Codes that cause the SDK to throw immediately.\n *\n * Composed of:\n * - `BUILT_IN_HARD_ERROR_CODES` (always included)\n * - `NETWORK_ERROR` and `REQUEST_TIMEOUT` when `retryOnNetworkError === false`\n * - `RestrictionParams.hardErrorCodes` (user-provided extensions)\n */\n get exceptionCodeForHard(): string[] {\n const codes = [...RestrictionManager.BUILT_IN_HARD_ERROR_CODES]\n\n if (this.#config.retryOnNetworkError === false) {\n codes.push('NETWORK_ERROR', 'REQUEST_TIMEOUT')\n }\n\n if (this.#config.hardErrorCodes && this.#config.hardErrorCodes.length > 0) {\n codes.push(...this.#config.hardErrorCodes)\n }\n\n return codes\n }\n\n /**\n * Codes returned as `AjaxResult` with an `AjaxError` payload instead of thrown.\n *\n * Composed of:\n * - `BUILT_IN_SOFT_ERROR_CODES` (always included)\n * - `RestrictionParams.softErrorCodes` (user-provided extensions)\n */\n get exceptionCodeForSoft(): string[] {\n const codes = [...RestrictionManager.BUILT_IN_SOFT_ERROR_CODES]\n\n if (this.#config.softErrorCodes && this.#config.softErrorCodes.length > 0) {\n codes.push(...this.#config.softErrorCodes)\n }\n\n return codes\n }\n\n /**\n * Statuses a 4xx category rule must not claim.\n *\n * `401` belongs to the auth-refresh path, which owns it end to end. `408`\n * and `429` are the two retryable 4xx — the same pair\n * `#isNonRetryableClientError` excludes — and an error still being retried\n * has not been classified yet.\n *\n * `403` is deliberately **not** here. A permission or scope refusal is\n * caller-addressable, and `…_ACCESSDENIEDEXCEPTION` is already in the\n * built-in soft list, so excluding 403 would leave one 403 soft by list and\n * its neighbour thrown — exactly the per-code arbitrariness this rule\n * removes. (#460)\n */\n static readonly #CATEGORY_RULE_EXCLUDED_STATUSES: readonly number[] = [401, 408, 429]\n\n /**\n * Should this error reach the caller inside an `AjaxResult` rather than be\n * thrown?\n *\n * Evaluated in a fixed order, most specific first:\n *\n * 1. a code in `exceptionCodeForHard` throws — so the rule can never soften\n * a credential failure, and a caller's `hardErrorCodes` always wins;\n * 2. a code in `exceptionCodeForSoft` is soft — so the built-in list, the v2\n * codes and a caller's `softErrorCodes` keep working unchanged;\n * 3. an error that arrived in the **v3 error envelope** carrying a **4xx\n * other than 401 / 408 / 429** is soft, whatever its code;\n * 4. otherwise it throws.\n *\n * Step 3 was opt-in through the 2.x line, behind `classifyV3ErrorsByCategory`,\n * and is simply the behaviour as of 3.0.0 — the flag is gone rather than\n * inverted, because a permanent compatibility switch is what the 2.x\n * arrangement was scheduled to avoid becoming (#480). A caller who needs the\n * old classification for one code pins it in `hardErrorCodes`, which step 1\n * still honours.\n *\n * Step 3 keys on the envelope the response actually carried, never on the\n * client's own version: a gateway in front of the v3 controller is documented\n * to sometimes answer in the flat v2 shape, and such a body is left to the\n * lists.\n */\n isSoftError(error: unknown): boolean {\n const code = (error as { code?: unknown } | null)?.code\n const codeText = typeof code === 'string' ? code : ''\n\n if (this.exceptionCodeForHard.includes(codeText)) {\n return false\n }\n\n if (this.exceptionCodeForSoft.includes(codeText)) {\n return true\n }\n\n // This check, not the status range below, is what keeps an untagged error\n // out of the rule. Every other path that builds an `AjaxError` — the\n // 401 refresh, a timeout, a network failure, `_convertUnknownErrorToAjaxError`\n // — leaves `isV3Envelope` undefined, and today each also carries a status\n // the range happens to exclude. That overlap is a coincidence, not a\n // guarantee: a future conversion path producing a synthetic 403 without an\n // envelope must still be refused here. Do not remove this as redundant.\n if ((error as { isV3Envelope?: unknown } | null)?.isV3Envelope !== true) {\n return false\n }\n\n const status = Number((error as { status?: unknown } | null)?.status ?? 0)\n\n return Number.isInteger(status)\n && status >= 400\n && status < 500\n && !RestrictionManager.#CATEGORY_RULE_EXCLUDED_STATUSES.includes(status)\n }\n\n /**\n * Delay due to unknown errors\n */\n async #getErrorBackoff(_requestId: string): Promise<number> {\n // Unreachable today — the constructor merges against the defaults, so\n // `retryDelay` is always set. Kept because the alternative spelling is\n // `retryDelay!`, the assertion pattern this file just finished removing,\n // and an absent value there produces `NaN` delays rather than a clean\n // failure — a retry storm dressed up as a backoff.\n return this.#config.retryDelay ?? ParamsFactory.getDefault().retryDelay!\n }\n\n incrementError(method: string): void {\n const current = this.#errorCounts.get(method) || 0\n this.#errorCounts.set(method, current + 1)\n this.incrementStats('consecutiveErrors')\n }\n\n resetErrors(method: string): void {\n this.#errorCounts.delete(method)\n this.#stats.consecutiveErrors = 0\n }\n\n incrementStats(stat: keyof Pick<RestrictionManagerStats, 'retries' | 'consecutiveErrors' | 'limitHits'>): void {\n this.#stats[stat]++\n }\n\n /**\n * Returns job statistics\n */\n getStats(): RestrictionManagerStats & {\n adaptiveDelayAvg: number\n errorCounts: Record<string, number>\n } {\n return {\n ...this.#stats,\n ...this.#rateLimiter.getStats(),\n ...this.#adaptiveDelayer.getStats(),\n ...this.#operatingLimiter.getStats(),\n errorCounts: Object.fromEntries(this.#errorCounts)\n }\n }\n\n /**\n * Resets limiters and statistics\n */\n async reset(): Promise<void> {\n await this.#rateLimiter.reset()\n await this.#operatingLimiter.reset()\n await this.#adaptiveDelayer.reset()\n this.#errorCounts.clear()\n\n this.#stats = {\n retries: 0,\n consecutiveErrors: 0,\n limitHits: 0\n }\n }\n\n /**\n * Replaces the named parameters, keeping the ones not mentioned.\n *\n * It used to assign — `this.#config = params` — so a caller changing one\n * field silently lost every other one. `setRestrictionManagerParams({\n * maxRetries: 5 })` after a careful setup left `hardErrorCodes`,\n * `softErrorCodes`, `retryOnNetworkError` **and** `rateLimit` all\n * `undefined`, with no error and nothing in the log. (#479)\n *\n * The tell was in our own documentation: every example of this method spreads\n * `...ParamsFactory.getDefault()` first. That was not house style, it was a\n * workaround repeated everywhere the method appeared.\n *\n * **The merge is shallow.** `rateLimit`, `operatingLimit` and\n * `adaptiveConfig` are replaced **whole**, not merged field by field — pass\n * one and you supply all of its fields, omit it and it is left untouched.\n * Deep-merging them would let a half-specified `rateLimit` combine with an\n * older one into a pair of numbers nobody chose; replacing keeps a limiter's\n * configuration something a caller stated in one place.\n *\n * A sub-limiter is only reconfigured when its own block was supplied, which\n * is also why the non-null assertions here are gone: they claimed the caller\n * always sends every block, and the whole point of this method is that they\n * do not. A block that *is* supplied must be whole — `assertBlock` refuses a\n * partial one rather than letting `1000 / undefined` switch rate limiting off\n * for the rest of the process.\n *\n * An **explicitly `undefined`** value counts as \"not mentioned\". Object\n * spread would otherwise copy the key and erase the field, which is not what\n * `maxRetries: enabled ? 5 : undefined` means.\n */\n async setConfig(params: RestrictionParams): Promise<void> {\n const patch = definedOnly(params)\n\n assertBlock(patch.rateLimit, 'rateLimit', RATE_LIMIT_FIELDS)\n assertBlock(patch.operatingLimit, 'operatingLimit', OPERATING_LIMIT_FIELDS)\n assertBlock(patch.adaptiveConfig, 'adaptiveConfig', ADAPTIVE_CONFIG_FIELDS)\n\n this.#config = cloneParams({ ...this.#config, ...patch })\n\n if (patch.rateLimit !== undefined) {\n await this.#rateLimiter.setConfig({ ...patch.rateLimit })\n }\n\n if (patch.operatingLimit !== undefined) {\n await this.#operatingLimiter.setConfig({ ...patch.operatingLimit })\n }\n\n if (patch.adaptiveConfig !== undefined) {\n await this.#adaptiveDelayer.setConfig({ ...patch.adaptiveConfig })\n }\n }\n\n /**\n * A **copy**, nested blocks and code arrays included.\n *\n * A shallow spread handed the caller the very objects the sub-limiters use:\n * `RateLimiter` rewrites `drainRate` and `burstLimit` in place while it\n * throttles adaptively, so a caller reading the policy saw it change under\n * them, and a caller pushing onto the returned `hardErrorCodes` reconfigured\n * the manager without ever calling the setter. (#479)\n */\n getParams(): RestrictionParams {\n return cloneParams(this.#config)\n }\n\n /**\n * Delay function\n */\n async #delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n }\n\n /**\n * Public access to the delay function\n */\n async waiteDelay(ms: number): Promise<void> {\n return this.#delay(ms)\n }\n\n // region Log ////\n #logMethodBlocked(limiter: string, requestId: string, method: string, wait: number) {\n this.getLogger().notice(`${limiter} blocked method ${method}`, {\n requestId,\n method,\n wait,\n limiter\n }).catch(() => {})\n }\n\n #logMethodBlockedWithTimes(limiter: string, requestId: string, method: string, wait: number, times: number) {\n this.getLogger().notice(`${limiter} blocked method ${method} | ${times} times`, {\n requestId,\n method,\n times,\n wait,\n limiter\n }).catch(() => {})\n }\n\n #logError(limiter: string, requestId: string, code: string, message: string, method: string, wait: number) {\n this.getLogger().error(`${limiter} recognized the ${code} error for the ${method} method`, {\n requestId,\n method,\n wait,\n limiter,\n error: {\n code,\n message\n }\n }).catch(() => {})\n }\n\n #logSomeError(requestId: string, code: string, message: string, method: string, wait: number) {\n this.getLogger().error(`recognized the ${code} error for the ${method} method`, {\n requestId,\n method,\n wait,\n error: {\n code,\n message\n }\n }).catch(() => {})\n }\n\n #logNonRetryableClientError(requestId: string, code: string, message: string, method: string, status: number) {\n this.getLogger().error(`client error ${status} (${code}) for the ${method} method is not retryable`, {\n requestId,\n method,\n status,\n error: {\n code,\n message\n }\n }).catch(() => {})\n }\n // endregion ////\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAgBA,MAAM,iBAAA,GAAoB,CAAC,YAAA,EAAc,WAAA,EAAa,iBAAiB,CAAA;AACvE,MAAM,sBAAA,GAAyB,CAAC,UAAA,EAAY,SAAA,EAAW,cAAc,CAAA;AACrE,MAAM,sBAAA,GAAyB,CAAC,kBAAA,EAAoB,aAAA,EAAe,YAAY,SAAS,CAAA;AAgBxF,SAAS,YAAY,MAAA,EAA8C;AACjE,EAAA,OAAO,MAAA,CAAO,WAAA;AAAA,IACZ,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CAAE,MAAA,CAAO,CAAC,GAAG,KAAK,CAAA,KAAM,KAAA,KAAU,MAAS;AAAA,GAClE;AACF;AAJS,MAAA,CAAA,WAAA,EAAA,aAAA,CAAA;AAgBT,SAAS,YAAY,MAAA,EAA8C;AACjE,EAAA,OAAO;AAAA,IACL,GAAG,MAAA;AAAA,IACH,GAAI,MAAA,CAAO,SAAA,GAAY,EAAE,SAAA,EAAW,EAAE,GAAG,MAAA,CAAO,SAAA,EAAU,EAAE,GAAI,EAAC;AAAA,IACjE,GAAI,MAAA,CAAO,cAAA,GAAiB,EAAE,cAAA,EAAgB,EAAE,GAAG,MAAA,CAAO,cAAA,EAAe,EAAE,GAAI,EAAC;AAAA,IAChF,GAAI,MAAA,CAAO,cAAA,GAAiB,EAAE,cAAA,EAAgB,EAAE,GAAG,MAAA,CAAO,cAAA,EAAe,EAAE,GAAI,EAAC;AAAA,IAChF,GAAI,MAAA,CAAO,cAAA,GAAiB,EAAE,cAAA,EAAgB,CAAC,GAAG,MAAA,CAAO,cAAc,CAAA,EAAE,GAAI,EAAC;AAAA,IAC9E,GAAI,MAAA,CAAO,cAAA,GAAiB,EAAE,cAAA,EAAgB,CAAC,GAAG,MAAA,CAAO,cAAc,CAAA,EAAE,GAAI;AAAC,GAChF;AACF;AATS,MAAA,CAAA,WAAA,EAAA,aAAA,CAAA;AAyBT,SAAS,WAAA,CACP,KAAA,EACA,IAAA,EACA,MAAA,EACM;AACN,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GAAU,KAAA;AAChB,EAAA,MAAM,OAAA,GAAU,OAAA,KAAY,IAAA,GACxB,CAAC,GAAG,MAAM,CAAA,GACV,MAAA,CAAO,MAAA,CAAO,CAAA,KAAA,KAAS,OAAA,CAAQ,KAAK,MAAM,MAAS,CAAA;AAEvD,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,IAAI,QAAA,CAAS;AAAA,IACjB,IAAA,EAAM,oCAAA;AAAA,IACN,aAAa,CAAA,+BAAA,EAAkC,IAAI,4EACnC,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAC,CAAA,2DAAA,CAAA;AAAA,IAClC,MAAA,EAAQ;AAAA,GACT,CAAA;AACH;AAzBS,MAAA,CAAA,WAAA,EAAA,aAAA,CAAA;AAqCF,MAAM,kBAAA,CAAmB;AAAA,EAhHhC;AAgHgC,IAAA,MAAA,CAAA,IAAA,EAAA,oBAAA,CAAA;AAAA;AAAA,EAC9B,YAAA;AAAA,EACA,iBAAA;AAAA,EACA,gBAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA,GAAuF;AAAA;AAAA,IAErF,OAAA,EAAS,CAAA;AAAA;AAAA,IAET,iBAAA,EAAmB,CAAA;AAAA;AAAA,IAEnB,SAAA,EAAW;AAAA,GACb;AAAA,EAEA,YAAA,uBAAmB,GAAA,EAAoB;AAAA,EAE/B,OAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWR,YAAY,MAAA,EAA2B;AACrC,IAAA,IAAA,CAAK,OAAA,GAAU,cAAc,gBAAA,EAAiB;AAE9C,IAAA,MAAM,KAAA,GAAQ,YAAY,MAAM,CAAA;AAMhC,IAAA,WAAA,CAAY,KAAA,CAAM,SAAA,EAAW,WAAA,EAAa,iBAAiB,CAAA;AAC3D,IAAA,WAAA,CAAY,KAAA,CAAM,cAAA,EAAgB,gBAAA,EAAkB,sBAAsB,CAAA;AAC1E,IAAA,WAAA,CAAY,KAAA,CAAM,cAAA,EAAgB,gBAAA,EAAkB,sBAAsB,CAAA;AAE1E,IAAA,IAAA,CAAK,OAAA,GAAU,YAAY,EAAE,GAAG,cAAc,UAAA,EAAW,EAAG,GAAG,KAAA,EAAO,CAAA;AACtE,IAAA,IAAA,CAAK,YAAA,GAAe,IAAI,WAAA,CAAY,IAAA,CAAK,QAAQ,SAA4B,CAAA;AAC7E,IAAA,IAAA,CAAK,iBAAA,GAAoB,IAAI,gBAAA,CAAiB,IAAA,CAAK,QAAQ,cAAsC,CAAA;AACjG,IAAA,IAAA,CAAK,mBAAmB,IAAI,eAAA,CAAgB,KAAK,OAAA,CAAQ,cAAA,EAAkC,KAAK,iBAAiB,CAAA;AAAA,EACnH;AAAA;AAAA,EAGA,UAAU,MAAA,EAA+B;AACvC,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,IAAA,IAAA,CAAK,YAAA,CAAa,SAAA,CAAU,IAAA,CAAK,OAAO,CAAA;AACxC,IAAA,IAAA,CAAK,iBAAA,CAAkB,SAAA,CAAU,IAAA,CAAK,OAAO,CAAA;AAC7C,IAAA,IAAA,CAAK,gBAAA,CAAiB,SAAA,CAAU,IAAA,CAAK,OAAO,CAAA;AAAA,EAC9C;AAAA,EAEA,SAAA,GAA6B;AAC3B,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,oBAAA,CAAqB,SAAA,EAAmB,MAAA,EAAgB,MAAA,EAA6B;AAEzF,IAAA,MAAM,gBAAgB,MAAM,IAAA,CAAK,kBAAkB,YAAA,CAAa,SAAA,EAAW,QAAQ,MAAM,CAAA;AACzF,IAAA,IAAI,gBAAgB,CAAA,EAAG;AACrB,MAAA,IAAA,CAAK,eAAe,WAAW,CAAA;AAC/B,MAAA,IAAA,CAAK,kBAAkB,IAAA,CAAK,iBAAA,CAAkB,UAAS,EAAG,SAAA,EAAW,QAAQ,aAAa,CAAA;AAC1F,MAAA,MAAM,IAAA,CAAK,OAAO,aAAa,CAAA;AAAA,IACjC,CAAA,MAAO;AAEL,MAAA,MAAM,gBAAgB,MAAM,IAAA,CAAK,iBAAiB,YAAA,CAAa,SAAA,EAAW,QAAQ,MAAM,CAAA;AACxF,MAAA,IAAI,gBAAgB,CAAA,EAAG;AACrB,QAAA,IAAA,CAAK,eAAe,WAAW,CAAA;AAC/B,QAAA,IAAA,CAAK,kBAAkB,IAAA,CAAK,gBAAA,CAAiB,UAAS,EAAG,SAAA,EAAW,QAAQ,aAAa,CAAA;AACzF,QAAA,MAAM,IAAA,CAAK,OAAO,aAAa,CAAA;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cAAA,CAAe,SAAA,EAAmB,MAAA,EAA+B;AAErE,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,GAAG;AACD,MAAA,QAAA,GAAW,MAAM,IAAA,CAAK,YAAA,CAAa,YAAA,CAAa,WAAW,MAAM,CAAA;AACjE,MAAA,IAAI,WAAW,CAAA,EAAG;AAChB,QAAA,IAAA,CAAK,eAAe,WAAW,CAAA;AAC/B,QAAA,IAAA,CAAK,0BAAA,CAA2B,KAAK,YAAA,CAAa,QAAA,IAAY,SAAA,EAAW,MAAA,EAAQ,UAAU,KAAK,CAAA;AAChG,QAAA,MAAM,IAAA,CAAK,OAAO,QAAQ,CAAA;AAC1B,QAAA,KAAA,EAAA;AAAA,MACF;AAAA,IACF,SAAS,QAAA,GAAW,CAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,WAAA,CACJ,SAAA,EACA,MAAA,EACA,QAAA,EACe;AACf,IAAA,MAAM,IAAA,CAAK,iBAAA,CAAkB,WAAA,CAAY,SAAA,EAAW,QAAQ,QAAQ,CAAA;AACpE,IAAA,MAAM,IAAA,CAAK,gBAAA,CAAiB,WAAA,CAAY,SAAA,EAAW,QAAQ,QAAQ,CAAA;AACnE,IAAA,MAAM,IAAA,CAAK,YAAA,CAAa,WAAA,CAAY,SAAA,EAAW,QAAQ,QAAQ,CAAA;AAAA,EACjE;AAAA,EAEA,MAAM,WAAA,CACJ,SAAA,EACA,MAAA,EACA,MAAA,EACA,OACA,OAAA,EACiB;AAEjB,IAAA,IAAI,IAAA,CAAK,iBAAA,CAAkB,KAAK,CAAA,EAAG;AAEjC,MAAA,MAAM,IAAA,GAAQ,MAAM,IAAA,CAAK,wBAAA,CAAyB,SAAS,CAAA,GAAK,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,OAAO,CAAA;AACrF,MAAA,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,YAAA,CAAa,QAAA,EAAS,EAAG,WAAW,sBAAA,EAAwB,KAAA,CAAM,OAAA,EAAS,MAAA,EAAQ,IAAI,CAAA;AAC3G,MAAA,OAAO,IAAA;AAAA,IACT;AAGA,IAAA,IAAI,IAAA,CAAK,sBAAA,CAAuB,KAAK,CAAA,EAAG;AAEtC,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,GAAA,EAAQ,MAAM,IAAA,CAAK,0BAAA,CAA2B,SAAA,EAAW,MAAA,EAAQ,MAAA,EAAQ,KAAK,CAAC,CAAA;AACrG,MAAA,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,iBAAA,CAAkB,QAAA,EAAS,EAAG,WAAW,sBAAA,EAAwB,KAAA,CAAM,OAAA,EAAS,MAAA,EAAQ,IAAI,CAAA;AAChH,MAAA,OAAO,IAAA;AAAA,IACT;AAKA,IAAA,IAAI,IAAA,CAAK,0BAAA,CAA2B,KAAK,CAAA,EAAG;AAC1C,MAAA,IAAA,CAAK,4BAA4B,SAAA,EAAW,KAAA,EAAO,IAAA,GAAO,CAAA,EAAG,MAAM,IAAI,CAAA,CAAA,GAAK,GAAA,EAAK,KAAA,EAAO,WAAW,EAAA,EAAI,MAAA,EAAQ,OAAO,KAAA,EAAO,MAAA,IAAU,CAAC,CAAC,CAAA;AACzI,MAAA,OAAO,CAAA;AAAA,IACT;AAGA,IAAA,IAAI,CAAC,IAAA,CAAK,iBAAA,CAAkB,KAAK,CAAA,EAAG;AAElC,MAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,gBAAA,CAAiB,SAAS,CAAA;AACvD,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,GAAA,EAAQ,SAAS,CAAA;AAC3C,MAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,CAAI,QAAA,EAAU,YAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAO,CAAC,CAAA;AAGjE,MAAA,MAAM,SAAS,KAAA,GAAQ,GAAA,IAAO,IAAA,CAAK,MAAA,KAAW,CAAA,GAAI,CAAA,CAAA;AAClD,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,QAAQ,MAAM,CAAA;AAEzC,MAAA,IAAA,CAAK,aAAA,CAAc,SAAA,EAAW,KAAA,EAAO,IAAA,GAAO,CAAA,EAAG,KAAA,CAAM,IAAI,CAAA,CAAA,GAAK,GAAA,EAAK,KAAA,CAAM,OAAA,EAAS,MAAA,EAAQ,IAAI,CAAA;AAE9F,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,OAAO,CAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,KAAA,EAAqB;AACrC,IAAA,OAAO,KAAA,CAAM,MAAA,KAAW,GAAA,IACnB,KAAA,CAAM,IAAA,KAAS,sBAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,yBAAyB,SAAA,EAAoC;AACjE,IAAA,OAAO,IAAA,CAAK,YAAA,CAAa,cAAA,CAAe,SAAS,CAAA;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,uBAAuB,KAAA,EAAqB;AAC1C,IAAA,OAAO,KAAA,CAAM,MAAA,KAAW,GAAA,IACnB,KAAA,CAAM,IAAA,KAAS,sBAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,0BAAA,CAA2B,SAAA,EAAmB,MAAA,EAAgB,QAAc,MAAA,EAA+B;AAC/G,IAAA,OAAO,KAAK,iBAAA,CAAkB,aAAA,CAAc,SAAA,EAAW,MAAA,EAAQ,QAAQ,MAAM,CAAA;AAAA,EAC/E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,2BAA2B,KAAA,EAAqB;AAC9C,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,KAAA,EAAO,MAAA,IAAU,CAAC,CAAA;AACxC,IAAA,IAAI,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,EAAG;AACxB,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,OAAO,UAAU,GAAA,IAAO,MAAA,GAAS,GAAA,IAAO,MAAA,KAAW,OAAO,MAAA,KAAW,GAAA;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,KAAA,EAAqB;AACrC,IAAA,MAAM,WAAA,GAAc;AAAA,MAClB,IAAA,EAAM,OAAO,IAAA,IAAQ,IAAA;AAAA,MACrB,WAAA,EAAa,OAAO,OAAA,IAAW;AAAA,KACjC;AAEA,IAAA,OAAO;AAAA,MACL,GAAG,IAAA,CAAK,oBAAA;AAAA,MACR,GAAG,IAAA,CAAK;AAAA,KACV,CAAE,SAAS,WAAA,CAAY,IAAI,MACvB,WAAA,CAAY,WAAA,IAAe,EAAA,EAAI,QAAA,CAAS,oCAAoC,CAAA;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAgB,yBAAA,GAA+C;AAAA,IAC7D,iBAAA;AAAA,IACA,qBAAA;AAAA,IACA,KAAA;AAAA,IACA,uBAAA;AAAA,IAAyB,yBAAA;AAAA,IAA2B,gBAAA;AAAA,IACpD,gCAAA;AAAA,IAAkC,6BAAA;AAAA,IAClC,eAAA;AAAA,IACA,iBAAA;AAAA,IACA,gBAAA;AAAA,IAAkB,eAAA;AAAA,IAAiB,eAAA;AAAA,IACnC,eAAA;AAAA,IAAiB,qBAAA;AAAA,IAAuB,mBAAA;AAAA,IAAqB,oBAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQ7D,qDAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,6BAAA;AAAA,IACA,iCAAA;AAAA,IACA,4BAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAgB,yBAAA,GAA+C;AAAA,IAC7D,wBAAA;AAAA,IACA,gDAAA;AAAA,IACA,+CAAA;AAAA,IACA,iDAAA;AAAA,IACA,iDAAA;AAAA,IACA,kDAAA;AAAA,IACA,kDAAA;AAAA,IACA,sDAAA;AAAA,IACA,gEAAA;AAAA,IACA;AAAA,GACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,IAAI,oBAAA,GAAiC;AACnC,IAAA,MAAM,KAAA,GAAQ,CAAC,GAAG,kBAAA,CAAmB,yBAAyB,CAAA;AAE9D,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,mBAAA,KAAwB,KAAA,EAAO;AAC9C,MAAA,KAAA,CAAM,IAAA,CAAK,iBAAiB,iBAAiB,CAAA;AAAA,IAC/C;AAEA,IAAA,IAAI,KAAK,OAAA,CAAQ,cAAA,IAAkB,KAAK,OAAA,CAAQ,cAAA,CAAe,SAAS,CAAA,EAAG;AACzE,MAAA,KAAA,CAAM,IAAA,CAAK,GAAG,IAAA,CAAK,OAAA,CAAQ,cAAc,CAAA;AAAA,IAC3C;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,oBAAA,GAAiC;AACnC,IAAA,MAAM,KAAA,GAAQ,CAAC,GAAG,kBAAA,CAAmB,yBAAyB,CAAA;AAE9D,IAAA,IAAI,KAAK,OAAA,CAAQ,cAAA,IAAkB,KAAK,OAAA,CAAQ,cAAA,CAAe,SAAS,CAAA,EAAG;AACzE,MAAA,KAAA,CAAM,IAAA,CAAK,GAAG,IAAA,CAAK,OAAA,CAAQ,cAAc,CAAA;AAAA,IAC3C;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,OAAgB,gCAAA,GAAsD,CAAC,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4BpF,YAAY,KAAA,EAAyB;AACnC,IAAA,MAAM,OAAQ,KAAA,EAAqC,IAAA;AACnD,IAAA,MAAM,QAAA,GAAW,OAAO,IAAA,KAAS,QAAA,GAAW,IAAA,GAAO,EAAA;AAEnD,IAAA,IAAI,IAAA,CAAK,oBAAA,CAAqB,QAAA,CAAS,QAAQ,CAAA,EAAG;AAChD,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,IAAI,IAAA,CAAK,oBAAA,CAAqB,QAAA,CAAS,QAAQ,CAAA,EAAG;AAChD,MAAA,OAAO,IAAA;AAAA,IACT;AASA,IAAA,IAAK,KAAA,EAA6C,iBAAiB,IAAA,EAAM;AACvE,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,MAAM,MAAA,GAAS,MAAA,CAAQ,KAAA,EAAuC,MAAA,IAAU,CAAC,CAAA;AAEzE,IAAA,OAAO,MAAA,CAAO,SAAA,CAAU,MAAM,CAAA,IACzB,MAAA,IAAU,GAAA,IACV,MAAA,GAAS,GAAA,IACT,CAAC,kBAAA,CAAmB,gCAAA,CAAiC,QAAA,CAAS,MAAM,CAAA;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,UAAA,EAAqC;AAM1D,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,UAAA,IAAc,aAAA,CAAc,YAAW,CAAE,UAAA;AAAA,EAC/D;AAAA,EAEA,eAAe,MAAA,EAAsB;AACnC,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,MAAM,CAAA,IAAK,CAAA;AACjD,IAAA,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,OAAA,GAAU,CAAC,CAAA;AACzC,IAAA,IAAA,CAAK,eAAe,mBAAmB,CAAA;AAAA,EACzC;AAAA,EAEA,YAAY,MAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,YAAA,CAAa,OAAO,MAAM,CAAA;AAC/B,IAAA,IAAA,CAAK,OAAO,iBAAA,GAAoB,CAAA;AAAA,EAClC;AAAA,EAEA,eAAe,IAAA,EAAgG;AAC7G,IAAA,IAAA,CAAK,OAAO,IAAI,CAAA,EAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAA,GAGE;AACA,IAAA,OAAO;AAAA,MACL,GAAG,IAAA,CAAK,MAAA;AAAA,MACR,GAAG,IAAA,CAAK,YAAA,CAAa,QAAA,EAAS;AAAA,MAC9B,GAAG,IAAA,CAAK,gBAAA,CAAiB,QAAA,EAAS;AAAA,MAClC,GAAG,IAAA,CAAK,iBAAA,CAAkB,QAAA,EAAS;AAAA,MACnC,WAAA,EAAa,MAAA,CAAO,WAAA,CAAY,IAAA,CAAK,YAAY;AAAA,KACnD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAA,GAAuB;AAC3B,IAAA,MAAM,IAAA,CAAK,aAAa,KAAA,EAAM;AAC9B,IAAA,MAAM,IAAA,CAAK,kBAAkB,KAAA,EAAM;AACnC,IAAA,MAAM,IAAA,CAAK,iBAAiB,KAAA,EAAM;AAClC,IAAA,IAAA,CAAK,aAAa,KAAA,EAAM;AAExB,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,OAAA,EAAS,CAAA;AAAA,MACT,iBAAA,EAAmB,CAAA;AAAA,MACnB,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiCA,MAAM,UAAU,MAAA,EAA0C;AACxD,IAAA,MAAM,KAAA,GAAQ,YAAY,MAAM,CAAA;AAEhC,IAAA,WAAA,CAAY,KAAA,CAAM,SAAA,EAAW,WAAA,EAAa,iBAAiB,CAAA;AAC3D,IAAA,WAAA,CAAY,KAAA,CAAM,cAAA,EAAgB,gBAAA,EAAkB,sBAAsB,CAAA;AAC1E,IAAA,WAAA,CAAY,KAAA,CAAM,cAAA,EAAgB,gBAAA,EAAkB,sBAAsB,CAAA;AAE1E,IAAA,IAAA,CAAK,OAAA,GAAU,YAAY,EAAE,GAAG,KAAK,OAAA,EAAS,GAAG,OAAO,CAAA;AAExD,IAAA,IAAI,KAAA,CAAM,cAAc,MAAA,EAAW;AACjC,MAAA,MAAM,KAAK,YAAA,CAAa,SAAA,CAAU,EAAE,GAAG,KAAA,CAAM,WAAW,CAAA;AAAA,IAC1D;AAEA,IAAA,IAAI,KAAA,CAAM,mBAAmB,MAAA,EAAW;AACtC,MAAA,MAAM,KAAK,iBAAA,CAAkB,SAAA,CAAU,EAAE,GAAG,KAAA,CAAM,gBAAgB,CAAA;AAAA,IACpE;AAEA,IAAA,IAAI,KAAA,CAAM,mBAAmB,MAAA,EAAW;AACtC,MAAA,MAAM,KAAK,gBAAA,CAAiB,SAAA,CAAU,EAAE,GAAG,KAAA,CAAM,gBAAgB,CAAA;AAAA,IACnE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,SAAA,GAA+B;AAC7B,IAAA,OAAO,WAAA,CAAY,KAAK,OAAO,CAAA;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,EAAA,EAA2B;AACtC,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAA,OAAA,KAAW,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,EAAA,EAA2B;AAC1C,IAAA,OAAO,IAAA,CAAK,OAAO,EAAE,CAAA;AAAA,EACvB;AAAA;AAAA,EAGA,iBAAA,CAAkB,OAAA,EAAiB,SAAA,EAAmB,MAAA,EAAgB,IAAA,EAAc;AAClF,IAAA,IAAA,CAAK,WAAU,CAAE,MAAA,CAAO,GAAG,OAAO,CAAA,gBAAA,EAAmB,MAAM,CAAA,CAAA,EAAI;AAAA,MAC7D,SAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAA;AAAA,MACA;AAAA,KACD,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAAA,EACnB;AAAA,EAEA,0BAAA,CAA2B,OAAA,EAAiB,SAAA,EAAmB,MAAA,EAAgB,MAAc,KAAA,EAAe;AAC1G,IAAA,IAAA,CAAK,SAAA,GAAY,MAAA,CAAO,CAAA,EAAG,OAAO,CAAA,gBAAA,EAAmB,MAAM,CAAA,GAAA,EAAM,KAAK,CAAA,MAAA,CAAA,EAAU;AAAA,MAC9E,SAAA;AAAA,MACA,MAAA;AAAA,MACA,KAAA;AAAA,MACA,IAAA;AAAA,MACA;AAAA,KACD,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAAA,EACnB;AAAA,EAEA,UAAU,OAAA,EAAiB,SAAA,EAAmB,IAAA,EAAc,OAAA,EAAiB,QAAgB,IAAA,EAAc;AACzG,IAAA,IAAA,CAAK,SAAA,GAAY,KAAA,CAAM,CAAA,EAAG,OAAO,CAAA,gBAAA,EAAmB,IAAI,CAAA,eAAA,EAAkB,MAAM,CAAA,OAAA,CAAA,EAAW;AAAA,MACzF,SAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAA;AAAA,MACA,OAAA;AAAA,MACA,KAAA,EAAO;AAAA,QACL,IAAA;AAAA,QACA;AAAA;AACF,KACD,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAAA,EACnB;AAAA,EAEA,aAAA,CAAc,SAAA,EAAmB,IAAA,EAAc,OAAA,EAAiB,QAAgB,IAAA,EAAc;AAC5F,IAAA,IAAA,CAAK,WAAU,CAAE,KAAA,CAAM,kBAAkB,IAAI,CAAA,eAAA,EAAkB,MAAM,CAAA,OAAA,CAAA,EAAW;AAAA,MAC9E,SAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAA;AAAA,MACA,KAAA,EAAO;AAAA,QACL,IAAA;AAAA,QACA;AAAA;AACF,KACD,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAAA,EACnB;AAAA,EAEA,2BAAA,CAA4B,SAAA,EAAmB,IAAA,EAAc,OAAA,EAAiB,QAAgB,MAAA,EAAgB;AAC5G,IAAA,IAAA,CAAK,SAAA,GAAY,KAAA,CAAM,CAAA,aAAA,EAAgB,MAAM,CAAA,EAAA,EAAK,IAAI,CAAA,UAAA,EAAa,MAAM,CAAA,wBAAA,CAAA,EAA4B;AAAA,MACnG,SAAA;AAAA,MACA,MAAA;AAAA,MACA,MAAA;AAAA,MACA,KAAA,EAAO;AAAA,QACL,IAAA;AAAA,QACA;AAAA;AACF,KACD,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAAA,EACnB;AAAA;AAEF;;;;"}