import{n as e}from"./rolldown-runtime-C0FnF6B9.js";import{n as t}from"./iframe-DaN-XFub.js";import{i as n,r}from"./react-qN2cStNd.js";import{l as i,m as a}from"./blocks-BiaKjftm.js";function o(e){let t={code:`code`,h1:`h1`,h2:`h2`,h3:`h3`,p:`p`,pre:`pre`,...n(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(i,{title:`Foundation Lib/OData, таблицы и формулы`}),`
`,(0,c.jsx)(t.h1,{id:`odata-metadata-таблицы-и-формулы`,children:`OData metadata, таблицы и формулы`}),`
`,(0,c.jsxs)(t.p,{children:[`Здесь находятся чистые OData V2 helpers и runtime contracts для TanStack Table. Они не выполняют запросы. Для SAP Gateway transport, SSO, X-CSRF, metadata fetch и TanStack Query operation используйте `,(0,c.jsx)(t.code,{children:`@ryuzaki13/react-foundation-api/odata`}),`.`]}),`
`,(0,c.jsxs)(t.h2,{id:`odata-service-metadata-и-odata-v2-values`,children:[(0,c.jsx)(t.code,{children:`odata-service`}),`: metadata и OData V2 values`]}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import {
	buildEntityPath,
	buildODataFilter,
	buildODataOrderBy,
	odataFormatValue,
	parseServiceMetadata,
	wrapODataParams
} from "@ryuzaki13/react-foundation-lib/odata-service";
`})}),`
`,(0,c.jsx)(t.h3,{id:`основной-поток`,children:`Основной поток`}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`metadata XML → parseServiceMetadata → typed metadata/config
  → wrapODataParams + builder/filter/sort → foundation-api transport
  → metadata-aware parse/format → entity/feature mapping
`})}),`
`,(0,c.jsx)(t.p,{children:`Не передавайте в helpers невалидный external JSON как будто он уже соответствует domain model. Metadata parser описывает OData contract, а domain validation/mapping остаётся у host entity/feature.`}),`
`,(0,c.jsx)(t.h3,{id:`metadata-paths-и-параметры`,children:`Metadata, paths и параметры`}),`
`,(0,c.jsxs)(t.p,{children:[`| API                                                        | Результат                                                                                                                                             |
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `,(0,c.jsx)(t.code,{children:`parseServiceMetadata(xmlText)`}),`                            | Парсит OData V2 XML в `,(0,c.jsx)(t.code,{children:`ServiceMetadata`}),`: entities, properties, FunctionImports, keys, parameters и типы. Некорректный XML/metadata — ошибка boundary. |
| `,(0,c.jsx)(t.code,{children:`resolveMetadataColumnLabel(column)`}),`                       | Label с fallback на column id.                                                                                                                        |
| `,(0,c.jsx)(t.code,{children:`collectFilterableColumns`}),`, `,(0,c.jsx)(t.code,{children:`collectFilterableColumnsIds`}),`  | Отбирают filterable metadata fields.                                                                                                                  |
| `,(0,c.jsx)(t.code,{children:`wrapODataParams(params)`}),`, `,(0,c.jsx)(t.code,{children:`unwrapODataParams(params)`}),`     | Разделяют значения параметров и их OData type; используйте перед builder, а не сериализуйте вручную.                                                  |
| `,(0,c.jsx)(t.code,{children:`buildParameterEntries`}),`, `,(0,c.jsx)(t.code,{children:`buildEntityParameters`}),`           | Строят key/predicate часть entity из metadata и wrapped params.                                                                                       |
| `,(0,c.jsx)(t.code,{children:`buildEntityPath`}),`, `,(0,c.jsx)(t.code,{children:`buildEntityOperationPath`}),`              | Возвращают metadata-aware путь entity/operation.                                                                                                      |
| `,(0,c.jsx)(t.code,{children:`buildFunctionImportParameters`}),`, `,(0,c.jsx)(t.code,{children:`buildFunctionImportPath`}),` | Строят FunctionImport URL/query через `,(0,c.jsx)(t.code,{children:`URLSearchParams`}),`.                                                                                              |`]}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const metadata = parseServiceMetadata(metadataXml);
const params = wrapODataParams({ id: "42" });
const path = buildEntityPath(entityMetadata, { service: "DEMO_SRV", target: "Items" }, params);
`})}),`
`,(0,c.jsxs)(t.p,{children:[`Типы `,(0,c.jsx)(t.code,{children:`ServiceMetadata`}),`, `,(0,c.jsx)(t.code,{children:`EntityMetadata`}),`, `,(0,c.jsx)(t.code,{children:`FunctionImportMetadata`}),`, `,(0,c.jsx)(t.code,{children:`EntityColumnProperty`}),`, `,(0,c.jsx)(t.code,{children:`ODataMetaType`}),`, `,(0,c.jsx)(t.code,{children:`WrappedODataParameters`}),` и `,(0,c.jsx)(t.code,{children:`ODataServiceConfig`}),` экспортируются из того же subpath. Параметры entity и FunctionImport — разные OData contracts; не смешивайте их.`]}),`
`,(0,c.jsx)(t.h3,{id:`значения-и-formatter-registry`,children:`Значения и formatter registry`}),`
`,(0,c.jsxs)(t.p,{children:[`| API                                                                                                                  | Назначение                                                                                             |
| -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `,(0,c.jsx)(t.code,{children:`odataFormatValue(type, value)`}),`                                                                                      | Сериализует primitive в OData literal с escaping/suffix/date semantics.                                |
| `,(0,c.jsx)(t.code,{children:`odataParseValue(type, value)`}),`                                                                                       | Возвращает primitive/date или исходное `,(0,c.jsx)(t.code,{children:`unknown`}),`, если значение не может быть безопасно преобразовано. |
| `,(0,c.jsx)(t.code,{children:`odataParseValueByMetadata(descriptor, value)`}),`                                                                       | Парсит с учётом metadata descriptor, включая ABAP boolean-like поле.                                   |
| `,(0,c.jsx)(t.code,{children:`defaultODataTypeValue`}),`, `,(0,c.jsx)(t.code,{children:`defaultControlTypeValue`}),`                                                                   | Default value для OData/base control type.                                                             |
| `,(0,c.jsx)(t.code,{children:`getBaseTypeFromODataType`}),`, `,(0,c.jsx)(t.code,{children:`isODataBooleanType`}),`, `,(0,c.jsx)(t.code,{children:`isODataNumericType`}),`, `,(0,c.jsx)(t.code,{children:`isODataIntegerType`}),`, `,(0,c.jsx)(t.code,{children:`isODataDateType`}),`      | Type classification.                                                                                   |
| `,(0,c.jsx)(t.code,{children:`getFormattersFor`}),`, `,(0,c.jsx)(t.code,{children:`getFormattersForBaseType`}),`, `,(0,c.jsx)(t.code,{children:`getFormatter`}),`, `,(0,c.jsx)(t.code,{children:`getFormatterForBaseType`}),`                            | Читают встроенный formatter descriptions по type/id.                                                   |
| `,(0,c.jsx)(t.code,{children:`createFormatter`}),`, `,(0,c.jsx)(t.code,{children:`createBooleanFormatter`}),`, `,(0,c.jsx)(t.code,{children:`createStringFormatter`}),`, `,(0,c.jsx)(t.code,{children:`createNumberFormatter`}),`, `,(0,c.jsx)(t.code,{children:`createDateFormatter`}),` | Создают typed formatter definitions с Zod input schema.                                                |`]}),`
`,(0,c.jsx)(t.h3,{id:`фильтры-sorts-и-sql-like-expressions`,children:`Фильтры, sorts и SQL-like expressions`}),`
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`FilterExpression<T>`}),` — serializable дерево с `,(0,c.jsx)(t.code,{children:`FilterConditionExpression`}),` и `,(0,c.jsx)(t.code,{children:`FilterNestedExpression`}),`. Постройте его через `,(0,c.jsx)(t.code,{children:`createFilter`}),`, `,(0,c.jsx)(t.code,{children:`createFilterEqual`}),`, `,(0,c.jsx)(t.code,{children:`createFilterEqualFalsy`}),`, `,(0,c.jsx)(t.code,{children:`createFilterContains`}),`, `,(0,c.jsx)(t.code,{children:`createFilterBetween`}),`, объедините через `,(0,c.jsx)(t.code,{children:`mergeFilterExpressions`}),`, затем вызовите `,(0,c.jsx)(t.code,{children:`buildODataFilter`}),` или `,(0,c.jsx)(t.code,{children:`buildODataFilterRecursive`}),`.`]}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const expression = createFilterEqual<{ status: string }, string>("status", "active");
const filter = buildODataFilter(expression);
`})}),`
`,(0,c.jsxs)(t.p,{children:[`| API                                                                                   | Контракт                                                                                                                     |
| ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `,(0,c.jsx)(t.code,{children:`FilterOperation`}),`, `,(0,c.jsx)(t.code,{children:`FILTER_OPERATIONS`}),`, `,(0,c.jsx)(t.code,{children:`isFilterOperation`}),`, `,(0,c.jsx)(t.code,{children:`resolveOperationLabel`}),`  | Стабильный список и validation operator-ов.                                                                                  |
| `,(0,c.jsx)(t.code,{children:`Sort<T>`}),`, `,(0,c.jsx)(t.code,{children:`toggleSort`}),`, `,(0,c.jsx)(t.code,{children:`getSortIndex`}),`, `,(0,c.jsx)(t.code,{children:`getSortIndicator`}),`                           | Immutable sort state для UI.                                                                                                 |
| `,(0,c.jsx)(t.code,{children:`buildODataOrder`}),`, `,(0,c.jsx)(t.code,{children:`resolveEffectiveSorts`}),`, `,(0,c.jsx)(t.code,{children:`buildODataOrderBy`}),`                       | Сериализуют sort/grouping для OData.                                                                                         |
| `,(0,c.jsx)(t.code,{children:`createSqlFilterEqual`}),`, `,(0,c.jsx)(t.code,{children:`createSqlFilterIn`}),`, `,(0,c.jsx)(t.code,{children:`createSqlFilterGroup`}),`, `,(0,c.jsx)(t.code,{children:`buildSqlFilter`}),` | Отдельный SQL-filter contract: field id предварительно валидируется. Не подставляйте произвольный пользовательский field id. |`]}),`
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`ODataCompiledFilterDefinition`}),`, `,(0,c.jsx)(t.code,{children:`sanitizeFilterDefinitions`}),`, `,(0,c.jsx)(t.code,{children:`sanitizeFilterValues`}),`, `,(0,c.jsx)(t.code,{children:`mergeFilterValuePatch`}),`, `,(0,c.jsx)(t.code,{children:`compileFiltersToExpression`}),`, `,(0,c.jsx)(t.code,{children:`flattenFilterValuesToODataDependencies`}),` предназначены для serializable UI filter configuration. Санитизация создаёт canonical configuration; не записывайте её поверх активного пользовательского draft без явно названной save/restore boundary.`]}),`
`,(0,c.jsxs)(t.h2,{id:`odata-codetext-collections`,children:[(0,c.jsx)(t.code,{children:`odata`}),`: code/text collections`]}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { buildSeparatedArrays, findCollectionPairs, ODataDateFormat } from "@ryuzaki13/react-foundation-lib/odata";
`})}),`
`,(0,c.jsxs)(t.p,{children:[`| API                                                    | Назначение                                                                |
| ------------------------------------------------------ | ------------------------------------------------------------------------- |
| `,(0,c.jsx)(t.code,{children:`buildSeparatedArrays(collection, ...)`}),`                | Разделяет OData collection на code/text arrays для select-like consumers. |
| `,(0,c.jsx)(t.code,{children:`findCollectionPairs(...)`}),`                             | Находит code/text pair по collection/dependency filters.                  |
| `,(0,c.jsx)(t.code,{children:`ODataDateFormat`}),`                                      | Константы date formats для legacy OData values.                           |
| `,(0,c.jsx)(t.code,{children:`CollectionItem`}),`, `,(0,c.jsx)(t.code,{children:`CollectionPair`}),`, `,(0,c.jsx)(t.code,{children:`DependencyFilter`}),` | Публичные contracts коллекций.                                            |`]}),`
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`useODataCollectionStore`}),` и `,(0,c.jsx)(t.code,{children:`odataCollectionConfig`}),` описаны на странице Runtime/state: это UI defaults, а не OData transport/cache.`]}),`
`,(0,c.jsxs)(t.h2,{id:`table-tanstack-table-contracts`,children:[(0,c.jsx)(t.code,{children:`table`}),`: TanStack Table contracts`]}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { buildTableColumnLayout, createTableColumnsFromODataMetadata, useTableRowSelection } from "@ryuzaki13/react-foundation-lib/table";
`})}),`
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`TableColumnDef<TData>`}),` расширяет TanStack `,(0,c.jsx)(t.code,{children:`ColumnDef`}),`, а `,(0,c.jsx)(t.code,{children:`TableColumnMeta`}),`/`,(0,c.jsx)(t.code,{children:`TableColumnFormattingMeta`}),` описывают common metadata. Не мутируйте исходные `,(0,c.jsx)(t.code,{children:`ColumnDef`}),`: layout/order/sizing helpers возвращают новое состояние.`]}),`
`,(0,c.jsxs)(t.p,{children:[`| Группа    | Public API                                                                                                                                                                |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Layout    | `,(0,c.jsx)(t.code,{children:`resolveTableColumnOrder`}),`, `,(0,c.jsx)(t.code,{children:`buildTableColumnLayout`}),`, `,(0,c.jsx)(t.code,{children:`TableColumnLayoutItem`}),`, `,(0,c.jsx)(t.code,{children:`BuildTableColumnLayoutArgs`}),`.                                                               |
| Order     | `,(0,c.jsx)(t.code,{children:`normalizeTableColumnOrder`}),`, `,(0,c.jsx)(t.code,{children:`reorderTableHeaderColumns`}),`, `,(0,c.jsx)(t.code,{children:`resolveReorderedTableHeaderColumns`}),`, `,(0,c.jsx)(t.code,{children:`TableColumnOrderState`}),`.                                                  |
| Sizing    | `,(0,c.jsx)(t.code,{children:`DEFAULT_TABLE_COLUMN_MIN_WIDTH`}),`, `,(0,c.jsx)(t.code,{children:`normalizeTableColumnWidth`}),`, `,(0,c.jsx)(t.code,{children:`normalizeTableColumnSizing`}),`, `,(0,c.jsx)(t.code,{children:`patchTableColumnWidth`}),`, `,(0,c.jsx)(t.code,{children:`removeTableColumnWidth`}),`, `,(0,c.jsx)(t.code,{children:`TableColumnSizingState`}),`. |
| Selection | `,(0,c.jsx)(t.code,{children:`TableSelectionMode`}),`, `,(0,c.jsx)(t.code,{children:`toggleTableRowSelection`}),`, `,(0,c.jsx)(t.code,{children:`pruneTableRowSelection`}),`, `,(0,c.jsx)(t.code,{children:`useTableRowSelection`}),`.                                                                        |
| Metadata  | `,(0,c.jsx)(t.code,{children:`getTableColumnMeta`}),`, `,(0,c.jsx)(t.code,{children:`getTableColumnFormattingMeta`}),`, `,(0,c.jsx)(t.code,{children:`resolveTableLength`}),`, `,(0,c.jsx)(t.code,{children:`isTableInteractiveElement`}),`.                                                                  |`]}),`
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`useTableRowSelection`}),` синхронизирует selection state с TanStack Table. Передавайте устойчивый `,(0,c.jsx)(t.code,{children:`getRowId`}),` на business identity, не array index: изменяемая сортировка/фильтрация иначе свяжет selection с неверной строкой.`]}),`
`,(0,c.jsx)(t.h3,{id:`metadata-driven-odata-adapter`,children:`Metadata-driven OData adapter`}),`
`,(0,c.jsxs)(t.p,{children:[`| API                                                          | Назначение                                                                                |
| ------------------------------------------------------------ | ----------------------------------------------------------------------------------------- |
| `,(0,c.jsx)(t.code,{children:`createTableColumnsFromODataMetadata(options)`}),`               | Строит `,(0,c.jsx)(t.code,{children:`TableColumnDef`}),` из OData metadata.                                                |
| `,(0,c.jsx)(t.code,{children:`enrichTableColumnsWithODataFormatting(columns, options)`}),`    | Добавляет typed formatting metadata к существующим columns без изменения OData transport. |
| `,(0,c.jsx)(t.code,{children:`createTableColumnVisibilityFromODataMetadata(...)`}),`          | Формирует initial column visibility.                                                      |
| `,(0,c.jsx)(t.code,{children:`resolveTableColumnFormattingContextFromODataColumn(column)`}),` | Создаёт formatter context для одного metadata column.                                     |
| `,(0,c.jsx)(t.code,{children:`resolveStableColumnId(column)`}),`                              | Определяет устойчивый id table column.                                                    |`]}),`
`,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`meta.formatting`}),` — экспериментальный presentation contract, не OData request. Если pipeline требует дополнительные runtime fields, owner Query должен расширить select/dependencies через documented formatter pipeline API до fetch.`]}),`
`,(0,c.jsxs)(t.h2,{id:`tree-table-построение-дерева`,children:[(0,c.jsx)(t.code,{children:`tree-table`}),`: построение дерева`]}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { buildTreeTableRows, transposeFlatRowsToTreeTableRows } from "@ryuzaki13/react-foundation-lib/tree-table";
`})}),`
`,(0,c.jsxs)(t.p,{children:[`| API                                                                                                         | Контракт                                                                  |
| ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| `,(0,c.jsx)(t.code,{children:`buildTreeTableRows(rows, hierarchy)`}),`                                                                       | Строит `,(0,c.jsx)(t.code,{children:`TreeTableBuildResult`}),`: tree rows и diagnostics от flat hierarchy. |
| `,(0,c.jsx)(t.code,{children:`transposeFlatRowsToTreeTableRows(rows, options)`}),`                                                           | Создаёт display tree/синтетические nodes из flat rows.                    |
| `,(0,c.jsx)(t.code,{children:`TreeTableFlatHierarchy`}),`, `,(0,c.jsx)(t.code,{children:`TreeTableRowNode`}),`, `,(0,c.jsx)(t.code,{children:`TreeTableTransposedRow`}),`, `,(0,c.jsx)(t.code,{children:`TreeTableTransposeFlatRowsOptions`}),` | Публичные contracts и metadata fields.                                    |`]}),`
`,(0,c.jsx)(t.p,{children:`Функции не меняют исходные rows. Используйте explicit stable row/parent ids; не рассчитывайте на визуальный label как идентичность.`}),`
`,(0,c.jsxs)(t.h2,{id:`formulas-registry-calculated-columns`,children:[(0,c.jsx)(t.code,{children:`formulas`}),`: registry calculated columns`]}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import {
	compileTableFormula,
	configureTableFormulaRegistry,
	createTableFormulaRegistry,
	executeTableFormula,
	validateTableFormulaDependencies
} from "@ryuzaki13/react-foundation-lib/formulas";
`})}),`
`,(0,c.jsx)(t.h3,{id:`инициализация`,children:`Инициализация`}),`
`,(0,c.jsxs)(t.p,{children:[`Host владеет `,(0,c.jsx)(t.code,{children:`TableFormulaDefinition[]`}),` и один раз, до первого compile/validate/execute, создаёт и устанавливает registry:`]}),`
`,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const registry = createTableFormulaRegistry([
	{
		id: "margin",
		name: "Маржа",
		description: "Выручка минус себестоимость",
		fn: (ctx) => ctx.num(0) - ctx.num(1)
	}
]);
configureTableFormulaRegistry(registry);
`})}),`
`,(0,c.jsxs)(t.p,{children:[`| API                                                  | Результат                                                                                                            |
| ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `,(0,c.jsx)(t.code,{children:`createTableFormulaContext({ keys, rowData })`}),`       | Контекст `,(0,c.jsx)(t.code,{children:`key/value/num(index)`}),` для formula function.                                                                |
| `,(0,c.jsx)(t.code,{children:`createTableFormulaRegistry(definitions)`}),`            | Проверяет non-empty unique ids и создаёт immutable registry.                                                         |
| `,(0,c.jsx)(t.code,{children:`getTableFormulaList`}),`, `,(0,c.jsx)(t.code,{children:`getTableFormulaById`}),`         | Читают активный registry.                                                                                            |
| `,(0,c.jsx)(t.code,{children:`compileTableFormula({ formulaId, keys? })`}),`          | Компилирует executor или controlled compile result.                                                                  |
| `,(0,c.jsx)(t.code,{children:`executeTableFormula({ formulaId, keys?, rowData })`}),` | Одноразово выполняет formula и возвращает `,(0,c.jsx)(t.code,{children:`TableFormulaExecutionResult`}),`, не выбрасывая formula runtime error наружу. |
| `,(0,c.jsx)(t.code,{children:`validateTableFormulaDependencies(args)`}),`             | Проверяет formula id, dependency availability, out-of-range/unused indices.                                          |`]}),`
`,(0,c.jsxs)(t.p,{children:[`Formula function возвращает finite number. Ошибочные состояния (`,(0,c.jsx)(t.code,{children:`formula_not_found`}),`, `,(0,c.jsx)(t.code,{children:`runtime_error`}),`, `,(0,c.jsx)(t.code,{children:`invalid_result`}),`) являются данными результата, а не поводом silently подставить ноль. Обработайте их у formatter/table owner и показывайте безопасный fallback.`]})]})}function s(e={}){let{wrapper:t}={...n(),...e.components};return t?(0,c.jsx)(t,{...e,children:(0,c.jsx)(o,{...e})}):o(e)}var c;function l(){return(l=e((()=>{c=t(),r(),a()})))()}l();export{s as default};