@ryuzaki13/react-foundation-lib 1.2.4 → 1.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{dateUtils-BWIaWh13.js → dateUtils-B5V5aXB-.js} +225 -201
- package/dist/chunks/dateUtils-B5V5aXB-.js.map +1 -0
- package/dist/chunks/{formatters-CEsXVZ7n.js → formatters--mhLir82.js} +4 -4
- package/dist/chunks/{formatters-CEsXVZ7n.js.map → formatters--mhLir82.js.map} +1 -1
- package/dist/chunks/{odata-service-D8oFjUah.js → odata-service-DnPlNGpU.js} +2 -2
- package/dist/chunks/{odata-service-D8oFjUah.js.map → odata-service-DnPlNGpU.js.map} +1 -1
- package/dist/chunks/{validate-DrKdjesg.js → validate-nWY_Mla5.js} +2 -2
- package/dist/chunks/{validate-DrKdjesg.js.map → validate-nWY_Mla5.js.map} +1 -1
- package/dist/error-report/index.js +2 -2
- package/dist/excel/index.js +3 -3
- package/dist/formatters/date/index.d.ts +1 -1
- package/dist/formatters/date/index.d.ts.map +1 -1
- package/dist/formatters/date/parseDate.d.ts +13 -1
- package/dist/formatters/date/parseDate.d.ts.map +1 -1
- package/dist/formatters/index.js +5 -5
- package/dist/odata/index.js +1 -1
- package/dist/odata-service/index.js +1 -1
- package/package.json +1 -1
- package/src/docs/browserAndReact.mdx +150 -0
- package/src/docs/filesAndExcel.mdx +163 -0
- package/src/docs/formatters-runtime.mdx +455 -0
- package/src/docs/formatters.mdx +363 -0
- package/src/docs/odataAndTables.mdx +178 -0
- package/src/docs/pureUtilities.mdx +96 -0
- package/src/docs/runtimeAndState.mdx +155 -0
- package/src/formatters/date/README.md +36 -2
- package/src/foundationLib.mdx +105 -0
- package/dist/chunks/dateUtils-BWIaWh13.js.map +0 -1
- package/src/file/file.mdx +0 -6
- package/src/formatters/date/date.mdx +0 -6
- package/src/formatters/number/number.mdx +0 -6
- package/src/formatters/valueState/valueState.mdx +0 -6
- package/src/formulas/formulas.mdx +0 -6
- package/src/pwa/pwa.mdx +0 -6
- package/src/query-client/queryClient.mdx +0 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Mt as e } from "./odata-service-
|
|
1
|
+
import { Mt as e } from "./odata-service-DnPlNGpU.js";
|
|
2
2
|
var t = {
|
|
3
3
|
decimals: 1,
|
|
4
4
|
decimalSeparator: ",",
|
|
@@ -489,4 +489,4 @@ function E(e) {
|
|
|
489
489
|
//#endregion
|
|
490
490
|
export { f as a, d as c, o as d, s as f, u as h, m as i, n as l, l as m, T as n, g as o, c as p, C as r, h as s, E as t, t as u };
|
|
491
491
|
|
|
492
|
-
//# sourceMappingURL=validate-
|
|
492
|
+
//# sourceMappingURL=validate-nWY_Mla5.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-DrKdjesg.js","names":[],"sources":["../../src/formatters/number/presets.ts","../../src/formatters/rowBased/context.ts","../../src/formatters/rowBased/registry.ts","../../src/formatters/pipeline/validate.ts"],"sourcesContent":["import type { NumberFormatPreset, NumberFormatPresetConfig } from \"./types\";\n\n/** Символ группировки из ru-RU (U+00A0 или U+202F в зависимости от среды) */\nconst ruGroupChar = new Intl.NumberFormat(\"ru-RU\").formatToParts(1000).find((p) => p.type === \"group\")?.value ?? \"\\u00A0\";\n\n/** Значения по умолчанию — совпадают с ru-RU форматированием */\nexport const NUMBER_FORMAT_DEFAULTS: Omit<NumberFormatPreset, \"name\"> = {\n\tdecimals: 1,\n\tdecimalSeparator: \",\",\n\tgrouping: true,\n\tgroupingSeparator: ruGroupChar,\n\tgroupingSize: 3\n};\n\nexport const DEFAULT_NUMBER_PRESET_NAMES = Object.freeze({\n\tinteger: \"integer\",\n\tdecimal: \"decimal\",\n\tdecimal2: \"decimal-2\",\n\tdecimal3: \"decimal-3\",\n\tcurrency: \"currency\",\n\tprice: \"price\",\n\tpercent: \"percent\",\n\ttonnage: \"tonnage\",\n\tcompactCurrency: \"compact-currency\",\n\tcompactCurrencyRound: \"compact-currency-round\",\n\tcompactPercent: \"compact-percent\",\n\tcompactPercentRound: \"compact-percent-round\",\n\tcompactTonnage: \"compact-tonnage\",\n\tcompactTonnageRound: \"compact-tonnage-round\"\n});\n\n/**\n * Типовые предустановки числового форматирования.\n *\n * Compact-пресеты без суффикса сохраняют консервативное усечение, а парные\n * `*-round` дают явный математический режим без runtime-переопределения пресета.\n * Недостающие поля каждой предустановки заполняются из `NUMBER_FORMAT_DEFAULTS`.\n */\nconst BUILTIN: NumberFormatPresetConfig[] = [\n\t{ name: \"integer\", decimals: 0, decimalSeparator: \"\" },\n\t{ name: \"decimal\" },\n\t{ name: \"decimal-2\", decimals: 2 },\n\t{ name: \"decimal-3\", decimals: 3 },\n\t{ name: \"currency\", decimals: 0, decimalSeparator: \"\" },\n\t{ name: \"price\", decimals: 0, decimalSeparator: \"\" },\n\t{ name: \"percent\", decimals: 2 },\n\t{ name: \"tonnage\" },\n\t{ name: \"compact-currency\", decimals: 0, decimalSeparator: \"\", compact: {} },\n\t{ name: \"compact-currency-round\", decimals: 0, decimalSeparator: \"\", compact: { roundingMode: \"round\" } },\n\t{ name: \"compact-percent\", decimals: 2, compact: { maxDecimals: 2 } },\n\t{ name: \"compact-percent-round\", decimals: 2, compact: { maxDecimals: 2, roundingMode: \"round\" } },\n\t{ name: \"compact-tonnage\", compact: { maxDecimals: 1 } },\n\t{ name: \"compact-tonnage-round\", compact: { maxDecimals: 1, roundingMode: \"round\" } }\n];\n\nconst registry = new Map<string, NumberFormatPreset>();\n\nfunction init(): void {\n\tfor (const cfg of BUILTIN) {\n\t\tregistry.set(cfg.name, { ...NUMBER_FORMAT_DEFAULTS, ...cfg });\n\t}\n}\n\ninit();\n\nexport function getNumberPreset(name: string): NumberFormatPreset | undefined {\n\treturn registry.get(name);\n}\n\nexport function getNumberPresetNames(): string[] {\n\treturn Array.from(registry.keys());\n}\n\n/** Зарегистрировать или перезаписать предустановку. Недостающие поля берутся из FORMAT_DEFAULTS. */\nexport function registerNumberPreset(config: NumberFormatPresetConfig): NumberFormatPreset {\n\tconst preset: NumberFormatPreset = { ...NUMBER_FORMAT_DEFAULTS, ...config };\n\tregistry.set(preset.name, preset);\n\treturn preset;\n}\n\n/** Сбросить реестр к начальному состоянию (только типовые предустановки) */\nexport function resetNumberPresets(): void {\n\tregistry.clear();\n\tinit();\n}\n\nexport function resolveNumberPreset(presetOrName: string | NumberFormatPreset): NumberFormatPreset {\n\tif (typeof presetOrName !== \"string\") return presetOrName;\n\n\tconst found = getNumberPreset(presetOrName);\n\tif (!found) throw new Error(`Предустановка \"${presetOrName}\" не найдена`);\n\n\treturn found;\n}\n","import { parseNumber } from \"../number\";\n\nimport type { RowBasedFormatterContext, RowBasedFormatterContextInstrumentation } from \"./types\";\n\nexport function createRowBasedFormatterContext(args: {\n\trowData: Record<string, unknown>;\n\trawValue: unknown;\n\tcolumnId: string;\n\tkeys?: readonly string[];\n\tinstrumentation?: RowBasedFormatterContextInstrumentation;\n}): RowBasedFormatterContext {\n\t// TODO: duplicate createTableFormulaContext src\\shared\\lib\\formulas\\execute.ts\n\tconst keys = [...(args.keys ?? [])];\n\n\tconst readKey = (index: number): string | undefined => {\n\t\tif (!Number.isInteger(index) || index < 0) {\n\t\t\targs.instrumentation?.onOutOfRangeIndex?.(index);\n\t\t\treturn undefined;\n\t\t}\n\n\t\targs.instrumentation?.onReadIndex?.(index);\n\n\t\tif (index >= keys.length) {\n\t\t\targs.instrumentation?.onOutOfRangeIndex?.(index);\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn keys[index];\n\t};\n\n\tconst readValue = (index: number): unknown => {\n\t\tconst key = readKey(index);\n\t\tif (!key) return undefined;\n\t\treturn args.rowData[key];\n\t};\n\n\tconst readNum = (index: number): number => {\n\t\tconst key = readKey(index);\n\t\tif (!key) return 0;\n\t\treturn parseNumber(args.rowData[key]);\n\t};\n\n\treturn {\n\t\trowData: args.rowData,\n\t\trawValue: args.rawValue,\n\t\tcolumnId: args.columnId,\n\t\tkey: readKey,\n\t\tvalue: readValue,\n\t\tnum: readNum\n\t};\n}\n","import type { RowBasedFormatterDefinition } from \"./types\";\n\nexport type RowBasedFormatterRegistry = Readonly<{\n\tlist: readonly RowBasedFormatterDefinition[];\n\tbyId: ReadonlyMap<string, RowBasedFormatterDefinition>;\n}>;\n\n/**\n * Создаёт реестр формул для подмены значения в групповой строке.\n */\nexport function createRowBasedFormatterRegistry(definitions: readonly RowBasedFormatterDefinition[]): RowBasedFormatterRegistry {\n\tconst byId = new Map<string, RowBasedFormatterDefinition>();\n\tconst list: RowBasedFormatterDefinition[] = [];\n\n\tfor (const definition of definitions) {\n\t\tconst normalizedId = definition.id.trim();\n\t\tif (!normalizedId) {\n\t\t\tthrow new Error(\"Formula id для RowBasedFormatter не может быть пустым\");\n\t\t}\n\n\t\tif (byId.has(normalizedId)) {\n\t\t\tthrow new Error(`Найден дублирующийся formulaId в RowBasedFormatter: ${normalizedId}`);\n\t\t}\n\n\t\tconst normalizedDefinition: RowBasedFormatterDefinition = Object.freeze({\n\t\t\t...definition,\n\t\t\tid: normalizedId,\n\t\t\tname: definition.name.trim(),\n\t\t\tdescription: definition.description.trim()\n\t\t});\n\n\t\tbyId.set(normalizedId, normalizedDefinition);\n\t\tlist.push(normalizedDefinition);\n\t}\n\n\treturn Object.freeze({\n\t\tlist: Object.freeze(list),\n\t\tbyId\n\t});\n}\n\nlet rowBasedFormatterRegistry = createRowBasedFormatterRegistry([]);\n\n/**\n * Устанавливает реестр row-based форматтеров host-приложения.\n *\n * Pipeline использует этот реестр при валидации и компиляции formula-режима,\n * поэтому конфигурация должна завершиться до первого построения runtime.\n */\nexport function configureRowBasedFormatterRegistry(registry: RowBasedFormatterRegistry): void {\n\trowBasedFormatterRegistry = registry;\n}\n\n/**\n * Возвращает список доступных формул для групповой подмены.\n */\nexport function getRowBasedFormatterList(): readonly RowBasedFormatterDefinition[] {\n\treturn rowBasedFormatterRegistry.list;\n}\n\n/**\n * Возвращает формулу по id.\n */\nexport function getRowBasedFormatterById(formulaId: string | undefined): RowBasedFormatterDefinition | undefined {\n\tconst normalizedId = formulaId?.trim();\n\tif (!normalizedId) return undefined;\n\treturn rowBasedFormatterRegistry.byId.get(normalizedId);\n}\n","import { getNumberPreset } from \"../number\";\nimport { createRowBasedFormatterContext, getRowBasedFormatterById } from \"../rowBased\";\n\nimport type {\n\tFormattersPipelineConfig,\n\tFormattersPipelineEdge,\n\tFormattersPipelineGraph,\n\tFormattersPipelineNode,\n\tFormattersPipelinePlan,\n\tFormattersPipelineRowBasedOverrideFormulaConfig,\n\tFormattersPipelineStep\n} from \"./types\";\n\nexport type FormattersPipelineValidationCode =\n\t| \"config_not_defined\"\n\t| \"unsupported_version\"\n\t| \"graph_or_plan_required\"\n\t| \"node_id_duplicate\"\n\t| \"edge_id_duplicate\"\n\t| \"edge_node_not_found\"\n\t| \"source_count_invalid\"\n\t| \"sink_count_invalid\"\n\t| \"source_incoming_invalid\"\n\t| \"sink_outgoing_invalid\"\n\t| \"node_degree_invalid\"\n\t| \"path_broken\"\n\t| \"path_cycle_detected\"\n\t| \"path_disconnected_nodes\"\n\t| \"step_id_duplicate\"\n\t| \"step_resolve_value_state_multiple\"\n\t| \"step_typed_value_format_multiple\"\n\t| \"step_row_based_override_multiple\"\n\t| \"step_normalize_leading_zeros_multiple\"\n\t| \"step_typed_before_value_state\"\n\t| \"step_row_based_override_field_key_empty\"\n\t| \"step_row_based_override_formula_id_empty\"\n\t| \"step_row_based_override_formula_not_found\"\n\t| \"step_row_based_override_dependency_index_out_of_range\"\n\t| \"step_row_based_override_unused_dependencies\"\n\t| \"step_row_based_override_formula_does_not_use_dependencies\"\n\t| \"step_row_based_override_formula_runtime_error\"\n\t| \"step_threshold_states_count_invalid\"\n\t| \"step_value_hidden_without_icon\"\n\t| \"step_typed_value_format_preset_empty\"\n\t| \"step_typed_value_format_preset_not_found\";\n\nexport type FormattersPipelineValidationMessage = {\n\tcode: FormattersPipelineValidationCode;\n\tmessage: string;\n};\n\nexport type FormattersPipelineValidationResult = {\n\tok: boolean;\n\terrors: FormattersPipelineValidationMessage[];\n\twarnings: FormattersPipelineValidationMessage[];\n\tplan?: FormattersPipelinePlan;\n};\n\ntype MutableValidationState = {\n\terrors: FormattersPipelineValidationMessage[];\n\twarnings: FormattersPipelineValidationMessage[];\n};\n\nfunction pushError(state: MutableValidationState, code: FormattersPipelineValidationCode, message: string) {\n\tstate.errors.push({ code, message });\n}\n\nfunction pushWarning(state: MutableValidationState, code: FormattersPipelineValidationCode, message: string) {\n\tstate.warnings.push({ code, message });\n}\n\nfunction toSortedArray(items: Set<number>): number[] {\n\treturn [...items].sort((left, right) => left - right);\n}\n\nfunction createSampleRowData(dependencies: readonly string[], multiplier: number): Record<string, unknown> {\n\treturn dependencies.reduce<Record<string, unknown>>((acc, dependencyId, index) => {\n\t\tacc[dependencyId] = (index + 1) * multiplier;\n\t\treturn acc;\n\t}, {});\n}\n\nfunction validateRowBasedOverrideFormulaConfig(config: FormattersPipelineRowBasedOverrideFormulaConfig, state: MutableValidationState) {\n\tif (!config.formulaId.trim()) {\n\t\tpushError(state, \"step_row_based_override_formula_id_empty\", \"Для rowBasedOverride (formula) необходимо заполнить formulaId.\");\n\t\treturn;\n\t}\n\n\tconst formula = getRowBasedFormatterById(config.formulaId);\n\tconst dependencies = [...(config.dependencyIds ?? [])];\n\n\tif (!formula) {\n\t\tpushError(state, \"step_row_based_override_formula_not_found\", \"Формула rowBasedOverride не найдена в реестре.\");\n\t\treturn;\n\t}\n\n\tconst usedIndexes = new Set<number>();\n\tconst outOfRangeIndexes = new Set<number>();\n\tlet runtimeErrorCount = 0;\n\n\tconst runValidationPass = (sampleRowData: Record<string, unknown>) => {\n\t\ttry {\n\t\t\tconst context = createRowBasedFormatterContext({\n\t\t\t\trowData: sampleRowData,\n\t\t\t\trawValue: 100,\n\t\t\t\tcolumnId: \"__validation__\",\n\t\t\t\tkeys: dependencies,\n\t\t\t\tinstrumentation: {\n\t\t\t\t\tonReadIndex: (index) => {\n\t\t\t\t\t\tusedIndexes.add(index);\n\t\t\t\t\t},\n\t\t\t\t\tonOutOfRangeIndex: (index) => {\n\t\t\t\t\t\toutOfRangeIndexes.add(index);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tformula.fn(context);\n\t\t} catch {\n\t\t\truntimeErrorCount += 1;\n\t\t}\n\t};\n\n\t// Несколько прогонов повышают шанс увидеть обращения к индексам в разных ветках формулы.\n\trunValidationPass(createSampleRowData(dependencies, 100));\n\trunValidationPass(createSampleRowData(dependencies, -100));\n\n\tconst sortedUsedIndexes = toSortedArray(usedIndexes);\n\tconst requiredDependencyCount = sortedUsedIndexes.length > 0 ? sortedUsedIndexes[sortedUsedIndexes.length - 1] + 1 : 0;\n\n\tif (outOfRangeIndexes.size > 0) {\n\t\tpushError(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_dependency_index_out_of_range\",\n\t\t\t`Формула rowBasedOverride обращается к несуществующим индексам. Минимально требуется зависимостей: ${requiredDependencyCount}, выбрано: ${dependencies.length}.`\n\t\t);\n\t}\n\n\tif (sortedUsedIndexes.length === 0) {\n\t\tpushWarning(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_formula_does_not_use_dependencies\",\n\t\t\t\"Формула rowBasedOverride не использует dependencyIds.\"\n\t\t);\n\t}\n\n\tconst unusedDependencies = dependencies.filter((_, index) => !usedIndexes.has(index));\n\tif (unusedDependencies.length > 0) {\n\t\tpushWarning(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_unused_dependencies\",\n\t\t\t`Выбраны, но не используются формулой rowBasedOverride: ${unusedDependencies.join(\", \")}.`\n\t\t);\n\t}\n\n\tif (runtimeErrorCount > 0) {\n\t\tpushWarning(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_formula_runtime_error\",\n\t\t\t\"На тестовых данных формула rowBasedOverride завершилась с ошибкой.\"\n\t\t);\n\t}\n}\n\nfunction validateStepDefinitions(steps: readonly FormattersPipelineStep[], state: MutableValidationState) {\n\tconst stepIdSet = new Set<string>();\n\tconst counters = {\n\t\tnormalizeLeadingZeros: 0,\n\t\trowBasedOverride: 0,\n\t\tresolveValueState: 0,\n\t\ttypedValueFormat: 0\n\t};\n\n\tfor (const step of steps) {\n\t\tconst normalizedId = step.id.trim();\n\t\tif (!normalizedId) {\n\t\t\tpushError(state, \"step_id_duplicate\", \"Шаг pipeline не может иметь пустой id.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (stepIdSet.has(normalizedId)) {\n\t\t\tpushError(state, \"step_id_duplicate\", `Найден дублирующийся id шага pipeline: ${normalizedId}.`);\n\t\t}\n\t\tstepIdSet.add(normalizedId);\n\n\t\tswitch (step.type) {\n\t\t\tcase \"normalizeLeadingZeros\":\n\t\t\t\tcounters.normalizeLeadingZeros += 1;\n\t\t\t\tbreak;\n\t\t\tcase \"rowBasedOverride\":\n\t\t\t\tcounters.rowBasedOverride += 1;\n\n\t\t\t\tif (step.config.mode === \"field\" && !step.config.fieldKey.trim()) {\n\t\t\t\t\tpushError(\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\"step_row_based_override_field_key_empty\",\n\t\t\t\t\t\t\"Для rowBasedOverride (field) необходимо заполнить fieldKey.\"\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (step.config.mode === \"formula\") {\n\t\t\t\t\tvalidateRowBasedOverrideFormulaConfig(step.config, state);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"resolveValueState\":\n\t\t\t\tcounters.resolveValueState += 1;\n\n\t\t\t\tif (\n\t\t\t\t\tstep.config.resolver.kind === \"threshold\" &&\n\t\t\t\t\tstep.config.resolver.states.length !== step.config.resolver.thresholds.length + 1\n\t\t\t\t) {\n\t\t\t\t\tpushError(\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\"step_threshold_states_count_invalid\",\n\t\t\t\t\t\t\"Для threshold-резолвера количество states должно быть равно thresholds + 1.\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"typedValueFormat\":\n\t\t\t\tcounters.typedValueFormat += 1;\n\t\t\t\tif (step.config?.numberPresetName !== undefined) {\n\t\t\t\t\tconst normalizedPresetName = step.config.numberPresetName.trim();\n\t\t\t\t\tif (!normalizedPresetName) {\n\t\t\t\t\t\tpushError(state, \"step_typed_value_format_preset_empty\", \"Для typedValueFormat указан пустой numberPresetName.\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!getNumberPreset(normalizedPresetName)) {\n\t\t\t\t\t\tpushError(\n\t\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\t\"step_typed_value_format_preset_not_found\",\n\t\t\t\t\t\t\t`Для typedValueFormat указан неизвестный пресет: ${normalizedPresetName}.`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (counters.normalizeLeadingZeros > 1) {\n\t\tpushError(state, \"step_normalize_leading_zeros_multiple\", \"В pipeline может быть только один шаг normalizeLeadingZeros.\");\n\t}\n\n\tif (counters.rowBasedOverride > 1) {\n\t\tpushError(state, \"step_row_based_override_multiple\", \"В pipeline может быть только один шаг rowBasedOverride.\");\n\t}\n\n\tif (counters.resolveValueState > 1) {\n\t\tpushError(state, \"step_resolve_value_state_multiple\", \"В pipeline может быть только один шаг resolveValueState.\");\n\t}\n\n\tif (counters.typedValueFormat > 1) {\n\t\tpushError(state, \"step_typed_value_format_multiple\", \"В pipeline может быть только один шаг typedValueFormat.\");\n\t}\n\n\tconst resolveIndex = steps.findIndex((step) => step.type === \"resolveValueState\");\n\tconst typedIndex = steps.findIndex((step) => step.type === \"typedValueFormat\");\n\tif (resolveIndex !== -1 && typedIndex !== -1 && typedIndex < resolveIndex) {\n\t\tpushError(state, \"step_typed_before_value_state\", \"Шаг typedValueFormat не может выполняться до шага resolveValueState.\");\n\t}\n\n\tfor (const step of steps) {\n\t\tif (step.type !== \"resolveValueState\") continue;\n\t\tif (!step.config.icon?.enabled && step.config.icon?.showValue === false) {\n\t\t\tpushWarning(\n\t\t\t\tstate,\n\t\t\t\t\"step_value_hidden_without_icon\",\n\t\t\t\t\"Для resolveValueState установлено showValue=false при выключенной иконке: значение не будет отображаться.\"\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Валидация облегчённого плана pipeline.\n */\nexport function validateFormattersPipelinePlan(plan: FormattersPipelinePlan): FormattersPipelineValidationResult {\n\tconst state: MutableValidationState = { errors: [], warnings: [] };\n\n\tvalidateStepDefinitions(plan.steps, state);\n\n\treturn {\n\t\tok: state.errors.length === 0,\n\t\terrors: state.errors,\n\t\twarnings: state.warnings,\n\t\tplan: state.errors.length === 0 ? { steps: [...plan.steps] } : undefined\n\t};\n}\n\nfunction buildLinearPathFromGraph(\n\tnodes: readonly FormattersPipelineNode[],\n\tedges: readonly FormattersPipelineEdge[],\n\tstate: MutableValidationState\n): string[] | undefined {\n\tconst nodeById = new Map(nodes.map((node) => [node.id, node]));\n\tconst outgoing = new Map<string, string[]>();\n\tconst incoming = new Map<string, string[]>();\n\n\tfor (const node of nodes) {\n\t\toutgoing.set(node.id, []);\n\t\tincoming.set(node.id, []);\n\t}\n\n\tfor (const edge of edges) {\n\t\tconst source = edge.source.trim();\n\t\tconst target = edge.target.trim();\n\t\tif (!nodeById.has(source) || !nodeById.has(target)) {\n\t\t\tpushError(state, \"edge_node_not_found\", `Ребро ${edge.id} ссылается на несуществующий узел: ${source} -> ${target}.`);\n\t\t\tcontinue;\n\t\t}\n\n\t\toutgoing.get(source)?.push(target);\n\t\tincoming.get(target)?.push(source);\n\t}\n\n\tconst sources = nodes.filter((node) => node.type === \"source\");\n\tconst sinks = nodes.filter((node) => node.type === \"sink\");\n\n\tif (sources.length !== 1) {\n\t\tpushError(state, \"source_count_invalid\", \"В графе должен быть ровно один узел source.\");\n\t}\n\tif (sinks.length !== 1) {\n\t\tpushError(state, \"sink_count_invalid\", \"В графе должен быть ровно один узел sink.\");\n\t}\n\tif (state.errors.length > 0) return undefined;\n\n\tconst sourceNodeId = sources[0]!.id;\n\tconst sinkNodeId = sinks[0]!.id;\n\n\tfor (const node of nodes) {\n\t\tconst inDegree = incoming.get(node.id)?.length ?? 0;\n\t\tconst outDegree = outgoing.get(node.id)?.length ?? 0;\n\n\t\tif (node.type === \"source\") {\n\t\t\tif (inDegree !== 0) {\n\t\t\t\tpushError(state, \"source_incoming_invalid\", \"Узел source не должен иметь входящих рёбер.\");\n\t\t\t}\n\t\t\tif (outDegree !== 1) {\n\t\t\t\tpushError(state, \"node_degree_invalid\", \"Узел source должен иметь ровно одно исходящее ребро.\");\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (node.type === \"sink\") {\n\t\t\tif (outDegree !== 0) {\n\t\t\t\tpushError(state, \"sink_outgoing_invalid\", \"Узел sink не должен иметь исходящих рёбер.\");\n\t\t\t}\n\t\t\tif (inDegree !== 1) {\n\t\t\t\tpushError(state, \"node_degree_invalid\", \"Узел sink должен иметь ровно одно входящее ребро.\");\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (inDegree !== 1 || outDegree !== 1) {\n\t\t\tpushError(\n\t\t\t\tstate,\n\t\t\t\t\"node_degree_invalid\",\n\t\t\t\t`Узел ${node.id} должен иметь ровно одно входящее и одно исходящее ребро для линейного pipeline.`\n\t\t\t);\n\t\t}\n\t}\n\n\tif (state.errors.length > 0) return undefined;\n\n\tconst visited = new Set<string>();\n\tconst path: string[] = [];\n\tlet cursor = sourceNodeId;\n\n\twhile (true) {\n\t\tif (visited.has(cursor)) {\n\t\t\tpushError(state, \"path_cycle_detected\", \"В графе pipeline обнаружен цикл.\");\n\t\t\treturn undefined;\n\t\t}\n\t\tvisited.add(cursor);\n\t\tpath.push(cursor);\n\n\t\tif (cursor === sinkNodeId) {\n\t\t\tbreak;\n\t\t}\n\n\t\tconst nextCandidates = outgoing.get(cursor) ?? [];\n\t\tif (nextCandidates.length !== 1) {\n\t\t\tpushError(state, \"path_broken\", \"Не удалось построить линейный путь от source к sink.\");\n\t\t\treturn undefined;\n\t\t}\n\n\t\tcursor = nextCandidates[0]!;\n\t}\n\n\tif (visited.size !== nodes.length) {\n\t\tpushError(state, \"path_disconnected_nodes\", \"Граф содержит узлы, которые не входят в линейный путь source -> sink.\");\n\t\treturn undefined;\n\t}\n\n\treturn path;\n}\n\n/**\n * Валидация графа pipeline и построение линейного плана исполнения.\n */\nexport function validateFormattersPipelineGraph(graph: FormattersPipelineGraph): FormattersPipelineValidationResult {\n\tconst state: MutableValidationState = { errors: [], warnings: [] };\n\n\tif (!graph.nodes.length) {\n\t\tpushError(state, \"path_broken\", \"Граф pipeline не содержит узлов.\");\n\t\treturn { ok: false, errors: state.errors, warnings: state.warnings };\n\t}\n\n\tconst nodeById = new Map<string, FormattersPipelineNode>();\n\tfor (const node of graph.nodes) {\n\t\tconst normalizedId = node.id.trim();\n\t\tif (!normalizedId) {\n\t\t\tpushError(state, \"node_id_duplicate\", \"Узел pipeline не может иметь пустой id.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (nodeById.has(normalizedId)) {\n\t\t\tpushError(state, \"node_id_duplicate\", `Найден дублирующийся id узла pipeline: ${normalizedId}.`);\n\t\t\tcontinue;\n\t\t}\n\n\t\tnodeById.set(normalizedId, node);\n\t}\n\n\tconst edgeIdSet = new Set<string>();\n\tfor (const edge of graph.edges) {\n\t\tconst normalizedEdgeId = edge.id.trim();\n\t\tif (!normalizedEdgeId) {\n\t\t\tpushError(state, \"edge_id_duplicate\", \"Ребро pipeline не может иметь пустой id.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (edgeIdSet.has(normalizedEdgeId)) {\n\t\t\tpushError(state, \"edge_id_duplicate\", `Найден дублирующийся id ребра pipeline: ${normalizedEdgeId}.`);\n\t\t\tcontinue;\n\t\t}\n\n\t\tedgeIdSet.add(normalizedEdgeId);\n\t}\n\n\tif (state.errors.length > 0) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tconst path = buildLinearPathFromGraph(graph.nodes, graph.edges, state);\n\tif (!path) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tconst steps: FormattersPipelineStep[] = [];\n\tfor (const nodeId of path) {\n\t\tconst node = nodeById.get(nodeId);\n\t\tif (!node || node.type === \"source\" || node.type === \"sink\") continue;\n\n\t\tswitch (node.type) {\n\t\t\tcase \"normalizeLeadingZeros\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"normalizeLeadingZeros\",\n\t\t\t\t\tconfig: node.config ? { ...node.config } : undefined\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"rowBasedOverride\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"rowBasedOverride\",\n\t\t\t\t\tconfig:\n\t\t\t\t\t\tnode.config.mode === \"formula\"\n\t\t\t\t\t\t\t? { ...node.config, dependencyIds: node.config.dependencyIds ? [...node.config.dependencyIds] : undefined }\n\t\t\t\t\t\t\t: { ...node.config }\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"resolveValueState\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"resolveValueState\",\n\t\t\t\t\tconfig: {\n\t\t\t\t\t\tresolver:\n\t\t\t\t\t\t\tnode.config.resolver.kind === \"fixed\"\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\tkind: \"fixed\",\n\t\t\t\t\t\t\t\t\t\tentries: { ...node.config.resolver.entries },\n\t\t\t\t\t\t\t\t\t\tfallbackState: node.config.resolver.fallbackState\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t\tkind: \"threshold\",\n\t\t\t\t\t\t\t\t\t\tthresholds: node.config.resolver.thresholds.map((item) =>\n\t\t\t\t\t\t\t\t\t\t\ttypeof item === \"number\" ? item : { ...item }\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\tstates: [...node.config.resolver.states],\n\t\t\t\t\t\t\t\t\t\tinvalidState: node.config.resolver.invalidState\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\ticon: node.config.icon ? { ...node.config.icon } : undefined\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"typedValueFormat\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"typedValueFormat\",\n\t\t\t\t\tconfig: node.config ? { ...node.config } : undefined\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tvalidateStepDefinitions(steps, state);\n\n\treturn {\n\t\tok: state.errors.length === 0,\n\t\terrors: state.errors,\n\t\twarnings: state.warnings,\n\t\tplan: state.errors.length === 0 ? { steps } : undefined\n\t};\n}\n\n/**\n * Валидация конфигурации pipeline c выбором рабочего плана исполнения.\n *\n * Приоритет источника плана:\n * 1) `plan` из конфигурации;\n * 2) построение плана из `graph`.\n */\nexport function validateFormattersPipelineConfig(config: FormattersPipelineConfig | undefined): FormattersPipelineValidationResult {\n\tconst state: MutableValidationState = { errors: [], warnings: [] };\n\n\tif (!config) {\n\t\tpushError(state, \"config_not_defined\", \"Конфигурация pipeline не задана.\");\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tif (config.version !== 1) {\n\t\tpushError(state, \"unsupported_version\", `Неподдерживаемая версия pipeline: ${String(config.version)}.`);\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tif (!config.plan && !config.graph) {\n\t\tpushError(state, \"graph_or_plan_required\", \"Для pipeline должен быть задан хотя бы один источник: graph или plan.\");\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tif (config.plan) {\n\t\tconst planResult = validateFormattersPipelinePlan(config.plan);\n\t\tstate.errors.push(...planResult.errors);\n\t\tstate.warnings.push(...planResult.warnings);\n\n\t\tif (planResult.ok && planResult.plan) {\n\t\t\treturn {\n\t\t\t\tok: true,\n\t\t\t\terrors: state.errors,\n\t\t\t\twarnings: state.warnings,\n\t\t\t\tplan: planResult.plan\n\t\t\t};\n\t\t}\n\n\t\tif (config.graph) {\n\t\t\tpushWarning(state, \"path_broken\", \"Линейный plan невалиден. Выполнена попытка построить план из graph.\");\n\t\t\tstate.errors.length = 0;\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terrors: state.errors,\n\t\t\t\twarnings: state.warnings\n\t\t\t};\n\t\t}\n\t}\n\n\tif (config.graph) {\n\t\tconst graphResult = validateFormattersPipelineGraph(config.graph);\n\t\treturn {\n\t\t\tok: graphResult.ok,\n\t\t\terrors: [...state.errors, ...graphResult.errors],\n\t\t\twarnings: [...state.warnings, ...graphResult.warnings],\n\t\t\tplan: graphResult.plan\n\t\t};\n\t}\n\n\treturn {\n\t\tok: false,\n\t\terrors: state.errors,\n\t\twarnings: state.warnings\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"validate-nWY_Mla5.js","names":[],"sources":["../../src/formatters/number/presets.ts","../../src/formatters/rowBased/context.ts","../../src/formatters/rowBased/registry.ts","../../src/formatters/pipeline/validate.ts"],"sourcesContent":["import type { NumberFormatPreset, NumberFormatPresetConfig } from \"./types\";\n\n/** Символ группировки из ru-RU (U+00A0 или U+202F в зависимости от среды) */\nconst ruGroupChar = new Intl.NumberFormat(\"ru-RU\").formatToParts(1000).find((p) => p.type === \"group\")?.value ?? \"\\u00A0\";\n\n/** Значения по умолчанию — совпадают с ru-RU форматированием */\nexport const NUMBER_FORMAT_DEFAULTS: Omit<NumberFormatPreset, \"name\"> = {\n\tdecimals: 1,\n\tdecimalSeparator: \",\",\n\tgrouping: true,\n\tgroupingSeparator: ruGroupChar,\n\tgroupingSize: 3\n};\n\nexport const DEFAULT_NUMBER_PRESET_NAMES = Object.freeze({\n\tinteger: \"integer\",\n\tdecimal: \"decimal\",\n\tdecimal2: \"decimal-2\",\n\tdecimal3: \"decimal-3\",\n\tcurrency: \"currency\",\n\tprice: \"price\",\n\tpercent: \"percent\",\n\ttonnage: \"tonnage\",\n\tcompactCurrency: \"compact-currency\",\n\tcompactCurrencyRound: \"compact-currency-round\",\n\tcompactPercent: \"compact-percent\",\n\tcompactPercentRound: \"compact-percent-round\",\n\tcompactTonnage: \"compact-tonnage\",\n\tcompactTonnageRound: \"compact-tonnage-round\"\n});\n\n/**\n * Типовые предустановки числового форматирования.\n *\n * Compact-пресеты без суффикса сохраняют консервативное усечение, а парные\n * `*-round` дают явный математический режим без runtime-переопределения пресета.\n * Недостающие поля каждой предустановки заполняются из `NUMBER_FORMAT_DEFAULTS`.\n */\nconst BUILTIN: NumberFormatPresetConfig[] = [\n\t{ name: \"integer\", decimals: 0, decimalSeparator: \"\" },\n\t{ name: \"decimal\" },\n\t{ name: \"decimal-2\", decimals: 2 },\n\t{ name: \"decimal-3\", decimals: 3 },\n\t{ name: \"currency\", decimals: 0, decimalSeparator: \"\" },\n\t{ name: \"price\", decimals: 0, decimalSeparator: \"\" },\n\t{ name: \"percent\", decimals: 2 },\n\t{ name: \"tonnage\" },\n\t{ name: \"compact-currency\", decimals: 0, decimalSeparator: \"\", compact: {} },\n\t{ name: \"compact-currency-round\", decimals: 0, decimalSeparator: \"\", compact: { roundingMode: \"round\" } },\n\t{ name: \"compact-percent\", decimals: 2, compact: { maxDecimals: 2 } },\n\t{ name: \"compact-percent-round\", decimals: 2, compact: { maxDecimals: 2, roundingMode: \"round\" } },\n\t{ name: \"compact-tonnage\", compact: { maxDecimals: 1 } },\n\t{ name: \"compact-tonnage-round\", compact: { maxDecimals: 1, roundingMode: \"round\" } }\n];\n\nconst registry = new Map<string, NumberFormatPreset>();\n\nfunction init(): void {\n\tfor (const cfg of BUILTIN) {\n\t\tregistry.set(cfg.name, { ...NUMBER_FORMAT_DEFAULTS, ...cfg });\n\t}\n}\n\ninit();\n\nexport function getNumberPreset(name: string): NumberFormatPreset | undefined {\n\treturn registry.get(name);\n}\n\nexport function getNumberPresetNames(): string[] {\n\treturn Array.from(registry.keys());\n}\n\n/** Зарегистрировать или перезаписать предустановку. Недостающие поля берутся из FORMAT_DEFAULTS. */\nexport function registerNumberPreset(config: NumberFormatPresetConfig): NumberFormatPreset {\n\tconst preset: NumberFormatPreset = { ...NUMBER_FORMAT_DEFAULTS, ...config };\n\tregistry.set(preset.name, preset);\n\treturn preset;\n}\n\n/** Сбросить реестр к начальному состоянию (только типовые предустановки) */\nexport function resetNumberPresets(): void {\n\tregistry.clear();\n\tinit();\n}\n\nexport function resolveNumberPreset(presetOrName: string | NumberFormatPreset): NumberFormatPreset {\n\tif (typeof presetOrName !== \"string\") return presetOrName;\n\n\tconst found = getNumberPreset(presetOrName);\n\tif (!found) throw new Error(`Предустановка \"${presetOrName}\" не найдена`);\n\n\treturn found;\n}\n","import { parseNumber } from \"../number\";\n\nimport type { RowBasedFormatterContext, RowBasedFormatterContextInstrumentation } from \"./types\";\n\nexport function createRowBasedFormatterContext(args: {\n\trowData: Record<string, unknown>;\n\trawValue: unknown;\n\tcolumnId: string;\n\tkeys?: readonly string[];\n\tinstrumentation?: RowBasedFormatterContextInstrumentation;\n}): RowBasedFormatterContext {\n\t// TODO: duplicate createTableFormulaContext src\\shared\\lib\\formulas\\execute.ts\n\tconst keys = [...(args.keys ?? [])];\n\n\tconst readKey = (index: number): string | undefined => {\n\t\tif (!Number.isInteger(index) || index < 0) {\n\t\t\targs.instrumentation?.onOutOfRangeIndex?.(index);\n\t\t\treturn undefined;\n\t\t}\n\n\t\targs.instrumentation?.onReadIndex?.(index);\n\n\t\tif (index >= keys.length) {\n\t\t\targs.instrumentation?.onOutOfRangeIndex?.(index);\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn keys[index];\n\t};\n\n\tconst readValue = (index: number): unknown => {\n\t\tconst key = readKey(index);\n\t\tif (!key) return undefined;\n\t\treturn args.rowData[key];\n\t};\n\n\tconst readNum = (index: number): number => {\n\t\tconst key = readKey(index);\n\t\tif (!key) return 0;\n\t\treturn parseNumber(args.rowData[key]);\n\t};\n\n\treturn {\n\t\trowData: args.rowData,\n\t\trawValue: args.rawValue,\n\t\tcolumnId: args.columnId,\n\t\tkey: readKey,\n\t\tvalue: readValue,\n\t\tnum: readNum\n\t};\n}\n","import type { RowBasedFormatterDefinition } from \"./types\";\n\nexport type RowBasedFormatterRegistry = Readonly<{\n\tlist: readonly RowBasedFormatterDefinition[];\n\tbyId: ReadonlyMap<string, RowBasedFormatterDefinition>;\n}>;\n\n/**\n * Создаёт реестр формул для подмены значения в групповой строке.\n */\nexport function createRowBasedFormatterRegistry(definitions: readonly RowBasedFormatterDefinition[]): RowBasedFormatterRegistry {\n\tconst byId = new Map<string, RowBasedFormatterDefinition>();\n\tconst list: RowBasedFormatterDefinition[] = [];\n\n\tfor (const definition of definitions) {\n\t\tconst normalizedId = definition.id.trim();\n\t\tif (!normalizedId) {\n\t\t\tthrow new Error(\"Formula id для RowBasedFormatter не может быть пустым\");\n\t\t}\n\n\t\tif (byId.has(normalizedId)) {\n\t\t\tthrow new Error(`Найден дублирующийся formulaId в RowBasedFormatter: ${normalizedId}`);\n\t\t}\n\n\t\tconst normalizedDefinition: RowBasedFormatterDefinition = Object.freeze({\n\t\t\t...definition,\n\t\t\tid: normalizedId,\n\t\t\tname: definition.name.trim(),\n\t\t\tdescription: definition.description.trim()\n\t\t});\n\n\t\tbyId.set(normalizedId, normalizedDefinition);\n\t\tlist.push(normalizedDefinition);\n\t}\n\n\treturn Object.freeze({\n\t\tlist: Object.freeze(list),\n\t\tbyId\n\t});\n}\n\nlet rowBasedFormatterRegistry = createRowBasedFormatterRegistry([]);\n\n/**\n * Устанавливает реестр row-based форматтеров host-приложения.\n *\n * Pipeline использует этот реестр при валидации и компиляции formula-режима,\n * поэтому конфигурация должна завершиться до первого построения runtime.\n */\nexport function configureRowBasedFormatterRegistry(registry: RowBasedFormatterRegistry): void {\n\trowBasedFormatterRegistry = registry;\n}\n\n/**\n * Возвращает список доступных формул для групповой подмены.\n */\nexport function getRowBasedFormatterList(): readonly RowBasedFormatterDefinition[] {\n\treturn rowBasedFormatterRegistry.list;\n}\n\n/**\n * Возвращает формулу по id.\n */\nexport function getRowBasedFormatterById(formulaId: string | undefined): RowBasedFormatterDefinition | undefined {\n\tconst normalizedId = formulaId?.trim();\n\tif (!normalizedId) return undefined;\n\treturn rowBasedFormatterRegistry.byId.get(normalizedId);\n}\n","import { getNumberPreset } from \"../number\";\nimport { createRowBasedFormatterContext, getRowBasedFormatterById } from \"../rowBased\";\n\nimport type {\n\tFormattersPipelineConfig,\n\tFormattersPipelineEdge,\n\tFormattersPipelineGraph,\n\tFormattersPipelineNode,\n\tFormattersPipelinePlan,\n\tFormattersPipelineRowBasedOverrideFormulaConfig,\n\tFormattersPipelineStep\n} from \"./types\";\n\nexport type FormattersPipelineValidationCode =\n\t| \"config_not_defined\"\n\t| \"unsupported_version\"\n\t| \"graph_or_plan_required\"\n\t| \"node_id_duplicate\"\n\t| \"edge_id_duplicate\"\n\t| \"edge_node_not_found\"\n\t| \"source_count_invalid\"\n\t| \"sink_count_invalid\"\n\t| \"source_incoming_invalid\"\n\t| \"sink_outgoing_invalid\"\n\t| \"node_degree_invalid\"\n\t| \"path_broken\"\n\t| \"path_cycle_detected\"\n\t| \"path_disconnected_nodes\"\n\t| \"step_id_duplicate\"\n\t| \"step_resolve_value_state_multiple\"\n\t| \"step_typed_value_format_multiple\"\n\t| \"step_row_based_override_multiple\"\n\t| \"step_normalize_leading_zeros_multiple\"\n\t| \"step_typed_before_value_state\"\n\t| \"step_row_based_override_field_key_empty\"\n\t| \"step_row_based_override_formula_id_empty\"\n\t| \"step_row_based_override_formula_not_found\"\n\t| \"step_row_based_override_dependency_index_out_of_range\"\n\t| \"step_row_based_override_unused_dependencies\"\n\t| \"step_row_based_override_formula_does_not_use_dependencies\"\n\t| \"step_row_based_override_formula_runtime_error\"\n\t| \"step_threshold_states_count_invalid\"\n\t| \"step_value_hidden_without_icon\"\n\t| \"step_typed_value_format_preset_empty\"\n\t| \"step_typed_value_format_preset_not_found\";\n\nexport type FormattersPipelineValidationMessage = {\n\tcode: FormattersPipelineValidationCode;\n\tmessage: string;\n};\n\nexport type FormattersPipelineValidationResult = {\n\tok: boolean;\n\terrors: FormattersPipelineValidationMessage[];\n\twarnings: FormattersPipelineValidationMessage[];\n\tplan?: FormattersPipelinePlan;\n};\n\ntype MutableValidationState = {\n\terrors: FormattersPipelineValidationMessage[];\n\twarnings: FormattersPipelineValidationMessage[];\n};\n\nfunction pushError(state: MutableValidationState, code: FormattersPipelineValidationCode, message: string) {\n\tstate.errors.push({ code, message });\n}\n\nfunction pushWarning(state: MutableValidationState, code: FormattersPipelineValidationCode, message: string) {\n\tstate.warnings.push({ code, message });\n}\n\nfunction toSortedArray(items: Set<number>): number[] {\n\treturn [...items].sort((left, right) => left - right);\n}\n\nfunction createSampleRowData(dependencies: readonly string[], multiplier: number): Record<string, unknown> {\n\treturn dependencies.reduce<Record<string, unknown>>((acc, dependencyId, index) => {\n\t\tacc[dependencyId] = (index + 1) * multiplier;\n\t\treturn acc;\n\t}, {});\n}\n\nfunction validateRowBasedOverrideFormulaConfig(config: FormattersPipelineRowBasedOverrideFormulaConfig, state: MutableValidationState) {\n\tif (!config.formulaId.trim()) {\n\t\tpushError(state, \"step_row_based_override_formula_id_empty\", \"Для rowBasedOverride (formula) необходимо заполнить formulaId.\");\n\t\treturn;\n\t}\n\n\tconst formula = getRowBasedFormatterById(config.formulaId);\n\tconst dependencies = [...(config.dependencyIds ?? [])];\n\n\tif (!formula) {\n\t\tpushError(state, \"step_row_based_override_formula_not_found\", \"Формула rowBasedOverride не найдена в реестре.\");\n\t\treturn;\n\t}\n\n\tconst usedIndexes = new Set<number>();\n\tconst outOfRangeIndexes = new Set<number>();\n\tlet runtimeErrorCount = 0;\n\n\tconst runValidationPass = (sampleRowData: Record<string, unknown>) => {\n\t\ttry {\n\t\t\tconst context = createRowBasedFormatterContext({\n\t\t\t\trowData: sampleRowData,\n\t\t\t\trawValue: 100,\n\t\t\t\tcolumnId: \"__validation__\",\n\t\t\t\tkeys: dependencies,\n\t\t\t\tinstrumentation: {\n\t\t\t\t\tonReadIndex: (index) => {\n\t\t\t\t\t\tusedIndexes.add(index);\n\t\t\t\t\t},\n\t\t\t\t\tonOutOfRangeIndex: (index) => {\n\t\t\t\t\t\toutOfRangeIndexes.add(index);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tformula.fn(context);\n\t\t} catch {\n\t\t\truntimeErrorCount += 1;\n\t\t}\n\t};\n\n\t// Несколько прогонов повышают шанс увидеть обращения к индексам в разных ветках формулы.\n\trunValidationPass(createSampleRowData(dependencies, 100));\n\trunValidationPass(createSampleRowData(dependencies, -100));\n\n\tconst sortedUsedIndexes = toSortedArray(usedIndexes);\n\tconst requiredDependencyCount = sortedUsedIndexes.length > 0 ? sortedUsedIndexes[sortedUsedIndexes.length - 1] + 1 : 0;\n\n\tif (outOfRangeIndexes.size > 0) {\n\t\tpushError(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_dependency_index_out_of_range\",\n\t\t\t`Формула rowBasedOverride обращается к несуществующим индексам. Минимально требуется зависимостей: ${requiredDependencyCount}, выбрано: ${dependencies.length}.`\n\t\t);\n\t}\n\n\tif (sortedUsedIndexes.length === 0) {\n\t\tpushWarning(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_formula_does_not_use_dependencies\",\n\t\t\t\"Формула rowBasedOverride не использует dependencyIds.\"\n\t\t);\n\t}\n\n\tconst unusedDependencies = dependencies.filter((_, index) => !usedIndexes.has(index));\n\tif (unusedDependencies.length > 0) {\n\t\tpushWarning(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_unused_dependencies\",\n\t\t\t`Выбраны, но не используются формулой rowBasedOverride: ${unusedDependencies.join(\", \")}.`\n\t\t);\n\t}\n\n\tif (runtimeErrorCount > 0) {\n\t\tpushWarning(\n\t\t\tstate,\n\t\t\t\"step_row_based_override_formula_runtime_error\",\n\t\t\t\"На тестовых данных формула rowBasedOverride завершилась с ошибкой.\"\n\t\t);\n\t}\n}\n\nfunction validateStepDefinitions(steps: readonly FormattersPipelineStep[], state: MutableValidationState) {\n\tconst stepIdSet = new Set<string>();\n\tconst counters = {\n\t\tnormalizeLeadingZeros: 0,\n\t\trowBasedOverride: 0,\n\t\tresolveValueState: 0,\n\t\ttypedValueFormat: 0\n\t};\n\n\tfor (const step of steps) {\n\t\tconst normalizedId = step.id.trim();\n\t\tif (!normalizedId) {\n\t\t\tpushError(state, \"step_id_duplicate\", \"Шаг pipeline не может иметь пустой id.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (stepIdSet.has(normalizedId)) {\n\t\t\tpushError(state, \"step_id_duplicate\", `Найден дублирующийся id шага pipeline: ${normalizedId}.`);\n\t\t}\n\t\tstepIdSet.add(normalizedId);\n\n\t\tswitch (step.type) {\n\t\t\tcase \"normalizeLeadingZeros\":\n\t\t\t\tcounters.normalizeLeadingZeros += 1;\n\t\t\t\tbreak;\n\t\t\tcase \"rowBasedOverride\":\n\t\t\t\tcounters.rowBasedOverride += 1;\n\n\t\t\t\tif (step.config.mode === \"field\" && !step.config.fieldKey.trim()) {\n\t\t\t\t\tpushError(\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\"step_row_based_override_field_key_empty\",\n\t\t\t\t\t\t\"Для rowBasedOverride (field) необходимо заполнить fieldKey.\"\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (step.config.mode === \"formula\") {\n\t\t\t\t\tvalidateRowBasedOverrideFormulaConfig(step.config, state);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"resolveValueState\":\n\t\t\t\tcounters.resolveValueState += 1;\n\n\t\t\t\tif (\n\t\t\t\t\tstep.config.resolver.kind === \"threshold\" &&\n\t\t\t\t\tstep.config.resolver.states.length !== step.config.resolver.thresholds.length + 1\n\t\t\t\t) {\n\t\t\t\t\tpushError(\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\"step_threshold_states_count_invalid\",\n\t\t\t\t\t\t\"Для threshold-резолвера количество states должно быть равно thresholds + 1.\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"typedValueFormat\":\n\t\t\t\tcounters.typedValueFormat += 1;\n\t\t\t\tif (step.config?.numberPresetName !== undefined) {\n\t\t\t\t\tconst normalizedPresetName = step.config.numberPresetName.trim();\n\t\t\t\t\tif (!normalizedPresetName) {\n\t\t\t\t\t\tpushError(state, \"step_typed_value_format_preset_empty\", \"Для typedValueFormat указан пустой numberPresetName.\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!getNumberPreset(normalizedPresetName)) {\n\t\t\t\t\t\tpushError(\n\t\t\t\t\t\t\tstate,\n\t\t\t\t\t\t\t\"step_typed_value_format_preset_not_found\",\n\t\t\t\t\t\t\t`Для typedValueFormat указан неизвестный пресет: ${normalizedPresetName}.`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (counters.normalizeLeadingZeros > 1) {\n\t\tpushError(state, \"step_normalize_leading_zeros_multiple\", \"В pipeline может быть только один шаг normalizeLeadingZeros.\");\n\t}\n\n\tif (counters.rowBasedOverride > 1) {\n\t\tpushError(state, \"step_row_based_override_multiple\", \"В pipeline может быть только один шаг rowBasedOverride.\");\n\t}\n\n\tif (counters.resolveValueState > 1) {\n\t\tpushError(state, \"step_resolve_value_state_multiple\", \"В pipeline может быть только один шаг resolveValueState.\");\n\t}\n\n\tif (counters.typedValueFormat > 1) {\n\t\tpushError(state, \"step_typed_value_format_multiple\", \"В pipeline может быть только один шаг typedValueFormat.\");\n\t}\n\n\tconst resolveIndex = steps.findIndex((step) => step.type === \"resolveValueState\");\n\tconst typedIndex = steps.findIndex((step) => step.type === \"typedValueFormat\");\n\tif (resolveIndex !== -1 && typedIndex !== -1 && typedIndex < resolveIndex) {\n\t\tpushError(state, \"step_typed_before_value_state\", \"Шаг typedValueFormat не может выполняться до шага resolveValueState.\");\n\t}\n\n\tfor (const step of steps) {\n\t\tif (step.type !== \"resolveValueState\") continue;\n\t\tif (!step.config.icon?.enabled && step.config.icon?.showValue === false) {\n\t\t\tpushWarning(\n\t\t\t\tstate,\n\t\t\t\t\"step_value_hidden_without_icon\",\n\t\t\t\t\"Для resolveValueState установлено showValue=false при выключенной иконке: значение не будет отображаться.\"\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Валидация облегчённого плана pipeline.\n */\nexport function validateFormattersPipelinePlan(plan: FormattersPipelinePlan): FormattersPipelineValidationResult {\n\tconst state: MutableValidationState = { errors: [], warnings: [] };\n\n\tvalidateStepDefinitions(plan.steps, state);\n\n\treturn {\n\t\tok: state.errors.length === 0,\n\t\terrors: state.errors,\n\t\twarnings: state.warnings,\n\t\tplan: state.errors.length === 0 ? { steps: [...plan.steps] } : undefined\n\t};\n}\n\nfunction buildLinearPathFromGraph(\n\tnodes: readonly FormattersPipelineNode[],\n\tedges: readonly FormattersPipelineEdge[],\n\tstate: MutableValidationState\n): string[] | undefined {\n\tconst nodeById = new Map(nodes.map((node) => [node.id, node]));\n\tconst outgoing = new Map<string, string[]>();\n\tconst incoming = new Map<string, string[]>();\n\n\tfor (const node of nodes) {\n\t\toutgoing.set(node.id, []);\n\t\tincoming.set(node.id, []);\n\t}\n\n\tfor (const edge of edges) {\n\t\tconst source = edge.source.trim();\n\t\tconst target = edge.target.trim();\n\t\tif (!nodeById.has(source) || !nodeById.has(target)) {\n\t\t\tpushError(state, \"edge_node_not_found\", `Ребро ${edge.id} ссылается на несуществующий узел: ${source} -> ${target}.`);\n\t\t\tcontinue;\n\t\t}\n\n\t\toutgoing.get(source)?.push(target);\n\t\tincoming.get(target)?.push(source);\n\t}\n\n\tconst sources = nodes.filter((node) => node.type === \"source\");\n\tconst sinks = nodes.filter((node) => node.type === \"sink\");\n\n\tif (sources.length !== 1) {\n\t\tpushError(state, \"source_count_invalid\", \"В графе должен быть ровно один узел source.\");\n\t}\n\tif (sinks.length !== 1) {\n\t\tpushError(state, \"sink_count_invalid\", \"В графе должен быть ровно один узел sink.\");\n\t}\n\tif (state.errors.length > 0) return undefined;\n\n\tconst sourceNodeId = sources[0]!.id;\n\tconst sinkNodeId = sinks[0]!.id;\n\n\tfor (const node of nodes) {\n\t\tconst inDegree = incoming.get(node.id)?.length ?? 0;\n\t\tconst outDegree = outgoing.get(node.id)?.length ?? 0;\n\n\t\tif (node.type === \"source\") {\n\t\t\tif (inDegree !== 0) {\n\t\t\t\tpushError(state, \"source_incoming_invalid\", \"Узел source не должен иметь входящих рёбер.\");\n\t\t\t}\n\t\t\tif (outDegree !== 1) {\n\t\t\t\tpushError(state, \"node_degree_invalid\", \"Узел source должен иметь ровно одно исходящее ребро.\");\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (node.type === \"sink\") {\n\t\t\tif (outDegree !== 0) {\n\t\t\t\tpushError(state, \"sink_outgoing_invalid\", \"Узел sink не должен иметь исходящих рёбер.\");\n\t\t\t}\n\t\t\tif (inDegree !== 1) {\n\t\t\t\tpushError(state, \"node_degree_invalid\", \"Узел sink должен иметь ровно одно входящее ребро.\");\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (inDegree !== 1 || outDegree !== 1) {\n\t\t\tpushError(\n\t\t\t\tstate,\n\t\t\t\t\"node_degree_invalid\",\n\t\t\t\t`Узел ${node.id} должен иметь ровно одно входящее и одно исходящее ребро для линейного pipeline.`\n\t\t\t);\n\t\t}\n\t}\n\n\tif (state.errors.length > 0) return undefined;\n\n\tconst visited = new Set<string>();\n\tconst path: string[] = [];\n\tlet cursor = sourceNodeId;\n\n\twhile (true) {\n\t\tif (visited.has(cursor)) {\n\t\t\tpushError(state, \"path_cycle_detected\", \"В графе pipeline обнаружен цикл.\");\n\t\t\treturn undefined;\n\t\t}\n\t\tvisited.add(cursor);\n\t\tpath.push(cursor);\n\n\t\tif (cursor === sinkNodeId) {\n\t\t\tbreak;\n\t\t}\n\n\t\tconst nextCandidates = outgoing.get(cursor) ?? [];\n\t\tif (nextCandidates.length !== 1) {\n\t\t\tpushError(state, \"path_broken\", \"Не удалось построить линейный путь от source к sink.\");\n\t\t\treturn undefined;\n\t\t}\n\n\t\tcursor = nextCandidates[0]!;\n\t}\n\n\tif (visited.size !== nodes.length) {\n\t\tpushError(state, \"path_disconnected_nodes\", \"Граф содержит узлы, которые не входят в линейный путь source -> sink.\");\n\t\treturn undefined;\n\t}\n\n\treturn path;\n}\n\n/**\n * Валидация графа pipeline и построение линейного плана исполнения.\n */\nexport function validateFormattersPipelineGraph(graph: FormattersPipelineGraph): FormattersPipelineValidationResult {\n\tconst state: MutableValidationState = { errors: [], warnings: [] };\n\n\tif (!graph.nodes.length) {\n\t\tpushError(state, \"path_broken\", \"Граф pipeline не содержит узлов.\");\n\t\treturn { ok: false, errors: state.errors, warnings: state.warnings };\n\t}\n\n\tconst nodeById = new Map<string, FormattersPipelineNode>();\n\tfor (const node of graph.nodes) {\n\t\tconst normalizedId = node.id.trim();\n\t\tif (!normalizedId) {\n\t\t\tpushError(state, \"node_id_duplicate\", \"Узел pipeline не может иметь пустой id.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (nodeById.has(normalizedId)) {\n\t\t\tpushError(state, \"node_id_duplicate\", `Найден дублирующийся id узла pipeline: ${normalizedId}.`);\n\t\t\tcontinue;\n\t\t}\n\n\t\tnodeById.set(normalizedId, node);\n\t}\n\n\tconst edgeIdSet = new Set<string>();\n\tfor (const edge of graph.edges) {\n\t\tconst normalizedEdgeId = edge.id.trim();\n\t\tif (!normalizedEdgeId) {\n\t\t\tpushError(state, \"edge_id_duplicate\", \"Ребро pipeline не может иметь пустой id.\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (edgeIdSet.has(normalizedEdgeId)) {\n\t\t\tpushError(state, \"edge_id_duplicate\", `Найден дублирующийся id ребра pipeline: ${normalizedEdgeId}.`);\n\t\t\tcontinue;\n\t\t}\n\n\t\tedgeIdSet.add(normalizedEdgeId);\n\t}\n\n\tif (state.errors.length > 0) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tconst path = buildLinearPathFromGraph(graph.nodes, graph.edges, state);\n\tif (!path) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tconst steps: FormattersPipelineStep[] = [];\n\tfor (const nodeId of path) {\n\t\tconst node = nodeById.get(nodeId);\n\t\tif (!node || node.type === \"source\" || node.type === \"sink\") continue;\n\n\t\tswitch (node.type) {\n\t\t\tcase \"normalizeLeadingZeros\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"normalizeLeadingZeros\",\n\t\t\t\t\tconfig: node.config ? { ...node.config } : undefined\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"rowBasedOverride\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"rowBasedOverride\",\n\t\t\t\t\tconfig:\n\t\t\t\t\t\tnode.config.mode === \"formula\"\n\t\t\t\t\t\t\t? { ...node.config, dependencyIds: node.config.dependencyIds ? [...node.config.dependencyIds] : undefined }\n\t\t\t\t\t\t\t: { ...node.config }\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"resolveValueState\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"resolveValueState\",\n\t\t\t\t\tconfig: {\n\t\t\t\t\t\tresolver:\n\t\t\t\t\t\t\tnode.config.resolver.kind === \"fixed\"\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\tkind: \"fixed\",\n\t\t\t\t\t\t\t\t\t\tentries: { ...node.config.resolver.entries },\n\t\t\t\t\t\t\t\t\t\tfallbackState: node.config.resolver.fallbackState\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t\tkind: \"threshold\",\n\t\t\t\t\t\t\t\t\t\tthresholds: node.config.resolver.thresholds.map((item) =>\n\t\t\t\t\t\t\t\t\t\t\ttypeof item === \"number\" ? item : { ...item }\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\tstates: [...node.config.resolver.states],\n\t\t\t\t\t\t\t\t\t\tinvalidState: node.config.resolver.invalidState\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\ticon: node.config.icon ? { ...node.config.icon } : undefined\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"typedValueFormat\":\n\t\t\t\tsteps.push({\n\t\t\t\t\tid: node.id,\n\t\t\t\t\ttype: \"typedValueFormat\",\n\t\t\t\t\tconfig: node.config ? { ...node.config } : undefined\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tvalidateStepDefinitions(steps, state);\n\n\treturn {\n\t\tok: state.errors.length === 0,\n\t\terrors: state.errors,\n\t\twarnings: state.warnings,\n\t\tplan: state.errors.length === 0 ? { steps } : undefined\n\t};\n}\n\n/**\n * Валидация конфигурации pipeline c выбором рабочего плана исполнения.\n *\n * Приоритет источника плана:\n * 1) `plan` из конфигурации;\n * 2) построение плана из `graph`.\n */\nexport function validateFormattersPipelineConfig(config: FormattersPipelineConfig | undefined): FormattersPipelineValidationResult {\n\tconst state: MutableValidationState = { errors: [], warnings: [] };\n\n\tif (!config) {\n\t\tpushError(state, \"config_not_defined\", \"Конфигурация pipeline не задана.\");\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tif (config.version !== 1) {\n\t\tpushError(state, \"unsupported_version\", `Неподдерживаемая версия pipeline: ${String(config.version)}.`);\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tif (!config.plan && !config.graph) {\n\t\tpushError(state, \"graph_or_plan_required\", \"Для pipeline должен быть задан хотя бы один источник: graph или plan.\");\n\t\treturn {\n\t\t\tok: false,\n\t\t\terrors: state.errors,\n\t\t\twarnings: state.warnings\n\t\t};\n\t}\n\n\tif (config.plan) {\n\t\tconst planResult = validateFormattersPipelinePlan(config.plan);\n\t\tstate.errors.push(...planResult.errors);\n\t\tstate.warnings.push(...planResult.warnings);\n\n\t\tif (planResult.ok && planResult.plan) {\n\t\t\treturn {\n\t\t\t\tok: true,\n\t\t\t\terrors: state.errors,\n\t\t\t\twarnings: state.warnings,\n\t\t\t\tplan: planResult.plan\n\t\t\t};\n\t\t}\n\n\t\tif (config.graph) {\n\t\t\tpushWarning(state, \"path_broken\", \"Линейный plan невалиден. Выполнена попытка построить план из graph.\");\n\t\t\tstate.errors.length = 0;\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terrors: state.errors,\n\t\t\t\twarnings: state.warnings\n\t\t\t};\n\t\t}\n\t}\n\n\tif (config.graph) {\n\t\tconst graphResult = validateFormattersPipelineGraph(config.graph);\n\t\treturn {\n\t\t\tok: graphResult.ok,\n\t\t\terrors: [...state.errors, ...graphResult.errors],\n\t\t\twarnings: [...state.warnings, ...graphResult.warnings],\n\t\t\tplan: graphResult.plan\n\t\t};\n\t}\n\n\treturn {\n\t\tok: false,\n\t\terrors: state.errors,\n\t\twarnings: state.warnings\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { _ as e } from "../chunks/array-BBSjoTRy.js";
|
|
2
|
-
import { qt as t } from "../chunks/formatters
|
|
2
|
+
import { qt as t } from "../chunks/formatters--mhLir82.js";
|
|
3
3
|
import { stableStringify as n } from "../utils/index.js";
|
|
4
4
|
import { hashString128 as r, uuidv4 as i } from "../crypto/index.js";
|
|
5
|
-
import { x as a } from "../chunks/dateUtils-
|
|
5
|
+
import { x as a } from "../chunks/dateUtils-B5V5aXB-.js";
|
|
6
6
|
import { createIndexedDbQueryStorage as o } from "../query-client/index.js";
|
|
7
7
|
import { getSessionStorageId as s } from "../session-storage/index.js";
|
|
8
8
|
//#region src/error-report/safeValue.ts
|
package/dist/excel/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { c as e, l as t, s as n, u as r } from "../chunks/odata-service-
|
|
2
|
-
import {
|
|
3
|
-
import { d as s, t as c } from "../chunks/validate-
|
|
1
|
+
import { c as e, l as t, s as n, u as r } from "../chunks/odata-service-DnPlNGpU.js";
|
|
2
|
+
import { L as i, R as a, k as o } from "../chunks/dateUtils-B5V5aXB-.js";
|
|
3
|
+
import { d as s, t as c } from "../chunks/validate-nWY_Mla5.js";
|
|
4
4
|
import l from "write-excel-file/browser";
|
|
5
5
|
//#region src/excel/excel.ts
|
|
6
6
|
var u = {
|
|
@@ -3,7 +3,7 @@ export { getCalendarPeriod, isCalendarPeriodWithinDateBounds, isDateInsideCalend
|
|
|
3
3
|
export * from "./dateRange";
|
|
4
4
|
export * from "./educationDate";
|
|
5
5
|
export { formatDate, formatDateAsAbapDate, formatDateAsAbapDatetime, formatDateAsAbapMonth, formatDateAsAbapYear, formatDateAsDate, formatDateAsDateLong, formatDateAsDateMedium, formatDateAsDateShort, formatDateAsDateTime, formatDateAsDatetimeLong, formatDateAsDatetimeMedium, formatDateAsDatetimeShort, formatDateAsMonthShort, formatDateAsMonthMedium, formatDateAsMonthLong, formatDateAsMonthYearMedium, formatDateAsMonthYearLong, formatDateAsODataDate, formatDateAsODataDatetime, formatDateAsODataTime, formatDateAsTime, formatDateAsTimeLong, formatDateAsTimeMedium, formatDateAsTimeSeconds, formatDateAsTimeShort, formatDateRange } from "./formatDate";
|
|
6
|
-
export { parseDate, parseDateByFormat, parseDateByPattern, parseDateValue } from "./parseDate";
|
|
6
|
+
export { parseDate, parseDateByFormat, parseDateByPattern, parseDateTZ, parseDateValue, parseDateValueTZ } from "./parseDate";
|
|
7
7
|
export type { ParseDateByFormatOptions, ParseDateByPatternOptions } from "./parseDate";
|
|
8
8
|
export { DATE_PATTERN_DATE_TOKENS, DATE_PATTERN_TIME_TOKENS, DATE_PATTERN_TOKEN_RE, DATE_PATTERN_TOKENS } from "./pattern";
|
|
9
9
|
export { DATE_FORMAT_DEFAULTS, DATE_FORMAT_STYLE_PRESET_NAMES, DEFAULT_DATE_PRESET_NAMES, getDatePreset, getDatePresetNames, isDateFormatPrecision, isDateFormatStyle, registerDatePreset, resetDatePresets, resolveDateFormatName, resolveDateFormatPreset } from "./presets";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/formatters/date/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,eAAe,EACf,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACN,iBAAiB,EACjB,gCAAgC,EAChC,0BAA0B,EAC1B,KAAK,cAAc,EACnB,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EAChC,KAAK,kBAAkB,EACvB,MAAM,kBAAkB,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,OAAO,EACN,UAAU,EACV,oBAAoB,EACpB,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,EACxB,0BAA0B,EAC1B,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,2BAA2B,EAC3B,yBAAyB,EACzB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,eAAe,EACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/formatters/date/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,eAAe,EACf,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACN,iBAAiB,EACjB,gCAAgC,EAChC,0BAA0B,EAC1B,KAAK,cAAc,EACnB,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EAChC,KAAK,kBAAkB,EACvB,MAAM,kBAAkB,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,OAAO,EACN,UAAU,EACV,oBAAoB,EACpB,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,EACxB,0BAA0B,EAC1B,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,2BAA2B,EAC3B,yBAAyB,EACzB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,eAAe,EACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,WAAW,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC9H,YAAY,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACvF,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC3H,OAAO,EACN,oBAAoB,EACpB,8BAA8B,EAC9B,yBAAyB,EACzB,aAAa,EACb,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,8BAA8B,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,EACN,+BAA+B,EAC/B,oBAAoB,EACpB,6BAA6B,EAC7B,iCAAiC,EACjC,iBAAiB,EACjB,qBAAqB,EACrB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAClE,YAAY,EACX,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,MAAM,SAAS,CAAC"}
|
|
@@ -34,11 +34,23 @@ export interface ParseDateByFormatOptions {
|
|
|
34
34
|
*/
|
|
35
35
|
export declare function parseDateByFormat(value: unknown, dateFormat?: string, options?: ParseDateByFormatOptions): ParsedDateTimeValue | null;
|
|
36
36
|
/**
|
|
37
|
-
* Универсально парсит вход даты/времени из `unknown
|
|
37
|
+
* Универсально парсит вход даты/времени из `unknown`, сохраняя исторические
|
|
38
|
+
* видимые календарные компоненты без применения timezone.
|
|
38
39
|
*/
|
|
39
40
|
export declare function parseDateValue(value: unknown): ParsedDateValue | null;
|
|
41
|
+
/**
|
|
42
|
+
* Универсально парсит вход даты/времени из `unknown` как абсолютный instant.
|
|
43
|
+
*
|
|
44
|
+
* Явные timezone в ISO/OData и Unix timestamp преобразуются в `Date`
|
|
45
|
+
* с сохранением момента времени; форматы без timezone остаются календарными.
|
|
46
|
+
*/
|
|
47
|
+
export declare function parseDateValueTZ(value: unknown): ParsedDateValue | null;
|
|
40
48
|
/**
|
|
41
49
|
* Универсально парсит вход и всегда возвращает `Date | null`.
|
|
42
50
|
*/
|
|
43
51
|
export declare function parseDate(value: unknown): Date | null;
|
|
52
|
+
/**
|
|
53
|
+
* Универсально парсит вход с учётом timezone и возвращает `Date | null`.
|
|
54
|
+
*/
|
|
55
|
+
export declare function parseDateTZ(value: unknown): Date | null;
|
|
44
56
|
//# sourceMappingURL=parseDate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseDate.d.ts","sourceRoot":"","sources":["../../../src/formatters/date/parseDate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"parseDate.d.ts","sourceRoot":"","sources":["../../../src/formatters/date/parseDate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AA2mB5G;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACzC;;OAEG;IACH,SAAS,CAAC,EAAE,mBAAmB,CAAC;CAChC;AAED,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,OAAO,EACd,OAAO,SAAe,EACtB,OAAO,GAAE,yBAA8B,GACrC,eAAe,GAAG,IAAI,CA8DxB;AAED,MAAM,WAAW,wBAAwB;IACxC;;OAEG;IACH,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC;;OAEG;IACH,aAAa,CAAC,EAAE,IAAI,CAAC;CACrB;AAgBD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,wBAA6B,GAAG,mBAAmB,GAAG,IAAI,CAkCzI;AAsCD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAErE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAEvE;AAkBD;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAErD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAEvD"}
|
package/dist/formatters/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { _ as e, b as t, g as n, v as r, x as i, y as a } from "../chunks/array-BBSjoTRy.js";
|
|
2
|
-
import { $ as o, A as s, At as c, B as l, Bt as u, C as d, Ct as f, D as p, Dt as m, E as h, Et as g, F as _, Ft as v, G as y, Gt as b, H as x, Ht as S, I as C, It as w, J as T, Jt as E, K as D, Kt as O, L as k, Lt as A, M as j, Mt as M, N, Nt as P, O as F, Ot as I, P as L, Pt as R, Q as z, R as B, Rt as V, S as H, St as U, T as W, Tt as G, U as K, Ut as q, V as J, Vt as Y, W as X, Wt as Z, X as Q, Xt as $, Y as ee, Yt as te, Z as ne, _ as re, _t as ie, a as ae, at as oe, b as se, bt as ce, c as le, ct as ue, d as de, dt as fe, et as pe, f as me, ft as he, g as ge, gt as _e, h as ve, ht as ye, i as be, it as xe, j as Se, jt as Ce, k as we, kt as Te, l as Ee, lt as De, m as Oe, mt as ke, n as Ae, nt as je, o as Me, ot as Ne, p as Pe, pt as Fe, q as Ie, qt as Le, r as Re, rt as ze, s as Be, st as Ve, t as He, tt as Ue, u as We, ut as Ge, v as Ke, vt as qe, w as Je, wt as Ye, x as Xe, xt as Ze, y as Qe, yt as $e, z as et, zt as tt } from "../chunks/formatters
|
|
3
|
-
import { Ft as nt, It as rt, Mt as it, Nt as at, Pt as ot, jt as st } from "../chunks/odata-service-
|
|
4
|
-
import { A as ct, B as lt, C as ut, D as dt, E as ft, F as pt, G as mt, H as ht, I as gt,
|
|
5
|
-
import { a as
|
|
6
|
-
export {
|
|
2
|
+
import { $ as o, A as s, At as c, B as l, Bt as u, C as d, Ct as f, D as p, Dt as m, E as h, Et as g, F as _, Ft as v, G as y, Gt as b, H as x, Ht as S, I as C, It as w, J as T, Jt as E, K as D, Kt as O, L as k, Lt as A, M as j, Mt as M, N, Nt as P, O as F, Ot as I, P as L, Pt as R, Q as z, R as B, Rt as V, S as H, St as U, T as W, Tt as G, U as K, Ut as q, V as J, Vt as Y, W as X, Wt as Z, X as Q, Xt as $, Y as ee, Yt as te, Z as ne, _ as re, _t as ie, a as ae, at as oe, b as se, bt as ce, c as le, ct as ue, d as de, dt as fe, et as pe, f as me, ft as he, g as ge, gt as _e, h as ve, ht as ye, i as be, it as xe, j as Se, jt as Ce, k as we, kt as Te, l as Ee, lt as De, m as Oe, mt as ke, n as Ae, nt as je, o as Me, ot as Ne, p as Pe, pt as Fe, q as Ie, qt as Le, r as Re, rt as ze, s as Be, st as Ve, t as He, tt as Ue, u as We, ut as Ge, v as Ke, vt as qe, w as Je, wt as Ye, x as Xe, xt as Ze, y as Qe, yt as $e, z as et, zt as tt } from "../chunks/formatters--mhLir82.js";
|
|
3
|
+
import { Ft as nt, It as rt, Mt as it, Nt as at, Pt as ot, jt as st } from "../chunks/odata-service-DnPlNGpU.js";
|
|
4
|
+
import { A as ct, B as lt, C as ut, D as dt, E as ft, F as pt, G as mt, H as ht, I as gt, J as _t, K as vt, L as yt, M as bt, N as xt, O as St, P as Ct, R as wt, S as Tt, T as Et, U as Dt, V as Ot, W as kt, Y as At, _ as jt, a as Mt, b as Nt, c as Pt, d as Ft, f as It, g as Lt, h as Rt, i as zt, j as Bt, k as Vt, l as Ht, m as Ut, n as Wt, o as Gt, p as Kt, q as qt, r as Jt, s as Yt, u as Xt, v as Zt, w as Qt, x as $t, y as en, z as tn } from "../chunks/dateUtils-B5V5aXB-.js";
|
|
5
|
+
import { a as nn, c as rn, d as an, f as on, i as sn, l as cn, m as ln, n as un, o as dn, p as fn, r as pn, s as mn, t as hn, u as gn } from "../chunks/validate-nWY_Mla5.js";
|
|
6
|
+
export { pt as DATE_FORMAT_DEFAULTS, gt as DATE_FORMAT_STYLE_PRESET_NAMES, vt as DATE_PATTERN_DATE_TOKENS, qt as DATE_PATTERN_TIME_TOKENS, _t as DATE_PATTERN_TOKENS, At as DATE_PATTERN_TOKEN_RE, yt as DEFAULT_DATE_PRESET_NAMES, cn as DEFAULT_NUMBER_PRESET_NAMES, Ae as DEFAULT_VALUE_STATES, gn as NUMBER_FORMAT_DEFAULTS, Re as VALUE_STATE_COLOR_TOKENS, M as addCalendarDays, P as addCalendarMonths, R as addCalendarYears, _ as clearFormatCache, S as clearPhone, Ze as cloneDate, h as cloneFormatterPipelinePlanStep, p as cloneFormatterPipelinePlanStepToNode, F as cloneFormattersPipelineConfig, we as cloneNormalizeLeadingZerosConfig, s as cloneResolveValueStateConfig, Se as cloneRowBasedOverrideConfig, j as cloneTypedValueFormatConfig, Je as collectFormattersPipelineDependencyIds, W as collectRuntimeFieldDependencyIds, de as compileFormattersPipelineExecutor, be as compileFormattersPipelineRuntime, ae as compileFormattersPipelineRuntimeFields, re as computeShortHash, sn as configureRowBasedFormatterRegistry, U as countCalendarDaysInDateRange, v as createCalendarDate, Ve as createEducationDateTime, ve as createFixedResolver, rn as createRowBasedFormatterContext, nn as createRowBasedFormatterRegistry, Pe as createThresholdResolver, Ke as findResolverByCanonicalKey, Wt as formatDate, Jt as formatDateAsAbapDate, zt as formatDateAsAbapDatetime, Mt as formatDateAsAbapMonth, Gt as formatDateAsAbapYear, Yt as formatDateAsDate, Pt as formatDateAsDateLong, Ht as formatDateAsDateMedium, Xt as formatDateAsDateShort, Ft as formatDateAsDateTime, It as formatDateAsDatetimeLong, Kt as formatDateAsDatetimeMedium, Ut as formatDateAsDatetimeShort, Rt as formatDateAsMonthLong, Lt as formatDateAsMonthMedium, jt as formatDateAsMonthShort, Zt as formatDateAsMonthYearLong, en as formatDateAsMonthYearMedium, Nt as formatDateAsODataDate, $t as formatDateAsODataDatetime, Tt as formatDateAsODataTime, ut as formatDateAsTime, Qt as formatDateAsTimeLong, Et as formatDateAsTimeMedium, ft as formatDateAsTimeSeconds, dt as formatDateAsTimeShort, St as formatDateRange, ue as formatEducationDateKey, De as formatEducationTimeKey, Z as formatFullName, C as formatNumber, k as formatNumberAsCurrency, B as formatNumberAsCurrencyOrEmpty, et as formatNumberAsDecimal, l as formatNumberAsDecimal2, J as formatNumberAsDecimal2OrEmpty, x as formatNumberAsDecimal3, K as formatNumberAsDecimal3OrEmpty, X as formatNumberAsDecimalOrEmpty, y as formatNumberAsInteger, D as formatNumberAsIntegerOrEmpty, Ie as formatNumberAsPercent, T as formatNumberAsPercentOrEmpty, ee as formatNumberAsPrice, Q as formatNumberAsPriceOrEmpty, ne as formatNumberAsTonnage, z as formatNumberAsTonnageOrEmpty, q as formatPhone, Me as formatPipelineDisplayValue, b as formatShortName, me as formatTypedCellValue, Te as getCalendarPeriod, Ge as getCurrentEducationWeekKey, wt as getDatePreset, tn as getDatePresetNames, fe as getEducationWeekDays, he as getEducationWeekRange, Fe as getEducationWeekStartDate, ke as getEducationYear, ye as getEducationYearRange, w as getEndOfDay, le as getFormattersPipelineDefinitionById, Ee as getFormattersPipelineDefinitions, an as getNumberPreset, on as getNumberPresetNames, dn as getRowBasedFormatterById, mn as getRowBasedFormatterList, A as getStartOfDay, V as getStartOfMonth, tt as getStartOfWeek, u as getStartOfYear, Qe as getValueStateResolver, se as getValueStateResolverIds, c as isCalendarPeriodWithinDateBounds, _e as isCurrentEducationWeek, lt as isDateFormatPrecision, Ot as isDateFormatStyle, Ce as isDateInsideCalendarPeriod, f as isDateRangeTuple, ie as isEducationDateInCurrentYear, st as isPositiveValue, Y as isSameCalendarDay, Ye as isValidDate, pe as isZeroValue, G as normalizeDateRange, Ue as normalizeDateRangeReferenceDate, qe as normalizeEducationWeekKey, We as normalizeFormattersPipelineConfig, N as normalizeLeadingZeros, L as normalizeLeadingZerosStrict, n as normalizeRequiredText, e as normalizeText, r as normalizeTextSpaces, a as normalizeTextToLower, t as normalizeTextWithFallback, g as orderDates, nt as parseAbapBoolean, rt as parseBoolean, Vt as parseDate, ct as parseDateByFormat, Bt as parseDateByPattern, bt as parseDateTZ, xt as parseDateValue, Ct as parseDateValueTZ, $e as parseEducationDateKey, it as parseNumber, ht as registerDatePreset, ge as registerFixedResolver, fn as registerNumberPreset, Xe as registerResolver, Oe as registerThresholdResolver, Be as rekeyFormattersPipelineConfig, m as requireDateRange, Dt as resetDatePresets, ln as resetNumberPresets, H as resetValueStateResolvers, kt as resolveDateFormatName, mt as resolveDateFormatPreset, I as resolveDateRangePair, ce as resolveEducationWeekKey, je as resolveMonthAgoRange, ze as resolveMonthStartToTodayRange, xe as resolveMonthStartToYesterdayRange, oe as resolveTodayRange, d as resolveValueState, He as resolveValueStateClassName, Ne as resolveYesterdayRange, $ as startsWithIgnoringZeros, te as stripInnerSpaces, E as stripLeadingZeros, O as toAbapBoolean, at as toFiniteNumber, ot as toPositiveInteger, i as toSafeString, o as truncateNumber, Le as truncateText, hn as validateFormattersPipelineConfig, un as validateFormattersPipelineGraph, pn as validateFormattersPipelinePlan };
|
package/dist/odata/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as e } from "../chunks/dateUtils-
|
|
1
|
+
import { t as e } from "../chunks/dateUtils-B5V5aXB-.js";
|
|
2
2
|
import { t } from "../chunks/string-comparison-BKT7PXmq.js";
|
|
3
3
|
import { create as n } from "zustand";
|
|
4
4
|
import { immer as r } from "zustand/middleware/immer";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as e, A as t, At as n, B as r, C as i, Ct as a, D as o, Dt as s, E as c, Et as l, F as u, G as d, H as f, I as p, J as m, K as h, L as g, M as _, N as v, O as y, Ot as b, P as x, Q as S, R as C, S as w, St as T, T as E, Tt as D, U as O, V as k, W as A, X as j, Y as M, Z as N, _ as P, _t as F, a as I, at as L, b as R, bt as z, c as B, ct as V, d as H, dt as U, et as W, f as G, ft as K, g as q, gt as J, h as Y, ht as X, i as Z, it as Q, j as $, k as ee, kt as te, l as ne, lt as re, m as ie, mt as ae, n as oe, nt as se, o as ce, ot as le, p as ue, pt as de, q as fe, r as pe, rt as me, s as he, st as ge, t as _e, tt as ve, u as ye, ut as be, v as xe, vt as Se, w as Ce, wt as we, x as Te, xt as Ee, y as De, yt as Oe, z as ke } from "../chunks/odata-service-
|
|
1
|
+
import { $ as e, A as t, At as n, B as r, C as i, Ct as a, D as o, Dt as s, E as c, Et as l, F as u, G as d, H as f, I as p, J as m, K as h, L as g, M as _, N as v, O as y, Ot as b, P as x, Q as S, R as C, S as w, St as T, T as E, Tt as D, U as O, V as k, W as A, X as j, Y as M, Z as N, _ as P, _t as F, a as I, at as L, b as R, bt as z, c as B, ct as V, d as H, dt as U, et as W, f as G, ft as K, g as q, gt as J, h as Y, ht as X, i as Z, it as Q, j as $, k as ee, kt as te, l as ne, lt as re, m as ie, mt as ae, n as oe, nt as se, o as ce, ot as le, p as ue, pt as de, q as fe, r as pe, rt as me, s as he, st as ge, t as _e, tt as ve, u as ye, ut as be, v as xe, vt as Se, w as Ce, wt as we, x as Te, xt as Ee, y as De, yt as Oe, z as ke } from "../chunks/odata-service-DnPlNGpU.js";
|
|
2
2
|
export { s as BASE_META_TYPES, b as BASE_META_TYPE_LABELS, k as FILTER_OPERATIONS, i as FORCED_CODE_TEXT_IDS, f as FilterOperation, H as assertSqlFilterFieldId, ve as buildEntityOperationPath, se as buildEntityParameters, me as buildEntityPath, Q as buildFunctionImportParameters, L as buildFunctionImportPath, O as buildODataFilter, A as buildODataFilterRecursive, P as buildODataOrder, xe as buildODataOrderBy, le as buildParameterEntries, G as buildSqlFilter, y as collapseChainedODataSegmentFilterValues, e as collectFilterableColumns, W as collectFilterableColumnsIds, ee as compileFiltersToExpression, ge as createBooleanFormatter, V as createDateFormatter, d as createFilter, h as createFilterBetween, fe as createFilterContains, m as createFilterEqual, M as createFilterEqualFalsy, re as createFormatter, be as createNumberFormatter, ue as createSqlFilterEqual, ie as createSqlFilterGroup, Y as createSqlFilterIn, U as createStringFormatter, K as defaultControlTypeValue, de as defaultODataTypeValue, t as flattenFilterValuesToODataDependencies, ae as getBaseTypeFromODataType, X as getFormatter, J as getFormatterForBaseType, F as getFormattersFor, Se as getFormattersForBaseType, De as getSortIndex, R as getSortIndicator, te as isBaseMetaType, pe as isBaseValue, T as isBooleanSafe, a as isDateSafe, $ as isFilterLocalComponentId, j as isFilterOperation, Ce as isForcedCodeTextFamilyId, E as isForcedCodeTextId, we as isNumberSafe, he as isODataBooleanType, B as isODataDateType, ne as isODataIntegerType, ye as isODataNumericType, q as isSqlFilterScalarValue, D as isStringSafe, N as mergeFilterExpressions, _ as mergeFilterValuePatch, Z as normalizeBaseValue, v as normalizeDictionaryCodeKey, I as normalizeRangeValue, Oe as odataFormatValue, z as odataParseValue, Ee as odataParseValueByMetadata, l as odataTypeSchemas, c as parseServiceMetadata, n as resolveBaseTypeLabel, Te as resolveEffectiveSorts, o as resolveMetadataColumnLabel, x as resolveODataFilterDefinitionActiveColumnIds, u as resolveODataFilterDefinitionColumnIds, S as resolveOperationLabel, p as sanitizeFilterBinding, g as sanitizeFilterConditionGroup, C as sanitizeFilterDefinitions, ke as sanitizeFilterValue, r as sanitizeFilterValues, w as toggleSort, _e as unwrapODataParams, ce as unwrapODataQueryResult, oe as wrapODataParams };
|
package/package.json
CHANGED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { Meta } from "@storybook/addon-docs/blocks";
|
|
2
|
+
|
|
3
|
+
<Meta title="Foundation Lib/Browser и React API" />
|
|
4
|
+
|
|
5
|
+
# Browser и React API
|
|
6
|
+
|
|
7
|
+
Эти entrypoint работают только после монтирования в браузере. Вызывайте hooks на верхнем уровне React-компонента или custom hook, а императивные действия (скачивание, clipboard, открытие меню) — из event handler. Они не заменяют UI primitives из `@ryuzaki13/react-foundation-ui`.
|
|
8
|
+
|
|
9
|
+
## Общие hooks
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import {
|
|
13
|
+
useDebounce,
|
|
14
|
+
useDebouncedCallback,
|
|
15
|
+
useDndSortableSensors,
|
|
16
|
+
useFloatingListbox,
|
|
17
|
+
useSearchLink,
|
|
18
|
+
useSearchParams,
|
|
19
|
+
useThrottledCallback
|
|
20
|
+
} from "@ryuzaki13/react-foundation-lib/hooks";
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
| API | Назначение и lifecycle |
|
|
24
|
+
| --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
25
|
+
| `useDebounce(value, delay)` | Возвращает отложенное значение. Не запускает network запрос сам — используйте результат в owner Query/UI flow. |
|
|
26
|
+
| `useDebouncedCallback(callback, delay, { flushOnUnmount? })` | Возвращает debounced callback. Опция `flushOnUnmount` нужна только когда финальный вызов действительно обязателен. |
|
|
27
|
+
| `useThrottledCallback(callback, interval, { flushOnUnmount? })` | Возвращает `{ call, flush, cancel }`; стратегия last-write-wins. Вызывайте `flush` на границе сохранения, `cancel` при смене identity. |
|
|
28
|
+
| `useDndSortableSensors(distanceOrOptions?)` | Готовые Pointer/Keyboard sensors для `@dnd-kit/sortable`; default distance — 6 px. |
|
|
29
|
+
| `useLazyComponent(loader, ...)` | Используйте для lazy UI по устойчивому loader/cache key, а не вызывайте dynamic import во время render. |
|
|
30
|
+
| `useReferenceTrace(name, value)` | Development diagnostic для отслеживания смены ссылок; не часть бизнес-логики. |
|
|
31
|
+
| `useBlockBrowserZoom(enabled)` | Подписывается на browser events для блокировки zoom. Используйте только в явном специализированном UX, не как default. |
|
|
32
|
+
|
|
33
|
+
### Search и floating listbox
|
|
34
|
+
|
|
35
|
+
`useSearchParams<K>(allowedKeys?)` и `useSearchLink<K>()` требуют `@tanstack/react-router`. Первый возвращает `{ params, filteredParams, setParams }` и выполняет navigation с `replace: true`; второй возвращает `buildLink(params)`. Оба работают с URL state, а не с произвольным Zustand/local store.
|
|
36
|
+
|
|
37
|
+
`useFloatingListbox<T>(options)` требует `@floating-ui/react` и объединяет ref, ARIA-interactions, keyboard navigation и placement. Передавайте:
|
|
38
|
+
|
|
39
|
+
- `options`, `selectedIndex`, `getOptionDisabled` — данные и доступность опций;
|
|
40
|
+
- optional controlled `open` + `onOpenChange`;
|
|
41
|
+
- `onSelect`, `closeOnSelect`, `focusFloatingOnOpen`, `restoreFocusOnClose` — interaction policy;
|
|
42
|
+
- `placement` и `placementStrategy: "flip" | "auto"` — placement;
|
|
43
|
+
- `resolveFloatingSize(context)` — только layout/CSS size policy.
|
|
44
|
+
|
|
45
|
+
Hook возвращает Floating UI props/refs и их нужно распространять на reference, floating element и options строго по его контракту. Не заменяйте эти props самодельными keyboard handlers: это нарушит `aria-activedescendant`, focus restore и cleanup `autoUpdate`.
|
|
46
|
+
|
|
47
|
+
## DOM и overlay helpers
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import {
|
|
51
|
+
downloadFileFromBlob,
|
|
52
|
+
getOrCreatePortalRoot,
|
|
53
|
+
useClickOutside,
|
|
54
|
+
useEscapeDismiss,
|
|
55
|
+
useFocusTrap,
|
|
56
|
+
useIntersectionObserver,
|
|
57
|
+
useOverlayFocus
|
|
58
|
+
} from "@ryuzaki13/react-foundation-lib/dom";
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
| API | Контракт |
|
|
62
|
+
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- |
|
|
63
|
+
| `downloadFileFromObjectURL(filename, objectUrl)` | Инициирует download по готовому object URL; не владеет временем `URL.revokeObjectURL`. |
|
|
64
|
+
| `downloadFileFromBlob(filename, blob)` | Создаёт временный object URL и инициирует download. |
|
|
65
|
+
| `downloadFileFromJson(filename, payload)` | Сериализует payload в JSON blob и скачивает. |
|
|
66
|
+
| `getOrCreatePortalRoot(id)` | Возвращает/создаёт DOM root или `null`, если `document` недоступен. |
|
|
67
|
+
| `useClickOutside(refOrRefs, handler)` | Вызывает handler при внешнем pointer interaction; передавайте стабильные refs. |
|
|
68
|
+
| `useEscapeDismiss(options)` | Dismiss только для active/enabled overlay; поддерживает container и целевой document. |
|
|
69
|
+
| `useFocusTrap(isOpen)` | Возвращает ref для trapping focus внутри открытого overlay. |
|
|
70
|
+
| `useOverlayFocus(options)` | Управляет initial focus и restore для overlay; применяйте вместе с accessible dialog/menu. |
|
|
71
|
+
| `useElementHeightObserver(ref)` | Следит за высотой через `ResizeObserver`; результат используйте для layout, не для копирования props в state. |
|
|
72
|
+
| `useIntersectionObserver(ref, options?)` | Возвращает intersection state DOM element. |
|
|
73
|
+
| `useIsTouchDevice()` | Реактивно сообщает touch-capability браузера. |
|
|
74
|
+
|
|
75
|
+
Hooks сами подписываются и очищают observers/listeners при unmount. Не вызывайте `getOrCreatePortalRoot` или browser API в server render; hook-проверки не делают UI SSR-safe автоматически.
|
|
76
|
+
|
|
77
|
+
## Clipboard, media и context menu
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { useCopyText, useCopyElementTextWithFeedback } from "@ryuzaki13/react-foundation-lib/copy";
|
|
81
|
+
import { useMediaQuery, useMatchMedia, resolveResponsiveValue } from "@ryuzaki13/react-foundation-lib/media";
|
|
82
|
+
import { createVirtualAnchor, openMenu } from "@ryuzaki13/react-foundation-lib/context-menu";
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### `copy`
|
|
86
|
+
|
|
87
|
+
| API | Результат |
|
|
88
|
+
| ------------------------------------- | ----------------------------------------------------------------- |
|
|
89
|
+
| `useCopyText()` | Возвращает copy action для строки через Clipboard API с fallback. |
|
|
90
|
+
| `useElementText(ref)` | Читает текст из DOM element. |
|
|
91
|
+
| `useCopyElementText(ref)` | Комбинирует чтение элемента и copy. |
|
|
92
|
+
| `useCopyFeedback()` | Локальное временное состояние feedback после успешного copy. |
|
|
93
|
+
| `useCopyElementTextWithFeedback(ref)` | Удобная композиция copy element + feedback. |
|
|
94
|
+
|
|
95
|
+
Copy может быть отклонён browser permissions; показывайте ожидаемую UI-ошибку, но не считайте clipboard источником истины для сохранения данных.
|
|
96
|
+
|
|
97
|
+
### `media`
|
|
98
|
+
|
|
99
|
+
`BREAKPOINTS_EM` и `Breakpoint` задают стандартные breakpoints; `useMatchMedia()` возвращает `MediaMatches`. Для конкретного media query используйте `useMediaQuery(query, { ssrFallback? })`; `ssrFallback` определяет значение только до browser hydration/в окружении без `matchMedia`.
|
|
100
|
+
|
|
101
|
+
`ResponsiveValue<T>`, `isResponsiveMap`, `resolveResponsiveValue` и `resolveProps` — pure helpers для responsive props. `getCurrentFontSize`, `getCurrentLineHeight`, `getControlHeight`, `pxToEm` читают layout/DOM: не вызывайте их в render, если результат влияет на state без external synchronization.
|
|
102
|
+
|
|
103
|
+
### `context-menu`
|
|
104
|
+
|
|
105
|
+
`MenuAnchor`, `MenuState`, `MenuPoint`, `OpenMenuPayload` — serializable contracts состояния меню. `openMenu(payload)`, `closeMenu(state)` и `toggleMenu(state, payload)` — pure reducers; их можно держать в local/store owner.
|
|
106
|
+
|
|
107
|
+
Для pointer menu используйте `getMenuPointFromEvent(event)` и `createVirtualAnchor(point, contextElement?)`. Для keyboard anchor используйте `getMenuPointFromRect(rect)`. API лишь описывает состояние/anchor; отображение и accessibility menu остаются у UI-компонента.
|
|
108
|
+
|
|
109
|
+
## Virtualizer, PWA и Three.js
|
|
110
|
+
|
|
111
|
+
### Infinite virtualizer
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
import { useFetchNextPageEffect } from "@ryuzaki13/react-foundation-lib/virtualizer";
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Hook принимает `{ virtualItems, currentItemsCount, hasNextPage, fetchNextPage }`; при достижении последней виртуальной строки запускает один следующий fetch и не создаёт параллельные запросы. `fetchNextPage` должен быть стабильным Query action. Не передавайте raw `fetch` и не подменяйте backend state локальным массивом.
|
|
118
|
+
|
|
119
|
+
### Service Worker
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
import { parseSwCachePolicy, buildSwCachePolicyValue, useServiceWorkerUpdate } from "@ryuzaki13/react-foundation-lib/pwa";
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`useServiceWorkerUpdate()` возвращает `{ hasUpdate, applyUpdate, dismiss }`. Его задача — UI-поверхность для уже настроенного приложения с Service Worker; hook не публикует и не настраивает private registration API.
|
|
126
|
+
|
|
127
|
+
`pwa/sw-cache-policy` — отдельный точечный import того же pure policy API:
|
|
128
|
+
|
|
129
|
+
| API | Контракт |
|
|
130
|
+
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
131
|
+
| `parseSwCachePolicy(value)` | Парсит `off`, `ttl=<duration>` или `bust=<duration>` с `max`/`name`; invalid input даёт `undefined`. |
|
|
132
|
+
| `buildSwCachePolicyValue(draft)` | Нормализует `SwCachePolicyDraft` в canonical transport string. |
|
|
133
|
+
| `normalizeSwCacheName(value)` | Делает безопасное lower-case cache name или `undefined`. |
|
|
134
|
+
| `resolveSwCacheCacheNameByPolicy(value)` | Возвращает вычисленное имя cache только для `ttl`/`bust`. |
|
|
135
|
+
|
|
136
|
+
Пример: `ttl=24h;max=200;name=reference`. Это policy для transport/Service Worker, а не замена TanStack Query cache. Не включайте в SW cache auth-sensitive responses без отдельной security policy.
|
|
137
|
+
|
|
138
|
+
### Доступность Three.js
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
import { useThreeSceneAvailability, disableThreeSceneForSession } from "@ryuzaki13/react-foundation-lib/three-scene";
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
| API | Назначение |
|
|
145
|
+
| --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
146
|
+
| `isThreeSceneSupported(options?)` | Проверяет browser WebGL/WebGL2 support. |
|
|
147
|
+
| `isThreeSceneDisabledForSession(key?)`, `disableThreeSceneForSession(key?)` | Читают/устанавливают opt-out текущей tab session. |
|
|
148
|
+
| `useThreeSceneAvailability(options?)` | React state с `pending`/`available`/`unavailable` и причиной (`sessionDisabled`, `reducedMotion`, `webglUnsupported`, `ssr`). |
|
|
149
|
+
|
|
150
|
+
Проверка support не заменяет обработку ошибки renderer. При `unavailable` всегда рендерите семантический non-Three fallback.
|