@ryuzaki13/react-foundation-lib 2.21.0 → 2.23.0

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.
Files changed (97) hide show
  1. package/dist/analytical-table/buildAnalyticalTableModel.d.ts +5 -2
  2. package/dist/analytical-table/buildAnalyticalTableModel.d.ts.map +1 -1
  3. package/dist/analytical-table/{calculations.d.ts → definition/calculations.d.ts} +1 -1
  4. package/dist/analytical-table/definition/calculations.d.ts.map +1 -0
  5. package/dist/analytical-table/definition/compileAnalyticalTableDefinition.d.ts +4 -0
  6. package/dist/analytical-table/definition/compileAnalyticalTableDefinition.d.ts.map +1 -0
  7. package/dist/analytical-table/definition/types.d.ts +70 -0
  8. package/dist/analytical-table/definition/types.d.ts.map +1 -0
  9. package/dist/analytical-table/definition/validateAnalyticalView.d.ts +5 -0
  10. package/dist/analytical-table/definition/validateAnalyticalView.d.ts.map +1 -0
  11. package/dist/analytical-table/{dateColumns.d.ts → dynamic-columns/dateColumns.d.ts} +2 -1
  12. package/dist/analytical-table/dynamic-columns/dateColumns.d.ts.map +1 -0
  13. package/dist/analytical-table/dynamic-columns/index.d.ts +3 -0
  14. package/dist/analytical-table/dynamic-columns/index.d.ts.map +1 -0
  15. package/dist/analytical-table/{dateColumnTypes.d.ts → dynamic-columns/types.d.ts} +3 -3
  16. package/dist/analytical-table/dynamic-columns/types.d.ts.map +1 -0
  17. package/dist/analytical-table/index.d.ts +7 -5
  18. package/dist/analytical-table/index.d.ts.map +1 -1
  19. package/dist/analytical-table/index.js +362 -201
  20. package/dist/analytical-table/index.js.map +1 -1
  21. package/dist/analytical-table/projections/expansion.d.ts +4 -0
  22. package/dist/analytical-table/projections/expansion.d.ts.map +1 -0
  23. package/dist/analytical-table/{exportProjection.d.ts → projections/exportProjection.d.ts} +1 -1
  24. package/dist/analytical-table/projections/exportProjection.d.ts.map +1 -0
  25. package/dist/analytical-table/projections/indexAnalyticalRows.d.ts +4 -0
  26. package/dist/analytical-table/projections/indexAnalyticalRows.d.ts.map +1 -0
  27. package/dist/analytical-table/projections/resolveRowsProjection.d.ts +4 -0
  28. package/dist/analytical-table/projections/resolveRowsProjection.d.ts.map +1 -0
  29. package/dist/analytical-table/{exportTypes.d.ts → projections/types.d.ts} +2 -2
  30. package/dist/analytical-table/projections/types.d.ts.map +1 -0
  31. package/dist/analytical-table/{aggregation.d.ts → runtime/aggregation.d.ts} +1 -1
  32. package/dist/analytical-table/runtime/aggregation.d.ts.map +1 -0
  33. package/dist/analytical-table/runtime/buildGroupedModel.d.ts +11 -0
  34. package/dist/analytical-table/runtime/buildGroupedModel.d.ts.map +1 -0
  35. package/dist/analytical-table/runtime/createAnalyticalTableRuntime.d.ts +10 -0
  36. package/dist/analytical-table/runtime/createAnalyticalTableRuntime.d.ts.map +1 -0
  37. package/dist/analytical-table/runtime/filtering.d.ts +7 -0
  38. package/dist/analytical-table/runtime/filtering.d.ts.map +1 -0
  39. package/dist/analytical-table/runtime/grouping.d.ts +10 -0
  40. package/dist/analytical-table/runtime/grouping.d.ts.map +1 -0
  41. package/dist/analytical-table/runtime/hierarchy.d.ts +20 -0
  42. package/dist/analytical-table/runtime/hierarchy.d.ts.map +1 -0
  43. package/dist/analytical-table/runtime/sorting.d.ts +5 -0
  44. package/dist/analytical-table/runtime/sorting.d.ts.map +1 -0
  45. package/dist/analytical-table/runtime/totals.d.ts +12 -0
  46. package/dist/analytical-table/runtime/totals.d.ts.map +1 -0
  47. package/dist/analytical-table/runtime/types.d.ts +71 -0
  48. package/dist/analytical-table/runtime/types.d.ts.map +1 -0
  49. package/dist/analytical-table/{valueComparison.d.ts → runtime/valueComparison.d.ts} +1 -1
  50. package/dist/analytical-table/runtime/valueComparison.d.ts.map +1 -0
  51. package/dist/analytical-table/types.d.ts +4 -7
  52. package/dist/analytical-table/types.d.ts.map +1 -1
  53. package/dist/chunks/{formatters-CEltML3y.js → formatters-D1ob2OkI.js} +501 -451
  54. package/dist/chunks/formatters-D1ob2OkI.js.map +1 -0
  55. package/dist/chunks/{odata-service-CWkHASdw.js → odata-service-tp2U5yIr.js} +415 -415
  56. package/dist/chunks/{odata-service-CWkHASdw.js.map → odata-service-tp2U5yIr.js.map} +1 -1
  57. package/dist/chunks/{validate-M2zPiLXn.js → validate-C8cQm_9m.js} +2 -2
  58. package/dist/chunks/{validate-M2zPiLXn.js.map → validate-C8cQm_9m.js.map} +1 -1
  59. package/dist/error-report/index.js +2 -2
  60. package/dist/excel/index.js +18 -18
  61. package/dist/formatters/formatFileSize.d.ts +7 -0
  62. package/dist/formatters/formatFileSize.d.ts.map +1 -0
  63. package/dist/formatters/index.d.ts +1 -0
  64. package/dist/formatters/index.d.ts.map +1 -1
  65. package/dist/formatters/index.js +5 -5
  66. package/dist/odata-service/formatters.d.ts +2 -2
  67. package/dist/odata-service/index.js +1 -1
  68. package/dist/table/index.js.map +1 -1
  69. package/dist/table/useTableRowSelection.d.ts +1 -1
  70. package/dist/table/useTableRowSelection.d.ts.map +1 -1
  71. package/package.json +1 -1
  72. package/src/analytical-table/README.mdx +232 -143
  73. package/src/formatters/README.mdx +8 -0
  74. package/dist/analytical-table/aggregation.d.ts.map +0 -1
  75. package/dist/analytical-table/calculationTypes.d.ts +0 -11
  76. package/dist/analytical-table/calculationTypes.d.ts.map +0 -1
  77. package/dist/analytical-table/calculations.d.ts.map +0 -1
  78. package/dist/analytical-table/columnTypes.d.ts +0 -30
  79. package/dist/analytical-table/columnTypes.d.ts.map +0 -1
  80. package/dist/analytical-table/dataTypes.d.ts +0 -14
  81. package/dist/analytical-table/dataTypes.d.ts.map +0 -1
  82. package/dist/analytical-table/dateColumnTypes.d.ts.map +0 -1
  83. package/dist/analytical-table/dateColumns.d.ts.map +0 -1
  84. package/dist/analytical-table/expansion.d.ts +0 -4
  85. package/dist/analytical-table/expansion.d.ts.map +0 -1
  86. package/dist/analytical-table/exportProjection.d.ts.map +0 -1
  87. package/dist/analytical-table/exportTypes.d.ts.map +0 -1
  88. package/dist/analytical-table/filtering.d.ts +0 -4
  89. package/dist/analytical-table/filtering.d.ts.map +0 -1
  90. package/dist/analytical-table/indexAnalyticalRows.d.ts +0 -4
  91. package/dist/analytical-table/indexAnalyticalRows.d.ts.map +0 -1
  92. package/dist/analytical-table/modelTypes.d.ts +0 -43
  93. package/dist/analytical-table/modelTypes.d.ts.map +0 -1
  94. package/dist/analytical-table/valueComparison.d.ts.map +0 -1
  95. package/dist/analytical-table/viewTypes.d.ts +0 -24
  96. package/dist/analytical-table/viewTypes.d.ts.map +0 -1
  97. package/dist/chunks/formatters-CEltML3y.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"odata-service-CWkHASdw.js","names":[],"sources":["../../src/formatters/boolean/parseAbapBoolean.ts","../../src/formatters/date/pattern.ts","../../src/formatters/date/presets.ts","../../src/formatters/date/parseDate.ts","../../src/formatters/date/formatDate.ts","../../src/formatters/number/parseNumber.ts","../../src/odata-service/baseTypes.ts","../../src/odata-service/buildSeparatedArrays.ts","../../src/odata-service/dateUtils.ts","../../src/odata-service/schema.ts","../../src/odata-service/formatters.ts","../../src/odata-service/builder.ts","../../src/odata-service/columns.ts","../../src/odata-service/filters.ts","../../src/odata-service/filterDefinitions.ts","../../src/odata-service/findCollectionPairs.ts","../../src/odata-service/odataCollectionStore.ts","../../src/odata-service/parser.ts","../../src/odata-service/sorts.ts","../../src/odata-service/sqlFilters.ts","../../src/odata-service/typesValidation.ts","../../src/odata-service/unwrapODataQueryResult.ts","../../src/odata-service/utils.ts","../../src/odata-service/wrapParams.ts"],"sourcesContent":["export function parseAbapBoolean(value: unknown): boolean {\n\tif (value && typeof value === \"string\" && value === \"X\") return true;\n\treturn false;\n}\n\nexport function parseBoolean(value: unknown): boolean {\n\tif (!value) return false;\n\tif (typeof value === \"string\") {\n\t\treturn [\"true\", \"x\", \"1\"].includes(value.toLowerCase());\n\t}\n\treturn Boolean(value);\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 { parseDateValue } from \"./parseDate\";\nimport { compileDatePreset, CompiledDateFormatPreset, DEFAULT_DATE_PRESET_NAMES, getCompiledDatePreset } from \"./presets\";\nimport { DateFormatPrecision, DateFormatPreset, FormatDateOptions, ParsedDateValue } from \"./types\";\n\n/**\n * Кеш скомпилированных объектных предустановок.\n *\n * Именованные предустановки компилируются в реестре, а объектные могут\n * передаваться напрямую в горячем пути таблиц. WeakMap сохраняет готовый\n * Intl.DateTimeFormat на время жизни объекта и не мешает сборке мусора.\n */\nconst objectPresetCache = new WeakMap<DateFormatPreset, CompiledDateFormatPreset>();\n\n/**\n * Дополняет числовую часть даты ведущим нулём.\n */\nfunction padDatePart(value: number): string {\n\treturn String(value).padStart(2, \"0\");\n}\n\n/**\n * Разрешает предустановку по имени или объекту.\n */\nfunction resolvePreset(presetOrName: string | DateFormatPreset): CompiledDateFormatPreset {\n\tif (typeof presetOrName !== \"string\") {\n\t\tconst cachedPreset = objectPresetCache.get(presetOrName);\n\t\tif (cachedPreset) return cachedPreset;\n\n\t\tconst compiledPreset = compileDatePreset(presetOrName);\n\t\tobjectPresetCache.set(presetOrName, compiledPreset);\n\t\treturn compiledPreset;\n\t}\n\n\tconst preset = getCompiledDatePreset(presetOrName);\n\tif (!preset) {\n\t\tthrow new Error(`Предустановка даты \"${presetOrName}\" не найдена`);\n\t}\n\treturn preset;\n}\n\n/**\n * Определяет fallback с учётом опций вызова и предустановки.\n */\nfunction resolveFallback(preset: CompiledDateFormatPreset, options?: FormatDateOptions): string {\n\treturn options?.fallback ?? preset.invalidFallback;\n}\n\n/**\n * Форматирует уже распарсенное значение.\n */\nfunction formatParsedValue(\n\tparsed: ParsedDateValue,\n\tpreset: CompiledDateFormatPreset,\n\tfallback: string,\n\tprecision: DateFormatPrecision\n): string {\n\tif (parsed.kind === \"duration\") {\n\t\treturn preset.formatDuration ? preset.formatDuration(parsed.durationMs, fallback) : fallback;\n\t}\n\n\treturn preset.formatDateTime(parsed.date, precision);\n}\n\n/**\n * Универсально форматирует дату/время по предустановке или её имени.\n */\nexport function formatDate(\n\tvalue: unknown,\n\tpresetOrName: string | DateFormatPreset = DEFAULT_DATE_PRESET_NAMES.date,\n\toptions?: FormatDateOptions\n): string {\n\tconst preset = resolvePreset(presetOrName);\n\tconst fallback = resolveFallback(preset, options);\n\tconst precision = options?.precision ?? \"day\";\n\tconst parsed = parseDateValue(value);\n\n\tif (!parsed) return fallback;\n\treturn formatParsedValue(parsed, preset, fallback, precision);\n}\n\n/**\n * Форматирует значение как дату `dd.MM.yyyy`.\n */\nexport function formatDateAsDate(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.date, options);\n}\n\n/**\n * Форматирует значение как дату и время `dd.MM.yyyy HH:mm`.\n */\nexport function formatDateAsDateTime(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.datetime, options);\n}\n\n/**\n * Форматирует значение как время `HH:mm`.\n */\nexport function formatDateAsTime(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.time, options);\n}\n\n/**\n * Форматирует значение как время `HH:mm:ss`.\n */\nexport function formatDateAsTimeSeconds(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.timeSeconds, options);\n}\n\n/**\n * Форматирует значение как короткую дату `03.03.2026`.\n */\nexport function formatDateAsDateShort(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.dateShort, options);\n}\n\n/**\n * Форматирует значение как среднюю дату `3 мар. 2026 г.`.\n */\nexport function formatDateAsDateMedium(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.dateMedium, options);\n}\n\n/**\n * Форматирует значение как длинную дату `3 марта 2026 г.`.\n */\nexport function formatDateAsDateLong(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.dateLong, options);\n}\n\n/**\n * Форматирует значение как короткую дату без года `03.03`.\n */\nexport function formatDateAsMonthShort(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.monthShort, options);\n}\n\n/**\n * Форматирует значение как среднюю дату без года `3 мар.`.\n */\nexport function formatDateAsMonthMedium(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.monthMedium, options);\n}\n\n/**\n * Форматирует значение как длинную дату без года `3 марта`.\n */\nexport function formatDateAsMonthLong(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.monthLong, options);\n}\n\n/**\n * Форматирует значение как сокращённый месяц и год `мар. 2026`.\n */\nexport function formatDateAsMonthYearMedium(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.monthYearMedium, options);\n}\n\n/**\n * Форматирует значение как полный месяц и год `март 2026`.\n */\nexport function formatDateAsMonthYearLong(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.monthYearLong, options);\n}\n\n/**\n * Форматирует значение как короткое время `18:03`.\n */\nexport function formatDateAsTimeShort(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.timeShort, options);\n}\n\n/**\n * Форматирует значение как среднее время `18:03:50`.\n */\nexport function formatDateAsTimeMedium(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.timeMedium, options);\n}\n\n/**\n * Форматирует значение как длинное время `18:03:50`.\n */\nexport function formatDateAsTimeLong(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.timeLong, options);\n}\n\n/**\n * Форматирует значение как короткую дату и время `03.03.2026 18:03`.\n */\nexport function formatDateAsDatetimeShort(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.datetimeShort, options);\n}\n\n/**\n * Форматирует значение как среднюю дату и время `3 мар. 2026 г. 18:03:50`.\n */\nexport function formatDateAsDatetimeMedium(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.datetimeMedium, options);\n}\n\n/**\n * Форматирует значение как длинную дату и время `3 марта 2026 г. 18:03:50`.\n */\nexport function formatDateAsDatetimeLong(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.datetimeLong, options);\n}\n\n/**\n * Форматирует диапазон дат через разделитель ` - `.\n */\nexport function formatDateRange(\n\tstartValue: unknown,\n\tendValue: unknown,\n\tpresetOrName: string | DateFormatPreset = DEFAULT_DATE_PRESET_NAMES.date,\n\toptions?: FormatDateOptions\n): string {\n\tconst preset = resolvePreset(presetOrName);\n\tconst fallback = resolveFallback(preset, options);\n\tconst precision = options?.precision ?? \"day\";\n\n\tconst startParsed = parseDateValue(startValue);\n\tconst endParsed = parseDateValue(endValue);\n\tif (!startParsed || !endParsed) return fallback;\n\n\tconst start = formatParsedValue(startParsed, preset, fallback, precision);\n\tconst end = formatParsedValue(endParsed, preset, fallback, precision);\n\tif (!start || !end) return fallback;\n\n\treturn `${start} - ${end}`;\n}\n\n/**\n * Форматирует значение как год `yyyy`.\n */\nexport function formatDateAsAbapYear(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.abapYear, options);\n}\n\n/**\n * Форматирует значение как календарный месяц `yyyyMM`.\n */\nexport function formatDateAsAbapMonth(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.abapMonth, options);\n}\n\n/**\n * Форматирует значение как дату `yyyyMMdd`.\n */\nexport function formatDateAsAbapDate(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.abapDate, options);\n}\n\n/**\n * Форматирует значение как дату `yyyyMMddHHmmss`.\n */\nexport function formatDateAsAbapDatetime(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.abapDatetime, options);\n}\n\n/**\n * Форматирует значение как дату `yyyy-MM-dd`.\n */\nexport function formatDateAsODataDate(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.odataDate, options);\n}\n\n/**\n * Форматирует значение как дату и время `yyyy-MM-ddTHH:mm:ss`.\n */\nexport function formatDateAsODataDatetime(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.odataDatetime, options);\n}\n\n/**\n * Форматирует значение как время `PT00H00M00S`.\n */\nexport function formatDateAsODataTime(value: unknown, options?: FormatDateOptions): string {\n\tconst fallback = options?.fallback ?? \"\";\n\tconst parsed = parseDateValue(value);\n\tif (!parsed) return fallback;\n\n\tif (parsed.kind === \"duration\") {\n\t\tconst timePreset = resolvePreset(DEFAULT_DATE_PRESET_NAMES.timeSeconds);\n\t\tconst formattedDuration = timePreset.formatDuration?.(parsed.durationMs, fallback) ?? fallback;\n\t\tif (formattedDuration === fallback) return fallback;\n\n\t\tconst [hours = \"00\", minutes = \"00\", seconds = \"00\"] = formattedDuration.split(\":\");\n\t\treturn `PT${hours}H${minutes}M${seconds}S`;\n\t}\n\n\tconst date = parsed.date;\n\treturn `PT${padDatePart(date.getHours())}H${padDatePart(date.getMinutes())}M${padDatePart(date.getSeconds())}S`;\n}\n","/**\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 { BaseMetaType } from \"./types\";\n\nexport const BASE_META_TYPES = Object.freeze([\"string\", \"number\", \"boolean\", \"date\"] as const) satisfies readonly BaseMetaType[];\n\nconst BASE_META_TYPE_SET: ReadonlySet<string> = new Set(BASE_META_TYPES);\n\nexport const BASE_META_TYPE_LABELS: Readonly<Record<BaseMetaType, string>> = Object.freeze({\n\tstring: \"строка\",\n\tnumber: \"число\",\n\tboolean: \"boolean\",\n\tdate: \"дата\"\n});\n\nexport function isBaseMetaType(type: unknown): type is BaseMetaType {\n\treturn typeof type === \"string\" && BASE_META_TYPE_SET.has(type);\n}\n\nexport function resolveBaseTypeLabel(type: BaseMetaType): string {\n\treturn BASE_META_TYPE_LABELS[type];\n}\n","import { compareStrings } from \"../string-comparison\";\n\nimport { CollectionItem, CollectionPair } from \"./collectionTypes\";\n\nfunction createEmptySeparated<T extends CollectionItem>(pairs: CollectionPair[]) {\n\tconst resultRef: Record<string, T[]> = {};\n\tpairs.forEach((pair) => {\n\t\tresultRef[pair.codeKey] = [];\n\t});\n\treturn resultRef;\n}\n\n/**\n * Создание разделенных массивов для каждого кодового поля\n * @param items - исходные данные справочника\n * @param pairs - пары код-текст\n * @param excludeEmpty - флаг исключения пустых значений\n * @returns Объект с разделенными массивами по кодовым полям\n */\nexport function buildSeparatedArrays<T extends CollectionItem>(\n\titems: T[],\n\tpairs: CollectionPair[],\n\texcludeEmpty: boolean = true,\n\tsortByCode: boolean = true\n): Record<string, T[]> {\n\t// Если items пустой, возвращаем пустые массивы для всех пар\n\tif (!items || items.length === 0) {\n\t\treturn createEmptySeparated(pairs);\n\t}\n\n\t// Определяем, какие ключи действительно существуют в items\n\tconst availableKeys = new Set<string>();\n\tconst firstItem = items[0];\n\n\tif (firstItem) {\n\t\t// Собираем все доступные ключи из первого элемента\n\t\tObject.keys(firstItem).forEach((key) => {\n\t\t\tavailableKeys.add(key);\n\t\t});\n\t}\n\n\t// Фильтруем пары, оставляем только те, где оба ключа существуют в items\n\tconst validPairs = pairs.filter((pair) => {\n\t\treturn availableKeys.has(pair.codeKey as string) && availableKeys.has(pair.textKey as string);\n\t});\n\n\t// Если нет валидных пар, возвращаем пустой результат\n\tif (validPairs.length === 0) {\n\t\treturn createEmptySeparated(pairs);\n\t}\n\n\tconst result: Record<string, T[]> = {};\n\t// Инициализируем структуры данных\n\tconst pairMap = new Map<\n\t\tstring,\n\t\t{\n\t\t\tcodeKey: keyof T;\n\t\t\ttextKey: keyof T;\n\t\t\tuniqueSet: Set<string>;\n\t\t}\n\t>();\n\n\t// Подготовка для валидных пар\n\tfor (const pair of validPairs) {\n\t\tconst codeKeyStr = pair.codeKey as string;\n\t\tpairMap.set(codeKeyStr, {\n\t\t\tcodeKey: pair.codeKey,\n\t\t\ttextKey: pair.textKey,\n\t\t\tuniqueSet: new Set<string>()\n\t\t});\n\t\tresult[codeKeyStr] = [];\n\t}\n\n\t// Для невалидных пар создаем пустые массивы\n\tpairs.forEach((pair) => {\n\t\tconst codeKeyStr = pair.codeKey as string;\n\t\tif (!pairMap.has(codeKeyStr)) {\n\t\t\tresult[codeKeyStr] = [];\n\t\t}\n\t});\n\n\t// Единый проход по всем элементам\n\tfor (const item of items) {\n\t\tfor (const [codeKeyStr, pairData] of pairMap) {\n\t\t\tconst { codeKey, textKey, uniqueSet } = pairData;\n\n\t\t\t// Получаем значения с проверкой на существование\n\t\t\tconst codeValue = String(item[codeKey]);\n\t\t\tconst textValue = String(item[textKey]);\n\n\t\t\t// Если excludeEmpty и текстовое значение пустое - пропускаем\n\t\t\tif (excludeEmpty && !textValue) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Проверяем, что codeValue существует\n\t\t\tif (codeValue === undefined || codeValue === null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Проверка уникальности\n\t\t\tconst uniqueKey = `${String(codeValue)}|${String(textValue)}`;\n\t\t\tif (!uniqueSet.has(uniqueKey)) {\n\t\t\t\tuniqueSet.add(uniqueKey);\n\n\t\t\t\t// Создаем новый объект только с нужными полями\n\t\t\t\tresult[codeKeyStr].push({\n\t\t\t\t\t[codeKey]: codeValue,\n\t\t\t\t\t[textKey]: textValue\n\t\t\t\t} as T);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Сортировка результатов для валидных пар\n\tfor (const [codeKeyStr, pairData] of pairMap) {\n\t\tconst array = result[codeKeyStr];\n\t\tif (array.length > 0) {\n\t\t\tconst sortKey = sortByCode ? pairData.codeKey : pairData.textKey;\n\n\t\t\tarray.sort((a, b) => {\n\t\t\t\tconst valA = a[sortKey] || \"\";\n\t\t\t\tconst valB = b[sortKey] || \"\";\n\t\t\t\treturn compareStrings(String(valA), String(valB));\n\t\t\t});\n\t\t}\n\t}\n\n\treturn result;\n\n\t//\n\n\t// pairs.forEach((pair) => {\n\t// \tlet filteredItems = items;\n\n\t// \t// Фильтруем пустые значения, если требуется\n\t// \tif (excludeEmpty) {\n\t// \t\tfilteredItems = items.filter((item) => item[pair.textKey]);\n\t// \t}\n\n\t// \t// Создаем массив только с нужными полями\n\t// \tconst separatedItems = filteredItems.map(\n\t// \t\t(item) =>\n\t// \t\t\t({\n\t// \t\t\t\t[pair.codeKey]: item[pair.codeKey],\n\t// \t\t\t\t[pair.textKey]: item[pair.textKey]\n\t// \t\t\t}) as T\n\t// \t);\n\n\t// \t// Удаляем дубликаты\n\t// \tconst uniqueItems: T[] = Array.from(\n\t// \t\tnew Map(separatedItems.map((item) => [`${item[pair.codeKey]}|${item[pair.textKey]}`, item])).values()\n\t// \t);\n\n\t// \tconst sortKey = sortByCode ? pair.codeKey : pair.textKey;\n\n\t// \tuniqueItems.sort((a, b) => {\n\t// \t\tconst textA = a[sortKey] || \"\";\n\t// \t\tconst textB = b[sortKey] || \"\";\n\t// \t\treturn compareStrings(String(textA), String(textB));\n\t// \t});\n\n\t// \tresult[pair.codeKey] = uniqueItems;\n\t// });\n\n\t// return result;\n}\n","import { formatDateAsODataDatetime, formatDateAsODataTime } from \"../formatters/date/formatDate\";\n\n/**\n * Форматирование дат в литералы OData, совместимые с SAP UI5 DateFormat.\n *\n * Примеры:\n * * datetime'2025-11-11T12:00:00'\n * * datetimeoffset'2025-11-11T12:00:00Z'\n * * time'PT12H30M00S'\n */\nexport const ODataDateFormat = {\n\tdatetime(date: Date): string {\n\t\treturn `datetime'${formatDateAsODataDatetime(date)}'`;\n\t},\n\tdatetimeOffset(date: Date): string {\n\t\treturn `datetimeoffset'${date.toISOString()}'`;\n\t},\n\ttime(date: Date): string {\n\t\treturn `time'${formatDateAsODataTime(date)}'`;\n\t}\n};\n","import { z } from \"zod\";\n\nimport type { ODataMetaType } from \"./types\";\n\nexport const odataTypeSchemas: Record<ODataMetaType, z.ZodTypeAny> = {\n\tstring: z.string(),\n\tguid: z.uuid().or(z.string().regex(/^[0-9a-fA-F-]+$/, \"Invalid GUID\")),\n\tboolean: z.boolean(),\n\tint: z.number().int(),\n\tlong: z.number().int(),\n\tfloat: z.number(),\n\tdecimal: z.number(),\n\tdouble: z.number(),\n\tdatetime: z.date(),\n\tdatetimeOffset: z.date(),\n\ttime: z.date(),\n\tbinary: z.string(),\n\tbyte: z.number().int().min(0).max(255)\n};\n\n// Type Guards на основе Zod\nfunction isType<T>(value: unknown, schema: z.ZodType<T>): value is T {\n\treturn schema.safeParse(value).success;\n}\n\n// Специфичные Type Guards\nexport function isStringSafe(value: unknown): value is string {\n\treturn isType(value, odataTypeSchemas.string);\n}\n\nexport function isNumberSafe(value: unknown): value is number {\n\treturn isType(value, odataTypeSchemas.float); // используем float как базовый числовой тип\n}\n\nexport function isBooleanSafe(value: unknown): value is boolean {\n\treturn isType(value, odataTypeSchemas.boolean);\n}\n\nexport function isDateSafe(value: unknown): value is Date {\n\treturn isType(value, odataTypeSchemas.datetime);\n}\n","import { z } from \"zod\";\n\nimport { parseAbapBoolean } from \"../formatters/boolean/parseAbapBoolean\";\nimport { formatDateAsAbapDate } from \"../formatters/date/formatDate\";\nimport { parseDate } from \"../formatters/date/parseDate\";\nimport { parseNumber } from \"../formatters/number/parseNumber\";\n\nimport { ODataDateFormat } from \"./dateUtils\";\nimport { odataTypeSchemas } from \"./schema\";\n\nimport type {\n\tBaseMetaType,\n\tEntityParameterProperty,\n\tODataBooleanType,\n\tODataDateType,\n\tODataFormatterDescription,\n\tODataMetaType,\n\tODataNumericType,\n\tODataStringType\n} from \"./types\";\n\n/**\n * NOTE: Запрещено экспортировать!\n */\nfunction formatValidValue(type: ODataMetaType, validValue: unknown) {\n\tswitch (type) {\n\t\tcase \"string\":\n\t\t\treturn `'${String(validValue).replace(/'/g, \"''\")}'`;\n\t\tcase \"guid\":\n\t\t\treturn `guid'${String(validValue)}'`;\n\t\tcase \"boolean\":\n\t\t\treturn validValue ? \"'X'\" : \"' '\";\n\t\tcase \"long\":\n\t\t\treturn `${String(validValue)}L`;\n\t\tcase \"float\":\n\t\t\treturn `${String(validValue)}F`;\n\t\tcase \"decimal\":\n\t\t\treturn `${String(validValue)}M`;\n\t\tcase \"double\":\n\t\t\treturn `${String(validValue)}D`;\n\t\tcase \"datetime\":\n\t\tcase \"datetimeOffset\":\n\t\tcase \"time\":\n\t\t\tif (!(validValue instanceof Date)) {\n\t\t\t\tthrow new Error(`Неверная дата для типа '${type}': ${validValue}`);\n\t\t\t}\n\t\t\treturn ODataDateFormat[type](validValue);\n\t\tcase \"binary\":\n\t\t\treturn `binary'${validValue}'`;\n\t\tcase \"byte\":\n\t\tcase \"int\":\n\t\t\treturn `${String(validValue)}`;\n\n\t\tdefault:\n\t\t\tthrow new Error(`Неподдерживаемый тип: ${type satisfies never}`);\n\t}\n}\n\n/**\n * Форматирует значение для использования в URL в соответствии с типом OData\n * @param type Тип данных\n * @param value Значение\n * @returns Отформатированная строка\n */\nexport function odataFormatValue(type: ODataMetaType, value: unknown): string {\n\tconst schema = odataTypeSchemas[type];\n\tconst result = schema.safeParse(value);\n\tif (!result.success) {\n\t\tthrow new Error(`Некорректное значение для типа '${type}': ${result.error.issues[0]?.message ?? value}`);\n\t}\n\n\treturn formatValidValue(type, result.data);\n}\n\ntype ODataMetadataValueDescriptor = Pick<EntityParameterProperty, \"type\" | \"abapBooleanLike\">;\n\nfunction tryParseBooleanValue(value: unknown): boolean | undefined {\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"number\") {\n\t\tif (value === 1) return true;\n\t\tif (value === 0) return false;\n\t\treturn undefined;\n\t}\n\tif (typeof value !== \"string\") return undefined;\n\n\tif (value === \"X\") return true;\n\tif (value === \" \" || value === \"\") return false;\n\n\tconst normalized = value.trim().toLowerCase();\n\tif (normalized === \"true\" || normalized === \"1\") return true;\n\tif (normalized === \"false\" || normalized === \"0\") return false;\n\n\treturn undefined;\n}\n\nfunction tryParseAbapBooleanLikeValue(value: unknown): boolean | undefined {\n\tif (value == null) return false;\n\tif (typeof value !== \"string\") return undefined;\n\tif (value === \"X\" || value === \" \" || value === \"\") {\n\t\treturn parseAbapBoolean(value);\n\t}\n\treturn undefined;\n}\n\nexport function odataParseValue(type: ODataBooleanType, value: unknown): boolean | unknown;\nexport function odataParseValue(type: ODataNumericType, value: unknown): number | unknown;\nexport function odataParseValue(type: ODataDateType, value: unknown): Date | null | unknown;\nexport function odataParseValue(type: ODataStringType, value: unknown): string | unknown;\nexport function odataParseValue(type: ODataMetaType, value: unknown): string | unknown;\nexport function odataParseValue(type: ODataMetaType, value: unknown) {\n\tswitch (type) {\n\t\tcase \"boolean\": {\n\t\t\tconst parsed = tryParseBooleanValue(value);\n\t\t\treturn parsed ?? value;\n\t\t}\n\n\t\tcase \"int\":\n\t\tcase \"long\":\n\t\tcase \"float\":\n\t\tcase \"decimal\":\n\t\tcase \"double\":\n\t\tcase \"byte\":\n\t\t\treturn parseNumber(value);\n\n\t\tcase \"datetime\":\n\t\tcase \"datetimeOffset\":\n\t\tcase \"time\":\n\t\t\treturn parseDate(value);\n\n\t\tdefault:\n\t\t\treturn String(value);\n\t}\n}\n\nexport function odataParseValueByMetadata(descriptor: ODataMetadataValueDescriptor, value: unknown) {\n\tif (descriptor.abapBooleanLike) {\n\t\tconst parsedBoolean = tryParseAbapBooleanLikeValue(value);\n\t\tif (parsedBoolean !== undefined) {\n\t\t\treturn parsedBoolean;\n\t\t}\n\t}\n\n\treturn odataParseValue(descriptor.type, value);\n}\n\nexport function defaultODataTypeValue(type: ODataMetaType) {\n\tswitch (type) {\n\t\tcase \"boolean\":\n\t\t\treturn false;\n\n\t\tcase \"int\":\n\t\tcase \"long\":\n\t\tcase \"float\":\n\t\tcase \"decimal\":\n\t\tcase \"double\":\n\t\tcase \"byte\":\n\t\t\treturn 0;\n\n\t\tcase \"datetime\":\n\t\tcase \"datetimeOffset\":\n\t\tcase \"time\":\n\t\t\treturn new Date();\n\n\t\tdefault:\n\t\t\treturn \"\";\n\t}\n}\n\nexport function defaultControlTypeValue(type: BaseMetaType) {\n\tswitch (type) {\n\t\tcase \"boolean\":\n\t\t\treturn false;\n\t\tcase \"number\":\n\t\t\treturn 0;\n\t\tcase \"date\":\n\t\t\treturn new Date();\n\t\tdefault:\n\t\t\treturn \"\";\n\t}\n}\n\nexport function createFormatter<S extends z.ZodArray>(schema: S, fn: (...args: [...z.infer<S>]) => string) {\n\treturn (...args: unknown[]) => {\n\t\tconst result = schema.safeParse(args);\n\t\tif (!result.success) {\n\t\t\tthrow new Error(`Validation failed: ${result.error.message}`);\n\t\t}\n\t\treturn fn(...result.data);\n\t};\n}\n\nexport function createBooleanFormatter(fn: (...args: boolean[]) => string) {\n\treturn createFormatter(z.array(z.boolean()), fn);\n}\n\nexport function createStringFormatter(fn: (...args: string[]) => string) {\n\treturn createFormatter(z.array(z.string()), fn);\n}\n\nexport function createNumberFormatter(fn: (...args: number[]) => string) {\n\treturn createFormatter(z.array(z.number()), fn);\n}\n\nexport function createDateFormatter(fn: (...args: Date[]) => string) {\n\treturn createFormatter(z.array(z.date()), fn);\n}\n\ntype FormatterRecord = {\n\t[K in BaseMetaType]?: {\n\t\t/**\n\t\t * Базовый форматтер для типа (по умолчанию)\n\t\t */\n\t\tbase: Omit<ODataFormatterDescription, \"id\">;\n\t\t/**\n\t\t * Кастомные варианты форматтеров для типа\n\t\t */\n\t\t[key: string]: Omit<ODataFormatterDescription, \"id\">;\n\t};\n};\n\n/*export*/ const formatODataDatetime = createDateFormatter(ODataDateFormat.datetime);\n/*export*/ const formatODataDatetimeOffset = createDateFormatter(ODataDateFormat.datetimeOffset);\n/*export*/ const formatODataTime = createDateFormatter(ODataDateFormat.time);\n/*export*/ const formatODataAbapDate = createDateFormatter((value) => formatValidValue(\"string\", formatDateAsAbapDate(value)));\n\n/*export*/ const formatODataBoolean = createBooleanFormatter((value) => formatValidValue(\"boolean\", value));\n/*export*/ const formatODataBooleanAsChar = createBooleanFormatter((value) => formatValidValue(\"string\", Number(value)));\n/*export*/ const formatODataBooleanAsByte = createBooleanFormatter((value) => formatValidValue(\"byte\", Number(value)));\n\n/*export*/ const formatODataString = createStringFormatter((value) => formatValidValue(\"string\", value));\n\n/**\n * Форматтеры формируются только по базовым типам, по которым работают UI контролы.\n */\nconst formatters: FormatterRecord = {\n\tdate: {\n\t\tbase: {\n\t\t\tlabel: \"Базовый datetime\",\n\t\t\tdescription: \"Используется для параметров OData с типом данных datetime\",\n\t\t\tfn: formatODataDatetime\n\t\t},\n\t\tdatetimeOffset: {\n\t\t\tlabel: \"Базовый datetimeoffset\",\n\t\t\tdescription: \"Используется для параметров OData с типом данных datetimeoffset\",\n\t\t\tfn: formatODataDatetimeOffset\n\t\t},\n\t\ttime: {\n\t\t\tlabel: \"Базовый time\",\n\t\t\tdescription: \"Используется для параметров OData с типом данных time\",\n\t\t\tfn: formatODataTime\n\t\t},\n\t\tstringAbapDate: {\n\t\t\tlabel: \"Дата ABAP YYYYMMDD\",\n\t\t\tdescription: \"Используется для параметров OData с типом данных string(8)\",\n\t\t\tfn: formatODataAbapDate\n\t\t}\n\t},\n\tboolean: {\n\t\tbase: {\n\t\t\tlabel: \"Базовое ABAP булево\",\n\t\t\tdescription: \"Стандартный формат abap_bool со значением 'X' для true и '' для false\",\n\t\t\tfn: formatODataBoolean\n\t\t},\n\t\tasChar: {\n\t\t\tlabel: \"Как символ\",\n\t\t\tdescription: \"Преобразование булево в символы '0' или '1'\",\n\t\t\tfn: formatODataBooleanAsChar\n\t\t},\n\t\tasByte: {\n\t\t\tlabel: \"Как цифра\",\n\t\t\tdescription: \"Преобразование булево в цифру 0 или 1\",\n\t\t\tfn: formatODataBooleanAsByte\n\t\t}\n\t},\n\tstring: {\n\t\tbase: {\n\t\t\tlabel: \"Базовая строка\",\n\t\t\tdescription: \"\",\n\t\t\tfn: formatODataString\n\t\t}\n\t}\n};\n\nexport function getBaseTypeFromODataType<T extends ODataMetaType>(type: T): BaseMetaType {\n\tswitch (type) {\n\t\tcase \"boolean\":\n\t\t\treturn \"boolean\";\n\n\t\tcase \"int\":\n\t\tcase \"long\":\n\t\tcase \"float\":\n\t\tcase \"decimal\":\n\t\tcase \"double\":\n\t\tcase \"byte\":\n\t\t\treturn \"number\";\n\n\t\tcase \"datetime\":\n\t\tcase \"datetimeOffset\":\n\t\tcase \"time\":\n\t\t\treturn \"date\";\n\n\t\tdefault:\n\t\t\treturn \"string\";\n\t}\n}\n\nexport function getFormattersFor<T extends ODataMetaType>(type: T): ODataFormatterDescription[] {\n\tconst group = formatters[getBaseTypeFromODataType(type)];\n\tif (!group) return [];\n\n\treturn Object.entries(group).map(([id, fmt]) => ({\n\t\tid,\n\t\t...fmt\n\t}));\n}\n\n/**\n * Возвращает форматтеры напрямую по базовому типу UI-контрола.\n */\nexport function getFormattersForBaseType<T extends BaseMetaType>(type: T): ODataFormatterDescription[] {\n\tconst group = formatters[type];\n\tif (!group) return [];\n\n\treturn Object.entries(group).map(([id, fmt]) => ({\n\t\tid,\n\t\t...fmt\n\t}));\n}\n\nexport function getFormatter<T extends ODataMetaType>(type: T, id: string) {\n\treturn formatters[getBaseTypeFromODataType(type)]?.[id];\n}\n\nexport function getFormatterForBaseType<T extends BaseMetaType>(type: T, id: string) {\n\treturn formatters[type]?.[id];\n}\n","/**\n * Построитель URL для OData сущностей на основе метаданных\n */\n\nimport { odataFormatValue } from \"./formatters\";\nimport {\n\ttype EntityMetadata,\n\ttype EntityParameterProperty,\n\ttype FunctionImportMetadata,\n\ttype ODataOperationMethod,\n\ttype ODataParameterValue,\n\ttype ODataServiceConfig,\n\ttype ODataValue,\n\ttype WrappedODataParameters\n} from \"./types\";\n\ntype ParameterizedMetadata = {\n\tparameters?: EntityParameterProperty[];\n};\n\n/**\n * Валидирует длину отформатированного значения\n * @param formattedValue Отформатированное значение\n * @param maxLength Максимальная длина\n */\nfunction validateFormattedLength(formattedValue: string, maxLength?: number): void {\n\tif (!maxLength || typeof maxLength !== \"number\") return;\n\n\t// Проверяем что значение в кавычках и содержимое не превышает maxLength\n\tconst match = formattedValue.match(/^'(.*)'$/s);\n\tif (!match) {\n\t\tthrow new Error(`Значение должно быть заключено в одинарные кавычки: ${formattedValue}`);\n\t}\n\n\tconst content = match[1];\n\tif (content.length > maxLength) {\n\t\tthrow new Error(\n\t\t\t`Значение слишком длинное для maxLength=${maxLength}: '${formattedValue}' (${content.length} символов внутри кавычек)`\n\t\t);\n\t}\n}\n\n/**\n * Собирает строку параметров запроса к сущности на основе метаданных\n *\n * @param metadata Метаданные сущности\n * @param params Значения параметров\n */\nexport function buildParameterEntries(metadata: ParameterizedMetadata, params: WrappedODataParameters): Array<[string, string]> {\n\tif (!metadata.parameters) return [];\n\n\tconst parts = metadata.parameters.map<[string, string] | null>((param) => {\n\t\tconst { id, type, maxLength, mandatory } = param;\n\n\t\tconst odataValue = (params[id] ?? {}) as ODataValue<ODataParameterValue>;\n\t\tconst value = odataValue.value;\n\t\tconst formatter = odataValue.formatter;\n\n\t\tif (mandatory && (value === undefined || value === null)) {\n\t\t\tthrow new Error(`Отсутствует обязательный параметр: ${id}`);\n\t\t}\n\n\t\t// Пропускаем необязательные параметры без значений\n\t\tif (value === undefined || value === null) return null;\n\n\t\ttry {\n\t\t\tif (Array.isArray(value) && !formatter) {\n\t\t\t\tthrow new Error(\"Массив значений OData-параметра требует custom formatter\");\n\t\t\t}\n\n\t\t\tconst formattedValue = formatter ? formatter(value) : odataFormatValue(type, value);\n\n\t\t\tvalidateFormattedLength(formattedValue, maxLength);\n\n\t\t\treturn [id, formattedValue];\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Ошибка форматирования параметра ${id}: ${String(error)}`);\n\t\t}\n\t});\n\n\treturn parts.filter((part): part is [string, string] => part !== null);\n}\n\n/**\n * Собирает строку параметров запроса к сущности на основе metadata.\n */\nexport function buildEntityParameters(metadata: EntityMetadata, params: WrappedODataParameters): string {\n\tconst parts = buildParameterEntries(metadata, params);\n\treturn parts.length ? `(${parts.map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join(\",\")})` : \"\";\n}\n\n/**\n * Собирает query string-параметры для FunctionImport.\n */\nexport function buildFunctionImportParameters(metadata: FunctionImportMetadata, params: WrappedODataParameters): URLSearchParams {\n\tconst searchParams = new URLSearchParams();\n\n\tfor (const [key, value] of buildParameterEntries(metadata, params)) {\n\t\tsearchParams.set(key, value);\n\t}\n\n\treturn searchParams;\n}\n\nexport function buildEntityOperationPath(\n\tmetadata: EntityMetadata,\n\tconfig: ODataServiceConfig,\n\tparams: WrappedODataParameters,\n\tmethod: Exclude<ODataOperationMethod, \"fi\">\n): string {\n\tconst basePath = `/${config.service}/${config.target}`;\n\n\tif (method === \"create\") {\n\t\treturn basePath;\n\t}\n\n\tif (method === \"query\") {\n\t\tif (!metadata.result) {\n\t\t\tif (__DEV__) {\n\t\t\t\tif (Object.keys(params).length > 0) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`Параметры для query-запроса '/${config.service}/${config.target}' проигнорированы: target не поддерживает parameterized query.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn basePath;\n\t\t}\n\n\t\treturn buildEntityPath(metadata, config, params);\n\t}\n\n\tconst parameters = buildEntityParameters(metadata, params);\n\treturn `${basePath}${parameters}`;\n}\n\n/**\n * Собирает строку запроса к FunctionImport.\n */\nexport function buildFunctionImportPath(\n\tmetadata: FunctionImportMetadata,\n\tconfig: ODataServiceConfig,\n\tparams: WrappedODataParameters\n): string {\n\tconst searchParams = buildFunctionImportParameters(metadata, params);\n\tconst queryString = searchParams.toString();\n\tconst path = `/${config.service}/${config.target}`;\n\n\treturn queryString ? `${path}?${queryString}` : path;\n}\n\n/**\n * Собирает строку запроса к EntitySet\n */\nexport function buildEntityPath(metadata: EntityMetadata, config: ODataServiceConfig, params: WrappedODataParameters): string {\n\tconst parameters = buildEntityParameters(metadata, params);\n\tconst navigation = metadata.result ? `/${metadata.result}` : \"\";\n\n\treturn `/${config.service}/${config.target}${parameters}${navigation}`;\n}\n","import { EntityColumnProperty } from \"./types\";\n\n/**\n * Возвращает code-like filterable-колонки.\n */\nexport function collectFilterableColumns(columns: readonly Readonly<EntityColumnProperty>[]): Readonly<EntityColumnProperty>[] {\n\treturn columns.filter((column) => column.semanticType === \"code\" && column.filterable);\n}\n\n/**\n * Возвращает идентификаторы code-like filterable-колонок.\n */\nexport function collectFilterableColumnsIds(columns: readonly Readonly<EntityColumnProperty>[]): Readonly<Set<string>> {\n\treturn new Set(collectFilterableColumns(columns).map((c) => c.id));\n}\n","import { odataFormatValue } from \"./formatters\";\n\nimport type { BaseType, RowRecord } from \"../types\";\nimport type { ODataMetaType } from \"./types\";\n\nexport const FilterOperation = Object.freeze({\n\teq: \"eq\",\n\tne: \"ne\",\n\tgt: \"gt\",\n\tge: \"ge\",\n\tlt: \"lt\",\n\tle: \"le\",\n\tstartswith: \"startswith\",\n\tendswith: \"endswith\",\n\tcontains: \"contains\"\n} as const);\n\nexport type FilterOperation = (typeof FilterOperation)[keyof typeof FilterOperation];\n\nexport const FILTER_OPERATIONS = Object.freeze(Object.values(FilterOperation)) as readonly FilterOperation[];\n\nconst FILTER_OPERATION_LABELS: Readonly<Record<FilterOperation, string>> = Object.freeze({\n\teq: \"равно\",\n\tne: \"не равно\",\n\tgt: \"больше\",\n\tge: \"больше или равно\",\n\tlt: \"меньше\",\n\tle: \"меньше или равно\",\n\tstartswith: \"начинается с\",\n\tendswith: \"заканчивается на\",\n\tcontains: \"содержит\"\n});\n\nconst FILTER_OPERATION_SET: ReadonlySet<string> = new Set(FILTER_OPERATIONS);\n\nexport function isFilterOperation(value: unknown): value is FilterOperation {\n\treturn typeof value === \"string\" && FILTER_OPERATION_SET.has(value);\n}\n\nexport function resolveOperationLabel(operation: FilterOperation): string {\n\treturn FILTER_OPERATION_LABELS[operation];\n}\n\nexport interface FilterCondition<T> {\n\tkey: keyof T;\n\tvalue: BaseType;\n\toperation?: FilterOperation;\n\ttype?: ODataMetaType;\n}\n\n// Базовый интерфейс для выражения\nexport interface BaseFilterExpression {\n\t/**\n\t * @default false (or)\n\t */\n\tand?: boolean;\n}\n\n// Выражение с условиями (лист дерева)\nexport interface FilterConditionExpression<T> extends BaseFilterExpression {\n\tconditions: FilterCondition<T>[];\n\tfilters?: never; // Делаем явно недоступным\n}\n\n// Выражение с вложенными фильтрами (узел дерева)\nexport interface FilterNestedExpression<T> extends BaseFilterExpression {\n\tfilters: FilterExpression<T>[];\n\tconditions?: never; // Делаем явно недоступным\n}\n\n// Объединенный тип\nexport type FilterExpression<T> = FilterConditionExpression<T> | FilterNestedExpression<T>;\n\nfunction getODataTypeFromValue(value: unknown): ODataMetaType {\n\tswitch (typeof value) {\n\t\tcase \"bigint\":\n\t\tcase \"number\":\n\t\t\t// NOTE: тут теперь может возникнуть проблема, когда нужен будет long\n\t\t\treturn \"int\";\n\t\tcase \"boolean\":\n\t\t\treturn \"boolean\";\n\t\tcase \"object\":\n\t\t\tif (value instanceof Date) {\n\t\t\t\treturn \"datetime\";\n\t\t\t}\n\t}\n\n\treturn \"string\";\n}\n\n// Функция для построения условия\nfunction buildCondition<T>(condition: FilterCondition<T>): string {\n\tconst { key, operation = \"eq\", value, type } = condition;\n\tconst odataType = type ?? getODataTypeFromValue(value);\n\tconst escapedValue = odataFormatValue(odataType, value);\n\n\t// Специальные операторы для строк\n\tif (operation === \"contains\") {\n\t\treturn `substringof(${escapedValue},${String(key)})`;\n\t}\n\n\tif (operation === \"startswith\" || operation === \"endswith\") {\n\t\treturn `${operation}(${String(key)}, ${escapedValue})`;\n\t}\n\n\t// Стандартные операторы\n\treturn `${String(key)} ${operation} ${escapedValue}`;\n}\n\n// Type guards\nfunction isConditionExpression<T>(expr: FilterExpression<T>): expr is FilterConditionExpression<T> {\n\treturn \"conditions\" in expr && expr.conditions !== undefined;\n}\n\nfunction isNestedExpression<T>(expr: FilterExpression<T>): expr is FilterNestedExpression<T> {\n\treturn \"filters\" in expr && expr.filters !== undefined;\n}\n\nfunction compactExpressionStrings<T>(filters: FilterExpression<T>[], build: (expression: FilterExpression<T>) => string): string[] {\n\t// return filters.map((filter) => build(filter)).filter(Boolean);\n\tconst result: string[] = [];\n\n\tfor (const filter of filters) {\n\t\tconst value = build(filter);\n\t\tif (value) {\n\t\t\tresult.push(value);\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// Основная функция\nexport function buildODataFilter<T>(expression: FilterExpression<T> | undefined): string {\n\tif (!expression) return \"\";\n\n\tif (isConditionExpression(expression)) {\n\t\t// Обработка выражения с условиями\n\t\tconst { conditions, and = false } = expression;\n\n\t\tif (conditions.length === 0) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (conditions.length === 1) {\n\t\t\treturn buildCondition(conditions[0]);\n\t\t}\n\n\t\tconst operator = and ? \"and\" : \"or\";\n\t\tconst conditionsString = conditions.map(buildCondition).join(` ${operator} `);\n\t\treturn `(${conditionsString})`;\n\t}\n\n\tif (isNestedExpression(expression)) {\n\t\t// Обработка вложенного выражения\n\t\tconst { filters, and = false } = expression;\n\n\t\tif (filters.length === 0) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (filters.length === 1) {\n\t\t\treturn buildODataFilter(filters[0]);\n\t\t}\n\n\t\tconst operator = and ? \"and\" : \"or\";\n\t\tconst filterStrings = compactExpressionStrings(filters, buildODataFilter);\n\n\t\tif (filterStrings.length === 0) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (filterStrings.length === 1) {\n\t\t\treturn filterStrings[0];\n\t\t}\n\n\t\treturn `(${filterStrings.join(` ${operator} `)})`;\n\t}\n\n\tthrow new Error(\"Некорректное выражение фильтра\");\n}\n\n// Альтернативная версия с рекурсивной обработкой\nexport function buildODataFilterRecursive<T>(expression: FilterExpression<T> | undefined): string {\n\tconst processExpression = (expr: FilterExpression<T> | undefined): string => {\n\t\tif (!expr) return \"\";\n\n\t\tif (isConditionExpression(expr)) {\n\t\t\tconst { conditions, and = false } = expr;\n\n\t\t\tif (conditions.length === 0) return \"\";\n\t\t\tif (conditions.length === 1) return buildCondition(conditions[0]);\n\n\t\t\tconst operator = and ? \"and\" : \"or\";\n\t\t\treturn `(${conditions.map(buildCondition).join(` ${operator} `)})`;\n\t\t}\n\n\t\tif (isNestedExpression(expr)) {\n\t\t\tconst { filters, and = false } = expr;\n\n\t\t\tif (filters.length === 0) return \"\";\n\t\t\tif (filters.length === 1) return processExpression(filters[0]);\n\n\t\t\tconst operator = and ? \"and\" : \"or\";\n\t\t\tconst filterStrings = compactExpressionStrings(filters, processExpression).map((result) => {\n\t\t\t\treturn result.includes(\" \") ? `(${result})` : result;\n\t\t\t});\n\n\t\t\tif (filterStrings.length === 0) return \"\";\n\t\t\tif (filterStrings.length === 1) return filterStrings[0];\n\n\t\t\treturn `(${filterStrings.join(` ${operator} `)})`;\n\t\t}\n\n\t\treturn \"\";\n\t};\n\n\treturn processExpression(expression);\n}\n\nexport function createFilter<T, V extends BaseType>(\n\tkey: keyof T,\n\tvalue: (V | V[]) | null | undefined,\n\toperation: FilterOperation\n): FilterExpression<T> {\n\tif (value === null || value === undefined) return { conditions: [] };\n\n\tif (Array.isArray(value)) {\n\t\t// return {\n\t\t// \tconditions: value.filter((item) => item !== null || item !== undefined).map((item) => ({ key, value: item, operation }))\n\t\t// };\n\t\tconst conditions: FilterCondition<T>[] = [];\n\n\t\tfor (const item of value) {\n\t\t\tif (item !== null && item !== undefined) {\n\t\t\t\tconditions.push({ key, value: item, operation });\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tconditions\n\t\t};\n\t}\n\n\treturn {\n\t\tconditions: [{ key, value, operation }]\n\t};\n}\n\n/**\n * Создает выражение фильтра (`FilterExpression`)\n *\n * Пример конечного выражения:\n *\n * * псевдокод `(key ge odataFormatValue(value[0]) and key le odataFormatValue(value[1]))`\n * * результат `(COST eq 2000 and COST eq 5000)`\n */\nexport function createFilterBetween<T, V extends BaseType>(key: keyof T, values: readonly [V, V] | null | undefined): FilterExpression<T> {\n\tif (!values) return { conditions: [] };\n\n\tconst value1 = values[0];\n\tconst value2 = values[1];\n\n\tif (value1 === null || value1 === undefined || value2 === null || value2 === undefined) {\n\t\tif (value1) {\n\t\t\treturn {\n\t\t\t\tconditions: [{ key, value: value1, operation: \"ge\" }]\n\t\t\t};\n\t\t}\n\t\tif (value2) {\n\t\t\treturn {\n\t\t\t\tconditions: [{ key, value: value2, operation: \"le\" }]\n\t\t\t};\n\t\t}\n\t\treturn { conditions: [] };\n\t}\n\n\treturn {\n\t\tand: true,\n\t\tconditions: [\n\t\t\t{ key, value: value1, operation: \"ge\" },\n\t\t\t{ key, value: value2, operation: \"le\" }\n\t\t]\n\t};\n}\n\n/**\n * Создает выражение фильтра (`FilterExpression`)\n *\n * Пример конечного выражения:\n *\n * * псевдокод `key eq odataFormatValue(value)`\n * * результат `CUSTOMER eq '005417554'`\n *\n * Если `value` массив, то выражение формируется с оператором `or`: `(E1 or E2 or E3)`\n */\nexport function createFilterEqual<T, V extends BaseType>(key: keyof T, value: (V | V[]) | null | undefined): FilterExpression<T> {\n\treturn createFilter(key, value, \"eq\");\n}\n\nexport function createFilterEqualFalsy<T, V extends BaseType>(key: keyof T, value: (V | V[]) | null | undefined): FilterExpression<T> {\n\treturn createFilter(key, Array.isArray(value) ? value.map((v) => v || null) : value || null, \"eq\");\n}\n\n/**\n * Создает выражение фильтра (`FilterExpression`)\n *\n * Пример конечного выражения:\n *\n * * псевдокод `substringof(odataFormatValue(value), key)`\n * * результат `substringof('сталь', CUSTOMER)`\n *\n * Если `value` массив, то выражение формируется с оператором `or`: `(E1 or E2 or E3)`\n */\nexport function createFilterContains<T, V extends BaseType>(key: keyof T, value: (V | V[]) | null | undefined): FilterExpression<T> {\n\treturn createFilter(key, value, \"contains\");\n}\n\nexport function mergeFilterExpressions(\n\tleft?: FilterExpression<RowRecord>,\n\tright?: FilterExpression<RowRecord>\n): FilterExpression<RowRecord> | undefined {\n\tif (!left) return right;\n\tif (!right) return left;\n\n\treturn {\n\t\tand: true,\n\t\tfilters: [left, right]\n\t};\n}\n","import { compareStrings } from \"../string-comparison\";\nimport { BaseType, InputType } from \"../types\";\n\nimport { createFilterEqual, type FilterCondition, type FilterExpression, type FilterOperation } from \"./filters\";\n\nimport type { BaseMetaType, ODataChainsMap } from \"./types\";\n\ntype RowRecord = Record<string, unknown>;\ntype TreeFilterValue = Record<string, string[]>;\n\nexport type ODataFilterValue = InputType | TreeFilterValue;\nexport type ODataFilterValues = Record<string, ODataFilterValue>;\n\n/**\n * Одно условие OData-фильтра, которое может применяться не только к owner-колонке\n * фильтра, но и к явно выбранной колонке. Это нужно для локальных Select/MultiSelect:\n * один runtime-контрол выбирает option, а option уже знает, какую колонку таблицы\n * фильтровать и каким значением.\n */\nexport type ODataFilterCondition = {\n\t/**\n\t * Целевая колонка условия. Если не задана, компилятор использует ownerColumnId\n\t * фильтра, что сохраняет простую модель для обычных локальных value/boolean\n\t * фильтров и OData-сегментов.\n\t */\n\tcolumnId?: string;\n\toperation: FilterOperation;\n\tvalueSource: \"static\" | \"input\";\n\tvalue?: BaseType;\n};\n\nexport type ODataFilterConditionGroup = {\n\tand?: boolean;\n\tconditions: ODataFilterCondition[];\n};\n\nexport type ODataFilterOption = {\n\tkey: string;\n\tlabel: string;\n\tfilter?: ODataFilterConditionGroup;\n};\n\nexport type ODataFilterBinding =\n\t| {\n\t\t\tkind: \"list\";\n\t\t\t/** Связка выражений нескольких выбранных опций: `false`/отсутствие означает OR. */\n\t\t\tand?: boolean;\n\t\t\toptions: ODataFilterOption[];\n\t }\n\t| {\n\t\t\tkind: \"boolean\";\n\t\t\ttrueFilter?: ODataFilterConditionGroup;\n\t }\n\t| {\n\t\t\tkind: \"value\";\n\t\t\tvalueFilter?: ODataFilterConditionGroup;\n\t };\n\nexport type FilterDefinitionKind = \"segment\" | \"tree\" | \"advanced\" | \"local\" | \"registered\" | \"column\";\n\n/** Форма controlled-значения зарегистрированного фильтра. */\nexport type FilterRegisteredValueMode = \"single\" | \"multiple\";\n\nexport type FilterSegmentComponentId = \"multi-select\" | \"select\";\nexport type FilterTreeComponentId = \"tree-select\" | \"tree-multi-select\";\nexport type FilterLocalComponentId = \"select\" | \"multi-select\" | \"checkbox\" | \"text-input\" | \"number-input\";\nexport type FilterAdvancedComponentId = \"advanced-search-select\";\nexport type FilterComponentId = FilterSegmentComponentId | FilterTreeComponentId | FilterLocalComponentId | FilterAdvancedComponentId;\n\n// TODO: переименовать, теперь это не только odata\nexport type ODataCompiledFilterDefinition =\n\t| {\n\t\t\tid: string;\n\t\t\townerColumnId: string;\n\t\t\tcolumnIds: string[];\n\t\t\tkind: Extract<FilterDefinitionKind, \"segment\">;\n\t\t\tcomponentId: FilterSegmentComponentId;\n\t\t\tcontrolType: BaseMetaType;\n\t\t\tdictionaryCodeKey?: string;\n\t }\n\t| {\n\t\t\tid: string;\n\t\t\townerColumnId: string;\n\t\t\tcolumnIds: string[];\n\t\t\tkind: Extract<FilterDefinitionKind, \"tree\">;\n\t\t\tcomponentId: FilterTreeComponentId;\n\t\t\tcontrolType: BaseMetaType;\n\t\t\t/** Оператор между выбранными значениями разных уровней дерева. */\n\t\t\tlevelOperator?: \"and\" | \"or\";\n\t }\n\t| {\n\t\t\tid: string;\n\t\t\townerColumnId: string;\n\t\t\tcolumnIds: string[];\n\t\t\tkind: Extract<FilterDefinitionKind, \"local\">;\n\t\t\tcomponentId: FilterLocalComponentId;\n\t\t\tcontrolType: BaseMetaType;\n\t\t\tbinding: ODataFilterBinding;\n\t }\n\t| {\n\t\t\tid: string;\n\t\t\tkind: Extract<FilterDefinitionKind, \"registered\">;\n\t\t\t/** Id непрозрачного runtime-компонента из внешнего registry. */\n\t\t\tcomponentId: string;\n\t\t\tcontrolType: BaseMetaType;\n\t\t\tvalueMode: FilterRegisteredValueMode;\n\t\t\t/** Потенциально затрагиваемые физические колонки, производные от binding. */\n\t\t\tcolumnIds: string[];\n\t\t\t/** Отсутствует у parameter-only фильтра, который не формирует `$filter`. */\n\t\t\tbinding?: ODataFilterBinding;\n\t }\n\t| {\n\t\t\tid: string;\n\t\t\townerColumnId: string;\n\t\t\tkind: Extract<FilterDefinitionKind, \"advanced\">;\n\t\t\tcomponentId: FilterAdvancedComponentId;\n\t\t\tconfigId: string;\n\t }\n\t| {\n\t\t\tid: string;\n\t\t\townerColumnId: string;\n\t\t\tkind: Extract<FilterDefinitionKind, \"column\">;\n\t };\n\nexport function isFilterLocalComponentId(value: unknown): value is FilterLocalComponentId {\n\treturn value === \"select\" || value === \"multi-select\" || value === \"checkbox\" || value === \"text-input\" || value === \"number-input\";\n}\n\n/**\n * Собирает физические колонки, которые реально затрагивает группа условий.\n * Для conditions без columnId берём fallback owner-колонку: это важно для старого\n * поведения value/boolean-фильтров и для conditions, где колонка не выбирается явно.\n */\nfunction collectConditionGroupColumnIds(group: ODataFilterConditionGroup | undefined, fallbackColumnId: string) {\n\tif (!group?.conditions.length) return [];\n\n\treturn group.conditions.map((condition) => condition.columnId?.trim() || fallbackColumnId).filter((columnId) => Boolean(columnId));\n}\n\n/**\n * Выводит `columnIds` локального фильтра из его binding. Раньше local-фильтр всегда\n * владел только ownerColumnId, но list-option теперь может фильтровать любую\n * доступную visible/data колонку, поэтому runtime и конфликты фильтров должны\n * видеть полный набор затронутых колонок.\n */\nfunction collectBindingColumnIds(binding: ODataFilterBinding, fallbackColumnId: string) {\n\tconst columnIds =\n\t\tbinding.kind === \"list\"\n\t\t\t? binding.options.flatMap((option) => collectConditionGroupColumnIds(option.filter, fallbackColumnId))\n\t\t\t: binding.kind === \"boolean\"\n\t\t\t\t? collectConditionGroupColumnIds(binding.trueFilter, fallbackColumnId)\n\t\t\t\t: collectConditionGroupColumnIds(binding.valueFilter, fallbackColumnId);\n\n\treturn [...new Set(columnIds.length ? columnIds : fallbackColumnId ? [fallbackColumnId] : [])];\n}\n\nfunction resolveConditionGroupColumnIds(group: ODataFilterConditionGroup | undefined, fallbackColumnId: string) {\n\tconst columnIds = collectConditionGroupColumnIds(group, fallbackColumnId);\n\treturn columnIds.length ? columnIds : fallbackColumnId ? [fallbackColumnId] : [];\n}\n\ntype ListFilterDefinition = Extract<ODataCompiledFilterDefinition, { kind: \"local\" | \"registered\" }>;\n\nfunction isMultipleListFilterDefinition(definition: ListFilterDefinition) {\n\treturn definition.kind === \"registered\" ? definition.valueMode === \"multiple\" : definition.componentId === \"multi-select\";\n}\n\n/** Нормализует option keys и сохраняет пустую строку как допустимый выбор. */\nfunction sanitizeFilterOptionKeys(value: unknown): string[] {\n\tif (!Array.isArray(value)) return [];\n\n\treturn [...new Set(value.filter((item): item is string => typeof item === \"string\").map((item) => item.trim()))];\n}\n\nfunction resolveListFilterSelectedKeys(definition: ListFilterDefinition, value: ODataFilterValue) {\n\tif (isMultipleListFilterDefinition(definition)) {\n\t\treturn sanitizeFilterOptionKeys(value);\n\t}\n\n\tconst selectedValue = sanitizeScalarValue(value);\n\treturn typeof selectedValue === \"string\" ? [selectedValue] : [];\n}\n\n/**\n * Возвращает все физические колонки, которые потенциально затрагивает filter definition.\n *\n * Helper нужен runtime-проекциям, где важно понять совместимость фильтра с\n * конкретным OData target без повторной реализации правил compiler-а.\n */\nexport function resolveODataFilterDefinitionColumnIds(definition: ODataCompiledFilterDefinition): string[] {\n\tconst normalizedDefinition = sanitizeFilterDefinitions([definition])[0];\n\tif (!normalizedDefinition) return [];\n\n\tif (normalizedDefinition.kind === \"registered\") {\n\t\treturn [...normalizedDefinition.columnIds];\n\t}\n\n\tif (normalizedDefinition.kind === \"segment\" || normalizedDefinition.kind === \"column\" || normalizedDefinition.kind === \"advanced\") {\n\t\treturn [normalizedDefinition.ownerColumnId];\n\t}\n\n\treturn [...normalizedDefinition.columnIds];\n}\n\n/**\n * Возвращает физические колонки, которые реально затрагивает текущее значение фильтра.\n *\n * Для local list учитываются только выбранные option-ы, поэтому фильтр с\n * несколькими потенциальными колонками не блокирует target, если активный выбор\n * обращается только к доступным колонкам.\n */\nexport function resolveODataFilterDefinitionActiveColumnIds(\n\tdefinition: ODataCompiledFilterDefinition,\n\tvalue: ODataFilterValue | undefined\n): string[] {\n\tconst normalizedDefinition = sanitizeFilterDefinitions([definition])[0];\n\tconst normalizedValue = sanitizeFilterValue(value);\n\tif (!normalizedDefinition || normalizedValue === undefined) return [];\n\n\tswitch (normalizedDefinition.kind) {\n\t\tcase \"segment\":\n\t\tcase \"column\":\n\t\tcase \"advanced\": {\n\t\t\treturn [normalizedDefinition.ownerColumnId];\n\t\t}\n\n\t\tcase \"tree\": {\n\t\t\tconst treeValue = sanitizeTreeFilterValue(normalizedValue);\n\t\t\tif (!treeValue) return [];\n\t\t\treturn Object.keys(treeValue).filter((columnId) => normalizedDefinition.columnIds.includes(columnId));\n\t\t}\n\n\t\tcase \"local\": {\n\t\t\tif (normalizedDefinition.binding.kind === \"list\") {\n\t\t\t\tconst selectedKeys = resolveListFilterSelectedKeys(normalizedDefinition, normalizedValue);\n\t\t\t\treturn [\n\t\t\t\t\t...new Set(\n\t\t\t\t\t\tselectedKeys.flatMap((selectedKey) => {\n\t\t\t\t\t\t\tconst option =\n\t\t\t\t\t\t\t\tnormalizedDefinition.binding.kind === \"list\"\n\t\t\t\t\t\t\t\t\t? normalizedDefinition.binding.options.find((item) => item.key === selectedKey)\n\t\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\t\tif (!option) return [];\n\t\t\t\t\t\t\treturn resolveConditionGroupColumnIds(option.filter, normalizedDefinition.ownerColumnId);\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t];\n\t\t\t}\n\n\t\t\tif (normalizedDefinition.binding.kind === \"boolean\") {\n\t\t\t\treturn normalizedValue === true\n\t\t\t\t\t? resolveConditionGroupColumnIds(normalizedDefinition.binding.trueFilter, normalizedDefinition.ownerColumnId)\n\t\t\t\t\t: [];\n\t\t\t}\n\n\t\t\treturn resolveConditionGroupColumnIds(normalizedDefinition.binding.valueFilter, normalizedDefinition.ownerColumnId);\n\t\t}\n\n\t\tcase \"registered\": {\n\t\t\tconst binding = normalizedDefinition.binding;\n\t\t\tif (!binding) return [];\n\n\t\t\tif (binding.kind === \"list\") {\n\t\t\t\tconst selectedKeys = resolveListFilterSelectedKeys(normalizedDefinition, normalizedValue);\n\t\t\t\treturn [\n\t\t\t\t\t...new Set(\n\t\t\t\t\t\tselectedKeys.flatMap((selectedKey) => {\n\t\t\t\t\t\t\tconst option = binding.options.find((item) => item.key === selectedKey);\n\t\t\t\t\t\t\treturn option ? resolveConditionGroupColumnIds(option.filter, \"\") : [];\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t];\n\t\t\t}\n\n\t\t\tif (binding.kind === \"boolean\") {\n\t\t\t\treturn normalizedValue === true ? resolveConditionGroupColumnIds(binding.trueFilter, \"\") : [];\n\t\t\t}\n\n\t\t\treturn resolveConditionGroupColumnIds(binding.valueFilter, \"\");\n\t\t}\n\n\t\tdefault: {\n\t\t\tconst _checker: never = normalizedDefinition;\n\t\t\tvoid _checker;\n\t\t\treturn [];\n\t\t}\n\t}\n}\n\nexport function normalizeDictionaryCodeKey(value: string | undefined, ownerColumnId: string) {\n\tconst normalized = value?.trim();\n\treturn normalized && normalized !== ownerColumnId ? normalized : undefined;\n}\n\nfunction sanitizeScalarValue(value: unknown): BaseType | undefined {\n\tif (value instanceof Date) {\n\t\treturn Number.isFinite(value.getTime()) ? value : undefined;\n\t}\n\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim();\n\t\t// NOTE: 08.06.2026 разрешаем в фильтр передавать пустую строку\n\t\t// return normalized ? normalized : undefined;\n\t\treturn normalized;\n\t}\n\n\tif (typeof value === \"number\") {\n\t\treturn Number.isFinite(value) ? value : undefined;\n\t}\n\n\tif (typeof value === \"boolean\") {\n\t\treturn value;\n\t}\n\n\treturn undefined;\n}\n\nfunction serializeBaseValue(value: BaseType) {\n\tif (value instanceof Date) {\n\t\treturn `date:${value.toISOString()}`;\n\t}\n\n\treturn `${typeof value}:${String(value)}`;\n}\n\nfunction sanitizeArrayValue(value: unknown): BaseType[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\n\tconst seen = new Set<string>();\n\tconst normalized: BaseType[] = [];\n\n\tfor (const item of value) {\n\t\tconst nextValue = sanitizeScalarValue(item);\n\t\tif (nextValue === undefined) continue;\n\n\t\tconst key = serializeBaseValue(nextValue);\n\t\tif (seen.has(key)) continue;\n\t\tseen.add(key);\n\t\tnormalized.push(nextValue);\n\t}\n\n\tnormalized.sort((left, right) => compareStrings(serializeBaseValue(left), serializeBaseValue(right)));\n\n\treturn normalized.length ? normalized : undefined;\n}\n\nfunction sanitizeStringArray(value: unknown): string[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\n\tconst normalized = [\n\t\t...new Set(\n\t\t\tvalue\n\t\t\t\t.filter((item): item is string => typeof item === \"string\")\n\t\t\t\t.map((item) => item.trim())\n\t\t\t\t.filter(Boolean)\n\t\t)\n\t]; // .sort();\n\treturn normalized.length ? normalized : undefined;\n}\n\nfunction sanitizeTreeFilterValue(value: unknown): TreeFilterValue | undefined {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value) || value instanceof Date) return undefined;\n\n\tconst normalized = Object.fromEntries(\n\t\tObject.entries(value)\n\t\t\t.map(([columnId, rawValues]) => [columnId.trim(), sanitizeStringArray(rawValues)] as const)\n\t\t\t.filter((entry): entry is [string, string[]] => Boolean(entry[0]) && Boolean(entry[1]?.length))\n\t);\n\n\treturn Object.keys(normalized).length ? normalized : undefined;\n}\n\nexport function sanitizeFilterConditionGroup(group: ODataFilterConditionGroup | undefined): ODataFilterConditionGroup | undefined {\n\tif (!group?.conditions?.length) return undefined;\n\n\tconst conditions: ODataFilterCondition[] = [];\n\n\tfor (const condition of group.conditions) {\n\t\tconst value = sanitizeScalarValue(condition.value);\n\t\tif (condition.valueSource === \"static\" && value === undefined) continue;\n\n\t\tconditions.push({\n\t\t\tcolumnId: condition.columnId?.trim() || undefined,\n\t\t\toperation: condition.operation,\n\t\t\tvalueSource: condition.valueSource,\n\t\t\tvalue\n\t\t});\n\t}\n\n\tif (!conditions.length) return undefined;\n\n\treturn {\n\t\tand: group.and === false ? false : group.and ? true : undefined,\n\t\tconditions\n\t};\n}\n\nexport function sanitizeFilterBinding(binding: ODataFilterBinding | undefined): ODataFilterBinding | undefined {\n\tif (!binding) return undefined;\n\n\tif (binding.kind === \"list\") {\n\t\tconst options: ODataFilterOption[] = [];\n\t\t// const keysSet = new Set<string>();\n\n\t\tfor (const option of binding.options ?? []) {\n\t\t\tconst key = option.key.trim();\n\t\t\t// NOTE: пустой ключ разрешаем\n\t\t\t// TODO: подумать, допустимо ли дублирование\n\t\t\t// if (keysSet.has(key)) continue;\n\t\t\t// keysSet.add(key);\n\n\t\t\toptions.push({\n\t\t\t\tkey,\n\t\t\t\tlabel: option.label.trim() || key,\n\t\t\t\tfilter: sanitizeFilterConditionGroup(option.filter)\n\t\t\t});\n\t\t}\n\n\t\tif (!options.length) return undefined;\n\n\t\tconst and = binding.and === true ? true : binding.and === false ? false : undefined;\n\t\treturn {\n\t\t\tkind: \"list\",\n\t\t\t...(and === undefined ? {} : { and }),\n\t\t\toptions\n\t\t};\n\t}\n\n\tif (binding.kind === \"boolean\") {\n\t\treturn {\n\t\t\tkind: \"boolean\",\n\t\t\ttrueFilter: sanitizeFilterConditionGroup(binding.trueFilter)\n\t\t};\n\t}\n\n\treturn {\n\t\tkind: \"value\",\n\t\tvalueFilter: sanitizeFilterConditionGroup(binding.valueFilter)\n\t};\n}\n\nexport function sanitizeFilterDefinitions<T extends ODataCompiledFilterDefinition>(definitions?: readonly T[]): T[] {\n\tif (!definitions?.length) return [];\n\n\tconst normalized: T[] = [];\n\n\tfor (const definition of definitions) {\n\t\tconst id = definition.id.trim();\n\t\tif (!id) continue;\n\t\t/*\n\t\t * Sanitizer может получать readonly snapshot из Zustand/Immer. Legacy-поля\n\t\t * нормализуем только на локальной копии, чтобы чтение конфигурации никогда\n\t\t * не изменяло и не пыталось разморозить входной объект.\n\t\t */\n\t\tconst normalizedDefinition = { ...definition };\n\n\t\t// HACK: на период пересохранения всех конфигов\n\t\tif ((normalizedDefinition.kind as string) === \"odata-segment\") {\n\t\t\tnormalizedDefinition.kind = \"segment\";\n\t\t}\n\t\tif ((normalizedDefinition.kind as string) === \"odata-tree\") {\n\t\t\tnormalizedDefinition.kind = \"tree\";\n\t\t}\n\n\t\tif (normalizedDefinition.kind === \"registered\") {\n\t\t\tconst componentId = normalizedDefinition.componentId.trim();\n\t\t\tconst valueMode = normalizedDefinition.valueMode;\n\t\t\tif (!componentId || (valueMode !== \"single\" && valueMode !== \"multiple\")) continue;\n\n\t\t\tconst binding = sanitizeFilterBinding(normalizedDefinition.binding);\n\t\t\tnormalized.push({\n\t\t\t\t...normalizedDefinition,\n\t\t\t\tid,\n\t\t\t\tcomponentId,\n\t\t\t\tvalueMode,\n\t\t\t\tcolumnIds: binding ? collectBindingColumnIds(binding, \"\") : [],\n\t\t\t\tbinding\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst ownerColumnId = normalizedDefinition.ownerColumnId.trim();\n\t\tif (!ownerColumnId) continue;\n\n\t\tswitch (normalizedDefinition.kind) {\n\t\t\tcase \"segment\": {\n\t\t\t\tnormalized.push({\n\t\t\t\t\t...normalizedDefinition,\n\t\t\t\t\tid,\n\t\t\t\t\townerColumnId,\n\t\t\t\t\tcolumnIds: [ownerColumnId],\n\t\t\t\t\tcomponentId: normalizedDefinition.componentId === \"select\" ? \"select\" : \"multi-select\",\n\t\t\t\t\tdictionaryCodeKey: normalizeDictionaryCodeKey(normalizedDefinition.dictionaryCodeKey, ownerColumnId)\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"tree\": {\n\t\t\t\tconst columnIds = [...new Set(normalizedDefinition.columnIds.map((columnId) => columnId.trim()).filter(Boolean))];\n\t\t\t\t/*\n\t\t\t\t * Визуальное дерево может иметь consumer-синтетический root, который не\n\t\t\t\t * участвует в серверном фильтре. Поэтому definition обязан содержать хотя\n\t\t\t\t * бы одно фильтруемое поле, но не обязан сериализовать два UI-уровня.\n\t\t\t\t */\n\t\t\t\tif (!columnIds.length) break;\n\n\t\t\t\t// HACK: на период пересохранения всех конфигов\n\t\t\t\tconst rawComponentId = normalizedDefinition.componentId as string;\n\t\t\t\tconst componentId =\n\t\t\t\t\trawComponentId === \"treeSelect\" || rawComponentId === \"tree-select\" ? \"tree-select\" : \"tree-multi-select\";\n\n\t\t\t\tnormalized.push({\n\t\t\t\t\t...normalizedDefinition,\n\t\t\t\t\tid,\n\t\t\t\t\townerColumnId: columnIds.includes(ownerColumnId) ? ownerColumnId : columnIds[0],\n\t\t\t\t\tcolumnIds,\n\t\t\t\t\tcomponentId,\n\t\t\t\t\tlevelOperator: normalizedDefinition.levelOperator === \"or\" ? \"or\" : undefined\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"local\": {\n\t\t\t\tconst binding = sanitizeFilterBinding(normalizedDefinition.binding);\n\t\t\t\tif (!binding) break;\n\n\t\t\t\tnormalized.push({\n\t\t\t\t\t...normalizedDefinition,\n\t\t\t\t\tid,\n\t\t\t\t\townerColumnId,\n\t\t\t\t\t// Для local-фильтров список колонок является производным от conditions.\n\t\t\t\t\t// Это делает Select/MultiSelect с option -> columnId частью общего\n\t\t\t\t\t// контракта фильтров без отдельной runtime-модели.\n\t\t\t\t\tcolumnIds: collectBindingColumnIds(binding, ownerColumnId),\n\t\t\t\t\tbinding\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"advanced\": {\n\t\t\t\tnormalized.push({\n\t\t\t\t\t...normalizedDefinition,\n\t\t\t\t\tid,\n\t\t\t\t\townerColumnId\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"column\": {\n\t\t\t\tnormalized.push({\n\t\t\t\t\t...normalizedDefinition,\n\t\t\t\t\tid,\n\t\t\t\t\townerColumnId\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst _checker: never = normalizedDefinition;\n\t\t\t\tvoid _checker;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn normalized;\n}\n\nexport function sanitizeFilterValue(value: ODataFilterValue | undefined): ODataFilterValue | undefined {\n\tif (value === null || value === undefined) return undefined;\n\n\tconst scalarValue = sanitizeScalarValue(value);\n\tif (scalarValue !== undefined) return scalarValue;\n\n\tconst arrayValue = sanitizeArrayValue(value);\n\tif (arrayValue) return arrayValue;\n\n\treturn sanitizeTreeFilterValue(value);\n}\n\nexport function sanitizeFilterValues(values?: ODataFilterValues): ODataFilterValues {\n\tif (!values) return {};\n\n\tconst normalized: ODataFilterValues = {};\n\n\tfor (const [key, value] of Object.entries(values)) {\n\t\tconst filterId = key.trim();\n\t\tif (!filterId) continue;\n\n\t\tconst nextValue = sanitizeFilterValue(value);\n\t\tif (nextValue === undefined) continue;\n\t\tnormalized[filterId] = nextValue;\n\t}\n\n\treturn normalized;\n}\n\nexport function mergeFilterValuePatch(values: ODataFilterValues | undefined, filterId: string, value: ODataFilterValue | undefined) {\n\tconst normalizedValues = sanitizeFilterValues(values);\n\tconst nextValues = { ...normalizedValues };\n\tconst nextValue = sanitizeFilterValue(value);\n\n\tif (nextValue === undefined) {\n\t\tdelete nextValues[filterId];\n\t\treturn nextValues;\n\t}\n\n\tnextValues[filterId] = nextValue;\n\treturn nextValues;\n}\n\nexport function collapseChainedODataSegmentFilterValues(\n\tvalues: ODataFilterValues,\n\todataSegmentIds: readonly string[],\n\tchains: ODataChainsMap\n): ODataFilterValues {\n\tif (!values || Object.keys(values).length === 0) return {};\n\n\tconst result: ODataFilterValues = {};\n\tconst codeToChain: Record<string, string> = {};\n\n\tfor (const [chainKey, chainItems] of Object.entries(chains)) {\n\t\tfor (const item of chainItems) {\n\t\t\tcodeToChain[item.codeKey] = chainKey;\n\t\t}\n\t}\n\n\tconst groupedByChain: Record<string, string[]> = {};\n\tconst odataSegmentIdSet = new Set(odataSegmentIds);\n\n\tfor (const [filterId, value] of Object.entries(values)) {\n\t\tconst chainKey = codeToChain[filterId];\n\t\tconst isODataSegment = odataSegmentIdSet.has(filterId);\n\t\tconst isListValue = Array.isArray(value) || typeof value === \"string\";\n\n\t\tif (chainKey && isODataSegment && isListValue) {\n\t\t\tgroupedByChain[chainKey] = groupedByChain[chainKey] ?? [];\n\t\t\tgroupedByChain[chainKey].push(filterId);\n\t\t\tcontinue;\n\t\t}\n\n\t\tresult[filterId] = value;\n\t}\n\n\tfor (const [chainKey, filterIds] of Object.entries(groupedByChain)) {\n\t\tconst chain = chains[chainKey];\n\t\tif (!chain) continue;\n\n\t\tlet deepestFilterId: string | null = null;\n\t\tfor (const { codeKey } of [...chain].reverse()) {\n\t\t\tif (filterIds.includes(codeKey)) {\n\t\t\t\tdeepestFilterId = codeKey;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (deepestFilterId && values[deepestFilterId] !== undefined) {\n\t\t\tresult[deepestFilterId] = values[deepestFilterId];\n\t\t}\n\t}\n\n\treturn result;\n}\n\nfunction resolveExpressionValue(valueSource: \"static\" | \"input\", value: ODataFilterValue | BaseType | undefined) {\n\tif (valueSource === \"static\") {\n\t\treturn sanitizeScalarValue(value);\n\t}\n\n\treturn sanitizeScalarValue(value);\n}\n\nfunction compileCondition(\n\townerColumnId: string,\n\tcondition: ODataFilterCondition,\n\tinputValue?: ODataFilterValue\n): FilterCondition<RowRecord> | undefined {\n\tconst value = resolveExpressionValue(condition.valueSource, condition.valueSource === \"input\" ? inputValue : condition.value);\n\tif (value === undefined) return undefined;\n\tconst targetColumnId = condition.columnId?.trim() || ownerColumnId;\n\tif (!targetColumnId) return undefined;\n\n\treturn {\n\t\t// columnId позволяет одному локальному list-контролу генерировать условия\n\t\t// по разным колонкам; ownerColumnId остаётся безопасным fallback для\n\t\t// простых фильтров и ранее созданных groups без явной колонки.\n\t\tkey: targetColumnId,\n\t\toperation: condition.operation,\n\t\tvalue\n\t};\n}\n\nfunction compileConditionGroup(\n\townerColumnId: string,\n\tgroup: ODataFilterConditionGroup | undefined,\n\tinputValue?: ODataFilterValue\n): FilterExpression<RowRecord> | undefined {\n\tif (!group?.conditions.length) return undefined;\n\n\tconst conditions = group.conditions\n\t\t.map((condition) => compileCondition(ownerColumnId, condition, inputValue))\n\t\t.filter((condition): condition is FilterCondition<RowRecord> => Boolean(condition));\n\n\tif (!conditions.length) return undefined;\n\n\treturn {\n\t\tand: group.and === false ? undefined : true,\n\t\tconditions\n\t};\n}\n\nfunction compileDefaultBooleanFilter(ownerColumnId: string) {\n\treturn createFilterEqual<RowRecord, true>(ownerColumnId, true);\n}\n\nfunction compileDefaultValueFilter(ownerColumnId: string, value: BaseType | BaseType[]) {\n\treturn createFilterEqual<RowRecord, BaseType>(ownerColumnId, value);\n}\n\nfunction compileTreeFilter(definition: Extract<ODataCompiledFilterDefinition, { kind: \"tree\" }>, value: ODataFilterValue | undefined) {\n\tconst treeValue = sanitizeTreeFilterValue(value);\n\tif (!treeValue) return undefined;\n\n\tconst filters = definition.columnIds\n\t\t.map((columnId) => {\n\t\t\tconst selectedValues = treeValue[columnId];\n\t\t\tif (!selectedValues?.length) return undefined;\n\n\t\t\treturn createFilterEqual<RowRecord, string>(columnId, selectedValues);\n\t\t})\n\t\t.filter((filter): filter is FilterExpression<RowRecord> => Boolean(filter));\n\n\tif (!filters.length) return undefined;\n\tif (filters.length === 1) return filters[0];\n\n\treturn {\n\t\tand: definition.levelOperator === \"or\" ? undefined : true,\n\t\tfilters\n\t};\n}\n\nfunction compileListFilter(definition: ListFilterDefinition, value: ODataFilterValue | undefined): FilterExpression<RowRecord> | undefined {\n\tif (!definition.binding || definition.binding.kind !== \"list\") return undefined;\n\tconst binding = definition.binding;\n\tconst selectedKeys = resolveListFilterSelectedKeys(definition, value);\n\tif (!selectedKeys.length) return undefined;\n\n\tconst fallbackColumnId = definition.kind === \"local\" ? definition.ownerColumnId : \"\";\n\tconst filters = selectedKeys\n\t\t.map((selectedKey) => {\n\t\t\tconst option = binding.options.find((item) => item.key === selectedKey);\n\t\t\tif (!option) return undefined;\n\n\t\t\tconst explicitFilter = compileConditionGroup(fallbackColumnId, option.filter);\n\t\t\tif (explicitFilter || definition.kind === \"registered\") return explicitFilter;\n\n\t\t\treturn compileDefaultValueFilter(definition.ownerColumnId, option.key);\n\t\t})\n\t\t.filter((filter): filter is FilterExpression<RowRecord> => Boolean(filter));\n\n\tif (!filters.length) return undefined;\n\tif (filters.length === 1) return filters[0];\n\n\treturn {\n\t\tand: binding.and === true ? true : undefined,\n\t\tfilters\n\t};\n}\n\nfunction compileDefinitionFilter(\n\tdefinition: ODataCompiledFilterDefinition,\n\tvalue: ODataFilterValue | undefined\n): FilterExpression<RowRecord> | undefined {\n\tif (value === undefined) return undefined;\n\n\tswitch (definition.kind) {\n\t\tcase \"segment\": {\n\t\t\tif (definition.componentId === \"select\") {\n\t\t\t\tconst scalarValue = sanitizeScalarValue(value);\n\t\t\t\treturn scalarValue !== undefined ? compileDefaultValueFilter(definition.ownerColumnId, scalarValue) : undefined;\n\t\t\t}\n\n\t\t\tconst arrayValue = sanitizeArrayValue(value);\n\t\t\treturn arrayValue?.length ? compileDefaultValueFilter(definition.ownerColumnId, arrayValue) : undefined;\n\t\t}\n\n\t\tcase \"tree\": {\n\t\t\treturn compileTreeFilter(definition, value);\n\t\t}\n\n\t\tcase \"local\": {\n\t\t\tif (definition.binding.kind === \"list\") {\n\t\t\t\treturn compileListFilter(definition, value);\n\t\t\t}\n\n\t\t\tif (definition.binding.kind === \"boolean\") {\n\t\t\t\tif (value !== true) return undefined;\n\t\t\t\treturn (\n\t\t\t\t\tcompileConditionGroup(definition.ownerColumnId, definition.binding.trueFilter) ??\n\t\t\t\t\tcompileDefaultBooleanFilter(definition.ownerColumnId)\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\tcompileConditionGroup(definition.ownerColumnId, definition.binding.valueFilter, value) ??\n\t\t\t\t(() => {\n\t\t\t\t\tconst scalarValue = sanitizeScalarValue(value);\n\t\t\t\t\tconst arrayValue = sanitizeArrayValue(value);\n\t\t\t\t\tconst defaultValue = scalarValue ?? arrayValue;\n\t\t\t\t\treturn defaultValue !== undefined ? compileDefaultValueFilter(definition.ownerColumnId, defaultValue) : undefined;\n\t\t\t\t})()\n\t\t\t);\n\t\t}\n\n\t\tcase \"registered\": {\n\t\t\tif (!definition.binding) return undefined;\n\n\t\t\tif (definition.binding.kind === \"list\") {\n\t\t\t\treturn compileListFilter(definition, value);\n\t\t\t}\n\n\t\t\tif (definition.binding.kind === \"boolean\") {\n\t\t\t\treturn value === true ? compileConditionGroup(\"\", definition.binding.trueFilter) : undefined;\n\t\t\t}\n\n\t\t\treturn compileConditionGroup(\"\", definition.binding.valueFilter, value);\n\t\t}\n\n\t\tcase \"column\": {\n\t\t\tconst scalarValue = sanitizeScalarValue(value);\n\t\t\tconst arrayValue = sanitizeArrayValue(value);\n\t\t\tconst defaultValue = scalarValue ?? arrayValue;\n\t\t\treturn defaultValue !== undefined ? compileDefaultValueFilter(definition.ownerColumnId, defaultValue) : undefined;\n\t\t}\n\n\t\tcase \"advanced\": {\n\t\t\tconst arrayValue = sanitizeArrayValue(value);\n\t\t\treturn arrayValue?.length ? compileDefaultValueFilter(definition.ownerColumnId, arrayValue) : undefined;\n\t\t}\n\n\t\tdefault: {\n\t\t\tconst _checker: never = definition;\n\t\t\tvoid _checker;\n\t\t}\n\t}\n}\n\nexport function compileFiltersToExpression(\n\tdefinitions?: readonly ODataCompiledFilterDefinition[],\n\tvalues?: ODataFilterValues\n): FilterExpression<RowRecord> | undefined {\n\tconst normalizedDefinitions = sanitizeFilterDefinitions(definitions);\n\tconst normalizedValues = sanitizeFilterValues(values);\n\tif (!normalizedDefinitions.length || !Object.keys(normalizedValues).length) return undefined;\n\n\tconst filters = normalizedDefinitions\n\t\t.map((definition) => compileDefinitionFilter(definition, normalizedValues[definition.id]))\n\t\t.filter((filter): filter is FilterExpression<RowRecord> => Boolean(filter));\n\n\tif (!filters.length) return undefined;\n\tif (filters.length === 1) return filters[0];\n\n\treturn {\n\t\tand: true,\n\t\tfilters\n\t};\n}\n\nexport function flattenFilterValuesToODataDependencies(\n\tdefinitions?: readonly ODataCompiledFilterDefinition[],\n\tvalues?: ODataFilterValues\n): Record<string, string[]> {\n\tconst normalizedDefinitions = sanitizeFilterDefinitions(definitions);\n\tconst normalizedValues = sanitizeFilterValues(values);\n\tconst dependencies: Record<string, string[]> = {};\n\n\tfor (const definition of normalizedDefinitions) {\n\t\tif (definition.kind !== \"segment\" && definition.kind !== \"tree\") continue;\n\n\t\tconst value = normalizedValues[definition.id];\n\t\tif (value === undefined) continue;\n\n\t\tif (definition.kind === \"segment\") {\n\t\t\tconst scalarValue = typeof value === \"string\" ? value : undefined;\n\t\t\tconst arrayValue = sanitizeStringArray(value);\n\t\t\tconst selectedValues = scalarValue ? [scalarValue] : arrayValue;\n\t\t\tif (!selectedValues?.length) continue;\n\n\t\t\tdependencies[definition.dictionaryCodeKey ?? definition.ownerColumnId] = selectedValues;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst treeValue = sanitizeTreeFilterValue(value);\n\t\tif (!treeValue) continue;\n\n\t\tfor (const columnId of definition.columnIds) {\n\t\t\tconst selectedValues = treeValue[columnId];\n\t\t\tif (!selectedValues) continue;\n\t\t\tif (!selectedValues.length) continue;\n\t\t\tdependencies[columnId] = selectedValues;\n\t\t}\n\t}\n\n\treturn dependencies;\n}\n","import { CollectionItem, CollectionPair } from \"./collectionTypes\";\n\nexport function findCollectionPairs(\n\titem: CollectionItem,\n\toptions: { textSuffixes?: string[]; caseSensitive?: boolean; returnUnpaired?: boolean } = {}\n) {\n\tconst { textSuffixes = [\"_txt\", \"_text\", \"_t\", \"_Text\", \"_TXT\", \"_T\"], caseSensitive = false, returnUnpaired = false } = options;\n\n\tconst fields = Object.keys(item);\n\tconst pairs = [] as CollectionPair[];\n\tconst pairsMap = {} as Record<string, string>;\n\tconst usedFields = new Set();\n\tconst unpairedFields = new Set(fields);\n\n\t// Создаем регулярное выражение для поиска текстовых полей\n\tconst suffixPattern = textSuffixes.map((s) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")).join(\"|\");\n\tconst textFieldRegex = new RegExp(`(.*)(${suffixPattern})$`, caseSensitive ? \"\" : \"i\");\n\n\t// Сначала проходим по всем полям и находим текстовые\n\tconst textFields = fields.filter((field) => textFieldRegex.test(field));\n\n\t// Для каждого текстового поля ищем соответствующее кодовое\n\tfor (const textField of textFields) {\n\t\tif (usedFields.has(textField)) continue;\n\n\t\tconst match = textField.match(textFieldRegex);\n\t\tif (match) {\n\t\t\tconst baseName = match[1]; // Имя без суффикса\n\n\t\t\tif (fields.includes(baseName) && !usedFields.has(baseName)) {\n\t\t\t\tpairs.push({\n\t\t\t\t\tcodeKey: baseName,\n\t\t\t\t\ttextKey: textField\n\t\t\t\t});\n\t\t\t\tpairsMap[baseName] = textField;\n\t\t\t\tusedFields.add(baseName);\n\t\t\t\tusedFields.add(textField);\n\t\t\t\tunpairedFields.delete(baseName);\n\t\t\t\tunpairedFields.delete(textField);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst result: { pairs: CollectionPair[]; pairsMap: CollectionItem; unpaired?: string[] } = { pairs, pairsMap };\n\n\tif (returnUnpaired) {\n\t\tresult.unpaired = Array.from(unpairedFields);\n\t}\n\n\treturn result;\n}\n","// Глобальные конфигурируемые параметры отображения OData-коллекций.\n\nimport { create } from \"zustand\";\nimport { immer } from \"zustand/middleware/immer\";\n\ntype ODataCollectionState = {\n\tdefaultMaxVisibleItems: number;\n\tdefaultMinSearchTextLength: number;\n\tdefaultMinSearchCodeLength: number;\n\tdefaultSearchDebounceDelay: number;\n};\n\ntype ODataCollectionActions = {\n\tsetDefaultMaxVisibleItems: (value: number) => void;\n\tsetDefaultMinSearchTextLength: (value: number) => void;\n\tsetDefaultMinSearchCodeLength: (value: number) => void;\n\tsetDefaultSearchDebounceDelay: (value: number) => void;\n};\n\nexport const useODataCollectionStore = create<ODataCollectionState & ODataCollectionActions>()(\n\timmer((set) => ({\n\t\tdefaultMaxVisibleItems: 200,\n\t\tdefaultMinSearchCodeLength: 3,\n\t\tdefaultMinSearchTextLength: 1,\n\t\tdefaultSearchDebounceDelay: 100,\n\n\t\tsetDefaultMaxVisibleItems: (defaultMaxVisibleItems) => set({ defaultMaxVisibleItems }),\n\t\tsetDefaultMinSearchTextLength: (defaultMinSearchTextLength) => set({ defaultMinSearchTextLength }),\n\t\tsetDefaultMinSearchCodeLength: (defaultMinSearchCodeLength) => set({ defaultMinSearchCodeLength }),\n\t\tsetDefaultSearchDebounceDelay: (defaultSearchDebounceDelay) => set({ defaultSearchDebounceDelay })\n\t}))\n);\n\n// export const useODataCollectionDefaultMaxVisibleItems = () => useODataCollectionStore((s) => s.defaultMaxVisibleItems);\n// export const useODataCollectionDefaultMinSearchCodeLength = () => useODataCollectionStore((s) => s.defaultMinSearchCodeLength);\n// export const useODataCollectionDefaultMinSearchTextLength = () => useODataCollectionStore((s) => s.defaultMinSearchTextLength);\n// export const useODataCollectionDefaultSearchDebounceDelay = () => useODataCollectionStore((s) => s.defaultSearchDebounceDelay);\n\nexport const odataCollectionConfig = {\n\tuseMaxVisibleItems: () => useODataCollectionStore((s) => s.defaultMaxVisibleItems),\n\tuseMinSearchCodeLength: () => useODataCollectionStore((s) => s.defaultMinSearchCodeLength),\n\tuseMinSearchTextLength: () => useODataCollectionStore((s) => s.defaultMinSearchTextLength),\n\tuseSearchDebounce: () => useODataCollectionStore((s) => s.defaultSearchDebounceDelay)\n};\n","/**\n * Парсер метаданных OData V2\n */\n\nimport {\n\tEntityColumnProperty,\n\tEntityMetadata,\n\tEntityParameterProperty,\n\tFunctionImportMetadata,\n\tODataMetaType,\n\tServiceMetadata\n} from \"./types\";\n\nconst TEXT_SUFFIX_REGEXP = /^(.+)(_txt|_text|_t)$/i;\nexport const FORCED_CODE_TEXT_IDS: ReadonlySet<string> = new Set([\"ZDIV\", \"ZCFO1\"]);\n\ntype AssociationSetEndpoint = {\n\trole: string;\n\tentitySet: string;\n};\n\ntype AssociationSetMetadata = {\n\tends: AssociationSetEndpoint[];\n};\n\ntype ResultNavigationMetadata = {\n\tname: \"Set\" | \"Results\";\n\ttargetEntitySet?: string;\n};\n\n/** Возвращает label metadata-колонки с fallback на технический id. */\nexport function resolveMetadataColumnLabel(column: Pick<EntityColumnProperty, \"id\" | \"label\">): string {\n\treturn column.label || column.id;\n}\n\nexport function isForcedCodeTextId(columnId?: string): boolean {\n\tif (!columnId) return false;\n\treturn FORCED_CODE_TEXT_IDS.has(columnId.toUpperCase());\n}\n\nexport function isForcedCodeTextFamilyId(columnId?: string): boolean {\n\tif (!columnId) return false;\n\n\tconst normalizedId = columnId.toUpperCase();\n\tif (FORCED_CODE_TEXT_IDS.has(normalizedId)) return true;\n\n\tconst match = normalizedId.match(/^(.+)(_TXT|_TEXT|_T)$/);\n\tif (!match) return false;\n\n\treturn FORCED_CODE_TEXT_IDS.has(match[1]!);\n}\n\nfunction escapeRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Возвращает `true`, если свойство описано скалярным EDM-типом и может быть\n * представлено в нашей метамодели без отдельной поддержки complex type.\n */\nfunction isScalarEdmPropertyType(typeName: string): boolean {\n\treturn typeName.startsWith(\"Edm.\");\n}\n\nfunction resolveColumnIdByCaseInsensitive(columnsByIdUpper: Record<string, string>, columnId?: string): string | undefined {\n\tif (!columnId) return undefined;\n\treturn columnsByIdUpper[columnId.toUpperCase()];\n}\n\nfunction findTextColumnForCodeId(\n\tcodeId: string,\n\tcolumns: EntityColumnProperty[],\n\tcolumnsByIdUpper: Record<string, string>\n): string | undefined {\n\tconst normalizedCodeId = resolveColumnIdByCaseInsensitive(columnsByIdUpper, codeId);\n\tif (!normalizedCodeId) return undefined;\n\n\tconst textColumnRegExp = new RegExp(`^${escapeRegExp(normalizedCodeId)}(_txt|_text|_t)$`, \"i\");\n\n\tfor (const column of columns) {\n\t\tif (textColumnRegExp.test(column.id)) {\n\t\t\treturn column.id;\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\nfunction normalizeColumns(columns: EntityColumnProperty[]): EntityColumnProperty[] {\n\tconst columnsById: Record<string, EntityColumnProperty> = {};\n\tconst columnsByIdUpper: Record<string, string> = {};\n\n\tfor (const column of columns) {\n\t\tcolumnsById[column.id] = column;\n\t\tcolumnsByIdUpper[column.id.toUpperCase()] = column.id;\n\t}\n\n\tfor (const column of columns) {\n\t\tif (column.role === \"measure\") {\n\t\t\tcolumn.semanticType = \"none\";\n\t\t\tcolumn.linkedColumnId = undefined;\n\t\t\tcontinue;\n\t\t}\n\n\t\tcolumn.role = \"dimension\";\n\t\tcolumn.sortable = true;\n\t\tcolumn.filterable = true;\n\t\tcolumn.semanticType = TEXT_SUFFIX_REGEXP.test(column.id) ? \"text\" : \"code\";\n\n\t\tconst linkedColumnId = resolveColumnIdByCaseInsensitive(columnsByIdUpper, column.linkedColumnId);\n\t\tcolumn.linkedColumnId = linkedColumnId && linkedColumnId !== column.id ? linkedColumnId : undefined;\n\t}\n\n\tfor (const column of columns) {\n\t\tif (column.role !== \"dimension\" || column.semanticType !== \"code\") continue;\n\n\t\tlet textColumnId = column.linkedColumnId;\n\t\tif (textColumnId) {\n\t\t\tconst linkedColumn = columnsById[textColumnId];\n\t\t\tif (!linkedColumn || linkedColumn.role !== \"dimension\") {\n\t\t\t\ttextColumnId = undefined;\n\t\t\t} else {\n\t\t\t\tlinkedColumn.semanticType = \"text\";\n\t\t\t}\n\t\t}\n\n\t\tif (!textColumnId) {\n\t\t\ttextColumnId = findTextColumnForCodeId(column.id, columns, columnsByIdUpper);\n\t\t}\n\n\t\t// Часто эти пары не описаны в metadata, поэтому пробуем восстановить их по суффиксу.\n\t\tif (!textColumnId && isForcedCodeTextId(column.id)) {\n\t\t\ttextColumnId = findTextColumnForCodeId(column.id, columns, columnsByIdUpper);\n\t\t}\n\n\t\tcolumn.linkedColumnId = textColumnId;\n\n\t\tif (textColumnId) {\n\t\t\tconst textColumn = columnsById[textColumnId];\n\t\t\tif (textColumn && textColumn.role === \"dimension\") {\n\t\t\t\ttextColumn.semanticType = \"text\";\n\t\t\t\ttextColumn.linkedColumnId = column.id;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const column of columns) {\n\t\tif (column.role !== \"dimension\" || column.semanticType !== \"text\") continue;\n\n\t\tlet codeColumnId = column.linkedColumnId;\n\t\tif (codeColumnId) {\n\t\t\tconst linkedColumn = columnsById[codeColumnId];\n\t\t\tif (!linkedColumn || linkedColumn.role !== \"dimension\") {\n\t\t\t\tcodeColumnId = undefined;\n\t\t\t} else {\n\t\t\t\tlinkedColumn.semanticType = \"code\";\n\t\t\t}\n\t\t}\n\n\t\tif (!codeColumnId) {\n\t\t\tconst match = column.id.match(TEXT_SUFFIX_REGEXP);\n\t\t\tconst bySuffixCodeId = resolveColumnIdByCaseInsensitive(columnsByIdUpper, match?.[1]);\n\t\t\tif (bySuffixCodeId && columnsById[bySuffixCodeId]?.role === \"dimension\") {\n\t\t\t\tcodeColumnId = bySuffixCodeId;\n\t\t\t}\n\t\t}\n\n\t\tcolumn.linkedColumnId = codeColumnId;\n\n\t\tif (codeColumnId) {\n\t\t\tconst codeColumn = columnsById[codeColumnId];\n\t\t\tif (codeColumn && codeColumn.role === \"dimension\") {\n\t\t\t\tcodeColumn.semanticType = \"code\";\n\t\t\t\tif (!codeColumn.linkedColumnId) {\n\t\t\t\t\tcodeColumn.linkedColumnId = column.id;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn columns;\n}\n\n/**\n * Преобразует EDM-тип во внутренний тип системы.\n */\nfunction mapEdmToServiceType(edm: string): ODataMetaType {\n\tswitch (edm) {\n\t\tcase \"Edm.String\":\n\t\t\treturn \"string\";\n\t\tcase \"Edm.Guid\":\n\t\t\treturn \"guid\";\n\t\tcase \"Edm.Boolean\":\n\t\t\treturn \"boolean\";\n\t\tcase \"Edm.Int16\":\n\t\tcase \"Edm.Int32\":\n\t\t\treturn \"int\";\n\t\tcase \"Edm.Int64\":\n\t\t\treturn \"long\";\n\t\tcase \"Edm.Single\":\n\t\t\treturn \"float\";\n\t\tcase \"Edm.Decimal\":\n\t\t\treturn \"decimal\";\n\t\tcase \"Edm.Double\":\n\t\t\treturn \"double\";\n\t\tcase \"Edm.DateTime\":\n\t\t\treturn \"datetime\";\n\t\tcase \"Edm.DateTimeOffset\":\n\t\t\treturn \"datetimeOffset\";\n\t\tcase \"Edm.Time\":\n\t\t\treturn \"time\";\n\t\tcase \"Edm.Binary\":\n\t\t\treturn \"binary\";\n\t\tcase \"Edm.Byte\":\n\t\t\treturn \"byte\";\n\t\tdefault:\n\t\t\tthrow new Error(`Неподдерживаемый тип данных ${edm}`);\n\t}\n}\n\n/**\n * Создает свойство параметра из XML-элемента.\n */\nfunction createParameterProperty(element: Element): EntityParameterProperty {\n\tconst name = element.getAttribute(\"Name\")!;\n\tconst edmType = element.getAttribute(\"Type\") || \"\";\n\tconst mapped = mapEdmToServiceType(edmType);\n\n\tconst maxLength = element.hasAttribute(\"MaxLength\") ? Number(element.getAttribute(\"MaxLength\")) : undefined;\n\tconst precision = element.hasAttribute(\"Precision\") ? Number(element.getAttribute(\"Precision\")) : undefined;\n\tconst scale = element.hasAttribute(\"Scale\") ? Number(element.getAttribute(\"Scale\")) : undefined;\n\tconst label = element.getAttribute(\"sap:label\") || undefined;\n\tconst parameter = element.getAttribute(\"sap:parameter\") || undefined;\n\tconst nullable = element.getAttribute(\"Nullable\") !== \"false\" ? true : undefined;\n\n\treturn {\n\t\tid: name,\n\t\tlabel: label ?? name,\n\t\ttype: mapped,\n\t\toriginalType: edmType,\n\t\t...(mapped === \"string\" && maxLength === 1 ? { abapBooleanLike: true } : {}),\n\t\t...(maxLength !== undefined && { maxLength }),\n\t\t...(precision !== undefined && { precision }),\n\t\t...(scale !== undefined && { scale }),\n\t\t...(parameter !== undefined && { parameter }),\n\t\t...(nullable !== undefined && { nullable: true }),\n\t\t...(parameter === \"mandatory\" && { mandatory: true })\n\t};\n}\n\n/**\n * Создает свойство колонки из XML-элемента.\n */\nfunction createColumnProperty(element: Element): EntityColumnProperty {\n\tconst baseProps = createParameterProperty(element);\n\n\tconst linkedColumnId = element.getAttribute(\"sap:text\") || undefined;\n\tconst sortable = element.getAttribute(\"sap:sortable\") !== \"false\";\n\tconst filterable = element.getAttribute(\"sap:filterable\") !== \"false\";\n\tconst role = element.getAttribute(\"sap:aggregation-role\") === \"measure\" ? \"measure\" : \"dimension\";\n\tconst label = element.getAttribute(\"sap:label\") || undefined;\n\n\t// Убираем свойства, специфичные только для параметров.\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tconst { nullable, mandatory, ...columnProps } = baseProps;\n\n\treturn {\n\t\t...columnProps,\n\t\t...(linkedColumnId !== undefined && { linkedColumnId }),\n\t\t...(label !== undefined && { label }),\n\t\tsemanticType: \"none\",\n\t\tsortable,\n\t\tfilterable,\n\t\trole\n\t};\n}\n\n/**\n * Фильтрует свойства, исключая служебные.\n */\nfunction propertyFilter(element: Element): boolean {\n\tconst name = element.getAttribute(\"Name\");\n\tconst typeName = element.getAttribute(\"Type\") || \"\";\n\n\tif (!name) return false;\n\tif (!isScalarEdmPropertyType(typeName)) return false;\n\n\treturn !([/*\"ID\", \"Id\", \"id\",*/ \"CNT\", \"cnt\"].includes(name) || /_F$/i.test(name));\n}\n\n/**\n * Фильтрует свойства для колонок, исключая служебные.\n */\nfunction columnPropertyFilter(element: Element): boolean {\n\tconst name = element.getAttribute(\"Name\");\n\tconst typeName = element.getAttribute(\"Type\") || \"\";\n\n\tif (!name) return false;\n\tif (!isScalarEdmPropertyType(typeName)) return false;\n\n\treturn !([\"CNT\", \"cnt\"].includes(name) || /_F$/i.test(name));\n}\n\nfunction getProperties(element: Element): Element[] {\n\treturn Array.from(element.getElementsByTagName(\"Property\"));\n}\n\nfunction getKeys(element: Element): Element[] {\n\treturn Array.from(element.getElementsByTagName(\"PropertyRef\"));\n}\n\nfunction getNavigationProperties(element: Element): Element[] {\n\treturn Array.from(element.getElementsByTagName(\"NavigationProperty\"));\n}\n\n/**\n * Получает параметры из EntityType.\n */\nfunction getParametersProperties(entity: Element): EntityParameterProperty[] {\n\tconst properties = getProperties(entity).filter(propertyFilter);\n\treturn properties.map(createParameterProperty);\n}\n\n/**\n * Получает параметры из EntityType с учетом ключей.\n */\nfunction getParametersPropertiesWithKey(entity: Element): EntityParameterProperty[] {\n\tconst properties = getProperties(entity).filter(propertyFilter);\n\tconst keys = getKeys(entity);\n\n\treturn properties.map((property) => {\n\t\tconst param = createParameterProperty(property);\n\t\tif (keys.find((key) => key.getAttribute(\"Name\") === param.id)) {\n\t\t\tparam.mandatory = true;\n\t\t}\n\t\treturn param;\n\t});\n}\n\n/**\n * Получает колонки из EntityType.\n */\nfunction getColumnsProperties(entity: Element): EntityColumnProperty[] {\n\tconst properties = getProperties(entity).filter(columnPropertyFilter);\n\tconst columns = properties.map(createColumnProperty);\n\treturn normalizeColumns(columns);\n}\n\nfunction extractQualifiedNameShortName(value?: string | null): string | undefined {\n\tif (!value) return undefined;\n\tconst parts = value.split(\".\");\n\treturn parts[parts.length - 1] || undefined;\n}\n\nfunction createFunctionImportParameterProperty(element: Element): EntityParameterProperty {\n\tconst mode = element.getAttribute(\"Mode\");\n\tif (mode && mode !== \"In\") {\n\t\tconst name = element.getAttribute(\"Name\") || \"(unknown)\";\n\t\tthrow new Error(`FunctionImport parameter '${name}' uses unsupported Mode='${mode}'`);\n\t}\n\n\tconst typeName = element.getAttribute(\"Type\") || \"\";\n\tif (!isScalarEdmPropertyType(typeName)) {\n\t\tconst name = element.getAttribute(\"Name\") || \"(unknown)\";\n\t\tthrow new Error(`FunctionImport parameter '${name}' uses unsupported Type='${typeName}'`);\n\t}\n\n\tconst parameter = createParameterProperty(element);\n\tif (element.getAttribute(\"Nullable\") === \"false\") {\n\t\tparameter.mandatory = true;\n\t}\n\n\treturn parameter;\n}\n\nfunction buildEntityTypeByName(entityNodes: Element[]): Record<string, Element> {\n\treturn entityNodes.reduce<Record<string, Element>>((acc, entity) => {\n\t\tconst entityName = entity.getAttribute(\"Name\");\n\t\tif (entityName) {\n\t\t\tacc[entityName] = entity;\n\t\t}\n\t\treturn acc;\n\t}, {});\n}\n\nfunction buildEntitySetToEntityTypeMap(xml: Document): Record<string, string> {\n\tconst entitySets = Array.from(xml.getElementsByTagName(\"EntitySet\"));\n\n\treturn entitySets.reduce<Record<string, string>>((acc, entitySet) => {\n\t\tconst entitySetName = entitySet.getAttribute(\"Name\");\n\t\tconst entityType = extractQualifiedNameShortName(entitySet.getAttribute(\"EntityType\"));\n\t\tif (!entitySetName || !entityType) return acc;\n\n\t\tacc[entitySetName] = entityType;\n\t\treturn acc;\n\t}, {});\n}\n\nfunction buildAssociationSetByName(xml: Document): Record<string, AssociationSetMetadata> {\n\tconst associationSetNodes = Array.from(xml.getElementsByTagName(\"AssociationSet\"));\n\n\treturn associationSetNodes.reduce<Record<string, AssociationSetMetadata>>((acc, associationSet) => {\n\t\tconst associationName = associationSet.getAttribute(\"Association\");\n\t\tif (!associationName) return acc;\n\n\t\tconst ends = Array.from(associationSet.getElementsByTagName(\"End\"))\n\t\t\t.map((end) => {\n\t\t\t\tconst role = end.getAttribute(\"Role\");\n\t\t\t\tconst entitySet = end.getAttribute(\"EntitySet\");\n\t\t\t\tif (!role || !entitySet) return undefined;\n\t\t\t\treturn { role, entitySet };\n\t\t\t})\n\t\t\t.filter((end): end is AssociationSetEndpoint => Boolean(end));\n\n\t\tconst metadata = { ends };\n\t\tacc[associationName] = metadata;\n\n\t\tconst shortName = extractQualifiedNameShortName(associationName);\n\t\tif (shortName) {\n\t\t\tacc[shortName] = metadata;\n\t\t}\n\n\t\treturn acc;\n\t}, {});\n}\n\nfunction findResultNavigation(\n\tentityType: Element,\n\tassociationSetByName: Record<string, AssociationSetMetadata>\n): ResultNavigationMetadata | undefined {\n\tfor (const navigationProperty of getNavigationProperties(entityType)) {\n\t\tconst navigationName = navigationProperty.getAttribute(\"Name\");\n\t\tif (navigationName !== \"Set\" && navigationName !== \"Results\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst relationship = navigationProperty.getAttribute(\"Relationship\");\n\t\tconst associationSet = relationship ? associationSetByName[relationship] : undefined;\n\t\tconst toRole = navigationProperty.getAttribute(\"ToRole\");\n\t\tconst fromRole = navigationProperty.getAttribute(\"FromRole\");\n\n\t\tlet targetEntitySet = associationSet?.ends.find((end) => end.role === toRole)?.entitySet;\n\t\tif (!targetEntitySet && associationSet) {\n\t\t\ttargetEntitySet = associationSet.ends.find((end) => end.role !== fromRole)?.entitySet;\n\t\t}\n\n\t\treturn {\n\t\t\tname: navigationName,\n\t\t\ttargetEntitySet\n\t\t};\n\t}\n\n\treturn undefined;\n}\n\nfunction buildInternalEntitySetNames(\n\tentitySetToEntityTypeMap: Record<string, string>,\n\tentityTypeByName: Record<string, Element>,\n\tassociationSetByName: Record<string, AssociationSetMetadata>\n): Set<string> {\n\tconst internalEntitySets = new Set<string>();\n\n\tfor (const [entitySetName, entityTypeName] of Object.entries(entitySetToEntityTypeMap)) {\n\t\tconst entityType = entityTypeByName[entityTypeName];\n\t\tif (!entityType) continue;\n\n\t\tconst resultNavigation = findResultNavigation(entityType, associationSetByName);\n\t\tif (!resultNavigation?.targetEntitySet) continue;\n\t\tif (resultNavigation.targetEntitySet === entitySetName) continue;\n\n\t\tinternalEntitySets.add(resultNavigation.targetEntitySet);\n\t}\n\n\treturn internalEntitySets;\n}\n\nfunction resolveColumnsEntityType(\n\tentityType: Element,\n\tresultNavigation: ResultNavigationMetadata | undefined,\n\tentitySetToEntityTypeMap: Record<string, string>,\n\tentityTypeByName: Record<string, Element>\n): Element {\n\tconst resultEntityTypeName = resultNavigation?.targetEntitySet ? entitySetToEntityTypeMap[resultNavigation.targetEntitySet] : undefined;\n\treturn (resultEntityTypeName && entityTypeByName[resultEntityTypeName]) || entityType;\n}\n\nfunction resolveEntityParameters(entityType: Element, entityTypeName: string, resultNavigation: ResultNavigationMetadata | undefined) {\n\tif (resultNavigation) {\n\t\treturn getParametersProperties(entityType);\n\t}\n\n\tif (entityTypeName.endsWith(\"Type\")) {\n\t\treturn undefined;\n\t}\n\n\treturn getParametersPropertiesWithKey(entityType);\n}\n\nfunction getActionForKeyIds(actionFor: string | undefined, entityTypeByName: Record<string, Element>): Set<string> {\n\tif (!actionFor) return new Set<string>();\n\n\tconst entityTypeName = extractQualifiedNameShortName(actionFor);\n\tif (!entityTypeName) return new Set<string>();\n\n\tconst entityType = entityTypeByName[entityTypeName];\n\tif (!entityType) return new Set<string>();\n\n\treturn new Set(\n\t\tgetKeys(entityType)\n\t\t\t.map((key) => key.getAttribute(\"Name\"))\n\t\t\t.filter((value): value is string => Boolean(value))\n\t);\n}\n\nfunction parseFunctionImport(\n\telement: Element,\n\tentitySetToEntityTypeMap: Record<string, string>,\n\tentityTypeByName: Record<string, Element>\n): FunctionImportMetadata {\n\tconst name = element.getAttribute(\"Name\") || \"\";\n\tconst entitySet = element.getAttribute(\"EntitySet\") || undefined;\n\tconst actionFor = element.getAttribute(\"sap:action-for\") || undefined;\n\tconst actionForKeyIds = getActionForKeyIds(actionFor, entityTypeByName);\n\tconst parameters = Array.from(element.getElementsByTagName(\"Parameter\")).map((parameterElement) => {\n\t\tconst parameter = createFunctionImportParameterProperty(parameterElement);\n\t\tif (actionForKeyIds.has(parameter.id)) {\n\t\t\tparameter.mandatory = true;\n\t\t}\n\t\treturn parameter;\n\t});\n\n\treturn {\n\t\tname,\n\t\ttitle: element.getAttribute(\"sap:label\") || \"\",\n\t\thttpMethod: (element.getAttribute(\"m:HttpMethod\") as FunctionImportMetadata[\"httpMethod\"] | null) || undefined,\n\t\tparameters: parameters.length ? parameters : undefined,\n\t\treturnType: element.getAttribute(\"ReturnType\") || \"\",\n\t\t...(entitySet !== undefined && { entitySet }),\n\t\t...(actionFor !== undefined && { actionFor }),\n\t\t...(entitySet && entitySetToEntityTypeMap[entitySet] ? { resultEntity: entitySet } : {})\n\t};\n}\n\n/**\n * Парсит метаданные OData V2 из XML.\n */\nexport function parseServiceMetadata(xmlText: string): ServiceMetadata {\n\tconst parser = new DOMParser();\n\tconst xml = parser.parseFromString(xmlText, \"application/xml\");\n\tconst entityNodes = Array.from(xml.getElementsByTagName(\"EntityType\"));\n\tconst functionImportNodes = Array.from(xml.getElementsByTagName(\"FunctionImport\"));\n\tconst entitySetToEntityTypeMap = buildEntitySetToEntityTypeMap(xml);\n\tconst entityTypeByName = buildEntityTypeByName(entityNodes);\n\tconst associationSetByName = buildAssociationSetByName(xml);\n\tconst internalEntitySets = buildInternalEntitySetNames(entitySetToEntityTypeMap, entityTypeByName, associationSetByName);\n\n\tconst entities: Record<string, EntityMetadata> = {};\n\tconst functionImports: Record<string, FunctionImportMetadata> = {};\n\n\tfor (const [entitySetName, entityTypeName] of Object.entries(entitySetToEntityTypeMap)) {\n\t\tif (internalEntitySets.has(entitySetName)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst entityType = entityTypeByName[entityTypeName];\n\t\tif (!entityType) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst resultNavigation = findResultNavigation(entityType, associationSetByName);\n\t\tconst columnsEntityType = resolveColumnsEntityType(entityType, resultNavigation, entitySetToEntityTypeMap, entityTypeByName);\n\t\tconst title = entityType.getAttribute(\"sap:label\") || columnsEntityType.getAttribute(\"sap:label\") || \"\";\n\t\tconst columns = getColumnsProperties(columnsEntityType);\n\t\tconst parameters = resolveEntityParameters(entityType, entityTypeName, resultNavigation);\n\n\t\tentities[entitySetName] = {\n\t\t\ttitle,\n\t\t\tcolumns,\n\t\t\t...(parameters?.length ? { parameters } : {}),\n\t\t\t...(resultNavigation ? { result: resultNavigation.name } : {})\n\t\t};\n\t}\n\n\tfor (const functionImport of functionImportNodes) {\n\t\tconst parsed = parseFunctionImport(functionImport, entitySetToEntityTypeMap, entityTypeByName);\n\t\tfunctionImports[parsed.name] = parsed;\n\t}\n\n\treturn { entities, functionImports };\n}\n","export interface Sort<T> {\n\tkey: T;\n\t/**\n\t * @default false (asc)\n\t */\n\tdesc?: true;\n}\n\nexport function getSortIndex<T>(sorting: Sort<keyof T>[], key: keyof T): number {\n\treturn sorting.findIndex((s) => s.key === key);\n}\n\nexport function buildODataOrder<T>(sorting: Sort<keyof T>[]): string {\n\treturn sorting.map((s) => `${String(s.key)} ${s.desc ? \"desc\" : \"asc\"}`).join(\",\");\n}\n\nexport function toggleSort<T>(sorting: Sort<keyof T>[], key: keyof T, multi: boolean): Sort<keyof T>[] {\n\tconst idx = getSortIndex(sorting, key);\n\n\t// single-sort: начинаем с чистого массива (кроме клика по уже существующему — тоже можно сбрасывать)\n\tconst base = multi ? [...sorting] : [...sorting.filter((s) => s.key === key)];\n\n\tif (idx === -1) {\n\t\tbase.push({ key });\n\t\treturn base;\n\t}\n\n\tconst current = sorting[idx]!;\n\tif (!current.desc) {\n\t\t// asc -> desc\n\t\treturn base.map((s) => (s.key === key ? { key, desc: true } : s));\n\t}\n\n\t// desc -> remove\n\treturn base.filter((s) => s.key !== key);\n}\n\n/**\n * Возвращает эффективный набор сортировок для аналитической таблицы.\n *\n * Правило:\n * - при наличии пользовательской сортировки используется только она;\n * - если пользовательская сортировка отсутствует, используется сортировка по полям группировки (asc).\n */\nexport function resolveEffectiveSorts<TKey extends PropertyKey>(grouping: TKey[], sorting: Sort<TKey>[]): Sort<TKey>[] {\n\tif (sorting.length > 0) {\n\t\treturn sorting.map((item) => ({ key: item.key, desc: item.desc }));\n\t}\n\n\treturn grouping.map((key) => ({ key }));\n}\n\nexport function buildODataOrderBy<T>(grouping: (keyof T)[], sorting: Sort<keyof T>[]): string | undefined {\n\tconst effectiveSorting = resolveEffectiveSorts(grouping, sorting);\n\tconst parts = effectiveSorting.map((item) => `${String(item.key)} ${item.desc ? \"desc\" : \"asc\"}`);\n\n\treturn parts.length ? parts.join(\",\") : undefined;\n}\n\nexport function getSortIndicator<T>(\n\tgrouping: (keyof T)[],\n\tsorting: Sort<keyof T>[],\n\tcolId: keyof T\n): { active: boolean; desc?: boolean; order?: number; lockedByGrouping?: boolean } {\n\tconst hasUserSorting = sorting.length > 0;\n\tconst gIdx = grouping.indexOf(colId);\n\tif (!hasUserSorting && gIdx !== -1) {\n\t\treturn { active: true, order: gIdx + 1, lockedByGrouping: true };\n\t}\n\n\tconst sIdx = sorting.findIndex((s) => s.key === colId);\n\tif (sIdx === -1) return { active: false };\n\n\treturn { active: true, desc: sorting[sIdx]?.desc, order: sIdx + 1 };\n}\n","export type SqlFilterScalarValue = string | number | boolean;\n\nexport type SqlFilterOperation = \"eq\" | \"in\";\n\nexport type SqlFilterEqualCondition = {\n\t/** Имя SQL-поля после всех доменных маппингов. */\n\tfieldId: string;\n\t/** Оператор строгого равенства. */\n\toperation: \"eq\";\n\t/** Исходное значение фильтра. Неподдерживаемые и пустые значения не сериализуются. */\n\tvalue: unknown;\n};\n\nexport type SqlFilterInCondition = {\n\t/** Имя SQL-поля после всех доменных маппингов. */\n\tfieldId: string;\n\t/** Оператор включения в список значений. */\n\toperation: \"in\";\n\t/** Исходные значения фильтра. Неподдерживаемые и пустые значения не сериализуются. */\n\tvalues: readonly unknown[] | null | undefined;\n};\n\nexport type SqlFilterCondition = SqlFilterEqualCondition | SqlFilterInCondition;\n\nexport type SqlFilterConjunction = \"and\" | \"or\";\n\n/**\n * Явная группа SQL-like выражений с собственным логическим оператором.\n * Группа всегда сериализуется в скобках, чтобы её границы сохранялись при\n * объединении с соседними выражениями верхнего уровня через `AND`.\n */\nexport type SqlFilterGroup = {\n\toperation: \"group\";\n\tconjunction: SqlFilterConjunction;\n\texpressions: readonly SqlFilterExpression[];\n};\n\n/** Узел безопасного SQL-like выражения: простое условие или вложенная группа. */\nexport type SqlFilterExpression = SqlFilterCondition | SqlFilterGroup;\n\nconst SQL_FILTER_FIELD_ID_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nexport function isSqlFilterScalarValue(value: unknown): value is SqlFilterScalarValue {\n\treturn typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\";\n}\n\nexport function assertSqlFilterFieldId(fieldId: string): void {\n\tif (!SQL_FILTER_FIELD_ID_PATTERN.test(fieldId)) {\n\t\tthrow new Error(`Некорректное имя поля SQL-фильтра: ${fieldId}`);\n\t}\n}\n\nexport function createSqlFilterEqual(fieldId: string, value: unknown): SqlFilterEqualCondition {\n\treturn { fieldId, operation: \"eq\", value };\n}\n\nexport function createSqlFilterIn(fieldId: string, values: readonly unknown[] | null | undefined): SqlFilterInCondition {\n\treturn { fieldId, operation: \"in\", values };\n}\n\n/**\n * Создаёт логическую группу SQL-like выражений.\n * Вложенность нужна потребителям, где один пользовательский фильтр объединяет\n * альтернативные физические поля, а сам остаётся частью общего `AND`-выражения.\n */\nexport function createSqlFilterGroup(expressions: readonly SqlFilterExpression[], conjunction: SqlFilterConjunction): SqlFilterGroup {\n\treturn { operation: \"group\", conjunction, expressions };\n}\n\nfunction normalizeSqlFilterValue(value: unknown): string | undefined {\n\tif (value instanceof Date) {\n\t\tthrow new Error(\"Дата должна быть отформатирована вызывающей стороной до формирования SQL-фильтра\");\n\t}\n\n\tif (!isSqlFilterScalarValue(value)) return undefined;\n\n\tif (typeof value === \"number\" && !Number.isFinite(value)) return undefined;\n\n\tconst rawValue = String(value);\n\tif (!rawValue || rawValue.trim() === \"\") return undefined;\n\n\treturn `'${rawValue.replaceAll(\"'\", \"''\")}'`;\n}\n\nfunction buildSqlFilterExpression(expression: SqlFilterExpression): string | undefined {\n\tif (expression.operation === \"group\") {\n\t\tconst nestedExpressions = expression.expressions\n\t\t\t.map((nestedExpression) => buildSqlFilterExpression(nestedExpression))\n\t\t\t.filter((nestedExpression): nestedExpression is string => Boolean(nestedExpression));\n\t\tif (!nestedExpressions.length) return undefined;\n\n\t\tconst separator = expression.conjunction === \"or\" ? \" OR \" : \" AND \";\n\t\treturn `(${nestedExpressions.join(separator)})`;\n\t}\n\n\tif (expression.operation === \"eq\") {\n\t\tconst formattedValue = normalizeSqlFilterValue(expression.value);\n\t\tif (!formattedValue) return undefined;\n\n\t\tassertSqlFilterFieldId(expression.fieldId);\n\t\treturn `${expression.fieldId}=${formattedValue}`;\n\t}\n\n\tconst formattedValues = (expression.values ?? [])\n\t\t.map((value) => normalizeSqlFilterValue(value))\n\t\t.filter((value): value is string => Boolean(value));\n\tif (formattedValues.length === 0) return undefined;\n\n\tassertSqlFilterFieldId(expression.fieldId);\n\treturn `${expression.fieldId} IN (${formattedValues.join(\", \")})`;\n}\n\n/**\n * Формирует SQL-подобный фильтр для legacy payload, который backend вставляет в dynamic WHERE.\n *\n * Это не OData `$filter`: оператор `IN` здесь допустим только потому, что строка уходит в тело запроса,\n * а не в SAP Gateway URL. Для защиты от падения dynamic WHERE builder намеренно разрешает только\n * простые имена полей и строковые литералы с экранированными одинарными кавычками.\n */\nexport function buildSqlFilter(expressions: readonly SqlFilterExpression[] | undefined): string {\n\tif (!expressions) return \"\";\n\n\treturn expressions\n\t\t.map((expression) => buildSqlFilterExpression(expression))\n\t\t.filter((expression): expression is string => Boolean(expression))\n\t\t.join(\" AND \");\n}\n","import { type ODataBooleanType, type ODataDateType, type ODataIntegerType, type ODataMetaType, type ODataNumericType } from \"./types\";\n\nexport function isODataBooleanType(type: ODataMetaType | undefined): type is ODataBooleanType {\n\treturn type === \"boolean\";\n}\n\nexport function isODataNumericType(type: ODataMetaType | undefined): type is ODataNumericType {\n\treturn type === \"byte\" || type === \"int\" || type === \"long\" || type === \"float\" || type === \"decimal\" || type === \"double\";\n}\n\nexport function isODataIntegerType(type: ODataMetaType | undefined): type is ODataIntegerType {\n\treturn type === \"byte\" || type === \"int\" || type === \"long\";\n}\n\nexport function isODataDateType(type: ODataMetaType | undefined): type is ODataDateType {\n\treturn type === \"datetime\" || type === \"datetimeOffset\" || type === \"time\";\n}\n","import type { UseQueryResult } from \"@tanstack/react-query\";\n\n/**\n * Стандартный ответ `odataQueryFn` после трансформации данных.\n */\ninterface ODataQueryResultEnvelope<T> {\n\tdata: T;\n\ttotalCount?: number;\n}\n\n/**\n * Результат query-хука с уже распакованным полем `data`.\n */\nexport type UnwrappedODataQueryResult<T> = Omit<UseQueryResult<ODataQueryResultEnvelope<T>>, \"data\"> & {\n\tdata: T | undefined;\n\ttotalCount?: number;\n};\n\n/**\n * Приводит результат `useQuery` с `odataQueryFn` к привычному виду:\n * данные доступны сразу в `data`, а `totalCount` вынесен отдельно.\n */\nexport function unwrapODataQueryResult<T>(query: UseQueryResult<ODataQueryResultEnvelope<T>>): UnwrappedODataQueryResult<T> {\n\tconst data = query.data?.data;\n\tconst totalCount = query.data?.totalCount;\n\n\treturn { ...query, data, totalCount };\n}\n","import { BaseType, InputType, RangeType } from \"../types\";\nimport { isObject } from \"../validators\";\n\nexport function normalizeRangeValue(value: InputType): RangeType {\n\tif (Array.isArray(value)) {\n\t\treturn [value[0] ?? null, value[1] ?? null];\n\t}\n\n\treturn [isBaseValue(value) ? (value ?? null) : null, null];\n}\n\nexport function normalizeBaseValue(value: InputType): BaseType {\n\tif (value instanceof Date) {\n\t\treturn value;\n\t}\n\n\tif (Array.isArray(value) || isObject(value)) {\n\t\treturn null;\n\t}\n\n\treturn value;\n}\n\nexport function isBaseValue(value: unknown): value is BaseType {\n\treturn value == null || typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\" || value instanceof Date;\n}\n","import { UnwrappedODataParameters, WrapODataParameters, WrappedODataParameters } from \"./types\";\n\n// export function wrapODataParams(data: Record<string, unknown>): Record<string, ODataValue> {\n// \tif (!data) return {};\n// \treturn Object.entries(data).reduce(\n// \t\t(acc, [key, value]) => {\n// \t\t\t// NOTE: пропускаем пустые строки и 0\n// \t\t\tif (value != null) {\n// \t\t\t\tacc[key] = { value };\n// \t\t\t}\n// \t\t\treturn acc;\n// \t\t},\n// \t\t{} as Record<string, ODataValue>\n// \t);\n// }\n\n/**\n * Типизированный хелпер для преобразования плоской структуры в wrapped.\n */\nexport function wrapODataParams<T extends UnwrappedODataParameters>(params: T | undefined | null): WrapODataParameters<T> {\n\tif (!params) return {} as WrapODataParameters<T>;\n\n\tconst result = {} as WrapODataParameters<T>;\n\tfor (const key in params) {\n\t\tresult[key] = { value: params[key] };\n\t}\n\n\treturn result;\n}\n\nexport function unwrapODataParams(params?: WrappedODataParameters): UnwrappedODataParameters | undefined {\n\tif (!params) return undefined;\n\n\tconst normalized: UnwrappedODataParameters = {};\n\tfor (const key of Object.keys(params).sort()) {\n\t\tnormalized[key] = params[key]?.value ?? null;\n\t}\n\n\treturn normalized;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"odata-service-tp2U5yIr.js","names":[],"sources":["../../src/formatters/boolean/parseAbapBoolean.ts","../../src/formatters/number/parseNumber.ts","../../src/formatters/date/pattern.ts","../../src/formatters/date/presets.ts","../../src/formatters/date/parseDate.ts","../../src/formatters/date/formatDate.ts","../../src/odata-service/baseTypes.ts","../../src/odata-service/buildSeparatedArrays.ts","../../src/odata-service/dateUtils.ts","../../src/odata-service/schema.ts","../../src/odata-service/formatters.ts","../../src/odata-service/builder.ts","../../src/odata-service/columns.ts","../../src/odata-service/filters.ts","../../src/odata-service/filterDefinitions.ts","../../src/odata-service/findCollectionPairs.ts","../../src/odata-service/odataCollectionStore.ts","../../src/odata-service/parser.ts","../../src/odata-service/sorts.ts","../../src/odata-service/sqlFilters.ts","../../src/odata-service/typesValidation.ts","../../src/odata-service/unwrapODataQueryResult.ts","../../src/odata-service/utils.ts","../../src/odata-service/wrapParams.ts"],"sourcesContent":["export function parseAbapBoolean(value: unknown): boolean {\n\tif (value && typeof value === \"string\" && value === \"X\") return true;\n\treturn false;\n}\n\nexport function parseBoolean(value: unknown): boolean {\n\tif (!value) return false;\n\tif (typeof value === \"string\") {\n\t\treturn [\"true\", \"x\", \"1\"].includes(value.toLowerCase());\n\t}\n\treturn Boolean(value);\n}\n","/**\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 { parseDateValue } from \"./parseDate\";\nimport { compileDatePreset, CompiledDateFormatPreset, DEFAULT_DATE_PRESET_NAMES, getCompiledDatePreset } from \"./presets\";\nimport { DateFormatPrecision, DateFormatPreset, FormatDateOptions, ParsedDateValue } from \"./types\";\n\n/**\n * Кеш скомпилированных объектных предустановок.\n *\n * Именованные предустановки компилируются в реестре, а объектные могут\n * передаваться напрямую в горячем пути таблиц. WeakMap сохраняет готовый\n * Intl.DateTimeFormat на время жизни объекта и не мешает сборке мусора.\n */\nconst objectPresetCache = new WeakMap<DateFormatPreset, CompiledDateFormatPreset>();\n\n/**\n * Дополняет числовую часть даты ведущим нулём.\n */\nfunction padDatePart(value: number): string {\n\treturn String(value).padStart(2, \"0\");\n}\n\n/**\n * Разрешает предустановку по имени или объекту.\n */\nfunction resolvePreset(presetOrName: string | DateFormatPreset): CompiledDateFormatPreset {\n\tif (typeof presetOrName !== \"string\") {\n\t\tconst cachedPreset = objectPresetCache.get(presetOrName);\n\t\tif (cachedPreset) return cachedPreset;\n\n\t\tconst compiledPreset = compileDatePreset(presetOrName);\n\t\tobjectPresetCache.set(presetOrName, compiledPreset);\n\t\treturn compiledPreset;\n\t}\n\n\tconst preset = getCompiledDatePreset(presetOrName);\n\tif (!preset) {\n\t\tthrow new Error(`Предустановка даты \"${presetOrName}\" не найдена`);\n\t}\n\treturn preset;\n}\n\n/**\n * Определяет fallback с учётом опций вызова и предустановки.\n */\nfunction resolveFallback(preset: CompiledDateFormatPreset, options?: FormatDateOptions): string {\n\treturn options?.fallback ?? preset.invalidFallback;\n}\n\n/**\n * Форматирует уже распарсенное значение.\n */\nfunction formatParsedValue(\n\tparsed: ParsedDateValue,\n\tpreset: CompiledDateFormatPreset,\n\tfallback: string,\n\tprecision: DateFormatPrecision\n): string {\n\tif (parsed.kind === \"duration\") {\n\t\treturn preset.formatDuration ? preset.formatDuration(parsed.durationMs, fallback) : fallback;\n\t}\n\n\treturn preset.formatDateTime(parsed.date, precision);\n}\n\n/**\n * Универсально форматирует дату/время по предустановке или её имени.\n */\nexport function formatDate(\n\tvalue: unknown,\n\tpresetOrName: string | DateFormatPreset = DEFAULT_DATE_PRESET_NAMES.date,\n\toptions?: FormatDateOptions\n): string {\n\tconst preset = resolvePreset(presetOrName);\n\tconst fallback = resolveFallback(preset, options);\n\tconst precision = options?.precision ?? \"day\";\n\tconst parsed = parseDateValue(value);\n\n\tif (!parsed) return fallback;\n\treturn formatParsedValue(parsed, preset, fallback, precision);\n}\n\n/**\n * Форматирует значение как дату `dd.MM.yyyy`.\n */\nexport function formatDateAsDate(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.date, options);\n}\n\n/**\n * Форматирует значение как дату и время `dd.MM.yyyy HH:mm`.\n */\nexport function formatDateAsDateTime(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.datetime, options);\n}\n\n/**\n * Форматирует значение как время `HH:mm`.\n */\nexport function formatDateAsTime(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.time, options);\n}\n\n/**\n * Форматирует значение как время `HH:mm:ss`.\n */\nexport function formatDateAsTimeSeconds(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.timeSeconds, options);\n}\n\n/**\n * Форматирует значение как короткую дату `03.03.2026`.\n */\nexport function formatDateAsDateShort(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.dateShort, options);\n}\n\n/**\n * Форматирует значение как среднюю дату `3 мар. 2026 г.`.\n */\nexport function formatDateAsDateMedium(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.dateMedium, options);\n}\n\n/**\n * Форматирует значение как длинную дату `3 марта 2026 г.`.\n */\nexport function formatDateAsDateLong(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.dateLong, options);\n}\n\n/**\n * Форматирует значение как короткую дату без года `03.03`.\n */\nexport function formatDateAsMonthShort(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.monthShort, options);\n}\n\n/**\n * Форматирует значение как среднюю дату без года `3 мар.`.\n */\nexport function formatDateAsMonthMedium(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.monthMedium, options);\n}\n\n/**\n * Форматирует значение как длинную дату без года `3 марта`.\n */\nexport function formatDateAsMonthLong(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.monthLong, options);\n}\n\n/**\n * Форматирует значение как сокращённый месяц и год `мар. 2026`.\n */\nexport function formatDateAsMonthYearMedium(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.monthYearMedium, options);\n}\n\n/**\n * Форматирует значение как полный месяц и год `март 2026`.\n */\nexport function formatDateAsMonthYearLong(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.monthYearLong, options);\n}\n\n/**\n * Форматирует значение как короткое время `18:03`.\n */\nexport function formatDateAsTimeShort(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.timeShort, options);\n}\n\n/**\n * Форматирует значение как среднее время `18:03:50`.\n */\nexport function formatDateAsTimeMedium(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.timeMedium, options);\n}\n\n/**\n * Форматирует значение как длинное время `18:03:50`.\n */\nexport function formatDateAsTimeLong(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.timeLong, options);\n}\n\n/**\n * Форматирует значение как короткую дату и время `03.03.2026 18:03`.\n */\nexport function formatDateAsDatetimeShort(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.datetimeShort, options);\n}\n\n/**\n * Форматирует значение как среднюю дату и время `3 мар. 2026 г. 18:03:50`.\n */\nexport function formatDateAsDatetimeMedium(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.datetimeMedium, options);\n}\n\n/**\n * Форматирует значение как длинную дату и время `3 марта 2026 г. 18:03:50`.\n */\nexport function formatDateAsDatetimeLong(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.datetimeLong, options);\n}\n\n/**\n * Форматирует диапазон дат через разделитель ` - `.\n */\nexport function formatDateRange(\n\tstartValue: unknown,\n\tendValue: unknown,\n\tpresetOrName: string | DateFormatPreset = DEFAULT_DATE_PRESET_NAMES.date,\n\toptions?: FormatDateOptions\n): string {\n\tconst preset = resolvePreset(presetOrName);\n\tconst fallback = resolveFallback(preset, options);\n\tconst precision = options?.precision ?? \"day\";\n\n\tconst startParsed = parseDateValue(startValue);\n\tconst endParsed = parseDateValue(endValue);\n\tif (!startParsed || !endParsed) return fallback;\n\n\tconst start = formatParsedValue(startParsed, preset, fallback, precision);\n\tconst end = formatParsedValue(endParsed, preset, fallback, precision);\n\tif (!start || !end) return fallback;\n\n\treturn `${start} - ${end}`;\n}\n\n/**\n * Форматирует значение как год `yyyy`.\n */\nexport function formatDateAsAbapYear(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.abapYear, options);\n}\n\n/**\n * Форматирует значение как календарный месяц `yyyyMM`.\n */\nexport function formatDateAsAbapMonth(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.abapMonth, options);\n}\n\n/**\n * Форматирует значение как дату `yyyyMMdd`.\n */\nexport function formatDateAsAbapDate(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.abapDate, options);\n}\n\n/**\n * Форматирует значение как дату `yyyyMMddHHmmss`.\n */\nexport function formatDateAsAbapDatetime(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.abapDatetime, options);\n}\n\n/**\n * Форматирует значение как дату `yyyy-MM-dd`.\n */\nexport function formatDateAsODataDate(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.odataDate, options);\n}\n\n/**\n * Форматирует значение как дату и время `yyyy-MM-ddTHH:mm:ss`.\n */\nexport function formatDateAsODataDatetime(value: unknown, options?: FormatDateOptions): string {\n\treturn formatDate(value, DEFAULT_DATE_PRESET_NAMES.odataDatetime, options);\n}\n\n/**\n * Форматирует значение как время `PT00H00M00S`.\n */\nexport function formatDateAsODataTime(value: unknown, options?: FormatDateOptions): string {\n\tconst fallback = options?.fallback ?? \"\";\n\tconst parsed = parseDateValue(value);\n\tif (!parsed) return fallback;\n\n\tif (parsed.kind === \"duration\") {\n\t\tconst timePreset = resolvePreset(DEFAULT_DATE_PRESET_NAMES.timeSeconds);\n\t\tconst formattedDuration = timePreset.formatDuration?.(parsed.durationMs, fallback) ?? fallback;\n\t\tif (formattedDuration === fallback) return fallback;\n\n\t\tconst [hours = \"00\", minutes = \"00\", seconds = \"00\"] = formattedDuration.split(\":\");\n\t\treturn `PT${hours}H${minutes}M${seconds}S`;\n\t}\n\n\tconst date = parsed.date;\n\treturn `PT${padDatePart(date.getHours())}H${padDatePart(date.getMinutes())}M${padDatePart(date.getSeconds())}S`;\n}\n","import type { BaseMetaType } from \"./types\";\n\nexport const BASE_META_TYPES = Object.freeze([\"string\", \"number\", \"boolean\", \"date\"] as const) satisfies readonly BaseMetaType[];\n\nconst BASE_META_TYPE_SET: ReadonlySet<string> = new Set(BASE_META_TYPES);\n\nexport const BASE_META_TYPE_LABELS: Readonly<Record<BaseMetaType, string>> = Object.freeze({\n\tstring: \"строка\",\n\tnumber: \"число\",\n\tboolean: \"boolean\",\n\tdate: \"дата\"\n});\n\nexport function isBaseMetaType(type: unknown): type is BaseMetaType {\n\treturn typeof type === \"string\" && BASE_META_TYPE_SET.has(type);\n}\n\nexport function resolveBaseTypeLabel(type: BaseMetaType): string {\n\treturn BASE_META_TYPE_LABELS[type];\n}\n","import { compareStrings } from \"../string-comparison\";\n\nimport { CollectionItem, CollectionPair } from \"./collectionTypes\";\n\nfunction createEmptySeparated<T extends CollectionItem>(pairs: CollectionPair[]) {\n\tconst resultRef: Record<string, T[]> = {};\n\tpairs.forEach((pair) => {\n\t\tresultRef[pair.codeKey] = [];\n\t});\n\treturn resultRef;\n}\n\n/**\n * Создание разделенных массивов для каждого кодового поля\n * @param items - исходные данные справочника\n * @param pairs - пары код-текст\n * @param excludeEmpty - флаг исключения пустых значений\n * @returns Объект с разделенными массивами по кодовым полям\n */\nexport function buildSeparatedArrays<T extends CollectionItem>(\n\titems: T[],\n\tpairs: CollectionPair[],\n\texcludeEmpty: boolean = true,\n\tsortByCode: boolean = true\n): Record<string, T[]> {\n\t// Если items пустой, возвращаем пустые массивы для всех пар\n\tif (!items || items.length === 0) {\n\t\treturn createEmptySeparated(pairs);\n\t}\n\n\t// Определяем, какие ключи действительно существуют в items\n\tconst availableKeys = new Set<string>();\n\tconst firstItem = items[0];\n\n\tif (firstItem) {\n\t\t// Собираем все доступные ключи из первого элемента\n\t\tObject.keys(firstItem).forEach((key) => {\n\t\t\tavailableKeys.add(key);\n\t\t});\n\t}\n\n\t// Фильтруем пары, оставляем только те, где оба ключа существуют в items\n\tconst validPairs = pairs.filter((pair) => {\n\t\treturn availableKeys.has(pair.codeKey as string) && availableKeys.has(pair.textKey as string);\n\t});\n\n\t// Если нет валидных пар, возвращаем пустой результат\n\tif (validPairs.length === 0) {\n\t\treturn createEmptySeparated(pairs);\n\t}\n\n\tconst result: Record<string, T[]> = {};\n\t// Инициализируем структуры данных\n\tconst pairMap = new Map<\n\t\tstring,\n\t\t{\n\t\t\tcodeKey: keyof T;\n\t\t\ttextKey: keyof T;\n\t\t\tuniqueSet: Set<string>;\n\t\t}\n\t>();\n\n\t// Подготовка для валидных пар\n\tfor (const pair of validPairs) {\n\t\tconst codeKeyStr = pair.codeKey as string;\n\t\tpairMap.set(codeKeyStr, {\n\t\t\tcodeKey: pair.codeKey,\n\t\t\ttextKey: pair.textKey,\n\t\t\tuniqueSet: new Set<string>()\n\t\t});\n\t\tresult[codeKeyStr] = [];\n\t}\n\n\t// Для невалидных пар создаем пустые массивы\n\tpairs.forEach((pair) => {\n\t\tconst codeKeyStr = pair.codeKey as string;\n\t\tif (!pairMap.has(codeKeyStr)) {\n\t\t\tresult[codeKeyStr] = [];\n\t\t}\n\t});\n\n\t// Единый проход по всем элементам\n\tfor (const item of items) {\n\t\tfor (const [codeKeyStr, pairData] of pairMap) {\n\t\t\tconst { codeKey, textKey, uniqueSet } = pairData;\n\n\t\t\t// Получаем значения с проверкой на существование\n\t\t\tconst codeValue = String(item[codeKey]);\n\t\t\tconst textValue = String(item[textKey]);\n\n\t\t\t// Если excludeEmpty и текстовое значение пустое - пропускаем\n\t\t\tif (excludeEmpty && !textValue) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Проверяем, что codeValue существует\n\t\t\tif (codeValue === undefined || codeValue === null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Проверка уникальности\n\t\t\tconst uniqueKey = `${String(codeValue)}|${String(textValue)}`;\n\t\t\tif (!uniqueSet.has(uniqueKey)) {\n\t\t\t\tuniqueSet.add(uniqueKey);\n\n\t\t\t\t// Создаем новый объект только с нужными полями\n\t\t\t\tresult[codeKeyStr].push({\n\t\t\t\t\t[codeKey]: codeValue,\n\t\t\t\t\t[textKey]: textValue\n\t\t\t\t} as T);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Сортировка результатов для валидных пар\n\tfor (const [codeKeyStr, pairData] of pairMap) {\n\t\tconst array = result[codeKeyStr];\n\t\tif (array.length > 0) {\n\t\t\tconst sortKey = sortByCode ? pairData.codeKey : pairData.textKey;\n\n\t\t\tarray.sort((a, b) => {\n\t\t\t\tconst valA = a[sortKey] || \"\";\n\t\t\t\tconst valB = b[sortKey] || \"\";\n\t\t\t\treturn compareStrings(String(valA), String(valB));\n\t\t\t});\n\t\t}\n\t}\n\n\treturn result;\n\n\t//\n\n\t// pairs.forEach((pair) => {\n\t// \tlet filteredItems = items;\n\n\t// \t// Фильтруем пустые значения, если требуется\n\t// \tif (excludeEmpty) {\n\t// \t\tfilteredItems = items.filter((item) => item[pair.textKey]);\n\t// \t}\n\n\t// \t// Создаем массив только с нужными полями\n\t// \tconst separatedItems = filteredItems.map(\n\t// \t\t(item) =>\n\t// \t\t\t({\n\t// \t\t\t\t[pair.codeKey]: item[pair.codeKey],\n\t// \t\t\t\t[pair.textKey]: item[pair.textKey]\n\t// \t\t\t}) as T\n\t// \t);\n\n\t// \t// Удаляем дубликаты\n\t// \tconst uniqueItems: T[] = Array.from(\n\t// \t\tnew Map(separatedItems.map((item) => [`${item[pair.codeKey]}|${item[pair.textKey]}`, item])).values()\n\t// \t);\n\n\t// \tconst sortKey = sortByCode ? pair.codeKey : pair.textKey;\n\n\t// \tuniqueItems.sort((a, b) => {\n\t// \t\tconst textA = a[sortKey] || \"\";\n\t// \t\tconst textB = b[sortKey] || \"\";\n\t// \t\treturn compareStrings(String(textA), String(textB));\n\t// \t});\n\n\t// \tresult[pair.codeKey] = uniqueItems;\n\t// });\n\n\t// return result;\n}\n","import { formatDateAsODataDatetime, formatDateAsODataTime } from \"../formatters/date/formatDate\";\n\n/**\n * Форматирование дат в литералы OData, совместимые с SAP UI5 DateFormat.\n *\n * Примеры:\n * * datetime'2025-11-11T12:00:00'\n * * datetimeoffset'2025-11-11T12:00:00Z'\n * * time'PT12H30M00S'\n */\nexport const ODataDateFormat = {\n\tdatetime(date: Date): string {\n\t\treturn `datetime'${formatDateAsODataDatetime(date)}'`;\n\t},\n\tdatetimeOffset(date: Date): string {\n\t\treturn `datetimeoffset'${date.toISOString()}'`;\n\t},\n\ttime(date: Date): string {\n\t\treturn `time'${formatDateAsODataTime(date)}'`;\n\t}\n};\n","import { z } from \"zod\";\n\nimport type { ODataMetaType } from \"./types\";\n\nexport const odataTypeSchemas: Record<ODataMetaType, z.ZodTypeAny> = {\n\tstring: z.string(),\n\tguid: z.uuid().or(z.string().regex(/^[0-9a-fA-F-]+$/, \"Invalid GUID\")),\n\tboolean: z.boolean(),\n\tint: z.number().int(),\n\tlong: z.number().int(),\n\tfloat: z.number(),\n\tdecimal: z.number(),\n\tdouble: z.number(),\n\tdatetime: z.date(),\n\tdatetimeOffset: z.date(),\n\ttime: z.date(),\n\tbinary: z.string(),\n\tbyte: z.number().int().min(0).max(255)\n};\n\n// Type Guards на основе Zod\nfunction isType<T>(value: unknown, schema: z.ZodType<T>): value is T {\n\treturn schema.safeParse(value).success;\n}\n\n// Специфичные Type Guards\nexport function isStringSafe(value: unknown): value is string {\n\treturn isType(value, odataTypeSchemas.string);\n}\n\nexport function isNumberSafe(value: unknown): value is number {\n\treturn isType(value, odataTypeSchemas.float); // используем float как базовый числовой тип\n}\n\nexport function isBooleanSafe(value: unknown): value is boolean {\n\treturn isType(value, odataTypeSchemas.boolean);\n}\n\nexport function isDateSafe(value: unknown): value is Date {\n\treturn isType(value, odataTypeSchemas.datetime);\n}\n","import { z } from \"zod\";\n\nimport { parseAbapBoolean } from \"../formatters/boolean/parseAbapBoolean\";\nimport { formatDateAsAbapDate } from \"../formatters/date/formatDate\";\nimport { parseDate } from \"../formatters/date/parseDate\";\nimport { parseNumber } from \"../formatters/number/parseNumber\";\n\nimport { ODataDateFormat } from \"./dateUtils\";\nimport { odataTypeSchemas } from \"./schema\";\n\nimport type {\n\tBaseMetaType,\n\tEntityParameterProperty,\n\tODataBooleanType,\n\tODataDateType,\n\tODataFormatterDescription,\n\tODataMetaType,\n\tODataNumericType,\n\tODataStringType\n} from \"./types\";\n\n/**\n * NOTE: Запрещено экспортировать!\n */\nfunction formatValidValue(type: ODataMetaType, validValue: unknown) {\n\tswitch (type) {\n\t\tcase \"string\":\n\t\t\treturn `'${String(validValue).replace(/'/g, \"''\")}'`;\n\t\tcase \"guid\":\n\t\t\treturn `guid'${String(validValue)}'`;\n\t\tcase \"boolean\":\n\t\t\treturn validValue ? \"'X'\" : \"' '\";\n\t\tcase \"long\":\n\t\t\treturn `${String(validValue)}L`;\n\t\tcase \"float\":\n\t\t\treturn `${String(validValue)}F`;\n\t\tcase \"decimal\":\n\t\t\treturn `${String(validValue)}M`;\n\t\tcase \"double\":\n\t\t\treturn `${String(validValue)}D`;\n\t\tcase \"datetime\":\n\t\tcase \"datetimeOffset\":\n\t\tcase \"time\":\n\t\t\tif (!(validValue instanceof Date)) {\n\t\t\t\tthrow new Error(`Неверная дата для типа '${type}': ${validValue}`);\n\t\t\t}\n\t\t\treturn ODataDateFormat[type](validValue);\n\t\tcase \"binary\":\n\t\t\treturn `binary'${validValue}'`;\n\t\tcase \"byte\":\n\t\tcase \"int\":\n\t\t\treturn `${String(validValue)}`;\n\n\t\tdefault:\n\t\t\tthrow new Error(`Неподдерживаемый тип: ${type satisfies never}`);\n\t}\n}\n\n/**\n * Форматирует значение для использования в URL в соответствии с типом OData\n * @param type Тип данных\n * @param value Значение\n * @returns Отформатированная строка\n */\nexport function odataFormatValue(type: ODataMetaType, value: unknown): string {\n\tconst schema = odataTypeSchemas[type];\n\tconst result = schema.safeParse(value);\n\tif (!result.success) {\n\t\tthrow new Error(`Некорректное значение для типа '${type}': ${result.error.issues[0]?.message ?? value}`);\n\t}\n\n\treturn formatValidValue(type, result.data);\n}\n\ntype ODataMetadataValueDescriptor = Pick<EntityParameterProperty, \"type\" | \"abapBooleanLike\">;\n\nfunction tryParseBooleanValue(value: unknown): boolean | undefined {\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"number\") {\n\t\tif (value === 1) return true;\n\t\tif (value === 0) return false;\n\t\treturn undefined;\n\t}\n\tif (typeof value !== \"string\") return undefined;\n\n\tif (value === \"X\") return true;\n\tif (value === \" \" || value === \"\") return false;\n\n\tconst normalized = value.trim().toLowerCase();\n\tif (normalized === \"true\" || normalized === \"1\") return true;\n\tif (normalized === \"false\" || normalized === \"0\") return false;\n\n\treturn undefined;\n}\n\nfunction tryParseAbapBooleanLikeValue(value: unknown): boolean | undefined {\n\tif (value == null) return false;\n\tif (typeof value !== \"string\") return undefined;\n\tif (value === \"X\" || value === \" \" || value === \"\") {\n\t\treturn parseAbapBoolean(value);\n\t}\n\treturn undefined;\n}\n\nexport function odataParseValue(type: ODataBooleanType, value: unknown): boolean | unknown;\nexport function odataParseValue(type: ODataNumericType, value: unknown): number | unknown;\nexport function odataParseValue(type: ODataDateType, value: unknown): Date | null | unknown;\nexport function odataParseValue(type: ODataStringType, value: unknown): string | unknown;\nexport function odataParseValue(type: ODataMetaType, value: unknown): string | unknown;\nexport function odataParseValue(type: ODataMetaType, value: unknown) {\n\tswitch (type) {\n\t\tcase \"boolean\": {\n\t\t\tconst parsed = tryParseBooleanValue(value);\n\t\t\treturn parsed ?? value;\n\t\t}\n\n\t\tcase \"int\":\n\t\tcase \"long\":\n\t\tcase \"float\":\n\t\tcase \"decimal\":\n\t\tcase \"double\":\n\t\tcase \"byte\":\n\t\t\treturn parseNumber(value);\n\n\t\tcase \"datetime\":\n\t\tcase \"datetimeOffset\":\n\t\tcase \"time\":\n\t\t\treturn parseDate(value);\n\n\t\tdefault:\n\t\t\treturn String(value);\n\t}\n}\n\nexport function odataParseValueByMetadata(descriptor: ODataMetadataValueDescriptor, value: unknown) {\n\tif (descriptor.abapBooleanLike) {\n\t\tconst parsedBoolean = tryParseAbapBooleanLikeValue(value);\n\t\tif (parsedBoolean !== undefined) {\n\t\t\treturn parsedBoolean;\n\t\t}\n\t}\n\n\treturn odataParseValue(descriptor.type, value);\n}\n\nexport function defaultODataTypeValue(type: ODataMetaType) {\n\tswitch (type) {\n\t\tcase \"boolean\":\n\t\t\treturn false;\n\n\t\tcase \"int\":\n\t\tcase \"long\":\n\t\tcase \"float\":\n\t\tcase \"decimal\":\n\t\tcase \"double\":\n\t\tcase \"byte\":\n\t\t\treturn 0;\n\n\t\tcase \"datetime\":\n\t\tcase \"datetimeOffset\":\n\t\tcase \"time\":\n\t\t\treturn new Date();\n\n\t\tdefault:\n\t\t\treturn \"\";\n\t}\n}\n\nexport function defaultControlTypeValue(type: BaseMetaType) {\n\tswitch (type) {\n\t\tcase \"boolean\":\n\t\t\treturn false;\n\t\tcase \"number\":\n\t\t\treturn 0;\n\t\tcase \"date\":\n\t\t\treturn new Date();\n\t\tdefault:\n\t\t\treturn \"\";\n\t}\n}\n\nexport function createFormatter<S extends z.ZodArray>(schema: S, fn: (...args: [...z.infer<S>]) => string) {\n\treturn (...args: unknown[]) => {\n\t\tconst result = schema.safeParse(args);\n\t\tif (!result.success) {\n\t\t\tthrow new Error(`Validation failed: ${result.error.message}`);\n\t\t}\n\t\treturn fn(...result.data);\n\t};\n}\n\nexport function createBooleanFormatter(fn: (...args: boolean[]) => string) {\n\treturn createFormatter(z.array(z.boolean()), fn);\n}\n\nexport function createStringFormatter(fn: (...args: string[]) => string) {\n\treturn createFormatter(z.array(z.string()), fn);\n}\n\nexport function createNumberFormatter(fn: (...args: number[]) => string) {\n\treturn createFormatter(z.array(z.number()), fn);\n}\n\nexport function createDateFormatter(fn: (...args: Date[]) => string) {\n\treturn createFormatter(z.array(z.date()), fn);\n}\n\ntype FormatterRecord = {\n\t[K in BaseMetaType]?: {\n\t\t/**\n\t\t * Базовый форматтер для типа (по умолчанию)\n\t\t */\n\t\tbase: Omit<ODataFormatterDescription, \"id\">;\n\t\t/**\n\t\t * Кастомные варианты форматтеров для типа\n\t\t */\n\t\t[key: string]: Omit<ODataFormatterDescription, \"id\">;\n\t};\n};\n\n/*export*/ const formatODataDatetime = createDateFormatter(ODataDateFormat.datetime);\n/*export*/ const formatODataDatetimeOffset = createDateFormatter(ODataDateFormat.datetimeOffset);\n/*export*/ const formatODataTime = createDateFormatter(ODataDateFormat.time);\n/*export*/ const formatODataAbapDate = createDateFormatter((value) => formatValidValue(\"string\", formatDateAsAbapDate(value)));\n\n/*export*/ const formatODataBoolean = createBooleanFormatter((value) => formatValidValue(\"boolean\", value));\n/*export*/ const formatODataBooleanAsChar = createBooleanFormatter((value) => formatValidValue(\"string\", Number(value)));\n/*export*/ const formatODataBooleanAsByte = createBooleanFormatter((value) => formatValidValue(\"byte\", Number(value)));\n\n/*export*/ const formatODataString = createStringFormatter((value) => formatValidValue(\"string\", value));\n\n/**\n * Форматтеры формируются только по базовым типам, по которым работают UI контролы.\n */\nconst formatters: FormatterRecord = {\n\tdate: {\n\t\tbase: {\n\t\t\tlabel: \"Базовый datetime\",\n\t\t\tdescription: \"Используется для параметров OData с типом данных datetime\",\n\t\t\tfn: formatODataDatetime\n\t\t},\n\t\tdatetimeOffset: {\n\t\t\tlabel: \"Базовый datetimeoffset\",\n\t\t\tdescription: \"Используется для параметров OData с типом данных datetimeoffset\",\n\t\t\tfn: formatODataDatetimeOffset\n\t\t},\n\t\ttime: {\n\t\t\tlabel: \"Базовый time\",\n\t\t\tdescription: \"Используется для параметров OData с типом данных time\",\n\t\t\tfn: formatODataTime\n\t\t},\n\t\tstringAbapDate: {\n\t\t\tlabel: \"Дата ABAP YYYYMMDD\",\n\t\t\tdescription: \"Используется для параметров OData с типом данных string(8)\",\n\t\t\tfn: formatODataAbapDate\n\t\t}\n\t},\n\tboolean: {\n\t\tbase: {\n\t\t\tlabel: \"Базовое ABAP булево\",\n\t\t\tdescription: \"Стандартный формат abap_bool со значением 'X' для true и '' для false\",\n\t\t\tfn: formatODataBoolean\n\t\t},\n\t\tasChar: {\n\t\t\tlabel: \"Как символ\",\n\t\t\tdescription: \"Преобразование булево в символы '0' или '1'\",\n\t\t\tfn: formatODataBooleanAsChar\n\t\t},\n\t\tasByte: {\n\t\t\tlabel: \"Как цифра\",\n\t\t\tdescription: \"Преобразование булево в цифру 0 или 1\",\n\t\t\tfn: formatODataBooleanAsByte\n\t\t}\n\t},\n\tstring: {\n\t\tbase: {\n\t\t\tlabel: \"Базовая строка\",\n\t\t\tdescription: \"\",\n\t\t\tfn: formatODataString\n\t\t}\n\t}\n};\n\nexport function getBaseTypeFromODataType<T extends ODataMetaType>(type: T): BaseMetaType {\n\tswitch (type) {\n\t\tcase \"boolean\":\n\t\t\treturn \"boolean\";\n\n\t\tcase \"int\":\n\t\tcase \"long\":\n\t\tcase \"float\":\n\t\tcase \"decimal\":\n\t\tcase \"double\":\n\t\tcase \"byte\":\n\t\t\treturn \"number\";\n\n\t\tcase \"datetime\":\n\t\tcase \"datetimeOffset\":\n\t\tcase \"time\":\n\t\t\treturn \"date\";\n\n\t\tdefault:\n\t\t\treturn \"string\";\n\t}\n}\n\nexport function getFormattersFor<T extends ODataMetaType>(type: T): ODataFormatterDescription[] {\n\tconst group = formatters[getBaseTypeFromODataType(type)];\n\tif (!group) return [];\n\n\treturn Object.entries(group).map(([id, fmt]) => ({\n\t\tid,\n\t\t...fmt\n\t}));\n}\n\n/**\n * Возвращает форматтеры напрямую по базовому типу UI-контрола.\n */\nexport function getFormattersForBaseType<T extends BaseMetaType>(type: T): ODataFormatterDescription[] {\n\tconst group = formatters[type];\n\tif (!group) return [];\n\n\treturn Object.entries(group).map(([id, fmt]) => ({\n\t\tid,\n\t\t...fmt\n\t}));\n}\n\nexport function getFormatter<T extends ODataMetaType>(type: T, id: string) {\n\treturn formatters[getBaseTypeFromODataType(type)]?.[id];\n}\n\nexport function getFormatterForBaseType<T extends BaseMetaType>(type: T, id: string) {\n\treturn formatters[type]?.[id];\n}\n","/**\n * Построитель URL для OData сущностей на основе метаданных\n */\n\nimport { odataFormatValue } from \"./formatters\";\nimport {\n\ttype EntityMetadata,\n\ttype EntityParameterProperty,\n\ttype FunctionImportMetadata,\n\ttype ODataOperationMethod,\n\ttype ODataParameterValue,\n\ttype ODataServiceConfig,\n\ttype ODataValue,\n\ttype WrappedODataParameters\n} from \"./types\";\n\ntype ParameterizedMetadata = {\n\tparameters?: EntityParameterProperty[];\n};\n\n/**\n * Валидирует длину отформатированного значения\n * @param formattedValue Отформатированное значение\n * @param maxLength Максимальная длина\n */\nfunction validateFormattedLength(formattedValue: string, maxLength?: number): void {\n\tif (!maxLength || typeof maxLength !== \"number\") return;\n\n\t// Проверяем что значение в кавычках и содержимое не превышает maxLength\n\tconst match = formattedValue.match(/^'(.*)'$/s);\n\tif (!match) {\n\t\tthrow new Error(`Значение должно быть заключено в одинарные кавычки: ${formattedValue}`);\n\t}\n\n\tconst content = match[1];\n\tif (content.length > maxLength) {\n\t\tthrow new Error(\n\t\t\t`Значение слишком длинное для maxLength=${maxLength}: '${formattedValue}' (${content.length} символов внутри кавычек)`\n\t\t);\n\t}\n}\n\n/**\n * Собирает строку параметров запроса к сущности на основе метаданных\n *\n * @param metadata Метаданные сущности\n * @param params Значения параметров\n */\nexport function buildParameterEntries(metadata: ParameterizedMetadata, params: WrappedODataParameters): Array<[string, string]> {\n\tif (!metadata.parameters) return [];\n\n\tconst parts = metadata.parameters.map<[string, string] | null>((param) => {\n\t\tconst { id, type, maxLength, mandatory } = param;\n\n\t\tconst odataValue = (params[id] ?? {}) as ODataValue<ODataParameterValue>;\n\t\tconst value = odataValue.value;\n\t\tconst formatter = odataValue.formatter;\n\n\t\tif (mandatory && (value === undefined || value === null)) {\n\t\t\tthrow new Error(`Отсутствует обязательный параметр: ${id}`);\n\t\t}\n\n\t\t// Пропускаем необязательные параметры без значений\n\t\tif (value === undefined || value === null) return null;\n\n\t\ttry {\n\t\t\tif (Array.isArray(value) && !formatter) {\n\t\t\t\tthrow new Error(\"Массив значений OData-параметра требует custom formatter\");\n\t\t\t}\n\n\t\t\tconst formattedValue = formatter ? formatter(value) : odataFormatValue(type, value);\n\n\t\t\tvalidateFormattedLength(formattedValue, maxLength);\n\n\t\t\treturn [id, formattedValue];\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Ошибка форматирования параметра ${id}: ${String(error)}`);\n\t\t}\n\t});\n\n\treturn parts.filter((part): part is [string, string] => part !== null);\n}\n\n/**\n * Собирает строку параметров запроса к сущности на основе metadata.\n */\nexport function buildEntityParameters(metadata: EntityMetadata, params: WrappedODataParameters): string {\n\tconst parts = buildParameterEntries(metadata, params);\n\treturn parts.length ? `(${parts.map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join(\",\")})` : \"\";\n}\n\n/**\n * Собирает query string-параметры для FunctionImport.\n */\nexport function buildFunctionImportParameters(metadata: FunctionImportMetadata, params: WrappedODataParameters): URLSearchParams {\n\tconst searchParams = new URLSearchParams();\n\n\tfor (const [key, value] of buildParameterEntries(metadata, params)) {\n\t\tsearchParams.set(key, value);\n\t}\n\n\treturn searchParams;\n}\n\nexport function buildEntityOperationPath(\n\tmetadata: EntityMetadata,\n\tconfig: ODataServiceConfig,\n\tparams: WrappedODataParameters,\n\tmethod: Exclude<ODataOperationMethod, \"fi\">\n): string {\n\tconst basePath = `/${config.service}/${config.target}`;\n\n\tif (method === \"create\") {\n\t\treturn basePath;\n\t}\n\n\tif (method === \"query\") {\n\t\tif (!metadata.result) {\n\t\t\tif (__DEV__) {\n\t\t\t\tif (Object.keys(params).length > 0) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`Параметры для query-запроса '/${config.service}/${config.target}' проигнорированы: target не поддерживает parameterized query.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn basePath;\n\t\t}\n\n\t\treturn buildEntityPath(metadata, config, params);\n\t}\n\n\tconst parameters = buildEntityParameters(metadata, params);\n\treturn `${basePath}${parameters}`;\n}\n\n/**\n * Собирает строку запроса к FunctionImport.\n */\nexport function buildFunctionImportPath(\n\tmetadata: FunctionImportMetadata,\n\tconfig: ODataServiceConfig,\n\tparams: WrappedODataParameters\n): string {\n\tconst searchParams = buildFunctionImportParameters(metadata, params);\n\tconst queryString = searchParams.toString();\n\tconst path = `/${config.service}/${config.target}`;\n\n\treturn queryString ? `${path}?${queryString}` : path;\n}\n\n/**\n * Собирает строку запроса к EntitySet\n */\nexport function buildEntityPath(metadata: EntityMetadata, config: ODataServiceConfig, params: WrappedODataParameters): string {\n\tconst parameters = buildEntityParameters(metadata, params);\n\tconst navigation = metadata.result ? `/${metadata.result}` : \"\";\n\n\treturn `/${config.service}/${config.target}${parameters}${navigation}`;\n}\n","import { EntityColumnProperty } from \"./types\";\n\n/**\n * Возвращает code-like filterable-колонки.\n */\nexport function collectFilterableColumns(columns: readonly Readonly<EntityColumnProperty>[]): Readonly<EntityColumnProperty>[] {\n\treturn columns.filter((column) => column.semanticType === \"code\" && column.filterable);\n}\n\n/**\n * Возвращает идентификаторы code-like filterable-колонок.\n */\nexport function collectFilterableColumnsIds(columns: readonly Readonly<EntityColumnProperty>[]): Readonly<Set<string>> {\n\treturn new Set(collectFilterableColumns(columns).map((c) => c.id));\n}\n","import { odataFormatValue } from \"./formatters\";\n\nimport type { BaseType, RowRecord } from \"../types\";\nimport type { ODataMetaType } from \"./types\";\n\nexport const FilterOperation = Object.freeze({\n\teq: \"eq\",\n\tne: \"ne\",\n\tgt: \"gt\",\n\tge: \"ge\",\n\tlt: \"lt\",\n\tle: \"le\",\n\tstartswith: \"startswith\",\n\tendswith: \"endswith\",\n\tcontains: \"contains\"\n} as const);\n\nexport type FilterOperation = (typeof FilterOperation)[keyof typeof FilterOperation];\n\nexport const FILTER_OPERATIONS = Object.freeze(Object.values(FilterOperation)) as readonly FilterOperation[];\n\nconst FILTER_OPERATION_LABELS: Readonly<Record<FilterOperation, string>> = Object.freeze({\n\teq: \"равно\",\n\tne: \"не равно\",\n\tgt: \"больше\",\n\tge: \"больше или равно\",\n\tlt: \"меньше\",\n\tle: \"меньше или равно\",\n\tstartswith: \"начинается с\",\n\tendswith: \"заканчивается на\",\n\tcontains: \"содержит\"\n});\n\nconst FILTER_OPERATION_SET: ReadonlySet<string> = new Set(FILTER_OPERATIONS);\n\nexport function isFilterOperation(value: unknown): value is FilterOperation {\n\treturn typeof value === \"string\" && FILTER_OPERATION_SET.has(value);\n}\n\nexport function resolveOperationLabel(operation: FilterOperation): string {\n\treturn FILTER_OPERATION_LABELS[operation];\n}\n\nexport interface FilterCondition<T> {\n\tkey: keyof T;\n\tvalue: BaseType;\n\toperation?: FilterOperation;\n\ttype?: ODataMetaType;\n}\n\n// Базовый интерфейс для выражения\nexport interface BaseFilterExpression {\n\t/**\n\t * @default false (or)\n\t */\n\tand?: boolean;\n}\n\n// Выражение с условиями (лист дерева)\nexport interface FilterConditionExpression<T> extends BaseFilterExpression {\n\tconditions: FilterCondition<T>[];\n\tfilters?: never; // Делаем явно недоступным\n}\n\n// Выражение с вложенными фильтрами (узел дерева)\nexport interface FilterNestedExpression<T> extends BaseFilterExpression {\n\tfilters: FilterExpression<T>[];\n\tconditions?: never; // Делаем явно недоступным\n}\n\n// Объединенный тип\nexport type FilterExpression<T> = FilterConditionExpression<T> | FilterNestedExpression<T>;\n\nfunction getODataTypeFromValue(value: unknown): ODataMetaType {\n\tswitch (typeof value) {\n\t\tcase \"bigint\":\n\t\tcase \"number\":\n\t\t\t// NOTE: тут теперь может возникнуть проблема, когда нужен будет long\n\t\t\treturn \"int\";\n\t\tcase \"boolean\":\n\t\t\treturn \"boolean\";\n\t\tcase \"object\":\n\t\t\tif (value instanceof Date) {\n\t\t\t\treturn \"datetime\";\n\t\t\t}\n\t}\n\n\treturn \"string\";\n}\n\n// Функция для построения условия\nfunction buildCondition<T>(condition: FilterCondition<T>): string {\n\tconst { key, operation = \"eq\", value, type } = condition;\n\tconst odataType = type ?? getODataTypeFromValue(value);\n\tconst escapedValue = odataFormatValue(odataType, value);\n\n\t// Специальные операторы для строк\n\tif (operation === \"contains\") {\n\t\treturn `substringof(${escapedValue},${String(key)})`;\n\t}\n\n\tif (operation === \"startswith\" || operation === \"endswith\") {\n\t\treturn `${operation}(${String(key)}, ${escapedValue})`;\n\t}\n\n\t// Стандартные операторы\n\treturn `${String(key)} ${operation} ${escapedValue}`;\n}\n\n// Type guards\nfunction isConditionExpression<T>(expr: FilterExpression<T>): expr is FilterConditionExpression<T> {\n\treturn \"conditions\" in expr && expr.conditions !== undefined;\n}\n\nfunction isNestedExpression<T>(expr: FilterExpression<T>): expr is FilterNestedExpression<T> {\n\treturn \"filters\" in expr && expr.filters !== undefined;\n}\n\nfunction compactExpressionStrings<T>(filters: FilterExpression<T>[], build: (expression: FilterExpression<T>) => string): string[] {\n\t// return filters.map((filter) => build(filter)).filter(Boolean);\n\tconst result: string[] = [];\n\n\tfor (const filter of filters) {\n\t\tconst value = build(filter);\n\t\tif (value) {\n\t\t\tresult.push(value);\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// Основная функция\nexport function buildODataFilter<T>(expression: FilterExpression<T> | undefined): string {\n\tif (!expression) return \"\";\n\n\tif (isConditionExpression(expression)) {\n\t\t// Обработка выражения с условиями\n\t\tconst { conditions, and = false } = expression;\n\n\t\tif (conditions.length === 0) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (conditions.length === 1) {\n\t\t\treturn buildCondition(conditions[0]);\n\t\t}\n\n\t\tconst operator = and ? \"and\" : \"or\";\n\t\tconst conditionsString = conditions.map(buildCondition).join(` ${operator} `);\n\t\treturn `(${conditionsString})`;\n\t}\n\n\tif (isNestedExpression(expression)) {\n\t\t// Обработка вложенного выражения\n\t\tconst { filters, and = false } = expression;\n\n\t\tif (filters.length === 0) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (filters.length === 1) {\n\t\t\treturn buildODataFilter(filters[0]);\n\t\t}\n\n\t\tconst operator = and ? \"and\" : \"or\";\n\t\tconst filterStrings = compactExpressionStrings(filters, buildODataFilter);\n\n\t\tif (filterStrings.length === 0) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (filterStrings.length === 1) {\n\t\t\treturn filterStrings[0];\n\t\t}\n\n\t\treturn `(${filterStrings.join(` ${operator} `)})`;\n\t}\n\n\tthrow new Error(\"Некорректное выражение фильтра\");\n}\n\n// Альтернативная версия с рекурсивной обработкой\nexport function buildODataFilterRecursive<T>(expression: FilterExpression<T> | undefined): string {\n\tconst processExpression = (expr: FilterExpression<T> | undefined): string => {\n\t\tif (!expr) return \"\";\n\n\t\tif (isConditionExpression(expr)) {\n\t\t\tconst { conditions, and = false } = expr;\n\n\t\t\tif (conditions.length === 0) return \"\";\n\t\t\tif (conditions.length === 1) return buildCondition(conditions[0]);\n\n\t\t\tconst operator = and ? \"and\" : \"or\";\n\t\t\treturn `(${conditions.map(buildCondition).join(` ${operator} `)})`;\n\t\t}\n\n\t\tif (isNestedExpression(expr)) {\n\t\t\tconst { filters, and = false } = expr;\n\n\t\t\tif (filters.length === 0) return \"\";\n\t\t\tif (filters.length === 1) return processExpression(filters[0]);\n\n\t\t\tconst operator = and ? \"and\" : \"or\";\n\t\t\tconst filterStrings = compactExpressionStrings(filters, processExpression).map((result) => {\n\t\t\t\treturn result.includes(\" \") ? `(${result})` : result;\n\t\t\t});\n\n\t\t\tif (filterStrings.length === 0) return \"\";\n\t\t\tif (filterStrings.length === 1) return filterStrings[0];\n\n\t\t\treturn `(${filterStrings.join(` ${operator} `)})`;\n\t\t}\n\n\t\treturn \"\";\n\t};\n\n\treturn processExpression(expression);\n}\n\nexport function createFilter<T, V extends BaseType>(\n\tkey: keyof T,\n\tvalue: (V | V[]) | null | undefined,\n\toperation: FilterOperation\n): FilterExpression<T> {\n\tif (value === null || value === undefined) return { conditions: [] };\n\n\tif (Array.isArray(value)) {\n\t\t// return {\n\t\t// \tconditions: value.filter((item) => item !== null || item !== undefined).map((item) => ({ key, value: item, operation }))\n\t\t// };\n\t\tconst conditions: FilterCondition<T>[] = [];\n\n\t\tfor (const item of value) {\n\t\t\tif (item !== null && item !== undefined) {\n\t\t\t\tconditions.push({ key, value: item, operation });\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tconditions\n\t\t};\n\t}\n\n\treturn {\n\t\tconditions: [{ key, value, operation }]\n\t};\n}\n\n/**\n * Создает выражение фильтра (`FilterExpression`)\n *\n * Пример конечного выражения:\n *\n * * псевдокод `(key ge odataFormatValue(value[0]) and key le odataFormatValue(value[1]))`\n * * результат `(COST eq 2000 and COST eq 5000)`\n */\nexport function createFilterBetween<T, V extends BaseType>(key: keyof T, values: readonly [V, V] | null | undefined): FilterExpression<T> {\n\tif (!values) return { conditions: [] };\n\n\tconst value1 = values[0];\n\tconst value2 = values[1];\n\n\tif (value1 === null || value1 === undefined || value2 === null || value2 === undefined) {\n\t\tif (value1) {\n\t\t\treturn {\n\t\t\t\tconditions: [{ key, value: value1, operation: \"ge\" }]\n\t\t\t};\n\t\t}\n\t\tif (value2) {\n\t\t\treturn {\n\t\t\t\tconditions: [{ key, value: value2, operation: \"le\" }]\n\t\t\t};\n\t\t}\n\t\treturn { conditions: [] };\n\t}\n\n\treturn {\n\t\tand: true,\n\t\tconditions: [\n\t\t\t{ key, value: value1, operation: \"ge\" },\n\t\t\t{ key, value: value2, operation: \"le\" }\n\t\t]\n\t};\n}\n\n/**\n * Создает выражение фильтра (`FilterExpression`)\n *\n * Пример конечного выражения:\n *\n * * псевдокод `key eq odataFormatValue(value)`\n * * результат `CUSTOMER eq '005417554'`\n *\n * Если `value` массив, то выражение формируется с оператором `or`: `(E1 or E2 or E3)`\n */\nexport function createFilterEqual<T, V extends BaseType>(key: keyof T, value: (V | V[]) | null | undefined): FilterExpression<T> {\n\treturn createFilter(key, value, \"eq\");\n}\n\nexport function createFilterEqualFalsy<T, V extends BaseType>(key: keyof T, value: (V | V[]) | null | undefined): FilterExpression<T> {\n\treturn createFilter(key, Array.isArray(value) ? value.map((v) => v || null) : value || null, \"eq\");\n}\n\n/**\n * Создает выражение фильтра (`FilterExpression`)\n *\n * Пример конечного выражения:\n *\n * * псевдокод `substringof(odataFormatValue(value), key)`\n * * результат `substringof('сталь', CUSTOMER)`\n *\n * Если `value` массив, то выражение формируется с оператором `or`: `(E1 or E2 or E3)`\n */\nexport function createFilterContains<T, V extends BaseType>(key: keyof T, value: (V | V[]) | null | undefined): FilterExpression<T> {\n\treturn createFilter(key, value, \"contains\");\n}\n\nexport function mergeFilterExpressions(\n\tleft?: FilterExpression<RowRecord>,\n\tright?: FilterExpression<RowRecord>\n): FilterExpression<RowRecord> | undefined {\n\tif (!left) return right;\n\tif (!right) return left;\n\n\treturn {\n\t\tand: true,\n\t\tfilters: [left, right]\n\t};\n}\n","import { compareStrings } from \"../string-comparison\";\nimport { BaseType, InputType } from \"../types\";\n\nimport { createFilterEqual, type FilterCondition, type FilterExpression, type FilterOperation } from \"./filters\";\n\nimport type { BaseMetaType, ODataChainsMap } from \"./types\";\n\ntype RowRecord = Record<string, unknown>;\ntype TreeFilterValue = Record<string, string[]>;\n\nexport type ODataFilterValue = InputType | TreeFilterValue;\nexport type ODataFilterValues = Record<string, ODataFilterValue>;\n\n/**\n * Одно условие OData-фильтра, которое может применяться не только к owner-колонке\n * фильтра, но и к явно выбранной колонке. Это нужно для локальных Select/MultiSelect:\n * один runtime-контрол выбирает option, а option уже знает, какую колонку таблицы\n * фильтровать и каким значением.\n */\nexport type ODataFilterCondition = {\n\t/**\n\t * Целевая колонка условия. Если не задана, компилятор использует ownerColumnId\n\t * фильтра, что сохраняет простую модель для обычных локальных value/boolean\n\t * фильтров и OData-сегментов.\n\t */\n\tcolumnId?: string;\n\toperation: FilterOperation;\n\tvalueSource: \"static\" | \"input\";\n\tvalue?: BaseType;\n};\n\nexport type ODataFilterConditionGroup = {\n\tand?: boolean;\n\tconditions: ODataFilterCondition[];\n};\n\nexport type ODataFilterOption = {\n\tkey: string;\n\tlabel: string;\n\tfilter?: ODataFilterConditionGroup;\n};\n\nexport type ODataFilterBinding =\n\t| {\n\t\t\tkind: \"list\";\n\t\t\t/** Связка выражений нескольких выбранных опций: `false`/отсутствие означает OR. */\n\t\t\tand?: boolean;\n\t\t\toptions: ODataFilterOption[];\n\t }\n\t| {\n\t\t\tkind: \"boolean\";\n\t\t\ttrueFilter?: ODataFilterConditionGroup;\n\t }\n\t| {\n\t\t\tkind: \"value\";\n\t\t\tvalueFilter?: ODataFilterConditionGroup;\n\t };\n\nexport type FilterDefinitionKind = \"segment\" | \"tree\" | \"advanced\" | \"local\" | \"registered\" | \"column\";\n\n/** Форма controlled-значения зарегистрированного фильтра. */\nexport type FilterRegisteredValueMode = \"single\" | \"multiple\";\n\nexport type FilterSegmentComponentId = \"multi-select\" | \"select\";\nexport type FilterTreeComponentId = \"tree-select\" | \"tree-multi-select\";\nexport type FilterLocalComponentId = \"select\" | \"multi-select\" | \"checkbox\" | \"text-input\" | \"number-input\";\nexport type FilterAdvancedComponentId = \"advanced-search-select\";\nexport type FilterComponentId = FilterSegmentComponentId | FilterTreeComponentId | FilterLocalComponentId | FilterAdvancedComponentId;\n\n// TODO: переименовать, теперь это не только odata\nexport type ODataCompiledFilterDefinition =\n\t| {\n\t\t\tid: string;\n\t\t\townerColumnId: string;\n\t\t\tcolumnIds: string[];\n\t\t\tkind: Extract<FilterDefinitionKind, \"segment\">;\n\t\t\tcomponentId: FilterSegmentComponentId;\n\t\t\tcontrolType: BaseMetaType;\n\t\t\tdictionaryCodeKey?: string;\n\t }\n\t| {\n\t\t\tid: string;\n\t\t\townerColumnId: string;\n\t\t\tcolumnIds: string[];\n\t\t\tkind: Extract<FilterDefinitionKind, \"tree\">;\n\t\t\tcomponentId: FilterTreeComponentId;\n\t\t\tcontrolType: BaseMetaType;\n\t\t\t/** Оператор между выбранными значениями разных уровней дерева. */\n\t\t\tlevelOperator?: \"and\" | \"or\";\n\t }\n\t| {\n\t\t\tid: string;\n\t\t\townerColumnId: string;\n\t\t\tcolumnIds: string[];\n\t\t\tkind: Extract<FilterDefinitionKind, \"local\">;\n\t\t\tcomponentId: FilterLocalComponentId;\n\t\t\tcontrolType: BaseMetaType;\n\t\t\tbinding: ODataFilterBinding;\n\t }\n\t| {\n\t\t\tid: string;\n\t\t\tkind: Extract<FilterDefinitionKind, \"registered\">;\n\t\t\t/** Id непрозрачного runtime-компонента из внешнего registry. */\n\t\t\tcomponentId: string;\n\t\t\tcontrolType: BaseMetaType;\n\t\t\tvalueMode: FilterRegisteredValueMode;\n\t\t\t/** Потенциально затрагиваемые физические колонки, производные от binding. */\n\t\t\tcolumnIds: string[];\n\t\t\t/** Отсутствует у parameter-only фильтра, который не формирует `$filter`. */\n\t\t\tbinding?: ODataFilterBinding;\n\t }\n\t| {\n\t\t\tid: string;\n\t\t\townerColumnId: string;\n\t\t\tkind: Extract<FilterDefinitionKind, \"advanced\">;\n\t\t\tcomponentId: FilterAdvancedComponentId;\n\t\t\tconfigId: string;\n\t }\n\t| {\n\t\t\tid: string;\n\t\t\townerColumnId: string;\n\t\t\tkind: Extract<FilterDefinitionKind, \"column\">;\n\t };\n\nexport function isFilterLocalComponentId(value: unknown): value is FilterLocalComponentId {\n\treturn value === \"select\" || value === \"multi-select\" || value === \"checkbox\" || value === \"text-input\" || value === \"number-input\";\n}\n\n/**\n * Собирает физические колонки, которые реально затрагивает группа условий.\n * Для conditions без columnId берём fallback owner-колонку: это важно для старого\n * поведения value/boolean-фильтров и для conditions, где колонка не выбирается явно.\n */\nfunction collectConditionGroupColumnIds(group: ODataFilterConditionGroup | undefined, fallbackColumnId: string) {\n\tif (!group?.conditions.length) return [];\n\n\treturn group.conditions.map((condition) => condition.columnId?.trim() || fallbackColumnId).filter((columnId) => Boolean(columnId));\n}\n\n/**\n * Выводит `columnIds` локального фильтра из его binding. Раньше local-фильтр всегда\n * владел только ownerColumnId, но list-option теперь может фильтровать любую\n * доступную visible/data колонку, поэтому runtime и конфликты фильтров должны\n * видеть полный набор затронутых колонок.\n */\nfunction collectBindingColumnIds(binding: ODataFilterBinding, fallbackColumnId: string) {\n\tconst columnIds =\n\t\tbinding.kind === \"list\"\n\t\t\t? binding.options.flatMap((option) => collectConditionGroupColumnIds(option.filter, fallbackColumnId))\n\t\t\t: binding.kind === \"boolean\"\n\t\t\t\t? collectConditionGroupColumnIds(binding.trueFilter, fallbackColumnId)\n\t\t\t\t: collectConditionGroupColumnIds(binding.valueFilter, fallbackColumnId);\n\n\treturn [...new Set(columnIds.length ? columnIds : fallbackColumnId ? [fallbackColumnId] : [])];\n}\n\nfunction resolveConditionGroupColumnIds(group: ODataFilterConditionGroup | undefined, fallbackColumnId: string) {\n\tconst columnIds = collectConditionGroupColumnIds(group, fallbackColumnId);\n\treturn columnIds.length ? columnIds : fallbackColumnId ? [fallbackColumnId] : [];\n}\n\ntype ListFilterDefinition = Extract<ODataCompiledFilterDefinition, { kind: \"local\" | \"registered\" }>;\n\nfunction isMultipleListFilterDefinition(definition: ListFilterDefinition) {\n\treturn definition.kind === \"registered\" ? definition.valueMode === \"multiple\" : definition.componentId === \"multi-select\";\n}\n\n/** Нормализует option keys и сохраняет пустую строку как допустимый выбор. */\nfunction sanitizeFilterOptionKeys(value: unknown): string[] {\n\tif (!Array.isArray(value)) return [];\n\n\treturn [...new Set(value.filter((item): item is string => typeof item === \"string\").map((item) => item.trim()))];\n}\n\nfunction resolveListFilterSelectedKeys(definition: ListFilterDefinition, value: ODataFilterValue) {\n\tif (isMultipleListFilterDefinition(definition)) {\n\t\treturn sanitizeFilterOptionKeys(value);\n\t}\n\n\tconst selectedValue = sanitizeScalarValue(value);\n\treturn typeof selectedValue === \"string\" ? [selectedValue] : [];\n}\n\n/**\n * Возвращает все физические колонки, которые потенциально затрагивает filter definition.\n *\n * Helper нужен runtime-проекциям, где важно понять совместимость фильтра с\n * конкретным OData target без повторной реализации правил compiler-а.\n */\nexport function resolveODataFilterDefinitionColumnIds(definition: ODataCompiledFilterDefinition): string[] {\n\tconst normalizedDefinition = sanitizeFilterDefinitions([definition])[0];\n\tif (!normalizedDefinition) return [];\n\n\tif (normalizedDefinition.kind === \"registered\") {\n\t\treturn [...normalizedDefinition.columnIds];\n\t}\n\n\tif (normalizedDefinition.kind === \"segment\" || normalizedDefinition.kind === \"column\" || normalizedDefinition.kind === \"advanced\") {\n\t\treturn [normalizedDefinition.ownerColumnId];\n\t}\n\n\treturn [...normalizedDefinition.columnIds];\n}\n\n/**\n * Возвращает физические колонки, которые реально затрагивает текущее значение фильтра.\n *\n * Для local list учитываются только выбранные option-ы, поэтому фильтр с\n * несколькими потенциальными колонками не блокирует target, если активный выбор\n * обращается только к доступным колонкам.\n */\nexport function resolveODataFilterDefinitionActiveColumnIds(\n\tdefinition: ODataCompiledFilterDefinition,\n\tvalue: ODataFilterValue | undefined\n): string[] {\n\tconst normalizedDefinition = sanitizeFilterDefinitions([definition])[0];\n\tconst normalizedValue = sanitizeFilterValue(value);\n\tif (!normalizedDefinition || normalizedValue === undefined) return [];\n\n\tswitch (normalizedDefinition.kind) {\n\t\tcase \"segment\":\n\t\tcase \"column\":\n\t\tcase \"advanced\": {\n\t\t\treturn [normalizedDefinition.ownerColumnId];\n\t\t}\n\n\t\tcase \"tree\": {\n\t\t\tconst treeValue = sanitizeTreeFilterValue(normalizedValue);\n\t\t\tif (!treeValue) return [];\n\t\t\treturn Object.keys(treeValue).filter((columnId) => normalizedDefinition.columnIds.includes(columnId));\n\t\t}\n\n\t\tcase \"local\": {\n\t\t\tif (normalizedDefinition.binding.kind === \"list\") {\n\t\t\t\tconst selectedKeys = resolveListFilterSelectedKeys(normalizedDefinition, normalizedValue);\n\t\t\t\treturn [\n\t\t\t\t\t...new Set(\n\t\t\t\t\t\tselectedKeys.flatMap((selectedKey) => {\n\t\t\t\t\t\t\tconst option =\n\t\t\t\t\t\t\t\tnormalizedDefinition.binding.kind === \"list\"\n\t\t\t\t\t\t\t\t\t? normalizedDefinition.binding.options.find((item) => item.key === selectedKey)\n\t\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\t\tif (!option) return [];\n\t\t\t\t\t\t\treturn resolveConditionGroupColumnIds(option.filter, normalizedDefinition.ownerColumnId);\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t];\n\t\t\t}\n\n\t\t\tif (normalizedDefinition.binding.kind === \"boolean\") {\n\t\t\t\treturn normalizedValue === true\n\t\t\t\t\t? resolveConditionGroupColumnIds(normalizedDefinition.binding.trueFilter, normalizedDefinition.ownerColumnId)\n\t\t\t\t\t: [];\n\t\t\t}\n\n\t\t\treturn resolveConditionGroupColumnIds(normalizedDefinition.binding.valueFilter, normalizedDefinition.ownerColumnId);\n\t\t}\n\n\t\tcase \"registered\": {\n\t\t\tconst binding = normalizedDefinition.binding;\n\t\t\tif (!binding) return [];\n\n\t\t\tif (binding.kind === \"list\") {\n\t\t\t\tconst selectedKeys = resolveListFilterSelectedKeys(normalizedDefinition, normalizedValue);\n\t\t\t\treturn [\n\t\t\t\t\t...new Set(\n\t\t\t\t\t\tselectedKeys.flatMap((selectedKey) => {\n\t\t\t\t\t\t\tconst option = binding.options.find((item) => item.key === selectedKey);\n\t\t\t\t\t\t\treturn option ? resolveConditionGroupColumnIds(option.filter, \"\") : [];\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t];\n\t\t\t}\n\n\t\t\tif (binding.kind === \"boolean\") {\n\t\t\t\treturn normalizedValue === true ? resolveConditionGroupColumnIds(binding.trueFilter, \"\") : [];\n\t\t\t}\n\n\t\t\treturn resolveConditionGroupColumnIds(binding.valueFilter, \"\");\n\t\t}\n\n\t\tdefault: {\n\t\t\tconst _checker: never = normalizedDefinition;\n\t\t\tvoid _checker;\n\t\t\treturn [];\n\t\t}\n\t}\n}\n\nexport function normalizeDictionaryCodeKey(value: string | undefined, ownerColumnId: string) {\n\tconst normalized = value?.trim();\n\treturn normalized && normalized !== ownerColumnId ? normalized : undefined;\n}\n\nfunction sanitizeScalarValue(value: unknown): BaseType | undefined {\n\tif (value instanceof Date) {\n\t\treturn Number.isFinite(value.getTime()) ? value : undefined;\n\t}\n\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim();\n\t\t// NOTE: 08.06.2026 разрешаем в фильтр передавать пустую строку\n\t\t// return normalized ? normalized : undefined;\n\t\treturn normalized;\n\t}\n\n\tif (typeof value === \"number\") {\n\t\treturn Number.isFinite(value) ? value : undefined;\n\t}\n\n\tif (typeof value === \"boolean\") {\n\t\treturn value;\n\t}\n\n\treturn undefined;\n}\n\nfunction serializeBaseValue(value: BaseType) {\n\tif (value instanceof Date) {\n\t\treturn `date:${value.toISOString()}`;\n\t}\n\n\treturn `${typeof value}:${String(value)}`;\n}\n\nfunction sanitizeArrayValue(value: unknown): BaseType[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\n\tconst seen = new Set<string>();\n\tconst normalized: BaseType[] = [];\n\n\tfor (const item of value) {\n\t\tconst nextValue = sanitizeScalarValue(item);\n\t\tif (nextValue === undefined) continue;\n\n\t\tconst key = serializeBaseValue(nextValue);\n\t\tif (seen.has(key)) continue;\n\t\tseen.add(key);\n\t\tnormalized.push(nextValue);\n\t}\n\n\tnormalized.sort((left, right) => compareStrings(serializeBaseValue(left), serializeBaseValue(right)));\n\n\treturn normalized.length ? normalized : undefined;\n}\n\nfunction sanitizeStringArray(value: unknown): string[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\n\tconst normalized = [\n\t\t...new Set(\n\t\t\tvalue\n\t\t\t\t.filter((item): item is string => typeof item === \"string\")\n\t\t\t\t.map((item) => item.trim())\n\t\t\t\t.filter(Boolean)\n\t\t)\n\t]; // .sort();\n\treturn normalized.length ? normalized : undefined;\n}\n\nfunction sanitizeTreeFilterValue(value: unknown): TreeFilterValue | undefined {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value) || value instanceof Date) return undefined;\n\n\tconst normalized = Object.fromEntries(\n\t\tObject.entries(value)\n\t\t\t.map(([columnId, rawValues]) => [columnId.trim(), sanitizeStringArray(rawValues)] as const)\n\t\t\t.filter((entry): entry is [string, string[]] => Boolean(entry[0]) && Boolean(entry[1]?.length))\n\t);\n\n\treturn Object.keys(normalized).length ? normalized : undefined;\n}\n\nexport function sanitizeFilterConditionGroup(group: ODataFilterConditionGroup | undefined): ODataFilterConditionGroup | undefined {\n\tif (!group?.conditions?.length) return undefined;\n\n\tconst conditions: ODataFilterCondition[] = [];\n\n\tfor (const condition of group.conditions) {\n\t\tconst value = sanitizeScalarValue(condition.value);\n\t\tif (condition.valueSource === \"static\" && value === undefined) continue;\n\n\t\tconditions.push({\n\t\t\tcolumnId: condition.columnId?.trim() || undefined,\n\t\t\toperation: condition.operation,\n\t\t\tvalueSource: condition.valueSource,\n\t\t\tvalue\n\t\t});\n\t}\n\n\tif (!conditions.length) return undefined;\n\n\treturn {\n\t\tand: group.and === false ? false : group.and ? true : undefined,\n\t\tconditions\n\t};\n}\n\nexport function sanitizeFilterBinding(binding: ODataFilterBinding | undefined): ODataFilterBinding | undefined {\n\tif (!binding) return undefined;\n\n\tif (binding.kind === \"list\") {\n\t\tconst options: ODataFilterOption[] = [];\n\t\t// const keysSet = new Set<string>();\n\n\t\tfor (const option of binding.options ?? []) {\n\t\t\tconst key = option.key.trim();\n\t\t\t// NOTE: пустой ключ разрешаем\n\t\t\t// TODO: подумать, допустимо ли дублирование\n\t\t\t// if (keysSet.has(key)) continue;\n\t\t\t// keysSet.add(key);\n\n\t\t\toptions.push({\n\t\t\t\tkey,\n\t\t\t\tlabel: option.label.trim() || key,\n\t\t\t\tfilter: sanitizeFilterConditionGroup(option.filter)\n\t\t\t});\n\t\t}\n\n\t\tif (!options.length) return undefined;\n\n\t\tconst and = binding.and === true ? true : binding.and === false ? false : undefined;\n\t\treturn {\n\t\t\tkind: \"list\",\n\t\t\t...(and === undefined ? {} : { and }),\n\t\t\toptions\n\t\t};\n\t}\n\n\tif (binding.kind === \"boolean\") {\n\t\treturn {\n\t\t\tkind: \"boolean\",\n\t\t\ttrueFilter: sanitizeFilterConditionGroup(binding.trueFilter)\n\t\t};\n\t}\n\n\treturn {\n\t\tkind: \"value\",\n\t\tvalueFilter: sanitizeFilterConditionGroup(binding.valueFilter)\n\t};\n}\n\nexport function sanitizeFilterDefinitions<T extends ODataCompiledFilterDefinition>(definitions?: readonly T[]): T[] {\n\tif (!definitions?.length) return [];\n\n\tconst normalized: T[] = [];\n\n\tfor (const definition of definitions) {\n\t\tconst id = definition.id.trim();\n\t\tif (!id) continue;\n\t\t/*\n\t\t * Sanitizer может получать readonly snapshot из Zustand/Immer. Legacy-поля\n\t\t * нормализуем только на локальной копии, чтобы чтение конфигурации никогда\n\t\t * не изменяло и не пыталось разморозить входной объект.\n\t\t */\n\t\tconst normalizedDefinition = { ...definition };\n\n\t\t// HACK: на период пересохранения всех конфигов\n\t\tif ((normalizedDefinition.kind as string) === \"odata-segment\") {\n\t\t\tnormalizedDefinition.kind = \"segment\";\n\t\t}\n\t\tif ((normalizedDefinition.kind as string) === \"odata-tree\") {\n\t\t\tnormalizedDefinition.kind = \"tree\";\n\t\t}\n\n\t\tif (normalizedDefinition.kind === \"registered\") {\n\t\t\tconst componentId = normalizedDefinition.componentId.trim();\n\t\t\tconst valueMode = normalizedDefinition.valueMode;\n\t\t\tif (!componentId || (valueMode !== \"single\" && valueMode !== \"multiple\")) continue;\n\n\t\t\tconst binding = sanitizeFilterBinding(normalizedDefinition.binding);\n\t\t\tnormalized.push({\n\t\t\t\t...normalizedDefinition,\n\t\t\t\tid,\n\t\t\t\tcomponentId,\n\t\t\t\tvalueMode,\n\t\t\t\tcolumnIds: binding ? collectBindingColumnIds(binding, \"\") : [],\n\t\t\t\tbinding\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst ownerColumnId = normalizedDefinition.ownerColumnId.trim();\n\t\tif (!ownerColumnId) continue;\n\n\t\tswitch (normalizedDefinition.kind) {\n\t\t\tcase \"segment\": {\n\t\t\t\tnormalized.push({\n\t\t\t\t\t...normalizedDefinition,\n\t\t\t\t\tid,\n\t\t\t\t\townerColumnId,\n\t\t\t\t\tcolumnIds: [ownerColumnId],\n\t\t\t\t\tcomponentId: normalizedDefinition.componentId === \"select\" ? \"select\" : \"multi-select\",\n\t\t\t\t\tdictionaryCodeKey: normalizeDictionaryCodeKey(normalizedDefinition.dictionaryCodeKey, ownerColumnId)\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"tree\": {\n\t\t\t\tconst columnIds = [...new Set(normalizedDefinition.columnIds.map((columnId) => columnId.trim()).filter(Boolean))];\n\t\t\t\t/*\n\t\t\t\t * Визуальное дерево может иметь consumer-синтетический root, который не\n\t\t\t\t * участвует в серверном фильтре. Поэтому definition обязан содержать хотя\n\t\t\t\t * бы одно фильтруемое поле, но не обязан сериализовать два UI-уровня.\n\t\t\t\t */\n\t\t\t\tif (!columnIds.length) break;\n\n\t\t\t\t// HACK: на период пересохранения всех конфигов\n\t\t\t\tconst rawComponentId = normalizedDefinition.componentId as string;\n\t\t\t\tconst componentId =\n\t\t\t\t\trawComponentId === \"treeSelect\" || rawComponentId === \"tree-select\" ? \"tree-select\" : \"tree-multi-select\";\n\n\t\t\t\tnormalized.push({\n\t\t\t\t\t...normalizedDefinition,\n\t\t\t\t\tid,\n\t\t\t\t\townerColumnId: columnIds.includes(ownerColumnId) ? ownerColumnId : columnIds[0],\n\t\t\t\t\tcolumnIds,\n\t\t\t\t\tcomponentId,\n\t\t\t\t\tlevelOperator: normalizedDefinition.levelOperator === \"or\" ? \"or\" : undefined\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"local\": {\n\t\t\t\tconst binding = sanitizeFilterBinding(normalizedDefinition.binding);\n\t\t\t\tif (!binding) break;\n\n\t\t\t\tnormalized.push({\n\t\t\t\t\t...normalizedDefinition,\n\t\t\t\t\tid,\n\t\t\t\t\townerColumnId,\n\t\t\t\t\t// Для local-фильтров список колонок является производным от conditions.\n\t\t\t\t\t// Это делает Select/MultiSelect с option -> columnId частью общего\n\t\t\t\t\t// контракта фильтров без отдельной runtime-модели.\n\t\t\t\t\tcolumnIds: collectBindingColumnIds(binding, ownerColumnId),\n\t\t\t\t\tbinding\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"advanced\": {\n\t\t\t\tnormalized.push({\n\t\t\t\t\t...normalizedDefinition,\n\t\t\t\t\tid,\n\t\t\t\t\townerColumnId\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"column\": {\n\t\t\t\tnormalized.push({\n\t\t\t\t\t...normalizedDefinition,\n\t\t\t\t\tid,\n\t\t\t\t\townerColumnId\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst _checker: never = normalizedDefinition;\n\t\t\t\tvoid _checker;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn normalized;\n}\n\nexport function sanitizeFilterValue(value: ODataFilterValue | undefined): ODataFilterValue | undefined {\n\tif (value === null || value === undefined) return undefined;\n\n\tconst scalarValue = sanitizeScalarValue(value);\n\tif (scalarValue !== undefined) return scalarValue;\n\n\tconst arrayValue = sanitizeArrayValue(value);\n\tif (arrayValue) return arrayValue;\n\n\treturn sanitizeTreeFilterValue(value);\n}\n\nexport function sanitizeFilterValues(values?: ODataFilterValues): ODataFilterValues {\n\tif (!values) return {};\n\n\tconst normalized: ODataFilterValues = {};\n\n\tfor (const [key, value] of Object.entries(values)) {\n\t\tconst filterId = key.trim();\n\t\tif (!filterId) continue;\n\n\t\tconst nextValue = sanitizeFilterValue(value);\n\t\tif (nextValue === undefined) continue;\n\t\tnormalized[filterId] = nextValue;\n\t}\n\n\treturn normalized;\n}\n\nexport function mergeFilterValuePatch(values: ODataFilterValues | undefined, filterId: string, value: ODataFilterValue | undefined) {\n\tconst normalizedValues = sanitizeFilterValues(values);\n\tconst nextValues = { ...normalizedValues };\n\tconst nextValue = sanitizeFilterValue(value);\n\n\tif (nextValue === undefined) {\n\t\tdelete nextValues[filterId];\n\t\treturn nextValues;\n\t}\n\n\tnextValues[filterId] = nextValue;\n\treturn nextValues;\n}\n\nexport function collapseChainedODataSegmentFilterValues(\n\tvalues: ODataFilterValues,\n\todataSegmentIds: readonly string[],\n\tchains: ODataChainsMap\n): ODataFilterValues {\n\tif (!values || Object.keys(values).length === 0) return {};\n\n\tconst result: ODataFilterValues = {};\n\tconst codeToChain: Record<string, string> = {};\n\n\tfor (const [chainKey, chainItems] of Object.entries(chains)) {\n\t\tfor (const item of chainItems) {\n\t\t\tcodeToChain[item.codeKey] = chainKey;\n\t\t}\n\t}\n\n\tconst groupedByChain: Record<string, string[]> = {};\n\tconst odataSegmentIdSet = new Set(odataSegmentIds);\n\n\tfor (const [filterId, value] of Object.entries(values)) {\n\t\tconst chainKey = codeToChain[filterId];\n\t\tconst isODataSegment = odataSegmentIdSet.has(filterId);\n\t\tconst isListValue = Array.isArray(value) || typeof value === \"string\";\n\n\t\tif (chainKey && isODataSegment && isListValue) {\n\t\t\tgroupedByChain[chainKey] = groupedByChain[chainKey] ?? [];\n\t\t\tgroupedByChain[chainKey].push(filterId);\n\t\t\tcontinue;\n\t\t}\n\n\t\tresult[filterId] = value;\n\t}\n\n\tfor (const [chainKey, filterIds] of Object.entries(groupedByChain)) {\n\t\tconst chain = chains[chainKey];\n\t\tif (!chain) continue;\n\n\t\tlet deepestFilterId: string | null = null;\n\t\tfor (const { codeKey } of [...chain].reverse()) {\n\t\t\tif (filterIds.includes(codeKey)) {\n\t\t\t\tdeepestFilterId = codeKey;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (deepestFilterId && values[deepestFilterId] !== undefined) {\n\t\t\tresult[deepestFilterId] = values[deepestFilterId];\n\t\t}\n\t}\n\n\treturn result;\n}\n\nfunction resolveExpressionValue(valueSource: \"static\" | \"input\", value: ODataFilterValue | BaseType | undefined) {\n\tif (valueSource === \"static\") {\n\t\treturn sanitizeScalarValue(value);\n\t}\n\n\treturn sanitizeScalarValue(value);\n}\n\nfunction compileCondition(\n\townerColumnId: string,\n\tcondition: ODataFilterCondition,\n\tinputValue?: ODataFilterValue\n): FilterCondition<RowRecord> | undefined {\n\tconst value = resolveExpressionValue(condition.valueSource, condition.valueSource === \"input\" ? inputValue : condition.value);\n\tif (value === undefined) return undefined;\n\tconst targetColumnId = condition.columnId?.trim() || ownerColumnId;\n\tif (!targetColumnId) return undefined;\n\n\treturn {\n\t\t// columnId позволяет одному локальному list-контролу генерировать условия\n\t\t// по разным колонкам; ownerColumnId остаётся безопасным fallback для\n\t\t// простых фильтров и ранее созданных groups без явной колонки.\n\t\tkey: targetColumnId,\n\t\toperation: condition.operation,\n\t\tvalue\n\t};\n}\n\nfunction compileConditionGroup(\n\townerColumnId: string,\n\tgroup: ODataFilterConditionGroup | undefined,\n\tinputValue?: ODataFilterValue\n): FilterExpression<RowRecord> | undefined {\n\tif (!group?.conditions.length) return undefined;\n\n\tconst conditions = group.conditions\n\t\t.map((condition) => compileCondition(ownerColumnId, condition, inputValue))\n\t\t.filter((condition): condition is FilterCondition<RowRecord> => Boolean(condition));\n\n\tif (!conditions.length) return undefined;\n\n\treturn {\n\t\tand: group.and === false ? undefined : true,\n\t\tconditions\n\t};\n}\n\nfunction compileDefaultBooleanFilter(ownerColumnId: string) {\n\treturn createFilterEqual<RowRecord, true>(ownerColumnId, true);\n}\n\nfunction compileDefaultValueFilter(ownerColumnId: string, value: BaseType | BaseType[]) {\n\treturn createFilterEqual<RowRecord, BaseType>(ownerColumnId, value);\n}\n\nfunction compileTreeFilter(definition: Extract<ODataCompiledFilterDefinition, { kind: \"tree\" }>, value: ODataFilterValue | undefined) {\n\tconst treeValue = sanitizeTreeFilterValue(value);\n\tif (!treeValue) return undefined;\n\n\tconst filters = definition.columnIds\n\t\t.map((columnId) => {\n\t\t\tconst selectedValues = treeValue[columnId];\n\t\t\tif (!selectedValues?.length) return undefined;\n\n\t\t\treturn createFilterEqual<RowRecord, string>(columnId, selectedValues);\n\t\t})\n\t\t.filter((filter): filter is FilterExpression<RowRecord> => Boolean(filter));\n\n\tif (!filters.length) return undefined;\n\tif (filters.length === 1) return filters[0];\n\n\treturn {\n\t\tand: definition.levelOperator === \"or\" ? undefined : true,\n\t\tfilters\n\t};\n}\n\nfunction compileListFilter(definition: ListFilterDefinition, value: ODataFilterValue | undefined): FilterExpression<RowRecord> | undefined {\n\tif (!definition.binding || definition.binding.kind !== \"list\") return undefined;\n\tconst binding = definition.binding;\n\tconst selectedKeys = resolveListFilterSelectedKeys(definition, value);\n\tif (!selectedKeys.length) return undefined;\n\n\tconst fallbackColumnId = definition.kind === \"local\" ? definition.ownerColumnId : \"\";\n\tconst filters = selectedKeys\n\t\t.map((selectedKey) => {\n\t\t\tconst option = binding.options.find((item) => item.key === selectedKey);\n\t\t\tif (!option) return undefined;\n\n\t\t\tconst explicitFilter = compileConditionGroup(fallbackColumnId, option.filter);\n\t\t\tif (explicitFilter || definition.kind === \"registered\") return explicitFilter;\n\n\t\t\treturn compileDefaultValueFilter(definition.ownerColumnId, option.key);\n\t\t})\n\t\t.filter((filter): filter is FilterExpression<RowRecord> => Boolean(filter));\n\n\tif (!filters.length) return undefined;\n\tif (filters.length === 1) return filters[0];\n\n\treturn {\n\t\tand: binding.and === true ? true : undefined,\n\t\tfilters\n\t};\n}\n\nfunction compileDefinitionFilter(\n\tdefinition: ODataCompiledFilterDefinition,\n\tvalue: ODataFilterValue | undefined\n): FilterExpression<RowRecord> | undefined {\n\tif (value === undefined) return undefined;\n\n\tswitch (definition.kind) {\n\t\tcase \"segment\": {\n\t\t\tif (definition.componentId === \"select\") {\n\t\t\t\tconst scalarValue = sanitizeScalarValue(value);\n\t\t\t\treturn scalarValue !== undefined ? compileDefaultValueFilter(definition.ownerColumnId, scalarValue) : undefined;\n\t\t\t}\n\n\t\t\tconst arrayValue = sanitizeArrayValue(value);\n\t\t\treturn arrayValue?.length ? compileDefaultValueFilter(definition.ownerColumnId, arrayValue) : undefined;\n\t\t}\n\n\t\tcase \"tree\": {\n\t\t\treturn compileTreeFilter(definition, value);\n\t\t}\n\n\t\tcase \"local\": {\n\t\t\tif (definition.binding.kind === \"list\") {\n\t\t\t\treturn compileListFilter(definition, value);\n\t\t\t}\n\n\t\t\tif (definition.binding.kind === \"boolean\") {\n\t\t\t\tif (value !== true) return undefined;\n\t\t\t\treturn (\n\t\t\t\t\tcompileConditionGroup(definition.ownerColumnId, definition.binding.trueFilter) ??\n\t\t\t\t\tcompileDefaultBooleanFilter(definition.ownerColumnId)\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\tcompileConditionGroup(definition.ownerColumnId, definition.binding.valueFilter, value) ??\n\t\t\t\t(() => {\n\t\t\t\t\tconst scalarValue = sanitizeScalarValue(value);\n\t\t\t\t\tconst arrayValue = sanitizeArrayValue(value);\n\t\t\t\t\tconst defaultValue = scalarValue ?? arrayValue;\n\t\t\t\t\treturn defaultValue !== undefined ? compileDefaultValueFilter(definition.ownerColumnId, defaultValue) : undefined;\n\t\t\t\t})()\n\t\t\t);\n\t\t}\n\n\t\tcase \"registered\": {\n\t\t\tif (!definition.binding) return undefined;\n\n\t\t\tif (definition.binding.kind === \"list\") {\n\t\t\t\treturn compileListFilter(definition, value);\n\t\t\t}\n\n\t\t\tif (definition.binding.kind === \"boolean\") {\n\t\t\t\treturn value === true ? compileConditionGroup(\"\", definition.binding.trueFilter) : undefined;\n\t\t\t}\n\n\t\t\treturn compileConditionGroup(\"\", definition.binding.valueFilter, value);\n\t\t}\n\n\t\tcase \"column\": {\n\t\t\tconst scalarValue = sanitizeScalarValue(value);\n\t\t\tconst arrayValue = sanitizeArrayValue(value);\n\t\t\tconst defaultValue = scalarValue ?? arrayValue;\n\t\t\treturn defaultValue !== undefined ? compileDefaultValueFilter(definition.ownerColumnId, defaultValue) : undefined;\n\t\t}\n\n\t\tcase \"advanced\": {\n\t\t\tconst arrayValue = sanitizeArrayValue(value);\n\t\t\treturn arrayValue?.length ? compileDefaultValueFilter(definition.ownerColumnId, arrayValue) : undefined;\n\t\t}\n\n\t\tdefault: {\n\t\t\tconst _checker: never = definition;\n\t\t\tvoid _checker;\n\t\t}\n\t}\n}\n\nexport function compileFiltersToExpression(\n\tdefinitions?: readonly ODataCompiledFilterDefinition[],\n\tvalues?: ODataFilterValues\n): FilterExpression<RowRecord> | undefined {\n\tconst normalizedDefinitions = sanitizeFilterDefinitions(definitions);\n\tconst normalizedValues = sanitizeFilterValues(values);\n\tif (!normalizedDefinitions.length || !Object.keys(normalizedValues).length) return undefined;\n\n\tconst filters = normalizedDefinitions\n\t\t.map((definition) => compileDefinitionFilter(definition, normalizedValues[definition.id]))\n\t\t.filter((filter): filter is FilterExpression<RowRecord> => Boolean(filter));\n\n\tif (!filters.length) return undefined;\n\tif (filters.length === 1) return filters[0];\n\n\treturn {\n\t\tand: true,\n\t\tfilters\n\t};\n}\n\nexport function flattenFilterValuesToODataDependencies(\n\tdefinitions?: readonly ODataCompiledFilterDefinition[],\n\tvalues?: ODataFilterValues\n): Record<string, string[]> {\n\tconst normalizedDefinitions = sanitizeFilterDefinitions(definitions);\n\tconst normalizedValues = sanitizeFilterValues(values);\n\tconst dependencies: Record<string, string[]> = {};\n\n\tfor (const definition of normalizedDefinitions) {\n\t\tif (definition.kind !== \"segment\" && definition.kind !== \"tree\") continue;\n\n\t\tconst value = normalizedValues[definition.id];\n\t\tif (value === undefined) continue;\n\n\t\tif (definition.kind === \"segment\") {\n\t\t\tconst scalarValue = typeof value === \"string\" ? value : undefined;\n\t\t\tconst arrayValue = sanitizeStringArray(value);\n\t\t\tconst selectedValues = scalarValue ? [scalarValue] : arrayValue;\n\t\t\tif (!selectedValues?.length) continue;\n\n\t\t\tdependencies[definition.dictionaryCodeKey ?? definition.ownerColumnId] = selectedValues;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst treeValue = sanitizeTreeFilterValue(value);\n\t\tif (!treeValue) continue;\n\n\t\tfor (const columnId of definition.columnIds) {\n\t\t\tconst selectedValues = treeValue[columnId];\n\t\t\tif (!selectedValues) continue;\n\t\t\tif (!selectedValues.length) continue;\n\t\t\tdependencies[columnId] = selectedValues;\n\t\t}\n\t}\n\n\treturn dependencies;\n}\n","import { CollectionItem, CollectionPair } from \"./collectionTypes\";\n\nexport function findCollectionPairs(\n\titem: CollectionItem,\n\toptions: { textSuffixes?: string[]; caseSensitive?: boolean; returnUnpaired?: boolean } = {}\n) {\n\tconst { textSuffixes = [\"_txt\", \"_text\", \"_t\", \"_Text\", \"_TXT\", \"_T\"], caseSensitive = false, returnUnpaired = false } = options;\n\n\tconst fields = Object.keys(item);\n\tconst pairs = [] as CollectionPair[];\n\tconst pairsMap = {} as Record<string, string>;\n\tconst usedFields = new Set();\n\tconst unpairedFields = new Set(fields);\n\n\t// Создаем регулярное выражение для поиска текстовых полей\n\tconst suffixPattern = textSuffixes.map((s) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")).join(\"|\");\n\tconst textFieldRegex = new RegExp(`(.*)(${suffixPattern})$`, caseSensitive ? \"\" : \"i\");\n\n\t// Сначала проходим по всем полям и находим текстовые\n\tconst textFields = fields.filter((field) => textFieldRegex.test(field));\n\n\t// Для каждого текстового поля ищем соответствующее кодовое\n\tfor (const textField of textFields) {\n\t\tif (usedFields.has(textField)) continue;\n\n\t\tconst match = textField.match(textFieldRegex);\n\t\tif (match) {\n\t\t\tconst baseName = match[1]; // Имя без суффикса\n\n\t\t\tif (fields.includes(baseName) && !usedFields.has(baseName)) {\n\t\t\t\tpairs.push({\n\t\t\t\t\tcodeKey: baseName,\n\t\t\t\t\ttextKey: textField\n\t\t\t\t});\n\t\t\t\tpairsMap[baseName] = textField;\n\t\t\t\tusedFields.add(baseName);\n\t\t\t\tusedFields.add(textField);\n\t\t\t\tunpairedFields.delete(baseName);\n\t\t\t\tunpairedFields.delete(textField);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst result: { pairs: CollectionPair[]; pairsMap: CollectionItem; unpaired?: string[] } = { pairs, pairsMap };\n\n\tif (returnUnpaired) {\n\t\tresult.unpaired = Array.from(unpairedFields);\n\t}\n\n\treturn result;\n}\n","// Глобальные конфигурируемые параметры отображения OData-коллекций.\n\nimport { create } from \"zustand\";\nimport { immer } from \"zustand/middleware/immer\";\n\ntype ODataCollectionState = {\n\tdefaultMaxVisibleItems: number;\n\tdefaultMinSearchTextLength: number;\n\tdefaultMinSearchCodeLength: number;\n\tdefaultSearchDebounceDelay: number;\n};\n\ntype ODataCollectionActions = {\n\tsetDefaultMaxVisibleItems: (value: number) => void;\n\tsetDefaultMinSearchTextLength: (value: number) => void;\n\tsetDefaultMinSearchCodeLength: (value: number) => void;\n\tsetDefaultSearchDebounceDelay: (value: number) => void;\n};\n\nexport const useODataCollectionStore = create<ODataCollectionState & ODataCollectionActions>()(\n\timmer((set) => ({\n\t\tdefaultMaxVisibleItems: 200,\n\t\tdefaultMinSearchCodeLength: 3,\n\t\tdefaultMinSearchTextLength: 1,\n\t\tdefaultSearchDebounceDelay: 100,\n\n\t\tsetDefaultMaxVisibleItems: (defaultMaxVisibleItems) => set({ defaultMaxVisibleItems }),\n\t\tsetDefaultMinSearchTextLength: (defaultMinSearchTextLength) => set({ defaultMinSearchTextLength }),\n\t\tsetDefaultMinSearchCodeLength: (defaultMinSearchCodeLength) => set({ defaultMinSearchCodeLength }),\n\t\tsetDefaultSearchDebounceDelay: (defaultSearchDebounceDelay) => set({ defaultSearchDebounceDelay })\n\t}))\n);\n\n// export const useODataCollectionDefaultMaxVisibleItems = () => useODataCollectionStore((s) => s.defaultMaxVisibleItems);\n// export const useODataCollectionDefaultMinSearchCodeLength = () => useODataCollectionStore((s) => s.defaultMinSearchCodeLength);\n// export const useODataCollectionDefaultMinSearchTextLength = () => useODataCollectionStore((s) => s.defaultMinSearchTextLength);\n// export const useODataCollectionDefaultSearchDebounceDelay = () => useODataCollectionStore((s) => s.defaultSearchDebounceDelay);\n\nexport const odataCollectionConfig = {\n\tuseMaxVisibleItems: () => useODataCollectionStore((s) => s.defaultMaxVisibleItems),\n\tuseMinSearchCodeLength: () => useODataCollectionStore((s) => s.defaultMinSearchCodeLength),\n\tuseMinSearchTextLength: () => useODataCollectionStore((s) => s.defaultMinSearchTextLength),\n\tuseSearchDebounce: () => useODataCollectionStore((s) => s.defaultSearchDebounceDelay)\n};\n","/**\n * Парсер метаданных OData V2\n */\n\nimport {\n\tEntityColumnProperty,\n\tEntityMetadata,\n\tEntityParameterProperty,\n\tFunctionImportMetadata,\n\tODataMetaType,\n\tServiceMetadata\n} from \"./types\";\n\nconst TEXT_SUFFIX_REGEXP = /^(.+)(_txt|_text|_t)$/i;\nexport const FORCED_CODE_TEXT_IDS: ReadonlySet<string> = new Set([\"ZDIV\", \"ZCFO1\"]);\n\ntype AssociationSetEndpoint = {\n\trole: string;\n\tentitySet: string;\n};\n\ntype AssociationSetMetadata = {\n\tends: AssociationSetEndpoint[];\n};\n\ntype ResultNavigationMetadata = {\n\tname: \"Set\" | \"Results\";\n\ttargetEntitySet?: string;\n};\n\n/** Возвращает label metadata-колонки с fallback на технический id. */\nexport function resolveMetadataColumnLabel(column: Pick<EntityColumnProperty, \"id\" | \"label\">): string {\n\treturn column.label || column.id;\n}\n\nexport function isForcedCodeTextId(columnId?: string): boolean {\n\tif (!columnId) return false;\n\treturn FORCED_CODE_TEXT_IDS.has(columnId.toUpperCase());\n}\n\nexport function isForcedCodeTextFamilyId(columnId?: string): boolean {\n\tif (!columnId) return false;\n\n\tconst normalizedId = columnId.toUpperCase();\n\tif (FORCED_CODE_TEXT_IDS.has(normalizedId)) return true;\n\n\tconst match = normalizedId.match(/^(.+)(_TXT|_TEXT|_T)$/);\n\tif (!match) return false;\n\n\treturn FORCED_CODE_TEXT_IDS.has(match[1]!);\n}\n\nfunction escapeRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Возвращает `true`, если свойство описано скалярным EDM-типом и может быть\n * представлено в нашей метамодели без отдельной поддержки complex type.\n */\nfunction isScalarEdmPropertyType(typeName: string): boolean {\n\treturn typeName.startsWith(\"Edm.\");\n}\n\nfunction resolveColumnIdByCaseInsensitive(columnsByIdUpper: Record<string, string>, columnId?: string): string | undefined {\n\tif (!columnId) return undefined;\n\treturn columnsByIdUpper[columnId.toUpperCase()];\n}\n\nfunction findTextColumnForCodeId(\n\tcodeId: string,\n\tcolumns: EntityColumnProperty[],\n\tcolumnsByIdUpper: Record<string, string>\n): string | undefined {\n\tconst normalizedCodeId = resolveColumnIdByCaseInsensitive(columnsByIdUpper, codeId);\n\tif (!normalizedCodeId) return undefined;\n\n\tconst textColumnRegExp = new RegExp(`^${escapeRegExp(normalizedCodeId)}(_txt|_text|_t)$`, \"i\");\n\n\tfor (const column of columns) {\n\t\tif (textColumnRegExp.test(column.id)) {\n\t\t\treturn column.id;\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\nfunction normalizeColumns(columns: EntityColumnProperty[]): EntityColumnProperty[] {\n\tconst columnsById: Record<string, EntityColumnProperty> = {};\n\tconst columnsByIdUpper: Record<string, string> = {};\n\n\tfor (const column of columns) {\n\t\tcolumnsById[column.id] = column;\n\t\tcolumnsByIdUpper[column.id.toUpperCase()] = column.id;\n\t}\n\n\tfor (const column of columns) {\n\t\tif (column.role === \"measure\") {\n\t\t\tcolumn.semanticType = \"none\";\n\t\t\tcolumn.linkedColumnId = undefined;\n\t\t\tcontinue;\n\t\t}\n\n\t\tcolumn.role = \"dimension\";\n\t\tcolumn.sortable = true;\n\t\tcolumn.filterable = true;\n\t\tcolumn.semanticType = TEXT_SUFFIX_REGEXP.test(column.id) ? \"text\" : \"code\";\n\n\t\tconst linkedColumnId = resolveColumnIdByCaseInsensitive(columnsByIdUpper, column.linkedColumnId);\n\t\tcolumn.linkedColumnId = linkedColumnId && linkedColumnId !== column.id ? linkedColumnId : undefined;\n\t}\n\n\tfor (const column of columns) {\n\t\tif (column.role !== \"dimension\" || column.semanticType !== \"code\") continue;\n\n\t\tlet textColumnId = column.linkedColumnId;\n\t\tif (textColumnId) {\n\t\t\tconst linkedColumn = columnsById[textColumnId];\n\t\t\tif (!linkedColumn || linkedColumn.role !== \"dimension\") {\n\t\t\t\ttextColumnId = undefined;\n\t\t\t} else {\n\t\t\t\tlinkedColumn.semanticType = \"text\";\n\t\t\t}\n\t\t}\n\n\t\tif (!textColumnId) {\n\t\t\ttextColumnId = findTextColumnForCodeId(column.id, columns, columnsByIdUpper);\n\t\t}\n\n\t\t// Часто эти пары не описаны в metadata, поэтому пробуем восстановить их по суффиксу.\n\t\tif (!textColumnId && isForcedCodeTextId(column.id)) {\n\t\t\ttextColumnId = findTextColumnForCodeId(column.id, columns, columnsByIdUpper);\n\t\t}\n\n\t\tcolumn.linkedColumnId = textColumnId;\n\n\t\tif (textColumnId) {\n\t\t\tconst textColumn = columnsById[textColumnId];\n\t\t\tif (textColumn && textColumn.role === \"dimension\") {\n\t\t\t\ttextColumn.semanticType = \"text\";\n\t\t\t\ttextColumn.linkedColumnId = column.id;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const column of columns) {\n\t\tif (column.role !== \"dimension\" || column.semanticType !== \"text\") continue;\n\n\t\tlet codeColumnId = column.linkedColumnId;\n\t\tif (codeColumnId) {\n\t\t\tconst linkedColumn = columnsById[codeColumnId];\n\t\t\tif (!linkedColumn || linkedColumn.role !== \"dimension\") {\n\t\t\t\tcodeColumnId = undefined;\n\t\t\t} else {\n\t\t\t\tlinkedColumn.semanticType = \"code\";\n\t\t\t}\n\t\t}\n\n\t\tif (!codeColumnId) {\n\t\t\tconst match = column.id.match(TEXT_SUFFIX_REGEXP);\n\t\t\tconst bySuffixCodeId = resolveColumnIdByCaseInsensitive(columnsByIdUpper, match?.[1]);\n\t\t\tif (bySuffixCodeId && columnsById[bySuffixCodeId]?.role === \"dimension\") {\n\t\t\t\tcodeColumnId = bySuffixCodeId;\n\t\t\t}\n\t\t}\n\n\t\tcolumn.linkedColumnId = codeColumnId;\n\n\t\tif (codeColumnId) {\n\t\t\tconst codeColumn = columnsById[codeColumnId];\n\t\t\tif (codeColumn && codeColumn.role === \"dimension\") {\n\t\t\t\tcodeColumn.semanticType = \"code\";\n\t\t\t\tif (!codeColumn.linkedColumnId) {\n\t\t\t\t\tcodeColumn.linkedColumnId = column.id;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn columns;\n}\n\n/**\n * Преобразует EDM-тип во внутренний тип системы.\n */\nfunction mapEdmToServiceType(edm: string): ODataMetaType {\n\tswitch (edm) {\n\t\tcase \"Edm.String\":\n\t\t\treturn \"string\";\n\t\tcase \"Edm.Guid\":\n\t\t\treturn \"guid\";\n\t\tcase \"Edm.Boolean\":\n\t\t\treturn \"boolean\";\n\t\tcase \"Edm.Int16\":\n\t\tcase \"Edm.Int32\":\n\t\t\treturn \"int\";\n\t\tcase \"Edm.Int64\":\n\t\t\treturn \"long\";\n\t\tcase \"Edm.Single\":\n\t\t\treturn \"float\";\n\t\tcase \"Edm.Decimal\":\n\t\t\treturn \"decimal\";\n\t\tcase \"Edm.Double\":\n\t\t\treturn \"double\";\n\t\tcase \"Edm.DateTime\":\n\t\t\treturn \"datetime\";\n\t\tcase \"Edm.DateTimeOffset\":\n\t\t\treturn \"datetimeOffset\";\n\t\tcase \"Edm.Time\":\n\t\t\treturn \"time\";\n\t\tcase \"Edm.Binary\":\n\t\t\treturn \"binary\";\n\t\tcase \"Edm.Byte\":\n\t\t\treturn \"byte\";\n\t\tdefault:\n\t\t\tthrow new Error(`Неподдерживаемый тип данных ${edm}`);\n\t}\n}\n\n/**\n * Создает свойство параметра из XML-элемента.\n */\nfunction createParameterProperty(element: Element): EntityParameterProperty {\n\tconst name = element.getAttribute(\"Name\")!;\n\tconst edmType = element.getAttribute(\"Type\") || \"\";\n\tconst mapped = mapEdmToServiceType(edmType);\n\n\tconst maxLength = element.hasAttribute(\"MaxLength\") ? Number(element.getAttribute(\"MaxLength\")) : undefined;\n\tconst precision = element.hasAttribute(\"Precision\") ? Number(element.getAttribute(\"Precision\")) : undefined;\n\tconst scale = element.hasAttribute(\"Scale\") ? Number(element.getAttribute(\"Scale\")) : undefined;\n\tconst label = element.getAttribute(\"sap:label\") || undefined;\n\tconst parameter = element.getAttribute(\"sap:parameter\") || undefined;\n\tconst nullable = element.getAttribute(\"Nullable\") !== \"false\" ? true : undefined;\n\n\treturn {\n\t\tid: name,\n\t\tlabel: label ?? name,\n\t\ttype: mapped,\n\t\toriginalType: edmType,\n\t\t...(mapped === \"string\" && maxLength === 1 ? { abapBooleanLike: true } : {}),\n\t\t...(maxLength !== undefined && { maxLength }),\n\t\t...(precision !== undefined && { precision }),\n\t\t...(scale !== undefined && { scale }),\n\t\t...(parameter !== undefined && { parameter }),\n\t\t...(nullable !== undefined && { nullable: true }),\n\t\t...(parameter === \"mandatory\" && { mandatory: true })\n\t};\n}\n\n/**\n * Создает свойство колонки из XML-элемента.\n */\nfunction createColumnProperty(element: Element): EntityColumnProperty {\n\tconst baseProps = createParameterProperty(element);\n\n\tconst linkedColumnId = element.getAttribute(\"sap:text\") || undefined;\n\tconst sortable = element.getAttribute(\"sap:sortable\") !== \"false\";\n\tconst filterable = element.getAttribute(\"sap:filterable\") !== \"false\";\n\tconst role = element.getAttribute(\"sap:aggregation-role\") === \"measure\" ? \"measure\" : \"dimension\";\n\tconst label = element.getAttribute(\"sap:label\") || undefined;\n\n\t// Убираем свойства, специфичные только для параметров.\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tconst { nullable, mandatory, ...columnProps } = baseProps;\n\n\treturn {\n\t\t...columnProps,\n\t\t...(linkedColumnId !== undefined && { linkedColumnId }),\n\t\t...(label !== undefined && { label }),\n\t\tsemanticType: \"none\",\n\t\tsortable,\n\t\tfilterable,\n\t\trole\n\t};\n}\n\n/**\n * Фильтрует свойства, исключая служебные.\n */\nfunction propertyFilter(element: Element): boolean {\n\tconst name = element.getAttribute(\"Name\");\n\tconst typeName = element.getAttribute(\"Type\") || \"\";\n\n\tif (!name) return false;\n\tif (!isScalarEdmPropertyType(typeName)) return false;\n\n\treturn !([/*\"ID\", \"Id\", \"id\",*/ \"CNT\", \"cnt\"].includes(name) || /_F$/i.test(name));\n}\n\n/**\n * Фильтрует свойства для колонок, исключая служебные.\n */\nfunction columnPropertyFilter(element: Element): boolean {\n\tconst name = element.getAttribute(\"Name\");\n\tconst typeName = element.getAttribute(\"Type\") || \"\";\n\n\tif (!name) return false;\n\tif (!isScalarEdmPropertyType(typeName)) return false;\n\n\treturn !([\"CNT\", \"cnt\"].includes(name) || /_F$/i.test(name));\n}\n\nfunction getProperties(element: Element): Element[] {\n\treturn Array.from(element.getElementsByTagName(\"Property\"));\n}\n\nfunction getKeys(element: Element): Element[] {\n\treturn Array.from(element.getElementsByTagName(\"PropertyRef\"));\n}\n\nfunction getNavigationProperties(element: Element): Element[] {\n\treturn Array.from(element.getElementsByTagName(\"NavigationProperty\"));\n}\n\n/**\n * Получает параметры из EntityType.\n */\nfunction getParametersProperties(entity: Element): EntityParameterProperty[] {\n\tconst properties = getProperties(entity).filter(propertyFilter);\n\treturn properties.map(createParameterProperty);\n}\n\n/**\n * Получает параметры из EntityType с учетом ключей.\n */\nfunction getParametersPropertiesWithKey(entity: Element): EntityParameterProperty[] {\n\tconst properties = getProperties(entity).filter(propertyFilter);\n\tconst keys = getKeys(entity);\n\n\treturn properties.map((property) => {\n\t\tconst param = createParameterProperty(property);\n\t\tif (keys.find((key) => key.getAttribute(\"Name\") === param.id)) {\n\t\t\tparam.mandatory = true;\n\t\t}\n\t\treturn param;\n\t});\n}\n\n/**\n * Получает колонки из EntityType.\n */\nfunction getColumnsProperties(entity: Element): EntityColumnProperty[] {\n\tconst properties = getProperties(entity).filter(columnPropertyFilter);\n\tconst columns = properties.map(createColumnProperty);\n\treturn normalizeColumns(columns);\n}\n\nfunction extractQualifiedNameShortName(value?: string | null): string | undefined {\n\tif (!value) return undefined;\n\tconst parts = value.split(\".\");\n\treturn parts[parts.length - 1] || undefined;\n}\n\nfunction createFunctionImportParameterProperty(element: Element): EntityParameterProperty {\n\tconst mode = element.getAttribute(\"Mode\");\n\tif (mode && mode !== \"In\") {\n\t\tconst name = element.getAttribute(\"Name\") || \"(unknown)\";\n\t\tthrow new Error(`FunctionImport parameter '${name}' uses unsupported Mode='${mode}'`);\n\t}\n\n\tconst typeName = element.getAttribute(\"Type\") || \"\";\n\tif (!isScalarEdmPropertyType(typeName)) {\n\t\tconst name = element.getAttribute(\"Name\") || \"(unknown)\";\n\t\tthrow new Error(`FunctionImport parameter '${name}' uses unsupported Type='${typeName}'`);\n\t}\n\n\tconst parameter = createParameterProperty(element);\n\tif (element.getAttribute(\"Nullable\") === \"false\") {\n\t\tparameter.mandatory = true;\n\t}\n\n\treturn parameter;\n}\n\nfunction buildEntityTypeByName(entityNodes: Element[]): Record<string, Element> {\n\treturn entityNodes.reduce<Record<string, Element>>((acc, entity) => {\n\t\tconst entityName = entity.getAttribute(\"Name\");\n\t\tif (entityName) {\n\t\t\tacc[entityName] = entity;\n\t\t}\n\t\treturn acc;\n\t}, {});\n}\n\nfunction buildEntitySetToEntityTypeMap(xml: Document): Record<string, string> {\n\tconst entitySets = Array.from(xml.getElementsByTagName(\"EntitySet\"));\n\n\treturn entitySets.reduce<Record<string, string>>((acc, entitySet) => {\n\t\tconst entitySetName = entitySet.getAttribute(\"Name\");\n\t\tconst entityType = extractQualifiedNameShortName(entitySet.getAttribute(\"EntityType\"));\n\t\tif (!entitySetName || !entityType) return acc;\n\n\t\tacc[entitySetName] = entityType;\n\t\treturn acc;\n\t}, {});\n}\n\nfunction buildAssociationSetByName(xml: Document): Record<string, AssociationSetMetadata> {\n\tconst associationSetNodes = Array.from(xml.getElementsByTagName(\"AssociationSet\"));\n\n\treturn associationSetNodes.reduce<Record<string, AssociationSetMetadata>>((acc, associationSet) => {\n\t\tconst associationName = associationSet.getAttribute(\"Association\");\n\t\tif (!associationName) return acc;\n\n\t\tconst ends = Array.from(associationSet.getElementsByTagName(\"End\"))\n\t\t\t.map((end) => {\n\t\t\t\tconst role = end.getAttribute(\"Role\");\n\t\t\t\tconst entitySet = end.getAttribute(\"EntitySet\");\n\t\t\t\tif (!role || !entitySet) return undefined;\n\t\t\t\treturn { role, entitySet };\n\t\t\t})\n\t\t\t.filter((end): end is AssociationSetEndpoint => Boolean(end));\n\n\t\tconst metadata = { ends };\n\t\tacc[associationName] = metadata;\n\n\t\tconst shortName = extractQualifiedNameShortName(associationName);\n\t\tif (shortName) {\n\t\t\tacc[shortName] = metadata;\n\t\t}\n\n\t\treturn acc;\n\t}, {});\n}\n\nfunction findResultNavigation(\n\tentityType: Element,\n\tassociationSetByName: Record<string, AssociationSetMetadata>\n): ResultNavigationMetadata | undefined {\n\tfor (const navigationProperty of getNavigationProperties(entityType)) {\n\t\tconst navigationName = navigationProperty.getAttribute(\"Name\");\n\t\tif (navigationName !== \"Set\" && navigationName !== \"Results\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst relationship = navigationProperty.getAttribute(\"Relationship\");\n\t\tconst associationSet = relationship ? associationSetByName[relationship] : undefined;\n\t\tconst toRole = navigationProperty.getAttribute(\"ToRole\");\n\t\tconst fromRole = navigationProperty.getAttribute(\"FromRole\");\n\n\t\tlet targetEntitySet = associationSet?.ends.find((end) => end.role === toRole)?.entitySet;\n\t\tif (!targetEntitySet && associationSet) {\n\t\t\ttargetEntitySet = associationSet.ends.find((end) => end.role !== fromRole)?.entitySet;\n\t\t}\n\n\t\treturn {\n\t\t\tname: navigationName,\n\t\t\ttargetEntitySet\n\t\t};\n\t}\n\n\treturn undefined;\n}\n\nfunction buildInternalEntitySetNames(\n\tentitySetToEntityTypeMap: Record<string, string>,\n\tentityTypeByName: Record<string, Element>,\n\tassociationSetByName: Record<string, AssociationSetMetadata>\n): Set<string> {\n\tconst internalEntitySets = new Set<string>();\n\n\tfor (const [entitySetName, entityTypeName] of Object.entries(entitySetToEntityTypeMap)) {\n\t\tconst entityType = entityTypeByName[entityTypeName];\n\t\tif (!entityType) continue;\n\n\t\tconst resultNavigation = findResultNavigation(entityType, associationSetByName);\n\t\tif (!resultNavigation?.targetEntitySet) continue;\n\t\tif (resultNavigation.targetEntitySet === entitySetName) continue;\n\n\t\tinternalEntitySets.add(resultNavigation.targetEntitySet);\n\t}\n\n\treturn internalEntitySets;\n}\n\nfunction resolveColumnsEntityType(\n\tentityType: Element,\n\tresultNavigation: ResultNavigationMetadata | undefined,\n\tentitySetToEntityTypeMap: Record<string, string>,\n\tentityTypeByName: Record<string, Element>\n): Element {\n\tconst resultEntityTypeName = resultNavigation?.targetEntitySet ? entitySetToEntityTypeMap[resultNavigation.targetEntitySet] : undefined;\n\treturn (resultEntityTypeName && entityTypeByName[resultEntityTypeName]) || entityType;\n}\n\nfunction resolveEntityParameters(entityType: Element, entityTypeName: string, resultNavigation: ResultNavigationMetadata | undefined) {\n\tif (resultNavigation) {\n\t\treturn getParametersProperties(entityType);\n\t}\n\n\tif (entityTypeName.endsWith(\"Type\")) {\n\t\treturn undefined;\n\t}\n\n\treturn getParametersPropertiesWithKey(entityType);\n}\n\nfunction getActionForKeyIds(actionFor: string | undefined, entityTypeByName: Record<string, Element>): Set<string> {\n\tif (!actionFor) return new Set<string>();\n\n\tconst entityTypeName = extractQualifiedNameShortName(actionFor);\n\tif (!entityTypeName) return new Set<string>();\n\n\tconst entityType = entityTypeByName[entityTypeName];\n\tif (!entityType) return new Set<string>();\n\n\treturn new Set(\n\t\tgetKeys(entityType)\n\t\t\t.map((key) => key.getAttribute(\"Name\"))\n\t\t\t.filter((value): value is string => Boolean(value))\n\t);\n}\n\nfunction parseFunctionImport(\n\telement: Element,\n\tentitySetToEntityTypeMap: Record<string, string>,\n\tentityTypeByName: Record<string, Element>\n): FunctionImportMetadata {\n\tconst name = element.getAttribute(\"Name\") || \"\";\n\tconst entitySet = element.getAttribute(\"EntitySet\") || undefined;\n\tconst actionFor = element.getAttribute(\"sap:action-for\") || undefined;\n\tconst actionForKeyIds = getActionForKeyIds(actionFor, entityTypeByName);\n\tconst parameters = Array.from(element.getElementsByTagName(\"Parameter\")).map((parameterElement) => {\n\t\tconst parameter = createFunctionImportParameterProperty(parameterElement);\n\t\tif (actionForKeyIds.has(parameter.id)) {\n\t\t\tparameter.mandatory = true;\n\t\t}\n\t\treturn parameter;\n\t});\n\n\treturn {\n\t\tname,\n\t\ttitle: element.getAttribute(\"sap:label\") || \"\",\n\t\thttpMethod: (element.getAttribute(\"m:HttpMethod\") as FunctionImportMetadata[\"httpMethod\"] | null) || undefined,\n\t\tparameters: parameters.length ? parameters : undefined,\n\t\treturnType: element.getAttribute(\"ReturnType\") || \"\",\n\t\t...(entitySet !== undefined && { entitySet }),\n\t\t...(actionFor !== undefined && { actionFor }),\n\t\t...(entitySet && entitySetToEntityTypeMap[entitySet] ? { resultEntity: entitySet } : {})\n\t};\n}\n\n/**\n * Парсит метаданные OData V2 из XML.\n */\nexport function parseServiceMetadata(xmlText: string): ServiceMetadata {\n\tconst parser = new DOMParser();\n\tconst xml = parser.parseFromString(xmlText, \"application/xml\");\n\tconst entityNodes = Array.from(xml.getElementsByTagName(\"EntityType\"));\n\tconst functionImportNodes = Array.from(xml.getElementsByTagName(\"FunctionImport\"));\n\tconst entitySetToEntityTypeMap = buildEntitySetToEntityTypeMap(xml);\n\tconst entityTypeByName = buildEntityTypeByName(entityNodes);\n\tconst associationSetByName = buildAssociationSetByName(xml);\n\tconst internalEntitySets = buildInternalEntitySetNames(entitySetToEntityTypeMap, entityTypeByName, associationSetByName);\n\n\tconst entities: Record<string, EntityMetadata> = {};\n\tconst functionImports: Record<string, FunctionImportMetadata> = {};\n\n\tfor (const [entitySetName, entityTypeName] of Object.entries(entitySetToEntityTypeMap)) {\n\t\tif (internalEntitySets.has(entitySetName)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst entityType = entityTypeByName[entityTypeName];\n\t\tif (!entityType) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst resultNavigation = findResultNavigation(entityType, associationSetByName);\n\t\tconst columnsEntityType = resolveColumnsEntityType(entityType, resultNavigation, entitySetToEntityTypeMap, entityTypeByName);\n\t\tconst title = entityType.getAttribute(\"sap:label\") || columnsEntityType.getAttribute(\"sap:label\") || \"\";\n\t\tconst columns = getColumnsProperties(columnsEntityType);\n\t\tconst parameters = resolveEntityParameters(entityType, entityTypeName, resultNavigation);\n\n\t\tentities[entitySetName] = {\n\t\t\ttitle,\n\t\t\tcolumns,\n\t\t\t...(parameters?.length ? { parameters } : {}),\n\t\t\t...(resultNavigation ? { result: resultNavigation.name } : {})\n\t\t};\n\t}\n\n\tfor (const functionImport of functionImportNodes) {\n\t\tconst parsed = parseFunctionImport(functionImport, entitySetToEntityTypeMap, entityTypeByName);\n\t\tfunctionImports[parsed.name] = parsed;\n\t}\n\n\treturn { entities, functionImports };\n}\n","export interface Sort<T> {\n\tkey: T;\n\t/**\n\t * @default false (asc)\n\t */\n\tdesc?: true;\n}\n\nexport function getSortIndex<T>(sorting: Sort<keyof T>[], key: keyof T): number {\n\treturn sorting.findIndex((s) => s.key === key);\n}\n\nexport function buildODataOrder<T>(sorting: Sort<keyof T>[]): string {\n\treturn sorting.map((s) => `${String(s.key)} ${s.desc ? \"desc\" : \"asc\"}`).join(\",\");\n}\n\nexport function toggleSort<T>(sorting: Sort<keyof T>[], key: keyof T, multi: boolean): Sort<keyof T>[] {\n\tconst idx = getSortIndex(sorting, key);\n\n\t// single-sort: начинаем с чистого массива (кроме клика по уже существующему — тоже можно сбрасывать)\n\tconst base = multi ? [...sorting] : [...sorting.filter((s) => s.key === key)];\n\n\tif (idx === -1) {\n\t\tbase.push({ key });\n\t\treturn base;\n\t}\n\n\tconst current = sorting[idx]!;\n\tif (!current.desc) {\n\t\t// asc -> desc\n\t\treturn base.map((s) => (s.key === key ? { key, desc: true } : s));\n\t}\n\n\t// desc -> remove\n\treturn base.filter((s) => s.key !== key);\n}\n\n/**\n * Возвращает эффективный набор сортировок для аналитической таблицы.\n *\n * Правило:\n * - при наличии пользовательской сортировки используется только она;\n * - если пользовательская сортировка отсутствует, используется сортировка по полям группировки (asc).\n */\nexport function resolveEffectiveSorts<TKey extends PropertyKey>(grouping: TKey[], sorting: Sort<TKey>[]): Sort<TKey>[] {\n\tif (sorting.length > 0) {\n\t\treturn sorting.map((item) => ({ key: item.key, desc: item.desc }));\n\t}\n\n\treturn grouping.map((key) => ({ key }));\n}\n\nexport function buildODataOrderBy<T>(grouping: (keyof T)[], sorting: Sort<keyof T>[]): string | undefined {\n\tconst effectiveSorting = resolveEffectiveSorts(grouping, sorting);\n\tconst parts = effectiveSorting.map((item) => `${String(item.key)} ${item.desc ? \"desc\" : \"asc\"}`);\n\n\treturn parts.length ? parts.join(\",\") : undefined;\n}\n\nexport function getSortIndicator<T>(\n\tgrouping: (keyof T)[],\n\tsorting: Sort<keyof T>[],\n\tcolId: keyof T\n): { active: boolean; desc?: boolean; order?: number; lockedByGrouping?: boolean } {\n\tconst hasUserSorting = sorting.length > 0;\n\tconst gIdx = grouping.indexOf(colId);\n\tif (!hasUserSorting && gIdx !== -1) {\n\t\treturn { active: true, order: gIdx + 1, lockedByGrouping: true };\n\t}\n\n\tconst sIdx = sorting.findIndex((s) => s.key === colId);\n\tif (sIdx === -1) return { active: false };\n\n\treturn { active: true, desc: sorting[sIdx]?.desc, order: sIdx + 1 };\n}\n","export type SqlFilterScalarValue = string | number | boolean;\n\nexport type SqlFilterOperation = \"eq\" | \"in\";\n\nexport type SqlFilterEqualCondition = {\n\t/** Имя SQL-поля после всех доменных маппингов. */\n\tfieldId: string;\n\t/** Оператор строгого равенства. */\n\toperation: \"eq\";\n\t/** Исходное значение фильтра. Неподдерживаемые и пустые значения не сериализуются. */\n\tvalue: unknown;\n};\n\nexport type SqlFilterInCondition = {\n\t/** Имя SQL-поля после всех доменных маппингов. */\n\tfieldId: string;\n\t/** Оператор включения в список значений. */\n\toperation: \"in\";\n\t/** Исходные значения фильтра. Неподдерживаемые и пустые значения не сериализуются. */\n\tvalues: readonly unknown[] | null | undefined;\n};\n\nexport type SqlFilterCondition = SqlFilterEqualCondition | SqlFilterInCondition;\n\nexport type SqlFilterConjunction = \"and\" | \"or\";\n\n/**\n * Явная группа SQL-like выражений с собственным логическим оператором.\n * Группа всегда сериализуется в скобках, чтобы её границы сохранялись при\n * объединении с соседними выражениями верхнего уровня через `AND`.\n */\nexport type SqlFilterGroup = {\n\toperation: \"group\";\n\tconjunction: SqlFilterConjunction;\n\texpressions: readonly SqlFilterExpression[];\n};\n\n/** Узел безопасного SQL-like выражения: простое условие или вложенная группа. */\nexport type SqlFilterExpression = SqlFilterCondition | SqlFilterGroup;\n\nconst SQL_FILTER_FIELD_ID_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nexport function isSqlFilterScalarValue(value: unknown): value is SqlFilterScalarValue {\n\treturn typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\";\n}\n\nexport function assertSqlFilterFieldId(fieldId: string): void {\n\tif (!SQL_FILTER_FIELD_ID_PATTERN.test(fieldId)) {\n\t\tthrow new Error(`Некорректное имя поля SQL-фильтра: ${fieldId}`);\n\t}\n}\n\nexport function createSqlFilterEqual(fieldId: string, value: unknown): SqlFilterEqualCondition {\n\treturn { fieldId, operation: \"eq\", value };\n}\n\nexport function createSqlFilterIn(fieldId: string, values: readonly unknown[] | null | undefined): SqlFilterInCondition {\n\treturn { fieldId, operation: \"in\", values };\n}\n\n/**\n * Создаёт логическую группу SQL-like выражений.\n * Вложенность нужна потребителям, где один пользовательский фильтр объединяет\n * альтернативные физические поля, а сам остаётся частью общего `AND`-выражения.\n */\nexport function createSqlFilterGroup(expressions: readonly SqlFilterExpression[], conjunction: SqlFilterConjunction): SqlFilterGroup {\n\treturn { operation: \"group\", conjunction, expressions };\n}\n\nfunction normalizeSqlFilterValue(value: unknown): string | undefined {\n\tif (value instanceof Date) {\n\t\tthrow new Error(\"Дата должна быть отформатирована вызывающей стороной до формирования SQL-фильтра\");\n\t}\n\n\tif (!isSqlFilterScalarValue(value)) return undefined;\n\n\tif (typeof value === \"number\" && !Number.isFinite(value)) return undefined;\n\n\tconst rawValue = String(value);\n\tif (!rawValue || rawValue.trim() === \"\") return undefined;\n\n\treturn `'${rawValue.replaceAll(\"'\", \"''\")}'`;\n}\n\nfunction buildSqlFilterExpression(expression: SqlFilterExpression): string | undefined {\n\tif (expression.operation === \"group\") {\n\t\tconst nestedExpressions = expression.expressions\n\t\t\t.map((nestedExpression) => buildSqlFilterExpression(nestedExpression))\n\t\t\t.filter((nestedExpression): nestedExpression is string => Boolean(nestedExpression));\n\t\tif (!nestedExpressions.length) return undefined;\n\n\t\tconst separator = expression.conjunction === \"or\" ? \" OR \" : \" AND \";\n\t\treturn `(${nestedExpressions.join(separator)})`;\n\t}\n\n\tif (expression.operation === \"eq\") {\n\t\tconst formattedValue = normalizeSqlFilterValue(expression.value);\n\t\tif (!formattedValue) return undefined;\n\n\t\tassertSqlFilterFieldId(expression.fieldId);\n\t\treturn `${expression.fieldId}=${formattedValue}`;\n\t}\n\n\tconst formattedValues = (expression.values ?? [])\n\t\t.map((value) => normalizeSqlFilterValue(value))\n\t\t.filter((value): value is string => Boolean(value));\n\tif (formattedValues.length === 0) return undefined;\n\n\tassertSqlFilterFieldId(expression.fieldId);\n\treturn `${expression.fieldId} IN (${formattedValues.join(\", \")})`;\n}\n\n/**\n * Формирует SQL-подобный фильтр для legacy payload, который backend вставляет в dynamic WHERE.\n *\n * Это не OData `$filter`: оператор `IN` здесь допустим только потому, что строка уходит в тело запроса,\n * а не в SAP Gateway URL. Для защиты от падения dynamic WHERE builder намеренно разрешает только\n * простые имена полей и строковые литералы с экранированными одинарными кавычками.\n */\nexport function buildSqlFilter(expressions: readonly SqlFilterExpression[] | undefined): string {\n\tif (!expressions) return \"\";\n\n\treturn expressions\n\t\t.map((expression) => buildSqlFilterExpression(expression))\n\t\t.filter((expression): expression is string => Boolean(expression))\n\t\t.join(\" AND \");\n}\n","import { type ODataBooleanType, type ODataDateType, type ODataIntegerType, type ODataMetaType, type ODataNumericType } from \"./types\";\n\nexport function isODataBooleanType(type: ODataMetaType | undefined): type is ODataBooleanType {\n\treturn type === \"boolean\";\n}\n\nexport function isODataNumericType(type: ODataMetaType | undefined): type is ODataNumericType {\n\treturn type === \"byte\" || type === \"int\" || type === \"long\" || type === \"float\" || type === \"decimal\" || type === \"double\";\n}\n\nexport function isODataIntegerType(type: ODataMetaType | undefined): type is ODataIntegerType {\n\treturn type === \"byte\" || type === \"int\" || type === \"long\";\n}\n\nexport function isODataDateType(type: ODataMetaType | undefined): type is ODataDateType {\n\treturn type === \"datetime\" || type === \"datetimeOffset\" || type === \"time\";\n}\n","import type { UseQueryResult } from \"@tanstack/react-query\";\n\n/**\n * Стандартный ответ `odataQueryFn` после трансформации данных.\n */\ninterface ODataQueryResultEnvelope<T> {\n\tdata: T;\n\ttotalCount?: number;\n}\n\n/**\n * Результат query-хука с уже распакованным полем `data`.\n */\nexport type UnwrappedODataQueryResult<T> = Omit<UseQueryResult<ODataQueryResultEnvelope<T>>, \"data\"> & {\n\tdata: T | undefined;\n\ttotalCount?: number;\n};\n\n/**\n * Приводит результат `useQuery` с `odataQueryFn` к привычному виду:\n * данные доступны сразу в `data`, а `totalCount` вынесен отдельно.\n */\nexport function unwrapODataQueryResult<T>(query: UseQueryResult<ODataQueryResultEnvelope<T>>): UnwrappedODataQueryResult<T> {\n\tconst data = query.data?.data;\n\tconst totalCount = query.data?.totalCount;\n\n\treturn { ...query, data, totalCount };\n}\n","import { BaseType, InputType, RangeType } from \"../types\";\nimport { isObject } from \"../validators\";\n\nexport function normalizeRangeValue(value: InputType): RangeType {\n\tif (Array.isArray(value)) {\n\t\treturn [value[0] ?? null, value[1] ?? null];\n\t}\n\n\treturn [isBaseValue(value) ? (value ?? null) : null, null];\n}\n\nexport function normalizeBaseValue(value: InputType): BaseType {\n\tif (value instanceof Date) {\n\t\treturn value;\n\t}\n\n\tif (Array.isArray(value) || isObject(value)) {\n\t\treturn null;\n\t}\n\n\treturn value;\n}\n\nexport function isBaseValue(value: unknown): value is BaseType {\n\treturn value == null || typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\" || value instanceof Date;\n}\n","import { UnwrappedODataParameters, WrapODataParameters, WrappedODataParameters } from \"./types\";\n\n// export function wrapODataParams(data: Record<string, unknown>): Record<string, ODataValue> {\n// \tif (!data) return {};\n// \treturn Object.entries(data).reduce(\n// \t\t(acc, [key, value]) => {\n// \t\t\t// NOTE: пропускаем пустые строки и 0\n// \t\t\tif (value != null) {\n// \t\t\t\tacc[key] = { value };\n// \t\t\t}\n// \t\t\treturn acc;\n// \t\t},\n// \t\t{} as Record<string, ODataValue>\n// \t);\n// }\n\n/**\n * Типизированный хелпер для преобразования плоской структуры в wrapped.\n */\nexport function wrapODataParams<T extends UnwrappedODataParameters>(params: T | undefined | null): WrapODataParameters<T> {\n\tif (!params) return {} as WrapODataParameters<T>;\n\n\tconst result = {} as WrapODataParameters<T>;\n\tfor (const key in params) {\n\t\tresult[key] = { value: params[key] };\n\t}\n\n\treturn result;\n}\n\nexport function unwrapODataParams(params?: WrappedODataParameters): UnwrappedODataParameters | undefined {\n\tif (!params) return undefined;\n\n\tconst normalized: UnwrappedODataParameters = {};\n\tfor (const key of Object.keys(params).sort()) {\n\t\tnormalized[key] = params[key]?.value ?? null;\n\t}\n\n\treturn normalized;\n}\n"],"mappings":"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"}