# `@hestia-earth/ui-components/file-errors`

Framework-agnostic formatting of HESTIA file validation errors. No Angular, no Bulma, no
`window` dependency — import it from any TypeScript package (browser, Node, SSR).

The error catalog is the single source of truth shared with the Angular UI; only the
presentation differs (a pluggable renderer).

## Install

```ts
import { formatErrors } from '@hestia-earth/ui-components/file-errors';
```

## Basic usage — structured plain text

`formatErrors` takes the raw validation errors and returns one structured object per
visible error (errors that resolve to an empty message are dropped).

```ts
import { formatErrors } from '@hestia-earth/ui-components/file-errors';

const errors = [
  {
    dataPath: '.functionalUnit',
    keyword: 'enum',
    message: 'should be equal to one of the allowed values',
    params: { allowedValues: ['1 ha', 'relative'] }
  }
];

formatErrors(errors);
// [
//   {
//     level: 'error',
//     message: 'Only the following values are permitted: `1 ha`, `relative`.',
//     location: '`functionalUnit`',
//     dataPath: '.functionalUnit',
//     keyword: 'enum'
//   }
// ]
```

Each item is an `IFormattedError`:

```ts
interface IFormattedError {
  level: 'error' | 'warning';
  message: string; // plain text; code spans as `backticks`, links as [text](url), lists as bullets
  location?: string; // human-readable path, e.g. "Cycle › Practice"
  dataPath?: string;
  keyword?: string;
}
```

## Rendering as HTML (or anything else)

Pass a renderer. `htmlRenderer` produces the same Bulma-classed markup the platform UI uses;
`textRenderer` (the default) produces plain text / lightweight markdown. You can also supply
your own `IErrorRenderer`.

```ts
import { formatErrors, htmlRenderer } from '@hestia-earth/ui-components/file-errors';

formatErrors(errors, { renderer: htmlRenderer });
// message: '<p class="is-normal">Only the following values are permitted: <code>1 ha</code>, <code>relative</code>.</p>'
```

## Custom link URLs

Links default to `https://www.hestia.earth`. Override the base (or each URL) via `urls`:

```ts
import { formatErrors, urlConfig } from '@hestia-earth/ui-components/file-errors';

formatErrors(errors, { urls: urlConfig('https://www.hestia.earth') });
```

## Lower-level: build a reusable formatter

`formatErrors` builds a formatter on every call. To reuse one (e.g. format errors one at a
time, or reach the individual functions), use `createErrorFormatter`:

```ts
import { createErrorFormatter, textRenderer, defaultUrlConfig } from '@hestia-earth/ui-components/file-errors';

const { formatError, formatErrors, formatCustomErrorMessage, parseDataPath, dataPathLabel } = createErrorFormatter({
  renderer: textRenderer,
  urls: defaultUrlConfig
});

formatError(errors[0]); // single IValidationError -> { level, message, ...error }
formatCustomErrorMessage(errors[0].message, errors[0]); // just the message string
```

## Helpers

Pure, renderer-independent predicates are exported too:

```ts
import {
  errorHasError,
  errorHasWarning,
  isMigrationError,
  isMissingPropertyError,
  isMissingOneOfError,
  filterError,
  missingNodeErrors,
  guidePageId
} from '@hestia-earth/ui-components/file-errors';

const blocking = errors.filter(errorHasError);
const warnings = errors.filter(errorHasWarning);
```
