@ryuzaki13/react-foundation-lib 2.31.0 → 2.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analytical-table/index.js +8 -7
- package/dist/analytical-table/index.js.map +1 -1
- package/dist/chunks/formatDate-BUvpRI7H.js +133 -0
- package/dist/chunks/formatDate-BUvpRI7H.js.map +1 -0
- package/dist/chunks/{formatters-CZnnbdud.js → formatters-rxriDRPk.js} +14 -13
- package/dist/chunks/{formatters-CZnnbdud.js.map → formatters-rxriDRPk.js.map} +1 -1
- package/dist/chunks/scalarTypeClassification-BZcFmIyR.js +764 -0
- package/dist/chunks/scalarTypeClassification-BZcFmIyR.js.map +1 -0
- package/dist/chunks/{validate-CEQHqevt.js → validate-DsUR-bFF.js} +2 -2
- package/dist/chunks/{validate-CEQHqevt.js.map → validate-DsUR-bFF.js.map} +1 -1
- package/dist/error-report/index.js +2 -2
- package/dist/excel/index.js +20 -20
- package/dist/excel/index.js.map +1 -1
- package/dist/excel/tableExport.d.ts +2 -2
- package/dist/excel/tableExport.d.ts.map +1 -1
- package/dist/formatters/index.js +5 -4
- package/dist/formatters/pipeline/types.d.ts +4 -4
- package/dist/formatters/pipeline/types.d.ts.map +1 -1
- package/dist/hooks/useFloatingListbox.d.ts +1 -1
- package/dist/metadata/baseMetaTypes.d.ts +7 -0
- package/dist/metadata/baseMetaTypes.d.ts.map +1 -0
- package/dist/metadata/metadataTypes.d.ts +16 -0
- package/dist/metadata/metadataTypes.d.ts.map +1 -0
- package/dist/metadata/scalarTypeClassification.d.ts +8 -0
- package/dist/metadata/scalarTypeClassification.d.ts.map +1 -0
- package/dist/odata-service/baseTypes.d.ts +1 -5
- package/dist/odata-service/baseTypes.d.ts.map +1 -1
- package/dist/odata-service/formatters.d.ts +1 -2
- package/dist/odata-service/formatters.d.ts.map +1 -1
- package/dist/odata-service/index.js +1311 -2
- package/dist/odata-service/index.js.map +1 -0
- package/dist/odata-service/types.d.ts +8 -11
- package/dist/odata-service/types.d.ts.map +1 -1
- package/dist/odata-service/typesValidation.d.ts +1 -5
- package/dist/odata-service/typesValidation.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/formatters/README.mdx +5 -0
- package/src/foundationLib.mdx +8 -0
- package/src/metadata/README.md +35 -0
- package/src/odata-service/README.mdx +36 -1
- package/dist/chunks/odata-service-tp2U5yIr.js +0 -2211
- package/dist/chunks/odata-service-tp2U5yIr.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scalarTypeClassification-BZcFmIyR.js","names":[],"sources":["../../src/formatters/number/parseNumber.ts","../../src/formatters/date/pattern.ts","../../src/formatters/date/presets.ts","../../src/formatters/date/parseDate.ts","../../src/metadata/scalarTypeClassification.ts"],"sourcesContent":["/**\n * SAP-like парсер: пробелы/NBSP как группировка, ',' как десятичный.\n * Возвращает только finite number или undefined.\n */\nexport function toFiniteNumber(v: unknown): number | undefined {\n\tif (typeof v === \"number\") return Number.isFinite(v) ? v : undefined;\n\tif (typeof v !== \"string\") return undefined;\n\n\tconst trimmed = v.trim();\n\tif (!trimmed) return undefined;\n\n\tconst parsed = Number(trimmed);\n\tif (Number.isFinite(parsed)) return parsed;\n\n\t// SAP-like: убираем пробелы/NBSP/NNBSP, поддерживаем ',' как decimal\n\n\tlet s = \"\";\n\tfor (let i = 0; i < trimmed.length; i++) {\n\t\tconst c = trimmed.charCodeAt(i);\n\t\tif (c === 32 || c === 160 || c === 8239 || c === 39 /*'*/) continue;\n\t\ts += trimmed[i];\n\t}\n\n\tconst hasComma = s.indexOf(\",\") !== -1;\n\tconst hasDot = s.indexOf(\".\") !== -1;\n\n\tif (hasComma && hasDot) {\n\t\ts = s.replace(/,/g, \"\"); // 1,234.56 -> 1234.56\n\t} else if (hasComma) {\n\t\ts = s.replace(/,/g, \".\"); // 1234,56 -> 1234.56\n\t}\n\n\tconst n = Number(s);\n\treturn Number.isFinite(n) ? n : undefined;\n}\n\nexport function parseNumber(v: unknown): number {\n\treturn toFiniteNumber(v) ?? 0;\n}\n\nexport function isPositiveValue(value: unknown): boolean {\n\tconst normalizedValue = toFiniteNumber(value);\n\tif (normalizedValue) {\n\t\treturn normalizedValue > 0;\n\t}\n\n\treturn false;\n}\n\n/**\n * Читает положительное целое число из неизвестного значения.\n */\nexport function toPositiveInteger(value: unknown): number | undefined {\n\tconst normalizedValue = toFiniteNumber(value);\n\tif (normalizedValue === undefined || !Number.isInteger(normalizedValue) || normalizedValue <= 0) {\n\t\treturn undefined;\n\t}\n\n\treturn normalizedValue;\n}\n","import type { DateFormatPrecision } from \"./types\";\n\n/**\n * Токены календарной даты, поддерживаемые ручными шаблонами форматирования.\n */\nexport const DATE_PATTERN_DATE_TOKENS = Object.freeze([\"dd\", \"MM\", \"yyyy\", \"yy\"] as const);\n\n/**\n * Токены времени, поддерживаемые ручными шаблонами форматирования.\n */\nexport const DATE_PATTERN_TIME_TOKENS = Object.freeze([\"HH\", \"mm\", \"ss\"] as const);\n\n/**\n * Все токены ручного шаблона даты/времени.\n */\nexport const DATE_PATTERN_TOKENS = Object.freeze([...DATE_PATTERN_DATE_TOKENS, ...DATE_PATTERN_TIME_TOKENS] as const);\n\n/**\n * Регулярное выражение для поиска токенов ручного шаблона.\n */\nexport const DATE_PATTERN_TOKEN_RE = /(yyyy|yy|MM|dd|HH|mm|ss)/g;\n\nconst DATE_PATTERN_TOKEN_SET = new Set<string>(DATE_PATTERN_TOKENS);\nconst DATE_PATTERN_PRECISION_TOKENS: Readonly<Record<DateFormatPrecision, ReadonlySet<string>>> = Object.freeze({\n\tday: new Set(DATE_PATTERN_TOKENS),\n\tmonth: new Set([\"MM\", \"yyyy\", \"yy\"]),\n\tyear: new Set([\"yyyy\", \"yy\"])\n});\n\n/**\n * Проверяет, что сегмент шаблона является поддерживаемым токеном даты/времени.\n */\nexport function isDatePatternToken(value: string): boolean {\n\treturn DATE_PATTERN_TOKEN_SET.has(value);\n}\n\n/**\n * Проверяет, что шаблон содержит хотя бы один токен из списка.\n */\nexport function containsDatePatternToken(pattern: string, tokens: readonly string[]): boolean {\n\treturn tokens.some((token) => pattern.includes(token));\n}\n\n/**\n * Проверяет, похожа ли строка на ручной шаблон даты.\n */\nexport function hasDatePatternTokens(pattern: string): boolean {\n\tDATE_PATTERN_TOKEN_RE.lastIndex = 0;\n\treturn DATE_PATTERN_TOKEN_RE.test(pattern);\n}\n\n/**\n * Возвращает токены, допустимые для выбранной точности календарной даты.\n */\nexport function getDatePatternPrecisionTokens(precision: DateFormatPrecision): ReadonlySet<string> {\n\treturn DATE_PATTERN_PRECISION_TOKENS[precision];\n}\n\n/**\n * Удаляет из ручного шаблона части даты, которые ниже выбранной точности.\n */\nexport function resolveDatePatternPrecision(pattern: string, precision: DateFormatPrecision): string {\n\tif (precision === \"day\") return pattern;\n\n\tconst allowedTokens = getDatePatternPrecisionTokens(precision);\n\tconst resultSegments: string[] = [];\n\tlet pendingLiteral = \"\";\n\tlet hasKeptToken = false;\n\tlet keptTokenCount = 0;\n\tlet cursor = 0;\n\tlet match: RegExpExecArray | null;\n\n\tDATE_PATTERN_TOKEN_RE.lastIndex = 0;\n\twhile ((match = DATE_PATTERN_TOKEN_RE.exec(pattern))) {\n\t\tconst literal = pattern.slice(cursor, match.index);\n\t\tconst token = match[0];\n\n\t\tif (hasKeptToken) pendingLiteral += literal;\n\n\t\tif (allowedTokens.has(token)) {\n\t\t\tif (hasKeptToken) resultSegments.push(pendingLiteral);\n\t\t\tresultSegments.push(token);\n\t\t\tpendingLiteral = \"\";\n\t\t\thasKeptToken = true;\n\t\t\tkeptTokenCount += 1;\n\t\t}\n\n\t\tcursor = match.index + token.length;\n\t}\n\n\tif (keptTokenCount === 0) return pattern;\n\treturn resultSegments.join(\"\");\n}\n","import {\n\tcontainsDatePatternToken,\n\tDATE_PATTERN_DATE_TOKENS,\n\tDATE_PATTERN_TIME_TOKENS,\n\tDATE_PATTERN_TOKEN_RE,\n\tisDatePatternToken,\n\tresolveDatePatternPrecision\n} from \"./pattern\";\n\nimport type { DateFormatPrecision, DateFormatPreset, DateFormatPresetConfig, DateFormatStyle } from \"./types\";\n\n/**\n * Функция, которая форматирует уже подготовленную календарную дату.\n */\nexport type CompiledDateFormatter = (date: Date, precision?: DateFormatPrecision) => string;\n\n/**\n * Внутреннее представление предустановки с заранее созданными форматтерами.\n */\nexport interface CompiledDateFormatPreset extends DateFormatPreset {\n\tformatDateTime: CompiledDateFormatter;\n\tformatDuration?: (durationMs: number, fallback: string) => string;\n}\n\n/**\n * Локаль форматирования дат по умолчанию.\n */\nconst DEFAULT_LOCALE = \"ru-RU\";\n\n/**\n * Уровни детализации, для которых создаются встроенные style-пресеты.\n */\nconst FORMAT_STYLES = Object.freeze([\"short\", \"medium\", \"long\"] as const);\nconst FORMAT_PRECISIONS = Object.freeze([\"day\", \"month\", \"year\"] as const);\n\n/**\n * Значения по умолчанию для предустановок форматирования дат.\n */\nexport const DATE_FORMAT_DEFAULTS: Omit<DateFormatPreset, \"name\" | \"intlOptions\"> & { intlOptions: Intl.DateTimeFormatOptions } = {\n\tlocale: DEFAULT_LOCALE,\n\tintlOptions: { day: \"2-digit\", month: \"2-digit\", year: \"numeric\" },\n\tinvalidFallback: \"\"\n};\n\n/**\n * Имена встроенных предустановок.\n */\nexport const DEFAULT_DATE_PRESET_NAMES = Object.freeze({\n\tdate: \"date\",\n\tdateShort: \"date-short\",\n\tdateMedium: \"date-medium\",\n\tdateLong: \"date-long\",\n\tmonthShort: \"month-short\",\n\tmonthMedium: \"month-medium\",\n\tmonthLong: \"month-long\",\n\tmonthYearMedium: \"month-year-medium\",\n\tmonthYearLong: \"month-year-long\",\n\tdatetime: \"datetime\",\n\tdatetimeSeconds: \"datetime-seconds\",\n\tdatetimeShort: \"datetime-short\",\n\tdatetimeMedium: \"datetime-medium\",\n\tdatetimeLong: \"datetime-long\",\n\ttime: \"time\",\n\ttimeSeconds: \"time-seconds\",\n\ttimeShort: \"time-short\",\n\ttimeMedium: \"time-medium\",\n\ttimeLong: \"time-long\",\n\todataDate: \"odata-date\",\n\todataDatetime: \"odata-datetime\",\n\tabapDatetime: \"abap-datetime\",\n\tabapDate: \"abap-date\",\n\tabapMonth: \"abap-month\",\n\tabapYear: \"abap-year\"\n});\n\n/**\n * Алиасы style-форматов даты к именам встроенных date-пресетов.\n */\nexport const DATE_FORMAT_STYLE_PRESET_NAMES: Readonly<Record<DateFormatStyle, string>> = Object.freeze({\n\tshort: DEFAULT_DATE_PRESET_NAMES.dateShort,\n\tmedium: DEFAULT_DATE_PRESET_NAMES.dateMedium,\n\tlong: DEFAULT_DATE_PRESET_NAMES.dateLong\n});\n\nconst patternPresetCache = new Map<string, DateFormatPreset>();\n\n/**\n * Встроенные предустановки форматирования дат.\n */\nconst BUILTIN_PRESETS: DateFormatPresetConfig[] = [\n\t{ name: DEFAULT_DATE_PRESET_NAMES.date, intlOptions: { day: \"2-digit\", month: \"2-digit\", year: \"numeric\" } },\n\t{\n\t\tname: DEFAULT_DATE_PRESET_NAMES.datetime,\n\t\tintlDateOptions: { day: \"2-digit\", month: \"2-digit\", year: \"numeric\" },\n\t\tintlTimeOptions: { hour: \"2-digit\", minute: \"2-digit\", hourCycle: \"h23\" },\n\t\tintlJoiner: \" \"\n\t},\n\t{\n\t\tname: DEFAULT_DATE_PRESET_NAMES.datetimeSeconds,\n\t\tintlDateOptions: { day: \"2-digit\", month: \"2-digit\", year: \"numeric\" },\n\t\tintlTimeOptions: { hour: \"2-digit\", minute: \"2-digit\", second: \"2-digit\", hourCycle: \"h23\" },\n\t\tintlJoiner: \" \"\n\t},\n\t{\n\t\tname: DEFAULT_DATE_PRESET_NAMES.time,\n\t\tintlOptions: { hour: \"2-digit\", minute: \"2-digit\", hourCycle: \"h23\" },\n\t\tdurationPattern: \"HH:mm\"\n\t},\n\t{\n\t\tname: DEFAULT_DATE_PRESET_NAMES.timeSeconds,\n\t\tintlOptions: { hour: \"2-digit\", minute: \"2-digit\", second: \"2-digit\", hourCycle: \"h23\" },\n\t\tdurationPattern: \"HH:mm:ss\"\n\t},\n\t...FORMAT_STYLES.map((style) => ({\n\t\tname: `date-${style}`,\n\t\tintlOptions: getDateStyleIntlOptions(style)\n\t})),\n\t...FORMAT_STYLES.map((style) => ({\n\t\tname: `month-${style}`,\n\t\tintlOptions: getMonthStyleIntlOptions(style)\n\t})),\n\t{\n\t\tname: DEFAULT_DATE_PRESET_NAMES.monthYearMedium,\n\t\tintlOptions: { month: \"short\", year: \"numeric\" }\n\t},\n\t{\n\t\tname: DEFAULT_DATE_PRESET_NAMES.monthYearLong,\n\t\tintlOptions: { month: \"long\", year: \"numeric\" }\n\t},\n\t...FORMAT_STYLES.map((style) => ({\n\t\tname: `time-${style}`,\n\t\tintlOptions: getTimeStyleIntlOptions(style),\n\t\tdurationPattern: style === \"short\" ? \"HH:mm\" : \"HH:mm:ss\"\n\t})),\n\t...FORMAT_STYLES.map((style) => ({\n\t\tname: `datetime-${style}`,\n\t\tintlDateOptions: getDateStyleIntlOptions(style),\n\t\tintlTimeOptions: getTimeStyleIntlOptions(style),\n\t\tintlJoiner: \", \"\n\t})),\n\t{ name: DEFAULT_DATE_PRESET_NAMES.odataDate, pattern: \"yyyy-MM-dd\" },\n\t{ name: DEFAULT_DATE_PRESET_NAMES.odataDatetime, pattern: \"yyyy-MM-ddTHH:mm:ss\" },\n\t{ name: DEFAULT_DATE_PRESET_NAMES.abapDatetime, pattern: \"yyyyMMddHHmmss\" },\n\t{ name: DEFAULT_DATE_PRESET_NAMES.abapDate, pattern: \"yyyyMMdd\" },\n\t{ name: DEFAULT_DATE_PRESET_NAMES.abapMonth, pattern: \"yyyyMM\" },\n\t{ name: DEFAULT_DATE_PRESET_NAMES.abapYear, pattern: \"yyyy\" }\n];\n\n/**\n * Текстовая детализация месяца для встроенных пресетов `месяц + год`.\n */\nconst MONTH_YEAR_PRESET_STYLES: ReadonlyMap<string, \"short\" | \"long\"> = new Map([\n\t[DEFAULT_DATE_PRESET_NAMES.monthYearMedium, \"short\"],\n\t[DEFAULT_DATE_PRESET_NAMES.monthYearLong, \"long\"]\n]);\n\n/**\n * Реестр предустановок форматирования.\n */\nconst registry = new Map<string, CompiledDateFormatPreset>();\n\n/**\n * Дополняет числовую часть даты ведущим нулём.\n */\nfunction padDatePart(value: number, size = 2): string {\n\treturn String(value).padStart(size, \"0\");\n}\n\n/**\n * Возвращает настройки Intl для dateStyle-подобного формата без timezone-семантики.\n */\nfunction getDateStyleIntlOptions(style: DateFormatStyle, precision: DateFormatPrecision = \"day\"): Intl.DateTimeFormatOptions {\n\tif (precision === \"year\") return { year: \"numeric\" };\n\n\tif (precision === \"month\") {\n\t\tif (style === \"short\") return { month: \"2-digit\", year: \"numeric\" };\n\t\tif (style === \"medium\") return { month: \"short\", year: \"numeric\" };\n\t\treturn { month: \"long\", year: \"numeric\" };\n\t}\n\n\tif (style === \"short\") return { day: \"2-digit\", month: \"2-digit\", year: \"numeric\" };\n\tif (style === \"medium\") return { day: \"numeric\", month: \"short\", year: \"numeric\" };\n\treturn { day: \"numeric\", month: \"long\", year: \"numeric\" };\n}\n\n/**\n * Возвращает настройки Intl для dateStyle-подобного формата без года.\n *\n * Семейство сохраняет различия стандартных уровней детализации:\n * числовой short, сокращённый текстовый medium и полный текстовый long.\n */\nfunction getMonthStyleIntlOptions(style: DateFormatStyle): Intl.DateTimeFormatOptions {\n\tif (style === \"short\") return { day: \"2-digit\", month: \"2-digit\" };\n\tif (style === \"medium\") return { day: \"numeric\", month: \"short\" };\n\treturn { day: \"numeric\", month: \"long\" };\n}\n\n/**\n * Возвращает настройки Intl для timeStyle-подобного формата без timezoneName.\n *\n * Intl timeStyle=\"long\" добавляет часовой пояс в результат. В этом модуле\n * timezone намеренно не существует, поэтому long повторяет секундную точность\n * без вывода GMT/UTC-метки.\n */\nfunction getTimeStyleIntlOptions(style: DateFormatStyle): Intl.DateTimeFormatOptions {\n\tif (style === \"short\") return { hour: \"2-digit\", minute: \"2-digit\", hourCycle: \"h23\" };\n\treturn { hour: \"2-digit\", minute: \"2-digit\", second: \"2-digit\", hourCycle: \"h23\" };\n}\n\n/**\n * Удаляет timezone из настроек Intl, чтобы форматирование не могло сдвинуть\n * календарные компоненты или вывести timezoneName в строку.\n */\nfunction sanitizeIntlOptions(options: Intl.DateTimeFormatOptions): Intl.DateTimeFormatOptions {\n\tconst { timeZone, timeZoneName, ...safeOptions } = options;\n\tvoid timeZone;\n\tvoid timeZoneName;\n\treturn safeOptions;\n}\n\n/**\n * Проверяет, содержит ли Intl-конфигурация календарные поля.\n */\nfunction hasIntlDateFields(options: Intl.DateTimeFormatOptions): boolean {\n\treturn Boolean(options.dateStyle || options.year || options.month || options.day);\n}\n\n/**\n * Приводит Intl-конфигурацию к выбранной точности календарной даты.\n */\nfunction resolveIntlDatePrecisionOptions(options: Intl.DateTimeFormatOptions, precision: DateFormatPrecision): Intl.DateTimeFormatOptions {\n\tconst safeOptions = sanitizeIntlOptions(options);\n\tif (precision === \"day\" || !hasIntlDateFields(safeOptions)) return safeOptions;\n\n\tif (safeOptions.dateStyle) {\n\t\tconst style = safeOptions.dateStyle === \"short\" || safeOptions.dateStyle === \"medium\" ? safeOptions.dateStyle : \"long\";\n\t\treturn getDateStyleIntlOptions(style, precision);\n\t}\n\n\tif (precision === \"year\") {\n\t\treturn { year: safeOptions.year ?? \"numeric\" };\n\t}\n\n\treturn {\n\t\tmonth: safeOptions.month ?? \"2-digit\",\n\t\tyear: safeOptions.year ?? \"numeric\"\n\t};\n}\n\n/**\n * Создаёт функцию Intl-форматирования без timezone-настроек.\n *\n * Стандартный Intl timeStyle=\"long\" и timeStyle=\"full\" выводят timezoneName.\n * Поэтому любые timeStyle-настройки нормализуются в явные поля времени.\n */\nfunction createIntlFormatter(locale: string, options: Intl.DateTimeFormatOptions): CompiledDateFormatter {\n\tconst safeOptions = sanitizeIntlOptions(options);\n\tconst precisionFormatters = new Map<DateFormatPrecision, Intl.DateTimeFormat>();\n\n\tif (safeOptions.timeStyle) {\n\t\tconst timeOptions = getTimeStyleIntlOptions(safeOptions.timeStyle === \"short\" ? \"short\" : \"medium\");\n\n\t\tif (safeOptions.dateStyle) {\n\t\t\tconst dateFormatter = new Intl.DateTimeFormat(locale, { dateStyle: safeOptions.dateStyle });\n\t\t\tconst timeFormatter = new Intl.DateTimeFormat(locale, timeOptions);\n\t\t\treturn (date, precision = \"day\") => {\n\t\t\t\tif (precision === \"day\") return `${dateFormatter.format(date)}, ${timeFormatter.format(date)}`;\n\n\t\t\t\tconst precisionOptions = resolveIntlDatePrecisionOptions({ dateStyle: safeOptions.dateStyle }, precision);\n\t\t\t\tlet precisionFormatter = precisionFormatters.get(precision);\n\t\t\t\tif (!precisionFormatter) {\n\t\t\t\t\tprecisionFormatter = new Intl.DateTimeFormat(locale, precisionOptions);\n\t\t\t\t\tprecisionFormatters.set(precision, precisionFormatter);\n\t\t\t\t}\n\n\t\t\t\treturn precisionFormatter.format(date);\n\t\t\t};\n\t\t}\n\n\t\treturn new Intl.DateTimeFormat(locale, timeOptions).format;\n\t}\n\n\tconst defaultFormatter = new Intl.DateTimeFormat(locale, safeOptions);\n\treturn (date, precision = \"day\") => {\n\t\tif (precision === \"day\") return defaultFormatter.format(date);\n\n\t\tlet precisionFormatter = precisionFormatters.get(precision);\n\t\tif (!precisionFormatter) {\n\t\t\tprecisionFormatter = new Intl.DateTimeFormat(locale, resolveIntlDatePrecisionOptions(safeOptions, precision));\n\t\t\tprecisionFormatters.set(precision, precisionFormatter);\n\t\t}\n\n\t\treturn precisionFormatter.format(date);\n\t};\n}\n\n/**\n * Возвращает значение токена шаблона для календарной даты.\n */\nfunction getPatternTokenValue(token: string, date: Date): string {\n\tconst fullYear = String(date.getFullYear());\n\n\tswitch (token) {\n\t\tcase \"yyyy\":\n\t\t\treturn fullYear;\n\t\tcase \"yy\":\n\t\t\treturn fullYear.slice(-2);\n\t\tcase \"MM\":\n\t\t\treturn padDatePart(date.getMonth() + 1);\n\t\tcase \"dd\":\n\t\t\treturn padDatePart(date.getDate());\n\t\tcase \"HH\":\n\t\t\treturn padDatePart(date.getHours());\n\t\tcase \"mm\":\n\t\t\treturn padDatePart(date.getMinutes());\n\t\tcase \"ss\":\n\t\t\treturn padDatePart(date.getSeconds());\n\t\tdefault:\n\t\t\treturn token;\n\t}\n}\n\n/**\n * Компилирует машинный шаблон в функцию без разбора шаблона на каждый вызов.\n */\nfunction compileFixedPatternFormatter(pattern: string): CompiledDateFormatter {\n\tswitch (pattern) {\n\t\tcase \"yyyyMMdd\":\n\t\t\treturn (date) => `${date.getFullYear()}${padDatePart(date.getMonth() + 1)}${padDatePart(date.getDate())}`;\n\t\tcase \"yyyyMMddHHmmss\":\n\t\t\treturn (date) =>\n\t\t\t\t`${date.getFullYear()}${padDatePart(date.getMonth() + 1)}${padDatePart(date.getDate())}${padDatePart(date.getHours())}${padDatePart(\n\t\t\t\t\tdate.getMinutes()\n\t\t\t\t)}${padDatePart(date.getSeconds())}`;\n\t\tcase \"yyyy-MM-dd\":\n\t\t\treturn (date) => `${date.getFullYear()}-${padDatePart(date.getMonth() + 1)}-${padDatePart(date.getDate())}`;\n\t\tcase \"yyyy-MM-ddTHH:mm:ss\":\n\t\t\treturn (date) =>\n\t\t\t\t`${date.getFullYear()}-${padDatePart(date.getMonth() + 1)}-${padDatePart(date.getDate())}T${padDatePart(date.getHours())}:${padDatePart(\n\t\t\t\t\tdate.getMinutes()\n\t\t\t\t)}:${padDatePart(date.getSeconds())}`;\n\t\tdefault:\n\t\t\treturn compileGenericPatternFormatter(pattern);\n\t}\n}\n\n/**\n * Компилирует машинный шаблон с учётом точности календарной даты.\n */\nfunction compilePatternFormatter(pattern: string): CompiledDateFormatter {\n\tconst precisionFormatters = new Map<DateFormatPrecision, CompiledDateFormatter>();\n\n\treturn (date, precision = \"day\") => {\n\t\tlet formatter = precisionFormatters.get(precision);\n\t\tif (!formatter) {\n\t\t\tformatter = compileFixedPatternFormatter(resolveDatePatternPrecision(pattern, precision));\n\t\t\tprecisionFormatters.set(precision, formatter);\n\t\t}\n\n\t\treturn formatter(date, \"day\");\n\t};\n}\n\n/**\n * Компилирует произвольный шаблон один раз при регистрации предустановки.\n */\nfunction compileGenericPatternFormatter(pattern: string): CompiledDateFormatter {\n\tconst segments: string[] = [];\n\tlet lastIndex = 0;\n\tlet match: RegExpExecArray | null;\n\n\tDATE_PATTERN_TOKEN_RE.lastIndex = 0;\n\twhile ((match = DATE_PATTERN_TOKEN_RE.exec(pattern))) {\n\t\tif (match.index > lastIndex) segments.push(pattern.slice(lastIndex, match.index));\n\t\tsegments.push(match[0]);\n\t\tlastIndex = match.index + match[0].length;\n\t}\n\tif (lastIndex < pattern.length) segments.push(pattern.slice(lastIndex));\n\n\treturn (date) => {\n\t\tlet result = \"\";\n\t\tfor (const segment of segments) {\n\t\t\tresult += isDatePatternToken(segment) ? getPatternTokenValue(segment, date) : segment;\n\t\t}\n\t\treturn result;\n\t};\n}\n\n/**\n * Форматирует длительность в предскомпилированный time-шаблон.\n */\nfunction formatDurationByPattern(durationMs: number, pattern: string, fallback: string): string {\n\tif (containsDatePatternToken(pattern, DATE_PATTERN_DATE_TOKENS)) return fallback;\n\tif (!containsDatePatternToken(pattern, DATE_PATTERN_TIME_TOKENS)) return fallback;\n\n\tconst sign = durationMs < 0 ? \"-\" : \"\";\n\tconst absoluteSeconds = Math.trunc(Math.abs(durationMs) / 1_000);\n\tconst hours = Math.trunc(absoluteSeconds / 3_600);\n\tconst minutes = Math.trunc((absoluteSeconds % 3_600) / 60);\n\tconst seconds = absoluteSeconds % 60;\n\n\tif (pattern === \"HH:mm\") return `${sign}${padDatePart(hours)}:${padDatePart(minutes)}`;\n\tif (pattern === \"HH:mm:ss\") return `${sign}${padDatePart(hours)}:${padDatePart(minutes)}:${padDatePart(seconds)}`;\n\n\treturn (\n\t\tsign + pattern.replaceAll(\"HH\", padDatePart(hours)).replaceAll(\"mm\", padDatePart(minutes)).replaceAll(\"ss\", padDatePart(seconds))\n\t);\n}\n\n/**\n * Компилирует Intl-форматтер или машинный шаблон для предустановки.\n */\nexport function compileDatePreset(config: DateFormatPresetConfig | DateFormatPreset): CompiledDateFormatPreset {\n\tconst preset: DateFormatPreset = { ...DATE_FORMAT_DEFAULTS, ...config };\n\tconst formatDateTime = createPresetFormatter(preset);\n\tconst durationPattern = preset.durationPattern ?? preset.pattern;\n\tconst compiledPreset: CompiledDateFormatPreset = { ...preset, formatDateTime };\n\n\tif (durationPattern) {\n\t\tcompiledPreset.formatDuration = (durationMs, fallback) => formatDurationByPattern(durationMs, durationPattern, fallback);\n\t}\n\n\treturn compiledPreset;\n}\n\n/**\n * Создаёт функцию форматирования даты для предустановки.\n */\nfunction createPresetFormatter(preset: DateFormatPreset): CompiledDateFormatter {\n\tif (preset.pattern) return compilePatternFormatter(preset.pattern);\n\n\tif (preset.intlDateOptions && preset.intlTimeOptions) {\n\t\tconst dateFormatter = createIntlFormatter(preset.locale, preset.intlDateOptions);\n\t\tconst timeFormatter = createIntlFormatter(preset.locale, preset.intlTimeOptions);\n\t\tconst joiner = preset.intlJoiner ?? \" \";\n\n\t\treturn (date, precision = \"day\") => {\n\t\t\tif (precision !== \"day\") return dateFormatter(date, precision);\n\t\t\treturn `${dateFormatter(date)}${joiner}${timeFormatter(date)}`;\n\t\t};\n\t}\n\n\treturn createIntlFormatter(preset.locale, preset.intlOptions ?? DATE_FORMAT_DEFAULTS.intlOptions);\n}\n\n/**\n * Создаёт форматтер месяца и года без локализованного маркера года `г.`.\n *\n * `Intl.DateTimeFormat` для `ru-RU` добавляет этот маркер автоматически.\n * Пресет предназначен для компактного отображения месячной точности в DateInput,\n * поэтому собирает только содержательные части `month` и `year`.\n */\nfunction createMonthYearFormatter(locale: string, monthStyle: \"short\" | \"long\"): CompiledDateFormatter {\n\t// Русская локаль сокращает название месяца только в контексте даты с днём.\n\t// День нужен Intl для правильной формы, но в итоговую строку не включается.\n\tconst monthYearFormatter = new Intl.DateTimeFormat(\n\t\tlocale,\n\t\tmonthStyle === \"short\" ? { day: \"numeric\", month: monthStyle, year: \"numeric\" } : { month: monthStyle, year: \"numeric\" }\n\t);\n\tconst standaloneMonthFormatter = new Intl.DateTimeFormat(locale, { month: \"long\" });\n\tconst yearFormatter = new Intl.DateTimeFormat(locale, { year: \"numeric\" });\n\n\treturn (date, precision = \"day\") => {\n\t\tconst formatter = precision === \"year\" ? yearFormatter : monthYearFormatter;\n\t\tconst parts = formatter.formatToParts(date);\n\t\tconst year = parts.find((part) => part.type === \"year\")?.value ?? \"\";\n\t\tif (precision === \"year\") return year;\n\n\t\tconst contextualMonth = parts.find((part) => part.type === \"month\")?.value ?? \"\";\n\t\t// Для мая Intl возвращает нескорочённую родительную форму `мая`.\n\t\t// Если сокращение с точкой отсутствует, берём самостоятельную форму `май`.\n\t\tconst month =\n\t\t\tmonthStyle === \"short\" && !contextualMonth.endsWith(\".\")\n\t\t\t\t? (standaloneMonthFormatter.formatToParts(date).find((part) => part.type === \"month\")?.value ?? contextualMonth)\n\t\t\t\t: contextualMonth;\n\n\t\treturn `${month} ${year}`;\n\t};\n}\n\n/**\n * Компилирует встроенный пресет с учётом его фиксированной семантики.\n */\nfunction compileBuiltinDatePreset(config: DateFormatPresetConfig): CompiledDateFormatPreset {\n\tconst preset = compileDatePreset(config);\n\tconst monthYearStyle = MONTH_YEAR_PRESET_STYLES.get(config.name);\n\tif (!monthYearStyle) return preset;\n\n\treturn {\n\t\t...preset,\n\t\tformatDateTime: createMonthYearFormatter(preset.locale, monthYearStyle)\n\t};\n}\n\n/**\n * Инициализирует реестр встроенными предустановками.\n */\nfunction initPresets(): void {\n\tfor (const config of BUILTIN_PRESETS) {\n\t\tregistry.set(config.name, compileBuiltinDatePreset(config));\n\t}\n}\n\ninitPresets();\n\n/**\n * Возвращает предустановку по имени.\n */\nexport function getDatePreset(name: string): DateFormatPreset | undefined {\n\treturn registry.get(name);\n}\n\n/**\n * Возвращает скомпилированную предустановку по имени.\n */\nexport function getCompiledDatePreset(name: string): CompiledDateFormatPreset | undefined {\n\treturn registry.get(name);\n}\n\n/**\n * Возвращает список имён доступных предустановок.\n */\nexport function getDatePresetNames(): string[] {\n\treturn Array.from(registry.keys());\n}\n\n/**\n * Проверяет, что строка является алиасом style-пресета даты.\n */\nexport function isDateFormatStyle(value: string): value is DateFormatStyle {\n\treturn FORMAT_STYLES.includes(value as DateFormatStyle);\n}\n\n/**\n * Проверяет, что строка является поддерживаемой точностью даты.\n */\nexport function isDateFormatPrecision(value: string): value is DateFormatPrecision {\n\treturn FORMAT_PRECISIONS.includes(value as DateFormatPrecision);\n}\n\n/**\n * Нормализует имя пресета, алиас style-формата или ручной шаблон.\n */\nexport function resolveDateFormatName(dateFormat?: string, defaultFormat: string = DEFAULT_DATE_PRESET_NAMES.date): string {\n\tconst normalizedFormat = dateFormat?.trim();\n\tif (!normalizedFormat) return defaultFormat;\n\n\treturn isDateFormatStyle(normalizedFormat) ? DATE_FORMAT_STYLE_PRESET_NAMES[normalizedFormat] : normalizedFormat;\n}\n\n/**\n * Создаёт кешируемый объектный пресет для ручного шаблона.\n */\nfunction createPatternDatePreset(pattern: string, presetName: string, locale: string, invalidFallback: string): DateFormatPreset {\n\tconst cacheKey = `${presetName}\\u0000${locale}\\u0000${invalidFallback}\\u0000${pattern}`;\n\tconst cachedPreset = patternPresetCache.get(cacheKey);\n\tif (cachedPreset) return cachedPreset;\n\n\tconst preset = {\n\t\tname: `${presetName}:${pattern}`,\n\t\tpattern,\n\t\tlocale,\n\t\tinvalidFallback\n\t};\n\n\tpatternPresetCache.set(cacheKey, preset);\n\treturn preset;\n}\n\nexport interface ResolveDateFormatPresetOptions {\n\t/**\n\t * Формат по умолчанию, если входная строка пустая.\n\t */\n\tdefaultFormat?: string;\n\t/**\n\t * Префикс имени для объектных пресетов ручных шаблонов.\n\t */\n\tpatternPresetName?: string;\n\t/**\n\t * Локаль объектного пресета ручного шаблона.\n\t */\n\tlocale?: string;\n\t/**\n\t * Fallback объектного пресета ручного шаблона.\n\t */\n\tinvalidFallback?: string;\n}\n\n/**\n * Возвращает зарегистрированный пресет или кешируемый объектный пресет для ручного шаблона.\n */\nexport function resolveDateFormatPreset(\n\tdateFormat?: string,\n\t{\n\t\tdefaultFormat = DEFAULT_DATE_PRESET_NAMES.date,\n\t\tpatternPresetName = \"__date_pattern__\",\n\t\tlocale = DEFAULT_LOCALE,\n\t\tinvalidFallback = \"\"\n\t}: ResolveDateFormatPresetOptions = {}\n): string | DateFormatPreset {\n\tconst resolvedFormat = resolveDateFormatName(dateFormat, defaultFormat);\n\tif (getDatePreset(resolvedFormat)) return resolvedFormat;\n\n\treturn createPatternDatePreset(resolvedFormat, patternPresetName, locale, invalidFallback);\n}\n\n/**\n * Регистрирует или перезаписывает предустановку.\n */\nexport function registerDatePreset(config: DateFormatPresetConfig): DateFormatPreset {\n\tconst preset = compileDatePreset(config);\n\tregistry.set(preset.name, preset);\n\treturn preset;\n}\n\n/**\n * Сбрасывает реестр к встроенному состоянию.\n */\nexport function resetDatePresets(): void {\n\tregistry.clear();\n\tinitPresets();\n}\n","import { DATE_PATTERN_TOKEN_RE, hasDatePatternTokens, resolveDatePatternPrecision } from \"./pattern\";\nimport { DATE_FORMAT_DEFAULTS, DEFAULT_DATE_PRESET_NAMES, getDatePreset, resolveDateFormatName } from \"./presets\";\n\nimport type { DateFormatPattern, DateFormatPrecision, ParsedDateTimeValue, ParsedDateValue } from \"./types\";\n\n/**\n * Регулярное выражение для OData даты вида `/Date(1720137600000+0300)/`.\n */\nconst ODATA_TICKS_RE = /^\\/Date\\((-?\\d+)([+-]\\d{4})?\\)\\/$/;\n\n/**\n * Регулярное выражение для OData литералов вида `datetime'2026-03-03T18:03:50'`.\n */\nconst ODATA_LITERAL_RE = /^(datetimeoffset|datetime)'(.+)'$/i;\n\n/**\n * Регулярное выражение для ISO-даты без timezone.\n */\nconst ISO_LOCAL_RE = /^(\\d{4})-(\\d{2})-(\\d{2})(?:[T ](\\d{2})(?::(\\d{2})(?::(\\d{2})(?:\\.(\\d{1,9}))?)?)?)?$/;\n\n/**\n * Регулярное выражение для даты с явным timezone.\n */\nconst ISO_ZONED_RE = /(Z|([+-])(\\d{2}):?(\\d{2}))$/i;\n\n/**\n * Регулярное выражение для ABAP даты `YYYYMMDD`.\n */\nconst ABAP_COMPACT_RE = /^\\d{8}$/;\n\n/**\n * Регулярное выражение для ABAP timestamp `YYYYMMDDHHmmss...`.\n * Хвост после секунд содержит доли/служебные разряды и не влияет на календарное время.\n */\nconst ABAP_TIMESTAMP_RE = /^\\d{14,}$/;\n\n/**\n * Регулярное выражение для даты вида `DD.MM.YYYY`.\n */\nconst ABAP_DOTTED_RE = /^(\\d{2})\\.(\\d{2})\\.(\\d{4})$/;\n\n/**\n * Регулярное выражение для даты вида `MM/DD/YYYY`.\n */\nconst SLASH_DATE_RE = /^(\\d{2})\\/(\\d{2})\\/(\\d{4})$/;\n\n/**\n * Регулярное выражение для ISO-8601 длительности.\n */\nconst ISO_DURATION_RE = /^([+-])?P(?:(\\d+)Y)?(?:(\\d+)M)?(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)(?:\\.(\\d+))?S)?)?$/;\n\n/**\n * Набор строковых значений, трактуемых как пустые.\n */\nconst EMPTY_STRING_VALUES = new Set([\"\", \"null\", \"undefined\"]);\n\n/**\n * Константы для расчёта длительностей.\n */\nconst MS_IN_SECOND = 1_000;\nconst MS_IN_MINUTE = 60_000;\nconst MS_IN_HOUR = 3_600_000;\nconst MS_IN_DAY = 86_400_000;\nconst APPROX_DAYS_IN_MONTH = 30;\nconst APPROX_DAYS_IN_YEAR = 365;\nconst TWO_DIGIT_YEAR_PIVOT = 70;\n\n/**\n * Режим интерпретации источников, которые несут абсолютный момент времени.\n *\n * `floating` сохраняет историческую семантику видимых календарных компонентов,\n * `instant` применяет timezone и сохраняет Unix instant.\n */\ntype DateParsingMode = \"floating\" | \"instant\";\n\n/**\n * Внутренние настройки общего механизма парсинга.\n *\n * Опция намеренно не экспортируется: публичные функции жёстко выбирают режим,\n * чтобы существующий вызов нельзя было неявно переключить на другую семантику.\n */\ntype ParseDateValueInternalOptions = {\n\tmode?: DateParsingMode;\n};\n\nconst DEFAULT_DATE_PARSING_MODE: DateParsingMode = \"floating\";\n\n/**\n * Шаблоны ручного ввода для встроенных Intl-пресетов.\n */\nconst DATE_FORMAT_PARSE_PATTERNS: Readonly<Record<string, readonly DateFormatPattern[]>> = Object.freeze({\n\t[DEFAULT_DATE_PRESET_NAMES.date]: Object.freeze([\"dd.MM.yyyy\"] as const),\n\t[DEFAULT_DATE_PRESET_NAMES.dateShort]: Object.freeze([\"dd.MM.yyyy\"] as const),\n\t[DEFAULT_DATE_PRESET_NAMES.datetime]: Object.freeze([\"dd.MM.yyyy HH:mm\"] as const),\n\t[DEFAULT_DATE_PRESET_NAMES.datetimeSeconds]: Object.freeze([\"dd.MM.yyyy HH:mm:ss\"] as const),\n\t[DEFAULT_DATE_PRESET_NAMES.datetimeShort]: Object.freeze([\"dd.MM.yyyy, HH:mm\"] as const)\n});\n\n/**\n * Регулярное выражение для человекочитаемых дат вида `3 марта 2026 г.`.\n */\nconst LOCALIZED_DATE_RE = /^(\\d{1,2})\\s+([\\p{L}.]+)\\s+(\\d{4})(?:\\s*[\\p{L}.]+)?(?:,?\\s+(\\d{1,2}):(\\d{2})(?::(\\d{2}))?)?$/iu;\n/**\n * Регулярное выражение для короткой числовой даты без года вида `03.03`.\n */\nconst NUMERIC_DAY_MONTH_RE = /^(\\d{1,2})\\.(\\d{1,2})$/u;\n/**\n * Регулярное выражение для текстовой даты без года вида `3 марта`.\n */\nconst LOCALIZED_DAY_MONTH_RE = /^(\\d{1,2})\\s+([\\p{L}.]+)$/iu;\nconst LOCALIZED_MONTH_RE = /^([\\p{L}.]+)\\s+(\\d{4})(?:\\s*[\\p{L}.]+)?$/iu;\nconst LOCALIZED_YEAR_RE = /^(\\d{4})(?:\\s*[\\p{L}.]+)?$/iu;\n\nconst localizedMonthIndexCache = new Map<string, ReadonlyMap<string, number>>();\nconst DAY_MONTH_PRESET_NAMES = new Set<string>([\n\tDEFAULT_DATE_PRESET_NAMES.monthShort,\n\tDEFAULT_DATE_PRESET_NAMES.monthMedium,\n\tDEFAULT_DATE_PRESET_NAMES.monthLong\n]);\nconst MONTH_YEAR_PRESET_NAMES = new Set<string>([DEFAULT_DATE_PRESET_NAMES.monthYearMedium, DEFAULT_DATE_PRESET_NAMES.monthYearLong]);\n\n/**\n * Создаёт календарную дату без timezone-семантики и валидирует компоненты.\n */\nfunction createCalendarDate(year: number, month: number, day: number, hour = 0, minute = 0, second = 0, millisecond = 0): Date | null {\n\tconst result = new Date(year, month - 1, day, hour, minute, second, millisecond);\n\tconst isValid =\n\t\tresult.getFullYear() === year &&\n\t\tresult.getMonth() === month - 1 &&\n\t\tresult.getDate() === day &&\n\t\tresult.getHours() === hour &&\n\t\tresult.getMinutes() === minute &&\n\t\tresult.getSeconds() === second;\n\n\treturn isValid ? result : null;\n}\n\n/**\n * Нормализует имя месяца из Intl-форматтера для обратного парсинга.\n */\nfunction normalizeLocalizedMonthName(monthName: string, locale: string): string {\n\treturn monthName.toLocaleLowerCase(locale).replace(/\\.$/, \"\");\n}\n\n/**\n * Добавляет имя месяца в runtime-словарь локали.\n */\nfunction addLocalizedMonthName(monthIndex: Map<string, number>, monthName: string, index: number, locale: string): void {\n\tmonthIndex.set(normalizeLocalizedMonthName(monthName, locale), index);\n}\n\n/**\n * Добавляет имя месяца из formatToParts, чтобы учитывать падеж в составе полной даты.\n */\nfunction addLocalizedMonthPart(\n\tmonthIndex: Map<string, number>,\n\tformatter: Intl.DateTimeFormat,\n\tdate: Date,\n\tindex: number,\n\tlocale: string\n): void {\n\tconst monthPart = formatter.formatToParts(date).find((part) => part.type === \"month\");\n\tif (monthPart) addLocalizedMonthName(monthIndex, monthPart.value, index, locale);\n}\n\n/**\n * Собирает словарь названий месяцев через Intl.DateTimeFormat для заданной локали.\n */\nfunction getLocalizedMonthIndex(locale: string): ReadonlyMap<string, number> {\n\tconst cachedIndex = localizedMonthIndexCache.get(locale);\n\tif (cachedIndex) return cachedIndex;\n\n\tconst monthIndex = new Map<string, number>();\n\tconst shortFormatter = new Intl.DateTimeFormat(locale, { month: \"short\" });\n\tconst longFormatter = new Intl.DateTimeFormat(locale, { month: \"long\" });\n\tconst shortDateFormatter = new Intl.DateTimeFormat(locale, { day: \"numeric\", month: \"short\", year: \"numeric\" });\n\tconst longDateFormatter = new Intl.DateTimeFormat(locale, { day: \"numeric\", month: \"long\", year: \"numeric\" });\n\n\tfor (let month = 0; month < 12; month += 1) {\n\t\tconst date = new Date(2026, month, 1);\n\t\taddLocalizedMonthName(monthIndex, shortFormatter.format(date), month, locale);\n\t\taddLocalizedMonthName(monthIndex, longFormatter.format(date), month, locale);\n\t\taddLocalizedMonthPart(monthIndex, shortDateFormatter, date, month, locale);\n\t\taddLocalizedMonthPart(monthIndex, longDateFormatter, date, month, locale);\n\t}\n\n\tlocalizedMonthIndexCache.set(locale, monthIndex);\n\treturn monthIndex;\n}\n\n/**\n * Парсит человекочитаемую дату, сформированную Intl-пресетами текущей локали.\n */\nfunction parseLocalizedDayString(value: string, locale: string): ParsedDateTimeValue | null {\n\tconst match = LOCALIZED_DATE_RE.exec(value.trim());\n\tif (!match) return null;\n\n\tconst day = Number(match[1]);\n\tconst monthIndex = getLocalizedMonthIndex(locale).get(normalizeLocalizedMonthName(match[2], locale));\n\tconst year = Number(match[3]);\n\tconst hour = Number(match[4] ?? 0);\n\tconst minute = Number(match[5] ?? 0);\n\tconst second = Number(match[6] ?? 0);\n\n\tif (monthIndex === undefined) return null;\n\tif (!Number.isFinite(day) || !Number.isFinite(year) || !Number.isFinite(hour) || !Number.isFinite(minute) || !Number.isFinite(second)) {\n\t\treturn null;\n\t}\n\n\tconst parsed = createCalendarDate(year, monthIndex + 1, day, hour, minute, second);\n\treturn parsed ? asDateTimeValue(parsed, \"iso-local\") : null;\n}\n\n/**\n * Парсит человекочитаемую дату без года, сформированную day+month-пресетами.\n */\nfunction parseLocalizedDayMonthString(value: string, locale: string, year: number): ParsedDateTimeValue | null {\n\tconst numericMatch = NUMERIC_DAY_MONTH_RE.exec(value.trim());\n\tif (numericMatch) {\n\t\tconst day = Number(numericMatch[1]);\n\t\tconst month = Number(numericMatch[2]);\n\t\tconst parsed = createCalendarDate(year, month, day);\n\n\t\treturn parsed ? asDateTimeValue(parsed, \"iso-local\") : null;\n\t}\n\n\tconst match = LOCALIZED_DAY_MONTH_RE.exec(value.trim());\n\tif (!match) return null;\n\n\tconst day = Number(match[1]);\n\tconst monthIndex = getLocalizedMonthIndex(locale).get(normalizeLocalizedMonthName(match[2], locale));\n\n\tif (monthIndex === undefined || !Number.isFinite(day)) {\n\t\treturn null;\n\t}\n\n\tconst parsed = createCalendarDate(year, monthIndex + 1, day);\n\treturn parsed ? asDateTimeValue(parsed, \"iso-local\") : null;\n}\n\n/**\n * Парсит человекочитаемый месяц, сформированный Intl-пресетами текущей локали.\n */\nfunction parseLocalizedMonthString(value: string, locale: string): ParsedDateTimeValue | null {\n\tconst match = LOCALIZED_MONTH_RE.exec(value.trim());\n\tif (!match) return null;\n\n\tconst monthIndex = getLocalizedMonthIndex(locale).get(normalizeLocalizedMonthName(match[1], locale));\n\tconst year = Number(match[2]);\n\n\tif (monthIndex === undefined || !Number.isFinite(year)) return null;\n\n\tconst parsed = createCalendarDate(year, monthIndex + 1, 1);\n\treturn parsed ? asDateTimeValue(parsed, \"iso-local\") : null;\n}\n\n/**\n * Парсит человекочитаемый год, сформированный Intl-пресетами текущей локали.\n */\nfunction parseLocalizedYearString(value: string): ParsedDateTimeValue | null {\n\tconst match = LOCALIZED_YEAR_RE.exec(value.trim());\n\tif (!match) return null;\n\n\tconst year = Number(match[1]);\n\tif (!Number.isFinite(year)) return null;\n\n\tconst parsed = createCalendarDate(year, 1, 1);\n\treturn parsed ? asDateTimeValue(parsed, \"iso-local\") : null;\n}\n\n/**\n * Парсит человекочитаемую дату с учётом точности календарного значения.\n */\nfunction parseLocalizedDateString(value: string, locale: string, precision: DateFormatPrecision): ParsedDateTimeValue | null {\n\tif (precision === \"year\") return parseLocalizedYearString(value);\n\tif (precision === \"month\") return parseLocalizedMonthString(value, locale);\n\n\treturn parseLocalizedDayString(value, locale);\n}\n\n/**\n * Проверяет, что формат может быть распарсен как `день месяц` без года.\n */\nfunction isDayMonthPresetName(dateFormat: string): boolean {\n\treturn DAY_MONTH_PRESET_NAMES.has(dateFormat);\n}\n\n/**\n * Проверяет, что пресет содержит месяц и год без дня.\n */\nfunction isMonthYearPresetName(dateFormat: string): boolean {\n\treturn MONTH_YEAR_PRESET_NAMES.has(dateFormat);\n}\n\n/**\n * Возвращает опорный год для пресетов без года.\n */\nfunction resolveReferenceYear(referenceDate: Date | undefined): number {\n\tif (referenceDate instanceof Date && !Number.isNaN(referenceDate.getTime())) {\n\t\treturn referenceDate.getFullYear();\n\t}\n\n\treturn new Date().getFullYear();\n}\n\n/**\n * Пересобирает `Date` в календарную дату через локальные компоненты.\n */\nfunction cloneCalendarDate(date: Date): Date {\n\treturn new Date(\n\t\tdate.getFullYear(),\n\t\tdate.getMonth(),\n\t\tdate.getDate(),\n\t\tdate.getHours(),\n\t\tdate.getMinutes(),\n\t\tdate.getSeconds(),\n\t\tdate.getMilliseconds()\n\t);\n}\n\n/**\n * Пересобирает `Date` в календарную дату через UTC-компоненты.\n *\n * Используется для источников, где дата уже пришла как instant,\n * но визуальные компоненты нужно сохранить без timezone-сдвига.\n */\nfunction cloneUtcCalendarDate(date: Date): Date {\n\treturn new Date(\n\t\tdate.getUTCFullYear(),\n\t\tdate.getUTCMonth(),\n\t\tdate.getUTCDate(),\n\t\tdate.getUTCHours(),\n\t\tdate.getUTCMinutes(),\n\t\tdate.getUTCSeconds(),\n\t\tdate.getUTCMilliseconds()\n\t);\n}\n\n/**\n * Формирует результат парсинга календарной даты/времени.\n */\nfunction asDateTimeValue(date: Date, source: ParsedDateTimeValue[\"source\"]): ParsedDateTimeValue {\n\treturn { kind: \"date-time\", source, date };\n}\n\n/**\n * Парсит timestamp (секунды или миллисекунды Unix epoch).\n */\nfunction parseTimestamp(value: number, mode: DateParsingMode = DEFAULT_DATE_PARSING_MODE): ParsedDateTimeValue | null {\n\tif (!Number.isFinite(value)) return null;\n\n\tconst timestamp = Math.abs(value) < 1e12 ? value * 1_000 : value;\n\tconst parsed = new Date(timestamp);\n\tif (Number.isNaN(parsed.getTime())) return null;\n\n\treturn asDateTimeValue(mode === \"instant\" ? parsed : cloneUtcCalendarDate(parsed), \"timestamp\");\n}\n\n/**\n * Парсит OData ticks: floating-режим восстанавливает сервисные компоненты\n * через offset, instant-режим сохраняет абсолютный timestamp.\n */\nfunction parseODataTicks(value: string, mode: DateParsingMode = DEFAULT_DATE_PARSING_MODE): ParsedDateTimeValue | null {\n\tconst match = ODATA_TICKS_RE.exec(value);\n\tif (!match) return null;\n\n\tconst timestamp = Number(match[1]);\n\tif (!Number.isFinite(timestamp)) return null;\n\n\tif (mode === \"instant\") {\n\t\t// В OData v2 ticks уже содержат миллисекунды от Unix epoch.\n\t\t// Offset описывает сервисное представление и не должен повторно сдвигать instant.\n\t\tconst instantDate = new Date(timestamp);\n\t\treturn Number.isNaN(instantDate.getTime()) ? null : asDateTimeValue(instantDate, \"odata-ticks\");\n\t}\n\n\tconst offset = match[2];\n\tif (!offset) return asDateTimeValue(cloneUtcCalendarDate(new Date(timestamp)), \"odata-ticks\");\n\n\tconst sign = offset.startsWith(\"-\") ? -1 : 1;\n\tconst hours = Number(offset.slice(1, 3));\n\tconst minutes = Number(offset.slice(3, 5));\n\tif (!Number.isFinite(hours) || !Number.isFinite(minutes)) return null;\n\n\tconst offsetMs = sign * (hours * MS_IN_HOUR + minutes * MS_IN_MINUTE);\n\treturn asDateTimeValue(cloneUtcCalendarDate(new Date(timestamp + offsetMs)), \"odata-ticks\");\n}\n\n/**\n * Парсит даты без timezone в ISO-подобных форматах.\n */\nfunction parseIsoLocal(value: string): ParsedDateTimeValue | null {\n\tconst match = ISO_LOCAL_RE.exec(value);\n\tif (!match) return null;\n\n\tconst year = Number(match[1]);\n\tconst month = Number(match[2]);\n\tconst day = Number(match[3]);\n\tconst hour = Number(match[4] ?? 0);\n\tconst minute = Number(match[5] ?? 0);\n\tconst second = Number(match[6] ?? 0);\n\tconst millisecondsRaw = (match[7] ?? \"\").slice(0, 3).padEnd(3, \"0\");\n\tconst millisecond = Number(millisecondsRaw || 0);\n\n\tconst parsed = createCalendarDate(year, month, day, hour, minute, second, millisecond);\n\treturn parsed ? asDateTimeValue(parsed, \"iso-local\") : null;\n}\n\n/**\n * Возвращает смещение ISO timezone в миллисекундах.\n *\n * Положительный offset означает, что локальные компоненты опережают UTC,\n * поэтому при построении instant это значение вычитается.\n */\nfunction resolveIsoTimezoneOffsetMs(timezoneMatch: RegExpExecArray): number | null {\n\tif (timezoneMatch[1].toUpperCase() === \"Z\") return 0;\n\n\tconst sign = timezoneMatch[2] === \"-\" ? -1 : 1;\n\tconst hours = Number(timezoneMatch[3]);\n\tconst minutes = Number(timezoneMatch[4]);\n\tif (!Number.isFinite(hours) || !Number.isFinite(minutes) || hours > 23 || minutes > 59) return null;\n\n\treturn sign * (hours * MS_IN_HOUR + minutes * MS_IN_MINUTE);\n}\n\n/**\n * Парсит даты с явным timezone.\n */\nfunction parseIsoZoned(value: string, mode: DateParsingMode = DEFAULT_DATE_PARSING_MODE): ParsedDateTimeValue | null {\n\tconst timezoneMatch = ISO_ZONED_RE.exec(value);\n\tif (!timezoneMatch) return null;\n\n\tconst normalizedValue = value.slice(0, timezoneMatch.index);\n\tconst parsed = parseIsoLocal(normalizedValue);\n\tif (!parsed) return null;\n\tif (mode === \"floating\") return asDateTimeValue(parsed.date, \"iso-zoned\");\n\n\tconst timezoneOffsetMs = resolveIsoTimezoneOffsetMs(timezoneMatch);\n\tif (timezoneOffsetMs === null) return null;\n\n\tconst calendarDate = parsed.date;\n\tconst instantTimestamp =\n\t\tDate.UTC(\n\t\t\tcalendarDate.getFullYear(),\n\t\t\tcalendarDate.getMonth(),\n\t\t\tcalendarDate.getDate(),\n\t\t\tcalendarDate.getHours(),\n\t\t\tcalendarDate.getMinutes(),\n\t\t\tcalendarDate.getSeconds(),\n\t\t\tcalendarDate.getMilliseconds()\n\t\t) - timezoneOffsetMs;\n\n\tconst instantDate = new Date(instantTimestamp);\n\treturn Number.isNaN(instantDate.getTime()) ? null : asDateTimeValue(instantDate, \"iso-zoned\");\n}\n\n/**\n * Парсит ABAP дату формата `YYYYMMDD`.\n */\nfunction parseAbapCompact(value: string): ParsedDateTimeValue | null {\n\tif (!ABAP_COMPACT_RE.test(value)) return null;\n\n\tconst year = Number(value.slice(0, 4));\n\tconst month = Number(value.slice(4, 6));\n\tconst day = Number(value.slice(6, 8));\n\n\tconst parsed = createCalendarDate(year, month, day);\n\treturn parsed ? asDateTimeValue(parsed, \"abap-compact\") : null;\n}\n\n/**\n * Парсит ABAP timestamp формата `YYYYMMDDHHmmss...`.\n */\nfunction parseAbapTimestamp(value: string): ParsedDateTimeValue | null {\n\tif (!ABAP_TIMESTAMP_RE.test(value)) return null;\n\n\tconst year = Number(value.slice(0, 4));\n\tconst month = Number(value.slice(4, 6));\n\tconst day = Number(value.slice(6, 8));\n\tconst hour = Number(value.slice(8, 10));\n\tconst minute = Number(value.slice(10, 12));\n\tconst second = Number(value.slice(12, 14));\n\n\tconst parsed = createCalendarDate(year, month, day, hour, minute, second);\n\treturn parsed ? asDateTimeValue(parsed, \"abap-timestamp\") : null;\n}\n\n/**\n * Парсит дату формата `DD.MM.YYYY`.\n */\nfunction parseAbapDotted(value: string): ParsedDateTimeValue | null {\n\tconst match = ABAP_DOTTED_RE.exec(value);\n\tif (!match) return null;\n\n\tconst day = Number(match[1]);\n\tconst month = Number(match[2]);\n\tconst year = Number(match[3]);\n\n\tconst parsed = createCalendarDate(year, month, day);\n\treturn parsed ? asDateTimeValue(parsed, \"abap-dotted\") : null;\n}\n\n/**\n * Парсит дату формата `MM/DD/YYYY`.\n */\nfunction parseSlashDate(value: string): ParsedDateTimeValue | null {\n\tconst match = SLASH_DATE_RE.exec(value);\n\tif (!match) return null;\n\n\tconst month = Number(match[1]);\n\tconst day = Number(match[2]);\n\tconst year = Number(match[3]);\n\n\tconst parsed = createCalendarDate(year, month, day);\n\treturn parsed ? asDateTimeValue(parsed, \"slash-date\") : null;\n}\n\n/**\n * Парсит OData литералы `datetime'...'` и `datetimeoffset'...'`.\n */\nfunction parseODataLiteral(value: string, mode: DateParsingMode = DEFAULT_DATE_PARSING_MODE): ParsedDateTimeValue | null {\n\tconst match = ODATA_LITERAL_RE.exec(value);\n\tif (!match) return null;\n\n\tconst innerValue = match[2].trim();\n\treturn parseDateString(innerValue, \"odata-literal\", mode);\n}\n\n/**\n * Парсит ISO-8601 длительность.\n *\n * Для год/месяц используется приближение: 365 и 30 суток соответственно.\n */\nfunction parseIsoDuration(value: string): ParsedDateValue | null {\n\tconst match = ISO_DURATION_RE.exec(value);\n\tif (!match) return null;\n\n\tconst sign = match[1] === \"-\" ? -1 : 1;\n\tconst years = Number(match[2] ?? 0);\n\tconst months = Number(match[3] ?? 0);\n\tconst days = Number(match[4] ?? 0);\n\tconst hours = Number(match[5] ?? 0);\n\tconst minutes = Number(match[6] ?? 0);\n\tconst seconds = Number(match[7] ?? 0);\n\tconst fractionRaw = (match[8] ?? \"\").slice(0, 3).padEnd(3, \"0\");\n\tconst milliseconds = Number(fractionRaw || 0);\n\n\tconst hasAnyComponent = Boolean(years || months || days || hours || minutes || seconds || milliseconds);\n\tif (!hasAnyComponent) return null;\n\n\tconst durationMs =\n\t\tsign *\n\t\t(years * APPROX_DAYS_IN_YEAR * MS_IN_DAY +\n\t\t\tmonths * APPROX_DAYS_IN_MONTH * MS_IN_DAY +\n\t\t\tdays * MS_IN_DAY +\n\t\t\thours * MS_IN_HOUR +\n\t\t\tminutes * MS_IN_MINUTE +\n\t\t\tseconds * MS_IN_SECOND +\n\t\t\tmilliseconds);\n\n\treturn { kind: \"duration\", source: \"iso-duration\", durationMs };\n}\n\n/**\n * Перезаписывает источник, если требуется проставить контекст вызова.\n */\nfunction withSourceOverride(value: ParsedDateTimeValue, sourceOverride?: ParsedDateTimeValue[\"source\"]): ParsedDateTimeValue {\n\treturn sourceOverride ? { ...value, source: sourceOverride } : value;\n}\n\n/**\n * Парсит строку в дату.\n */\nfunction parseDateString(\n\tvalue: string,\n\tsourceOverride?: ParsedDateTimeValue[\"source\"],\n\tmode: DateParsingMode = DEFAULT_DATE_PARSING_MODE\n): ParsedDateTimeValue | null {\n\tconst zoned = parseIsoZoned(value, mode);\n\tif (zoned) return withSourceOverride(zoned, sourceOverride);\n\n\tconst localIso = parseIsoLocal(value);\n\tif (localIso) return withSourceOverride(localIso, sourceOverride);\n\n\tconst dotted = parseAbapDotted(value);\n\tif (dotted) return withSourceOverride(dotted, sourceOverride);\n\n\tconst slashed = parseSlashDate(value);\n\tif (slashed) return withSourceOverride(slashed, sourceOverride);\n\n\tconst timestamp = parseAbapTimestamp(value);\n\tif (timestamp) return withSourceOverride(timestamp, sourceOverride);\n\n\tconst compact = parseAbapCompact(value);\n\tif (compact) return withSourceOverride(compact, sourceOverride);\n\n\tconst timestampAsNumber = Number(value);\n\tif (/^-?\\d+$/.test(value) && Number.isFinite(timestampAsNumber)) {\n\t\tconst timestamp = parseTimestamp(timestampAsNumber, mode);\n\t\tif (timestamp) return withSourceOverride(timestamp, sourceOverride);\n\t}\n\n\treturn null;\n}\n\n/**\n * Экранирует литерал для безопасной подстановки в регулярное выражение.\n */\nfunction escapeRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Преобразует двузначный год в четырёхзначный.\n *\n * Значения `00-69` трактуются как `2000-2069`,\n * значения `70-99` трактуются как `1970-1999`.\n */\nfunction resolveTwoDigitYear(year: number): number {\n\treturn year < TWO_DIGIT_YEAR_PIVOT ? 2000 + year : 1900 + year;\n}\n\n/**\n * Парсит строку по пользовательскому шаблону даты.\n *\n * Поддерживаются токены `dd`, `MM`, `yyyy`, `yy`, `HH`, `mm` и `ss`.\n */\nexport interface ParseDateByPatternOptions {\n\t/**\n\t * Точность календарной даты.\n\t */\n\tprecision?: DateFormatPrecision;\n}\n\nexport function parseDateByPattern(\n\tvalue: unknown,\n\tpattern = \"dd.MM.yyyy\",\n\toptions: ParseDateByPatternOptions = {}\n): ParsedDateValue | null {\n\tif (typeof value !== \"string\") {\n\t\treturn parseDateValue(value);\n\t}\n\n\tconst trimmed = value.trim();\n\tif (EMPTY_STRING_VALUES.has(trimmed.toLowerCase())) return null;\n\n\tconst precision = options.precision ?? \"day\";\n\tconst precisionPattern = resolveDatePatternPrecision(pattern, precision);\n\tconst captureNames: string[] = [];\n\tlet cursor = 0;\n\tlet regexPattern = \"^\";\n\tlet matchPart: RegExpExecArray | null = null;\n\n\tDATE_PATTERN_TOKEN_RE.lastIndex = 0;\n\n\twhile ((matchPart = DATE_PATTERN_TOKEN_RE.exec(precisionPattern)) !== null) {\n\t\tregexPattern += escapeRegExp(precisionPattern.slice(cursor, matchPart.index));\n\t\tcaptureNames.push(matchPart[0]);\n\n\t\tif (matchPart[0] === \"yyyy\") regexPattern += \"(\\\\d{4})\";\n\t\telse regexPattern += \"(\\\\d{2})\";\n\n\t\tcursor = matchPart.index + matchPart[0].length;\n\t}\n\n\tif (captureNames.length === 0) return null;\n\n\tregexPattern += `${escapeRegExp(precisionPattern.slice(cursor))}$`;\n\tconst regex = new RegExp(regexPattern);\n\tconst match = regex.exec(trimmed);\n\tif (!match) return null;\n\n\tlet year: number | null = null;\n\tlet month: number | null = null;\n\tlet day: number | null = null;\n\tlet hour = 0;\n\tlet minute = 0;\n\tlet second = 0;\n\n\tfor (let index = 0; index < captureNames.length; index += 1) {\n\t\tconst token = captureNames[index];\n\t\tconst rawValue = match[index + 1];\n\t\tconst numericValue = Number(rawValue);\n\t\tif (!Number.isFinite(numericValue)) return null;\n\n\t\tif (token === \"yyyy\") year = numericValue;\n\t\tif (token === \"yy\") year = resolveTwoDigitYear(numericValue);\n\t\tif (token === \"MM\") month = numericValue;\n\t\tif (token === \"dd\") day = numericValue;\n\t\tif (token === \"HH\") hour = numericValue;\n\t\tif (token === \"mm\") minute = numericValue;\n\t\tif (token === \"ss\") second = numericValue;\n\t}\n\n\tif (!year) return null;\n\tif (precision !== \"year\" && !month) return null;\n\tif (precision === \"day\" && !day) return null;\n\n\tconst parsed = createCalendarDate(year, month ?? 1, day ?? 1, hour, minute, second);\n\treturn parsed ? asDateTimeValue(parsed, \"iso-local\") : null;\n}\n\nexport interface ParseDateByFormatOptions {\n\t/**\n\t * Формат по умолчанию, если входной формат не задан.\n\t */\n\tdefaultFormat?: DateFormatPattern;\n\t/**\n\t * Локаль для обратного парсинга человекочитаемых Intl-строк.\n\t */\n\tlocale?: string;\n\t/**\n\t * Точность календарной даты.\n\t */\n\tprecision?: DateFormatPrecision;\n\t/**\n\t * Опорная дата для пресетов без года, например `month-long`.\n\t */\n\treferenceDate?: Date;\n}\n\n/**\n * Возвращает набор строгих шаблонов для парсинга по имени пресета или ручному формату.\n */\nfunction getDateFormatParsePatterns(dateFormat: string, precision: DateFormatPrecision): readonly DateFormatPattern[] {\n\tconst preset = getDatePreset(dateFormat);\n\tconst presetPatterns = DATE_FORMAT_PARSE_PATTERNS[dateFormat];\n\n\tif (preset?.pattern) return [resolveDatePatternPrecision(preset.pattern, precision)];\n\tif (presetPatterns) return presetPatterns.map((pattern) => resolveDatePatternPrecision(pattern, precision));\n\tif (!preset && hasDatePatternTokens(dateFormat)) return [resolveDatePatternPrecision(dateFormat, precision)];\n\n\treturn [];\n}\n\n/**\n * Парсит календарную дату по имени пресета, style-алиасу или ручному шаблону.\n */\nexport function parseDateByFormat(value: unknown, dateFormat?: string, options: ParseDateByFormatOptions = {}): ParsedDateTimeValue | null {\n\tif (typeof value !== \"string\") {\n\t\tconst parsed = parseDateValue(value);\n\t\treturn parsed?.kind === \"date-time\" ? parsed : null;\n\t}\n\n\tconst trimmed = value.trim();\n\tif (EMPTY_STRING_VALUES.has(trimmed.toLowerCase())) return null;\n\n\tconst precision = options.precision ?? \"day\";\n\tconst resolvedFormat = resolveDateFormatName(dateFormat, options.defaultFormat ?? DEFAULT_DATE_PRESET_NAMES.date);\n\tfor (const pattern of getDateFormatParsePatterns(resolvedFormat, precision)) {\n\t\tconst parsedByPattern = parseDateByPattern(trimmed, pattern, { precision });\n\t\tif (parsedByPattern?.kind === \"date-time\") return parsedByPattern;\n\t}\n\n\tif (precision === \"day\") {\n\t\tconst parsedByValue = parseDateValue(trimmed);\n\t\tif (parsedByValue?.kind === \"date-time\") return parsedByValue;\n\t}\n\n\tconst preset = getDatePreset(resolvedFormat);\n\tconst locale = preset?.locale ?? options.locale ?? DATE_FORMAT_DEFAULTS.locale;\n\n\tif (precision === \"day\" && isDayMonthPresetName(resolvedFormat)) {\n\t\tconst parsedDayMonth = parseLocalizedDayMonthString(trimmed, locale, resolveReferenceYear(options.referenceDate));\n\t\tif (parsedDayMonth) return parsedDayMonth;\n\t}\n\n\tif (precision !== \"year\" && isMonthYearPresetName(resolvedFormat)) {\n\t\treturn parseLocalizedMonthString(trimmed, locale);\n\t}\n\n\treturn parseLocalizedDateString(trimmed, locale, precision);\n}\n\n/**\n * Общий механизм парсинга с явно выбранной timezone-семантикой.\n */\nfunction parseDateValueInternal(\n\tvalue: unknown,\n\t{ mode = DEFAULT_DATE_PARSING_MODE }: ParseDateValueInternalOptions = {}\n): ParsedDateValue | null {\n\tif (value == null) return null;\n\n\tif (value instanceof Date) {\n\t\tif (Number.isNaN(value.getTime())) return null;\n\t\tconst date = mode === \"instant\" ? new Date(value.getTime()) : cloneCalendarDate(value);\n\t\treturn asDateTimeValue(date, \"date-object\");\n\t}\n\n\tif (typeof value === \"number\") {\n\t\treturn parseTimestamp(value, mode);\n\t}\n\n\tif (typeof value !== \"string\") return null;\n\n\tconst trimmed = value.trim();\n\tif (EMPTY_STRING_VALUES.has(trimmed.toLowerCase())) return null;\n\n\tconst odataTicks = parseODataTicks(trimmed, mode);\n\tif (odataTicks) return odataTicks;\n\n\tconst odataLiteral = parseODataLiteral(trimmed, mode);\n\tif (odataLiteral) return odataLiteral;\n\n\tconst duration = parseIsoDuration(trimmed);\n\tif (duration) return duration;\n\n\treturn parseDateString(trimmed, undefined, mode);\n}\n\n/**\n * Универсально парсит вход даты/времени из `unknown`, сохраняя исторические\n * видимые календарные компоненты без применения timezone.\n */\nexport function parseDateValue(value: unknown): ParsedDateValue | null {\n\treturn parseDateValueInternal(value);\n}\n\n/**\n * Универсально парсит вход даты/времени из `unknown` как абсолютный instant.\n *\n * Явные timezone в ISO/OData и Unix timestamp преобразуются в `Date`\n * с сохранением момента времени; форматы без timezone остаются календарными.\n */\nexport function parseDateValueTZ(value: unknown): ParsedDateValue | null {\n\treturn parseDateValueInternal(value, { mode: \"instant\" });\n}\n\n/**\n * Преобразует результат парсинга к `Date`, в том числе для duration-значений.\n *\n * Для duration используется та же \"плавающая\" календарная семантика, что и для timestamp:\n * UTC-компоненты пересобираются в локальный `Date`, чтобы не появлялся timezone-сдвиг.\n */\nfunction coerceParsedDateToDate(value: ParsedDateValue | null): Date | null {\n\tif (!value) return null;\n\tif (value.kind === \"date-time\") return value.date;\n\n\tconst durationDate = new Date(value.durationMs);\n\tif (Number.isNaN(durationDate.getTime())) return null;\n\n\treturn cloneUtcCalendarDate(durationDate);\n}\n\n/**\n * Универсально парсит вход и всегда возвращает `Date | null`.\n */\nexport function parseDate(value: unknown): Date | null {\n\treturn coerceParsedDateToDate(parseDateValue(value));\n}\n\n/**\n * Универсально парсит вход с учётом timezone и возвращает `Date | null`.\n */\nexport function parseDateTZ(value: unknown): Date | null {\n\treturn coerceParsedDateToDate(parseDateValueTZ(value));\n}\n","import {\n\ttype BaseMetaType,\n\ttype BooleanMetaType,\n\ttype DateMetaType,\n\ttype IntegerMetaType,\n\ttype NumericMetaType,\n\ttype ScalarMetaType\n} from \"./metadataTypes\";\n\n/** Определяет базовый тип поля для UI и Excel без инициализации протокольных модулей. */\nexport function getBaseTypeFromScalarType<T extends ScalarMetaType>(type: T): BaseMetaType {\n\tif (isScalarBooleanType(type)) return \"boolean\";\n\tif (isScalarNumericType(type)) return \"number\";\n\tif (isScalarDateType(type)) return \"date\";\n\treturn \"string\";\n}\n\nexport function isScalarBooleanType(type: ScalarMetaType | undefined): type is BooleanMetaType {\n\treturn type === \"boolean\";\n}\n\nexport function isScalarNumericType(type: ScalarMetaType | undefined): type is NumericMetaType {\n\treturn type === \"byte\" || type === \"int\" || type === \"long\" || type === \"float\" || type === \"decimal\" || type === \"double\";\n}\n\nexport function isScalarIntegerType(type: ScalarMetaType | undefined): type is IntegerMetaType {\n\treturn type === \"byte\" || type === \"int\" || type === \"long\";\n}\n\nexport function isScalarDateType(type: ScalarMetaType | undefined): type is DateMetaType {\n\treturn type === \"datetime\" || type === \"datetimeOffset\" || type === \"time\";\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as e } from "./formulas-BXT_XBWI.js";
|
|
2
|
-
import {
|
|
2
|
+
import { A as t } from "./scalarTypeClassification-BZcFmIyR.js";
|
|
3
3
|
var n = {
|
|
4
4
|
decimals: 1,
|
|
5
5
|
decimalSeparator: ",",
|
|
@@ -605,4 +605,4 @@ function R(e) {
|
|
|
605
605
|
//#endregion
|
|
606
606
|
export { d as S, n as _, C as a, l as b, S as c, x as d, p as f, r as g, f as h, T as i, g as l, m, L as n, D as o, h as p, F as r, E as s, R as t, _ as u, s as v, u as x, c as y };
|
|
607
607
|
|
|
608
|
-
//# sourceMappingURL=validate-
|
|
608
|
+
//# sourceMappingURL=validate-DsUR-bFF.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-CEQHqevt.js","names":[],"sources":["../../src/formatters/number/presets.ts","../../src/formatters/pipeline/clone.ts","../../src/formatters/rowBased/context.ts","../../src/formatters/rowBased/registry.ts","../../src/formatters/pipeline/validate.ts"],"sourcesContent":["import type { NumberFormatPreset, NumberFormatPresetConfig } from \"./types\";\n\n/** Символ группировки из ru-RU (U+00A0 или U+202F в зависимости от среды) */\nconst ruGroupChar = new Intl.NumberFormat(\"ru-RU\").formatToParts(1000).find((p) => p.type === \"group\")?.value ?? \"\\u00A0\";\n\n/** Значения по умолчанию — совпадают с ru-RU форматированием */\nexport const NUMBER_FORMAT_DEFAULTS: Omit<NumberFormatPreset, \"name\"> = {\n\tdecimals: 1,\n\tdecimalSeparator: \",\",\n\tgrouping: true,\n\tgroupingSeparator: ruGroupChar,\n\tgroupingSize: 3\n};\n\nexport const DEFAULT_NUMBER_PRESET_NAMES = Object.freeze({\n\tinteger: \"integer\",\n\tdecimal: \"decimal\",\n\tdecimal2: \"decimal-2\",\n\tdecimal3: \"decimal-3\",\n\tcurrency: \"currency\",\n\tprice: \"price\",\n\tpercent: \"percent\",\n\ttonnage: \"tonnage\",\n\tcompactCurrency: \"compact-currency\",\n\tcompactCurrencyRound: \"compact-currency-round\",\n\tcompactPercent: \"compact-percent\",\n\tcompactPercentRound: \"compact-percent-round\",\n\tcompactTonnage: \"compact-tonnage\",\n\tcompactTonnageRound: \"compact-tonnage-round\"\n});\n\n/**\n * Типовые предустановки числового форматирования.\n *\n * Compact-пресеты без суффикса сохраняют консервативное усечение, а парные\n * `*-round` дают явный математический режим без runtime-переопределения пресета.\n * Недостающие поля каждой предустановки заполняются из `NUMBER_FORMAT_DEFAULTS`.\n */\nconst BUILTIN: NumberFormatPresetConfig[] = [\n\t{ name: \"integer\", decimals: 0, decimalSeparator: \"\" },\n\t{ name: \"decimal\" },\n\t{ name: \"decimal-2\", decimals: 2 },\n\t{ name: \"decimal-3\", decimals: 3 },\n\t{ name: \"currency\", decimals: 0, decimalSeparator: \"\" },\n\t{ name: \"price\", decimals: 0, decimalSeparator: \"\" },\n\t{ name: \"percent\", decimals: 2 },\n\t{ name: \"tonnage\" },\n\t{ name: \"compact-currency\", decimals: 0, decimalSeparator: \"\", compact: {} },\n\t{ name: \"compact-currency-round\", decimals: 0, decimalSeparator: \"\", compact: { roundingMode: \"round\" } },\n\t{ name: \"compact-percent\", decimals: 2, compact: { maxDecimals: 2 } },\n\t{ name: \"compact-percent-round\", decimals: 2, compact: { maxDecimals: 2, roundingMode: \"round\" } },\n\t{ name: \"compact-tonnage\", compact: { maxDecimals: 1 } },\n\t{ name: \"compact-tonnage-round\", compact: { maxDecimals: 1, roundingMode: \"round\" } }\n];\n\nconst registry = new Map<string, NumberFormatPreset>();\n\nfunction init(): void {\n\tfor (const cfg of BUILTIN) {\n\t\tregistry.set(cfg.name, { ...NUMBER_FORMAT_DEFAULTS, ...cfg });\n\t}\n}\n\ninit();\n\nexport function getNumberPreset(name: string): NumberFormatPreset | undefined {\n\treturn registry.get(name);\n}\n\nexport function getNumberPresetNames(): string[] {\n\treturn Array.from(registry.keys());\n}\n\n/** Зарегистрировать или перезаписать предустановку. Недостающие поля берутся из FORMAT_DEFAULTS. */\nexport function registerNumberPreset(config: NumberFormatPresetConfig): NumberFormatPreset {\n\tconst preset: NumberFormatPreset = { ...NUMBER_FORMAT_DEFAULTS, ...config };\n\tregistry.set(preset.name, preset);\n\treturn preset;\n}\n\n/** Сбросить реестр к начальному состоянию (только типовые предустановки) */\nexport function resetNumberPresets(): void {\n\tregistry.clear();\n\tinit();\n}\n\nexport function resolveNumberPreset(presetOrName: string | NumberFormatPreset): NumberFormatPreset {\n\tif (typeof presetOrName !== \"string\") return presetOrName;\n\n\tconst found = getNumberPreset(presetOrName);\n\tif (!found) throw new Error(`Предустановка \"${presetOrName}\" не найдена`);\n\n\treturn found;\n}\n","import type {\n\tFormattersPipelineConfig,\n\tFormattersPipelineGraph,\n\tFormattersPipelineNode,\n\tFormattersPipelineNormalizeLeadingZerosConfig,\n\tFormattersPipelinePlan,\n\tFormattersPipelineResolveValueStateConfig,\n\tFormattersPipelineRowBasedOverrideConfig,\n\tFormattersPipelineStep,\n\tFormattersPipelineTypedValueFormatConfig\n} from \"./types\";\n\nexport function cloneTypedValueFormatConfig(\n\tconfig: FormattersPipelineTypedValueFormatConfig | undefined\n): FormattersPipelineTypedValueFormatConfig | undefined {\n\treturn config ? { ...config } : undefined;\n}\n\nexport function cloneNormalizeLeadingZerosConfig(\n\tconfig: FormattersPipelineNormalizeLeadingZerosConfig | undefined\n): FormattersPipelineNormalizeLeadingZerosConfig | undefined {\n\treturn config ? { ...config } : undefined;\n}\n\nexport function cloneRowBasedOverrideConfig(config: FormattersPipelineRowBasedOverrideConfig): FormattersPipelineRowBasedOverrideConfig {\n\treturn config.mode === \"formula\"\n\t\t? { ...config, dependencyIds: config.dependencyIds ? [...config.dependencyIds] : undefined }\n\t\t: { ...config };\n}\n\nexport function cloneResolveValueStateConfig(config: FormattersPipelineResolveValueStateConfig): FormattersPipelineResolveValueStateConfig {\n\treturn {\n\t\tresolver:\n\t\t\tconfig.resolver.kind === \"fixed\"\n\t\t\t\t? {\n\t\t\t\t\t\tkind: \"fixed\",\n\t\t\t\t\t\tentries: { ...config.resolver.entries },\n\t\t\t\t\t\tfallbackState: config.resolver.fallbackState\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\tkind: \"threshold\",\n\t\t\t\t\t\tthresholds: config.resolver.thresholds.map((item) => (typeof item === \"number\" ? item : { ...item })),\n\t\t\t\t\t\tstates: [...config.resolver.states],\n\t\t\t\t\t\tinvalidState: config.resolver.invalidState\n\t\t\t\t\t},\n\t\tvalueSource:\n\t\t\tconfig.valueSource?.kind === \"formula\"\n\t\t\t\t? { ...config.valueSource, dependencyIds: [...config.valueSource.dependencyIds] }\n\t\t\t\t: config.valueSource\n\t\t\t\t\t? { ...config.valueSource }\n\t\t\t\t\t: undefined,\n\t\ticon: config.icon ? { ...config.icon } : undefined\n\t};\n}\n\nexport function cloneFormatterPipelinePlanStep(step: FormattersPipelineStep): FormattersPipelineStep {\n\tswitch (step.type) {\n\t\tcase \"typedValueFormat\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tconfig: cloneTypedValueFormatConfig(step.config)\n\t\t\t};\n\t\tcase \"normalizeLeadingZeros\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tconfig: cloneNormalizeLeadingZerosConfig(step.config)\n\t\t\t};\n\t\tcase \"rowBasedOverride\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tconfig: cloneRowBasedOverrideConfig(step.config)\n\t\t\t};\n\t\tcase \"resolveValueState\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tconfig: cloneResolveValueStateConfig(step.config)\n\t\t\t};\n\t\tdefault: {\n\t\t\tconst checker: never = step;\n\t\t\tvoid checker;\n\t\t}\n\t}\n\n\tthrow new Error(`Недопустимый тип '${(step as Record<string, unknown>)?.type}' для шага FormatterPipeline`);\n}\n\nexport function cloneFormatterPipelinePlanStepToNode(\n\tstep: FormattersPipelineStep,\n\tposition: { x: number; y: number }\n): FormattersPipelineNode {\n\tswitch (step.type) {\n\t\tcase \"typedValueFormat\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tposition: { ...position },\n\t\t\t\tconfig: cloneTypedValueFormatConfig(step.config)\n\t\t\t};\n\t\tcase \"normalizeLeadingZeros\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tposition: { ...position },\n\t\t\t\tconfig: cloneNormalizeLeadingZerosConfig(step.config)\n\t\t\t};\n\t\tcase \"rowBasedOverride\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tposition: { ...position },\n\t\t\t\tconfig: cloneRowBasedOverrideConfig(step.config)\n\t\t\t};\n\t\tcase \"resolveValueState\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tposition: { ...position },\n\t\t\t\tconfig: cloneResolveValueStateConfig(step.config)\n\t\t\t};\n\t\tdefault: {\n\t\t\tconst checker: never = step;\n\t\t\tvoid checker;\n\t\t}\n\t}\n\n\tthrow new Error(`Недопустимый тип '${(step as Record<string, unknown>)?.type}' для шага FormatterPipeline`);\n}\n\nfunction cloneNode(node: FormattersPipelineNode): FormattersPipelineNode {\n\tswitch (node.type) {\n\t\tcase \"source\":\n\t\tcase \"sink\":\n\t\t\treturn {\n\t\t\t\t...node,\n\t\t\t\tposition: { ...node.position }\n\t\t\t};\n\t\tdefault:\n\t\t\treturn cloneFormatterPipelinePlanStepToNode(node, node.position);\n\t}\n}\n\nfunction cloneGraph(graph: FormattersPipelineGraph): FormattersPipelineGraph {\n\treturn {\n\t\tnodes: graph.nodes.map(cloneNode),\n\t\tedges: graph.edges.map((edge) => ({ ...edge })),\n\t\tviewport: graph.viewport ? { ...graph.viewport } : undefined\n\t};\n}\n\nfunction clonePlan(plan: FormattersPipelinePlan): FormattersPipelinePlan {\n\treturn {\n\t\tsteps: plan.steps.map(cloneFormatterPipelinePlanStep)\n\t};\n}\n\n/**\n * Возвращает полную копию конфигурации pipeline для безопасного хранения в сторе.\n */\nexport function cloneFormattersPipelineConfig(config: FormattersPipelineConfig | undefined): FormattersPipelineConfig | undefined {\n\tif (!config) return undefined;\n\n\tconst version = config.version;\n\tconst graph = config.graph ? cloneGraph(config.graph) : undefined;\n\tconst plan = config.plan ? clonePlan(config.plan) : undefined;\n\n\treturn { version, graph, plan };\n}\n","import { parseNumber } from \"../number\";\n\nimport type { RowBasedFormatterContext, RowBasedFormatterContextInstrumentation } from \"./types\";\n\nexport function createRowBasedFormatterContext(args: {\n\trowData: Record<string, unknown>;\n\trawValue: unknown;\n\tcolumnId: string;\n\tkeys?: readonly string[];\n\tinstrumentation?: RowBasedFormatterContextInstrumentation;\n}): RowBasedFormatterContext {\n\t// TODO: duplicate createTableFormulaContext src\\shared\\lib\\formulas\\execute.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\tconst readNum = (index: number): number => {\n\t\tconst key = readKey(index);\n\t\tif (!key) return 0;\n\t\treturn parseNumber(args.rowData[key]);\n\t};\n\n\treturn {\n\t\trowData: args.rowData,\n\t\trawValue: args.rawValue,\n\t\tcolumnId: args.columnId,\n\t\tkey: readKey,\n\t\tvalue: readValue,\n\t\tnum: readNum\n\t};\n}\n","import type { RowBasedFormatterDefinition } from \"./types\";\n\nexport type RowBasedFormatterRegistry = Readonly<{\n\tlist: readonly RowBasedFormatterDefinition[];\n\tbyId: ReadonlyMap<string, RowBasedFormatterDefinition>;\n}>;\n\n/**\n * Создаёт реестр формул для подмены значения в групповой строке.\n */\nexport function createRowBasedFormatterRegistry(definitions: readonly RowBasedFormatterDefinition[]): RowBasedFormatterRegistry {\n\tconst byId = new Map<string, RowBasedFormatterDefinition>();\n\tconst list: RowBasedFormatterDefinition[] = [];\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 для RowBasedFormatter не может быть пустым\");\n\t\t}\n\n\t\tif (byId.has(normalizedId)) {\n\t\t\tthrow new Error(`Найден дублирующийся formulaId в RowBasedFormatter: ${normalizedId}`);\n\t\t}\n\n\t\tconst normalizedDefinition: RowBasedFormatterDefinition = 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});\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 rowBasedFormatterRegistry = createRowBasedFormatterRegistry([]);\n\n/**\n * Устанавливает реестр row-based форматтеров host-приложения.\n *\n * Pipeline использует этот реестр при валидации и компиляции formula-режима,\n * поэтому конфигурация должна завершиться до первого построения runtime.\n */\nexport function configureRowBasedFormatterRegistry(registry: RowBasedFormatterRegistry): void {\n\trowBasedFormatterRegistry = registry;\n}\n\n/**\n * Возвращает список доступных формул для групповой подмены.\n */\nexport function getRowBasedFormatterList(): readonly RowBasedFormatterDefinition[] {\n\treturn rowBasedFormatterRegistry.list;\n}\n\n/**\n * Возвращает формулу по id.\n */\nexport function getRowBasedFormatterById(formulaId: string | undefined): RowBasedFormatterDefinition | undefined {\n\tconst normalizedId = formulaId?.trim();\n\tif (!normalizedId) return undefined;\n\treturn rowBasedFormatterRegistry.byId.get(normalizedId);\n}\n","import { validateTableFormulaDependencies } from \"../../formulas\";\nimport { getNumberPreset } from \"../number\";\nimport { createRowBasedFormatterContext, getRowBasedFormatterById } from \"../rowBased\";\n\nimport { cloneResolveValueStateConfig } from \"./clone\";\n\nimport type {\n\tFormattersPipelineConfig,\n\tFormattersPipelineEdge,\n\tFormattersPipelineGraph,\n\tFormattersPipelineNode,\n\tFormattersPipelinePlan,\n\tFormattersPipelineRowBasedOverrideFormulaConfig,\n\tFormattersPipelineStep,\n\tFormattersPipelineValueStateFormulaSource\n} from \"./types\";\n\nexport type FormattersPipelineValidationCode =\n\t| \"config_not_defined\"\n\t| \"unsupported_version\"\n\t| \"graph_or_plan_required\"\n\t| \"node_id_duplicate\"\n\t| \"edge_id_duplicate\"\n\t| \"edge_node_not_found\"\n\t| \"source_count_invalid\"\n\t| \"sink_count_invalid\"\n\t| \"source_incoming_invalid\"\n\t| \"sink_outgoing_invalid\"\n\t| \"node_degree_invalid\"\n\t| \"path_broken\"\n\t| \"path_cycle_detected\"\n\t| \"path_disconnected_nodes\"\n\t| \"step_id_duplicate\"\n\t| \"step_resolve_value_state_multiple\"\n\t| \"step_typed_value_format_multiple\"\n\t| \"step_row_based_override_multiple\"\n\t| \"step_normalize_leading_zeros_multiple\"\n\t| \"step_typed_before_value_state\"\n\t| \"step_row_based_override_field_key_empty\"\n\t| \"step_row_based_override_formula_id_empty\"\n\t| \"step_row_based_override_formula_not_found\"\n\t| \"step_row_based_override_dependency_index_out_of_range\"\n\t| \"step_row_based_override_unused_dependencies\"\n\t| \"step_row_based_override_formula_does_not_use_dependencies\"\n\t| \"step_row_based_override_formula_runtime_error\"\n\t| \"step_value_state_formula_id_empty\"\n\t| \"step_value_state_formula_not_found\"\n\t| \"step_value_state_dependency_id_empty\"\n\t| \"step_value_state_dependency_index_out_of_range\"\n\t| \"step_value_state_unused_dependencies\"\n\t| \"step_value_state_formula_does_not_use_dependencies\"\n\t| \"step_value_state_formula_runtime_error\"\n\t| \"step_threshold_states_count_invalid\"\n\t| \"step_value_hidden_without_icon\"\n\t| \"step_typed_value_format_preset_empty\"\n\t| \"step_typed_value_format_preset_not_found\";\n\nexport type FormattersPipelineValidationMessage = {\n\tcode: FormattersPipelineValidationCode;\n\tmessage: string;\n};\n\nexport type FormattersPipelineValidationResult = {\n\tok: boolean;\n\terrors: FormattersPipelineValidationMessage[];\n\twarnings: FormattersPipelineValidationMessage[];\n\tplan?: FormattersPipelinePlan;\n};\n\ntype MutableValidationState = {\n\terrors: FormattersPipelineValidationMessage[];\n\twarnings: FormattersPipelineValidationMessage[];\n};\n\nfunction pushError(state: MutableValidationState, code: FormattersPipelineValidationCode, message: string) {\n\tstate.errors.push({ code, message });\n}\n\nfunction pushWarning(state: MutableValidationState, code: FormattersPipelineValidationCode, message: string) {\n\tstate.warnings.push({ code, message });\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\nfunction validateRowBasedOverrideFormulaConfig(config: FormattersPipelineRowBasedOverrideFormulaConfig, state: MutableValidationState) {\n\tif (!config.formulaId.trim()) {\n\t\tpushError(state, \"step_row_based_override_formula_id_empty\", \"Для rowBasedOverride (formula) необходимо заполнить formulaId.\");\n\t\treturn;\n\t}\n\n\tconst formula = getRowBasedFormatterById(config.formulaId);\n\tconst dependencies = [...(config.dependencyIds ?? [])];\n\n\tif (!formula) {\n\t\tpushError(state, \"step_row_based_override_formula_not_found\", \"Формула rowBasedOverride не найдена в реестре.\");\n\t\treturn;\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 = createRowBasedFormatterContext({\n\t\t\t\trowData: sampleRowData,\n\t\t\t\trawValue: 100,\n\t\t\t\tcolumnId: \"__validation__\",\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\tpushError(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_dependency_index_out_of_range\",\n\t\t\t`Формула rowBasedOverride обращается к несуществующим индексам. Минимально требуется зависимостей: ${requiredDependencyCount}, выбрано: ${dependencies.length}.`\n\t\t);\n\t}\n\n\tif (sortedUsedIndexes.length === 0) {\n\t\tpushWarning(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_formula_does_not_use_dependencies\",\n\t\t\t\"Формула rowBasedOverride не использует dependencyIds.\"\n\t\t);\n\t}\n\n\tconst unusedDependencies = dependencies.filter((_, index) => !usedIndexes.has(index));\n\tif (unusedDependencies.length > 0) {\n\t\tpushWarning(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_unused_dependencies\",\n\t\t\t`Выбраны, но не используются формулой rowBasedOverride: ${unusedDependencies.join(\", \")}.`\n\t\t);\n\t}\n\n\tif (runtimeErrorCount > 0) {\n\t\tpushWarning(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_formula_runtime_error\",\n\t\t\t\"На тестовых данных формула rowBasedOverride завершилась с ошибкой.\"\n\t\t);\n\t}\n}\n\n/**\n * Pipeline проверяет контракт формулы и индексы, а наличие полей в конкретном\n * источнике данных проверяет потребитель через collectRuntimeFieldDependencyIds.\n */\nfunction validateValueStateFormulaSource(source: FormattersPipelineValueStateFormulaSource, state: MutableValidationState) {\n\tif (!source.formulaId.trim()) {\n\t\tpushError(state, \"step_value_state_formula_id_empty\", \"Для источника состояния необходимо выбрать формулу.\");\n\t\treturn;\n\t}\n\n\tif (source.dependencyIds.some((dependencyId) => !dependencyId.trim())) {\n\t\tpushError(state, \"step_value_state_dependency_id_empty\", \"Зависимость формулы состояния не может иметь пустой id.\");\n\t\treturn;\n\t}\n\n\tconst validation = validateTableFormulaDependencies({\n\t\tformulaId: source.formulaId,\n\t\tdependencies: source.dependencyIds,\n\t\tavailableColumnIds: source.dependencyIds\n\t});\n\tfor (const error of validation.errors) {\n\t\tif (error.code === \"formula_not_found\") {\n\t\t\tpushError(state, \"step_value_state_formula_not_found\", \"Формула источника состояния не найдена в реестре.\");\n\t\t} else if (error.code === \"dependency_index_out_of_range\") {\n\t\t\tpushError(state, \"step_value_state_dependency_index_out_of_range\", error.message);\n\t\t}\n\t}\n\tfor (const warning of validation.warnings) {\n\t\tswitch (warning.code) {\n\t\t\tcase \"unused_dependencies\":\n\t\t\t\tpushWarning(state, \"step_value_state_unused_dependencies\", warning.message);\n\t\t\t\tbreak;\n\t\t\tcase \"formula_does_not_use_dependencies\":\n\t\t\t\tpushWarning(state, \"step_value_state_formula_does_not_use_dependencies\", warning.message);\n\t\t\t\tbreak;\n\t\t\tcase \"formula_runtime_error\":\n\t\t\t\tpushWarning(state, \"step_value_state_formula_runtime_error\", warning.message);\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\nfunction validateStepDefinitions(steps: readonly FormattersPipelineStep[], state: MutableValidationState) {\n\tconst stepIdSet = new Set<string>();\n\tconst counters = {\n\t\tnormalizeLeadingZeros: 0,\n\t\trowBasedOverride: 0,\n\t\tresolveValueState: 0,\n\t\ttypedValueFormat: 0\n\t};\n\n\tfor (const step of steps) {\n\t\tconst normalizedId = step.id.trim();\n\t\tif (!normalizedId) {\n\t\t\tpushError(state, \"step_id_duplicate\", \"Шаг pipeline не может иметь пустой id.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (stepIdSet.has(normalizedId)) {\n\t\t\tpushError(state, \"step_id_duplicate\", `Найден дублирующийся id шага pipeline: ${normalizedId}.`);\n\t\t}\n\t\tstepIdSet.add(normalizedId);\n\n\t\tswitch (step.type) {\n\t\t\tcase \"normalizeLeadingZeros\":\n\t\t\t\tcounters.normalizeLeadingZeros += 1;\n\t\t\t\tbreak;\n\t\t\tcase \"rowBasedOverride\":\n\t\t\t\tcounters.rowBasedOverride += 1;\n\n\t\t\t\tif (step.config.mode === \"field\" && !step.config.fieldKey.trim()) {\n\t\t\t\t\tpushError(\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\"step_row_based_override_field_key_empty\",\n\t\t\t\t\t\t\"Для rowBasedOverride (field) необходимо заполнить fieldKey.\"\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (step.config.mode === \"formula\") {\n\t\t\t\t\tvalidateRowBasedOverrideFormulaConfig(step.config, state);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"resolveValueState\":\n\t\t\t\tcounters.resolveValueState += 1;\n\t\t\t\tif (step.config.valueSource?.kind === \"formula\") {\n\t\t\t\t\tvalidateValueStateFormulaSource(step.config.valueSource, state);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tstep.config.resolver.kind === \"threshold\" &&\n\t\t\t\t\tstep.config.resolver.states.length !== step.config.resolver.thresholds.length + 1\n\t\t\t\t) {\n\t\t\t\t\tpushError(\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\"step_threshold_states_count_invalid\",\n\t\t\t\t\t\t\"Для threshold-резолвера количество states должно быть равно thresholds + 1.\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"typedValueFormat\":\n\t\t\t\tcounters.typedValueFormat += 1;\n\t\t\t\tif (step.config?.numberPresetName !== undefined) {\n\t\t\t\t\tconst normalizedPresetName = step.config.numberPresetName.trim();\n\t\t\t\t\tif (!normalizedPresetName) {\n\t\t\t\t\t\tpushError(state, \"step_typed_value_format_preset_empty\", \"Для typedValueFormat указан пустой numberPresetName.\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!getNumberPreset(normalizedPresetName)) {\n\t\t\t\t\t\tpushError(\n\t\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\t\"step_typed_value_format_preset_not_found\",\n\t\t\t\t\t\t\t`Для typedValueFormat указан неизвестный пресет: ${normalizedPresetName}.`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (counters.normalizeLeadingZeros > 1) {\n\t\tpushError(state, \"step_normalize_leading_zeros_multiple\", \"В pipeline может быть только один шаг normalizeLeadingZeros.\");\n\t}\n\n\tif (counters.rowBasedOverride > 1) {\n\t\tpushError(state, \"step_row_based_override_multiple\", \"В pipeline может быть только один шаг rowBasedOverride.\");\n\t}\n\n\tif (counters.resolveValueState > 1) {\n\t\tpushError(state, \"step_resolve_value_state_multiple\", \"В pipeline может быть только один шаг resolveValueState.\");\n\t}\n\n\tif (counters.typedValueFormat > 1) {\n\t\tpushError(state, \"step_typed_value_format_multiple\", \"В pipeline может быть только один шаг typedValueFormat.\");\n\t}\n\n\tconst resolveIndex = steps.findIndex((step) => step.type === \"resolveValueState\");\n\tconst typedIndex = steps.findIndex((step) => step.type === \"typedValueFormat\");\n\tif (resolveIndex !== -1 && typedIndex !== -1 && typedIndex < resolveIndex) {\n\t\tpushError(state, \"step_typed_before_value_state\", \"Шаг typedValueFormat не может выполняться до шага resolveValueState.\");\n\t}\n\n\tfor (const step of steps) {\n\t\tif (step.type !== \"resolveValueState\") continue;\n\t\tif (!step.config.icon?.enabled && step.config.icon?.showValue === false) {\n\t\t\tpushWarning(\n\t\t\t\tstate,\n\t\t\t\t\"step_value_hidden_without_icon\",\n\t\t\t\t\"Для resolveValueState установлено showValue=false при выключенной иконке: значение не будет отображаться.\"\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Валидация облегчённого плана pipeline.\n */\nexport function validateFormattersPipelinePlan(plan: FormattersPipelinePlan): FormattersPipelineValidationResult {\n\tconst state: MutableValidationState = { errors: [], warnings: [] };\n\n\tvalidateStepDefinitions(plan.steps, state);\n\n\treturn {\n\t\tok: state.errors.length === 0,\n\t\terrors: state.errors,\n\t\twarnings: state.warnings,\n\t\tplan: state.errors.length === 0 ? { steps: [...plan.steps] } : undefined\n\t};\n}\n\nfunction buildLinearPathFromGraph(\n\tnodes: readonly FormattersPipelineNode[],\n\tedges: readonly FormattersPipelineEdge[],\n\tstate: MutableValidationState\n): string[] | undefined {\n\tconst nodeById = new Map(nodes.map((node) => [node.id, node]));\n\tconst outgoing = new Map<string, string[]>();\n\tconst incoming = new Map<string, string[]>();\n\n\tfor (const node of nodes) {\n\t\toutgoing.set(node.id, []);\n\t\tincoming.set(node.id, []);\n\t}\n\n\tfor (const edge of edges) {\n\t\tconst source = edge.source.trim();\n\t\tconst target = edge.target.trim();\n\t\tif (!nodeById.has(source) || !nodeById.has(target)) {\n\t\t\tpushError(state, \"edge_node_not_found\", `Ребро ${edge.id} ссылается на несуществующий узел: ${source} -> ${target}.`);\n\t\t\tcontinue;\n\t\t}\n\n\t\toutgoing.get(source)?.push(target);\n\t\tincoming.get(target)?.push(source);\n\t}\n\n\tconst sources = nodes.filter((node) => node.type === \"source\");\n\tconst sinks = nodes.filter((node) => node.type === \"sink\");\n\n\tif (sources.length !== 1) {\n\t\tpushError(state, \"source_count_invalid\", \"В графе должен быть ровно один узел source.\");\n\t}\n\tif (sinks.length !== 1) {\n\t\tpushError(state, \"sink_count_invalid\", \"В графе должен быть ровно один узел sink.\");\n\t}\n\tif (state.errors.length > 0) return undefined;\n\n\tconst sourceNodeId = sources[0]!.id;\n\tconst sinkNodeId = sinks[0]!.id;\n\n\tfor (const node of nodes) {\n\t\tconst inDegree = incoming.get(node.id)?.length ?? 0;\n\t\tconst outDegree = outgoing.get(node.id)?.length ?? 0;\n\n\t\tif (node.type === \"source\") {\n\t\t\tif (inDegree !== 0) {\n\t\t\t\tpushError(state, \"source_incoming_invalid\", \"Узел source не должен иметь входящих рёбер.\");\n\t\t\t}\n\t\t\tif (outDegree !== 1) {\n\t\t\t\tpushError(state, \"node_degree_invalid\", \"Узел source должен иметь ровно одно исходящее ребро.\");\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (node.type === \"sink\") {\n\t\t\tif (outDegree !== 0) {\n\t\t\t\tpushError(state, \"sink_outgoing_invalid\", \"Узел sink не должен иметь исходящих рёбер.\");\n\t\t\t}\n\t\t\tif (inDegree !== 1) {\n\t\t\t\tpushError(state, \"node_degree_invalid\", \"Узел sink должен иметь ровно одно входящее ребро.\");\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (inDegree !== 1 || outDegree !== 1) {\n\t\t\tpushError(\n\t\t\t\tstate,\n\t\t\t\t\"node_degree_invalid\",\n\t\t\t\t`Узел ${node.id} должен иметь ровно одно входящее и одно исходящее ребро для линейного pipeline.`\n\t\t\t);\n\t\t}\n\t}\n\n\tif (state.errors.length > 0) return undefined;\n\n\tconst visited = new Set<string>();\n\tconst path: string[] = [];\n\tlet cursor = sourceNodeId;\n\n\twhile (true) {\n\t\tif (visited.has(cursor)) {\n\t\t\tpushError(state, \"path_cycle_detected\", \"В графе pipeline обнаружен цикл.\");\n\t\t\treturn undefined;\n\t\t}\n\t\tvisited.add(cursor);\n\t\tpath.push(cursor);\n\n\t\tif (cursor === sinkNodeId) {\n\t\t\tbreak;\n\t\t}\n\n\t\tconst nextCandidates = outgoing.get(cursor) ?? [];\n\t\tif (nextCandidates.length !== 1) {\n\t\t\tpushError(state, \"path_broken\", \"Не удалось построить линейный путь от source к sink.\");\n\t\t\treturn undefined;\n\t\t}\n\n\t\tcursor = nextCandidates[0]!;\n\t}\n\n\tif (visited.size !== nodes.length) {\n\t\tpushError(state, \"path_disconnected_nodes\", \"Граф содержит узлы, которые не входят в линейный путь source -> sink.\");\n\t\treturn undefined;\n\t}\n\n\treturn path;\n}\n\n/**\n * Валидация графа pipeline и построение линейного плана исполнения.\n */\nexport function validateFormattersPipelineGraph(graph: FormattersPipelineGraph): FormattersPipelineValidationResult {\n\tconst state: MutableValidationState = { errors: [], warnings: [] };\n\n\tif (!graph.nodes.length) {\n\t\tpushError(state, \"path_broken\", \"Граф pipeline не содержит узлов.\");\n\t\treturn { ok: false, errors: state.errors, warnings: state.warnings };\n\t}\n\n\tconst nodeById = new Map<string, FormattersPipelineNode>();\n\tfor (const node of graph.nodes) {\n\t\tconst normalizedId = node.id.trim();\n\t\tif (!normalizedId) {\n\t\t\tpushError(state, \"node_id_duplicate\", \"Узел pipeline не может иметь пустой id.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (nodeById.has(normalizedId)) {\n\t\t\tpushError(state, \"node_id_duplicate\", `Найден дублирующийся id узла pipeline: ${normalizedId}.`);\n\t\t\tcontinue;\n\t\t}\n\n\t\tnodeById.set(normalizedId, node);\n\t}\n\n\tconst edgeIdSet = new Set<string>();\n\tfor (const edge of graph.edges) {\n\t\tconst normalizedEdgeId = edge.id.trim();\n\t\tif (!normalizedEdgeId) {\n\t\t\tpushError(state, \"edge_id_duplicate\", \"Ребро pipeline не может иметь пустой id.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (edgeIdSet.has(normalizedEdgeId)) {\n\t\t\tpushError(state, \"edge_id_duplicate\", `Найден дублирующийся id ребра pipeline: ${normalizedEdgeId}.`);\n\t\t\tcontinue;\n\t\t}\n\n\t\tedgeIdSet.add(normalizedEdgeId);\n\t}\n\n\tif (state.errors.length > 0) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tconst path = buildLinearPathFromGraph(graph.nodes, graph.edges, state);\n\tif (!path) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tconst steps: FormattersPipelineStep[] = [];\n\tfor (const nodeId of path) {\n\t\tconst node = nodeById.get(nodeId);\n\t\tif (!node || node.type === \"source\" || node.type === \"sink\") continue;\n\n\t\tswitch (node.type) {\n\t\t\tcase \"normalizeLeadingZeros\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"normalizeLeadingZeros\",\n\t\t\t\t\tconfig: node.config ? { ...node.config } : undefined\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"rowBasedOverride\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"rowBasedOverride\",\n\t\t\t\t\tconfig:\n\t\t\t\t\t\tnode.config.mode === \"formula\"\n\t\t\t\t\t\t\t? { ...node.config, dependencyIds: node.config.dependencyIds ? [...node.config.dependencyIds] : undefined }\n\t\t\t\t\t\t\t: { ...node.config }\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"resolveValueState\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"resolveValueState\",\n\t\t\t\t\tconfig: cloneResolveValueStateConfig(node.config)\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"typedValueFormat\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"typedValueFormat\",\n\t\t\t\t\tconfig: node.config ? { ...node.config } : undefined\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tvalidateStepDefinitions(steps, state);\n\n\treturn {\n\t\tok: state.errors.length === 0,\n\t\terrors: state.errors,\n\t\twarnings: state.warnings,\n\t\tplan: state.errors.length === 0 ? { steps } : undefined\n\t};\n}\n\n/**\n * Валидация конфигурации pipeline c выбором рабочего плана исполнения.\n *\n * Приоритет источника плана:\n * 1) `plan` из конфигурации;\n * 2) построение плана из `graph`.\n */\nexport function validateFormattersPipelineConfig(config: FormattersPipelineConfig | undefined): FormattersPipelineValidationResult {\n\tconst state: MutableValidationState = { errors: [], warnings: [] };\n\n\tif (!config) {\n\t\tpushError(state, \"config_not_defined\", \"Конфигурация pipeline не задана.\");\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tif (config.version !== 1) {\n\t\tpushError(state, \"unsupported_version\", `Неподдерживаемая версия pipeline: ${String(config.version)}.`);\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tif (!config.plan && !config.graph) {\n\t\tpushError(state, \"graph_or_plan_required\", \"Для pipeline должен быть задан хотя бы один источник: graph или plan.\");\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tif (config.plan) {\n\t\tconst planResult = validateFormattersPipelinePlan(config.plan);\n\t\tstate.errors.push(...planResult.errors);\n\t\tstate.warnings.push(...planResult.warnings);\n\n\t\tif (planResult.ok && planResult.plan) {\n\t\t\treturn {\n\t\t\t\tok: true,\n\t\t\t\terrors: state.errors,\n\t\t\t\twarnings: state.warnings,\n\t\t\t\tplan: planResult.plan\n\t\t\t};\n\t\t}\n\n\t\tif (config.graph) {\n\t\t\tpushWarning(state, \"path_broken\", \"Линейный plan невалиден. Выполнена попытка построить план из graph.\");\n\t\t\tstate.errors.length = 0;\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terrors: state.errors,\n\t\t\t\twarnings: state.warnings\n\t\t\t};\n\t\t}\n\t}\n\n\tif (config.graph) {\n\t\tconst graphResult = validateFormattersPipelineGraph(config.graph);\n\t\treturn {\n\t\t\tok: graphResult.ok,\n\t\t\terrors: [...state.errors, ...graphResult.errors],\n\t\t\twarnings: [...state.warnings, ...graphResult.warnings],\n\t\t\tplan: graphResult.plan\n\t\t};\n\t}\n\n\treturn {\n\t\tok: false,\n\t\terrors: state.errors,\n\t\twarnings: state.warnings\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"validate-DsUR-bFF.js","names":[],"sources":["../../src/formatters/number/presets.ts","../../src/formatters/pipeline/clone.ts","../../src/formatters/rowBased/context.ts","../../src/formatters/rowBased/registry.ts","../../src/formatters/pipeline/validate.ts"],"sourcesContent":["import type { NumberFormatPreset, NumberFormatPresetConfig } from \"./types\";\n\n/** Символ группировки из ru-RU (U+00A0 или U+202F в зависимости от среды) */\nconst ruGroupChar = new Intl.NumberFormat(\"ru-RU\").formatToParts(1000).find((p) => p.type === \"group\")?.value ?? \"\\u00A0\";\n\n/** Значения по умолчанию — совпадают с ru-RU форматированием */\nexport const NUMBER_FORMAT_DEFAULTS: Omit<NumberFormatPreset, \"name\"> = {\n\tdecimals: 1,\n\tdecimalSeparator: \",\",\n\tgrouping: true,\n\tgroupingSeparator: ruGroupChar,\n\tgroupingSize: 3\n};\n\nexport const DEFAULT_NUMBER_PRESET_NAMES = Object.freeze({\n\tinteger: \"integer\",\n\tdecimal: \"decimal\",\n\tdecimal2: \"decimal-2\",\n\tdecimal3: \"decimal-3\",\n\tcurrency: \"currency\",\n\tprice: \"price\",\n\tpercent: \"percent\",\n\ttonnage: \"tonnage\",\n\tcompactCurrency: \"compact-currency\",\n\tcompactCurrencyRound: \"compact-currency-round\",\n\tcompactPercent: \"compact-percent\",\n\tcompactPercentRound: \"compact-percent-round\",\n\tcompactTonnage: \"compact-tonnage\",\n\tcompactTonnageRound: \"compact-tonnage-round\"\n});\n\n/**\n * Типовые предустановки числового форматирования.\n *\n * Compact-пресеты без суффикса сохраняют консервативное усечение, а парные\n * `*-round` дают явный математический режим без runtime-переопределения пресета.\n * Недостающие поля каждой предустановки заполняются из `NUMBER_FORMAT_DEFAULTS`.\n */\nconst BUILTIN: NumberFormatPresetConfig[] = [\n\t{ name: \"integer\", decimals: 0, decimalSeparator: \"\" },\n\t{ name: \"decimal\" },\n\t{ name: \"decimal-2\", decimals: 2 },\n\t{ name: \"decimal-3\", decimals: 3 },\n\t{ name: \"currency\", decimals: 0, decimalSeparator: \"\" },\n\t{ name: \"price\", decimals: 0, decimalSeparator: \"\" },\n\t{ name: \"percent\", decimals: 2 },\n\t{ name: \"tonnage\" },\n\t{ name: \"compact-currency\", decimals: 0, decimalSeparator: \"\", compact: {} },\n\t{ name: \"compact-currency-round\", decimals: 0, decimalSeparator: \"\", compact: { roundingMode: \"round\" } },\n\t{ name: \"compact-percent\", decimals: 2, compact: { maxDecimals: 2 } },\n\t{ name: \"compact-percent-round\", decimals: 2, compact: { maxDecimals: 2, roundingMode: \"round\" } },\n\t{ name: \"compact-tonnage\", compact: { maxDecimals: 1 } },\n\t{ name: \"compact-tonnage-round\", compact: { maxDecimals: 1, roundingMode: \"round\" } }\n];\n\nconst registry = new Map<string, NumberFormatPreset>();\n\nfunction init(): void {\n\tfor (const cfg of BUILTIN) {\n\t\tregistry.set(cfg.name, { ...NUMBER_FORMAT_DEFAULTS, ...cfg });\n\t}\n}\n\ninit();\n\nexport function getNumberPreset(name: string): NumberFormatPreset | undefined {\n\treturn registry.get(name);\n}\n\nexport function getNumberPresetNames(): string[] {\n\treturn Array.from(registry.keys());\n}\n\n/** Зарегистрировать или перезаписать предустановку. Недостающие поля берутся из FORMAT_DEFAULTS. */\nexport function registerNumberPreset(config: NumberFormatPresetConfig): NumberFormatPreset {\n\tconst preset: NumberFormatPreset = { ...NUMBER_FORMAT_DEFAULTS, ...config };\n\tregistry.set(preset.name, preset);\n\treturn preset;\n}\n\n/** Сбросить реестр к начальному состоянию (только типовые предустановки) */\nexport function resetNumberPresets(): void {\n\tregistry.clear();\n\tinit();\n}\n\nexport function resolveNumberPreset(presetOrName: string | NumberFormatPreset): NumberFormatPreset {\n\tif (typeof presetOrName !== \"string\") return presetOrName;\n\n\tconst found = getNumberPreset(presetOrName);\n\tif (!found) throw new Error(`Предустановка \"${presetOrName}\" не найдена`);\n\n\treturn found;\n}\n","import type {\n\tFormattersPipelineConfig,\n\tFormattersPipelineGraph,\n\tFormattersPipelineNode,\n\tFormattersPipelineNormalizeLeadingZerosConfig,\n\tFormattersPipelinePlan,\n\tFormattersPipelineResolveValueStateConfig,\n\tFormattersPipelineRowBasedOverrideConfig,\n\tFormattersPipelineStep,\n\tFormattersPipelineTypedValueFormatConfig\n} from \"./types\";\n\nexport function cloneTypedValueFormatConfig(\n\tconfig: FormattersPipelineTypedValueFormatConfig | undefined\n): FormattersPipelineTypedValueFormatConfig | undefined {\n\treturn config ? { ...config } : undefined;\n}\n\nexport function cloneNormalizeLeadingZerosConfig(\n\tconfig: FormattersPipelineNormalizeLeadingZerosConfig | undefined\n): FormattersPipelineNormalizeLeadingZerosConfig | undefined {\n\treturn config ? { ...config } : undefined;\n}\n\nexport function cloneRowBasedOverrideConfig(config: FormattersPipelineRowBasedOverrideConfig): FormattersPipelineRowBasedOverrideConfig {\n\treturn config.mode === \"formula\"\n\t\t? { ...config, dependencyIds: config.dependencyIds ? [...config.dependencyIds] : undefined }\n\t\t: { ...config };\n}\n\nexport function cloneResolveValueStateConfig(config: FormattersPipelineResolveValueStateConfig): FormattersPipelineResolveValueStateConfig {\n\treturn {\n\t\tresolver:\n\t\t\tconfig.resolver.kind === \"fixed\"\n\t\t\t\t? {\n\t\t\t\t\t\tkind: \"fixed\",\n\t\t\t\t\t\tentries: { ...config.resolver.entries },\n\t\t\t\t\t\tfallbackState: config.resolver.fallbackState\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\tkind: \"threshold\",\n\t\t\t\t\t\tthresholds: config.resolver.thresholds.map((item) => (typeof item === \"number\" ? item : { ...item })),\n\t\t\t\t\t\tstates: [...config.resolver.states],\n\t\t\t\t\t\tinvalidState: config.resolver.invalidState\n\t\t\t\t\t},\n\t\tvalueSource:\n\t\t\tconfig.valueSource?.kind === \"formula\"\n\t\t\t\t? { ...config.valueSource, dependencyIds: [...config.valueSource.dependencyIds] }\n\t\t\t\t: config.valueSource\n\t\t\t\t\t? { ...config.valueSource }\n\t\t\t\t\t: undefined,\n\t\ticon: config.icon ? { ...config.icon } : undefined\n\t};\n}\n\nexport function cloneFormatterPipelinePlanStep(step: FormattersPipelineStep): FormattersPipelineStep {\n\tswitch (step.type) {\n\t\tcase \"typedValueFormat\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tconfig: cloneTypedValueFormatConfig(step.config)\n\t\t\t};\n\t\tcase \"normalizeLeadingZeros\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tconfig: cloneNormalizeLeadingZerosConfig(step.config)\n\t\t\t};\n\t\tcase \"rowBasedOverride\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tconfig: cloneRowBasedOverrideConfig(step.config)\n\t\t\t};\n\t\tcase \"resolveValueState\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tconfig: cloneResolveValueStateConfig(step.config)\n\t\t\t};\n\t\tdefault: {\n\t\t\tconst checker: never = step;\n\t\t\tvoid checker;\n\t\t}\n\t}\n\n\tthrow new Error(`Недопустимый тип '${(step as Record<string, unknown>)?.type}' для шага FormatterPipeline`);\n}\n\nexport function cloneFormatterPipelinePlanStepToNode(\n\tstep: FormattersPipelineStep,\n\tposition: { x: number; y: number }\n): FormattersPipelineNode {\n\tswitch (step.type) {\n\t\tcase \"typedValueFormat\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tposition: { ...position },\n\t\t\t\tconfig: cloneTypedValueFormatConfig(step.config)\n\t\t\t};\n\t\tcase \"normalizeLeadingZeros\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tposition: { ...position },\n\t\t\t\tconfig: cloneNormalizeLeadingZerosConfig(step.config)\n\t\t\t};\n\t\tcase \"rowBasedOverride\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tposition: { ...position },\n\t\t\t\tconfig: cloneRowBasedOverrideConfig(step.config)\n\t\t\t};\n\t\tcase \"resolveValueState\":\n\t\t\treturn {\n\t\t\t\t...step,\n\t\t\t\tposition: { ...position },\n\t\t\t\tconfig: cloneResolveValueStateConfig(step.config)\n\t\t\t};\n\t\tdefault: {\n\t\t\tconst checker: never = step;\n\t\t\tvoid checker;\n\t\t}\n\t}\n\n\tthrow new Error(`Недопустимый тип '${(step as Record<string, unknown>)?.type}' для шага FormatterPipeline`);\n}\n\nfunction cloneNode(node: FormattersPipelineNode): FormattersPipelineNode {\n\tswitch (node.type) {\n\t\tcase \"source\":\n\t\tcase \"sink\":\n\t\t\treturn {\n\t\t\t\t...node,\n\t\t\t\tposition: { ...node.position }\n\t\t\t};\n\t\tdefault:\n\t\t\treturn cloneFormatterPipelinePlanStepToNode(node, node.position);\n\t}\n}\n\nfunction cloneGraph(graph: FormattersPipelineGraph): FormattersPipelineGraph {\n\treturn {\n\t\tnodes: graph.nodes.map(cloneNode),\n\t\tedges: graph.edges.map((edge) => ({ ...edge })),\n\t\tviewport: graph.viewport ? { ...graph.viewport } : undefined\n\t};\n}\n\nfunction clonePlan(plan: FormattersPipelinePlan): FormattersPipelinePlan {\n\treturn {\n\t\tsteps: plan.steps.map(cloneFormatterPipelinePlanStep)\n\t};\n}\n\n/**\n * Возвращает полную копию конфигурации pipeline для безопасного хранения в сторе.\n */\nexport function cloneFormattersPipelineConfig(config: FormattersPipelineConfig | undefined): FormattersPipelineConfig | undefined {\n\tif (!config) return undefined;\n\n\tconst version = config.version;\n\tconst graph = config.graph ? cloneGraph(config.graph) : undefined;\n\tconst plan = config.plan ? clonePlan(config.plan) : undefined;\n\n\treturn { version, graph, plan };\n}\n","import { parseNumber } from \"../number\";\n\nimport type { RowBasedFormatterContext, RowBasedFormatterContextInstrumentation } from \"./types\";\n\nexport function createRowBasedFormatterContext(args: {\n\trowData: Record<string, unknown>;\n\trawValue: unknown;\n\tcolumnId: string;\n\tkeys?: readonly string[];\n\tinstrumentation?: RowBasedFormatterContextInstrumentation;\n}): RowBasedFormatterContext {\n\t// TODO: duplicate createTableFormulaContext src\\shared\\lib\\formulas\\execute.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\tconst readNum = (index: number): number => {\n\t\tconst key = readKey(index);\n\t\tif (!key) return 0;\n\t\treturn parseNumber(args.rowData[key]);\n\t};\n\n\treturn {\n\t\trowData: args.rowData,\n\t\trawValue: args.rawValue,\n\t\tcolumnId: args.columnId,\n\t\tkey: readKey,\n\t\tvalue: readValue,\n\t\tnum: readNum\n\t};\n}\n","import type { RowBasedFormatterDefinition } from \"./types\";\n\nexport type RowBasedFormatterRegistry = Readonly<{\n\tlist: readonly RowBasedFormatterDefinition[];\n\tbyId: ReadonlyMap<string, RowBasedFormatterDefinition>;\n}>;\n\n/**\n * Создаёт реестр формул для подмены значения в групповой строке.\n */\nexport function createRowBasedFormatterRegistry(definitions: readonly RowBasedFormatterDefinition[]): RowBasedFormatterRegistry {\n\tconst byId = new Map<string, RowBasedFormatterDefinition>();\n\tconst list: RowBasedFormatterDefinition[] = [];\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 для RowBasedFormatter не может быть пустым\");\n\t\t}\n\n\t\tif (byId.has(normalizedId)) {\n\t\t\tthrow new Error(`Найден дублирующийся formulaId в RowBasedFormatter: ${normalizedId}`);\n\t\t}\n\n\t\tconst normalizedDefinition: RowBasedFormatterDefinition = 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});\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 rowBasedFormatterRegistry = createRowBasedFormatterRegistry([]);\n\n/**\n * Устанавливает реестр row-based форматтеров host-приложения.\n *\n * Pipeline использует этот реестр при валидации и компиляции formula-режима,\n * поэтому конфигурация должна завершиться до первого построения runtime.\n */\nexport function configureRowBasedFormatterRegistry(registry: RowBasedFormatterRegistry): void {\n\trowBasedFormatterRegistry = registry;\n}\n\n/**\n * Возвращает список доступных формул для групповой подмены.\n */\nexport function getRowBasedFormatterList(): readonly RowBasedFormatterDefinition[] {\n\treturn rowBasedFormatterRegistry.list;\n}\n\n/**\n * Возвращает формулу по id.\n */\nexport function getRowBasedFormatterById(formulaId: string | undefined): RowBasedFormatterDefinition | undefined {\n\tconst normalizedId = formulaId?.trim();\n\tif (!normalizedId) return undefined;\n\treturn rowBasedFormatterRegistry.byId.get(normalizedId);\n}\n","import { validateTableFormulaDependencies } from \"../../formulas\";\nimport { getNumberPreset } from \"../number\";\nimport { createRowBasedFormatterContext, getRowBasedFormatterById } from \"../rowBased\";\n\nimport { cloneResolveValueStateConfig } from \"./clone\";\n\nimport type {\n\tFormattersPipelineConfig,\n\tFormattersPipelineEdge,\n\tFormattersPipelineGraph,\n\tFormattersPipelineNode,\n\tFormattersPipelinePlan,\n\tFormattersPipelineRowBasedOverrideFormulaConfig,\n\tFormattersPipelineStep,\n\tFormattersPipelineValueStateFormulaSource\n} from \"./types\";\n\nexport type FormattersPipelineValidationCode =\n\t| \"config_not_defined\"\n\t| \"unsupported_version\"\n\t| \"graph_or_plan_required\"\n\t| \"node_id_duplicate\"\n\t| \"edge_id_duplicate\"\n\t| \"edge_node_not_found\"\n\t| \"source_count_invalid\"\n\t| \"sink_count_invalid\"\n\t| \"source_incoming_invalid\"\n\t| \"sink_outgoing_invalid\"\n\t| \"node_degree_invalid\"\n\t| \"path_broken\"\n\t| \"path_cycle_detected\"\n\t| \"path_disconnected_nodes\"\n\t| \"step_id_duplicate\"\n\t| \"step_resolve_value_state_multiple\"\n\t| \"step_typed_value_format_multiple\"\n\t| \"step_row_based_override_multiple\"\n\t| \"step_normalize_leading_zeros_multiple\"\n\t| \"step_typed_before_value_state\"\n\t| \"step_row_based_override_field_key_empty\"\n\t| \"step_row_based_override_formula_id_empty\"\n\t| \"step_row_based_override_formula_not_found\"\n\t| \"step_row_based_override_dependency_index_out_of_range\"\n\t| \"step_row_based_override_unused_dependencies\"\n\t| \"step_row_based_override_formula_does_not_use_dependencies\"\n\t| \"step_row_based_override_formula_runtime_error\"\n\t| \"step_value_state_formula_id_empty\"\n\t| \"step_value_state_formula_not_found\"\n\t| \"step_value_state_dependency_id_empty\"\n\t| \"step_value_state_dependency_index_out_of_range\"\n\t| \"step_value_state_unused_dependencies\"\n\t| \"step_value_state_formula_does_not_use_dependencies\"\n\t| \"step_value_state_formula_runtime_error\"\n\t| \"step_threshold_states_count_invalid\"\n\t| \"step_value_hidden_without_icon\"\n\t| \"step_typed_value_format_preset_empty\"\n\t| \"step_typed_value_format_preset_not_found\";\n\nexport type FormattersPipelineValidationMessage = {\n\tcode: FormattersPipelineValidationCode;\n\tmessage: string;\n};\n\nexport type FormattersPipelineValidationResult = {\n\tok: boolean;\n\terrors: FormattersPipelineValidationMessage[];\n\twarnings: FormattersPipelineValidationMessage[];\n\tplan?: FormattersPipelinePlan;\n};\n\ntype MutableValidationState = {\n\terrors: FormattersPipelineValidationMessage[];\n\twarnings: FormattersPipelineValidationMessage[];\n};\n\nfunction pushError(state: MutableValidationState, code: FormattersPipelineValidationCode, message: string) {\n\tstate.errors.push({ code, message });\n}\n\nfunction pushWarning(state: MutableValidationState, code: FormattersPipelineValidationCode, message: string) {\n\tstate.warnings.push({ code, message });\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\nfunction validateRowBasedOverrideFormulaConfig(config: FormattersPipelineRowBasedOverrideFormulaConfig, state: MutableValidationState) {\n\tif (!config.formulaId.trim()) {\n\t\tpushError(state, \"step_row_based_override_formula_id_empty\", \"Для rowBasedOverride (formula) необходимо заполнить formulaId.\");\n\t\treturn;\n\t}\n\n\tconst formula = getRowBasedFormatterById(config.formulaId);\n\tconst dependencies = [...(config.dependencyIds ?? [])];\n\n\tif (!formula) {\n\t\tpushError(state, \"step_row_based_override_formula_not_found\", \"Формула rowBasedOverride не найдена в реестре.\");\n\t\treturn;\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 = createRowBasedFormatterContext({\n\t\t\t\trowData: sampleRowData,\n\t\t\t\trawValue: 100,\n\t\t\t\tcolumnId: \"__validation__\",\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\tpushError(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_dependency_index_out_of_range\",\n\t\t\t`Формула rowBasedOverride обращается к несуществующим индексам. Минимально требуется зависимостей: ${requiredDependencyCount}, выбрано: ${dependencies.length}.`\n\t\t);\n\t}\n\n\tif (sortedUsedIndexes.length === 0) {\n\t\tpushWarning(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_formula_does_not_use_dependencies\",\n\t\t\t\"Формула rowBasedOverride не использует dependencyIds.\"\n\t\t);\n\t}\n\n\tconst unusedDependencies = dependencies.filter((_, index) => !usedIndexes.has(index));\n\tif (unusedDependencies.length > 0) {\n\t\tpushWarning(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_unused_dependencies\",\n\t\t\t`Выбраны, но не используются формулой rowBasedOverride: ${unusedDependencies.join(\", \")}.`\n\t\t);\n\t}\n\n\tif (runtimeErrorCount > 0) {\n\t\tpushWarning(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_formula_runtime_error\",\n\t\t\t\"На тестовых данных формула rowBasedOverride завершилась с ошибкой.\"\n\t\t);\n\t}\n}\n\n/**\n * Pipeline проверяет контракт формулы и индексы, а наличие полей в конкретном\n * источнике данных проверяет потребитель через collectRuntimeFieldDependencyIds.\n */\nfunction validateValueStateFormulaSource(source: FormattersPipelineValueStateFormulaSource, state: MutableValidationState) {\n\tif (!source.formulaId.trim()) {\n\t\tpushError(state, \"step_value_state_formula_id_empty\", \"Для источника состояния необходимо выбрать формулу.\");\n\t\treturn;\n\t}\n\n\tif (source.dependencyIds.some((dependencyId) => !dependencyId.trim())) {\n\t\tpushError(state, \"step_value_state_dependency_id_empty\", \"Зависимость формулы состояния не может иметь пустой id.\");\n\t\treturn;\n\t}\n\n\tconst validation = validateTableFormulaDependencies({\n\t\tformulaId: source.formulaId,\n\t\tdependencies: source.dependencyIds,\n\t\tavailableColumnIds: source.dependencyIds\n\t});\n\tfor (const error of validation.errors) {\n\t\tif (error.code === \"formula_not_found\") {\n\t\t\tpushError(state, \"step_value_state_formula_not_found\", \"Формула источника состояния не найдена в реестре.\");\n\t\t} else if (error.code === \"dependency_index_out_of_range\") {\n\t\t\tpushError(state, \"step_value_state_dependency_index_out_of_range\", error.message);\n\t\t}\n\t}\n\tfor (const warning of validation.warnings) {\n\t\tswitch (warning.code) {\n\t\t\tcase \"unused_dependencies\":\n\t\t\t\tpushWarning(state, \"step_value_state_unused_dependencies\", warning.message);\n\t\t\t\tbreak;\n\t\t\tcase \"formula_does_not_use_dependencies\":\n\t\t\t\tpushWarning(state, \"step_value_state_formula_does_not_use_dependencies\", warning.message);\n\t\t\t\tbreak;\n\t\t\tcase \"formula_runtime_error\":\n\t\t\t\tpushWarning(state, \"step_value_state_formula_runtime_error\", warning.message);\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\nfunction validateStepDefinitions(steps: readonly FormattersPipelineStep[], state: MutableValidationState) {\n\tconst stepIdSet = new Set<string>();\n\tconst counters = {\n\t\tnormalizeLeadingZeros: 0,\n\t\trowBasedOverride: 0,\n\t\tresolveValueState: 0,\n\t\ttypedValueFormat: 0\n\t};\n\n\tfor (const step of steps) {\n\t\tconst normalizedId = step.id.trim();\n\t\tif (!normalizedId) {\n\t\t\tpushError(state, \"step_id_duplicate\", \"Шаг pipeline не может иметь пустой id.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (stepIdSet.has(normalizedId)) {\n\t\t\tpushError(state, \"step_id_duplicate\", `Найден дублирующийся id шага pipeline: ${normalizedId}.`);\n\t\t}\n\t\tstepIdSet.add(normalizedId);\n\n\t\tswitch (step.type) {\n\t\t\tcase \"normalizeLeadingZeros\":\n\t\t\t\tcounters.normalizeLeadingZeros += 1;\n\t\t\t\tbreak;\n\t\t\tcase \"rowBasedOverride\":\n\t\t\t\tcounters.rowBasedOverride += 1;\n\n\t\t\t\tif (step.config.mode === \"field\" && !step.config.fieldKey.trim()) {\n\t\t\t\t\tpushError(\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\"step_row_based_override_field_key_empty\",\n\t\t\t\t\t\t\"Для rowBasedOverride (field) необходимо заполнить fieldKey.\"\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (step.config.mode === \"formula\") {\n\t\t\t\t\tvalidateRowBasedOverrideFormulaConfig(step.config, state);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"resolveValueState\":\n\t\t\t\tcounters.resolveValueState += 1;\n\t\t\t\tif (step.config.valueSource?.kind === \"formula\") {\n\t\t\t\t\tvalidateValueStateFormulaSource(step.config.valueSource, state);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tstep.config.resolver.kind === \"threshold\" &&\n\t\t\t\t\tstep.config.resolver.states.length !== step.config.resolver.thresholds.length + 1\n\t\t\t\t) {\n\t\t\t\t\tpushError(\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\"step_threshold_states_count_invalid\",\n\t\t\t\t\t\t\"Для threshold-резолвера количество states должно быть равно thresholds + 1.\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"typedValueFormat\":\n\t\t\t\tcounters.typedValueFormat += 1;\n\t\t\t\tif (step.config?.numberPresetName !== undefined) {\n\t\t\t\t\tconst normalizedPresetName = step.config.numberPresetName.trim();\n\t\t\t\t\tif (!normalizedPresetName) {\n\t\t\t\t\t\tpushError(state, \"step_typed_value_format_preset_empty\", \"Для typedValueFormat указан пустой numberPresetName.\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!getNumberPreset(normalizedPresetName)) {\n\t\t\t\t\t\tpushError(\n\t\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\t\"step_typed_value_format_preset_not_found\",\n\t\t\t\t\t\t\t`Для typedValueFormat указан неизвестный пресет: ${normalizedPresetName}.`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (counters.normalizeLeadingZeros > 1) {\n\t\tpushError(state, \"step_normalize_leading_zeros_multiple\", \"В pipeline может быть только один шаг normalizeLeadingZeros.\");\n\t}\n\n\tif (counters.rowBasedOverride > 1) {\n\t\tpushError(state, \"step_row_based_override_multiple\", \"В pipeline может быть только один шаг rowBasedOverride.\");\n\t}\n\n\tif (counters.resolveValueState > 1) {\n\t\tpushError(state, \"step_resolve_value_state_multiple\", \"В pipeline может быть только один шаг resolveValueState.\");\n\t}\n\n\tif (counters.typedValueFormat > 1) {\n\t\tpushError(state, \"step_typed_value_format_multiple\", \"В pipeline может быть только один шаг typedValueFormat.\");\n\t}\n\n\tconst resolveIndex = steps.findIndex((step) => step.type === \"resolveValueState\");\n\tconst typedIndex = steps.findIndex((step) => step.type === \"typedValueFormat\");\n\tif (resolveIndex !== -1 && typedIndex !== -1 && typedIndex < resolveIndex) {\n\t\tpushError(state, \"step_typed_before_value_state\", \"Шаг typedValueFormat не может выполняться до шага resolveValueState.\");\n\t}\n\n\tfor (const step of steps) {\n\t\tif (step.type !== \"resolveValueState\") continue;\n\t\tif (!step.config.icon?.enabled && step.config.icon?.showValue === false) {\n\t\t\tpushWarning(\n\t\t\t\tstate,\n\t\t\t\t\"step_value_hidden_without_icon\",\n\t\t\t\t\"Для resolveValueState установлено showValue=false при выключенной иконке: значение не будет отображаться.\"\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Валидация облегчённого плана pipeline.\n */\nexport function validateFormattersPipelinePlan(plan: FormattersPipelinePlan): FormattersPipelineValidationResult {\n\tconst state: MutableValidationState = { errors: [], warnings: [] };\n\n\tvalidateStepDefinitions(plan.steps, state);\n\n\treturn {\n\t\tok: state.errors.length === 0,\n\t\terrors: state.errors,\n\t\twarnings: state.warnings,\n\t\tplan: state.errors.length === 0 ? { steps: [...plan.steps] } : undefined\n\t};\n}\n\nfunction buildLinearPathFromGraph(\n\tnodes: readonly FormattersPipelineNode[],\n\tedges: readonly FormattersPipelineEdge[],\n\tstate: MutableValidationState\n): string[] | undefined {\n\tconst nodeById = new Map(nodes.map((node) => [node.id, node]));\n\tconst outgoing = new Map<string, string[]>();\n\tconst incoming = new Map<string, string[]>();\n\n\tfor (const node of nodes) {\n\t\toutgoing.set(node.id, []);\n\t\tincoming.set(node.id, []);\n\t}\n\n\tfor (const edge of edges) {\n\t\tconst source = edge.source.trim();\n\t\tconst target = edge.target.trim();\n\t\tif (!nodeById.has(source) || !nodeById.has(target)) {\n\t\t\tpushError(state, \"edge_node_not_found\", `Ребро ${edge.id} ссылается на несуществующий узел: ${source} -> ${target}.`);\n\t\t\tcontinue;\n\t\t}\n\n\t\toutgoing.get(source)?.push(target);\n\t\tincoming.get(target)?.push(source);\n\t}\n\n\tconst sources = nodes.filter((node) => node.type === \"source\");\n\tconst sinks = nodes.filter((node) => node.type === \"sink\");\n\n\tif (sources.length !== 1) {\n\t\tpushError(state, \"source_count_invalid\", \"В графе должен быть ровно один узел source.\");\n\t}\n\tif (sinks.length !== 1) {\n\t\tpushError(state, \"sink_count_invalid\", \"В графе должен быть ровно один узел sink.\");\n\t}\n\tif (state.errors.length > 0) return undefined;\n\n\tconst sourceNodeId = sources[0]!.id;\n\tconst sinkNodeId = sinks[0]!.id;\n\n\tfor (const node of nodes) {\n\t\tconst inDegree = incoming.get(node.id)?.length ?? 0;\n\t\tconst outDegree = outgoing.get(node.id)?.length ?? 0;\n\n\t\tif (node.type === \"source\") {\n\t\t\tif (inDegree !== 0) {\n\t\t\t\tpushError(state, \"source_incoming_invalid\", \"Узел source не должен иметь входящих рёбер.\");\n\t\t\t}\n\t\t\tif (outDegree !== 1) {\n\t\t\t\tpushError(state, \"node_degree_invalid\", \"Узел source должен иметь ровно одно исходящее ребро.\");\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (node.type === \"sink\") {\n\t\t\tif (outDegree !== 0) {\n\t\t\t\tpushError(state, \"sink_outgoing_invalid\", \"Узел sink не должен иметь исходящих рёбер.\");\n\t\t\t}\n\t\t\tif (inDegree !== 1) {\n\t\t\t\tpushError(state, \"node_degree_invalid\", \"Узел sink должен иметь ровно одно входящее ребро.\");\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (inDegree !== 1 || outDegree !== 1) {\n\t\t\tpushError(\n\t\t\t\tstate,\n\t\t\t\t\"node_degree_invalid\",\n\t\t\t\t`Узел ${node.id} должен иметь ровно одно входящее и одно исходящее ребро для линейного pipeline.`\n\t\t\t);\n\t\t}\n\t}\n\n\tif (state.errors.length > 0) return undefined;\n\n\tconst visited = new Set<string>();\n\tconst path: string[] = [];\n\tlet cursor = sourceNodeId;\n\n\twhile (true) {\n\t\tif (visited.has(cursor)) {\n\t\t\tpushError(state, \"path_cycle_detected\", \"В графе pipeline обнаружен цикл.\");\n\t\t\treturn undefined;\n\t\t}\n\t\tvisited.add(cursor);\n\t\tpath.push(cursor);\n\n\t\tif (cursor === sinkNodeId) {\n\t\t\tbreak;\n\t\t}\n\n\t\tconst nextCandidates = outgoing.get(cursor) ?? [];\n\t\tif (nextCandidates.length !== 1) {\n\t\t\tpushError(state, \"path_broken\", \"Не удалось построить линейный путь от source к sink.\");\n\t\t\treturn undefined;\n\t\t}\n\n\t\tcursor = nextCandidates[0]!;\n\t}\n\n\tif (visited.size !== nodes.length) {\n\t\tpushError(state, \"path_disconnected_nodes\", \"Граф содержит узлы, которые не входят в линейный путь source -> sink.\");\n\t\treturn undefined;\n\t}\n\n\treturn path;\n}\n\n/**\n * Валидация графа pipeline и построение линейного плана исполнения.\n */\nexport function validateFormattersPipelineGraph(graph: FormattersPipelineGraph): FormattersPipelineValidationResult {\n\tconst state: MutableValidationState = { errors: [], warnings: [] };\n\n\tif (!graph.nodes.length) {\n\t\tpushError(state, \"path_broken\", \"Граф pipeline не содержит узлов.\");\n\t\treturn { ok: false, errors: state.errors, warnings: state.warnings };\n\t}\n\n\tconst nodeById = new Map<string, FormattersPipelineNode>();\n\tfor (const node of graph.nodes) {\n\t\tconst normalizedId = node.id.trim();\n\t\tif (!normalizedId) {\n\t\t\tpushError(state, \"node_id_duplicate\", \"Узел pipeline не может иметь пустой id.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (nodeById.has(normalizedId)) {\n\t\t\tpushError(state, \"node_id_duplicate\", `Найден дублирующийся id узла pipeline: ${normalizedId}.`);\n\t\t\tcontinue;\n\t\t}\n\n\t\tnodeById.set(normalizedId, node);\n\t}\n\n\tconst edgeIdSet = new Set<string>();\n\tfor (const edge of graph.edges) {\n\t\tconst normalizedEdgeId = edge.id.trim();\n\t\tif (!normalizedEdgeId) {\n\t\t\tpushError(state, \"edge_id_duplicate\", \"Ребро pipeline не может иметь пустой id.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (edgeIdSet.has(normalizedEdgeId)) {\n\t\t\tpushError(state, \"edge_id_duplicate\", `Найден дублирующийся id ребра pipeline: ${normalizedEdgeId}.`);\n\t\t\tcontinue;\n\t\t}\n\n\t\tedgeIdSet.add(normalizedEdgeId);\n\t}\n\n\tif (state.errors.length > 0) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tconst path = buildLinearPathFromGraph(graph.nodes, graph.edges, state);\n\tif (!path) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tconst steps: FormattersPipelineStep[] = [];\n\tfor (const nodeId of path) {\n\t\tconst node = nodeById.get(nodeId);\n\t\tif (!node || node.type === \"source\" || node.type === \"sink\") continue;\n\n\t\tswitch (node.type) {\n\t\t\tcase \"normalizeLeadingZeros\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"normalizeLeadingZeros\",\n\t\t\t\t\tconfig: node.config ? { ...node.config } : undefined\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"rowBasedOverride\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"rowBasedOverride\",\n\t\t\t\t\tconfig:\n\t\t\t\t\t\tnode.config.mode === \"formula\"\n\t\t\t\t\t\t\t? { ...node.config, dependencyIds: node.config.dependencyIds ? [...node.config.dependencyIds] : undefined }\n\t\t\t\t\t\t\t: { ...node.config }\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"resolveValueState\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"resolveValueState\",\n\t\t\t\t\tconfig: cloneResolveValueStateConfig(node.config)\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"typedValueFormat\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"typedValueFormat\",\n\t\t\t\t\tconfig: node.config ? { ...node.config } : undefined\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tvalidateStepDefinitions(steps, state);\n\n\treturn {\n\t\tok: state.errors.length === 0,\n\t\terrors: state.errors,\n\t\twarnings: state.warnings,\n\t\tplan: state.errors.length === 0 ? { steps } : undefined\n\t};\n}\n\n/**\n * Валидация конфигурации pipeline c выбором рабочего плана исполнения.\n *\n * Приоритет источника плана:\n * 1) `plan` из конфигурации;\n * 2) построение плана из `graph`.\n */\nexport function validateFormattersPipelineConfig(config: FormattersPipelineConfig | undefined): FormattersPipelineValidationResult {\n\tconst state: MutableValidationState = { errors: [], warnings: [] };\n\n\tif (!config) {\n\t\tpushError(state, \"config_not_defined\", \"Конфигурация pipeline не задана.\");\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tif (config.version !== 1) {\n\t\tpushError(state, \"unsupported_version\", `Неподдерживаемая версия pipeline: ${String(config.version)}.`);\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tif (!config.plan && !config.graph) {\n\t\tpushError(state, \"graph_or_plan_required\", \"Для pipeline должен быть задан хотя бы один источник: graph или plan.\");\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tif (config.plan) {\n\t\tconst planResult = validateFormattersPipelinePlan(config.plan);\n\t\tstate.errors.push(...planResult.errors);\n\t\tstate.warnings.push(...planResult.warnings);\n\n\t\tif (planResult.ok && planResult.plan) {\n\t\t\treturn {\n\t\t\t\tok: true,\n\t\t\t\terrors: state.errors,\n\t\t\t\twarnings: state.warnings,\n\t\t\t\tplan: planResult.plan\n\t\t\t};\n\t\t}\n\n\t\tif (config.graph) {\n\t\t\tpushWarning(state, \"path_broken\", \"Линейный plan невалиден. Выполнена попытка построить план из graph.\");\n\t\t\tstate.errors.length = 0;\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terrors: state.errors,\n\t\t\t\twarnings: state.warnings\n\t\t\t};\n\t\t}\n\t}\n\n\tif (config.graph) {\n\t\tconst graphResult = validateFormattersPipelineGraph(config.graph);\n\t\treturn {\n\t\t\tok: graphResult.ok,\n\t\t\terrors: [...state.errors, ...graphResult.errors],\n\t\t\twarnings: [...state.warnings, ...graphResult.warnings],\n\t\t\tplan: graphResult.plan\n\t\t};\n\t}\n\n\treturn {\n\t\tok: false,\n\t\terrors: state.errors,\n\t\twarnings: state.warnings\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Ut as e } from "../chunks/formatters-
|
|
1
|
+
import { Ut as e } from "../chunks/formatters-rxriDRPk.js";
|
|
2
2
|
import { _ as t } from "../chunks/array-D-_yMMUK.js";
|
|
3
3
|
import { stableStringify as n } from "../utils/index.js";
|
|
4
|
-
import {
|
|
4
|
+
import { b as r } from "../chunks/formatDate-BUvpRI7H.js";
|
|
5
5
|
import { t as i } from "../chunks/uuid-CUJPAbRY.js";
|
|
6
6
|
import { hashString128 as a } from "../crypto/index.js";
|
|
7
7
|
import { ERROR_REPORT_BUILD_ID_PATTERN as o } from "../error-report-build/index.js";
|
package/dist/excel/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as s, v as c } from "../chunks/validate-
|
|
1
|
+
import { _ as e, a as t, i as n, m as r, n as i, o as a, r as o } from "../chunks/scalarTypeClassification-BZcFmIyR.js";
|
|
2
|
+
import { t as s, v as c } from "../chunks/validate-DsUR-bFF.js";
|
|
3
3
|
import { m as l } from "../chunks/dom-BK22UmgF.js";
|
|
4
4
|
import { escapeXmlValue as u } from "../xml/index.js";
|
|
5
5
|
import d from "write-excel-file/browser";
|
|
@@ -53,7 +53,7 @@ function re(e, t) {
|
|
|
53
53
|
let t = typeof e == "number" ? e : Number(e);
|
|
54
54
|
return Number.isFinite(t) ? t : void 0;
|
|
55
55
|
}
|
|
56
|
-
return t === String ? String(e) : t === Boolean ? !!e : t === Date ? e instanceof Date ? e :
|
|
56
|
+
return t === String ? String(e) : t === Boolean ? !!e : t === Date ? e instanceof Date ? e : a(e) ?? void 0 : e;
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
function b(e) {
|
|
@@ -242,7 +242,7 @@ function Z(e) {
|
|
|
242
242
|
return t?.type === "typedValueFormat" ? t.config : void 0;
|
|
243
243
|
}
|
|
244
244
|
function Q(e) {
|
|
245
|
-
return e.clientOnly ? Number :
|
|
245
|
+
return e.clientOnly ? Number : o(e.odataType) ? Date : i(e.odataType) ? Boolean : t(e.odataType) || e.role === "measure" ? Number : String;
|
|
246
246
|
}
|
|
247
247
|
function ae(e) {
|
|
248
248
|
let t = Z(e.formattersPipeline)?.numberPresetName?.trim();
|
|
@@ -252,30 +252,30 @@ function oe(e) {
|
|
|
252
252
|
let t = c(ae(e));
|
|
253
253
|
return t ? t.decimals > 0 ? `#,##0.${"0".repeat(t.decimals)}` : B : V;
|
|
254
254
|
}
|
|
255
|
-
function se(
|
|
256
|
-
return Z(
|
|
255
|
+
function se(e) {
|
|
256
|
+
return Z(e.formattersPipeline)?.datePresetName?.trim() || (e.odataType === "time" ? r.time : e.odataType === "datetime" || e.odataType === "datetimeOffset" ? r.datetime : r.date);
|
|
257
257
|
}
|
|
258
258
|
function $(e) {
|
|
259
259
|
return e.replace(/H/g, "h").replace(/M/g, "m");
|
|
260
260
|
}
|
|
261
|
-
function ce(
|
|
262
|
-
if (
|
|
263
|
-
if (
|
|
264
|
-
if (
|
|
265
|
-
if (
|
|
266
|
-
if (
|
|
267
|
-
if (
|
|
268
|
-
if (
|
|
269
|
-
if (
|
|
270
|
-
if (
|
|
271
|
-
if (
|
|
261
|
+
function ce(e) {
|
|
262
|
+
if (e === r.odataDatetime || e === r.abapDatetime) return X;
|
|
263
|
+
if (e === r.odataDate || e === r.abapDate) return H;
|
|
264
|
+
if (e === r.monthShort) return U;
|
|
265
|
+
if (e === r.monthMedium) return ie;
|
|
266
|
+
if (e === r.monthLong) return W;
|
|
267
|
+
if (e === r.monthYearMedium) return G;
|
|
268
|
+
if (e === r.monthYearLong) return K;
|
|
269
|
+
if (e.startsWith("datetime")) return e === r.datetime || e === r.datetimeShort ? Y : X;
|
|
270
|
+
if (e.startsWith("time")) return e === r.time || e === r.timeShort ? q : J;
|
|
271
|
+
if (e.startsWith("date")) return H;
|
|
272
272
|
}
|
|
273
273
|
function le(e, t) {
|
|
274
274
|
return ce(e) || (t?.pattern ? $(t.pattern) : $(e));
|
|
275
275
|
}
|
|
276
|
-
function ue(
|
|
277
|
-
let
|
|
278
|
-
return le(
|
|
276
|
+
function ue(t) {
|
|
277
|
+
let n = se(t);
|
|
278
|
+
return le(n, e(n));
|
|
279
279
|
}
|
|
280
280
|
function de(e, t) {
|
|
281
281
|
if (t === Number) return oe(e);
|