@ryuzaki13/react-foundation-lib 1.1.16 → 1.1.18
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.
- package/README.md +7 -5
- package/dist/chunks/{formatters-DCx4jhka.js → formatters-DeZh3JUD.js} +305 -305
- package/dist/chunks/{formatters-DCx4jhka.js.map → formatters-DeZh3JUD.js.map} +1 -1
- package/dist/chunks/{validate-B_ITGoAs.js → validate-DmeCsK9c.js} +11 -11
- package/dist/chunks/validate-DmeCsK9c.js.map +1 -0
- package/dist/error-report/errorInfo.d.ts.map +1 -1
- package/dist/error-report/index.js +133 -129
- package/dist/error-report/index.js.map +1 -1
- package/dist/excel/index.js +4 -4
- package/dist/formatters/index.js +3 -3
- package/dist/formatters/rowBased/registry.d.ts +9 -3
- package/dist/formatters/rowBased/registry.d.ts.map +1 -1
- package/dist/formulas/index.js +190 -2
- package/dist/formulas/index.js.map +1 -0
- package/dist/formulas/registry.d.ts +9 -3
- package/dist/formulas/registry.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/chunks/formulas-BxcH5Zjt.js +0 -279
- package/dist/chunks/formulas-BxcH5Zjt.js.map +0 -1
- package/dist/chunks/validate-B_ITGoAs.js.map +0 -1
- package/dist/formatters/rowBased/definitions/index.d.ts +0 -6
- package/dist/formatters/rowBased/definitions/index.d.ts.map +0 -1
- package/dist/formulas/definitions/base.d.ts +0 -7
- package/dist/formulas/definitions/base.d.ts.map +0 -1
- package/dist/formulas/definitions/index.d.ts +0 -3
- package/dist/formulas/definitions/index.d.ts.map +0 -1
- package/dist/formulas/definitions/sales.d.ts +0 -7
- package/dist/formulas/definitions/sales.d.ts.map +0 -1
|
@@ -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/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\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: 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: 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: typeof error === \"string\" ? error : String(error ?? \"Неизвестная ошибка\")\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","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 { 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 async function captureRuntimeErrorReport(error: unknown, context: ErrorReportRuntimeContext = {}, queryClient?: QueryClient) {\n\tconst source = context.source ?? context.category ?? \"runtime\";\n\n\taddErrorReportBreadcrumb({\n\t\ttype: \"runtime-error\",\n\t\tdetail: sanitizeDetail({ category: context.category ?? \"runtime\", source, ...context.detail })\n\t});\n\n\tconst [persistedQueries, queryClientDiagnostics] = queryClient\n\t\t? await Promise.all([collectPersistedQueryDiagnostics(), Promise.resolve(collectQueryClientDiagnostics(queryClient))])\n\t\t: [undefined, undefined];\n\n\treturn captureErrorReportDraft({\n\t\tcategory: context.category ?? \"runtime\",\n\t\tsource,\n\t\terror: context.errorInfo ?? createErrorInfo(error),\n\t\treact: context.componentStack ? { componentStack: context.componentStack } : undefined,\n\t\tqueryClient: queryClientDiagnostics,\n\t\tpersistedQueries,\n\t\tcontext: sanitizeDetail(context.detail)\n\t});\n}\n","import 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}\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/errorInfo.ts","../../src/error-report/diagnostics.ts","../../src/error-report/environment.ts","../../src/error-report/drafts.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","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 { 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 async function captureRuntimeErrorReport(error: unknown, context: ErrorReportRuntimeContext = {}, queryClient?: QueryClient) {\n\tconst source = context.source ?? context.category ?? \"runtime\";\n\n\taddErrorReportBreadcrumb({\n\t\ttype: \"runtime-error\",\n\t\tdetail: sanitizeDetail({ category: context.category ?? \"runtime\", source, ...context.detail })\n\t});\n\n\tconst [persistedQueries, queryClientDiagnostics] = queryClient\n\t\t? await Promise.all([collectPersistedQueryDiagnostics(), Promise.resolve(collectQueryClientDiagnostics(queryClient))])\n\t\t: [undefined, undefined];\n\n\treturn captureErrorReportDraft({\n\t\tcategory: context.category ?? \"runtime\",\n\t\tsource,\n\t\terror: context.errorInfo ?? createErrorInfo(error),\n\t\treact: context.componentStack ? { componentStack: context.componentStack } : undefined,\n\t\tqueryClient: queryClientDiagnostics,\n\t\tpersistedQueries,\n\t\tcontext: sanitizeDetail(context.detail)\n\t});\n}\n","import 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}\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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"}
|
package/dist/excel/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { c as e, l as t, s as n, u as r } from "../chunks/odata-service-DNYr2dDx.js";
|
|
2
2
|
import { E as i, M as a, N as o } from "../chunks/dateUtils-D9dpdTl7.js";
|
|
3
|
-
import {
|
|
3
|
+
import { d as s, t as c } from "../chunks/validate-DmeCsK9c.js";
|
|
4
4
|
import l from "write-excel-file/browser";
|
|
5
5
|
//#region src/excel/excel.ts
|
|
6
6
|
var u = {
|
|
@@ -109,7 +109,7 @@ async function w(e) {
|
|
|
109
109
|
//#region src/excel/tableExport.ts
|
|
110
110
|
var T = "#,##0", E = "#,##0.0", D = "dd.mm.yyyy", O = "d mmm", k = "d mmmm", A = "hh:mm", j = "hh:mm:ss", M = `${D} ${A}`, N = `${D} ${j}`;
|
|
111
111
|
function P(e) {
|
|
112
|
-
let t =
|
|
112
|
+
let t = c(e).plan?.steps.find((e) => e.type === "typedValueFormat");
|
|
113
113
|
return t?.type === "typedValueFormat" ? t.config : void 0;
|
|
114
114
|
}
|
|
115
115
|
function F(t) {
|
|
@@ -117,10 +117,10 @@ function F(t) {
|
|
|
117
117
|
}
|
|
118
118
|
function I(e) {
|
|
119
119
|
let n = P(e.formattersPipeline)?.numberPresetName?.trim();
|
|
120
|
-
return n &&
|
|
120
|
+
return n && s(n) ? n : t(e.odataType) ? "integer" : "decimal";
|
|
121
121
|
}
|
|
122
122
|
function L(e) {
|
|
123
|
-
let t =
|
|
123
|
+
let t = s(I(e));
|
|
124
124
|
return t ? t.decimals > 0 ? `#,##0.${"0".repeat(t.decimals)}` : T : E;
|
|
125
125
|
}
|
|
126
126
|
function R(e) {
|
package/dist/formatters/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { _ as e, b as t, g as n, v as r, x as i, y as a } from "../chunks/array-BBSjoTRy.js";
|
|
2
|
-
import { $ as o, A as s, At as c, B as l, Bt as u, C as d, Ct as f, D as p, Dt as m, E as h, Et as g, F as _, Ft as v, G as y, Gt as b, H as x, Ht as S, I as C, It as w, J as T, Jt as E, K as D, Kt as O, L as k, Lt as A, M as j, Mt as M, N, Nt as P, O as F, Ot as I, P as L, Pt as R, Q as z, R as B, Rt as V, S as H, St as U, T as W, Tt as G, U as K, Ut as q, V as J, Vt as Y, W as X, Wt as Z, X as Q, Xt as $, Y as ee, Yt as te, Z as ne, _ as re, _t as ie, a as ae, at as oe, b as se, bt as ce, c as le, ct as ue, d as de, dt as fe, et as pe, f as me, ft as he, g as ge, gt as _e, h as ve, ht as ye, i as be, it as xe, j as Se, jt as Ce, k as we, kt as Te, l as Ee, lt as De, m as Oe, mt as ke, n as Ae, nt as je, o as Me, ot as Ne, p as Pe, pt as Fe, q as Ie, qt as Le, r as Re, rt as ze, s as Be, st as Ve, t as He, tt as Ue, u as We, ut as Ge, v as Ke, vt as qe, w as Je, wt as Ye, x as Xe, xt as Ze, y as Qe, yt as $e, z as et, zt as tt } from "../chunks/formatters-
|
|
2
|
+
import { $ as o, A as s, At as c, B as l, Bt as u, C as d, Ct as f, D as p, Dt as m, E as h, Et as g, F as _, Ft as v, G as y, Gt as b, H as x, Ht as S, I as C, It as w, J as T, Jt as E, K as D, Kt as O, L as k, Lt as A, M as j, Mt as M, N, Nt as P, O as F, Ot as I, P as L, Pt as R, Q as z, R as B, Rt as V, S as H, St as U, T as W, Tt as G, U as K, Ut as q, V as J, Vt as Y, W as X, Wt as Z, X as Q, Xt as $, Y as ee, Yt as te, Z as ne, _ as re, _t as ie, a as ae, at as oe, b as se, bt as ce, c as le, ct as ue, d as de, dt as fe, et as pe, f as me, ft as he, g as ge, gt as _e, h as ve, ht as ye, i as be, it as xe, j as Se, jt as Ce, k as we, kt as Te, l as Ee, lt as De, m as Oe, mt as ke, n as Ae, nt as je, o as Me, ot as Ne, p as Pe, pt as Fe, q as Ie, qt as Le, r as Re, rt as ze, s as Be, st as Ve, t as He, tt as Ue, u as We, ut as Ge, v as Ke, vt as qe, w as Je, wt as Ye, x as Xe, xt as Ze, y as Qe, yt as $e, z as et, zt as tt } from "../chunks/formatters-DeZh3JUD.js";
|
|
3
3
|
import { Ft as nt, It as rt, Mt as it, Nt as at, Pt as ot, jt as st } from "../chunks/odata-service-DNYr2dDx.js";
|
|
4
4
|
import { A as ct, B as lt, C as ut, D as dt, E as ft, F as pt, H as mt, I as ht, L as gt, M as _t, N as vt, O as yt, P as bt, R as xt, S as St, T as Ct, U as wt, V as Tt, W as Et, _ as Dt, a as Ot, b as kt, c as At, d as jt, f as Mt, g as Nt, h as Pt, i as Ft, j as It, k as Lt, l as Rt, m as zt, n as Bt, o as Vt, p as Ht, r as Ut, s as Wt, u as Gt, v as Kt, w as qt, x as Jt, y as Yt, z as Xt } from "../chunks/dateUtils-D9dpdTl7.js";
|
|
5
|
-
import { a as Zt, c as Qt, d as $t, f as en, i as tn, l as nn,
|
|
6
|
-
export { ct as DATE_FORMAT_DEFAULTS, It as DATE_FORMAT_STYLE_PRESET_NAMES, Tt as DATE_PATTERN_DATE_TOKENS, mt as DATE_PATTERN_TIME_TOKENS, wt as DATE_PATTERN_TOKENS, Et as DATE_PATTERN_TOKEN_RE, _t as DEFAULT_DATE_PRESET_NAMES,
|
|
5
|
+
import { a as Zt, c as Qt, d as $t, f as en, i as tn, l as nn, m as rn, n as an, o as on, p as sn, r as cn, s as ln, t as un, u as dn } from "../chunks/validate-DmeCsK9c.js";
|
|
6
|
+
export { ct as DATE_FORMAT_DEFAULTS, It as DATE_FORMAT_STYLE_PRESET_NAMES, Tt as DATE_PATTERN_DATE_TOKENS, mt as DATE_PATTERN_TIME_TOKENS, wt as DATE_PATTERN_TOKENS, Et as DATE_PATTERN_TOKEN_RE, _t as DEFAULT_DATE_PRESET_NAMES, nn as DEFAULT_NUMBER_PRESET_NAMES, Ae as DEFAULT_VALUE_STATES, dn as NUMBER_FORMAT_DEFAULTS, Re as VALUE_STATE_COLOR_TOKENS, M as addCalendarDays, P as addCalendarMonths, R as addCalendarYears, _ as clearFormatCache, S as clearPhone, Ze as cloneDate, h as cloneFormatterPipelinePlanStep, p as cloneFormatterPipelinePlanStepToNode, F as cloneFormattersPipelineConfig, we as cloneNormalizeLeadingZerosConfig, s as cloneResolveValueStateConfig, Se as cloneRowBasedOverrideConfig, j as cloneTypedValueFormatConfig, Je as collectFormattersPipelineDependencyIds, W as collectRuntimeFieldDependencyIds, de as compileFormattersPipelineExecutor, be as compileFormattersPipelineRuntime, ae as compileFormattersPipelineRuntimeFields, re as computeShortHash, tn as configureRowBasedFormatterRegistry, U as countCalendarDaysInDateRange, v as createCalendarDate, Ve as createEducationDateTime, ve as createFixedResolver, Qt as createRowBasedFormatterContext, Zt as createRowBasedFormatterRegistry, Pe as createThresholdResolver, Ke as findResolverByCanonicalKey, Bt as formatDate, Ut as formatDateAsAbapDate, Ft as formatDateAsAbapDatetime, Ot as formatDateAsAbapMonth, Vt as formatDateAsAbapYear, Wt as formatDateAsDate, At as formatDateAsDateLong, Rt as formatDateAsDateMedium, Gt as formatDateAsDateShort, jt as formatDateAsDateTime, Mt as formatDateAsDatetimeLong, Ht as formatDateAsDatetimeMedium, zt as formatDateAsDatetimeShort, Pt as formatDateAsMonthLong, Nt as formatDateAsMonthShort, Dt as formatDateAsODataDate, Kt as formatDateAsODataDatetime, Yt as formatDateAsODataTime, kt as formatDateAsTime, Jt as formatDateAsTimeLong, St as formatDateAsTimeMedium, ut as formatDateAsTimeSeconds, qt as formatDateAsTimeShort, Ct as formatDateRange, ue as formatEducationDateKey, De as formatEducationTimeKey, Z as formatFullName, C as formatNumber, k as formatNumberAsCurrency, B as formatNumberAsCurrencyOrEmpty, et as formatNumberAsDecimal, l as formatNumberAsDecimal2, J as formatNumberAsDecimal2OrEmpty, x as formatNumberAsDecimal3, K as formatNumberAsDecimal3OrEmpty, X as formatNumberAsDecimalOrEmpty, y as formatNumberAsInteger, D as formatNumberAsIntegerOrEmpty, Ie as formatNumberAsPercent, T as formatNumberAsPercentOrEmpty, ee as formatNumberAsPrice, Q as formatNumberAsPriceOrEmpty, ne as formatNumberAsTonnage, z as formatNumberAsTonnageOrEmpty, q as formatPhone, Me as formatPipelineDisplayValue, b as formatShortName, me as formatTypedCellValue, Te as getCalendarPeriod, Ge as getCurrentEducationWeekKey, vt as getDatePreset, bt as getDatePresetNames, fe as getEducationWeekDays, he as getEducationWeekRange, Fe as getEducationWeekStartDate, ke as getEducationYear, ye as getEducationYearRange, w as getEndOfDay, le as getFormattersPipelineDefinitionById, Ee as getFormattersPipelineDefinitions, $t as getNumberPreset, en as getNumberPresetNames, on as getRowBasedFormatterById, ln as getRowBasedFormatterList, A as getStartOfDay, V as getStartOfMonth, tt as getStartOfWeek, u as getStartOfYear, Qe as getValueStateResolver, se as getValueStateResolverIds, c as isCalendarPeriodWithinDateBounds, _e as isCurrentEducationWeek, pt as isDateFormatPrecision, ht as isDateFormatStyle, Ce as isDateInsideCalendarPeriod, f as isDateRangeTuple, ie as isEducationDateInCurrentYear, st as isPositiveValue, Y as isSameCalendarDay, Ye as isValidDate, pe as isZeroValue, G as normalizeDateRange, Ue as normalizeDateRangeReferenceDate, qe as normalizeEducationWeekKey, We as normalizeFormattersPipelineConfig, N as normalizeLeadingZeros, L as normalizeLeadingZerosStrict, n as normalizeRequiredText, e as normalizeText, r as normalizeTextSpaces, a as normalizeTextToLower, t as normalizeTextWithFallback, g as orderDates, nt as parseAbapBoolean, rt as parseBoolean, ft as parseDate, dt as parseDateByFormat, yt as parseDateByPattern, Lt as parseDateValue, $e as parseEducationDateKey, it as parseNumber, gt as registerDatePreset, ge as registerFixedResolver, sn as registerNumberPreset, Xe as registerResolver, Oe as registerThresholdResolver, Be as rekeyFormattersPipelineConfig, m as requireDateRange, xt as resetDatePresets, rn as resetNumberPresets, H as resetValueStateResolvers, Xt as resolveDateFormatName, lt as resolveDateFormatPreset, I as resolveDateRangePair, ce as resolveEducationWeekKey, je as resolveMonthAgoRange, ze as resolveMonthStartToTodayRange, xe as resolveMonthStartToYesterdayRange, oe as resolveTodayRange, d as resolveValueState, He as resolveValueStateClassName, Ne as resolveYesterdayRange, $ as startsWithIgnoringZeros, te as stripInnerSpaces, E as stripLeadingZeros, O as toAbapBoolean, at as toFiniteNumber, ot as toPositiveInteger, i as toSafeString, o as truncateNumber, Le as truncateText, un as validateFormattersPipelineConfig, an as validateFormattersPipelineGraph, cn as validateFormattersPipelinePlan };
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import type { RowBasedFormatterDefinition } from "./types";
|
|
2
|
-
type RowBasedFormatterRegistry = {
|
|
2
|
+
export type RowBasedFormatterRegistry = Readonly<{
|
|
3
3
|
list: readonly RowBasedFormatterDefinition[];
|
|
4
4
|
byId: ReadonlyMap<string, RowBasedFormatterDefinition>;
|
|
5
|
-
}
|
|
5
|
+
}>;
|
|
6
6
|
/**
|
|
7
7
|
* Создаёт реестр формул для подмены значения в групповой строке.
|
|
8
8
|
*/
|
|
9
9
|
export declare function createRowBasedFormatterRegistry(definitions: readonly RowBasedFormatterDefinition[]): RowBasedFormatterRegistry;
|
|
10
|
+
/**
|
|
11
|
+
* Устанавливает реестр row-based форматтеров host-приложения.
|
|
12
|
+
*
|
|
13
|
+
* Pipeline использует этот реестр при валидации и компиляции formula-режима,
|
|
14
|
+
* поэтому конфигурация должна завершиться до первого построения runtime.
|
|
15
|
+
*/
|
|
16
|
+
export declare function configureRowBasedFormatterRegistry(registry: RowBasedFormatterRegistry): void;
|
|
10
17
|
/**
|
|
11
18
|
* Возвращает список доступных формул для групповой подмены.
|
|
12
19
|
*/
|
|
@@ -15,5 +22,4 @@ export declare function getRowBasedFormatterList(): readonly RowBasedFormatterDe
|
|
|
15
22
|
* Возвращает формулу по id.
|
|
16
23
|
*/
|
|
17
24
|
export declare function getRowBasedFormatterById(formulaId: string | undefined): RowBasedFormatterDefinition | undefined;
|
|
18
|
-
export {};
|
|
19
25
|
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/formatters/rowBased/registry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/formatters/rowBased/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAE3D,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAAC;IAChD,IAAI,EAAE,SAAS,2BAA2B,EAAE,CAAC;IAC7C,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;CACvD,CAAC,CAAC;AAEH;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,WAAW,EAAE,SAAS,2BAA2B,EAAE,GAAG,yBAAyB,CA6B9H;AAID;;;;;GAKG;AACH,wBAAgB,kCAAkC,CAAC,QAAQ,EAAE,yBAAyB,GAAG,IAAI,CAE5F;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,SAAS,2BAA2B,EAAE,CAEjF;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,2BAA2B,GAAG,SAAS,CAI/G"}
|
package/dist/formulas/index.js
CHANGED
|
@@ -1,2 +1,190 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
//#region src/formulas/registry.ts
|
|
2
|
+
function e(e) {
|
|
3
|
+
let t = /* @__PURE__ */ new Map(), n = [];
|
|
4
|
+
for (let r of e) {
|
|
5
|
+
let e = r.id.trim();
|
|
6
|
+
if (!e) throw Error("Formula id не может быть пустым");
|
|
7
|
+
if (t.has(e)) throw Error(`Найден дублирующийся formulaId: ${e}`);
|
|
8
|
+
let i = Object.freeze({
|
|
9
|
+
...r,
|
|
10
|
+
id: e,
|
|
11
|
+
name: r.name.trim(),
|
|
12
|
+
description: r.description.trim(),
|
|
13
|
+
keywords: r.keywords ? [...r.keywords] : void 0
|
|
14
|
+
});
|
|
15
|
+
t.set(e, i), n.push(i);
|
|
16
|
+
}
|
|
17
|
+
return Object.freeze({
|
|
18
|
+
list: Object.freeze(n),
|
|
19
|
+
byId: t
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
var t = e([]);
|
|
23
|
+
function n(e) {
|
|
24
|
+
t = e;
|
|
25
|
+
}
|
|
26
|
+
function r() {
|
|
27
|
+
return t.list;
|
|
28
|
+
}
|
|
29
|
+
function i(e) {
|
|
30
|
+
let n = e?.trim();
|
|
31
|
+
if (n) return t.byId.get(n);
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/formulas/execute.ts
|
|
35
|
+
function a(e) {
|
|
36
|
+
let t = Number(e);
|
|
37
|
+
return Number.isFinite(t) ? t : 0;
|
|
38
|
+
}
|
|
39
|
+
function o(e) {
|
|
40
|
+
let t = [...e.keys ?? []], n = (n) => {
|
|
41
|
+
if (!Number.isInteger(n) || n < 0) {
|
|
42
|
+
e.instrumentation?.onOutOfRangeIndex?.(n);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (e.instrumentation?.onReadIndex?.(n), n >= t.length) {
|
|
46
|
+
e.instrumentation?.onOutOfRangeIndex?.(n);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
return t[n];
|
|
50
|
+
}, r = (t) => {
|
|
51
|
+
let r = n(t);
|
|
52
|
+
if (r) return e.rowData[r];
|
|
53
|
+
};
|
|
54
|
+
return {
|
|
55
|
+
key: n,
|
|
56
|
+
value: r,
|
|
57
|
+
num: (e) => a(r(e))
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function s(e) {
|
|
61
|
+
let t = i(e.formulaId);
|
|
62
|
+
if (!t) return {
|
|
63
|
+
ok: !1,
|
|
64
|
+
reason: "formula_not_found"
|
|
65
|
+
};
|
|
66
|
+
let n = [...e.keys ?? []], r = {}, o = {
|
|
67
|
+
key: (e) => Number.isInteger(e) && e >= 0 && e < n.length ? n[e] : void 0,
|
|
68
|
+
value: (e) => {
|
|
69
|
+
if (!Number.isInteger(e) || e < 0 || e >= n.length) return;
|
|
70
|
+
let t = n[e];
|
|
71
|
+
if (t) return r[t];
|
|
72
|
+
},
|
|
73
|
+
num: (e) => {
|
|
74
|
+
if (!Number.isInteger(e) || e < 0 || e >= n.length) return 0;
|
|
75
|
+
let t = n[e];
|
|
76
|
+
return t ? a(r[t]) : 0;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
return {
|
|
80
|
+
ok: !0,
|
|
81
|
+
execute: (e) => {
|
|
82
|
+
r = e;
|
|
83
|
+
try {
|
|
84
|
+
let e = t.fn(o);
|
|
85
|
+
return Number.isFinite(e) ? {
|
|
86
|
+
ok: !0,
|
|
87
|
+
value: e
|
|
88
|
+
} : {
|
|
89
|
+
ok: !1,
|
|
90
|
+
reason: "invalid_result"
|
|
91
|
+
};
|
|
92
|
+
} catch {
|
|
93
|
+
return {
|
|
94
|
+
ok: !1,
|
|
95
|
+
reason: "runtime_error"
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function c(e) {
|
|
102
|
+
let t = s({
|
|
103
|
+
formulaId: e.formulaId,
|
|
104
|
+
keys: e.keys
|
|
105
|
+
});
|
|
106
|
+
return t.ok ? t.execute(e.rowData) : {
|
|
107
|
+
ok: !1,
|
|
108
|
+
reason: t.reason
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/formulas/validate.ts
|
|
113
|
+
function l(e) {
|
|
114
|
+
return [...e].sort((e, t) => e - t);
|
|
115
|
+
}
|
|
116
|
+
function u(e, t) {
|
|
117
|
+
return e.reduce((e, n, r) => (e[n] = (r + 1) * t, e), {});
|
|
118
|
+
}
|
|
119
|
+
function d(e) {
|
|
120
|
+
let t = [], n = [], r = i(e.formulaId), a = [...e.dependencies ?? []], s = e.availableColumnIds ?? [];
|
|
121
|
+
if (!r) return t.push({
|
|
122
|
+
code: "formula_not_found",
|
|
123
|
+
message: "Формула не найдена в реестре."
|
|
124
|
+
}), {
|
|
125
|
+
ok: !1,
|
|
126
|
+
errors: t,
|
|
127
|
+
warnings: n,
|
|
128
|
+
usage: {
|
|
129
|
+
usedDependencyIndexes: [],
|
|
130
|
+
usedDependencyIds: [],
|
|
131
|
+
requiredDependencyCount: 0
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
let c = new Set(s), d = a.filter((e) => !c.has(e));
|
|
135
|
+
d.length > 0 && t.push({
|
|
136
|
+
code: "dependency_not_available",
|
|
137
|
+
message: `Не найдены среди доступных полей: ${d.join(", ")}.`
|
|
138
|
+
});
|
|
139
|
+
let f = /* @__PURE__ */ new Set(), p = /* @__PURE__ */ new Set(), m = 0, h = (e) => {
|
|
140
|
+
try {
|
|
141
|
+
let t = o({
|
|
142
|
+
rowData: e,
|
|
143
|
+
keys: a,
|
|
144
|
+
instrumentation: {
|
|
145
|
+
onReadIndex: (e) => {
|
|
146
|
+
f.add(e);
|
|
147
|
+
},
|
|
148
|
+
onOutOfRangeIndex: (e) => {
|
|
149
|
+
p.add(e);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
r.fn(t);
|
|
154
|
+
} catch {
|
|
155
|
+
m += 1;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
h(u(a, 100)), h(u(a, -100));
|
|
159
|
+
let g = l(f), _ = g.length > 0 ? g[g.length - 1] + 1 : 0;
|
|
160
|
+
p.size > 0 && t.push({
|
|
161
|
+
code: "dependency_index_out_of_range",
|
|
162
|
+
message: `Формула обращается к несуществующим индексам. Минимально требуется зависимостей: ${_}, выбрано: ${a.length}.`
|
|
163
|
+
}), g.length === 0 && n.push({
|
|
164
|
+
code: "formula_does_not_use_dependencies",
|
|
165
|
+
message: "Формула не использует dependencies."
|
|
166
|
+
});
|
|
167
|
+
let v = a.filter((e, t) => !f.has(t));
|
|
168
|
+
v.length > 0 && n.push({
|
|
169
|
+
code: "unused_dependencies",
|
|
170
|
+
message: `Выбраны, но не используются формулой: ${v.join(", ")}.`
|
|
171
|
+
}), m > 0 && n.push({
|
|
172
|
+
code: "formula_runtime_error",
|
|
173
|
+
message: "На тестовых данных формула завершилась с ошибкой."
|
|
174
|
+
});
|
|
175
|
+
let y = g.map((e) => a[e]).filter(Boolean);
|
|
176
|
+
return {
|
|
177
|
+
ok: t.length === 0,
|
|
178
|
+
errors: t,
|
|
179
|
+
warnings: n,
|
|
180
|
+
usage: {
|
|
181
|
+
usedDependencyIndexes: g,
|
|
182
|
+
usedDependencyIds: y,
|
|
183
|
+
requiredDependencyCount: _
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
//#endregion
|
|
188
|
+
export { s as compileTableFormula, n as configureTableFormulaRegistry, o as createTableFormulaContext, e as createTableFormulaRegistry, c as executeTableFormula, i as getTableFormulaById, r as getTableFormulaList, d as validateTableFormulaDependencies };
|
|
189
|
+
|
|
190
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/formulas/registry.ts","../../src/formulas/execute.ts","../../src/formulas/validate.ts"],"sourcesContent":["import type { TableFormulaDefinition } from \"./types\";\n\nexport type TableFormulaRegistry = Readonly<{\n\tlist: readonly TableFormulaDefinition[];\n\tbyId: ReadonlyMap<string, TableFormulaDefinition>;\n}>;\n\nexport function createTableFormulaRegistry(definitions: readonly TableFormulaDefinition[]): TableFormulaRegistry {\n\tconst byId = new Map<string, TableFormulaDefinition>();\n\tconst list: TableFormulaDefinition[] = [];\n\n\tfor (const definition of definitions) {\n\t\tconst normalizedId = definition.id.trim();\n\t\tif (!normalizedId) {\n\t\t\tthrow new Error(\"Formula id не может быть пустым\");\n\t\t}\n\n\t\tif (byId.has(normalizedId)) {\n\t\t\tthrow new Error(`Найден дублирующийся formulaId: ${normalizedId}`);\n\t\t}\n\n\t\tconst normalizedDefinition: TableFormulaDefinition = Object.freeze({\n\t\t\t...definition,\n\t\t\tid: normalizedId,\n\t\t\tname: definition.name.trim(),\n\t\t\tdescription: definition.description.trim(),\n\t\t\tkeywords: definition.keywords ? [...definition.keywords] : undefined\n\t\t});\n\n\t\tbyId.set(normalizedId, normalizedDefinition);\n\t\tlist.push(normalizedDefinition);\n\t}\n\n\treturn Object.freeze({\n\t\tlist: Object.freeze(list),\n\t\tbyId\n\t});\n}\n\nlet tableFormulaRegistry = createTableFormulaRegistry([]);\n\n/**\n * Устанавливает реестр формул host-приложения для всех formula runtime API.\n *\n * Конфигурация выполняется composition root до первого чтения, валидации или\n * компиляции формулы. Библиотека намеренно не содержит прикладной каталог.\n */\nexport function configureTableFormulaRegistry(registry: TableFormulaRegistry): void {\n\ttableFormulaRegistry = registry;\n}\n\nexport function getTableFormulaList(): readonly TableFormulaDefinition[] {\n\treturn tableFormulaRegistry.list;\n}\n\nexport function getTableFormulaById(formulaId: string | undefined): TableFormulaDefinition | undefined {\n\tconst normalizedId = formulaId?.trim();\n\tif (!normalizedId) return undefined;\n\treturn tableFormulaRegistry.byId.get(normalizedId);\n}\n","import { getTableFormulaById } from \"./registry\";\n\nimport type { TableFormulaContext, TableFormulaRowData } from \"./types\";\n\ntype TableFormulaContextInstrumentation = {\n\tonReadIndex?: (index: number) => void;\n\tonOutOfRangeIndex?: (index: number) => void;\n};\n\nfunction toFiniteNumberOrZero(value: unknown): number {\n\tconst normalized = Number(value);\n\treturn Number.isFinite(normalized) ? normalized : 0;\n}\n\nexport function createTableFormulaContext(args: {\n\trowData: TableFormulaRowData;\n\tkeys?: readonly string[];\n\tinstrumentation?: TableFormulaContextInstrumentation;\n}): TableFormulaContext {\n\t// TODO: duplicate createRowBasedFormatterContext src\\shared\\lib\\formatters\\rowBased\\context.ts\n\tconst keys = [...(args.keys ?? [])];\n\n\tconst readKey = (index: number): string | undefined => {\n\t\tif (!Number.isInteger(index) || index < 0) {\n\t\t\targs.instrumentation?.onOutOfRangeIndex?.(index);\n\t\t\treturn undefined;\n\t\t}\n\n\t\targs.instrumentation?.onReadIndex?.(index);\n\n\t\tif (index >= keys.length) {\n\t\t\targs.instrumentation?.onOutOfRangeIndex?.(index);\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn keys[index];\n\t};\n\n\tconst readValue = (index: number): unknown => {\n\t\tconst key = readKey(index);\n\t\tif (!key) return undefined;\n\t\treturn args.rowData[key];\n\t};\n\n\treturn {\n\t\tkey: readKey,\n\t\tvalue: readValue,\n\t\tnum: (index) => toFiniteNumberOrZero(readValue(index))\n\t};\n}\n\nexport type TableFormulaExecutionResult =\n\t| {\n\t\t\tok: true;\n\t\t\tvalue: number;\n\t }\n\t| {\n\t\t\tok: false;\n\t\t\treason: \"formula_not_found\" | \"invalid_result\" | \"runtime_error\";\n\t };\n\nexport type TableFormulaCompiledExecutor = (rowData: TableFormulaRowData) => TableFormulaExecutionResult;\n\ntype CompileTableFormulaResult =\n\t| {\n\t\t\tok: true;\n\t\t\texecute: TableFormulaCompiledExecutor;\n\t }\n\t| {\n\t\t\tok: false;\n\t\t\treason: \"formula_not_found\";\n\t };\n\nexport function compileTableFormula(args: { formulaId: string | undefined; keys?: readonly string[] }): CompileTableFormulaResult {\n\tconst formula = getTableFormulaById(args.formulaId);\n\tif (!formula) {\n\t\treturn { ok: false, reason: \"formula_not_found\" };\n\t}\n\n\tconst keys = [...(args.keys ?? [])];\n\tlet rowDataRef: TableFormulaRowData = {};\n\tconst context: TableFormulaContext = {\n\t\tkey: (index) => (Number.isInteger(index) && index >= 0 && index < keys.length ? keys[index] : undefined),\n\t\tvalue: (index) => {\n\t\t\tif (!Number.isInteger(index) || index < 0 || index >= keys.length) return undefined;\n\t\t\tconst key = keys[index];\n\t\t\tif (!key) return undefined;\n\t\t\treturn rowDataRef[key];\n\t\t},\n\t\tnum: (index) => {\n\t\t\tif (!Number.isInteger(index) || index < 0 || index >= keys.length) return 0;\n\t\t\tconst key = keys[index];\n\t\t\tif (!key) return 0;\n\t\t\treturn toFiniteNumberOrZero(rowDataRef[key]);\n\t\t}\n\t};\n\n\treturn {\n\t\tok: true,\n\t\texecute: (rowData) => {\n\t\t\trowDataRef = rowData;\n\n\t\t\ttry {\n\t\t\t\tconst value = formula.fn(context);\n\t\t\t\tif (!Number.isFinite(value)) {\n\t\t\t\t\treturn { ok: false, reason: \"invalid_result\" };\n\t\t\t\t}\n\n\t\t\t\treturn { ok: true, value };\n\t\t\t} catch {\n\t\t\t\treturn { ok: false, reason: \"runtime_error\" };\n\t\t\t}\n\t\t}\n\t};\n}\n\nexport function executeTableFormula(args: {\n\tformulaId: string | undefined;\n\trowData: TableFormulaRowData;\n\tkeys?: readonly string[];\n}): TableFormulaExecutionResult {\n\tconst compiled = compileTableFormula({\n\t\tformulaId: args.formulaId,\n\t\tkeys: args.keys\n\t});\n\tif (!compiled.ok) {\n\t\treturn { ok: false, reason: compiled.reason };\n\t}\n\n\treturn compiled.execute(args.rowData);\n}\n","import { createTableFormulaContext } from \"./execute\";\nimport { getTableFormulaById } from \"./registry\";\n\ntype ValidationCode =\n\t| \"formula_not_found\"\n\t| \"dependency_index_out_of_range\"\n\t| \"dependency_not_available\"\n\t| \"unused_dependencies\"\n\t| \"formula_does_not_use_dependencies\"\n\t| \"formula_runtime_error\";\n\nexport interface TableFormulaValidationMessage {\n\tcode: ValidationCode;\n\tmessage: string;\n}\nexport interface TableFormulaDependenciesValidationResult {\n\tok: boolean;\n\terrors: TableFormulaValidationMessage[];\n\twarnings: TableFormulaValidationMessage[];\n\tusage: {\n\t\tusedDependencyIndexes: number[];\n\t\tusedDependencyIds: string[];\n\t\trequiredDependencyCount: number;\n\t};\n}\n\nfunction toSortedArray(items: Set<number>): number[] {\n\treturn [...items].sort((left, right) => left - right);\n}\n\nfunction createSampleRowData(dependencies: readonly string[], multiplier: number): Record<string, unknown> {\n\treturn dependencies.reduce<Record<string, unknown>>((acc, dependencyId, index) => {\n\t\tacc[dependencyId] = (index + 1) * multiplier;\n\t\treturn acc;\n\t}, {});\n}\n\nexport function validateTableFormulaDependencies(args: {\n\tformulaId: string | undefined;\n\tdependencies?: readonly string[];\n\tavailableColumnIds?: readonly string[];\n}): TableFormulaDependenciesValidationResult {\n\tconst errors: TableFormulaValidationMessage[] = [];\n\tconst warnings: TableFormulaValidationMessage[] = [];\n\n\tconst formula = getTableFormulaById(args.formulaId);\n\tconst dependencies = [...(args.dependencies ?? [])];\n\tconst availableColumnIds = args.availableColumnIds ?? [];\n\n\tif (!formula) {\n\t\terrors.push({\n\t\t\tcode: \"formula_not_found\",\n\t\t\tmessage: \"Формула не найдена в реестре.\"\n\t\t});\n\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors,\n\t\t\twarnings,\n\t\t\tusage: {\n\t\t\t\tusedDependencyIndexes: [],\n\t\t\t\tusedDependencyIds: [],\n\t\t\t\trequiredDependencyCount: 0\n\t\t\t}\n\t\t};\n\t}\n\n\tconst availableSet = new Set(availableColumnIds);\n\tconst missingDependencies = dependencies.filter((dependencyId) => !availableSet.has(dependencyId));\n\tif (missingDependencies.length > 0) {\n\t\terrors.push({\n\t\t\tcode: \"dependency_not_available\",\n\t\t\tmessage: `Не найдены среди доступных полей: ${missingDependencies.join(\", \")}.`\n\t\t});\n\t}\n\n\tconst usedIndexes = new Set<number>();\n\tconst outOfRangeIndexes = new Set<number>();\n\tlet runtimeErrorCount = 0;\n\n\tconst runValidationPass = (sampleRowData: Record<string, unknown>) => {\n\t\ttry {\n\t\t\tconst context = createTableFormulaContext({\n\t\t\t\trowData: sampleRowData,\n\t\t\t\tkeys: dependencies,\n\t\t\t\tinstrumentation: {\n\t\t\t\t\tonReadIndex: (index) => {\n\t\t\t\t\t\tusedIndexes.add(index);\n\t\t\t\t\t},\n\t\t\t\t\tonOutOfRangeIndex: (index) => {\n\t\t\t\t\t\toutOfRangeIndexes.add(index);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tformula.fn(context);\n\t\t} catch {\n\t\t\truntimeErrorCount += 1;\n\t\t}\n\t};\n\n\t// Несколько прогонов повышают шанс увидеть обращения к индексам в разных ветках формулы.\n\trunValidationPass(createSampleRowData(dependencies, 100));\n\trunValidationPass(createSampleRowData(dependencies, -100));\n\n\tconst sortedUsedIndexes = toSortedArray(usedIndexes);\n\tconst requiredDependencyCount = sortedUsedIndexes.length > 0 ? sortedUsedIndexes[sortedUsedIndexes.length - 1] + 1 : 0;\n\n\tif (outOfRangeIndexes.size > 0) {\n\t\terrors.push({\n\t\t\tcode: \"dependency_index_out_of_range\",\n\t\t\tmessage: `Формула обращается к несуществующим индексам. Минимально требуется зависимостей: ${requiredDependencyCount}, выбрано: ${dependencies.length}.`\n\t\t});\n\t}\n\n\tif (sortedUsedIndexes.length === 0) {\n\t\twarnings.push({\n\t\t\tcode: \"formula_does_not_use_dependencies\",\n\t\t\tmessage: \"Формула не использует dependencies.\"\n\t\t});\n\t}\n\n\tconst unusedDependencies = dependencies.filter((_, index) => !usedIndexes.has(index));\n\tif (unusedDependencies.length > 0) {\n\t\twarnings.push({\n\t\t\tcode: \"unused_dependencies\",\n\t\t\tmessage: `Выбраны, но не используются формулой: ${unusedDependencies.join(\", \")}.`\n\t\t});\n\t}\n\n\tif (runtimeErrorCount > 0) {\n\t\twarnings.push({\n\t\t\tcode: \"formula_runtime_error\",\n\t\t\tmessage: \"На тестовых данных формула завершилась с ошибкой.\"\n\t\t});\n\t}\n\n\tconst usedDependencyIds = sortedUsedIndexes.map((index) => dependencies[index]).filter(Boolean);\n\n\treturn {\n\t\tok: errors.length === 0,\n\t\terrors,\n\t\twarnings,\n\t\tusage: {\n\t\t\tusedDependencyIndexes: sortedUsedIndexes,\n\t\t\tusedDependencyIds,\n\t\t\trequiredDependencyCount\n\t\t}\n\t};\n}\n"],"mappings":";AAOA,SAAgB,EAA2B,GAAsE;CAChH,IAAM,oBAAO,IAAI,IAAoC,GAC/C,IAAiC,CAAC;CAExC,KAAK,IAAM,KAAc,GAAa;EACrC,IAAM,IAAe,EAAW,GAAG,KAAK;EACxC,IAAI,CAAC,GACJ,MAAU,MAAM,iCAAiC;EAGlD,IAAI,EAAK,IAAI,CAAY,GACxB,MAAU,MAAM,mCAAmC,GAAc;EAGlE,IAAM,IAA+C,OAAO,OAAO;GAClE,GAAG;GACH,IAAI;GACJ,MAAM,EAAW,KAAK,KAAK;GAC3B,aAAa,EAAW,YAAY,KAAK;GACzC,UAAU,EAAW,WAAW,CAAC,GAAG,EAAW,QAAQ,IAAI,KAAA;EAC5D,CAAC;EAGD,AADA,EAAK,IAAI,GAAc,CAAoB,GAC3C,EAAK,KAAK,CAAoB;CAC/B;CAEA,OAAO,OAAO,OAAO;EACpB,MAAM,OAAO,OAAO,CAAI;EACxB;CACD,CAAC;AACF;AAEA,IAAI,IAAuB,EAA2B,CAAC,CAAC;AAQxD,SAAgB,EAA8B,GAAsC;CACnF,IAAuB;AACxB;AAEA,SAAgB,IAAyD;CACxE,OAAO,EAAqB;AAC7B;AAEA,SAAgB,EAAoB,GAAmE;CACtG,IAAM,IAAe,GAAW,KAAK;CAChC,OACL,OAAO,EAAqB,KAAK,IAAI,CAAY;AAClD;;;AClDA,SAAS,EAAqB,GAAwB;CACrD,IAAM,IAAa,OAAO,CAAK;CAC/B,OAAO,OAAO,SAAS,CAAU,IAAI,IAAa;AACnD;AAEA,SAAgB,EAA0B,GAIlB;CAEvB,IAAM,IAAO,CAAC,GAAI,EAAK,QAAQ,CAAC,CAAE,GAE5B,KAAW,MAAsC;EACtD,IAAI,CAAC,OAAO,UAAU,CAAK,KAAK,IAAQ,GAAG;GAC1C,EAAK,iBAAiB,oBAAoB,CAAK;GAC/C;EACD;EAIA,IAFA,EAAK,iBAAiB,cAAc,CAAK,GAErC,KAAS,EAAK,QAAQ;GACzB,EAAK,iBAAiB,oBAAoB,CAAK;GAC/C;EACD;EAEA,OAAO,EAAK;CACb,GAEM,KAAa,MAA2B;EAC7C,IAAM,IAAM,EAAQ,CAAK;EACpB,OACL,OAAO,EAAK,QAAQ;CACrB;CAEA,OAAO;EACN,KAAK;EACL,OAAO;EACP,MAAM,MAAU,EAAqB,EAAU,CAAK,CAAC;CACtD;AACD;AAwBA,SAAgB,EAAoB,GAA8F;CACjI,IAAM,IAAU,EAAoB,EAAK,SAAS;CAClD,IAAI,CAAC,GACJ,OAAO;EAAE,IAAI;EAAO,QAAQ;CAAoB;CAGjD,IAAM,IAAO,CAAC,GAAI,EAAK,QAAQ,CAAC,CAAE,GAC9B,IAAkC,CAAC,GACjC,IAA+B;EACpC,MAAM,MAAW,OAAO,UAAU,CAAK,KAAK,KAAS,KAAK,IAAQ,EAAK,SAAS,EAAK,KAAS,KAAA;EAC9F,QAAQ,MAAU;GACjB,IAAI,CAAC,OAAO,UAAU,CAAK,KAAK,IAAQ,KAAK,KAAS,EAAK,QAAQ;GACnE,IAAM,IAAM,EAAK;GACZ,OACL,OAAO,EAAW;EACnB;EACA,MAAM,MAAU;GACf,IAAI,CAAC,OAAO,UAAU,CAAK,KAAK,IAAQ,KAAK,KAAS,EAAK,QAAQ,OAAO;GAC1E,IAAM,IAAM,EAAK;GAEjB,OADK,IACE,EAAqB,EAAW,EAAI,IAD1B;EAElB;CACD;CAEA,OAAO;EACN,IAAI;EACJ,UAAU,MAAY;GACrB,IAAa;GAEb,IAAI;IACH,IAAM,IAAQ,EAAQ,GAAG,CAAO;IAKhC,OAJK,OAAO,SAAS,CAAK,IAInB;KAAE,IAAI;KAAM;IAAM,IAHjB;KAAE,IAAI;KAAO,QAAQ;IAAiB;GAI/C,QAAQ;IACP,OAAO;KAAE,IAAI;KAAO,QAAQ;IAAgB;GAC7C;EACD;CACD;AACD;AAEA,SAAgB,EAAoB,GAIJ;CAC/B,IAAM,IAAW,EAAoB;EACpC,WAAW,EAAK;EAChB,MAAM,EAAK;CACZ,CAAC;CAKD,OAJK,EAAS,KAIP,EAAS,QAAQ,EAAK,OAAO,IAH5B;EAAE,IAAI;EAAO,QAAQ,EAAS;CAAO;AAI9C;;;ACxGA,SAAS,EAAc,GAA8B;CACpD,OAAO,CAAC,GAAG,CAAK,CAAC,CAAC,MAAM,GAAM,MAAU,IAAO,CAAK;AACrD;AAEA,SAAS,EAAoB,GAAiC,GAA6C;CAC1G,OAAO,EAAa,QAAiC,GAAK,GAAc,OACvE,EAAI,MAAiB,IAAQ,KAAK,GAC3B,IACL,CAAC,CAAC;AACN;AAEA,SAAgB,EAAiC,GAIJ;CAC5C,IAAM,IAA0C,CAAC,GAC3C,IAA4C,CAAC,GAE7C,IAAU,EAAoB,EAAK,SAAS,GAC5C,IAAe,CAAC,GAAI,EAAK,gBAAgB,CAAC,CAAE,GAC5C,IAAqB,EAAK,sBAAsB,CAAC;CAEvD,IAAI,CAAC,GAMJ,OALA,EAAO,KAAK;EACX,MAAM;EACN,SAAS;CACV,CAAC,GAEM;EACN,IAAI;EACJ;EACA;EACA,OAAO;GACN,uBAAuB,CAAC;GACxB,mBAAmB,CAAC;GACpB,yBAAyB;EAC1B;CACD;CAGD,IAAM,IAAe,IAAI,IAAI,CAAkB,GACzC,IAAsB,EAAa,QAAQ,MAAiB,CAAC,EAAa,IAAI,CAAY,CAAC;CACjG,AAAI,EAAoB,SAAS,KAChC,EAAO,KAAK;EACX,MAAM;EACN,SAAS,qCAAqC,EAAoB,KAAK,IAAI,EAAE;CAC9E,CAAC;CAGF,IAAM,oBAAc,IAAI,IAAY,GAC9B,oBAAoB,IAAI,IAAY,GACtC,IAAoB,GAElB,KAAqB,MAA2C;EACrE,IAAI;GACH,IAAM,IAAU,EAA0B;IACzC,SAAS;IACT,MAAM;IACN,iBAAiB;KAChB,cAAc,MAAU;MACvB,EAAY,IAAI,CAAK;KACtB;KACA,oBAAoB,MAAU;MAC7B,EAAkB,IAAI,CAAK;KAC5B;IACD;GACD,CAAC;GACD,EAAQ,GAAG,CAAO;EACnB,QAAQ;GACP,KAAqB;EACtB;CACD;CAIA,AADA,EAAkB,EAAoB,GAAc,GAAG,CAAC,GACxD,EAAkB,EAAoB,GAAc,IAAI,CAAC;CAEzD,IAAM,IAAoB,EAAc,CAAW,GAC7C,IAA0B,EAAkB,SAAS,IAAI,EAAkB,EAAkB,SAAS,KAAK,IAAI;CASrH,AAPI,EAAkB,OAAO,KAC5B,EAAO,KAAK;EACX,MAAM;EACN,SAAS,oFAAoF,EAAwB,aAAa,EAAa,OAAO;CACvJ,CAAC,GAGE,EAAkB,WAAW,KAChC,EAAS,KAAK;EACb,MAAM;EACN,SAAS;CACV,CAAC;CAGF,IAAM,IAAqB,EAAa,QAAQ,GAAG,MAAU,CAAC,EAAY,IAAI,CAAK,CAAC;CAQpF,AAPI,EAAmB,SAAS,KAC/B,EAAS,KAAK;EACb,MAAM;EACN,SAAS,yCAAyC,EAAmB,KAAK,IAAI,EAAE;CACjF,CAAC,GAGE,IAAoB,KACvB,EAAS,KAAK;EACb,MAAM;EACN,SAAS;CACV,CAAC;CAGF,IAAM,IAAoB,EAAkB,KAAK,MAAU,EAAa,EAAM,CAAC,CAAC,OAAO,OAAO;CAE9F,OAAO;EACN,IAAI,EAAO,WAAW;EACtB;EACA;EACA,OAAO;GACN,uBAAuB;GACvB;GACA;EACD;CACD;AACD"}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import type { TableFormulaDefinition } from "./types";
|
|
2
|
-
type TableFormulaRegistry = {
|
|
2
|
+
export type TableFormulaRegistry = Readonly<{
|
|
3
3
|
list: readonly TableFormulaDefinition[];
|
|
4
4
|
byId: ReadonlyMap<string, TableFormulaDefinition>;
|
|
5
|
-
}
|
|
5
|
+
}>;
|
|
6
6
|
export declare function createTableFormulaRegistry(definitions: readonly TableFormulaDefinition[]): TableFormulaRegistry;
|
|
7
|
+
/**
|
|
8
|
+
* Устанавливает реестр формул host-приложения для всех formula runtime API.
|
|
9
|
+
*
|
|
10
|
+
* Конфигурация выполняется composition root до первого чтения, валидации или
|
|
11
|
+
* компиляции формулы. Библиотека намеренно не содержит прикладной каталог.
|
|
12
|
+
*/
|
|
13
|
+
export declare function configureTableFormulaRegistry(registry: TableFormulaRegistry): void;
|
|
7
14
|
export declare function getTableFormulaList(): readonly TableFormulaDefinition[];
|
|
8
15
|
export declare function getTableFormulaById(formulaId: string | undefined): TableFormulaDefinition | undefined;
|
|
9
|
-
export {};
|
|
10
16
|
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/formulas/registry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/formulas/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAEtD,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC3C,IAAI,EAAE,SAAS,sBAAsB,EAAE,CAAC;IACxC,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;CAClD,CAAC,CAAC;AAEH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,SAAS,sBAAsB,EAAE,GAAG,oBAAoB,CA8B/G;AAID;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAElF;AAED,wBAAgB,mBAAmB,IAAI,SAAS,sBAAsB,EAAE,CAEvE;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,sBAAsB,GAAG,SAAS,CAIrG"}
|