# forbidden-prettier.mjs

## Огляд

Модуль `forbidden-prettier.mjs` — це FS-перевірка (suspect FS-check) з категорії правил `text`, яка стежить за тим, щоб у корені проєкту не з'являвся жоден файл, який Prettier автоматично підхоплює як конфігурацію чи ignore-список.

Правило `text.mdc` (див. однойменну категорію `.cursor/rules/`) повністю забороняє використання Prettier, пакета `@nitra/prettier-config` і будь-яких прив'язок до Prettier у проєкті — заміна Prettier у репозиторії — це форматер `oxfmt`. Перевірка package.json-сторони (поля `scripts`, `dependencies`, `devDependencies`) виконується Rego-полісі `text.package_json`, а ця перевірка доповнює її і ловить саме FS-сторону: фізично присутні у корені файли конфігів і `.prettierignore`, які runner Prettier зчитує автоматично.

Список заборонених імен синхронізовано з документацією Prettier 3.x (https://prettier.io/docs/configuration). Якщо Prettier додасть новий формат конфігу — у константу треба додати відповідний рядок.

Файл є ES-модулем (`.mjs`). Експортує єдину функцію `check`, яка повертає exit code (0 — успіх, 1 — провал), що дозволяє запустити її з CLI або іншого скрипта-агрегатора перевірок.

## Експорти / API

| Експорт       | Тип                         | Призначення                                                                                                     |
| ------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `check(cwd?)` | `function(string=): number` | Іменований експорт. Запускає перевірку відсутності Prettier-артефактів у вказаному корені й повертає exit code. |

Інших публічних експортів модуль не має. Константа `FORBIDDEN_PRETTIER_FILES` оголошена локально у модулі і назовні не експортується.

## Функції

### `check(cwd = process.cwd())`

Сигнатура:

```js
export function check(cwd = process.cwd()): number
```

Параметри:

- `cwd` — `string`, опційний. Абсолютний шлях до кореня репозиторію (або іншої теки), в якому потрібно шукати Prettier-артефакти. Якщо не передано, використовується поточна робоча тека процесу (`process.cwd()`).

Повертає:

- `number` — exit code, отриманий від `reporter.getExitCode()`. За контрактом `createCheckReporter`:
  - `0` — у корені не знайдено жодного забороненого Prettier-файлу;
  - `1` — знайдено хоча б один заборонений файл; кожен факт повідомлено окремим `fail(...)`-рядком.

Side effects:

- Виводить повідомлення про статус перевірки через репортер (`pass` / `fail`). Конкретний канал виводу й формат рядків визначає реалізація `createCheckReporter()` (як правило — `stdout`/`stderr` з префіксами).
- Звертається до файлової системи: для кожного імені зі списку викликає `existsSync(join(cwd, file))`. Жодних читань вмісту файлів, жодних записів чи видалень не виконується — перевірка лише на факт існування шляху.
- Не змінює змінні оточення, не модифікує `process` (крім читання `process.cwd()` як дефолтного значення параметра).

Алгоритм:

1. Створити репортер через `createCheckReporter()`; з нього взяти методи `pass` і `fail`.
2. Ініціалізувати локальний прапорець `anyFound = false`.
3. Для кожного імені `file` зі списку `FORBIDDEN_PRETTIER_FILES`:
   - обчислити повний шлях `join(cwd, file)`;
   - якщо `existsSync(...)` повертає `true` — викликати `fail` з повідомленням виду `"<file> заборонено — Prettier не використовуємо, перейди на oxfmt (text.mdc)"` і виставити `anyFound = true`. Цикл не переривається — перевіряємо всі імена, щоб репорт містив повний список знайдених порушень за один прогін.
4. Якщо після циклу `anyFound === false` — викликати `pass('Prettier-конфігів і .prettierignore немає в корені')` (єдиний підсумковий success-рядок).
5. Повернути `reporter.getExitCode()`.

## Залежності

### Зовнішні (стандартна бібліотека Node.js)

- `node:fs` — імпортується `existsSync` для синхронної перевірки існування шляху.
- `node:path` — імпортується `join` для безпечного склеювання `cwd` з іменем файлу (працює коректно на всіх ОС).

### Внутрішні

- `../../../scripts/lib/check-reporter.mjs` — модуль із фабрикою `createCheckReporter()`. Фабрика повертає об'єкт із принаймні полями:
  - `pass(message: string): void` — повідомити про успіх;
  - `fail(message: string): void` — повідомити про порушення;
  - `getExitCode(): number` — підсумковий exit code (зазвичай 0 при відсутності `fail` і 1 — якщо `fail` був хоча б раз).

  Контракт репортера спільний для всіх FS-перевірок у `npm/rules/`, тож формат повідомлень уніфіковано.

### Дотичні правила

- `text.mdc` (`.cursor/rules/n-text.mdc` у проєкті) — джерело заборони Prettier. У повідомленнях `fail` явно посилається користувача на цей файл.
- Rego-полісі `text.package_json` — додаткова перевірка package.json-сторони (доповнює дану FS-перевірку, але не викликається з цього модуля).

## Потік виконання / Використання

Модуль розрахований на виклик із CLI-обгортки чи з агрегатора перевірок, який послідовно проганяє правила з категорії `text`.

Типовий сценарій використання:

1. Скрипт-агрегатор (або CLI на кшталт `n-cursor check` чи окремий runner) імпортує функцію:

   ```js
   import { check } from './npm/rules/text/js/forbidden-prettier.mjs'
   ```

2. Викликає `check()` без аргументів (тоді корінь = `process.cwd()` процесу-агрегатора) або з явним коренем, наприклад при перевірці іншого workspace:

   ```js
   const exitCode = check('/abs/path/to/repo/root')
   ```

3. Отриманий `exitCode` агрегатор підсумовує з іншими перевірками; на CI ненульовий код завалює job.

Локальний запуск як standalone-скрипта (за бажанням, оскільки модуль не має блоку `if (import.meta.url === ...)`) можна організувати тонкою обгорткою або запустити `check` через `node -e`:

```sh
node --input-type=module -e "import('./npm/rules/text/js/forbidden-prettier.mjs').then(m => process.exit(m.check()))"
```

Семантика результату:

- `0` — у корені немає жодного з 18 заборонених імен (різні формати `.prettierrc.*`, `prettier.config.*`, `.prettierignore`). Користувач бачить один success-рядок.
- `1` — знайдено N ≥ 1 файлів. Користувач бачить N окремих fail-рядків (по одному на кожен знайдений артефакт) і нульових success-рядків. Це дозволяє за одним прогоном CI-перевірки одразу побачити повний список того, що треба прибрати.

Чого функція **не** робить (важливо для контексту):

- не зчитує вмісту конфігів — лише факт їх присутності;
- не намагається автоматично видаляти знайдені файли (це задача користувача — мігрувати на `oxfmt` і прибрати артефакти);
- не перевіряє вкладені теки/workspaces — рекурсивного обходу немає, контролюється лише корінь `cwd`;
- не реагує на наявність полів `prettier` у `package.json` — це інша зона відповідальності (Rego `text.package_json`).

## Константи

### `FORBIDDEN_PRETTIER_FILES`

Локальний `const`-масив рядків — повний перелік імен, які Prettier 3.x шукає у корені проєкту. На момент створення модуля містить такі імена (у порядку оригіналу):

- `.prettierignore`
- `.prettierrc`
- `.prettierrc.json`
- `.prettierrc.jsonc`
- `.prettierrc.json5`
- `.prettierrc.yaml`
- `.prettierrc.yml`
- `.prettierrc.toml`
- `.prettierrc.js`
- `.prettierrc.cjs`
- `.prettierrc.mjs`
- `.prettierrc.ts`
- `.prettierrc.cts`
- `.prettierrc.mts`
- `prettier.config.js`
- `prettier.config.cjs`
- `prettier.config.mjs`
- `prettier.config.ts`
- `prettier.config.cts`
- `prettier.config.mts`

Поясняюча нотатка з коментаря у файлі: «Список синхронізовано з конфіг-форматами Prettier 3.x (https://prettier.io/docs/configuration). Якщо Prettier додасть новий формат — додай рядок.» — підтримка списку ручна; при апгрейді Prettier (як майбутньої версії) перевір документацію і за потреби розшир константу.
