# `fix.mjs` — entry-point правила `js-bun-db`

## Огляд

Файл `npm/rules/js-bun-db/fix.mjs` — це **точка входу** (entry-point) для правила `js-bun-db` пакета `@nitra/cursor`. Правило перевіряє/виправляє код, що працює з базою даних у середовищі Bun (JavaScript runtime), і виконується у стандартному CI4-пайплайні:

1. `applies` — визначає, до яких файлів застосовується правило;
2. `JS-concerns` — перевіряє/чинить специфічні JS-аспекти (через стандартний пайплайн);
3. `policy` — застосовує політики правила (наприклад, заборонені патерни, переписування коду);
4. `mdc-refs` — оновлює перехресні посилання у `.mdc`-документах (Markdown Cursor).

Файл виконує **дві ролі одночасно**:

- **Library mode** — експортує функцію `run(ctx)`, яку викликає зовнішній orchestrator (CLI `@nitra/cursor`, ESLint-обгортка, інші правила) для виконання пайплайну у спільному процесі (з можливістю переюзу `walkCache` через переданий `ctx`).
- **Standalone mode** — якщо файл запущено напряму як CLI (`bun rules/js-bun-db/fix.mjs`), він проганяє повний CLI-цикл (`runRuleCli`) із завантаженням конфігурації, whitelist-фільтрацією та підсумковим виводом, після чого виставляє відповідний `process.exit(code)` для CI/IDE.

Файл свідомо мінімалістичний: уся реальна логіка винесена у бібліотечні утиліти (`run-standard-rule.mjs`, `run-rule-cli.mjs`); `fix.mjs` лише делегує виклики, передаючи `import.meta.dirname` як ідентифікатор поточної директорії правила.

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

| Експорт | Тип        | Призначення                                                                              |
| ------- | ---------- | ---------------------------------------------------------------------------------------- |
| `run`   | `function` | Library-режим: виконує стандартний пайплайн правила для переданого/дефолтного контексту. |

Інших іменованих експортів немає. Файл також містить **side-effect-блок** верхнього рівня (див. секцію [Потік виконання](#потік-виконання--використання)), який спрацьовує лише за умови запуску модуля як CLI.

## Функції

### `run(ctx)`

```js
export function run(ctx)
```

**Призначення.** Запускає стандартний пайплайн правила (`applies → JS-concerns → policy → mdc-refs`) для директорії, у якій лежить сам `fix.mjs`. Тобто — для правила `js-bun-db`. Делегує всю роботу функції `runStandardRule`.

**Параметри.**

| Ім'я  | Тип                                                         | Обов'язковість | Опис                                                                                                                                                                            |
| ----- | ----------------------------------------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ctx` | `RuleContext` (з `../../scripts/lib/run-standard-rule.mjs`) | Опціональний   | Контекст прогону (наприклад, `walkCache` — закешований обхід файлової системи, поділюваний між правилами одного CLI-сеансу). Якщо не передано — `runStandardRule` створює свій. |

**Повертає.** `Promise<number>`:

- `0` — правило відпрацювало успішно, порушень немає (або всі виправлені автоматично, якщо це fix-режим);
- `1` — виявлено порушення, які не вдалося виправити автоматично.

**Side effects.**

- Може **читати** файли проєкту (через walk у `runStandardRule`).
- Може **записувати/змінювати** файли проєкту, якщо стандартний пайплайн застосовує автоматичні фіксери.
- Може **писати у stdout/stderr** діагностичні повідомлення стандартного пайплайну.
- **Не** викликає `process.exit` — рішення про exit-code залишається за викликачем.

**Ключовий момент.** Перший аргумент `runStandardRule` — `import.meta.dirname` — це абсолютний шлях до директорії, у якій лежить `fix.mjs` (тобто `…/npm/rules/js-bun-db/`). За цим шляхом `runStandardRule` визначає **id правила** і завантажує його `.mdc`, `check-*.mjs`, тощо.

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

### Внутрішні модулі (npm/scripts/lib)

| Імпорт            | Звідки                                    | Роль                                                                                                                                                                                                   |
| ----------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `isRunAsCli`      | `../../scripts/lib/run-rule-cli.mjs`      | Утиліта-детектор: повертає `true`, якщо переданий `import.meta.url` відповідає файлу, який запущено як головний модуль (`process.argv[1]`). Дозволяє відрізнити library-import від standalone-запуску. |
| `runRuleCli`      | `../../scripts/lib/run-rule-cli.mjs`      | Standalone CLI orchestration: завантажує конфіг (`.cursor.json`/`package.json`), застосовує whitelist, запускає правило з директорії, друкує summary і повертає `Promise<number>` (exit-code).         |
| `runStandardRule` | `../../scripts/lib/run-standard-rule.mjs` | Бібліотечний прогон стандартного пайплайну правила (`applies → JS-concerns → policy → mdc-refs`). Не виконує CLI-обв'язку (конфіг, summary).                                                           |

### Системні API

| API                   | Використання                                                                                                                       |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `import.meta.dirname` | Абсолютний шлях до директорії, що містить цей `fix.mjs`. Передається у `runStandardRule` та `runRuleCli` як ідентифікатор правила. |
| `import.meta.url`     | URL поточного модуля. Передається в `isRunAsCli` для перевірки, чи запущено модуль як CLI.                                         |
| `process.exit`        | Викликається лише у standalone-гілці з кодом, поверненим `runRuleCli`. Дає змогу CI/IDE отримати exit-status.                      |

### ESLint-директива

Файл містить рядкову директиву:

```text
// eslint-disable-next-line n/no-process-exit, unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
```

Свідоме вимкнення правил `n/no-process-exit` та `unicorn/no-process-exit` для рядка з `process.exit`. Виправдання: standalone entry-point **зобов'язаний** повертати exit-code для CI/IDE-консьюмерів.

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

### Дві ролі модуля

Файл проектувався так, щоб **той самий код** обслуговував і library-, і standalone-сценарії, без дублювання логіки.

#### Library mode (import + run)

```js
import { run } from '@nitra/cursor/rules/js-bun-db/fix.mjs'

const exitCode = await run({ walkCache })
//   ^^^^^^^^   0 = OK, 1 = порушення
```

- Викликач (наприклад, головний CLI `@nitra/cursor`) уже завантажив конфіг, побудував список правил, створив спільний `walkCache`.
- Викликає `run(ctx)`, отримує число (exit-code-семантика), сам приймає рішення про `process.exit`.
- Гілка `if (isRunAsCli(...))` **не виконується**, бо `import.meta.url` цього файлу не збігається з URL головного модуля процесу.

#### Standalone mode (bun rules/js-bun-db/fix.mjs)

```bash
bun npm/rules/js-bun-db/fix.mjs
# еквівалентно:
npx @nitra/cursor fix js-bun-db
```

- Bun запускає `fix.mjs` як головний модуль.
- `isRunAsCli(import.meta.url)` повертає `true`.
- Виконується `await runRuleCli(import.meta.dirname)` — повний CLI-цикл: завантаження конфігурації, whitelist-фільтрація, прогон, друк підсумку.
- Результат (number) передається у `process.exit`, який завершує процес із потрібним exit-code для CI/IDE.

### Послідовність кроків при standalone-запуску

1. Інтерпретатор виконує верхньорівневі імпорти (`isRunAsCli`, `runRuleCli`, `runStandardRule`).
2. Створюється/реєструється функція `run` (експорт).
3. Перевіряється `isRunAsCli(import.meta.url)` — для standalone дає `true`.
4. Викликається `await runRuleCli(import.meta.dirname)` — повертає `Promise<number>`.
5. `process.exit(<number>)` завершує процес.

### Послідовність кроків при library-import

1. Інтерпретатор виконує верхньорівневі імпорти.
2. Створюється функція `run` (експорт стає доступним викликачу).
3. `isRunAsCli(...)` повертає `false` — гілка `if (...)` пропускається.
4. Модуль готовий: викликач у будь-який момент викликає `run(ctx)`.

### Архітектурні нотатки

- **Чому два режими в одному файлі.** Така подвійна роль (`library + standalone`) — конвенція пакета `@nitra/cursor` для всіх `fix.mjs` правил. Це дає:
  - можливість швидко прогнати **одне правило** локально під час розробки (`bun rules/<id>/fix.mjs`);
  - можливість CLI-оркестратору **імпортувати** правило без форку процесу;
  - єдиний контракт (`run(ctx) → Promise<number>`) для всіх правил пакета.
- **Чому `import.meta.dirname`.** Це абсолютний шлях, який не залежить від CWD виклику; правило знаходить свої артефакти (`.mdc`, `check-*.mjs`, `meta.json`) відносно власного розташування на диску.
- **Чому `await` перед `runRuleCli`.** `runRuleCli` — асинхронна функція; `process.exit` має отримати готове число, а не `Promise`.

## Rebuild Test

З опису вище можна реконструювати поведінку файлу:

1. **Імпорти.** Дві утиліти з `../../scripts/lib/run-rule-cli.mjs` (`isRunAsCli`, `runRuleCli`) та одна з `../../scripts/lib/run-standard-rule.mjs` (`runStandardRule`).
2. **Експорт `run(ctx)`.** Повертає `runStandardRule(import.meta.dirname, ctx)`. Сигнатура: `(ctx?: RuleContext) => Promise<number>`. `0` — OK, `1` — порушення.
3. **CLI-блок.** Умова `if (isRunAsCli(import.meta.url))`. Усередині — `process.exit(await runRuleCli(import.meta.dirname))`. Перед `process.exit` стоїть `eslint-disable-next-line` для `n/no-process-exit` та `unicorn/no-process-exit` із поясненням, що standalone entry-point має повертати exit-code.
4. **Жодної іншої логіки.** Файл не містить ні констант, ні класів, ні допоміжних функцій — лише делегування.
