@ryuzaki13/react-foundation-lib 1.9.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/error-report/safeValue.ts","../../src/error-report/breadcrumbs.ts","../../src/error-report/errorInfo.ts","../../src/error-report/diagnostics.ts","../../src/error-report/environment.ts","../../src/error-report/drafts.ts","../../src/error-report/runtimeDeduplication.ts","../../src/error-report/transport.ts","../../src/error-report/capture.ts","../../src/error-report/runtime.ts"],"sourcesContent":["import type { ErrorReportSafeValue } from \"./types\";\n\nconst MAX_DEPTH = 4;\nconst MAX_ARRAY_ITEMS = 20;\nconst MAX_OBJECT_KEYS = 40;\n\n/**\n * Превращает произвольное значение в JSON-совместимую диагностическую форму.\n * Значения сохраняются читаемыми, потому что queryKey/meta/context нужны\n * для восстановления пользовательского сценария; тяжелые данные query cache\n * отсекаются отдельно и сюда не передаются.\n */\nexport function createDiagnosticValue(value: unknown, depth = 0): ErrorReportSafeValue {\n\tif (depth >= MAX_DEPTH) return { type: \"truncated\" };\n\tif (value === null || typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n\t\treturn value;\n\t}\n\tif (value === undefined) return { type: \"undefined\" };\n\tif (value instanceof Date) return value.toISOString();\n\tif (Array.isArray(value)) {\n\t\treturn value.slice(0, MAX_ARRAY_ITEMS).map((item) => createDiagnosticValue(item, depth + 1));\n\t}\n\tif (typeof value === \"object\") {\n\t\tconst entries = Object.entries(value as Record<string, unknown>).slice(0, MAX_OBJECT_KEYS);\n\n\t\treturn Object.fromEntries(entries.map(([key, item]) => [key, createDiagnosticValue(item, depth + 1)]));\n\t}\n\tif (typeof value === \"function\") return { type: \"function\" };\n\tif (typeof value === \"symbol\") return { type: \"symbol\" };\n\tif (typeof value === \"bigint\") return value.toString();\n\n\treturn { type: \"unknown\" };\n}\n\n/**\n * Описывает форму данных кеша без самих значений: типы, размеры массивов и ключи объектов.\n */\nexport function createDataShape(value: unknown, depth = 0): ErrorReportSafeValue {\n\tif (depth >= MAX_DEPTH) return { type: \"truncated\" };\n\tif (value === null) return { type: \"null\" };\n\tif (value === undefined) return { type: \"undefined\" };\n\tif (Array.isArray(value)) {\n\t\treturn {\n\t\t\ttype: \"array\",\n\t\t\tlength: value.length,\n\t\t\tfirstItemsShape: value.slice(0, 3).map((item) => createDataShape(item, depth + 1))\n\t\t};\n\t}\n\tif (typeof value === \"object\") {\n\t\tconst entries = Object.entries(value as Record<string, unknown>).slice(0, MAX_OBJECT_KEYS);\n\n\t\treturn {\n\t\t\ttype: \"object\",\n\t\t\tkeys: entries.map(([key]) => key),\n\t\t\tshape: Object.fromEntries(entries.map(([key, item]) => [key, createDataShape(item, depth + 1)]))\n\t\t};\n\t}\n\n\treturn { type: typeof value };\n}\n\nexport function sanitizeDetail(detail: Record<string, unknown> | undefined): Record<string, ErrorReportSafeValue> | undefined {\n\tif (!detail) return undefined;\n\n\tconst entries = Object.entries(detail)\n\t\t.slice(0, MAX_OBJECT_KEYS)\n\t\t.map(([key, value]) => [key, createDiagnosticValue(value)] as const);\n\n\treturn entries.length ? Object.fromEntries(entries) : undefined;\n}\n","import { truncateText } from \"../formatters\";\n\nimport { sanitizeDetail } from \"./safeValue\";\n\nimport type { ErrorReportBreadcrumb } from \"./types\";\n\nconst MAX_BREADCRUMBS = 80;\nconst MAX_ELEMENT_CHAIN = 20;\nconst MAX_TEXT_LENGTH = 80;\nconst MAX_ATTRIBUTE_LENGTH = 120;\nconst CLICK_TARGET_SELECTOR = [\n\t\"button\",\n\t\"a\",\n\t\"input\",\n\t\"select\",\n\t\"textarea\",\n\t\"[role]\",\n\t\"[aria-label]\",\n\t\"[title]\",\n\t\"[data-ui]\",\n\t\"[data-action]\"\n].join(\",\");\n\nlet breadcrumbs: ErrorReportBreadcrumb[] = [];\n\nfunction nowUtc() {\n\treturn new Date().toISOString();\n}\n\nexport function addErrorReportBreadcrumb(breadcrumb: Omit<ErrorReportBreadcrumb, \"utc\"> & { utc?: string }) {\n\tbreadcrumbs = [...breadcrumbs, { ...breadcrumb, utc: breadcrumb.utc ?? nowUtc() }].slice(-MAX_BREADCRUMBS);\n}\n\nexport function getErrorReportBreadcrumbs() {\n\treturn breadcrumbs;\n}\n\nexport function clearErrorReportBreadcrumbs() {\n\tbreadcrumbs = [];\n}\n\nfunction truncateAttributeText(value: string | null | undefined) {\n\treturn truncateText(value, MAX_ATTRIBUTE_LENGTH);\n}\n\nfunction readStableAttributes(element: Element) {\n\treturn {\n\t\tid: truncateAttributeText(element.id),\n\t\trole: truncateAttributeText(element.getAttribute(\"role\")),\n\t\ttype: truncateAttributeText(element.getAttribute(\"type\")),\n\t\ttitle: truncateAttributeText(element.getAttribute(\"title\")),\n\t\tariaLabel: truncateAttributeText(element.getAttribute(\"aria-label\")),\n\t\tdataUi: truncateAttributeText(element.getAttribute(\"data-ui\")),\n\t\tdataAction: truncateAttributeText(element.getAttribute(\"data-action\"))\n\t};\n}\n\nfunction readClickText(element: Element) {\n\tif (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement) {\n\t\treturn undefined;\n\t}\n\n\tif (!element.matches(\"button,a,[role],[aria-label],[title]\")) return undefined;\n\n\treturn truncateText(element.textContent, MAX_TEXT_LENGTH);\n}\n\nfunction escapeSelectorPart(value: string) {\n\tif (typeof CSS !== \"undefined\" && typeof CSS.escape === \"function\") {\n\t\treturn CSS.escape(value);\n\t}\n\n\treturn value.replace(/[\"\\\\#.[\\]>~+:]/g, \"\\\\$&\");\n}\n\nfunction buildElementSelector(element: Element) {\n\tconst attrs = readStableAttributes(element);\n\tconst parts = [element.tagName.toLowerCase()];\n\n\tif (attrs.id) parts.push(`#${escapeSelectorPart(attrs.id)}`);\n\tif (attrs.role) parts.push(`[role=\"${attrs.role}\"]`);\n\tif (attrs.type) parts.push(`[type=\"${attrs.type}\"]`);\n\tif (attrs.dataUi) parts.push(`[data-ui=\"${attrs.dataUi}\"]`);\n\tif (attrs.dataAction) parts.push(`[data-action=\"${attrs.dataAction}\"]`);\n\n\treturn parts.join(\"\");\n}\n\nfunction describeElement(element: Element) {\n\tconst attrs = readStableAttributes(element);\n\n\treturn {\n\t\ttag: element.tagName.toLowerCase(),\n\t\tselector: buildElementSelector(element),\n\t\ttext: readClickText(element),\n\t\t...attrs\n\t};\n}\n\nfunction compactElementDescription(description: ReturnType<typeof describeElement>) {\n\treturn Object.fromEntries(\n\t\tObject.entries(description).filter(([, value]) => value !== undefined && (!Array.isArray(value) || value.length > 0))\n\t);\n}\n\nfunction getClickElementChain(target: Element) {\n\tconst chain: Element[] = [];\n\tlet current: Element | null = target;\n\n\twhile (current && current !== document.documentElement && chain.length < MAX_ELEMENT_CHAIN) {\n\t\tchain.push(current);\n\t\tif (current === document.body) break;\n\t\tcurrent = current.parentElement;\n\t}\n\n\treturn chain;\n}\n\nfunction findMeaningfulClickTarget(target: Element) {\n\treturn target.closest(CLICK_TARGET_SELECTOR) ?? target;\n}\n\nfunction describeClickTarget(target: EventTarget | null) {\n\tif (!(target instanceof Element)) return undefined;\n\n\tconst meaningfulTarget = findMeaningfulClickTarget(target);\n\tconst chain = getClickElementChain(meaningfulTarget);\n\n\treturn chain.map((element) => buildElementSelector(element)).join(\" > \");\n}\n\nfunction describeClickDetail(event: MouseEvent) {\n\tconst target = event.target instanceof Element ? event.target : undefined;\n\tconst meaningfulTarget = target ? findMeaningfulClickTarget(target) : undefined;\n\tconst chain = meaningfulTarget\n\t\t? getClickElementChain(meaningfulTarget).map((element) => compactElementDescription(describeElement(element)))\n\t\t: [];\n\n\treturn sanitizeDetail({\n\t\tbutton: event.button,\n\t\tctrlKey: event.ctrlKey,\n\t\tshiftKey: event.shiftKey,\n\t\taltKey: event.altKey,\n\t\tclientX: event.clientX,\n\t\tclientY: event.clientY,\n\t\ttarget: meaningfulTarget ? compactElementDescription(describeElement(meaningfulTarget)) : undefined,\n\t\tchain\n\t});\n}\n\n/**\n * Подключает breadcrumbs по действиям пользователя без тел запросов.\n */\nexport function installErrorReportBrowserBreadcrumbs() {\n\tif (typeof window === \"undefined\") return () => undefined;\n\n\tconst onClick = (event: MouseEvent) => {\n\t\taddErrorReportBreadcrumb({\n\t\t\ttype: \"click\",\n\t\t\ttarget: describeClickTarget(event.target),\n\t\t\tdetail: describeClickDetail(event)\n\t\t});\n\t};\n\n\tconst onVisibilityChange = () => {\n\t\taddErrorReportBreadcrumb({\n\t\t\ttype: \"visibility\",\n\t\t\tdetail: sanitizeDetail({ visibilityState: document.visibilityState })\n\t\t});\n\t};\n\n\twindow.addEventListener(\"click\", onClick, true);\n\tdocument.addEventListener(\"visibilitychange\", onVisibilityChange);\n\n\treturn () => {\n\t\twindow.removeEventListener(\"click\", onClick, true);\n\t\tdocument.removeEventListener(\"visibilitychange\", onVisibilityChange);\n\t};\n}\n","import { normalizeText } from \"../formatters\";\n\nimport type { ErrorReportErrorInfo } from \"./types\";\n\nconst DEFAULT_ERROR_MESSAGE = \"Неизвестная ошибка\";\n\n/**\n * Гарантирует непустое диагностическое сообщение, сохраняя исходный текст ошибки.\n * Fallback нужен для Error без message и для брошенных пустых строк.\n */\nfunction resolveErrorMessage(message: string) {\n\treturn normalizeText(message) ? message : DEFAULT_ERROR_MESSAGE;\n}\n\nfunction readStatus(value: Record<string, unknown>) {\n\tconst status = value.status ?? value.statusCode ?? value.httpStatus;\n\treturn typeof status === \"number\" && Number.isFinite(status) ? status : undefined;\n}\n\nfunction readServerFnTransportErrorInfo(error: unknown): ErrorReportErrorInfo | null {\n\tif (!error || typeof error !== \"object\") {\n\t\treturn null;\n\t}\n\n\tconst transport = error as Record<string, unknown>;\n\tconst appError = transport.appError;\n\tif (!appError || typeof appError !== \"object\") {\n\t\treturn null;\n\t}\n\n\tconst payload = appError as Record<string, unknown>;\n\tconst message = normalizeText(payload.message);\n\tif (!message) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tname: \"AppError\",\n\t\tmessage,\n\t\tcode: normalizeText(payload.code),\n\t\thttpStatus: readStatus(payload)\n\t};\n}\n\n/**\n * Нормализует любое брошенное значение в форму, удобную для поиска и сохранения.\n * Stacktrace намеренно сохраняется полностью: это основная диагностическая ценность отчета.\n */\nexport function createErrorInfo(error: unknown): ErrorReportErrorInfo {\n\tconst serverFnErrorInfo = readServerFnTransportErrorInfo(error);\n\tif (serverFnErrorInfo) {\n\t\treturn serverFnErrorInfo;\n\t}\n\n\tif (error instanceof Error) {\n\t\treturn {\n\t\t\tname: error.name || \"Error\",\n\t\t\tmessage: resolveErrorMessage(error.message),\n\t\t\tstackTrace: error.stack\n\t\t};\n\t}\n\n\tif (error && typeof error === \"object\") {\n\t\tconst record = error as Record<string, unknown>;\n\t\treturn {\n\t\t\tname: typeof record.name === \"string\" ? record.name : \"Error\",\n\t\t\tmessage: resolveErrorMessage(typeof record.message === \"string\" ? record.message : String(error)),\n\t\t\tstackTrace: typeof record.stack === \"string\" ? record.stack : undefined,\n\t\t\thttpStatus: readStatus(record)\n\t\t};\n\t}\n\n\treturn {\n\t\tname: \"Error\",\n\t\tmessage: resolveErrorMessage(typeof error === \"string\" ? error : String(error ?? DEFAULT_ERROR_MESSAGE))\n\t};\n}\n","import { type PersistedQuery } from \"@tanstack/query-persist-client-core\";\nimport { type MutationKey, type MutationState, type QueryClient, type QueryKey, type QueryState } from \"@tanstack/react-query\";\n\nimport { createIndexedDbQueryStorage } from \"../query-client\";\n\nimport { createErrorInfo } from \"./errorInfo\";\nimport { createDataShape, createDiagnosticValue, sanitizeDetail } from \"./safeValue\";\nimport {\n\ttype ErrorReportMutationDiagnostics,\n\ttype ErrorReportPersistedQueryDiagnostics,\n\ttype ErrorReportQueryDiagnostics,\n\ttype ErrorReportSafeValue\n} from \"./types\";\n\ntype QueryDiagnosticSource = {\n\tqueryHash: string;\n\tqueryKey: QueryKey;\n\tstate: QueryState<unknown, unknown>;\n\tmeta?: Record<string, unknown>;\n\tgetObserversCount: () => number;\n};\n\ntype MutationDiagnosticSource = {\n\toptions: {\n\t\tmutationKey?: MutationKey;\n\t};\n\tstate: MutationState<unknown, unknown, unknown, unknown>;\n\tmeta?: Record<string, unknown>;\n};\n\nconst MAX_QUERY_DIAGNOSTICS = 40;\nconst MAX_MUTATION_DIAGNOSTICS = 40;\nconst MAX_PERSISTED_QUERY_DIAGNOSTICS = 40;\n\nfunction sanitizeMeta(meta: Record<string, unknown> | undefined): Record<string, ErrorReportSafeValue> | undefined {\n\treturn sanitizeDetail(meta);\n}\n\nexport function collectQueryDiagnostics(query: QueryDiagnosticSource): ErrorReportQueryDiagnostics {\n\treturn {\n\t\tqueryHash: query.queryHash,\n\t\tqueryKey: createDiagnosticValue(query.queryKey),\n\t\tstatus: query.state.status,\n\t\tfetchStatus: query.state.fetchStatus,\n\t\tdataUpdatedAt: query.state.dataUpdatedAt,\n\t\terrorUpdatedAt: query.state.errorUpdatedAt,\n\t\tfailureCount: query.state.fetchFailureCount,\n\t\tisInvalidated: query.state.isInvalidated,\n\t\tobserversCount: query.getObserversCount(),\n\t\tmeta: sanitizeMeta(query.meta),\n\t\tdataShape: createDataShape(query.state.data),\n\t\terror: query.state.error ? createErrorInfo(query.state.error) : undefined\n\t};\n}\n\nexport function collectMutationDiagnostics(mutation: MutationDiagnosticSource): ErrorReportMutationDiagnostics {\n\treturn {\n\t\tmutationKey: mutation.options.mutationKey ? createDiagnosticValue(mutation.options.mutationKey) : undefined,\n\t\tstatus: mutation.state.status,\n\t\tfailureCount: mutation.state.failureCount,\n\t\tsubmittedAt: mutation.state.submittedAt,\n\t\tmeta: sanitizeMeta(mutation.meta),\n\t\terror: mutation.state.error ? createErrorInfo(mutation.state.error) : undefined\n\t};\n}\n\nexport function collectQueryClientDiagnostics(queryClient: QueryClient) {\n\treturn {\n\t\tqueries: queryClient.getQueryCache().getAll().slice(-MAX_QUERY_DIAGNOSTICS).map(collectQueryDiagnostics),\n\t\tmutations: queryClient.getMutationCache().getAll().slice(-MAX_MUTATION_DIAGNOSTICS).map(collectMutationDiagnostics)\n\t};\n}\n\nfunction collectPersistedStateDiagnostics(storageKey: string, persistedQuery: PersistedQuery): ErrorReportPersistedQueryDiagnostics {\n\tconst state = persistedQuery.state;\n\n\treturn {\n\t\tstorageKey,\n\t\tbuster: persistedQuery.buster,\n\t\tqueryHash: persistedQuery.queryHash,\n\t\tqueryKey: createDiagnosticValue(persistedQuery.queryKey),\n\t\tstatus: state.status,\n\t\tfetchStatus: state.fetchStatus,\n\t\tdataUpdatedAt: state.dataUpdatedAt,\n\t\terrorUpdatedAt: state.errorUpdatedAt,\n\t\tfailureCount: state.fetchFailureCount,\n\t\terror: state.error ? createErrorInfo(state.error) : undefined\n\t};\n}\n\n/**\n * Читает IndexedDB persistence и возвращает только технические поля.\n * `state.data` и другие значения кеша не попадают в результат.\n */\nexport async function collectPersistedQueryDiagnostics(): Promise<ErrorReportPersistedQueryDiagnostics[]> {\n\tconst storage = createIndexedDbQueryStorage<PersistedQuery>();\n\tif (!storage?.entries) return [];\n\n\ttry {\n\t\tconst entries = await storage.entries();\n\t\treturn entries\n\t\t\t.slice(-MAX_PERSISTED_QUERY_DIAGNOSTICS)\n\t\t\t.map(([storageKey, persistedQuery]) => collectPersistedStateDiagnostics(storageKey, persistedQuery));\n\t} catch {\n\t\treturn [];\n\t}\n}\n","type ErrorReportEnvironmentOptions = {\n\tisDev?: boolean;\n};\n\n/**\n * Отчеты собираются только в браузере и только вне dev-режима.\n * На серверном рендеринге draft не создается, чтобы не смешивать SSR-ошибки с клиентской диагностикой.\n */\nexport function isErrorReportingEnabled(options: ErrorReportEnvironmentOptions = {}) {\n\tconst isDev = options.isDev ?? __DEV__;\n\n\treturn typeof window !== \"undefined\" && !isDev;\n}\n\nexport function getErrorReportEnvironment() {\n\tconst mode: \"development\" | \"production\" = __DEV__ ? \"development\" : \"production\";\n\n\treturn {\n\t\tmode,\n\t\tbuildId: typeof __APP_BUILD_ID__ === \"string\" ? __APP_BUILD_ID__ : undefined\n\t};\n}\n\nexport function getErrorReportClientEnvironment() {\n\tif (typeof window === \"undefined\") return undefined;\n\n\treturn {\n\t\tuserAgent: window.navigator.userAgent,\n\t\tlanguage: window.navigator.language,\n\t\ttimeZone: Intl.DateTimeFormat().resolvedOptions().timeZone\n\t};\n}\n","import { uuidv4 } from \"../crypto\";\nimport { formatDateAsODataDatetime } from \"../formatters\";\nimport { getSessionStorageId } from \"../session-storage\";\n\nimport { getErrorReportBreadcrumbs } from \"./breadcrumbs\";\nimport { getErrorReportClientEnvironment, getErrorReportEnvironment, isErrorReportingEnabled } from \"./environment\";\n\nimport type { ErrorReportCategory, ErrorReportDraft, ErrorReportErrorInfo, ErrorReportPayload, ErrorReportSafeValue } from \"./types\";\n\nconst STORAGE_KEY = `${__APP_ID__}.errorReport.drafts.v1`;\nconst SESSION_STORAGE_KEY = `${__APP_ID__}.errorReport.sessionId.v1`;\nconst MAX_DRAFTS = 10;\n\nlet drafts = loadDrafts();\n\nfunction nowUtc() {\n\treturn formatDateAsODataDatetime(new Date());\n}\n\nfunction loadDrafts(): ErrorReportDraft[] {\n\tif (typeof sessionStorage === \"undefined\") return [];\n\n\ttry {\n\t\tconst raw = sessionStorage.getItem(STORAGE_KEY);\n\t\tconst parsed = raw ? JSON.parse(raw) : [];\n\t\treturn Array.isArray(parsed) ? (parsed as ErrorReportDraft[]) : [];\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction saveDrafts(nextDrafts: ErrorReportDraft[]) {\n\tdrafts = nextDrafts.slice(-MAX_DRAFTS);\n\tif (typeof sessionStorage === \"undefined\") return;\n\n\ttry {\n\t\tsessionStorage.setItem(STORAGE_KEY, JSON.stringify(drafts));\n\t} catch {\n\t\t// Переполнение sessionStorage не должно ломать пользовательский сценарий.\n\t}\n}\n\nfunction getLocationSnapshot() {\n\tif (typeof window === \"undefined\") return undefined;\n\n\treturn {\n\t\tpathname: window.location.pathname,\n\t\torigin: window.location.origin\n\t};\n}\n\nfunction getViewportSnapshot() {\n\tif (typeof window === \"undefined\") return undefined;\n\n\treturn {\n\t\twidth: window.innerWidth,\n\t\theight: window.innerHeight,\n\t\tdevicePixelRatio: window.devicePixelRatio\n\t};\n}\n\nexport function getErrorReportDraft(reportId: string) {\n\treturn drafts.find((draft) => draft.reportId === reportId);\n}\n\nexport function updateErrorReportDraft(reportId: string, patch: Partial<ErrorReportDraft>) {\n\tconst current = getErrorReportDraft(reportId);\n\tif (!current) return undefined;\n\n\tconst next = { ...current, ...patch };\n\tsaveDrafts(drafts.map((draft) => (draft.reportId === reportId ? next : draft)));\n\treturn next;\n}\n\nexport function getErrorReportDrafts() {\n\treturn drafts;\n}\n\nexport function captureErrorReportDraft(args: {\n\tcategory: ErrorReportCategory;\n\tsource: string;\n\terror: ErrorReportErrorInfo;\n\tquery?: ErrorReportPayload[\"query\"];\n\tmutation?: ErrorReportPayload[\"mutation\"];\n\tqueryClient?: ErrorReportPayload[\"queryClient\"];\n\tpersistedQueries?: ErrorReportPayload[\"persistedQueries\"];\n\treact?: ErrorReportPayload[\"react\"];\n\tcontext?: Record<string, ErrorReportSafeValue>;\n}) {\n\tif (!isErrorReportingEnabled()) return undefined;\n\n\tconst reportId = uuidv4();\n\tconst sessionId = getSessionStorageId(SESSION_STORAGE_KEY);\n\tconst createdUtc = nowUtc();\n\tconst payload: ErrorReportPayload = {\n\t\treportId,\n\t\tsessionId,\n\t\tcreatedUtc,\n\t\tcategory: args.category,\n\t\tsource: args.source,\n\t\terror: args.error,\n\t\tenvironment: getErrorReportEnvironment(),\n\t\tclient: getErrorReportClientEnvironment(),\n\t\tlocation: getLocationSnapshot(),\n\t\tviewport: getViewportSnapshot(),\n\t\treact: args.react,\n\t\tquery: args.query,\n\t\tmutation: args.mutation,\n\t\tqueryClient: args.queryClient,\n\t\tpersistedQueries: args.persistedQueries,\n\t\tbreadcrumbs: getErrorReportBreadcrumbs(),\n\t\tcontext: args.context\n\t};\n\tconst draft: ErrorReportDraft = {\n\t\treportId,\n\t\tsessionId,\n\t\tcreatedUtc,\n\t\tcategory: args.category,\n\t\tstatus: \"pending\",\n\t\tpayload\n\t};\n\n\tsaveDrafts([...drafts, draft]);\n\treturn draft;\n}\n","import { hashString128 } from \"../crypto\";\nimport { stableStringify } from \"../utils\";\n\nimport type { ErrorReportDraft, ErrorReportErrorInfo, ErrorReportSafeValue } from \"./types\";\n\nexport const RUNTIME_ERROR_REPORT_DEDUPLICATION_WINDOW_MS = 60_000;\n\nconst MAX_RECENT_RUNTIME_ERROR_REPORTS = 100;\nconst recentRuntimeErrorReports = new Map<\n\tstring,\n\t{\n\t\tcapturedAt: number;\n\t\tcapture: Promise<ErrorReportDraft | undefined>;\n\t\texpirationTimer: ReturnType<typeof setTimeout>;\n\t}\n>();\n\ntype RuntimeErrorReportDeduplicationInput = {\n\tcategory: \"runtime\" | \"react\";\n\tsource: string;\n\terror: ErrorReportErrorInfo;\n\tpathname?: string;\n\tscope?: {\n\t\tcomponentStack?: string;\n\t\tdetail?: Record<string, ErrorReportSafeValue>;\n\t};\n};\n\nfunction normalizeStackTrace(stackTrace: string | undefined) {\n\tif (!stackTrace) return undefined;\n\n\treturn stackTrace\n\t\t.split(\"\\n\")\n\t\t.map((line) => line.trim())\n\t\t.filter(Boolean);\n}\n\nfunction createRuntimeErrorReportFingerprint(input: RuntimeErrorReportDeduplicationInput) {\n\treturn hashString128(\n\t\tstableStringify({\n\t\t\tcategory: input.category,\n\t\t\tsource: input.source,\n\t\t\terror: {\n\t\t\t\t...input.error,\n\t\t\t\tstackTrace: normalizeStackTrace(input.error.stackTrace)\n\t\t\t},\n\t\t\tpathname: input.pathname,\n\t\t\tscope: input.scope\n\t\t})\n\t);\n}\n\n/**\n * Удаляет только ожидаемую запись и освобождает связанный таймер.\n * Проверка Promise защищает новую запись того же fingerprint от завершения\n * или отклонения старого capture после lifecycle-сброса.\n */\nfunction removeRuntimeErrorReport(fingerprint: string, expectedCapture?: Promise<ErrorReportDraft | undefined>) {\n\tconst recentReport = recentRuntimeErrorReports.get(fingerprint);\n\tif (!recentReport || (expectedCapture && recentReport.capture !== expectedCapture)) {\n\t\treturn;\n\t}\n\n\tclearTimeout(recentReport.expirationTimer);\n\trecentRuntimeErrorReports.delete(fingerprint);\n}\n\nfunction removeExpiredRuntimeErrorReports(now: number) {\n\tfor (const [fingerprint, recentReport] of recentRuntimeErrorReports) {\n\t\tif (now - recentReport.capturedAt >= RUNTIME_ERROR_REPORT_DEDUPLICATION_WINDOW_MS) {\n\t\t\tremoveRuntimeErrorReport(fingerprint, recentReport.capture);\n\t\t}\n\t}\n}\n\nfunction removeOldestRuntimeErrorReport() {\n\tconst oldestFingerprint = recentRuntimeErrorReports.keys().next().value;\n\tif (oldestFingerprint) {\n\t\tremoveRuntimeErrorReport(oldestFingerprint);\n\t}\n}\n\n/**\n * Объединяет одинаковые runtime capture-вызовы вокруг одной Promise.\n * Все потребители получают один draft, поэтому capture-only boundary не может\n * заблокировать последующую app-level доставку того же отчёта.\n */\nexport function coalesceRuntimeErrorReportCapture(\n\tinput: RuntimeErrorReportDeduplicationInput,\n\tcapture: () => Promise<ErrorReportDraft | undefined>\n) {\n\tconst now = Date.now();\n\tconst fingerprint = createRuntimeErrorReportFingerprint(input);\n\tconst recentReport = recentRuntimeErrorReports.get(fingerprint);\n\n\tif (recentReport && now - recentReport.capturedAt < RUNTIME_ERROR_REPORT_DEDUPLICATION_WINDOW_MS) {\n\t\treturn recentReport.capture;\n\t}\n\n\tremoveExpiredRuntimeErrorReports(now);\n\twhile (recentRuntimeErrorReports.size >= MAX_RECENT_RUNTIME_ERROR_REPORTS) {\n\t\tremoveOldestRuntimeErrorReport();\n\t}\n\n\tconst capturePromise = capture();\n\tconst expirationTimer = setTimeout(() => {\n\t\tremoveRuntimeErrorReport(fingerprint, capturePromise);\n\t}, RUNTIME_ERROR_REPORT_DEDUPLICATION_WINDOW_MS);\n\n\trecentRuntimeErrorReports.set(fingerprint, {\n\t\tcapturedAt: now,\n\t\tcapture: capturePromise,\n\t\texpirationTimer\n\t});\n\n\tvoid capturePromise.catch(() => {\n\t\tremoveRuntimeErrorReport(fingerprint, capturePromise);\n\t});\n\n\treturn capturePromise;\n}\n\n/**\n * Очищает модульное состояние при смене app-level runtime reporter.\n * Функция не входит в публичный package subpath и нужна lifecycle-коду и тестам.\n */\nexport function clearRuntimeErrorReportDeduplication() {\n\tfor (const recentReport of recentRuntimeErrorReports.values()) {\n\t\tclearTimeout(recentReport.expirationTimer);\n\t}\n\trecentRuntimeErrorReports.clear();\n}\n","export type ErrorReportTransportHtmlSummary = {\n\tlength: number;\n\ttitle?: string;\n\tformCount?: number;\n\tinputNames?: string[];\n\ttextPreview?: string;\n};\n\nexport type ErrorReportTransportErrorContext = {\n\tsource: \"fetch.parseResponse\" | \"fetch.buildHttpError\";\n\trequestUrl?: string;\n\tresponseUrl?: string;\n\tmethod?: string;\n\tbaseUrlType?: string;\n\tsapClient?: string | null;\n\tstatus?: number;\n\tstatusText?: string;\n\tcontentType?: string;\n\tredirected?: boolean;\n\tresponseType?: string;\n\thtml?: ErrorReportTransportHtmlSummary;\n};\n\nexport type ErrorReportTransportErrorReporter = (error: Error, context: ErrorReportTransportErrorContext) => void | Promise<void>;\n\nconst DEDUPLICATION_INTERVAL_MS = 60_000;\nconst MAX_RECENT_REPORT_KEYS = 100;\nconst TRANSPORT_REPORT_DELAY_MS = 250;\n\nlet transportErrorReporter: ErrorReportTransportErrorReporter | undefined;\nconst scheduledTransportErrors = new WeakSet<Error>();\nconst suppressedTransportErrors = new WeakSet<Error>();\nconst recentReportKeys = new Map<string, number>();\n\nfunction createReportKey(context: ErrorReportTransportErrorContext) {\n\treturn [context.source, context.method, context.status, context.requestUrl, context.responseUrl].filter(Boolean).join(\"|\");\n}\n\nfunction shouldSkipByRecentKey(context: ErrorReportTransportErrorContext) {\n\tconst now = Date.now();\n\tconst key = createReportKey(context);\n\n\tfor (const [recentKey, timestamp] of recentReportKeys) {\n\t\tif (now - timestamp > DEDUPLICATION_INTERVAL_MS || recentReportKeys.size > MAX_RECENT_REPORT_KEYS) {\n\t\t\trecentReportKeys.delete(recentKey);\n\t\t}\n\t}\n\n\tconst lastReportedAt = recentReportKeys.get(key);\n\tif (lastReportedAt && now - lastReportedAt < DEDUPLICATION_INTERVAL_MS) return true;\n\n\trecentReportKeys.set(key, now);\n\treturn false;\n}\n\n/**\n * Регистрирует приложение как получателя транспортных ошибок.\n * Сам OData transport не знает про QueryClient и UI, поэтому только публикует событие,\n * а app-слой решает, как именно создать и отправить отчет.\n */\nexport function setErrorReportTransportErrorReporter(reporter: ErrorReportTransportErrorReporter | undefined) {\n\ttransportErrorReporter = reporter;\n\trecentReportKeys.clear();\n}\n\nexport function isTransportErrorReportScheduled(error: unknown) {\n\treturn error instanceof Error && scheduledTransportErrors.has(error);\n}\n\nexport function suppressTransportErrorReport(error: unknown) {\n\tif (error instanceof Error) {\n\t\tsuppressedTransportErrors.add(error);\n\t}\n}\n\nexport function reportTransportError(error: Error, context: ErrorReportTransportErrorContext) {\n\tscheduledTransportErrors.add(error);\n\n\t// Даем React Query шанс перехватить эту же ошибку и создать query/mutation-отчет\n\t// с более полезным снимком кеша. Если такого перехвата нет, transport-отчет уйдет сам.\n\tsetTimeout(() => {\n\t\tif (suppressedTransportErrors.has(error)) return;\n\t\tif (!transportErrorReporter) return;\n\t\tif (shouldSkipByRecentKey(context)) return;\n\n\t\ttry {\n\t\t\tconst result = transportErrorReporter(error, context);\n\t\t\tvoid Promise.resolve(result).catch(() => undefined);\n\t\t} catch {\n\t\t\t// Ошибка диагностического hook не должна менять поведение исходного fetch.\n\t\t}\n\t}, TRANSPORT_REPORT_DELAY_MS);\n}\n","import { type Mutation, type Query, type QueryClient } from \"@tanstack/react-query\";\n\nimport { addErrorReportBreadcrumb } from \"./breadcrumbs\";\nimport {\n\tcollectMutationDiagnostics,\n\tcollectPersistedQueryDiagnostics,\n\tcollectQueryClientDiagnostics,\n\tcollectQueryDiagnostics\n} from \"./diagnostics\";\nimport { captureErrorReportDraft } from \"./drafts\";\nimport { createErrorInfo } from \"./errorInfo\";\nimport { coalesceRuntimeErrorReportCapture } from \"./runtimeDeduplication\";\nimport { sanitizeDetail } from \"./safeValue\";\nimport { suppressTransportErrorReport } from \"./transport\";\n\nimport type { ErrorReportMutationContext, ErrorReportQueryContext, ErrorReportRuntimeContext } from \"./types\";\n\nexport async function captureQueryErrorReport(\n\terror: unknown,\n\tquery: Query<unknown, unknown, unknown>,\n\tqueryClient: QueryClient,\n\tcontext?: ErrorReportQueryContext\n) {\n\tsuppressTransportErrorReport(error);\n\tconst source = context?.source ?? \"query\";\n\n\taddErrorReportBreadcrumb({\n\t\ttype: \"query-error\",\n\t\tdetail: sanitizeDetail({\n\t\t\tqueryHash: query.queryHash,\n\t\t\tqueryKey: context?.queryKey ?? query.queryKey,\n\t\t\t...context?.detail\n\t\t})\n\t});\n\n\tconst [persistedQueries, queryClientDiagnostics] = await Promise.all([\n\t\tcollectPersistedQueryDiagnostics(),\n\t\tPromise.resolve(collectQueryClientDiagnostics(queryClient))\n\t]);\n\n\treturn captureErrorReportDraft({\n\t\tcategory: \"query\",\n\t\tsource,\n\t\terror: context?.errorInfo ?? createErrorInfo(error),\n\t\tquery: collectQueryDiagnostics(query),\n\t\tqueryClient: queryClientDiagnostics,\n\t\tpersistedQueries,\n\t\tcontext: sanitizeDetail(context?.detail)\n\t});\n}\n\nexport async function captureMutationErrorReport(\n\terror: unknown,\n\tmutation: Mutation<unknown, unknown, unknown, unknown>,\n\tqueryClient: QueryClient,\n\tcontext: ErrorReportMutationContext = {}\n) {\n\tsuppressTransportErrorReport(error);\n\tconst source = context.source ?? \"mutation\";\n\n\taddErrorReportBreadcrumb({\n\t\ttype: \"mutation-error\",\n\t\tdetail: sanitizeDetail({ mutationKey: mutation.options.mutationKey, ...context.detail })\n\t});\n\n\tconst [persistedQueries, queryClientDiagnostics] = await Promise.all([\n\t\tcollectPersistedQueryDiagnostics(),\n\t\tPromise.resolve(collectQueryClientDiagnostics(queryClient))\n\t]);\n\n\treturn captureErrorReportDraft({\n\t\tcategory: \"mutation\",\n\t\tsource,\n\t\terror: context.errorInfo ?? createErrorInfo(error),\n\t\tmutation: collectMutationDiagnostics(mutation),\n\t\tqueryClient: queryClientDiagnostics,\n\t\tpersistedQueries\n\t});\n}\n\nexport function captureRuntimeErrorReport(error: unknown, context: ErrorReportRuntimeContext = {}, queryClient?: QueryClient) {\n\tconst category = context.category ?? \"runtime\";\n\tconst source = context.source ?? context.category ?? \"runtime\";\n\tconst errorInfo = context.errorInfo ?? createErrorInfo(error);\n\tconst detail = sanitizeDetail(context.detail);\n\n\tconst captureDraft = async () => {\n\t\taddErrorReportBreadcrumb({\n\t\t\ttype: \"runtime-error\",\n\t\t\tdetail: sanitizeDetail({ category, source, ...context.detail })\n\t\t});\n\n\t\tconst [persistedQueries, queryClientDiagnostics] = queryClient\n\t\t\t? await Promise.all([collectPersistedQueryDiagnostics(), Promise.resolve(collectQueryClientDiagnostics(queryClient))])\n\t\t\t: [undefined, undefined];\n\n\t\treturn captureErrorReportDraft({\n\t\t\tcategory,\n\t\t\tsource,\n\t\t\terror: errorInfo,\n\t\t\treact: context.componentStack ? { componentStack: context.componentStack } : undefined,\n\t\t\tqueryClient: queryClientDiagnostics,\n\t\t\tpersistedQueries,\n\t\t\tcontext: detail\n\t\t});\n\t};\n\n\t/**\n\t * Error report draft создаётся только в браузере. Прямой вызов capture\n\t * сохраняет прежнее SSR-поведение без клиентского TTL-таймера, который\n\t * иначе удерживал бы Node-процесс после no-op результата.\n\t */\n\tif (typeof window === \"undefined\") {\n\t\treturn captureDraft();\n\t}\n\n\treturn coalesceRuntimeErrorReportCapture(\n\t\t{\n\t\t\tcategory,\n\t\t\tsource,\n\t\t\terror: errorInfo,\n\t\t\tpathname: window.location.pathname,\n\t\t\tscope: {\n\t\t\t\tcomponentStack: context.componentStack,\n\t\t\t\tdetail\n\t\t\t}\n\t\t},\n\t\tcaptureDraft\n\t);\n}\n","import { clearRuntimeErrorReportDeduplication } from \"./runtimeDeduplication\";\n\nimport type { ErrorReportRuntimeContext } from \"./types\";\n\nexport type ErrorReportRuntimeErrorReporter = (error: unknown, context: ErrorReportRuntimeContext) => void | Promise<void>;\n\nlet runtimeErrorReporter: ErrorReportRuntimeErrorReporter | undefined;\n\n/**\n * Регистрирует app-слой как получателя ручных runtime-ошибок.\n * Shared-код может вызвать reportRuntimeError без знания о QueryClient, UI и режиме доставки.\n */\nexport function setErrorReportRuntimeErrorReporter(reporter: ErrorReportRuntimeErrorReporter | undefined) {\n\truntimeErrorReporter = reporter;\n\tclearRuntimeErrorReportDeduplication();\n}\n\n/**\n * Ручная отправка runtime-ошибки из try/catch или другого кода вне React-компонента.\n * Функция не бросает исключений: диагностический отчет не должен ломать основной сценарий.\n *\n * @example\n *\n * try {\n * // ...\n * } catch (error) {\n * reportRuntimeError(error, {\n * detail: {\n * source: \"s3-download\",\n * action: \"download-from-s3\"\n * }\n * });\n * }\n */\nexport async function reportRuntimeError(error: unknown, context: ErrorReportRuntimeContext = {}) {\n\tif (!runtimeErrorReporter) return;\n\n\ttry {\n\t\tawait runtimeErrorReporter(error, context);\n\t} catch {\n\t\t// Ошибка диагностического hook не должна менять поведение пользовательского кода.\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/error-report/safeValue.ts","../../src/error-report/breadcrumbs.ts","../../src/error-report/payload.ts","../../src/error-report/errorInfo.ts","../../src/error-report/diagnostics.ts","../../src/error-report/environment.ts","../../src/error-report/schema.ts","../../src/error-report/drafts.ts","../../src/error-report/runtimeDeduplication.ts","../../src/error-report/transport.ts","../../src/error-report/capture.ts","../../src/error-report/queueContract.ts","../../src/error-report/queueRecord.ts","../../src/error-report/queue.ts","../../src/error-report/runtime.ts"],"sourcesContent":["import type { ErrorReportSafeValue, ErrorReportSanitizationContext, ErrorReportSanitizer } from \"./types\";\n\nconst MAX_DEPTH = 4;\nconst MAX_ARRAY_ITEMS = 20;\nconst MAX_OBJECT_KEYS = 40;\nconst MAX_DIAGNOSTIC_STRING_LENGTH = 4_096;\nconst REDACTED_VALUE = \"[REDACTED]\";\nconst SENSITIVE_KEY_PARTS = [\n\t\"apikey\",\n\t\"authorization\",\n\t\"cookie\",\n\t\"csrf\",\n\t\"password\",\n\t\"passwd\",\n\t\"refreshtoken\",\n\t\"secret\",\n\t\"sessiontoken\",\n\t\"token\"\n];\nconst URL_KEY_SUFFIX = \"url\";\n\nlet errorReportSanitizer: ErrorReportSanitizer | undefined;\n\nfunction normalizeKey(key: string) {\n\treturn key.toLowerCase().replace(/[^a-z0-9]/g, \"\");\n}\n\nfunction isSensitiveKey(key: string) {\n\tconst normalizedKey = normalizeKey(key);\n\treturn SENSITIVE_KEY_PARTS.some((part) => normalizedKey.includes(part));\n}\n\nfunction isUrlKey(key: string) {\n\treturn normalizeKey(key).endsWith(URL_KEY_SUFFIX);\n}\n\nfunction looksLikeUrlWithPrivateParts(value: string) {\n\treturn /^(?:https?:\\/\\/|\\/)[^\\s]*[?#]/i.test(value);\n}\n\nfunction stripUrlSearchAndHash(value: string) {\n\ttry {\n\t\tconst parsed = new URL(value, \"https://error-report.invalid\");\n\t\tconst pathname = parsed.pathname;\n\t\treturn parsed.origin === \"https://error-report.invalid\" ? pathname : `${parsed.origin}${pathname}`;\n\t} catch {\n\t\treturn value.split(/[?#]/, 1)[0] ?? value;\n\t}\n}\n\n/**\n * Удаляет наиболее узнаваемые секреты и email из свободного диагностического\n * текста. Это страховочная сетка; предметные персональные данные приложение\n * обязано исключить своим allow-list sanitizer.\n */\nexport function sanitizeDiagnosticText(value: string, maxLength = MAX_DIAGNOSTIC_STRING_LENGTH) {\n\tlet sanitizedValue = value.slice(0, maxLength);\n\tif (/\\bbearer\\s/i.test(sanitizedValue)) {\n\t\tsanitizedValue = sanitizedValue.replace(/\\bBearer\\s+[A-Za-z0-9._~+/=-]{8,}/gi, \"Bearer [REDACTED]\");\n\t}\n\tif (sanitizedValue.includes(\"@\")) {\n\t\tsanitizedValue = sanitizedValue.replace(/[A-Z0-9._%+-]{1,254}@[A-Z0-9.-]{1,253}\\.[A-Z]{2,63}/gi, \"[REDACTED_EMAIL]\");\n\t}\n\n\treturn sanitizedValue;\n}\n\n/** Возвращает размер строки в UTF-8, совпадающий с размером JSON transport. */\nexport function getUtf8TextSize(value: string) {\n\treturn new TextEncoder().encode(value).byteLength;\n}\n\n/**\n * Обрезает уже очищенный текст по UTF-8 bytes без разрыва surrogate pair.\n * Binary search нужен для Unicode stack traces, где число code units не равно\n * размеру transport payload.\n */\nexport function sanitizeDiagnosticTextBytes(value: string, maxBytes: number) {\n\tconst sanitizedValue = sanitizeDiagnosticText(value, maxBytes);\n\tif (getUtf8TextSize(sanitizedValue) <= maxBytes) return sanitizedValue;\n\n\tlet left = 0;\n\tlet right = sanitizedValue.length;\n\twhile (left < right) {\n\t\tconst middle = Math.ceil((left + right) / 2);\n\t\tif (getUtf8TextSize(sanitizedValue.slice(0, middle)) <= maxBytes) left = middle;\n\t\telse right = middle - 1;\n\t}\n\n\tconst lastCodeUnit = sanitizedValue.charCodeAt(left - 1);\n\tconst safeEnd = lastCodeUnit >= 0xd800 && lastCodeUnit <= 0xdbff ? left - 1 : left;\n\treturn sanitizedValue.slice(0, safeEnd);\n}\n\ntype DiagnosticValueState = {\n\tseen: WeakSet<object>;\n\tmaxStringLength: number;\n};\n\nfunction createDiagnosticValueInternal(value: unknown, depth: number, state: DiagnosticValueState, key?: string): ErrorReportSafeValue {\n\tif (key && isSensitiveKey(key)) return REDACTED_VALUE;\n\tif (depth >= MAX_DEPTH) return { type: \"truncated\" };\n\tif (value === null || typeof value === \"boolean\") return value;\n\tif (typeof value === \"number\") return Number.isFinite(value) ? value : { type: \"non-finite-number\" };\n\tif (typeof value === \"string\") {\n\t\tconst normalizedValue = (key && isUrlKey(key)) || looksLikeUrlWithPrivateParts(value) ? stripUrlSearchAndHash(value) : value;\n\t\treturn sanitizeDiagnosticText(normalizedValue, state.maxStringLength);\n\t}\n\tif (value === undefined) return { type: \"undefined\" };\n\tif (value instanceof Date) return Number.isNaN(value.getTime()) ? { type: \"invalid-date\" } : value.toISOString();\n\tif (typeof value === \"object\") {\n\t\tif (state.seen.has(value)) return { type: \"circular\" };\n\t\tstate.seen.add(value);\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value.slice(0, MAX_ARRAY_ITEMS).map((item) => createDiagnosticValueInternal(item, depth + 1, state));\n\t}\n\tif (typeof value === \"object\") {\n\t\ttry {\n\t\t\tconst entries = Object.entries(value as Record<string, unknown>)\n\t\t\t\t.sort(([left], [right]) => left.localeCompare(right))\n\t\t\t\t.slice(0, MAX_OBJECT_KEYS);\n\n\t\t\treturn Object.fromEntries(\n\t\t\t\tentries.map(([entryKey, item]) => [entryKey, createDiagnosticValueInternal(item, depth + 1, state, entryKey)])\n\t\t\t);\n\t\t} catch {\n\t\t\treturn { type: \"unreadable\" };\n\t\t}\n\t}\n\tif (typeof value === \"function\") return { type: \"function\" };\n\tif (typeof value === \"symbol\") return { type: \"symbol\" };\n\tif (typeof value === \"bigint\") return value.toString();\n\n\treturn { type: \"unknown\" };\n}\n\n/**\n * Превращает произвольное значение в JSON-совместимую диагностическую форму.\n * Значения сохраняются читаемыми, потому что queryKey/meta/context нужны\n * для восстановления пользовательского сценария; тяжелые данные query cache\n * отсекаются отдельно и сюда не передаются.\n */\nexport function createDiagnosticValue(value: unknown, depth = 0): ErrorReportSafeValue {\n\treturn createDiagnosticValueInternal(value, depth, {\n\t\tseen: new WeakSet(),\n\t\tmaxStringLength: MAX_DIAGNOSTIC_STRING_LENGTH\n\t});\n}\n\n/**\n * Описывает форму данных кеша без самих значений: типы, размеры массивов и ключи объектов.\n */\nexport function createDataShape(value: unknown, depth = 0): ErrorReportSafeValue {\n\tif (depth >= MAX_DEPTH) return { type: \"truncated\" };\n\tif (value === null) return { type: \"null\" };\n\tif (value === undefined) return { type: \"undefined\" };\n\tif (Array.isArray(value)) {\n\t\treturn {\n\t\t\ttype: \"array\",\n\t\t\tlength: value.length,\n\t\t\tfirstItemsShape: value.slice(0, 3).map((item) => createDataShape(item, depth + 1))\n\t\t};\n\t}\n\tif (typeof value === \"object\") {\n\t\tconst entries = Object.entries(value as Record<string, unknown>).slice(0, MAX_OBJECT_KEYS);\n\n\t\treturn {\n\t\t\ttype: \"object\",\n\t\t\tkeys: entries.map(([key]) => key),\n\t\t\tshape: Object.fromEntries(entries.map(([key, item]) => [key, createDataShape(item, depth + 1)]))\n\t\t};\n\t}\n\n\treturn { type: typeof value };\n}\n\n/**\n * Подключает предметный sanitizer приложения. `undefined` отключает callback и\n * одновременно предотвращает утечку старой policy при hot reload и в тестах.\n */\nexport function setErrorReportSanitizer(sanitizer: ErrorReportSanitizer | undefined) {\n\terrorReportSanitizer = sanitizer;\n}\n\n/**\n * Выполняет built-in нормализацию, затем предметную policy приложения и ещё\n * одну bounded-нормализацию результата перед включением секции в payload.\n */\nexport function sanitizeErrorReportValue(\n\tvalue: unknown,\n\tcontext: ErrorReportSanitizationContext,\n\tmaxStringLength = MAX_DIAGNOSTIC_STRING_LENGTH\n) {\n\tconst createBoundedValue = (candidate: unknown) =>\n\t\tcreateDiagnosticValueInternal(candidate, 0, { seen: new WeakSet(), maxStringLength });\n\tconst safeValue = createBoundedValue(value);\n\tif (!errorReportSanitizer) return safeValue;\n\n\ttry {\n\t\tconst appSanitizedValue = errorReportSanitizer(safeValue, context);\n\t\treturn appSanitizedValue === undefined ? undefined : createBoundedValue(appSanitizedValue);\n\t} catch {\n\t\t// Ошибка optional sanitizer безопаснее приводит к удалению секции, а не к\n\t\t// сохранению потенциально чувствительного исходного значения.\n\t\treturn undefined;\n\t}\n}\n\nexport function sanitizeDetail(\n\tdetail: Record<string, unknown> | undefined,\n\tcontext: ErrorReportSanitizationContext = { scope: \"context\" }\n): Record<string, ErrorReportSafeValue> | undefined {\n\tif (!detail) return undefined;\n\n\tconst sanitizedValue = sanitizeErrorReportValue(detail, context);\n\tif (!sanitizedValue || Array.isArray(sanitizedValue) || typeof sanitizedValue !== \"object\") return undefined;\n\n\treturn Object.keys(sanitizedValue).length ? sanitizedValue : undefined;\n}\n","import { truncateText } from \"../formatters\";\n\nimport { sanitizeDetail, sanitizeDiagnosticText } from \"./safeValue\";\n\nimport type { ErrorReportBreadcrumb } from \"./types\";\n\nconst MAX_BREADCRUMBS = 80;\nconst MAX_ELEMENT_CHAIN = 20;\nconst MAX_ATTRIBUTE_LENGTH = 120;\nconst INTERACTIVE_CLICK_TARGET_SELECTOR = [\"button\", \"a\", \"input\", \"select\", \"textarea\", \"[role]\"].join(\",\");\nconst SAFE_TARGET_VALUE = /^[a-z0-9][a-z0-9._:/-]*$/i;\n\nlet breadcrumbs: ErrorReportBreadcrumb[] = [];\n\nfunction nowUtc() {\n\treturn new Date().toISOString();\n}\n\nexport function addErrorReportBreadcrumb(breadcrumb: Omit<ErrorReportBreadcrumb, \"utc\"> & { utc?: string }) {\n\tbreadcrumbs = [\n\t\t...breadcrumbs,\n\t\t{\n\t\t\t...breadcrumb,\n\t\t\tutc: sanitizeDiagnosticText(breadcrumb.utc ?? nowUtc(), 64),\n\t\t\trouteId: breadcrumb.routeId\n\t\t\t\t? sanitizeDiagnosticText(breadcrumb.routeId.split(/[?#]/, 1)[0] ?? breadcrumb.routeId, 512)\n\t\t\t\t: undefined,\n\t\t\tappId: breadcrumb.appId ? sanitizeDiagnosticText(breadcrumb.appId, 128) : undefined,\n\t\t\tviewId: breadcrumb.viewId ? sanitizeDiagnosticText(breadcrumb.viewId, 128) : undefined,\n\t\t\ttarget: breadcrumb.target ? sanitizeDiagnosticText(breadcrumb.target, 2_048) : undefined,\n\t\t\tdetail: sanitizeDetail(breadcrumb.detail, {\n\t\t\t\tscope: \"breadcrumb-detail\",\n\t\t\t\tsource: breadcrumb.type\n\t\t\t})\n\t\t}\n\t].slice(-MAX_BREADCRUMBS);\n}\n\nexport function getErrorReportBreadcrumbs() {\n\treturn breadcrumbs.slice();\n}\n\nexport function clearErrorReportBreadcrumbs() {\n\tbreadcrumbs = [];\n}\n\nfunction truncateAttributeText(value: string | null | undefined) {\n\treturn truncateText(value, MAX_ATTRIBUTE_LENGTH);\n}\n\nfunction readSafeTargetValue(element: Element) {\n\tconst value = truncateAttributeText(element.getAttribute(\"data-error-report-target\"));\n\treturn value && SAFE_TARGET_VALUE.test(value) ? value : undefined;\n}\n\nfunction readTechnicalAttribute(element: Element, name: string) {\n\tconst value = truncateAttributeText(element.getAttribute(name));\n\treturn value && SAFE_TARGET_VALUE.test(value) ? value : undefined;\n}\n\nfunction readTechnicalAttributes(element: Element) {\n\tconst errorReportTarget = readSafeTargetValue(element);\n\n\t// Специализированный маркер однозначно переопределяет прежнюю host-разметку.\n\t// Fallback сохраняет уже внедрённые data-ui/data-action без возврата к DOM text.\n\treturn {\n\t\trole: readTechnicalAttribute(element, \"role\"),\n\t\ttype: readTechnicalAttribute(element, \"type\"),\n\t\terrorReportTarget,\n\t\tdataUi: errorReportTarget ? undefined : readTechnicalAttribute(element, \"data-ui\"),\n\t\tdataAction: errorReportTarget ? undefined : readTechnicalAttribute(element, \"data-action\")\n\t};\n}\n\nfunction escapeSelectorPart(value: string) {\n\tif (typeof CSS !== \"undefined\" && typeof CSS.escape === \"function\") {\n\t\treturn CSS.escape(value);\n\t}\n\n\treturn value.replace(/[\"\\\\#.[\\]>~+:]/g, \"\\\\$&\");\n}\n\nfunction buildElementSelector(element: Element) {\n\tconst attrs = readTechnicalAttributes(element);\n\tconst parts = [element.tagName.toLowerCase()];\n\n\tif (attrs.role) parts.push(`[role=\"${attrs.role}\"]`);\n\tif (attrs.type) parts.push(`[type=\"${attrs.type}\"]`);\n\tif (attrs.errorReportTarget) {\n\t\tparts.push(`[data-error-report-target=\"${escapeSelectorPart(attrs.errorReportTarget)}\"]`);\n\t} else {\n\t\tif (attrs.dataUi) parts.push(`[data-ui=\"${escapeSelectorPart(attrs.dataUi)}\"]`);\n\t\tif (attrs.dataAction) parts.push(`[data-action=\"${escapeSelectorPart(attrs.dataAction)}\"]`);\n\t}\n\n\treturn parts.join(\"\");\n}\n\nfunction describeElement(element: Element) {\n\tconst attrs = readTechnicalAttributes(element);\n\n\treturn {\n\t\ttag: element.tagName.toLowerCase(),\n\t\tselector: buildElementSelector(element),\n\t\t...attrs\n\t};\n}\n\nfunction compactElementDescription(description: ReturnType<typeof describeElement>) {\n\treturn Object.fromEntries(\n\t\tObject.entries(description).filter(([, value]) => value !== undefined && (!Array.isArray(value) || value.length > 0))\n\t);\n}\n\nfunction getClickElementChain(target: Element) {\n\tconst chain: Element[] = [];\n\tlet current: Element | null = target;\n\n\twhile (current && current !== document.documentElement && chain.length < MAX_ELEMENT_CHAIN) {\n\t\tchain.push(current);\n\t\tif (current === document.body) break;\n\t\tcurrent = current.parentElement;\n\t}\n\n\treturn chain;\n}\n\nfunction findMeaningfulClickTarget(target: Element) {\n\tconst chain = getClickElementChain(target);\n\tconst explicitTarget = chain.find((element) => readSafeTargetValue(element));\n\tif (explicitTarget) return explicitTarget;\n\n\treturn (\n\t\tchain.find(\n\t\t\t(element) =>\n\t\t\t\telement.matches(INTERACTIVE_CLICK_TARGET_SELECTOR) ||\n\t\t\t\treadTechnicalAttribute(element, \"data-action\") !== undefined ||\n\t\t\t\treadTechnicalAttribute(element, \"data-ui\") !== undefined\n\t\t) ?? target\n\t);\n}\n\nfunction describeClickTarget(target: EventTarget | null) {\n\tif (!(target instanceof Element)) return undefined;\n\n\tconst meaningfulTarget = findMeaningfulClickTarget(target);\n\tconst chain = getClickElementChain(meaningfulTarget);\n\n\treturn chain.map((element) => buildElementSelector(element)).join(\" > \");\n}\n\nfunction describeClickDetail(event: MouseEvent) {\n\tconst target = event.target instanceof Element ? event.target : undefined;\n\tconst meaningfulTarget = target ? findMeaningfulClickTarget(target) : undefined;\n\tconst chain = meaningfulTarget\n\t\t? getClickElementChain(meaningfulTarget).map((element) => compactElementDescription(describeElement(element)))\n\t\t: [];\n\n\treturn sanitizeDetail(\n\t\t{\n\t\t\tbutton: event.button,\n\t\t\tctrlKey: event.ctrlKey,\n\t\t\tshiftKey: event.shiftKey,\n\t\t\taltKey: event.altKey,\n\t\t\tclientX: event.clientX,\n\t\t\tclientY: event.clientY,\n\t\t\ttarget: meaningfulTarget ? compactElementDescription(describeElement(meaningfulTarget)) : undefined,\n\t\t\tchain\n\t\t},\n\t\t{ scope: \"breadcrumb-detail\", source: \"click\" }\n\t);\n}\n\n/**\n * Подключает breadcrumbs по действиям пользователя без тел запросов.\n */\nexport function installErrorReportBrowserBreadcrumbs() {\n\tif (typeof window === \"undefined\") return () => undefined;\n\n\tconst onClick = (event: MouseEvent) => {\n\t\taddErrorReportBreadcrumb({\n\t\t\ttype: \"click\",\n\t\t\ttarget: describeClickTarget(event.target),\n\t\t\tdetail: describeClickDetail(event)\n\t\t});\n\t};\n\n\tconst onVisibilityChange = () => {\n\t\taddErrorReportBreadcrumb({\n\t\t\ttype: \"visibility\",\n\t\t\tdetail: sanitizeDetail({ visibilityState: document.visibilityState }, { scope: \"breadcrumb-detail\", source: \"visibility\" })\n\t\t});\n\t};\n\n\twindow.addEventListener(\"click\", onClick, true);\n\tdocument.addEventListener(\"visibilitychange\", onVisibilityChange);\n\n\treturn () => {\n\t\twindow.removeEventListener(\"click\", onClick, true);\n\t\tdocument.removeEventListener(\"visibilitychange\", onVisibilityChange);\n\t};\n}\n","import { sanitizeDetail, sanitizeDiagnosticText, sanitizeDiagnosticTextBytes, sanitizeErrorReportValue } from \"./safeValue\";\n\nimport type {\n\tErrorReportErrorInfo,\n\tErrorReportMutationDiagnostics,\n\tErrorReportPayload,\n\tErrorReportPersistedQueryDiagnostics,\n\tErrorReportQueryDiagnostics\n} from \"./types\";\n\nexport const ERROR_REPORT_PAYLOAD_VERSION = 1 as const;\nexport const ERROR_REPORT_PAYLOAD_MAX_BYTES = 256 * 1_024;\nexport const ERROR_REPORT_STACK_TRACE_MAX_BYTES = 64 * 1_024;\n\nconst ERROR_REPORT_COMPONENT_STACK_MAX_BYTES = 32 * 1_024;\nconst ERROR_REPORT_SOURCE_MAX_LENGTH = 256;\nconst ERROR_REPORT_APPLICATION_MAX_LENGTH = 128;\nconst ERROR_REPORT_LOCATION_MAX_LENGTH = 2_048;\n\nfunction serializedByteLength(value: unknown) {\n\treturn new TextEncoder().encode(JSON.stringify(value)).byteLength;\n}\n\nfunction sanitizePathname(value: string) {\n\treturn sanitizeDiagnosticText(value.split(/[?#]/, 1)[0] ?? value, ERROR_REPORT_LOCATION_MAX_LENGTH);\n}\n\nfunction sanitizeScopedText(\n\tvalue: string,\n\tcontext: { scope: \"error-message\" | \"stack-trace\"; source?: string },\n\tlimit: number,\n\tlimitUnit: \"bytes\" | \"characters\" = \"characters\"\n) {\n\tconst builtInValue = limitUnit === \"bytes\" ? sanitizeDiagnosticTextBytes(value, limit) : sanitizeDiagnosticText(value, limit);\n\tconst sanitizedValue = sanitizeErrorReportValue(builtInValue, context, limit);\n\tif (typeof sanitizedValue !== \"string\") return undefined;\n\treturn limitUnit === \"bytes\" ? sanitizeDiagnosticTextBytes(sanitizedValue, limit) : sanitizeDiagnosticText(sanitizedValue, limit);\n}\n\nfunction sanitizeErrorInfo(error: ErrorReportErrorInfo, source?: string): ErrorReportErrorInfo {\n\treturn {\n\t\tname: sanitizeDiagnosticText(error.name, 256),\n\t\tmessage: sanitizeScopedText(error.message, { scope: \"error-message\", source }, 4_096) ?? \"[REDACTED]\",\n\t\tcode: error.code ? sanitizeDiagnosticText(error.code, 128) : undefined,\n\t\tstackTrace: error.stackTrace\n\t\t\t? sanitizeScopedText(error.stackTrace, { scope: \"stack-trace\", source }, ERROR_REPORT_STACK_TRACE_MAX_BYTES, \"bytes\")\n\t\t\t: undefined,\n\t\thttpStatus: error.httpStatus\n\t};\n}\n\nfunction sanitizeQueryDiagnostics(query: ErrorReportQueryDiagnostics): ErrorReportQueryDiagnostics {\n\treturn {\n\t\t...query,\n\t\tqueryHash: sanitizeDiagnosticText(query.queryHash, 512),\n\t\tqueryKey: sanitizeErrorReportValue(query.queryKey, {\n\t\t\tscope: \"query-key\",\n\t\t\tsource: query.queryHash\n\t\t}) ?? { type: \"redacted\" },\n\t\tmeta: sanitizeDetail(query.meta, { scope: \"query-meta\", source: query.queryHash }),\n\t\tdataShape: query.dataShape\n\t\t\t? sanitizeErrorReportValue(query.dataShape, { scope: \"query-data-shape\", source: query.queryHash })\n\t\t\t: undefined,\n\t\terror: query.error ? sanitizeErrorInfo(query.error, query.queryHash) : undefined\n\t};\n}\n\nfunction sanitizeMutationDiagnostics(mutation: ErrorReportMutationDiagnostics): ErrorReportMutationDiagnostics {\n\treturn {\n\t\t...mutation,\n\t\tmutationKey: mutation.mutationKey ? sanitizeErrorReportValue(mutation.mutationKey, { scope: \"mutation-key\" }) : undefined,\n\t\tmeta: sanitizeDetail(mutation.meta, { scope: \"mutation-meta\" }),\n\t\terror: mutation.error ? sanitizeErrorInfo(mutation.error, \"mutation\") : undefined\n\t};\n}\n\nfunction sanitizePersistedQueryDiagnostics(query: ErrorReportPersistedQueryDiagnostics): ErrorReportPersistedQueryDiagnostics {\n\treturn {\n\t\t...query,\n\t\tbuster: query.buster ? sanitizeDiagnosticText(query.buster, 512) : undefined,\n\t\tqueryHash: query.queryHash ? sanitizeDiagnosticText(query.queryHash, 512) : undefined,\n\t\tqueryKey: query.queryKey\n\t\t\t? sanitizeErrorReportValue(query.queryKey, {\n\t\t\t\t\tscope: \"persisted-query-key\",\n\t\t\t\t\tsource: query.queryHash\n\t\t\t\t})\n\t\t\t: undefined,\n\t\terror: query.error ? sanitizeErrorInfo(query.error, query.queryHash) : undefined\n\t};\n}\n\n/** Возвращает точный UTF-8 размер JSON-формы, которую получит transport. */\nexport function getErrorReportPayloadSize(payload: ErrorReportPayload) {\n\treturn serializedByteLength(payload);\n}\n\nfunction normalizePayloadStrings(payload: ErrorReportPayload): ErrorReportPayload {\n\treturn {\n\t\t...payload,\n\t\treportId: sanitizeDiagnosticText(payload.reportId, 128),\n\t\tsessionId: sanitizeDiagnosticText(payload.sessionId, 128),\n\t\tcreatedUtc: sanitizeDiagnosticText(payload.createdUtc, 64),\n\t\tapplication: sanitizeDiagnosticText(payload.application, ERROR_REPORT_APPLICATION_MAX_LENGTH),\n\t\tsource: sanitizeDiagnosticText(payload.source, ERROR_REPORT_SOURCE_MAX_LENGTH),\n\t\terror: sanitizeErrorInfo(payload.error, payload.source),\n\t\tenvironment: {\n\t\t\t...payload.environment,\n\t\t\tbuildId: payload.environment.buildId ? sanitizeDiagnosticText(payload.environment.buildId, 128) : undefined\n\t\t},\n\t\tclient: payload.client\n\t\t\t? {\n\t\t\t\t\tuserAgent: payload.client.userAgent ? sanitizeDiagnosticText(payload.client.userAgent) : undefined,\n\t\t\t\t\tlanguage: payload.client.language ? sanitizeDiagnosticText(payload.client.language, 128) : undefined,\n\t\t\t\t\ttimeZone: payload.client.timeZone ? sanitizeDiagnosticText(payload.client.timeZone, 128) : undefined\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tlocation: payload.location\n\t\t\t? {\n\t\t\t\t\tpathname: sanitizePathname(payload.location.pathname),\n\t\t\t\t\torigin: payload.location.origin\n\t\t\t\t\t\t? sanitizeDiagnosticText(\n\t\t\t\t\t\t\t\tpayload.location.origin.split(/[?#]/, 1)[0] ?? payload.location.origin,\n\t\t\t\t\t\t\t\tERROR_REPORT_LOCATION_MAX_LENGTH\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t: undefined,\n\t\treact: payload.react?.componentStack\n\t\t\t? {\n\t\t\t\t\tcomponentStack: sanitizeScopedText(\n\t\t\t\t\t\tpayload.react.componentStack,\n\t\t\t\t\t\t{ scope: \"stack-trace\", source: \"react-component-stack\" },\n\t\t\t\t\t\tERROR_REPORT_COMPONENT_STACK_MAX_BYTES,\n\t\t\t\t\t\t\"bytes\"\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tquery: payload.query ? sanitizeQueryDiagnostics(payload.query) : undefined,\n\t\tmutation: payload.mutation ? sanitizeMutationDiagnostics(payload.mutation) : undefined,\n\t\tqueryClient: payload.queryClient\n\t\t\t? {\n\t\t\t\t\tqueries: payload.queryClient.queries.slice(-40).map(sanitizeQueryDiagnostics),\n\t\t\t\t\tmutations: payload.queryClient.mutations.slice(-40).map(sanitizeMutationDiagnostics)\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tpersistedQueries: payload.persistedQueries?.slice(-40).map(sanitizePersistedQueryDiagnostics),\n\t\tbreadcrumbs: payload.breadcrumbs.slice(-80).map((breadcrumb) => ({\n\t\t\t...breadcrumb,\n\t\t\tutc: sanitizeDiagnosticText(breadcrumb.utc, 64),\n\t\t\trouteId: breadcrumb.routeId ? sanitizeDiagnosticText(breadcrumb.routeId, 512) : undefined,\n\t\t\tappId: breadcrumb.appId ? sanitizeDiagnosticText(breadcrumb.appId, 128) : undefined,\n\t\t\tviewId: breadcrumb.viewId ? sanitizeDiagnosticText(breadcrumb.viewId, 128) : undefined,\n\t\t\ttarget: breadcrumb.target ? sanitizeDiagnosticText(breadcrumb.target, 2_048) : undefined,\n\t\t\tdetail: sanitizeDetail(breadcrumb.detail, {\n\t\t\t\tscope: \"breadcrumb-detail\",\n\t\t\t\tsource: breadcrumb.type\n\t\t\t})\n\t\t})),\n\t\tcontext: sanitizeDetail(payload.context, { scope: \"context\", source: payload.source })\n\t};\n}\n\n/**\n * Удаляет диагностические секции в фиксированном порядке, пока payload не\n * помещается в transport/storage limit. Identity, классификация и ошибка\n * сохраняются всегда; маркер перечисляет каждую фактически удалённую секцию.\n */\nexport function limitErrorReportPayload(input: ErrorReportPayload): ErrorReportPayload {\n\tconst normalized = normalizePayloadStrings(input);\n\tconst originalBytes = getErrorReportPayloadSize(normalized);\n\tif (originalBytes <= ERROR_REPORT_PAYLOAD_MAX_BYTES) return normalized;\n\n\tconst droppedSections: string[] = [];\n\tlet payload: ErrorReportPayload = {\n\t\t...normalized,\n\t\ttruncation: {\n\t\t\treason: \"payload-size\",\n\t\t\tlimitBytes: ERROR_REPORT_PAYLOAD_MAX_BYTES,\n\t\t\toriginalBytes,\n\t\t\tdroppedSections\n\t\t}\n\t};\n\n\tconst drop = (\n\t\tsection: string,\n\t\tisPresent: (current: ErrorReportPayload) => boolean,\n\t\tupdate: (current: ErrorReportPayload) => ErrorReportPayload\n\t) => {\n\t\tif (!isPresent(payload) || getErrorReportPayloadSize(payload) <= ERROR_REPORT_PAYLOAD_MAX_BYTES) return;\n\t\tdroppedSections.push(section);\n\t\tpayload = update(payload);\n\t};\n\n\tdrop(\n\t\t\"queryClient\",\n\t\t(current) => current.queryClient !== undefined,\n\t\t(current) => ({ ...current, queryClient: undefined })\n\t);\n\tdrop(\n\t\t\"persistedQueries\",\n\t\t(current) => current.persistedQueries !== undefined,\n\t\t(current) => ({ ...current, persistedQueries: undefined })\n\t);\n\tdrop(\n\t\t\"context\",\n\t\t(current) => current.context !== undefined,\n\t\t(current) => ({ ...current, context: undefined })\n\t);\n\tdrop(\n\t\t\"query.meta\",\n\t\t(current) => current.query?.meta !== undefined,\n\t\t(current) => ({\n\t\t\t...current,\n\t\t\tquery: current.query ? { ...current.query, meta: undefined } : undefined\n\t\t})\n\t);\n\tdrop(\n\t\t\"query.dataShape\",\n\t\t(current) => current.query?.dataShape !== undefined,\n\t\t(current) => ({\n\t\t\t...current,\n\t\t\tquery: current.query ? { ...current.query, dataShape: undefined } : undefined\n\t\t})\n\t);\n\tdrop(\n\t\t\"mutation.meta\",\n\t\t(current) => current.mutation?.meta !== undefined,\n\t\t(current) => ({\n\t\t\t...current,\n\t\t\tmutation: current.mutation ? { ...current.mutation, meta: undefined } : undefined\n\t\t})\n\t);\n\tdrop(\n\t\t\"breadcrumbs:oldest\",\n\t\t(current) => current.breadcrumbs.length > 20,\n\t\t(current) => ({\n\t\t\t...current,\n\t\t\tbreadcrumbs: current.breadcrumbs.slice(-20)\n\t\t})\n\t);\n\tdrop(\n\t\t\"query\",\n\t\t(current) => current.query !== undefined,\n\t\t(current) => ({ ...current, query: undefined })\n\t);\n\tdrop(\n\t\t\"mutation\",\n\t\t(current) => current.mutation !== undefined,\n\t\t(current) => ({ ...current, mutation: undefined })\n\t);\n\tdrop(\n\t\t\"react\",\n\t\t(current) => current.react !== undefined,\n\t\t(current) => ({ ...current, react: undefined })\n\t);\n\tdrop(\n\t\t\"breadcrumbs\",\n\t\t(current) => current.breadcrumbs.length > 0,\n\t\t(current) => ({ ...current, breadcrumbs: [] })\n\t);\n\tdrop(\n\t\t\"client\",\n\t\t(current) => current.client !== undefined,\n\t\t(current) => ({ ...current, client: undefined })\n\t);\n\tdrop(\n\t\t\"viewport\",\n\t\t(current) => current.viewport !== undefined,\n\t\t(current) => ({ ...current, viewport: undefined })\n\t);\n\n\treturn payload;\n}\n","import { normalizeText } from \"../formatters\";\n\nimport { ERROR_REPORT_STACK_TRACE_MAX_BYTES } from \"./payload\";\nimport { sanitizeDiagnosticText, sanitizeDiagnosticTextBytes } from \"./safeValue\";\n\nimport type { ErrorReportErrorInfo } from \"./types\";\n\nconst DEFAULT_ERROR_MESSAGE = \"Неизвестная ошибка\";\n\n/**\n * Гарантирует непустое диагностическое сообщение, сохраняя исходный текст ошибки.\n * Fallback нужен для Error без message и для брошенных пустых строк.\n */\nfunction resolveErrorMessage(message: string) {\n\treturn normalizeText(message) ? sanitizeDiagnosticText(message) : DEFAULT_ERROR_MESSAGE;\n}\n\nfunction readStatus(value: Record<string, unknown>) {\n\tconst status = value.status ?? value.statusCode ?? value.httpStatus;\n\treturn typeof status === \"number\" && Number.isFinite(status) ? status : undefined;\n}\n\nfunction readServerFnTransportErrorInfo(error: unknown): ErrorReportErrorInfo | null {\n\tif (!error || typeof error !== \"object\") {\n\t\treturn null;\n\t}\n\n\tconst transport = error as Record<string, unknown>;\n\tconst appError = transport.appError;\n\tif (!appError || typeof appError !== \"object\") {\n\t\treturn null;\n\t}\n\n\tconst payload = appError as Record<string, unknown>;\n\tconst message = normalizeText(payload.message);\n\tif (!message) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tname: \"AppError\",\n\t\tmessage: sanitizeDiagnosticText(message),\n\t\tcode: normalizeText(payload.code) ? sanitizeDiagnosticText(String(payload.code), 128) : undefined,\n\t\thttpStatus: readStatus(payload)\n\t};\n}\n\n/**\n * Нормализует любое брошенное значение в форму, удобную для поиска и сохранения.\n * Stacktrace намеренно сохраняется полностью: это основная диагностическая ценность отчета.\n */\nexport function createErrorInfo(error: unknown): ErrorReportErrorInfo {\n\tconst serverFnErrorInfo = readServerFnTransportErrorInfo(error);\n\tif (serverFnErrorInfo) {\n\t\treturn serverFnErrorInfo;\n\t}\n\n\tif (error instanceof Error) {\n\t\treturn {\n\t\t\tname: sanitizeDiagnosticText(error.name || \"Error\", 256),\n\t\t\tmessage: resolveErrorMessage(error.message),\n\t\t\tstackTrace: error.stack ? sanitizeDiagnosticTextBytes(error.stack, ERROR_REPORT_STACK_TRACE_MAX_BYTES) : undefined\n\t\t};\n\t}\n\n\tif (error && typeof error === \"object\") {\n\t\tconst record = error as Record<string, unknown>;\n\t\treturn {\n\t\t\tname: sanitizeDiagnosticText(typeof record.name === \"string\" ? record.name : \"Error\", 256),\n\t\t\tmessage: resolveErrorMessage(typeof record.message === \"string\" ? record.message : String(error)),\n\t\t\tstackTrace:\n\t\t\t\ttypeof record.stack === \"string\"\n\t\t\t\t\t? sanitizeDiagnosticTextBytes(record.stack, ERROR_REPORT_STACK_TRACE_MAX_BYTES)\n\t\t\t\t\t: undefined,\n\t\t\thttpStatus: readStatus(record)\n\t\t};\n\t}\n\n\treturn {\n\t\tname: \"Error\",\n\t\tmessage: resolveErrorMessage(typeof error === \"string\" ? error : String(error ?? DEFAULT_ERROR_MESSAGE))\n\t};\n}\n","import { type PersistedQuery } from \"@tanstack/query-persist-client-core\";\nimport { type MutationKey, type MutationState, type QueryClient, type QueryKey, type QueryState } from \"@tanstack/react-query\";\n\nimport { hashString128 } from \"../crypto\";\nimport { createIndexedDbQueryStorage } from \"../query-client\";\nimport { stableStringify } from \"../utils\";\n\nimport { createErrorInfo } from \"./errorInfo\";\nimport { createDataShape, sanitizeDetail, sanitizeDiagnosticText, sanitizeErrorReportValue } from \"./safeValue\";\nimport {\n\ttype ErrorReportMutationDiagnostics,\n\ttype ErrorReportPersistedQueryDiagnostics,\n\ttype ErrorReportQueryDiagnostics,\n\ttype ErrorReportSafeValue\n} from \"./types\";\n\ntype QueryDiagnosticSource = {\n\tqueryHash: string;\n\tqueryKey: QueryKey;\n\tstate: QueryState<unknown, unknown>;\n\tmeta?: Record<string, unknown>;\n\tgetObserversCount: () => number;\n};\n\ntype MutationDiagnosticSource = {\n\toptions: {\n\t\tmutationKey?: MutationKey;\n\t};\n\tstate: MutationState<unknown, unknown, unknown, unknown>;\n\tmeta?: Record<string, unknown>;\n};\n\nconst MAX_QUERY_DIAGNOSTICS = 40;\nconst MAX_MUTATION_DIAGNOSTICS = 40;\nconst MAX_PERSISTED_QUERY_DIAGNOSTICS = 40;\n\nfunction sanitizeMeta(\n\tmeta: Record<string, unknown> | undefined,\n\tscope: \"mutation-meta\" | \"query-meta\",\n\tsource?: string\n): Record<string, ErrorReportSafeValue> | undefined {\n\treturn sanitizeDetail(meta, { scope, source });\n}\n\nexport function collectQueryDiagnostics(query: QueryDiagnosticSource): ErrorReportQueryDiagnostics {\n\tconst queryKey = sanitizeErrorReportValue(query.queryKey, { scope: \"query-key\" }) ?? { type: \"redacted\" };\n\tconst queryHash = hashString128(stableStringify(queryKey));\n\n\treturn {\n\t\tqueryHash,\n\t\tqueryKey,\n\t\tstatus: query.state.status,\n\t\tfetchStatus: query.state.fetchStatus,\n\t\tdataUpdatedAt: query.state.dataUpdatedAt,\n\t\terrorUpdatedAt: query.state.errorUpdatedAt,\n\t\tfailureCount: query.state.fetchFailureCount,\n\t\tisInvalidated: query.state.isInvalidated,\n\t\tobserversCount: query.getObserversCount(),\n\t\tmeta: sanitizeMeta(query.meta, \"query-meta\", queryHash),\n\t\tdataShape: sanitizeErrorReportValue(createDataShape(query.state.data), {\n\t\t\tscope: \"query-data-shape\",\n\t\t\tsource: queryHash\n\t\t}),\n\t\terror: query.state.error ? createErrorInfo(query.state.error) : undefined\n\t};\n}\n\nexport function collectMutationDiagnostics(mutation: MutationDiagnosticSource): ErrorReportMutationDiagnostics {\n\treturn {\n\t\tmutationKey: mutation.options.mutationKey\n\t\t\t? sanitizeErrorReportValue(mutation.options.mutationKey, { scope: \"mutation-key\" })\n\t\t\t: undefined,\n\t\tstatus: mutation.state.status,\n\t\tfailureCount: mutation.state.failureCount,\n\t\tsubmittedAt: mutation.state.submittedAt,\n\t\tmeta: sanitizeMeta(mutation.meta, \"mutation-meta\"),\n\t\terror: mutation.state.error ? createErrorInfo(mutation.state.error) : undefined\n\t};\n}\n\nexport function collectQueryClientDiagnostics(queryClient: QueryClient) {\n\treturn {\n\t\tqueries: queryClient.getQueryCache().getAll().slice(-MAX_QUERY_DIAGNOSTICS).map(collectQueryDiagnostics),\n\t\tmutations: queryClient.getMutationCache().getAll().slice(-MAX_MUTATION_DIAGNOSTICS).map(collectMutationDiagnostics)\n\t};\n}\n\nfunction collectPersistedStateDiagnostics(persistedQuery: PersistedQuery): ErrorReportPersistedQueryDiagnostics {\n\tconst state = persistedQuery.state;\n\tconst queryKey = sanitizeErrorReportValue(persistedQuery.queryKey, { scope: \"persisted-query-key\" });\n\tconst queryHash = queryKey ? hashString128(stableStringify(queryKey)) : undefined;\n\n\treturn {\n\t\tbuster: persistedQuery.buster ? sanitizeDiagnosticText(persistedQuery.buster, 512) : undefined,\n\t\tqueryHash,\n\t\tqueryKey,\n\t\tstatus: state.status,\n\t\tfetchStatus: state.fetchStatus,\n\t\tdataUpdatedAt: state.dataUpdatedAt,\n\t\terrorUpdatedAt: state.errorUpdatedAt,\n\t\tfailureCount: state.fetchFailureCount,\n\t\terror: state.error ? createErrorInfo(state.error) : undefined\n\t};\n}\n\n/**\n * Читает IndexedDB persistence и возвращает только технические поля.\n * `state.data` и другие значения кеша не попадают в результат.\n */\nexport async function collectPersistedQueryDiagnostics(): Promise<ErrorReportPersistedQueryDiagnostics[]> {\n\tconst storage = createIndexedDbQueryStorage<PersistedQuery>();\n\tif (!storage?.entries) return [];\n\n\ttry {\n\t\tconst entries = await storage.entries();\n\t\treturn entries\n\t\t\t.slice(-MAX_PERSISTED_QUERY_DIAGNOSTICS)\n\t\t\t.map(([, persistedQuery]) => collectPersistedStateDiagnostics(persistedQuery));\n\t} catch {\n\t\treturn [];\n\t}\n}\n","type ErrorReportEnvironmentOptions = {\n\tisDev?: boolean;\n};\n\n/**\n * Отчеты собираются только в браузере и только вне dev-режима.\n * На серверном рендеринге draft не создается, чтобы не смешивать SSR-ошибки с клиентской диагностикой.\n */\nexport function isErrorReportingEnabled(options: ErrorReportEnvironmentOptions = {}) {\n\tconst isDev = options.isDev ?? __DEV__;\n\n\treturn typeof window !== \"undefined\" && !isDev;\n}\n\nexport function getErrorReportEnvironment() {\n\tconst mode: \"development\" | \"production\" = __DEV__ ? \"development\" : \"production\";\n\n\treturn {\n\t\tmode,\n\t\tbuildId: typeof __APP_BUILD_ID__ === \"string\" ? __APP_BUILD_ID__ : undefined\n\t};\n}\n\nexport function getErrorReportClientEnvironment() {\n\tif (typeof window === \"undefined\") return undefined;\n\n\treturn {\n\t\tuserAgent: window.navigator.userAgent,\n\t\tlanguage: window.navigator.language,\n\t\ttimeZone: Intl.DateTimeFormat().resolvedOptions().timeZone\n\t};\n}\n","import { z } from \"zod\";\n\nimport { ERROR_REPORT_PAYLOAD_MAX_BYTES, getErrorReportPayloadSize } from \"./payload\";\nimport { getUtf8TextSize } from \"./safeValue\";\n\nimport type { ErrorReportDraft, ErrorReportPayload, ErrorReportSafeValue } from \"./types\";\n\nconst safeValueSchema: z.ZodType<ErrorReportSafeValue> = z.lazy(() =>\n\tz.union([\n\t\tz.string().max(4_096),\n\t\tz.number().finite(),\n\t\tz.boolean(),\n\t\tz.null(),\n\t\tz.array(safeValueSchema).max(20),\n\t\tz.record(z.string(), safeValueSchema).refine((value) => Object.keys(value).length <= 40)\n\t])\n);\n\nconst safeRecordSchema = z.record(z.string(), safeValueSchema).refine((value) => Object.keys(value).length <= 40);\nconst errorInfoSchema = z\n\t.object({\n\t\tname: z.string().min(1).max(256),\n\t\tmessage: z.string().min(1).max(4_096),\n\t\tcode: z.string().max(128).optional(),\n\t\tstackTrace: z\n\t\t\t.string()\n\t\t\t.refine((value) => getUtf8TextSize(value) <= 64 * 1_024)\n\t\t\t.optional(),\n\t\thttpStatus: z.number().finite().optional()\n\t})\n\t.strict();\nconst breadcrumbSchema = z\n\t.object({\n\t\tutc: z.string().min(1).max(64),\n\t\ttype: z.enum([\"route\", \"click\", \"visibility\", \"query-error\", \"mutation-error\", \"runtime-error\"]),\n\t\trouteId: z.string().max(512).optional(),\n\t\tappId: z.string().max(128).optional(),\n\t\tviewId: z.string().max(128).optional(),\n\t\ttarget: z.string().max(2_048).optional(),\n\t\tdetail: safeRecordSchema.optional()\n\t})\n\t.strict();\nconst queryDiagnosticsSchema = z\n\t.object({\n\t\tqueryHash: z.string().max(512),\n\t\tqueryKey: safeValueSchema,\n\t\tstatus: z.string().max(64).optional(),\n\t\tfetchStatus: z.string().max(64).optional(),\n\t\tdataUpdatedAt: z.number().finite().optional(),\n\t\terrorUpdatedAt: z.number().finite().optional(),\n\t\tfailureCount: z.number().finite().optional(),\n\t\tisInvalidated: z.boolean().optional(),\n\t\tobserversCount: z.number().finite().optional(),\n\t\tmeta: safeRecordSchema.optional(),\n\t\tdataShape: safeValueSchema.optional(),\n\t\terror: errorInfoSchema.optional()\n\t})\n\t.strict();\nconst mutationDiagnosticsSchema = z\n\t.object({\n\t\tmutationKey: safeValueSchema.optional(),\n\t\tstatus: z.string().max(64).optional(),\n\t\tfailureCount: z.number().finite().optional(),\n\t\tsubmittedAt: z.number().finite().optional(),\n\t\tmeta: safeRecordSchema.optional(),\n\t\terror: errorInfoSchema.optional()\n\t})\n\t.strict();\nconst persistedQueryDiagnosticsSchema = z\n\t.object({\n\t\tbuster: z.string().max(512).optional(),\n\t\tqueryHash: z.string().max(512).optional(),\n\t\tqueryKey: safeValueSchema.optional(),\n\t\tstatus: z.string().max(64).optional(),\n\t\tfetchStatus: z.string().max(64).optional(),\n\t\tdataUpdatedAt: z.number().finite().optional(),\n\t\terrorUpdatedAt: z.number().finite().optional(),\n\t\tfailureCount: z.number().finite().optional(),\n\t\terror: errorInfoSchema.optional()\n\t})\n\t.strict();\n\nconst errorReportPayloadSchema: z.ZodType<ErrorReportPayload> = z\n\t.object({\n\t\tpayloadVersion: z.literal(1),\n\t\tapplication: z.string().min(1).max(128),\n\t\treportId: z.string().uuid(),\n\t\tsessionId: z.string().uuid(),\n\t\tcreatedUtc: z.string().min(1).max(64),\n\t\tcategory: z.enum([\"query\", \"mutation\", \"runtime\", \"react\"]),\n\t\tsource: z.string().min(1).max(256),\n\t\terror: errorInfoSchema,\n\t\tenvironment: z\n\t\t\t.object({\n\t\t\t\tmode: z.enum([\"development\", \"production\"]),\n\t\t\t\tbuildId: z.string().max(128).optional()\n\t\t\t})\n\t\t\t.strict(),\n\t\tclient: z\n\t\t\t.object({\n\t\t\t\tuserAgent: z.string().max(4_096).optional(),\n\t\t\t\tlanguage: z.string().max(128).optional(),\n\t\t\t\ttimeZone: z.string().max(128).optional()\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.optional(),\n\t\tlocation: z\n\t\t\t.object({\n\t\t\t\tpathname: z.string().max(2_048),\n\t\t\t\torigin: z.string().max(2_048).optional()\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.optional(),\n\t\tviewport: z\n\t\t\t.object({\n\t\t\t\twidth: z.number().finite(),\n\t\t\t\theight: z.number().finite(),\n\t\t\t\tdevicePixelRatio: z.number().finite().optional()\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.optional(),\n\t\treact: z\n\t\t\t.object({\n\t\t\t\tcomponentStack: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.refine((value) => getUtf8TextSize(value) <= 32 * 1_024)\n\t\t\t\t\t.optional()\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.optional(),\n\t\tquery: queryDiagnosticsSchema.optional(),\n\t\tmutation: mutationDiagnosticsSchema.optional(),\n\t\tqueryClient: z\n\t\t\t.object({\n\t\t\t\tqueries: z.array(queryDiagnosticsSchema).max(40),\n\t\t\t\tmutations: z.array(mutationDiagnosticsSchema).max(40)\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.optional(),\n\t\tpersistedQueries: z.array(persistedQueryDiagnosticsSchema).max(40).optional(),\n\t\tbreadcrumbs: z.array(breadcrumbSchema).max(80),\n\t\tcontext: safeRecordSchema.optional(),\n\t\ttruncation: z\n\t\t\t.object({\n\t\t\t\treason: z.literal(\"payload-size\"),\n\t\t\t\tlimitBytes: z.literal(ERROR_REPORT_PAYLOAD_MAX_BYTES),\n\t\t\t\toriginalBytes: z.number().int().positive(),\n\t\t\t\tdroppedSections: z.array(z.string().max(128)).max(32)\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.optional()\n\t})\n\t.strict()\n\t.refine((payload) => getErrorReportPayloadSize(payload) <= ERROR_REPORT_PAYLOAD_MAX_BYTES);\n\nconst errorReportDraftSchema: z.ZodType<ErrorReportDraft> = z\n\t.object({\n\t\treportId: z.string().uuid(),\n\t\tsessionId: z.string().uuid(),\n\t\tcreatedUtc: z.string().min(1).max(64),\n\t\tcategory: z.enum([\"query\", \"mutation\", \"runtime\", \"react\"]),\n\t\tstatus: z.enum([\"pending\", \"sending\", \"sent\", \"failed\"]),\n\t\tsentUtc: z.string().min(1).max(64).optional(),\n\t\tfailedReason: z.string().max(4_096).optional(),\n\t\tpayload: errorReportPayloadSchema\n\t})\n\t.strict()\n\t.superRefine((draft, context) => {\n\t\tconst matchingIdentity =\n\t\t\tdraft.reportId === draft.payload.reportId &&\n\t\t\tdraft.sessionId === draft.payload.sessionId &&\n\t\t\tdraft.createdUtc === draft.payload.createdUtc &&\n\t\t\tdraft.category === draft.payload.category;\n\n\t\tif (!matchingIdentity) {\n\t\t\tcontext.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tmessage: \"Draft identity должна совпадать с payload identity.\"\n\t\t\t});\n\t\t}\n\t});\n\nfunction isSerializedInputWithinLimit(value: unknown, maxBytes: number) {\n\ttry {\n\t\treturn new TextEncoder().encode(JSON.stringify(value)).byteLength <= maxBytes;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Парсит только текущую versioned форму. Unversioned и будущие payload\n * отклоняются явно, чтобы storage/delivery не угадывали форму контракта.\n */\nexport function parseErrorReportPayload(value: unknown) {\n\tif (!isSerializedInputWithinLimit(value, ERROR_REPORT_PAYLOAD_MAX_BYTES)) return undefined;\n\n\ttry {\n\t\tconst result = errorReportPayloadSchema.safeParse(value);\n\t\treturn result.success ? result.data : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** Проверяет одну draft-запись, включая совпадение её identity с payload. */\nexport function parseErrorReportDraft(value: unknown) {\n\tif (!isSerializedInputWithinLimit(value, ERROR_REPORT_PAYLOAD_MAX_BYTES + 16 * 1_024)) return undefined;\n\n\ttry {\n\t\tconst result = errorReportDraftSchema.safeParse(value);\n\t\treturn result.success ? result.data : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Восстанавливает все валидные drafts независимо: одна повреждённая запись не\n * должна уничтожить остальные элементы browser storage.\n */\nexport function parseErrorReportDrafts(value: unknown) {\n\tif (!Array.isArray(value)) return [];\n\treturn value.flatMap((draft) => {\n\t\tconst parsed = parseErrorReportDraft(draft);\n\t\treturn parsed ? [parsed] : [];\n\t});\n}\n","import { uuidv4 } from \"../crypto\";\nimport { formatDateAsODataDatetime } from \"../formatters\";\nimport { getSessionStorageId } from \"../session-storage\";\n\nimport { getErrorReportBreadcrumbs } from \"./breadcrumbs\";\nimport { getErrorReportClientEnvironment, getErrorReportEnvironment, isErrorReportingEnabled } from \"./environment\";\nimport { ERROR_REPORT_PAYLOAD_VERSION, limitErrorReportPayload } from \"./payload\";\nimport { sanitizeDetail, sanitizeDiagnosticText, sanitizeErrorReportValue } from \"./safeValue\";\nimport { parseErrorReportDraft, parseErrorReportDrafts } from \"./schema\";\n\nimport type {\n\tErrorReportCategory,\n\tErrorReportDraft,\n\tErrorReportDraftLifecyclePatch,\n\tErrorReportErrorInfo,\n\tErrorReportPayload,\n\tErrorReportSafeValue\n} from \"./types\";\n\nconst STORAGE_KEY = `${__APP_ID__}.errorReport.drafts.v2`;\nconst SESSION_STORAGE_KEY = `${__APP_ID__}.errorReport.sessionId.v1`;\nconst MAX_DRAFTS = 10;\n\nlet drafts = loadDrafts();\n\nfunction nowUtc() {\n\treturn formatDateAsODataDatetime(new Date());\n}\n\nfunction loadDrafts(): ErrorReportDraft[] {\n\tif (typeof sessionStorage === \"undefined\") return [];\n\n\ttry {\n\t\tconst raw = sessionStorage.getItem(STORAGE_KEY);\n\t\treturn parseErrorReportDrafts(raw ? JSON.parse(raw) : []);\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction saveDrafts(nextDrafts: ErrorReportDraft[]) {\n\tdrafts = nextDrafts.slice(-MAX_DRAFTS);\n\tif (typeof sessionStorage === \"undefined\") return;\n\n\ttry {\n\t\tsessionStorage.setItem(STORAGE_KEY, JSON.stringify(drafts));\n\t} catch {\n\t\t// Переполнение sessionStorage не должно ломать пользовательский сценарий.\n\t}\n}\n\nfunction getLocationSnapshot() {\n\tif (typeof window === \"undefined\") return undefined;\n\n\treturn {\n\t\tpathname: window.location.pathname,\n\t\torigin: window.location.origin\n\t};\n}\n\nfunction getViewportSnapshot() {\n\tif (typeof window === \"undefined\") return undefined;\n\n\treturn {\n\t\twidth: window.innerWidth,\n\t\theight: window.innerHeight,\n\t\tdevicePixelRatio: window.devicePixelRatio\n\t};\n}\n\nfunction sanitizeFailedReason(value: string | undefined) {\n\tif (!value) return undefined;\n\tconst sanitizedValue = sanitizeErrorReportValue(value, { scope: \"draft-failed-reason\", source: \"delivery\" });\n\treturn typeof sanitizedValue === \"string\" ? sanitizedValue : undefined;\n}\n\nexport function getErrorReportDraft(reportId: string) {\n\treturn drafts.find((draft) => draft.reportId === reportId);\n}\n\nexport function updateErrorReportDraft(reportId: string, patch: ErrorReportDraftLifecyclePatch) {\n\tconst current = getErrorReportDraft(reportId);\n\tif (!current) return undefined;\n\n\tconst next = {\n\t\t...current,\n\t\t...patch,\n\t\tsentUtc: \"sentUtc\" in patch ? (patch.sentUtc ? sanitizeDiagnosticText(patch.sentUtc, 64) : undefined) : current.sentUtc,\n\t\tfailedReason: \"failedReason\" in patch ? sanitizeFailedReason(patch.failedReason) : current.failedReason\n\t};\n\tconst parsed = parseErrorReportDraft(next);\n\tif (!parsed) return undefined;\n\n\tsaveDrafts(drafts.map((draft) => (draft.reportId === reportId ? parsed : draft)));\n\treturn parsed;\n}\n\nexport function getErrorReportDrafts() {\n\treturn drafts;\n}\n\nexport function captureErrorReportDraft(args: {\n\tcategory: ErrorReportCategory;\n\tsource: string;\n\terror: ErrorReportErrorInfo;\n\tquery?: ErrorReportPayload[\"query\"];\n\tmutation?: ErrorReportPayload[\"mutation\"];\n\tqueryClient?: ErrorReportPayload[\"queryClient\"];\n\tpersistedQueries?: ErrorReportPayload[\"persistedQueries\"];\n\treact?: ErrorReportPayload[\"react\"];\n\tcontext?: Record<string, ErrorReportSafeValue>;\n}) {\n\tif (!isErrorReportingEnabled()) return undefined;\n\n\tconst reportId = uuidv4();\n\tconst sessionId = getSessionStorageId(SESSION_STORAGE_KEY);\n\tconst createdUtc = nowUtc();\n\tconst payload = limitErrorReportPayload({\n\t\tpayloadVersion: ERROR_REPORT_PAYLOAD_VERSION,\n\t\tapplication: __APP_ID__,\n\t\treportId,\n\t\tsessionId,\n\t\tcreatedUtc,\n\t\tcategory: args.category,\n\t\tsource: sanitizeDiagnosticText(args.source, 256),\n\t\terror: args.error,\n\t\tenvironment: getErrorReportEnvironment(),\n\t\tclient: getErrorReportClientEnvironment(),\n\t\tlocation: getLocationSnapshot(),\n\t\tviewport: getViewportSnapshot(),\n\t\treact: args.react,\n\t\tquery: args.query,\n\t\tmutation: args.mutation,\n\t\tqueryClient: args.queryClient,\n\t\tpersistedQueries: args.persistedQueries,\n\t\tbreadcrumbs: getErrorReportBreadcrumbs(),\n\t\tcontext: sanitizeDetail(args.context, { scope: \"context\", source: args.source })\n\t} satisfies ErrorReportPayload);\n\tconst draft: ErrorReportDraft = {\n\t\treportId,\n\t\tsessionId,\n\t\tcreatedUtc,\n\t\tcategory: args.category,\n\t\tstatus: \"pending\",\n\t\tpayload\n\t};\n\tconst parsed = parseErrorReportDraft(draft);\n\tif (!parsed) return undefined;\n\n\tsaveDrafts([...drafts, parsed]);\n\treturn parsed;\n}\n","import { hashString128 } from \"../crypto\";\nimport { stableStringify } from \"../utils\";\n\nimport type { ErrorReportDraft, ErrorReportErrorInfo, ErrorReportSafeValue } from \"./types\";\n\nexport const RUNTIME_ERROR_REPORT_DEDUPLICATION_WINDOW_MS = 60_000;\n\nconst MAX_RECENT_RUNTIME_ERROR_REPORTS = 100;\nconst recentRuntimeErrorReports = new Map<\n\tstring,\n\t{\n\t\tcapturedAt: number;\n\t\tcapture: Promise<ErrorReportDraft | undefined>;\n\t\texpirationTimer: ReturnType<typeof setTimeout>;\n\t}\n>();\n\ntype RuntimeErrorReportDeduplicationInput = {\n\tcategory: \"runtime\" | \"react\";\n\tsource: string;\n\terror: ErrorReportErrorInfo;\n\tpathname?: string;\n\tscope?: {\n\t\tcomponentStack?: string;\n\t\tdetail?: Record<string, ErrorReportSafeValue>;\n\t};\n};\n\nfunction normalizeStackTrace(stackTrace: string | undefined) {\n\tif (!stackTrace) return undefined;\n\n\treturn stackTrace\n\t\t.split(\"\\n\")\n\t\t.map((line) => line.trim())\n\t\t.filter(Boolean);\n}\n\nfunction createRuntimeErrorReportFingerprint(input: RuntimeErrorReportDeduplicationInput) {\n\treturn hashString128(\n\t\tstableStringify({\n\t\t\tcategory: input.category,\n\t\t\tsource: input.source,\n\t\t\terror: {\n\t\t\t\t...input.error,\n\t\t\t\tstackTrace: normalizeStackTrace(input.error.stackTrace)\n\t\t\t},\n\t\t\tpathname: input.pathname,\n\t\t\tscope: input.scope\n\t\t})\n\t);\n}\n\n/**\n * Удаляет только ожидаемую запись и освобождает связанный таймер.\n * Проверка Promise защищает новую запись того же fingerprint от завершения\n * или отклонения старого capture после lifecycle-сброса.\n */\nfunction removeRuntimeErrorReport(fingerprint: string, expectedCapture?: Promise<ErrorReportDraft | undefined>) {\n\tconst recentReport = recentRuntimeErrorReports.get(fingerprint);\n\tif (!recentReport || (expectedCapture && recentReport.capture !== expectedCapture)) {\n\t\treturn;\n\t}\n\n\tclearTimeout(recentReport.expirationTimer);\n\trecentRuntimeErrorReports.delete(fingerprint);\n}\n\nfunction removeExpiredRuntimeErrorReports(now: number) {\n\tfor (const [fingerprint, recentReport] of recentRuntimeErrorReports) {\n\t\tif (now - recentReport.capturedAt >= RUNTIME_ERROR_REPORT_DEDUPLICATION_WINDOW_MS) {\n\t\t\tremoveRuntimeErrorReport(fingerprint, recentReport.capture);\n\t\t}\n\t}\n}\n\nfunction removeOldestRuntimeErrorReport() {\n\tconst oldestFingerprint = recentRuntimeErrorReports.keys().next().value;\n\tif (oldestFingerprint) {\n\t\tremoveRuntimeErrorReport(oldestFingerprint);\n\t}\n}\n\n/**\n * Объединяет одинаковые runtime capture-вызовы вокруг одной Promise.\n * Все потребители получают один draft, поэтому capture-only boundary не может\n * заблокировать последующую app-level доставку того же отчёта.\n */\nexport function coalesceRuntimeErrorReportCapture(\n\tinput: RuntimeErrorReportDeduplicationInput,\n\tcapture: () => Promise<ErrorReportDraft | undefined>\n) {\n\tconst now = Date.now();\n\tconst fingerprint = createRuntimeErrorReportFingerprint(input);\n\tconst recentReport = recentRuntimeErrorReports.get(fingerprint);\n\n\tif (recentReport && now - recentReport.capturedAt < RUNTIME_ERROR_REPORT_DEDUPLICATION_WINDOW_MS) {\n\t\treturn recentReport.capture;\n\t}\n\n\tremoveExpiredRuntimeErrorReports(now);\n\twhile (recentRuntimeErrorReports.size >= MAX_RECENT_RUNTIME_ERROR_REPORTS) {\n\t\tremoveOldestRuntimeErrorReport();\n\t}\n\n\tconst capturePromise = capture();\n\tconst expirationTimer = setTimeout(() => {\n\t\tremoveRuntimeErrorReport(fingerprint, capturePromise);\n\t}, RUNTIME_ERROR_REPORT_DEDUPLICATION_WINDOW_MS);\n\n\trecentRuntimeErrorReports.set(fingerprint, {\n\t\tcapturedAt: now,\n\t\tcapture: capturePromise,\n\t\texpirationTimer\n\t});\n\n\tvoid capturePromise.catch(() => {\n\t\tremoveRuntimeErrorReport(fingerprint, capturePromise);\n\t});\n\n\treturn capturePromise;\n}\n\n/**\n * Очищает модульное состояние при смене app-level runtime reporter.\n * Функция не входит в публичный package subpath и нужна lifecycle-коду и тестам.\n */\nexport function clearRuntimeErrorReportDeduplication() {\n\tfor (const recentReport of recentRuntimeErrorReports.values()) {\n\t\tclearTimeout(recentReport.expirationTimer);\n\t}\n\trecentRuntimeErrorReports.clear();\n}\n","export type ErrorReportTransportHtmlSummary = {\n\tlength: number;\n\tformCount?: number;\n\tinputNames?: string[];\n};\n\nexport type ErrorReportTransportErrorContext = {\n\tsource: \"fetch.parseResponse\" | \"fetch.buildHttpError\";\n\trequestUrl?: string;\n\tresponseUrl?: string;\n\tmethod?: string;\n\tbaseUrlType?: string;\n\tsapClient?: string | null;\n\tstatus?: number;\n\tstatusText?: string;\n\tcontentType?: string;\n\tredirected?: boolean;\n\tresponseType?: string;\n\thtml?: ErrorReportTransportHtmlSummary;\n};\n\nexport type ErrorReportTransportErrorReporter = (error: Error, context: ErrorReportTransportErrorContext) => void | Promise<void>;\n\nconst DEDUPLICATION_INTERVAL_MS = 60_000;\nconst MAX_RECENT_REPORT_KEYS = 100;\nconst TRANSPORT_REPORT_DELAY_MS = 250;\n\nlet transportErrorReporter: ErrorReportTransportErrorReporter | undefined;\nconst scheduledTransportErrors = new WeakSet<Error>();\nconst suppressedTransportErrors = new WeakSet<Error>();\nconst recentReportKeys = new Map<string, number>();\n\nfunction createReportKey(context: ErrorReportTransportErrorContext) {\n\treturn [context.source, context.method, context.status, context.requestUrl, context.responseUrl].filter(Boolean).join(\"|\");\n}\n\nfunction shouldSkipByRecentKey(context: ErrorReportTransportErrorContext) {\n\tconst now = Date.now();\n\tconst key = createReportKey(context);\n\n\tfor (const [recentKey, timestamp] of recentReportKeys) {\n\t\tif (now - timestamp > DEDUPLICATION_INTERVAL_MS || recentReportKeys.size > MAX_RECENT_REPORT_KEYS) {\n\t\t\trecentReportKeys.delete(recentKey);\n\t\t}\n\t}\n\n\tconst lastReportedAt = recentReportKeys.get(key);\n\tif (lastReportedAt && now - lastReportedAt < DEDUPLICATION_INTERVAL_MS) return true;\n\n\trecentReportKeys.set(key, now);\n\treturn false;\n}\n\n/**\n * Регистрирует приложение как получателя транспортных ошибок.\n * Сам OData transport не знает про QueryClient и UI, поэтому только публикует событие,\n * а app-слой решает, как именно создать и отправить отчет.\n */\nexport function setErrorReportTransportErrorReporter(reporter: ErrorReportTransportErrorReporter | undefined) {\n\ttransportErrorReporter = reporter;\n\trecentReportKeys.clear();\n}\n\nexport function isTransportErrorReportScheduled(error: unknown) {\n\treturn error instanceof Error && scheduledTransportErrors.has(error);\n}\n\nexport function suppressTransportErrorReport(error: unknown) {\n\tif (error instanceof Error) {\n\t\tsuppressedTransportErrors.add(error);\n\t}\n}\n\nexport function reportTransportError(error: Error, context: ErrorReportTransportErrorContext) {\n\tscheduledTransportErrors.add(error);\n\n\t// Даем React Query шанс перехватить эту же ошибку и создать query/mutation-отчет\n\t// с более полезным снимком кеша. Если такого перехвата нет, transport-отчет уйдет сам.\n\tsetTimeout(() => {\n\t\tif (suppressedTransportErrors.has(error)) return;\n\t\tif (!transportErrorReporter) return;\n\t\tif (shouldSkipByRecentKey(context)) return;\n\n\t\ttry {\n\t\t\tconst result = transportErrorReporter(error, context);\n\t\t\tvoid Promise.resolve(result).catch(() => undefined);\n\t\t} catch {\n\t\t\t// Ошибка диагностического hook не должна менять поведение исходного fetch.\n\t\t}\n\t}, TRANSPORT_REPORT_DELAY_MS);\n}\n","import { type Mutation, type Query, type QueryClient } from \"@tanstack/react-query\";\n\nimport { addErrorReportBreadcrumb } from \"./breadcrumbs\";\nimport {\n\tcollectMutationDiagnostics,\n\tcollectPersistedQueryDiagnostics,\n\tcollectQueryClientDiagnostics,\n\tcollectQueryDiagnostics\n} from \"./diagnostics\";\nimport { captureErrorReportDraft } from \"./drafts\";\nimport { createErrorInfo } from \"./errorInfo\";\nimport { coalesceRuntimeErrorReportCapture } from \"./runtimeDeduplication\";\nimport { sanitizeDetail } from \"./safeValue\";\nimport { suppressTransportErrorReport } from \"./transport\";\n\nimport type { ErrorReportMutationContext, ErrorReportQueryContext, ErrorReportRuntimeContext } from \"./types\";\n\nexport async function captureQueryErrorReport(\n\terror: unknown,\n\tquery: Query<unknown, unknown, unknown>,\n\tqueryClient: QueryClient,\n\tcontext?: ErrorReportQueryContext\n) {\n\tsuppressTransportErrorReport(error);\n\tconst source = context?.source ?? \"query\";\n\n\taddErrorReportBreadcrumb({\n\t\ttype: \"query-error\",\n\t\tdetail: sanitizeDetail(\n\t\t\t{\n\t\t\t\tqueryKey: context?.queryKey ?? query.queryKey,\n\t\t\t\t...context?.detail\n\t\t\t},\n\t\t\t{ scope: \"breadcrumb-detail\", source }\n\t\t)\n\t});\n\n\tconst [persistedQueries, queryClientDiagnostics] = await Promise.all([\n\t\tcollectPersistedQueryDiagnostics(),\n\t\tPromise.resolve(collectQueryClientDiagnostics(queryClient))\n\t]);\n\n\treturn captureErrorReportDraft({\n\t\tcategory: \"query\",\n\t\tsource,\n\t\terror: context?.errorInfo ?? createErrorInfo(error),\n\t\tquery: collectQueryDiagnostics(query),\n\t\tqueryClient: queryClientDiagnostics,\n\t\tpersistedQueries,\n\t\tcontext: sanitizeDetail(context?.detail, { scope: \"context\", source })\n\t});\n}\n\nexport async function captureMutationErrorReport(\n\terror: unknown,\n\tmutation: Mutation<unknown, unknown, unknown, unknown>,\n\tqueryClient: QueryClient,\n\tcontext: ErrorReportMutationContext = {}\n) {\n\tsuppressTransportErrorReport(error);\n\tconst source = context.source ?? \"mutation\";\n\n\taddErrorReportBreadcrumb({\n\t\ttype: \"mutation-error\",\n\t\tdetail: sanitizeDetail({ mutationKey: mutation.options.mutationKey, ...context.detail }, { scope: \"breadcrumb-detail\", source })\n\t});\n\n\tconst [persistedQueries, queryClientDiagnostics] = await Promise.all([\n\t\tcollectPersistedQueryDiagnostics(),\n\t\tPromise.resolve(collectQueryClientDiagnostics(queryClient))\n\t]);\n\n\treturn captureErrorReportDraft({\n\t\tcategory: \"mutation\",\n\t\tsource,\n\t\terror: context.errorInfo ?? createErrorInfo(error),\n\t\tmutation: collectMutationDiagnostics(mutation),\n\t\tqueryClient: queryClientDiagnostics,\n\t\tpersistedQueries,\n\t\tcontext: sanitizeDetail(context.detail, { scope: \"context\", source })\n\t});\n}\n\nexport function captureRuntimeErrorReport(error: unknown, context: ErrorReportRuntimeContext = {}, queryClient?: QueryClient) {\n\tconst category = context.category ?? \"runtime\";\n\tconst source = context.source ?? context.category ?? \"runtime\";\n\tconst errorInfo = context.errorInfo ?? createErrorInfo(error);\n\tconst detail = sanitizeDetail(context.detail, { scope: \"context\", source });\n\n\tconst captureDraft = async () => {\n\t\taddErrorReportBreadcrumb({\n\t\t\ttype: \"runtime-error\",\n\t\t\tdetail: sanitizeDetail({ category, source, ...context.detail }, { scope: \"breadcrumb-detail\", source })\n\t\t});\n\n\t\tconst [persistedQueries, queryClientDiagnostics] = queryClient\n\t\t\t? await Promise.all([collectPersistedQueryDiagnostics(), Promise.resolve(collectQueryClientDiagnostics(queryClient))])\n\t\t\t: [undefined, undefined];\n\n\t\treturn captureErrorReportDraft({\n\t\t\tcategory,\n\t\t\tsource,\n\t\t\terror: errorInfo,\n\t\t\treact: context.componentStack ? { componentStack: context.componentStack } : undefined,\n\t\t\tqueryClient: queryClientDiagnostics,\n\t\t\tpersistedQueries,\n\t\t\tcontext: detail\n\t\t});\n\t};\n\n\t/**\n\t * Error report draft создаётся только в браузере. Прямой вызов capture\n\t * сохраняет прежнее SSR-поведение без клиентского TTL-таймера, который\n\t * иначе удерживал бы Node-процесс после no-op результата.\n\t */\n\tif (typeof window === \"undefined\") {\n\t\treturn captureDraft();\n\t}\n\n\treturn coalesceRuntimeErrorReportCapture(\n\t\t{\n\t\t\tcategory,\n\t\t\tsource,\n\t\t\terror: errorInfo,\n\t\t\tpathname: window.location.pathname,\n\t\t\tscope: {\n\t\t\t\tcomponentStack: context.componentStack,\n\t\t\t\tdetail\n\t\t\t}\n\t\t},\n\t\tcaptureDraft\n\t);\n}\n","import { type ErrorReportPayload } from \"./types\";\n\nexport const ERROR_REPORT_QUEUE_VERSION = 1 as const;\nexport const ERROR_REPORT_QUEUE_MAX_ITEMS = 50;\nexport const ERROR_REPORT_QUEUE_TTL_MS = 7 * 24 * 60 * 60 * 1_000;\nexport const ERROR_REPORT_QUEUE_LEASE_MS = 30 * 1_000;\n\nexport type ErrorReportQueueFailureKind = \"http\" | \"network\" | \"timeout\" | \"unknown\";\n\nexport type ErrorReportQueueRecord = {\n\treadonly queueVersion: typeof ERROR_REPORT_QUEUE_VERSION;\n\treadonly reportId: string;\n\treadonly enqueuedUtc: string;\n\treadonly expiresUtc: string;\n\treadonly nextAttemptUtc: string;\n\treadonly attemptCount: number;\n\treadonly payload: ErrorReportPayload;\n\treadonly lease?: {\n\t\treadonly ownerId: string;\n\t\treadonly expiresUtc: string;\n\t};\n\treadonly lastFailure?: {\n\t\treadonly utc: string;\n\t\treadonly kind: ErrorReportQueueFailureKind;\n\t\treadonly httpStatus?: number;\n\t};\n};\n\nexport type ErrorReportQueueEnqueueResult =\n\t| { readonly status: \"enqueued\"; readonly evictedReportId?: string }\n\t| { readonly status: \"duplicate\" }\n\t| { readonly status: \"invalid-payload\" }\n\t| { readonly status: \"capacity-exceeded\" };\n\nexport type ErrorReportQueueLeaseOptions = {\n\treadonly ownerId: string;\n\treadonly now?: Date;\n\treadonly leaseDurationMs?: number;\n};\n\nexport type ErrorReportQueueTransitionResult = \"updated\" | \"missing\" | \"lease-mismatch\";\n\nexport type ErrorReportQueueRetry = {\n\treadonly nextAttemptUtc: string;\n\treadonly failure: {\n\t\treadonly utc: string;\n\t\treadonly kind: ErrorReportQueueFailureKind;\n\t\treadonly httpStatus?: number;\n\t};\n};\n\n/**\n * Durable queue contract отделяет delivery policy от конкретной IndexedDB\n * реализации. Все переходы, зависящие от lease owner, выполняются атомарно.\n */\nexport type ErrorReportQueue = {\n\treadonly enqueue: (payload: ErrorReportPayload, now?: Date) => Promise<ErrorReportQueueEnqueueResult>;\n\treadonly leaseNext: (options: ErrorReportQueueLeaseOptions) => Promise<ErrorReportQueueRecord | undefined>;\n\treadonly acknowledge: (reportId: string, ownerId: string) => Promise<ErrorReportQueueTransitionResult>;\n\treadonly reschedule: (reportId: string, ownerId: string, retry: ErrorReportQueueRetry) => Promise<ErrorReportQueueTransitionResult>;\n\treadonly discard: (reportId: string, ownerId: string) => Promise<ErrorReportQueueTransitionResult>;\n\treadonly getRecords: (now?: Date) => Promise<readonly ErrorReportQueueRecord[]>;\n\treadonly getNextWakeUtc: (now?: Date) => Promise<string | undefined>;\n};\n","import {\n\tERROR_REPORT_QUEUE_MAX_ITEMS,\n\tERROR_REPORT_QUEUE_VERSION,\n\ttype ErrorReportQueueFailureKind,\n\ttype ErrorReportQueueRecord\n} from \"./queueContract\";\nimport { parseErrorReportPayload } from \"./schema\";\n\nconst FAILURE_KINDS = new Set<ErrorReportQueueFailureKind>([\"http\", \"network\", \"timeout\", \"unknown\"]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isUtc(value: unknown): value is string {\n\treturn typeof value === \"string\" && value.length <= 64 && Number.isFinite(Date.parse(value));\n}\n\nfunction isSafeCount(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0;\n}\n\nfunction parseFailure(value: unknown): ErrorReportQueueRecord[\"lastFailure\"] {\n\tif (value === undefined) return undefined;\n\tif (!isRecord(value) || !isUtc(value.utc) || typeof value.kind !== \"string\") return undefined;\n\tif (!FAILURE_KINDS.has(value.kind as ErrorReportQueueFailureKind)) return undefined;\n\tif (\n\t\tvalue.httpStatus !== undefined &&\n\t\t(typeof value.httpStatus !== \"number\" || !Number.isInteger(value.httpStatus) || value.httpStatus < 100 || value.httpStatus > 599)\n\t) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tutc: value.utc,\n\t\tkind: value.kind as ErrorReportQueueFailureKind,\n\t\thttpStatus: value.httpStatus as number | undefined\n\t};\n}\n\nfunction parseLease(value: unknown): ErrorReportQueueRecord[\"lease\"] {\n\tif (value === undefined) return undefined;\n\tif (!isRecord(value) || typeof value.ownerId !== \"string\" || value.ownerId.length === 0 || value.ownerId.length > 128) {\n\t\treturn undefined;\n\t}\n\tif (!isUtc(value.expiresUtc)) return undefined;\n\n\treturn { ownerId: value.ownerId, expiresUtc: value.expiresUtc };\n}\n\n/**\n * Queue parser не угадывает прежние storage-формы. Повреждённая или будущая\n * запись отбрасывается отдельно, не уничтожая соседние валидные отчёты.\n */\nexport function parseErrorReportQueueRecord(value: unknown): ErrorReportQueueRecord | undefined {\n\tif (!isRecord(value) || value.queueVersion !== ERROR_REPORT_QUEUE_VERSION) return undefined;\n\tif (typeof value.reportId !== \"string\" || !isUtc(value.enqueuedUtc) || !isUtc(value.expiresUtc)) return undefined;\n\tif (!isUtc(value.nextAttemptUtc) || !isSafeCount(value.attemptCount)) return undefined;\n\n\tconst payload = parseErrorReportPayload(value.payload);\n\tif (!payload || payload.reportId !== value.reportId) return undefined;\n\n\tconst lease = parseLease(value.lease);\n\tif (value.lease !== undefined && !lease) return undefined;\n\tconst lastFailure = parseFailure(value.lastFailure);\n\tif (value.lastFailure !== undefined && !lastFailure) return undefined;\n\n\treturn {\n\t\tqueueVersion: ERROR_REPORT_QUEUE_VERSION,\n\t\treportId: value.reportId,\n\t\tenqueuedUtc: value.enqueuedUtc,\n\t\texpiresUtc: value.expiresUtc,\n\t\tnextAttemptUtc: value.nextAttemptUtc,\n\t\tattemptCount: value.attemptCount,\n\t\tpayload,\n\t\tlease,\n\t\tlastFailure\n\t};\n}\n\n/** Возвращает bounded текущую очередь без истёкших и повторяющихся ID. */\nexport function normalizeErrorReportQueueRecords(value: unknown, nowMs: number): ErrorReportQueueRecord[] {\n\tif (!Array.isArray(value)) return [];\n\n\tconst reportIds = new Set<string>();\n\tconst records: ErrorReportQueueRecord[] = [];\n\tfor (const valueRecord of value) {\n\t\tconst record = parseErrorReportQueueRecord(valueRecord);\n\t\tif (!record || Date.parse(record.expiresUtc) <= nowMs || reportIds.has(record.reportId)) continue;\n\n\t\treportIds.add(record.reportId);\n\t\trecords.push(record);\n\t\tif (records.length === ERROR_REPORT_QUEUE_MAX_ITEMS) break;\n\t}\n\n\treturn records;\n}\n","import { createIndexedDbQueryStorage, type IndexedDbQueryStorage } from \"../query-client\";\n\nimport {\n\tERROR_REPORT_QUEUE_LEASE_MS,\n\tERROR_REPORT_QUEUE_MAX_ITEMS,\n\tERROR_REPORT_QUEUE_TTL_MS,\n\tERROR_REPORT_QUEUE_VERSION,\n\ttype ErrorReportQueue,\n\ttype ErrorReportQueueEnqueueResult,\n\ttype ErrorReportQueueRecord,\n\ttype ErrorReportQueueTransitionResult\n} from \"./queueContract\";\nimport { normalizeErrorReportQueueRecords } from \"./queueRecord\";\nimport { parseErrorReportPayload } from \"./schema\";\nimport { type ErrorReportPayload } from \"./types\";\n\nconst QUEUE_STORAGE_KEY = \"queue.v1\";\nconst QUEUE_STORE_NAME = \"records\";\n\nexport type CreateErrorReportQueueOptions = {\n\treadonly dbName?: string;\n\treadonly indexedDB?: IDBFactory;\n\t/** Тестовая/альтернативная storage boundary; browser-приложения обычно её не задают. */\n\treadonly storage?: Pick<IndexedDbQueryStorage<unknown>, \"getItem\" | \"updateItem\">;\n};\n\nfunction toUtc(value: number) {\n\treturn new Date(value).toISOString();\n}\n\nfunction normalizeOwnerId(value: string) {\n\tconst ownerId = value.trim();\n\tif (ownerId.length === 0 || ownerId.length > 128) {\n\t\tthrow new Error(\"Error report lease owner должен содержать от 1 до 128 символов\");\n\t}\n\treturn ownerId;\n}\n\nfunction compareQueueOrder(left: ErrorReportQueueRecord, right: ErrorReportQueueRecord) {\n\treturn (\n\t\tDate.parse(left.nextAttemptUtc) - Date.parse(right.nextAttemptUtc) || Date.parse(left.enqueuedUtc) - Date.parse(right.enqueuedUtc)\n\t);\n}\n\nfunction resolveTransition(\n\trecords: ErrorReportQueueRecord[],\n\treportId: string,\n\townerId: string\n): { readonly index: number; readonly result: ErrorReportQueueTransitionResult } {\n\tconst index = records.findIndex((record) => record.reportId === reportId);\n\tif (index < 0) return { index, result: \"missing\" };\n\tif (records[index]?.lease?.ownerId !== ownerId) return { index, result: \"lease-mismatch\" };\n\treturn { index, result: \"updated\" };\n}\n\n/**\n * Создаёт IndexedDB-backed очередь. Одна запись-envelope намеренно хранит не\n * более 50 payload: существующий atomic update primitive тогда сериализует\n * выбор lease между вкладками без дополнительного локального storage слоя.\n */\nexport function createErrorReportQueue(options: CreateErrorReportQueueOptions = {}): ErrorReportQueue | undefined {\n\tconst storage =\n\t\toptions.storage ??\n\t\tcreateIndexedDbQueryStorage<unknown>({\n\t\t\tdbName: options.dbName ?? `${__APP_ID__}.error-report.queue.v1`,\n\t\t\tstoreName: QUEUE_STORE_NAME,\n\t\t\tindexedDB: options.indexedDB\n\t\t});\n\tif (!storage) return undefined;\n\tconst queueStorage = storage;\n\n\tfunction update<TResult>(\n\t\tnowMs: number,\n\t\toperation: (records: ErrorReportQueueRecord[]) => { readonly records: ErrorReportQueueRecord[]; readonly result: TResult }\n\t) {\n\t\treturn queueStorage.updateItem(QUEUE_STORAGE_KEY, (storedValue) => {\n\t\t\tconst decision = operation(normalizeErrorReportQueueRecords(storedValue, nowMs));\n\t\t\treturn { action: \"set\" as const, value: decision.records, result: decision.result };\n\t\t});\n\t}\n\n\treturn {\n\t\tenqueue: async (payload: ErrorReportPayload, now = new Date()) => {\n\t\t\tconst parsedPayload = parseErrorReportPayload(payload);\n\t\t\tif (!parsedPayload) return { status: \"invalid-payload\" as const };\n\n\t\t\tconst nowMs = now.getTime();\n\t\t\tif (!Number.isFinite(nowMs)) return { status: \"invalid-payload\" as const };\n\n\t\t\treturn update<ErrorReportQueueEnqueueResult>(nowMs, (records) => {\n\t\t\t\tif (records.some((record) => record.reportId === parsedPayload.reportId)) {\n\t\t\t\t\treturn { records, result: { status: \"duplicate\" as const } };\n\t\t\t\t}\n\n\t\t\t\tlet evictedReportId: string | undefined;\n\t\t\t\tif (records.length >= ERROR_REPORT_QUEUE_MAX_ITEMS) {\n\t\t\t\t\tconst evictedIndex = records\n\t\t\t\t\t\t.map((record, index) => ({ record, index }))\n\t\t\t\t\t\t.filter(({ record }) => record.lease === undefined)\n\t\t\t\t\t\t.sort((left, right) => Date.parse(left.record.enqueuedUtc) - Date.parse(right.record.enqueuedUtc))[0]?.index;\n\n\t\t\t\t\tif (evictedIndex === undefined) {\n\t\t\t\t\t\treturn { records, result: { status: \"capacity-exceeded\" as const } };\n\t\t\t\t\t}\n\n\t\t\t\t\tevictedReportId = records[evictedIndex]?.reportId;\n\t\t\t\t\trecords.splice(evictedIndex, 1);\n\t\t\t\t}\n\n\t\t\t\tconst nowUtc = toUtc(nowMs);\n\t\t\t\trecords.push({\n\t\t\t\t\tqueueVersion: ERROR_REPORT_QUEUE_VERSION,\n\t\t\t\t\treportId: parsedPayload.reportId,\n\t\t\t\t\tenqueuedUtc: nowUtc,\n\t\t\t\t\texpiresUtc: toUtc(nowMs + ERROR_REPORT_QUEUE_TTL_MS),\n\t\t\t\t\tnextAttemptUtc: nowUtc,\n\t\t\t\t\tattemptCount: 0,\n\t\t\t\t\tpayload: parsedPayload\n\t\t\t\t});\n\n\t\t\t\treturn {\n\t\t\t\t\trecords,\n\t\t\t\t\tresult: evictedReportId ? { status: \"enqueued\" as const, evictedReportId } : { status: \"enqueued\" as const }\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t\tleaseNext: async ({ ownerId: inputOwnerId, now = new Date(), leaseDurationMs = ERROR_REPORT_QUEUE_LEASE_MS }) => {\n\t\t\tconst ownerId = normalizeOwnerId(inputOwnerId);\n\t\t\tconst nowMs = now.getTime();\n\t\t\tif (!Number.isFinite(nowMs) || !Number.isFinite(leaseDurationMs) || leaseDurationMs <= 0) {\n\t\t\t\tthrow new Error(\"Error report lease требует валидное время и положительную длительность\");\n\t\t\t}\n\n\t\t\treturn update(nowMs, (records) => {\n\t\t\t\tconst record = records\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t(candidate) =>\n\t\t\t\t\t\t\tDate.parse(candidate.nextAttemptUtc) <= nowMs &&\n\t\t\t\t\t\t\t(candidate.lease === undefined || Date.parse(candidate.lease.expiresUtc) <= nowMs)\n\t\t\t\t\t)\n\t\t\t\t\t.sort(compareQueueOrder)[0];\n\t\t\t\tif (!record) return { records, result: undefined };\n\n\t\t\t\tconst leasedRecord: ErrorReportQueueRecord = {\n\t\t\t\t\t...record,\n\t\t\t\t\tattemptCount: record.attemptCount + 1,\n\t\t\t\t\tlease: { ownerId, expiresUtc: toUtc(nowMs + leaseDurationMs) }\n\t\t\t\t};\n\t\t\t\treturn {\n\t\t\t\t\trecords: records.map((candidate) => (candidate.reportId === record.reportId ? leasedRecord : candidate)),\n\t\t\t\t\tresult: leasedRecord\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t\tacknowledge: async (reportId, inputOwnerId) => {\n\t\t\tconst ownerId = normalizeOwnerId(inputOwnerId);\n\t\t\treturn update(Date.now(), (records) => {\n\t\t\t\tconst transition = resolveTransition(records, reportId, ownerId);\n\t\t\t\tif (transition.result !== \"updated\") return { records, result: transition.result };\n\t\t\t\trecords.splice(transition.index, 1);\n\t\t\t\treturn { records, result: \"updated\" as const };\n\t\t\t});\n\t\t},\n\t\treschedule: async (reportId, inputOwnerId, retry) => {\n\t\t\tconst ownerId = normalizeOwnerId(inputOwnerId);\n\t\t\tconst nextAttemptMs = Date.parse(retry.nextAttemptUtc);\n\t\t\tconst failureUtcMs = Date.parse(retry.failure.utc);\n\t\t\tif (!Number.isFinite(nextAttemptMs) || !Number.isFinite(failureUtcMs)) {\n\t\t\t\tthrow new Error(\"Error report retry требует валидные UTC timestamps\");\n\t\t\t}\n\n\t\t\treturn update(failureUtcMs, (records) => {\n\t\t\t\tconst transition = resolveTransition(records, reportId, ownerId);\n\t\t\t\tif (transition.result !== \"updated\") return { records, result: transition.result };\n\t\t\t\tconst record = records[transition.index];\n\t\t\t\tif (!record) return { records, result: \"missing\" as const };\n\t\t\t\trecords[transition.index] = {\n\t\t\t\t\t...record,\n\t\t\t\t\tnextAttemptUtc: retry.nextAttemptUtc,\n\t\t\t\t\tlease: undefined,\n\t\t\t\t\tlastFailure: retry.failure\n\t\t\t\t};\n\t\t\t\treturn { records, result: \"updated\" as const };\n\t\t\t});\n\t\t},\n\t\tdiscard: async (reportId, inputOwnerId) => {\n\t\t\tconst ownerId = normalizeOwnerId(inputOwnerId);\n\t\t\treturn update(Date.now(), (records) => {\n\t\t\t\tconst transition = resolveTransition(records, reportId, ownerId);\n\t\t\t\tif (transition.result !== \"updated\") return { records, result: transition.result };\n\t\t\t\trecords.splice(transition.index, 1);\n\t\t\t\treturn { records, result: \"updated\" as const };\n\t\t\t});\n\t\t},\n\t\tgetRecords: async (now = new Date()) => {\n\t\t\tconst nowMs = now.getTime();\n\t\t\tif (!Number.isFinite(nowMs)) return [];\n\t\t\tconst storedValue = await queueStorage.getItem(QUEUE_STORAGE_KEY);\n\t\t\treturn normalizeErrorReportQueueRecords(storedValue, nowMs).sort(compareQueueOrder);\n\t\t},\n\t\tgetNextWakeUtc: async (now = new Date()) => {\n\t\t\tconst nowMs = now.getTime();\n\t\t\tif (!Number.isFinite(nowMs)) return undefined;\n\t\t\tconst records = normalizeErrorReportQueueRecords(await queueStorage.getItem(QUEUE_STORAGE_KEY), nowMs);\n\t\t\tconst nextWakeMs = records.reduce<number | undefined>((current, record) => {\n\t\t\t\tconst recordWakeMs = Math.max(Date.parse(record.nextAttemptUtc), record.lease ? Date.parse(record.lease.expiresUtc) : 0);\n\t\t\t\treturn current === undefined || recordWakeMs < current ? recordWakeMs : current;\n\t\t\t}, undefined);\n\t\t\treturn nextWakeMs === undefined ? undefined : toUtc(nextWakeMs);\n\t\t}\n\t};\n}\n","import { clearRuntimeErrorReportDeduplication } from \"./runtimeDeduplication\";\n\nimport type { ErrorReportRuntimeContext } from \"./types\";\n\nexport type ErrorReportRuntimeErrorReporter = (error: unknown, context: ErrorReportRuntimeContext) => void | Promise<void>;\n\nlet runtimeErrorReporter: ErrorReportRuntimeErrorReporter | undefined;\n\n/**\n * Регистрирует app-слой как получателя ручных runtime-ошибок.\n * Shared-код может вызвать reportRuntimeError без знания о QueryClient, UI и режиме доставки.\n */\nexport function setErrorReportRuntimeErrorReporter(reporter: ErrorReportRuntimeErrorReporter | undefined) {\n\truntimeErrorReporter = reporter;\n\tclearRuntimeErrorReportDeduplication();\n}\n\n/**\n * Ручная отправка runtime-ошибки из try/catch или другого кода вне React-компонента.\n * Функция не бросает исключений: диагностический отчет не должен ломать основной сценарий.\n *\n * @example\n *\n * try {\n * // ...\n * } catch (error) {\n * reportRuntimeError(error, {\n * detail: {\n * source: \"s3-download\",\n * action: \"download-from-s3\"\n * }\n * });\n * }\n */\nexport async function reportRuntimeError(error: unknown, context: ErrorReportRuntimeContext = {}) {\n\tif (!runtimeErrorReporter) return;\n\n\ttry {\n\t\tawait runtimeErrorReporter(error, context);\n\t} catch {\n\t\t// Ошибка диагностического hook не должна менять поведение пользовательского кода.\n\t}\n}\n"],"mappings":";;;;;;;;;AAEA,IAAM,KAAY,GACZ,KAAkB,IAClB,KAAkB,IAClB,IAA+B,MAC/B,KAAiB,cACjB,KAAsB;CAC3B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,GACM,KAAiB,OAEnB;AAEJ,SAAS,GAAa,GAAa;CAClC,OAAO,EAAI,YAAY,CAAC,CAAC,QAAQ,cAAc,EAAE;AAClD;AAEA,SAAS,GAAe,GAAa;CACpC,IAAM,IAAgB,GAAa,CAAG;CACtC,OAAO,GAAoB,MAAM,MAAS,EAAc,SAAS,CAAI,CAAC;AACvE;AAEA,SAAS,GAAS,GAAa;CAC9B,OAAO,GAAa,CAAG,CAAC,CAAC,SAAS,EAAc;AACjD;AAEA,SAAS,GAA6B,GAAe;CACpD,OAAO,iCAAiC,KAAK,CAAK;AACnD;AAEA,SAAS,GAAsB,GAAe;CAC7C,IAAI;EACH,IAAM,IAAS,IAAI,IAAI,GAAO,8BAA8B,GACtD,IAAW,EAAO;EACxB,OAAO,EAAO,WAAW,iCAAiC,IAAW,GAAG,EAAO,SAAS;CACzF,QAAQ;EACP,OAAO,EAAM,MAAM,QAAQ,CAAC,CAAC,CAAC,MAAM;CACrC;AACD;AAOA,SAAgB,EAAuB,GAAe,IAAY,GAA8B;CAC/F,IAAI,IAAiB,EAAM,MAAM,GAAG,CAAS;CAQ7C,OAPI,cAAc,KAAK,CAAc,MACpC,IAAiB,EAAe,QAAQ,uCAAuC,mBAAmB,IAE/F,EAAe,SAAS,GAAG,MAC9B,IAAiB,EAAe,QAAQ,yDAAyD,kBAAkB,IAG7G;AACR;AAGA,SAAgB,EAAgB,GAAe;CAC9C,OAAO,IAAI,YAAY,CAAC,CAAC,OAAO,CAAK,CAAC,CAAC;AACxC;AAOA,SAAgB,EAA4B,GAAe,GAAkB;CAC5E,IAAM,IAAiB,EAAuB,GAAO,CAAQ;CAC7D,IAAI,EAAgB,CAAc,KAAK,GAAU,OAAO;CAExD,IAAI,IAAO,GACP,IAAQ,EAAe;CAC3B,OAAO,IAAO,IAAO;EACpB,IAAM,IAAS,KAAK,MAAM,IAAO,KAAS,CAAC;EAC3C,AAAI,EAAgB,EAAe,MAAM,GAAG,CAAM,CAAC,KAAK,IAAU,IAAO,IACpE,IAAQ,IAAS;CACvB;CAEA,IAAM,IAAe,EAAe,WAAW,IAAO,CAAC,GACjD,IAAU,KAAgB,SAAU,KAAgB,QAAS,IAAO,IAAI;CAC9E,OAAO,EAAe,MAAM,GAAG,CAAO;AACvC;AAOA,SAAS,EAA8B,GAAgB,GAAe,GAA6B,GAAoC;CACtI,IAAI,KAAO,GAAe,CAAG,GAAG,OAAO;CACvC,IAAI,KAAS,IAAW,OAAO,EAAE,MAAM,YAAY;CACnD,IAAI,MAAU,QAAQ,OAAO,KAAU,WAAW,OAAO;CACzD,IAAI,OAAO,KAAU,UAAU,OAAO,OAAO,SAAS,CAAK,IAAI,IAAQ,EAAE,MAAM,oBAAoB;CACnG,IAAI,OAAO,KAAU,UAEpB,OAAO,EADkB,KAAO,GAAS,CAAG,KAAM,GAA6B,CAAK,IAAI,GAAsB,CAAK,IAAI,GACxE,EAAM,eAAe;CAErE,IAAI,MAAU,KAAA,GAAW,OAAO,EAAE,MAAM,YAAY;CACpD,IAAI,aAAiB,MAAM,OAAO,OAAO,MAAM,EAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,eAAe,IAAI,EAAM,YAAY;CAC/G,IAAI,OAAO,KAAU,UAAU;EAC9B,IAAI,EAAM,KAAK,IAAI,CAAK,GAAG,OAAO,EAAE,MAAM,WAAW;EACrD,EAAM,KAAK,IAAI,CAAK;CACrB;CACA,IAAI,MAAM,QAAQ,CAAK,GACtB,OAAO,EAAM,MAAM,GAAG,EAAe,CAAC,CAAC,KAAK,MAAS,EAA8B,GAAM,IAAQ,GAAG,CAAK,CAAC;CAE3G,IAAI,OAAO,KAAU,UACpB,IAAI;EACH,IAAM,IAAU,OAAO,QAAQ,CAAgC,CAAC,CAC9D,MAAM,CAAC,IAAO,CAAC,OAAW,EAAK,cAAc,CAAK,CAAC,CAAC,CACpD,MAAM,GAAG,EAAe;EAE1B,OAAO,OAAO,YACb,EAAQ,KAAK,CAAC,GAAU,OAAU,CAAC,GAAU,EAA8B,GAAM,IAAQ,GAAG,GAAO,CAAQ,CAAC,CAAC,CAC9G;CACD,QAAQ;EACP,OAAO,EAAE,MAAM,aAAa;CAC7B;CAMD,OAJI,OAAO,KAAU,aAAmB,EAAE,MAAM,WAAW,IACvD,OAAO,KAAU,WAAiB,EAAE,MAAM,SAAS,IACnD,OAAO,KAAU,WAAiB,EAAM,SAAS,IAE9C,EAAE,MAAM,UAAU;AAC1B;AAQA,SAAgB,GAAsB,GAAgB,IAAQ,GAAyB;CACtF,OAAO,EAA8B,GAAO,GAAO;EAClD,sBAAM,IAAI,QAAQ;EAClB,iBAAiB;CAClB,CAAC;AACF;AAKA,SAAgB,EAAgB,GAAgB,IAAQ,GAAyB;CAChF,IAAI,KAAS,IAAW,OAAO,EAAE,MAAM,YAAY;CACnD,IAAI,MAAU,MAAM,OAAO,EAAE,MAAM,OAAO;CAC1C,IAAI,MAAU,KAAA,GAAW,OAAO,EAAE,MAAM,YAAY;CACpD,IAAI,MAAM,QAAQ,CAAK,GACtB,OAAO;EACN,MAAM;EACN,QAAQ,EAAM;EACd,iBAAiB,EAAM,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,MAAS,EAAgB,GAAM,IAAQ,CAAC,CAAC;CAClF;CAED,IAAI,OAAO,KAAU,UAAU;EAC9B,IAAM,IAAU,OAAO,QAAQ,CAAgC,CAAC,CAAC,MAAM,GAAG,EAAe;EAEzF,OAAO;GACN,MAAM;GACN,MAAM,EAAQ,KAAK,CAAC,OAAS,CAAG;GAChC,OAAO,OAAO,YAAY,EAAQ,KAAK,CAAC,GAAK,OAAU,CAAC,GAAK,EAAgB,GAAM,IAAQ,CAAC,CAAC,CAAC,CAAC;EAChG;CACD;CAEA,OAAO,EAAE,MAAM,OAAO,EAAM;AAC7B;AAMA,SAAgB,GAAwB,GAA6C;CACpF,IAAuB;AACxB;AAMA,SAAgB,EACf,GACA,GACA,IAAkB,GACjB;CACD,IAAM,KAAsB,MAC3B,EAA8B,GAAW,GAAG;EAAE,sBAAM,IAAI,QAAQ;EAAG;CAAgB,CAAC,GAC/E,IAAY,EAAmB,CAAK;CAC1C,IAAI,CAAC,GAAsB,OAAO;CAElC,IAAI;EACH,IAAM,IAAoB,EAAqB,GAAW,CAAO;EACjE,OAAO,MAAsB,KAAA,IAAY,KAAA,IAAY,EAAmB,CAAiB;CAC1F,QAAQ;EAGP;CACD;AACD;AAEA,SAAgB,EACf,GACA,IAA0C,EAAE,OAAO,UAAU,GACV;CACnD,IAAI,CAAC,GAAQ;CAEb,IAAM,IAAiB,EAAyB,GAAQ,CAAO;CAC3D,OAAC,KAAkB,MAAM,QAAQ,CAAc,KAAK,OAAO,KAAmB,WAElF,OAAO,OAAO,KAAK,CAAc,CAAC,CAAC,SAAS,IAAiB,KAAA;AAC9D;;;ACpNA,IAAM,KAAoB,IACpB,KAAuB,KACvB,KAAoC;CAAC;CAAU;CAAK;CAAS;CAAU;CAAY;AAAQ,CAAC,CAAC,KAAK,GAAG,GACrG,KAAoB,6BAEtB,IAAuC,CAAC;AAE5C,SAAS,KAAS;CACjB,wBAAO,IAAI,KAAK,EAAA,CAAE,YAAY;AAC/B;AAEA,SAAgB,EAAyB,GAAmE;CAC3G,IAAc,CACb,GAAG,GACH;EACC,GAAG;EACH,KAAK,EAAuB,EAAW,OAAO,GAAO,GAAG,EAAE;EAC1D,SAAS,EAAW,UACjB,EAAuB,EAAW,QAAQ,MAAM,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAW,SAAS,GAAG,IACxF,KAAA;EACH,OAAO,EAAW,QAAQ,EAAuB,EAAW,OAAO,GAAG,IAAI,KAAA;EAC1E,QAAQ,EAAW,SAAS,EAAuB,EAAW,QAAQ,GAAG,IAAI,KAAA;EAC7E,QAAQ,EAAW,SAAS,EAAuB,EAAW,QAAQ,IAAK,IAAI,KAAA;EAC/E,QAAQ,EAAe,EAAW,QAAQ;GACzC,OAAO;GACP,QAAQ,EAAW;EACpB,CAAC;CACF,CACD,CAAC,CAAC,MAAM,GAAgB;AACzB;AAEA,SAAgB,KAA4B;CAC3C,OAAO,EAAY,MAAM;AAC1B;AAEA,SAAgB,KAA8B;CAC7C,IAAc,CAAC;AAChB;AAEA,SAAS,GAAsB,GAAkC;CAChE,OAAO,EAAa,GAAO,EAAoB;AAChD;AAEA,SAAS,GAAoB,GAAkB;CAC9C,IAAM,IAAQ,GAAsB,EAAQ,aAAa,0BAA0B,CAAC;CACpF,OAAO,KAAS,GAAkB,KAAK,CAAK,IAAI,IAAQ,KAAA;AACzD;AAEA,SAAS,EAAuB,GAAkB,GAAc;CAC/D,IAAM,IAAQ,GAAsB,EAAQ,aAAa,CAAI,CAAC;CAC9D,OAAO,KAAS,GAAkB,KAAK,CAAK,IAAI,IAAQ,KAAA;AACzD;AAEA,SAAS,GAAwB,GAAkB;CAClD,IAAM,IAAoB,GAAoB,CAAO;CAIrD,OAAO;EACN,MAAM,EAAuB,GAAS,MAAM;EAC5C,MAAM,EAAuB,GAAS,MAAM;EAC5C;EACA,QAAQ,IAAoB,KAAA,IAAY,EAAuB,GAAS,SAAS;EACjF,YAAY,IAAoB,KAAA,IAAY,EAAuB,GAAS,aAAa;CAC1F;AACD;AAEA,SAAS,EAAmB,GAAe;CAK1C,OAJI,OAAO,MAAQ,OAAe,OAAO,IAAI,UAAW,aAChD,IAAI,OAAO,CAAK,IAGjB,EAAM,QAAQ,mBAAmB,MAAM;AAC/C;AAEA,SAAS,GAAqB,GAAkB;CAC/C,IAAM,IAAQ,GAAwB,CAAO,GACvC,IAAQ,CAAC,EAAQ,QAAQ,YAAY,CAAC;CAW5C,OATI,EAAM,QAAM,EAAM,KAAK,UAAU,EAAM,KAAK,GAAG,GAC/C,EAAM,QAAM,EAAM,KAAK,UAAU,EAAM,KAAK,GAAG,GAC/C,EAAM,oBACT,EAAM,KAAK,8BAA8B,EAAmB,EAAM,iBAAiB,EAAE,GAAG,KAEpF,EAAM,UAAQ,EAAM,KAAK,aAAa,EAAmB,EAAM,MAAM,EAAE,GAAG,GAC1E,EAAM,cAAY,EAAM,KAAK,iBAAiB,EAAmB,EAAM,UAAU,EAAE,GAAG,IAGpF,EAAM,KAAK,EAAE;AACrB;AAEA,SAAS,GAAgB,GAAkB;CAC1C,IAAM,IAAQ,GAAwB,CAAO;CAE7C,OAAO;EACN,KAAK,EAAQ,QAAQ,YAAY;EACjC,UAAU,GAAqB,CAAO;EACtC,GAAG;CACJ;AACD;AAEA,SAAS,GAA0B,GAAiD;CACnF,OAAO,OAAO,YACb,OAAO,QAAQ,CAAW,CAAC,CAAC,QAAQ,GAAG,OAAW,MAAU,KAAA,MAAc,CAAC,MAAM,QAAQ,CAAK,KAAK,EAAM,SAAS,EAAE,CACrH;AACD;AAEA,SAAS,EAAqB,GAAiB;CAC9C,IAAM,IAAmB,CAAC,GACtB,IAA0B;CAE9B,OAAO,KAAW,MAAY,SAAS,mBAAmB,EAAM,SAAS,OACxE,EAAM,KAAK,CAAO,GACd,MAAY,SAAS,QACzB,IAAU,EAAQ;CAGnB,OAAO;AACR;AAEA,SAAS,GAA0B,GAAiB;CACnD,IAAM,IAAQ,EAAqB,CAAM;CAIzC,OAHuB,EAAM,MAAM,MAAY,GAAoB,CAAO,CACtE,MAGH,EAAM,MACJ,MACA,EAAQ,QAAQ,EAAiC,KACjD,EAAuB,GAAS,aAAa,MAAM,KAAA,KACnD,EAAuB,GAAS,SAAS,MAAM,KAAA,CACjD,KAAK;AAEP;AAEA,SAAS,GAAoB,GAA4B;CAClD,iBAAkB,SAKxB,OAFc,EADW,GAA0B,CAChB,CAE5B,CAAA,CAAM,KAAK,MAAY,GAAqB,CAAO,CAAC,CAAC,CAAC,KAAK,KAAK;AACxE;AAEA,SAAS,GAAoB,GAAmB;CAC/C,IAAM,IAAS,EAAM,kBAAkB,UAAU,EAAM,SAAS,KAAA,GAC1D,IAAmB,IAAS,GAA0B,CAAM,IAAI,KAAA,GAChE,IAAQ,IACX,EAAqB,CAAgB,CAAC,CAAC,KAAK,MAAY,GAA0B,GAAgB,CAAO,CAAC,CAAC,IAC3G,CAAC;CAEJ,OAAO,EACN;EACC,QAAQ,EAAM;EACd,SAAS,EAAM;EACf,UAAU,EAAM;EAChB,QAAQ,EAAM;EACd,SAAS,EAAM;EACf,SAAS,EAAM;EACf,QAAQ,IAAmB,GAA0B,GAAgB,CAAgB,CAAC,IAAI,KAAA;EAC1F;CACD,GACA;EAAE,OAAO;EAAqB,QAAQ;CAAQ,CAC/C;AACD;AAKA,SAAgB,KAAuC;CACtD,IAAI,OAAO,SAAW,KAAa,aAAa,KAAA;CAEhD,IAAM,KAAW,MAAsB;EACtC,EAAyB;GACxB,MAAM;GACN,QAAQ,GAAoB,EAAM,MAAM;GACxC,QAAQ,GAAoB,CAAK;EAClC,CAAC;CACF,GAEM,UAA2B;EAChC,EAAyB;GACxB,MAAM;GACN,QAAQ,EAAe,EAAE,iBAAiB,SAAS,gBAAgB,GAAG;IAAE,OAAO;IAAqB,QAAQ;GAAa,CAAC;EAC3H,CAAC;CACF;CAKA,OAHA,OAAO,iBAAiB,SAAS,GAAS,EAAI,GAC9C,SAAS,iBAAiB,oBAAoB,CAAkB,SAEnD;EAEZ,AADA,OAAO,oBAAoB,SAAS,GAAS,EAAI,GACjD,SAAS,oBAAoB,oBAAoB,CAAkB;CACpE;AACD;;;AC/LA,IAAa,KAA+B,GAC/B,IAAiC,QACjC,IAAqC,OAE5C,KAAyC,OACzC,KAAiC,KACjC,KAAsC,KACtC,KAAmC;AAEzC,SAAS,GAAqB,GAAgB;CAC7C,OAAO,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK,UAAU,CAAK,CAAC,CAAC,CAAC;AACxD;AAEA,SAAS,GAAiB,GAAe;CACxC,OAAO,EAAuB,EAAM,MAAM,QAAQ,CAAC,CAAC,CAAC,MAAM,GAAO,EAAgC;AACnG;AAEA,SAAS,EACR,GACA,GACA,GACA,IAAoC,cACnC;CAED,IAAM,IAAiB,EADF,MAAc,UAAU,EAA4B,GAAO,CAAK,IAAI,EAAuB,GAAO,CAAK,GAC9D,GAAS,CAAK;CACxE,WAAO,KAAmB,UAC9B,OAAO,MAAc,UAAU,EAA4B,GAAgB,CAAK,IAAI,EAAuB,GAAgB,CAAK;AACjI;AAEA,SAAS,EAAkB,GAA6B,GAAuC;CAC9F,OAAO;EACN,MAAM,EAAuB,EAAM,MAAM,GAAG;EAC5C,SAAS,EAAmB,EAAM,SAAS;GAAE,OAAO;GAAiB;EAAO,GAAG,IAAK,KAAK;EACzF,MAAM,EAAM,OAAO,EAAuB,EAAM,MAAM,GAAG,IAAI,KAAA;EAC7D,YAAY,EAAM,aACf,EAAmB,EAAM,YAAY;GAAE,OAAO;GAAe;EAAO,GAAG,GAAoC,OAAO,IAClH,KAAA;EACH,YAAY,EAAM;CACnB;AACD;AAEA,SAAS,GAAyB,GAAiE;CAClG,OAAO;EACN,GAAG;EACH,WAAW,EAAuB,EAAM,WAAW,GAAG;EACtD,UAAU,EAAyB,EAAM,UAAU;GAClD,OAAO;GACP,QAAQ,EAAM;EACf,CAAC,KAAK,EAAE,MAAM,WAAW;EACzB,MAAM,EAAe,EAAM,MAAM;GAAE,OAAO;GAAc,QAAQ,EAAM;EAAU,CAAC;EACjF,WAAW,EAAM,YACd,EAAyB,EAAM,WAAW;GAAE,OAAO;GAAoB,QAAQ,EAAM;EAAU,CAAC,IAChG,KAAA;EACH,OAAO,EAAM,QAAQ,EAAkB,EAAM,OAAO,EAAM,SAAS,IAAI,KAAA;CACxE;AACD;AAEA,SAAS,GAA4B,GAA0E;CAC9G,OAAO;EACN,GAAG;EACH,aAAa,EAAS,cAAc,EAAyB,EAAS,aAAa,EAAE,OAAO,eAAe,CAAC,IAAI,KAAA;EAChH,MAAM,EAAe,EAAS,MAAM,EAAE,OAAO,gBAAgB,CAAC;EAC9D,OAAO,EAAS,QAAQ,EAAkB,EAAS,OAAO,UAAU,IAAI,KAAA;CACzE;AACD;AAEA,SAAS,GAAkC,GAAmF;CAC7H,OAAO;EACN,GAAG;EACH,QAAQ,EAAM,SAAS,EAAuB,EAAM,QAAQ,GAAG,IAAI,KAAA;EACnE,WAAW,EAAM,YAAY,EAAuB,EAAM,WAAW,GAAG,IAAI,KAAA;EAC5E,UAAU,EAAM,WACb,EAAyB,EAAM,UAAU;GACzC,OAAO;GACP,QAAQ,EAAM;EACf,CAAC,IACA,KAAA;EACH,OAAO,EAAM,QAAQ,EAAkB,EAAM,OAAO,EAAM,SAAS,IAAI,KAAA;CACxE;AACD;AAGA,SAAgB,EAA0B,GAA6B;CACtE,OAAO,GAAqB,CAAO;AACpC;AAEA,SAAS,GAAwB,GAAiD;CACjF,OAAO;EACN,GAAG;EACH,UAAU,EAAuB,EAAQ,UAAU,GAAG;EACtD,WAAW,EAAuB,EAAQ,WAAW,GAAG;EACxD,YAAY,EAAuB,EAAQ,YAAY,EAAE;EACzD,aAAa,EAAuB,EAAQ,aAAa,EAAmC;EAC5F,QAAQ,EAAuB,EAAQ,QAAQ,EAA8B;EAC7E,OAAO,EAAkB,EAAQ,OAAO,EAAQ,MAAM;EACtD,aAAa;GACZ,GAAG,EAAQ;GACX,SAAS,EAAQ,YAAY,UAAU,EAAuB,EAAQ,YAAY,SAAS,GAAG,IAAI,KAAA;EACnG;EACA,QAAQ,EAAQ,SACb;GACA,WAAW,EAAQ,OAAO,YAAY,EAAuB,EAAQ,OAAO,SAAS,IAAI,KAAA;GACzF,UAAU,EAAQ,OAAO,WAAW,EAAuB,EAAQ,OAAO,UAAU,GAAG,IAAI,KAAA;GAC3F,UAAU,EAAQ,OAAO,WAAW,EAAuB,EAAQ,OAAO,UAAU,GAAG,IAAI,KAAA;EAC5F,IACC,KAAA;EACH,UAAU,EAAQ,WACf;GACA,UAAU,GAAiB,EAAQ,SAAS,QAAQ;GACpD,QAAQ,EAAQ,SAAS,SACtB,EACA,EAAQ,SAAS,OAAO,MAAM,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAQ,SAAS,QAChE,EACD,IACC,KAAA;EACJ,IACC,KAAA;EACH,OAAO,EAAQ,OAAO,iBACnB,EACA,gBAAgB,EACf,EAAQ,MAAM,gBACd;GAAE,OAAO;GAAe,QAAQ;EAAwB,GACxD,IACA,OACD,EACD,IACC,KAAA;EACH,OAAO,EAAQ,QAAQ,GAAyB,EAAQ,KAAK,IAAI,KAAA;EACjE,UAAU,EAAQ,WAAW,GAA4B,EAAQ,QAAQ,IAAI,KAAA;EAC7E,aAAa,EAAQ,cAClB;GACA,SAAS,EAAQ,YAAY,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,EAAwB;GAC5E,WAAW,EAAQ,YAAY,UAAU,MAAM,GAAG,CAAC,CAAC,IAAI,EAA2B;EACpF,IACC,KAAA;EACH,kBAAkB,EAAQ,kBAAkB,MAAM,GAAG,CAAC,CAAC,IAAI,EAAiC;EAC5F,aAAa,EAAQ,YAAY,MAAM,GAAG,CAAC,CAAC,KAAK,OAAgB;GAChE,GAAG;GACH,KAAK,EAAuB,EAAW,KAAK,EAAE;GAC9C,SAAS,EAAW,UAAU,EAAuB,EAAW,SAAS,GAAG,IAAI,KAAA;GAChF,OAAO,EAAW,QAAQ,EAAuB,EAAW,OAAO,GAAG,IAAI,KAAA;GAC1E,QAAQ,EAAW,SAAS,EAAuB,EAAW,QAAQ,GAAG,IAAI,KAAA;GAC7E,QAAQ,EAAW,SAAS,EAAuB,EAAW,QAAQ,IAAK,IAAI,KAAA;GAC/E,QAAQ,EAAe,EAAW,QAAQ;IACzC,OAAO;IACP,QAAQ,EAAW;GACpB,CAAC;EACF,EAAE;EACF,SAAS,EAAe,EAAQ,SAAS;GAAE,OAAO;GAAW,QAAQ,EAAQ;EAAO,CAAC;CACtF;AACD;AAOA,SAAgB,GAAwB,GAA+C;CACtF,IAAM,IAAa,GAAwB,CAAK,GAC1C,IAAgB,EAA0B,CAAU;CAC1D,IAAI,KAAA,QAAiD,OAAO;CAE5D,IAAM,IAA4B,CAAC,GAC/B,IAA8B;EACjC,GAAG;EACH,YAAY;GACX,QAAQ;GACR,YAAY;GACZ;GACA;EACD;CACD,GAEM,KACL,GACA,GACA,MACI;EACA,CAAC,EAAU,CAAO,KAAK,EAA0B,CAAO,KAAA,WAC5D,EAAgB,KAAK,CAAO,GAC5B,IAAU,EAAO,CAAO;CACzB;CAgFA,OA9EA,EACC,gBACC,MAAY,EAAQ,gBAAgB,KAAA,IACpC,OAAa;EAAE,GAAG;EAAS,aAAa,KAAA;CAAU,EACpD,GACA,EACC,qBACC,MAAY,EAAQ,qBAAqB,KAAA,IACzC,OAAa;EAAE,GAAG;EAAS,kBAAkB,KAAA;CAAU,EACzD,GACA,EACC,YACC,MAAY,EAAQ,YAAY,KAAA,IAChC,OAAa;EAAE,GAAG;EAAS,SAAS,KAAA;CAAU,EAChD,GACA,EACC,eACC,MAAY,EAAQ,OAAO,SAAS,KAAA,IACpC,OAAa;EACb,GAAG;EACH,OAAO,EAAQ,QAAQ;GAAE,GAAG,EAAQ;GAAO,MAAM,KAAA;EAAU,IAAI,KAAA;CAChE,EACD,GACA,EACC,oBACC,MAAY,EAAQ,OAAO,cAAc,KAAA,IACzC,OAAa;EACb,GAAG;EACH,OAAO,EAAQ,QAAQ;GAAE,GAAG,EAAQ;GAAO,WAAW,KAAA;EAAU,IAAI,KAAA;CACrE,EACD,GACA,EACC,kBACC,MAAY,EAAQ,UAAU,SAAS,KAAA,IACvC,OAAa;EACb,GAAG;EACH,UAAU,EAAQ,WAAW;GAAE,GAAG,EAAQ;GAAU,MAAM,KAAA;EAAU,IAAI,KAAA;CACzE,EACD,GACA,EACC,uBACC,MAAY,EAAQ,YAAY,SAAS,KACzC,OAAa;EACb,GAAG;EACH,aAAa,EAAQ,YAAY,MAAM,GAAG;CAC3C,EACD,GACA,EACC,UACC,MAAY,EAAQ,UAAU,KAAA,IAC9B,OAAa;EAAE,GAAG;EAAS,OAAO,KAAA;CAAU,EAC9C,GACA,EACC,aACC,MAAY,EAAQ,aAAa,KAAA,IACjC,OAAa;EAAE,GAAG;EAAS,UAAU,KAAA;CAAU,EACjD,GACA,EACC,UACC,MAAY,EAAQ,UAAU,KAAA,IAC9B,OAAa;EAAE,GAAG;EAAS,OAAO,KAAA;CAAU,EAC9C,GACA,EACC,gBACC,MAAY,EAAQ,YAAY,SAAS,IACzC,OAAa;EAAE,GAAG;EAAS,aAAa,CAAC;CAAE,EAC7C,GACA,EACC,WACC,MAAY,EAAQ,WAAW,KAAA,IAC/B,OAAa;EAAE,GAAG;EAAS,QAAQ,KAAA;CAAU,EAC/C,GACA,EACC,aACC,MAAY,EAAQ,aAAa,KAAA,IACjC,OAAa;EAAE,GAAG;EAAS,UAAU,KAAA;CAAU,EACjD,GAEO;AACR;;;ACzQA,IAAM,KAAwB;AAM9B,SAAS,EAAoB,GAAiB;CAC7C,OAAO,EAAc,CAAO,IAAI,EAAuB,CAAO,IAAI;AACnE;AAEA,SAAS,GAAW,GAAgC;CACnD,IAAM,IAAS,EAAM,UAAU,EAAM,cAAc,EAAM;CACzD,OAAO,OAAO,KAAW,YAAY,OAAO,SAAS,CAAM,IAAI,IAAS,KAAA;AACzE;AAEA,SAAS,GAA+B,GAA6C;CACpF,IAAI,CAAC,KAAS,OAAO,KAAU,UAC9B,OAAO;CAIR,IAAM,IAAW,EAAU;CAC3B,IAAI,CAAC,KAAY,OAAO,KAAa,UACpC,OAAO;CAGR,IAAM,IAAU,GACV,IAAU,EAAc,EAAQ,OAAO;CAK7C,OAJK,IAIE;EACN,MAAM;EACN,SAAS,EAAuB,CAAO;EACvC,MAAM,EAAc,EAAQ,IAAI,IAAI,EAAuB,OAAO,EAAQ,IAAI,GAAG,GAAG,IAAI,KAAA;EACxF,YAAY,GAAW,CAAO;CAC/B,IARQ;AAST;AAMA,SAAgB,EAAgB,GAAsC;CACrE,IAAM,IAAoB,GAA+B,CAAK;CAC9D,IAAI,GACH,OAAO;CAGR,IAAI,aAAiB,OACpB,OAAO;EACN,MAAM,EAAuB,EAAM,QAAQ,SAAS,GAAG;EACvD,SAAS,EAAoB,EAAM,OAAO;EAC1C,YAAY,EAAM,QAAQ,EAA4B,EAAM,OAAO,CAAkC,IAAI,KAAA;CAC1G;CAGD,IAAI,KAAS,OAAO,KAAU,UAAU;EACvC,IAAM,IAAS;EACf,OAAO;GACN,MAAM,EAAuB,OAAO,EAAO,QAAS,WAAW,EAAO,OAAO,SAAS,GAAG;GACzF,SAAS,EAAoB,OAAO,EAAO,WAAY,WAAW,EAAO,UAAU,OAAO,CAAK,CAAC;GAChG,YACC,OAAO,EAAO,SAAU,WACrB,EAA4B,EAAO,OAAO,CAAkC,IAC5E,KAAA;GACJ,YAAY,GAAW,CAAM;EAC9B;CACD;CAEA,OAAO;EACN,MAAM;EACN,SAAS,EAAoB,OAAO,KAAU,WAAW,IAAQ,OAAO,KAAS,EAAqB,CAAC;CACxG;AACD;;;AC9CA,SAAS,GACR,GACA,GACA,GACmD;CACnD,OAAO,EAAe,GAAM;EAAE;EAAO;CAAO,CAAC;AAC9C;AAEA,SAAgB,EAAwB,GAA2D;CAClG,IAAM,IAAW,EAAyB,EAAM,UAAU,EAAE,OAAO,YAAY,CAAC,KAAK,EAAE,MAAM,WAAW,GAClG,IAAY,EAAc,EAAgB,CAAQ,CAAC;CAEzD,OAAO;EACN;EACA;EACA,QAAQ,EAAM,MAAM;EACpB,aAAa,EAAM,MAAM;EACzB,eAAe,EAAM,MAAM;EAC3B,gBAAgB,EAAM,MAAM;EAC5B,cAAc,EAAM,MAAM;EAC1B,eAAe,EAAM,MAAM;EAC3B,gBAAgB,EAAM,kBAAkB;EACxC,MAAM,GAAa,EAAM,MAAM,cAAc,CAAS;EACtD,WAAW,EAAyB,EAAgB,EAAM,MAAM,IAAI,GAAG;GACtE,OAAO;GACP,QAAQ;EACT,CAAC;EACD,OAAO,EAAM,MAAM,QAAQ,EAAgB,EAAM,MAAM,KAAK,IAAI,KAAA;CACjE;AACD;AAEA,SAAgB,EAA2B,GAAoE;CAC9G,OAAO;EACN,aAAa,EAAS,QAAQ,cAC3B,EAAyB,EAAS,QAAQ,aAAa,EAAE,OAAO,eAAe,CAAC,IAChF,KAAA;EACH,QAAQ,EAAS,MAAM;EACvB,cAAc,EAAS,MAAM;EAC7B,aAAa,EAAS,MAAM;EAC5B,MAAM,GAAa,EAAS,MAAM,eAAe;EACjD,OAAO,EAAS,MAAM,QAAQ,EAAgB,EAAS,MAAM,KAAK,IAAI,KAAA;CACvE;AACD;AAEA,SAAgB,EAA8B,GAA0B;CACvE,OAAO;EACN,SAAS,EAAY,cAAc,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,GAAsB,CAAC,CAAC,IAAI,CAAuB;EACvG,WAAW,EAAY,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,GAAyB,CAAC,CAAC,IAAI,CAA0B;CACnH;AACD;AAEA,SAAS,GAAiC,GAAsE;CAC/G,IAAM,IAAQ,EAAe,OACvB,IAAW,EAAyB,EAAe,UAAU,EAAE,OAAO,sBAAsB,CAAC,GAC7F,IAAY,IAAW,EAAc,EAAgB,CAAQ,CAAC,IAAI,KAAA;CAExE,OAAO;EACN,QAAQ,EAAe,SAAS,EAAuB,EAAe,QAAQ,GAAG,IAAI,KAAA;EACrF;EACA;EACA,QAAQ,EAAM;EACd,aAAa,EAAM;EACnB,eAAe,EAAM;EACrB,gBAAgB,EAAM;EACtB,cAAc,EAAM;EACpB,OAAO,EAAM,QAAQ,EAAgB,EAAM,KAAK,IAAI,KAAA;CACrD;AACD;AAMA,eAAsB,IAAoF;CACzG,IAAM,IAAU,EAA4C;CAC5D,IAAI,CAAC,GAAS,SAAS,OAAO,CAAC;CAE/B,IAAI;EAEH,QAAO,MADe,EAAQ,QAAQ,EAAA,CAEpC,MAAM,GAAgC,CAAC,CACvC,KAAK,GAAG,OAAoB,GAAiC,CAAc,CAAC;CAC/E,QAAQ;EACP,OAAO,CAAC;CACT;AACD;;;ACjHA,SAAgB,GAAwB,IAAyC,CAAC,GAAG;CACpF,IAAM,IAAQ,EAAQ,SAAS;CAE/B,OAAO,OAAO,SAAW,OAAe,CAAC;AAC1C;AAEA,SAAgB,KAA4B;CAG3C,OAAO;EACN,MAH0C,UAAU,gBAAgB;EAIpE,SAAS,OAAO,oBAAqB,WAAW,mBAAmB,KAAA;CACpE;AACD;AAEA,SAAgB,KAAkC;CAC7C,aAAO,SAAW,MAEtB,OAAO;EACN,WAAW,OAAO,UAAU;EAC5B,UAAU,OAAO,UAAU;EAC3B,UAAU,KAAK,eAAe,CAAC,CAAC,gBAAgB,CAAC,CAAC;CACnD;AACD;;;ACxBA,IAAM,IAAmD,EAAE,WAC1D,EAAE,MAAM;CACP,EAAE,OAAO,CAAC,CAAC,IAAI,IAAK;CACpB,EAAE,OAAO,CAAC,CAAC,OAAO;CAClB,EAAE,QAAQ;CACV,EAAE,KAAK;CACP,EAAE,MAAM,CAAe,CAAC,CAAC,IAAI,EAAE;CAC/B,EAAE,OAAO,EAAE,OAAO,GAAG,CAAe,CAAC,CAAC,QAAQ,MAAU,OAAO,KAAK,CAAK,CAAC,CAAC,UAAU,EAAE;AACxF,CAAC,CACF,GAEM,IAAmB,EAAE,OAAO,EAAE,OAAO,GAAG,CAAe,CAAC,CAAC,QAAQ,MAAU,OAAO,KAAK,CAAK,CAAC,CAAC,UAAU,EAAE,GAC1G,IAAkB,EACtB,OAAO;CACP,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG;CAC/B,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAK;CACpC,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS;CACnC,YAAY,EACV,OAAO,CAAC,CACR,QAAQ,MAAU,EAAgB,CAAK,KAAK,KAAU,CAAC,CACvD,SAAS;CACX,YAAY,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS;AAC1C,CAAC,CAAC,CACD,OAAO,GACH,KAAmB,EACvB,OAAO;CACP,KAAK,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;CAC7B,MAAM,EAAE,KAAK;EAAC;EAAS;EAAS;EAAc;EAAe;EAAkB;CAAe,CAAC;CAC/F,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS;CACtC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS;CACpC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS;CACrC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,IAAK,CAAC,CAAC,SAAS;CACvC,QAAQ,EAAiB,SAAS;AACnC,CAAC,CAAC,CACD,OAAO,GACH,KAAyB,EAC7B,OAAO;CACP,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,GAAG;CAC7B,UAAU;CACV,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS;CACpC,aAAa,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS;CACzC,eAAe,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS;CAC5C,gBAAgB,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS;CAC7C,cAAc,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS;CAC3C,eAAe,EAAE,QAAQ,CAAC,CAAC,SAAS;CACpC,gBAAgB,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS;CAC7C,MAAM,EAAiB,SAAS;CAChC,WAAW,EAAgB,SAAS;CACpC,OAAO,EAAgB,SAAS;AACjC,CAAC,CAAC,CACD,OAAO,GACH,KAA4B,EAChC,OAAO;CACP,aAAa,EAAgB,SAAS;CACtC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS;CACpC,cAAc,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS;CAC3C,aAAa,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS;CAC1C,MAAM,EAAiB,SAAS;CAChC,OAAO,EAAgB,SAAS;AACjC,CAAC,CAAC,CACD,OAAO,GACH,KAAkC,EACtC,OAAO;CACP,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS;CACrC,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS;CACxC,UAAU,EAAgB,SAAS;CACnC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS;CACpC,aAAa,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS;CACzC,eAAe,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS;CAC5C,gBAAgB,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS;CAC7C,cAAc,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS;CAC3C,OAAO,EAAgB,SAAS;AACjC,CAAC,CAAC,CACD,OAAO,GAEH,KAA0D,EAC9D,OAAO;CACP,gBAAgB,EAAE,QAAQ,CAAC;CAC3B,aAAa,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG;CACtC,UAAU,EAAE,OAAO,CAAC,CAAC,KAAK;CAC1B,WAAW,EAAE,OAAO,CAAC,CAAC,KAAK;CAC3B,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;CACpC,UAAU,EAAE,KAAK;EAAC;EAAS;EAAY;EAAW;CAAO,CAAC;CAC1D,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG;CACjC,OAAO;CACP,aAAa,EACX,OAAO;EACP,MAAM,EAAE,KAAK,CAAC,eAAe,YAAY,CAAC;EAC1C,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS;CACvC,CAAC,CAAC,CACD,OAAO;CACT,QAAQ,EACN,OAAO;EACP,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,IAAK,CAAC,CAAC,SAAS;EAC1C,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS;EACvC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS;CACxC,CAAC,CAAC,CACD,OAAO,CAAC,CACR,SAAS;CACX,UAAU,EACR,OAAO;EACP,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,IAAK;EAC9B,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,IAAK,CAAC,CAAC,SAAS;CACxC,CAAC,CAAC,CACD,OAAO,CAAC,CACR,SAAS;CACX,UAAU,EACR,OAAO;EACP,OAAO,EAAE,OAAO,CAAC,CAAC,OAAO;EACzB,QAAQ,EAAE,OAAO,CAAC,CAAC,OAAO;EAC1B,kBAAkB,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS;CAChD,CAAC,CAAC,CACD,OAAO,CAAC,CACR,SAAS;CACX,OAAO,EACL,OAAO,EACP,gBAAgB,EACd,OAAO,CAAC,CACR,QAAQ,MAAU,EAAgB,CAAK,KAAK,KAAU,CAAC,CACvD,SAAS,EACZ,CAAC,CAAC,CACD,OAAO,CAAC,CACR,SAAS;CACX,OAAO,GAAuB,SAAS;CACvC,UAAU,GAA0B,SAAS;CAC7C,aAAa,EACX,OAAO;EACP,SAAS,EAAE,MAAM,EAAsB,CAAC,CAAC,IAAI,EAAE;EAC/C,WAAW,EAAE,MAAM,EAAyB,CAAC,CAAC,IAAI,EAAE;CACrD,CAAC,CAAC,CACD,OAAO,CAAC,CACR,SAAS;CACX,kBAAkB,EAAE,MAAM,EAA+B,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS;CAC5E,aAAa,EAAE,MAAM,EAAgB,CAAC,CAAC,IAAI,EAAE;CAC7C,SAAS,EAAiB,SAAS;CACnC,YAAY,EACV,OAAO;EACP,QAAQ,EAAE,QAAQ,cAAc;EAChC,YAAY,EAAE,QAAQ,CAA8B;EACpD,eAAe,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS;EACzC,iBAAiB,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE;CACrD,CAAC,CAAC,CACD,OAAO,CAAC,CACR,SAAS;AACZ,CAAC,CAAC,CACD,OAAO,CAAC,CACR,QAAQ,MAAY,EAA0B,CAAO,KAAK,CAA8B,GAEpF,KAAsD,EAC1D,OAAO;CACP,UAAU,EAAE,OAAO,CAAC,CAAC,KAAK;CAC1B,WAAW,EAAE,OAAO,CAAC,CAAC,KAAK;CAC3B,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;CACpC,UAAU,EAAE,KAAK;EAAC;EAAS;EAAY;EAAW;CAAO,CAAC;CAC1D,QAAQ,EAAE,KAAK;EAAC;EAAW;EAAW;EAAQ;CAAQ,CAAC;CACvD,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS;CAC5C,cAAc,EAAE,OAAO,CAAC,CAAC,IAAI,IAAK,CAAC,CAAC,SAAS;CAC7C,SAAS;AACV,CAAC,CAAC,CACD,OAAO,CAAC,CACR,aAAa,GAAO,MAAY;CAOhC,CALC,EAAM,aAAa,EAAM,QAAQ,YACjC,EAAM,cAAc,EAAM,QAAQ,aAClC,EAAM,eAAe,EAAM,QAAQ,cACnC,EAAM,aAAa,EAAM,QAAQ,aAGjC,EAAQ,SAAS;EAChB,MAAM;EACN,SAAS;CACV,CAAC;AAEH,CAAC;AAEF,SAAS,GAA6B,GAAgB,GAAkB;CACvE,IAAI;EACH,OAAO,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK,UAAU,CAAK,CAAC,CAAC,CAAC,cAAc;CACtE,QAAQ;EACP,OAAO;CACR;AACD;AAMA,SAAgB,EAAwB,GAAgB;CAClD,OAA6B,GAAA,MAAqC,GAEvE,IAAI;EACH,IAAM,IAAS,GAAyB,UAAU,CAAK;EACvD,OAAO,EAAO,UAAU,EAAO,OAAO,KAAA;CACvC,QAAQ;EACP;CACD;AACD;AAGA,SAAgB,EAAsB,GAAgB;CAChD,OAA6B,GAAA,MAAkD,GAEpF,IAAI;EACH,IAAM,IAAS,GAAuB,UAAU,CAAK;EACrD,OAAO,EAAO,UAAU,EAAO,OAAO,KAAA;CACvC,QAAQ;EACP;CACD;AACD;AAMA,SAAgB,GAAuB,GAAgB;CAEtD,OADK,MAAM,QAAQ,CAAK,IACjB,EAAM,SAAS,MAAU;EAC/B,IAAM,IAAS,EAAsB,CAAK;EAC1C,OAAO,IAAS,CAAC,CAAM,IAAI,CAAC;CAC7B,CAAC,IAJiC,CAAC;AAKpC;;;AChNA,IAAM,KAAc,GAAG,WAAW,yBAC5B,KAAsB,GAAG,WAAW,4BAGtC,IAAS,GAAW;AAExB,SAAS,KAAS;CACjB,OAAO,kBAA0B,IAAI,KAAK,CAAC;AAC5C;AAEA,SAAS,KAAiC;CACzC,IAAI,OAAO,iBAAmB,KAAa,OAAO,CAAC;CAEnD,IAAI;EACH,IAAM,IAAM,eAAe,QAAQ,EAAW;EAC9C,OAAO,GAAuB,IAAM,KAAK,MAAM,CAAG,IAAI,CAAC,CAAC;CACzD,QAAQ;EACP,OAAO,CAAC;CACT;AACD;AAEA,SAAS,GAAW,GAAgC;CACnD,QAAS,EAAW,MAAM,GAAW,GACjC,SAAO,iBAAmB,MAE9B,IAAI;EACH,eAAe,QAAQ,IAAa,KAAK,UAAU,CAAM,CAAC;CAC3D,QAAQ,CAER;AACD;AAEA,SAAS,KAAsB;CAC1B,aAAO,SAAW,MAEtB,OAAO;EACN,UAAU,OAAO,SAAS;EAC1B,QAAQ,OAAO,SAAS;CACzB;AACD;AAEA,SAAS,KAAsB;CAC1B,aAAO,SAAW,MAEtB,OAAO;EACN,OAAO,OAAO;EACd,QAAQ,OAAO;EACf,kBAAkB,OAAO;CAC1B;AACD;AAEA,SAAS,GAAqB,GAA2B;CACxD,IAAI,CAAC,GAAO;CACZ,IAAM,IAAiB,EAAyB,GAAO;EAAE,OAAO;EAAuB,QAAQ;CAAW,CAAC;CAC3G,OAAO,OAAO,KAAmB,WAAW,IAAiB,KAAA;AAC9D;AAEA,SAAgB,GAAoB,GAAkB;CACrD,OAAO,EAAO,MAAM,MAAU,EAAM,aAAa,CAAQ;AAC1D;AAEA,SAAgB,GAAuB,GAAkB,GAAuC;CAC/F,IAAM,IAAU,GAAoB,CAAQ;CAC5C,IAAI,CAAC,GAAS;CAQd,IAAM,IAAS,EAAsB;EALpC,GAAG;EACH,GAAG;EACH,SAAS,aAAa,IAAS,EAAM,UAAU,EAAuB,EAAM,SAAS,EAAE,IAAI,KAAA,IAAa,EAAQ;EAChH,cAAc,kBAAkB,IAAQ,GAAqB,EAAM,YAAY,IAAI,EAAQ;CAEvD,CAAI;CACpC,OAGL,OADA,GAAW,EAAO,KAAK,MAAW,EAAM,aAAa,IAAW,IAAS,CAAM,CAAC,GACzE;AACR;AAEA,SAAgB,KAAuB;CACtC,OAAO;AACR;AAEA,SAAgB,EAAwB,GAUrC;CACF,IAAI,CAAC,GAAwB,GAAG;CAEhC,IAAM,IAAW,EAAO,GAClB,IAAY,EAAoB,EAAmB,GACnD,IAAa,GAAO,GACpB,IAAU,GAAwB;EACvC,gBAAA;EACA,aAAa;EACb;EACA;EACA;EACA,UAAU,EAAK;EACf,QAAQ,EAAuB,EAAK,QAAQ,GAAG;EAC/C,OAAO,EAAK;EACZ,aAAa,GAA0B;EACvC,QAAQ,GAAgC;EACxC,UAAU,GAAoB;EAC9B,UAAU,GAAoB;EAC9B,OAAO,EAAK;EACZ,OAAO,EAAK;EACZ,UAAU,EAAK;EACf,aAAa,EAAK;EAClB,kBAAkB,EAAK;EACvB,aAAa,GAA0B;EACvC,SAAS,EAAe,EAAK,SAAS;GAAE,OAAO;GAAW,QAAQ,EAAK;EAAO,CAAC;CAChF,CAA8B,GASxB,IAAS,EAAsB;EAPpC;EACA;EACA;EACA,UAAU,EAAK;EACf,QAAQ;EACR;CAEoC,CAAK;CACrC,OAGL,OADA,GAAW,CAAC,GAAG,GAAQ,CAAM,CAAC,GACvB;AACR;;;AClJA,IAAa,KAA+C,KAEtD,KAAmC,KACnC,oBAA4B,IAAI,IAOpC;AAaF,SAAS,GAAoB,GAAgC;CACvD,OAEL,OAAO,EACL,MAAM,IAAI,CAAC,CACX,KAAK,MAAS,EAAK,KAAK,CAAC,CAAC,CAC1B,OAAO,OAAO;AACjB;AAEA,SAAS,GAAoC,GAA6C;CACzF,OAAO,EACN,EAAgB;EACf,UAAU,EAAM;EAChB,QAAQ,EAAM;EACd,OAAO;GACN,GAAG,EAAM;GACT,YAAY,GAAoB,EAAM,MAAM,UAAU;EACvD;EACA,UAAU,EAAM;EAChB,OAAO,EAAM;CACd,CAAC,CACF;AACD;AAOA,SAAS,EAAyB,GAAqB,GAAyD;CAC/G,IAAM,IAAe,EAA0B,IAAI,CAAW;CAC1D,CAAC,KAAiB,KAAmB,EAAa,YAAY,MAIlE,aAAa,EAAa,eAAe,GACzC,EAA0B,OAAO,CAAW;AAC7C;AAEA,SAAS,GAAiC,GAAa;CACtD,KAAK,IAAM,CAAC,GAAa,MAAiB,GACzC,AAAI,IAAM,EAAa,cAAA,OACtB,EAAyB,GAAa,EAAa,OAAO;AAG7D;AAEA,SAAS,KAAiC;CACzC,IAAM,IAAoB,EAA0B,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;CAClE,AAAI,KACH,EAAyB,CAAiB;AAE5C;AAOA,SAAgB,GACf,GACA,GACC;CACD,IAAM,IAAM,KAAK,IAAI,GACf,IAAc,GAAoC,CAAK,GACvD,IAAe,EAA0B,IAAI,CAAW;CAE9D,IAAI,KAAgB,IAAM,EAAa,aAAA,KACtC,OAAO,EAAa;CAIrB,KADA,GAAiC,CAAG,GAC7B,EAA0B,QAAQ,KACxC,GAA+B;CAGhC,IAAM,IAAiB,EAAQ,GACzB,IAAkB,iBAAiB;EACxC,EAAyB,GAAa,CAAc;CACrD,GAAG,EAA4C;CAY/C,OAVA,EAA0B,IAAI,GAAa;EAC1C,YAAY;EACZ,SAAS;EACT;CACD,CAAC,GAED,EAAoB,YAAY;EAC/B,EAAyB,GAAa,CAAc;CACrD,CAAC,GAEM;AACR;AAMA,SAAgB,KAAuC;CACtD,KAAK,IAAM,KAAgB,EAA0B,OAAO,GAC3D,aAAa,EAAa,eAAe;CAE1C,EAA0B,MAAM;AACjC;;;AC5GA,IAAM,KAA4B,KAC5B,KAAyB,KACzB,KAA4B,KAE9B,GACE,qBAA2B,IAAI,QAAe,GAC9C,qBAA4B,IAAI,QAAe,GAC/C,oBAAmB,IAAI,IAAoB;AAEjD,SAAS,GAAgB,GAA2C;CACnE,OAAO;EAAC,EAAQ;EAAQ,EAAQ;EAAQ,EAAQ;EAAQ,EAAQ;EAAY,EAAQ;CAAW,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;AAC1H;AAEA,SAAS,GAAsB,GAA2C;CACzE,IAAM,IAAM,KAAK,IAAI,GACf,IAAM,GAAgB,CAAO;CAEnC,KAAK,IAAM,CAAC,GAAW,MAAc,GACpC,CAAI,IAAM,IAAY,MAA6B,EAAiB,OAAO,OAC1E,EAAiB,OAAO,CAAS;CAInC,IAAM,IAAiB,EAAiB,IAAI,CAAG;CAI/C,OAHI,KAAkB,IAAM,IAAiB,KAAkC,MAE/E,EAAiB,IAAI,GAAK,CAAG,GACtB;AACR;AAOA,SAAgB,GAAqC,GAAyD;CAE7G,AADA,IAAyB,GACzB,EAAiB,MAAM;AACxB;AAEA,SAAgB,GAAgC,GAAgB;CAC/D,OAAO,aAAiB,SAAS,GAAyB,IAAI,CAAK;AACpE;AAEA,SAAgB,EAA6B,GAAgB;CAC5D,AAAI,aAAiB,SACpB,GAA0B,IAAI,CAAK;AAErC;AAEA,SAAgB,GAAqB,GAAc,GAA2C;CAK7F,AAJA,GAAyB,IAAI,CAAK,GAIlC,iBAAiB;EACZ,QAA0B,IAAI,CAAK,KAClC,KACD,IAAsB,CAAO,GAEjC,IAAI;GACH,IAAM,IAAS,EAAuB,GAAO,CAAO;GACpD,QAAa,QAAQ,CAAM,CAAC,CAAC,YAAY,KAAA,CAAS;EACnD,QAAQ,CAER;CACD,GAAG,EAAyB;AAC7B;;;ACzEA,eAAsB,GACrB,GACA,GACA,GACA,GACC;CACD,EAA6B,CAAK;CAClC,IAAM,IAAS,GAAS,UAAU;CAElC,EAAyB;EACxB,MAAM;EACN,QAAQ,EACP;GACC,UAAU,GAAS,YAAY,EAAM;GACrC,GAAG,GAAS;EACb,GACA;GAAE,OAAO;GAAqB;EAAO,CACtC;CACD,CAAC;CAED,IAAM,CAAC,GAAkB,KAA0B,MAAM,QAAQ,IAAI,CACpE,EAAiC,GACjC,QAAQ,QAAQ,EAA8B,CAAW,CAAC,CAC3D,CAAC;CAED,OAAO,EAAwB;EAC9B,UAAU;EACV;EACA,OAAO,GAAS,aAAa,EAAgB,CAAK;EAClD,OAAO,EAAwB,CAAK;EACpC,aAAa;EACb;EACA,SAAS,EAAe,GAAS,QAAQ;GAAE,OAAO;GAAW;EAAO,CAAC;CACtE,CAAC;AACF;AAEA,eAAsB,GACrB,GACA,GACA,GACA,IAAsC,CAAC,GACtC;CACD,EAA6B,CAAK;CAClC,IAAM,IAAS,EAAQ,UAAU;CAEjC,EAAyB;EACxB,MAAM;EACN,QAAQ,EAAe;GAAE,aAAa,EAAS,QAAQ;GAAa,GAAG,EAAQ;EAAO,GAAG;GAAE,OAAO;GAAqB;EAAO,CAAC;CAChI,CAAC;CAED,IAAM,CAAC,GAAkB,KAA0B,MAAM,QAAQ,IAAI,CACpE,EAAiC,GACjC,QAAQ,QAAQ,EAA8B,CAAW,CAAC,CAC3D,CAAC;CAED,OAAO,EAAwB;EAC9B,UAAU;EACV;EACA,OAAO,EAAQ,aAAa,EAAgB,CAAK;EACjD,UAAU,EAA2B,CAAQ;EAC7C,aAAa;EACb;EACA,SAAS,EAAe,EAAQ,QAAQ;GAAE,OAAO;GAAW;EAAO,CAAC;CACrE,CAAC;AACF;AAEA,SAAgB,GAA0B,GAAgB,IAAqC,CAAC,GAAG,GAA2B;CAC7H,IAAM,IAAW,EAAQ,YAAY,WAC/B,IAAS,EAAQ,UAAU,EAAQ,YAAY,WAC/C,IAAY,EAAQ,aAAa,EAAgB,CAAK,GACtD,IAAS,EAAe,EAAQ,QAAQ;EAAE,OAAO;EAAW;CAAO,CAAC,GAEpE,IAAe,YAAY;EAChC,EAAyB;GACxB,MAAM;GACN,QAAQ,EAAe;IAAE;IAAU;IAAQ,GAAG,EAAQ;GAAO,GAAG;IAAE,OAAO;IAAqB;GAAO,CAAC;EACvG,CAAC;EAED,IAAM,CAAC,GAAkB,KAA0B,IAChD,MAAM,QAAQ,IAAI,CAAC,EAAiC,GAAG,QAAQ,QAAQ,EAA8B,CAAW,CAAC,CAAC,CAAC,IACnH,CAAC,KAAA,GAAW,KAAA,CAAS;EAExB,OAAO,EAAwB;GAC9B;GACA;GACA,OAAO;GACP,OAAO,EAAQ,iBAAiB,EAAE,gBAAgB,EAAQ,eAAe,IAAI,KAAA;GAC7E,aAAa;GACb;GACA,SAAS;EACV,CAAC;CACF;CAWA,OAJI,OAAO,SAAW,MACd,EAAa,IAGd,GACN;EACC;EACA;EACA,OAAO;EACP,UAAU,OAAO,SAAS;EAC1B,OAAO;GACN,gBAAgB,EAAQ;GACxB;EACD;CACD,GACA,CACD;AACD;;;AClIA,IAAa,KAA6B,GAC7B,KAA+B,IAC/B,KAA4B,QAC5B,KAA8B,KCGrC,qBAAgB,IAAI,IAAiC;CAAC;CAAQ;CAAW;CAAW;AAAS,CAAC;AAEpG,SAAS,EAAS,GAAkD;CACnE,OAAO,OAAO,KAAU,cAAY,KAAkB,CAAC,MAAM,QAAQ,CAAK;AAC3E;AAEA,SAAS,EAAM,GAAiC;CAC/C,OAAO,OAAO,KAAU,YAAY,EAAM,UAAU,MAAM,OAAO,SAAS,KAAK,MAAM,CAAK,CAAC;AAC5F;AAEA,SAAS,GAAY,GAAiC;CACrD,OAAO,OAAO,KAAU,YAAY,OAAO,cAAc,CAAK,KAAK,KAAS;AAC7E;AAEA,SAAS,GAAa,GAAuD;CACxE,UAAU,KAAA,KACV,GAAC,EAAS,CAAK,KAAK,CAAC,EAAM,EAAM,GAAG,KAAK,OAAO,EAAM,QAAS,aAC9D,GAAc,IAAI,EAAM,IAAmC,KAE/D,IAAM,eAAe,KAAA,MACpB,OAAO,EAAM,cAAe,YAAY,CAAC,OAAO,UAAU,EAAM,UAAU,KAAK,EAAM,aAAa,OAAO,EAAM,aAAa,OAK9H,OAAO;EACN,KAAK,EAAM;EACX,MAAM,EAAM;EACZ,YAAY,EAAM;CACnB;AACD;AAEA,SAAS,GAAW,GAAiD;CAChE,UAAU,KAAA,KACV,GAAC,EAAS,CAAK,KAAK,OAAO,EAAM,WAAY,YAAY,EAAM,QAAQ,WAAW,KAAK,EAAM,QAAQ,SAAS,QAG7G,EAAM,EAAM,UAAU,GAE3B,OAAO;EAAE,SAAS,EAAM;EAAS,YAAY,EAAM;CAAW;AAC/D;AAMA,SAAgB,GAA4B,GAAoD;CAG/F,IAFI,CAAC,EAAS,CAAK,KAAK,EAAM,iBAAA,KAC1B,OAAO,EAAM,YAAa,YAAY,CAAC,EAAM,EAAM,WAAW,KAAK,CAAC,EAAM,EAAM,UAAU,KAC1F,CAAC,EAAM,EAAM,cAAc,KAAK,CAAC,GAAY,EAAM,YAAY,GAAG;CAEtE,IAAM,IAAU,EAAwB,EAAM,OAAO;CACrD,IAAI,CAAC,KAAW,EAAQ,aAAa,EAAM,UAAU;CAErD,IAAM,IAAQ,GAAW,EAAM,KAAK;CACpC,IAAI,EAAM,UAAU,KAAA,KAAa,CAAC,GAAO;CACzC,IAAM,IAAc,GAAa,EAAM,WAAW;CAC9C,QAAM,gBAAgB,KAAA,KAAa,CAAC,IAExC,OAAO;EACN,cAAA;EACA,UAAU,EAAM;EAChB,aAAa,EAAM;EACnB,YAAY,EAAM;EAClB,gBAAgB,EAAM;EACtB,cAAc,EAAM;EACpB;EACA;EACA;CACD;AACD;AAGA,SAAgB,EAAiC,GAAgB,GAAyC;CACzG,IAAI,CAAC,MAAM,QAAQ,CAAK,GAAG,OAAO,CAAC;CAEnC,IAAM,oBAAY,IAAI,IAAY,GAC5B,IAAoC,CAAC;CAC3C,KAAK,IAAM,KAAe,GAAO;EAChC,IAAM,IAAS,GAA4B,CAAW;EAClD,OAAC,KAAU,KAAK,MAAM,EAAO,UAAU,KAAK,KAAS,EAAU,IAAI,EAAO,QAAQ,OAEtF,EAAU,IAAI,EAAO,QAAQ,GAC7B,EAAQ,KAAK,CAAM,GACf,EAAQ,WAAA,KAAyC;CACtD;CAEA,OAAO;AACR;;;AChFA,IAAM,IAAoB,YACpB,KAAmB;AASzB,SAAS,EAAM,GAAe;CAC7B,OAAO,IAAI,KAAK,CAAK,CAAC,CAAC,YAAY;AACpC;AAEA,SAAS,EAAiB,GAAe;CACxC,IAAM,IAAU,EAAM,KAAK;CAC3B,IAAI,EAAQ,WAAW,KAAK,EAAQ,SAAS,KAC5C,MAAU,MAAM,gEAAgE;CAEjF,OAAO;AACR;AAEA,SAAS,GAAkB,GAA8B,GAA+B;CACvF,OACC,KAAK,MAAM,EAAK,cAAc,IAAI,KAAK,MAAM,EAAM,cAAc,KAAK,KAAK,MAAM,EAAK,WAAW,IAAI,KAAK,MAAM,EAAM,WAAW;AAEnI;AAEA,SAAS,EACR,GACA,GACA,GACgF;CAChF,IAAM,IAAQ,EAAQ,WAAW,MAAW,EAAO,aAAa,CAAQ;CAGxE,OAFI,IAAQ,IAAU;EAAE;EAAO,QAAQ;CAAU,IAC7C,EAAQ,EAAM,EAAE,OAAO,YAAY,IAChC;EAAE;EAAO,QAAQ;CAAU,IADqB;EAAE;EAAO,QAAQ;CAAiB;AAE1F;AAOA,SAAgB,GAAuB,IAAyC,CAAC,GAAiC;CACjH,IAAM,IACL,EAAQ,WACR,EAAqC;EACpC,QAAQ,EAAQ,UAAU,GAAG,WAAW;EACxC,WAAW;EACX,WAAW,EAAQ;CACpB,CAAC;CACF,IAAI,CAAC,GAAS;CACd,IAAM,IAAe;CAErB,SAAS,EACR,GACA,GACC;EACD,OAAO,EAAa,WAAW,IAAoB,MAAgB;GAClE,IAAM,IAAW,EAAU,EAAiC,GAAa,CAAK,CAAC;GAC/E,OAAO;IAAE,QAAQ;IAAgB,OAAO,EAAS;IAAS,QAAQ,EAAS;GAAO;EACnF,CAAC;CACF;CAEA,OAAO;EACN,SAAS,OAAO,GAA6B,oBAAM,IAAI,KAAK,MAAM;GACjE,IAAM,IAAgB,EAAwB,CAAO;GACrD,IAAI,CAAC,GAAe,OAAO,EAAE,QAAQ,kBAA2B;GAEhE,IAAM,IAAQ,EAAI,QAAQ;GAG1B,OAFK,OAAO,SAAS,CAAK,IAEnB,EAAsC,IAAQ,MAAY;IAChE,IAAI,EAAQ,MAAM,MAAW,EAAO,aAAa,EAAc,QAAQ,GACtE,OAAO;KAAE;KAAS,QAAQ,EAAE,QAAQ,YAAqB;IAAE;IAG5D,IAAI;IACJ,IAAI,EAAQ,UAAA,IAAwC;KACnD,IAAM,IAAe,EACnB,KAAK,GAAQ,OAAW;MAAE;MAAQ;KAAM,EAAE,CAAC,CAC3C,QAAQ,EAAE,gBAAa,EAAO,UAAU,KAAA,CAAS,CAAC,CAClD,MAAM,GAAM,MAAU,KAAK,MAAM,EAAK,OAAO,WAAW,IAAI,KAAK,MAAM,EAAM,OAAO,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE;KAExG,IAAI,MAAiB,KAAA,GACpB,OAAO;MAAE;MAAS,QAAQ,EAAE,QAAQ,oBAA6B;KAAE;KAIpE,AADA,IAAkB,EAAQ,EAAa,EAAE,UACzC,EAAQ,OAAO,GAAc,CAAC;IAC/B;IAEA,IAAM,IAAS,EAAM,CAAK;IAW1B,OAVA,EAAQ,KAAK;KACZ,cAAA;KACA,UAAU,EAAc;KACxB,aAAa;KACb,YAAY,EAAM,IAAQ,EAAyB;KACnD,gBAAgB;KAChB,cAAc;KACd,SAAS;IACV,CAAC,GAEM;KACN;KACA,QAAQ,IAAkB;MAAE,QAAQ;MAAqB;KAAgB,IAAI,EAAE,QAAQ,WAAoB;IAC5G;GACD,CAAC,IArCmC,EAAE,QAAQ,kBAA2B;EAsC1E;EACA,WAAW,OAAO,EAAE,SAAS,GAAc,yBAAM,IAAI,KAAK,GAAG,qBAAkB,SAAkC;GAChH,IAAM,IAAU,EAAiB,CAAY,GACvC,IAAQ,EAAI,QAAQ;GAC1B,IAAI,CAAC,OAAO,SAAS,CAAK,KAAK,CAAC,OAAO,SAAS,CAAe,KAAK,KAAmB,GACtF,MAAU,MAAM,wEAAwE;GAGzF,OAAO,EAAO,IAAQ,MAAY;IACjC,IAAM,IAAS,EACb,QACC,MACA,KAAK,MAAM,EAAU,cAAc,KAAK,MACvC,EAAU,UAAU,KAAA,KAAa,KAAK,MAAM,EAAU,MAAM,UAAU,KAAK,EAC9E,CAAC,CACA,KAAK,EAAiB,CAAC,CAAC;IAC1B,IAAI,CAAC,GAAQ,OAAO;KAAE;KAAS,QAAQ,KAAA;IAAU;IAEjD,IAAM,IAAuC;KAC5C,GAAG;KACH,cAAc,EAAO,eAAe;KACpC,OAAO;MAAE;MAAS,YAAY,EAAM,IAAQ,CAAe;KAAE;IAC9D;IACA,OAAO;KACN,SAAS,EAAQ,KAAK,MAAe,EAAU,aAAa,EAAO,WAAW,IAAe,CAAU;KACvG,QAAQ;IACT;GACD,CAAC;EACF;EACA,aAAa,OAAO,GAAU,MAAiB;GAC9C,IAAM,IAAU,EAAiB,CAAY;GAC7C,OAAO,EAAO,KAAK,IAAI,IAAI,MAAY;IACtC,IAAM,IAAa,EAAkB,GAAS,GAAU,CAAO;IAG/D,OAFI,EAAW,WAAW,aAC1B,EAAQ,OAAO,EAAW,OAAO,CAAC,GAC3B;KAAE;KAAS,QAAQ;IAAmB,KAFD;KAAE;KAAS,QAAQ,EAAW;IAAO;GAGlF,CAAC;EACF;EACA,YAAY,OAAO,GAAU,GAAc,MAAU;GACpD,IAAM,IAAU,EAAiB,CAAY,GACvC,IAAgB,KAAK,MAAM,EAAM,cAAc,GAC/C,IAAe,KAAK,MAAM,EAAM,QAAQ,GAAG;GACjD,IAAI,CAAC,OAAO,SAAS,CAAa,KAAK,CAAC,OAAO,SAAS,CAAY,GACnE,MAAU,MAAM,oDAAoD;GAGrE,OAAO,EAAO,IAAe,MAAY;IACxC,IAAM,IAAa,EAAkB,GAAS,GAAU,CAAO;IAC/D,IAAI,EAAW,WAAW,WAAW,OAAO;KAAE;KAAS,QAAQ,EAAW;IAAO;IACjF,IAAM,IAAS,EAAQ,EAAW;IAQlC,OAPK,KACL,EAAQ,EAAW,SAAS;KAC3B,GAAG;KACH,gBAAgB,EAAM;KACtB,OAAO,KAAA;KACP,aAAa,EAAM;IACpB,GACO;KAAE;KAAS,QAAQ;IAAmB,KAPzB;KAAE;KAAS,QAAQ;IAAmB;GAQ3D,CAAC;EACF;EACA,SAAS,OAAO,GAAU,MAAiB;GAC1C,IAAM,IAAU,EAAiB,CAAY;GAC7C,OAAO,EAAO,KAAK,IAAI,IAAI,MAAY;IACtC,IAAM,IAAa,EAAkB,GAAS,GAAU,CAAO;IAG/D,OAFI,EAAW,WAAW,aAC1B,EAAQ,OAAO,EAAW,OAAO,CAAC,GAC3B;KAAE;KAAS,QAAQ;IAAmB,KAFD;KAAE;KAAS,QAAQ,EAAW;IAAO;GAGlF,CAAC;EACF;EACA,YAAY,OAAO,oBAAM,IAAI,KAAK,MAAM;GACvC,IAAM,IAAQ,EAAI,QAAQ;GAG1B,OAFK,OAAO,SAAS,CAAK,IAEnB,EAAiC,MADd,EAAa,QAAQ,CAAiB,GACX,CAAK,CAAC,CAAC,KAAK,EAAiB,IAF9C,CAAC;EAGtC;EACA,gBAAgB,OAAO,oBAAM,IAAI,KAAK,MAAM;GAC3C,IAAM,IAAQ,EAAI,QAAQ;GAC1B,IAAI,CAAC,OAAO,SAAS,CAAK,GAAG;GAE7B,IAAM,IADU,EAAiC,MAAM,EAAa,QAAQ,CAAiB,GAAG,CAC7E,CAAA,CAAQ,QAA4B,GAAS,MAAW;IAC1E,IAAM,IAAe,KAAK,IAAI,KAAK,MAAM,EAAO,cAAc,GAAG,EAAO,QAAQ,KAAK,MAAM,EAAO,MAAM,UAAU,IAAI,CAAC;IACvH,OAAO,MAAY,KAAA,KAAa,IAAe,IAAU,IAAe;GACzE,GAAG,KAAA,CAAS;GACZ,OAAO,MAAe,KAAA,IAAY,KAAA,IAAY,EAAM,CAAU;EAC/D;CACD;AACD;;;AC7MA,IAAI;AAMJ,SAAgB,GAAmC,GAAuD;CAEzG,AADA,IAAuB,GACvB,GAAqC;AACtC;AAmBA,eAAsB,GAAmB,GAAgB,IAAqC,CAAC,GAAG;CAC5F,OAEL,IAAI;EACH,MAAM,EAAqB,GAAO,CAAO;CAC1C,QAAQ,CAER;AACD"}
@@ -0,0 +1,13 @@
1
+ import type { ErrorReportPayload } from "./types";
2
+ export declare const ERROR_REPORT_PAYLOAD_VERSION: 1;
3
+ export declare const ERROR_REPORT_PAYLOAD_MAX_BYTES: number;
4
+ export declare const ERROR_REPORT_STACK_TRACE_MAX_BYTES: number;
5
+ /** Возвращает точный UTF-8 размер JSON-формы, которую получит transport. */
6
+ export declare function getErrorReportPayloadSize(payload: ErrorReportPayload): number;
7
+ /**
8
+ * Удаляет диагностические секции в фиксированном порядке, пока payload не
9
+ * помещается в transport/storage limit. Identity, классификация и ошибка
10
+ * сохраняются всегда; маркер перечисляет каждую фактически удалённую секцию.
11
+ */
12
+ export declare function limitErrorReportPayload(input: ErrorReportPayload): ErrorReportPayload;
13
+ //# sourceMappingURL=payload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../src/error-report/payload.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAGX,kBAAkB,EAGlB,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,4BAA4B,EAAG,CAAU,CAAC;AACvD,eAAO,MAAM,8BAA8B,QAAc,CAAC;AAC1D,eAAO,MAAM,kCAAkC,QAAa,CAAC;AA+E7D,4EAA4E;AAC5E,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,kBAAkB,UAEpE;AAoED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,kBAAkB,GAAG,kBAAkB,CAyGrF"}
@@ -0,0 +1,15 @@
1
+ import { type IndexedDbQueryStorage } from "../query-client";
2
+ import { type ErrorReportQueue } from "./queueContract";
3
+ export type CreateErrorReportQueueOptions = {
4
+ readonly dbName?: string;
5
+ readonly indexedDB?: IDBFactory;
6
+ /** Тестовая/альтернативная storage boundary; browser-приложения обычно её не задают. */
7
+ readonly storage?: Pick<IndexedDbQueryStorage<unknown>, "getItem" | "updateItem">;
8
+ };
9
+ /**
10
+ * Создаёт IndexedDB-backed очередь. Одна запись-envelope намеренно хранит не
11
+ * более 50 payload: существующий atomic update primitive тогда сериализует
12
+ * выбор lease между вкладками без дополнительного локального storage слоя.
13
+ */
14
+ export declare function createErrorReportQueue(options?: CreateErrorReportQueueOptions): ErrorReportQueue | undefined;
15
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/error-report/queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAE1F,OAAO,EAKN,KAAK,gBAAgB,EAIrB,MAAM,iBAAiB,CAAC;AAQzB,MAAM,MAAM,6BAA6B,GAAG;IAC3C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC;IAChC,wFAAwF;IACxF,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC,CAAC;CAClF,CAAC;AA+BF;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,6BAAkC,GAAG,gBAAgB,GAAG,SAAS,CAuJhH"}
@@ -0,0 +1,62 @@
1
+ import { type ErrorReportPayload } from "./types";
2
+ export declare const ERROR_REPORT_QUEUE_VERSION: 1;
3
+ export declare const ERROR_REPORT_QUEUE_MAX_ITEMS = 50;
4
+ export declare const ERROR_REPORT_QUEUE_TTL_MS: number;
5
+ export declare const ERROR_REPORT_QUEUE_LEASE_MS: number;
6
+ export type ErrorReportQueueFailureKind = "http" | "network" | "timeout" | "unknown";
7
+ export type ErrorReportQueueRecord = {
8
+ readonly queueVersion: typeof ERROR_REPORT_QUEUE_VERSION;
9
+ readonly reportId: string;
10
+ readonly enqueuedUtc: string;
11
+ readonly expiresUtc: string;
12
+ readonly nextAttemptUtc: string;
13
+ readonly attemptCount: number;
14
+ readonly payload: ErrorReportPayload;
15
+ readonly lease?: {
16
+ readonly ownerId: string;
17
+ readonly expiresUtc: string;
18
+ };
19
+ readonly lastFailure?: {
20
+ readonly utc: string;
21
+ readonly kind: ErrorReportQueueFailureKind;
22
+ readonly httpStatus?: number;
23
+ };
24
+ };
25
+ export type ErrorReportQueueEnqueueResult = {
26
+ readonly status: "enqueued";
27
+ readonly evictedReportId?: string;
28
+ } | {
29
+ readonly status: "duplicate";
30
+ } | {
31
+ readonly status: "invalid-payload";
32
+ } | {
33
+ readonly status: "capacity-exceeded";
34
+ };
35
+ export type ErrorReportQueueLeaseOptions = {
36
+ readonly ownerId: string;
37
+ readonly now?: Date;
38
+ readonly leaseDurationMs?: number;
39
+ };
40
+ export type ErrorReportQueueTransitionResult = "updated" | "missing" | "lease-mismatch";
41
+ export type ErrorReportQueueRetry = {
42
+ readonly nextAttemptUtc: string;
43
+ readonly failure: {
44
+ readonly utc: string;
45
+ readonly kind: ErrorReportQueueFailureKind;
46
+ readonly httpStatus?: number;
47
+ };
48
+ };
49
+ /**
50
+ * Durable queue contract отделяет delivery policy от конкретной IndexedDB
51
+ * реализации. Все переходы, зависящие от lease owner, выполняются атомарно.
52
+ */
53
+ export type ErrorReportQueue = {
54
+ readonly enqueue: (payload: ErrorReportPayload, now?: Date) => Promise<ErrorReportQueueEnqueueResult>;
55
+ readonly leaseNext: (options: ErrorReportQueueLeaseOptions) => Promise<ErrorReportQueueRecord | undefined>;
56
+ readonly acknowledge: (reportId: string, ownerId: string) => Promise<ErrorReportQueueTransitionResult>;
57
+ readonly reschedule: (reportId: string, ownerId: string, retry: ErrorReportQueueRetry) => Promise<ErrorReportQueueTransitionResult>;
58
+ readonly discard: (reportId: string, ownerId: string) => Promise<ErrorReportQueueTransitionResult>;
59
+ readonly getRecords: (now?: Date) => Promise<readonly ErrorReportQueueRecord[]>;
60
+ readonly getNextWakeUtc: (now?: Date) => Promise<string | undefined>;
61
+ };
62
+ //# sourceMappingURL=queueContract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queueContract.d.ts","sourceRoot":"","sources":["../../src/error-report/queueContract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { type ErrorReportQueueRecord } from "./queueContract";
2
+ /**
3
+ * Queue parser не угадывает прежние storage-формы. Повреждённая или будущая
4
+ * запись отбрасывается отдельно, не уничтожая соседние валидные отчёты.
5
+ */
6
+ export declare function parseErrorReportQueueRecord(value: unknown): ErrorReportQueueRecord | undefined;
7
+ /** Возвращает bounded текущую очередь без истёкших и повторяющихся ID. */
8
+ export declare function normalizeErrorReportQueueRecords(value: unknown, nowMs: number): ErrorReportQueueRecord[];
9
+ //# sourceMappingURL=queueRecord.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queueRecord.d.ts","sourceRoot":"","sources":["../../src/error-report/queueRecord.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,sBAAsB,EAC3B,MAAM,iBAAiB,CAAC;AA6CzB;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,GAAG,SAAS,CAwB9F;AAED,0EAA0E;AAC1E,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,sBAAsB,EAAE,CAexG"}
@@ -1,4 +1,18 @@
1
- import type { ErrorReportSafeValue } from "./types";
1
+ import type { ErrorReportSafeValue, ErrorReportSanitizationContext, ErrorReportSanitizer } from "./types";
2
+ /**
3
+ * Удаляет наиболее узнаваемые секреты и email из свободного диагностического
4
+ * текста. Это страховочная сетка; предметные персональные данные приложение
5
+ * обязано исключить своим allow-list sanitizer.
6
+ */
7
+ export declare function sanitizeDiagnosticText(value: string, maxLength?: number): string;
8
+ /** Возвращает размер строки в UTF-8, совпадающий с размером JSON transport. */
9
+ export declare function getUtf8TextSize(value: string): number;
10
+ /**
11
+ * Обрезает уже очищенный текст по UTF-8 bytes без разрыва surrogate pair.
12
+ * Binary search нужен для Unicode stack traces, где число code units не равно
13
+ * размеру transport payload.
14
+ */
15
+ export declare function sanitizeDiagnosticTextBytes(value: string, maxBytes: number): string;
2
16
  /**
3
17
  * Превращает произвольное значение в JSON-совместимую диагностическую форму.
4
18
  * Значения сохраняются читаемыми, потому что queryKey/meta/context нужны
@@ -10,5 +24,15 @@ export declare function createDiagnosticValue(value: unknown, depth?: number): E
10
24
  * Описывает форму данных кеша без самих значений: типы, размеры массивов и ключи объектов.
11
25
  */
12
26
  export declare function createDataShape(value: unknown, depth?: number): ErrorReportSafeValue;
13
- export declare function sanitizeDetail(detail: Record<string, unknown> | undefined): Record<string, ErrorReportSafeValue> | undefined;
27
+ /**
28
+ * Подключает предметный sanitizer приложения. `undefined` отключает callback и
29
+ * одновременно предотвращает утечку старой policy при hot reload и в тестах.
30
+ */
31
+ export declare function setErrorReportSanitizer(sanitizer: ErrorReportSanitizer | undefined): void;
32
+ /**
33
+ * Выполняет built-in нормализацию, затем предметную policy приложения и ещё
34
+ * одну bounded-нормализацию результата перед включением секции в payload.
35
+ */
36
+ export declare function sanitizeErrorReportValue(value: unknown, context: ErrorReportSanitizationContext, maxStringLength?: number): ErrorReportSafeValue | undefined;
37
+ export declare function sanitizeDetail(detail: Record<string, unknown> | undefined, context?: ErrorReportSanitizationContext): Record<string, ErrorReportSafeValue> | undefined;
14
38
  //# sourceMappingURL=safeValue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"safeValue.d.ts","sourceRoot":"","sources":["../../src/error-report/safeValue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAMpD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,SAAI,GAAG,oBAAoB,CAoBrF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,SAAI,GAAG,oBAAoB,CAsB/E;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAAG,SAAS,CAQ5H"}
1
+ {"version":3,"file":"safeValue.d.ts","sourceRoot":"","sources":["../../src/error-report/safeValue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,8BAA8B,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAkD1G;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAA+B,UAU7F;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,UAE5C;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,UAe1E;AA6CD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,SAAI,GAAG,oBAAoB,CAKrF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,SAAI,GAAG,oBAAoB,CAsB/E;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,oBAAoB,GAAG,SAAS,QAElF;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACvC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,8BAA8B,EACvC,eAAe,SAA+B,oCAe9C;AAED,wBAAgB,cAAc,CAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC3C,OAAO,GAAE,8BAAqD,GAC5D,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAAG,SAAS,CAOlD"}
@@ -0,0 +1,14 @@
1
+ import type { ErrorReportDraft, ErrorReportPayload } from "./types";
2
+ /**
3
+ * Парсит только текущую versioned форму. Unversioned и будущие payload
4
+ * отклоняются явно, чтобы storage/delivery не угадывали форму контракта.
5
+ */
6
+ export declare function parseErrorReportPayload(value: unknown): ErrorReportPayload | undefined;
7
+ /** Проверяет одну draft-запись, включая совпадение её identity с payload. */
8
+ export declare function parseErrorReportDraft(value: unknown): ErrorReportDraft | undefined;
9
+ /**
10
+ * Восстанавливает все валидные drafts независимо: одна повреждённая запись не
11
+ * должна уничтожить остальные элементы browser storage.
12
+ */
13
+ export declare function parseErrorReportDrafts(value: unknown): ErrorReportDraft[];
14
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/error-report/schema.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAwB,MAAM,SAAS,CAAC;AAyL1F;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,kCASrD;AAED,6EAA6E;AAC7E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,gCASnD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,sBAMpD"}
@@ -1,9 +1,7 @@
1
1
  export type ErrorReportTransportHtmlSummary = {
2
2
  length: number;
3
- title?: string;
4
3
  formCount?: number;
5
4
  inputNames?: string[];
6
- textPreview?: string;
7
5
  };
8
6
  export type ErrorReportTransportErrorContext = {
9
7
  source: "fetch.parseResponse" | "fetch.buildHttpError";
@@ -1 +1 @@
1
- {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/error-report/transport.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,+BAA+B,GAAG;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG;IAC9C,MAAM,EAAE,qBAAqB,GAAG,sBAAsB,CAAC;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,+BAA+B,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,gCAAgC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAgClI;;;;GAIG;AACH,wBAAgB,oCAAoC,CAAC,QAAQ,EAAE,iCAAiC,GAAG,SAAS,QAG3G;AAED,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,WAE7D;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,QAI1D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,gCAAgC,QAiB3F"}
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/error-report/transport.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,+BAA+B,GAAG;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG;IAC9C,MAAM,EAAE,qBAAqB,GAAG,sBAAsB,CAAC;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,+BAA+B,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,gCAAgC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAgClI;;;;GAIG;AACH,wBAAgB,oCAAoC,CAAC,QAAQ,EAAE,iCAAiC,GAAG,SAAS,QAG3G;AAED,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,WAE7D;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,QAI1D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,gCAAgC,QAiB3F"}