---
type: JS Module
title: check-reporter.mjs
resource: npm/scripts/lib/check-reporter.mjs
docgen:
  crc: b76ed480
---

Модуль `check-reporter.mjs` — це невелика спільна (shared) бібліотека-фабрика для check-скриптів (`check-*.mjs`) і для `lint-docker`. Вона надає уніфікований спосіб репортити результати перевірок: успіхи (`pass`) та помилки (`fail`), а також акумулювати фінальний код виходу процесу (`exit code`).

Основна ідея: викликаючи фабрику `createCheckReporter()`, споживач отримує об’єкт з трьома методами — `pass`, `fail` і `getExitCode`. Будь-який виклик `fail` переводить внутрішній лічильник у стан помилки (`exitCode = 1`), і подальший `getExitCode()` повертатиме `1`. Якщо `fail` жодного разу не викликали — `getExitCode()` поверне `0`.

Модуль навмисно тримає API мінімальним і не нав’язує конкретний формат виводу: рядок успіху форматується делегованою функцією `pass` з `../utils/pass.mjs`, а помилка виводиться у форматі `  ❌ <msg>` через `console.log`.

Важлива поведінкова деталь: `getExitCode` — це **метод-геттер у вигляді функції**, а не геттер-властивість через `get`. Тому слід викликати саме `reporter.getExitCode()` у момент завершення, а не деструктурувати `const { exitCode } = reporter` — інакше отримаєш undefined або застаріле значення, оскільки `exitCode` як поле в об’єкті не експонується назовні (це замикання).

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

Модуль експортує одну іменовану (named) функцію:

- `createCheckReporter()` — фабрика, що повертає об’єкт-репортер.

Структура об’єкта, який повертає `createCheckReporter()`:

| Поле          | Тип                     | Опис                                                                                               |
| ------------- | ----------------------- | -------------------------------------------------------------------------------------------------- |
| `pass`        | `typeof pass`           | Реекспорт функції `pass` з `../utils/pass.mjs`. Друкує рядок успіху у форматі, визначеному `pass`. |
| `fail`        | `(msg: string) => void` | Друкує рядок помилки з префіксом ` ❌` і виставляє внутрішній `exitCode = 1`.                      |
| `getExitCode` | `() => number`          | Повертає `0`, якщо `fail` жодного разу не викликали, інакше `1`.                                   |

JSDoc-сигнатура у файлі:

```js
/**
 * @returns {{
 *   pass: typeof pass,
 *   fail: (msg: string) => void,
 *   getExitCode: () => number
 * }}
 */
```

## Функції

### `createCheckReporter()`

**Сигнатура:**

```js
export function createCheckReporter(): {
  pass: typeof pass,
  fail: (msg: string) => void,
  getExitCode: () => number,
}
```

**Параметри:** немає.

**Повертає:** новий об’єкт-репортер з трьома методами. Кожен виклик `createCheckReporter()` створює **окреме замикання** з власним внутрішнім `exitCode`, тобто різні репортери незалежні один від одного.

**Side effects:** при створенні — жодних. Side effects виникають лише при виклику методів повернутого об’єкта (`fail` пише в stdout через `console.log`; `pass` робить те, що визначено в `../utils/pass.mjs`).

**Внутрішня логіка:**

1. Створюється локальна змінна `let exitCode = 0`.
2. Повертається об’єктний літерал з трьома методами:
   - `pass` — пряма посилання на імпортовану функцію `pass`.
   - `fail(msg)` — виконує `console.log(\` ❌ ${msg}\`)`і присвоює`exitCode = 1`.
   - `getExitCode()` — повертає поточне значення `exitCode`.

### Метод `pass` (повертається з фабрики)

**Сигнатура:** успадковує сигнатуру функції `pass` з `../utils/pass.mjs` (`typeof pass`).

**Поведінка:** повний контракт — за `../utils/pass.mjs`. У межах цього модуля `pass` просто реекспортується без обгортки і не впливає на `exitCode`.

### Метод `fail(msg)` (повертається з фабрики)

**Сигнатура:**

```js
fail(msg: string): void
```

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

- `msg: string` — текст повідомлення про помилку.

**Повертає:** `undefined`.

**Side effects:**

- Пише в stdout рядок виду `  ❌ <msg>` через `console.log` (два пробіли індентації + хрестик-емодзі + пробіл + повідомлення).
- Виставляє внутрішній `exitCode = 1` у замиканні фабрики.

**Семантика:** після першого виклику `fail` репортер «фіксує» загальний стан як помилковий — це безповоротна операція в межах одного інстансу.

### Метод `getExitCode()` (повертається з фабрики)

**Сигнатура:**

```js
getExitCode(): number
```

**Параметри:** немає.

**Повертає:** `0` (якщо `fail` не викликали жодного разу) або `1` (якщо викликали хоча б один раз).

**Side effects:** немає.

**Чому функція, а не властивість:** значення `exitCode` зберігається в замиканні. Звичайне поле об’єкта закарбувало б початкове `0` і не відображало б подальших змін. Геттер-функція забезпечує «живе» зчитування актуального стану.

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

### Внутрішні (з репо)

- `../utils/pass.mjs` — імпортується named-імпорт `pass`. Це функція, що друкує рядок успіху в уніфікованому форматі. Для деталей формату див. документацію `pass.mjs`.

### Зовнішні (Node/runtime)

- Глобальний `console.log` — для виводу помилок у `fail()`.

### Без побічних залежностей

Модуль чистий від npm-пакетів, не звертається до файлової системи, мережі чи `process.exit` — повернений `getExitCode()` лише **повідомляє** код, але **не завершує** процес самостійно. Завершення процесу — відповідальність викликаючого скрипта.

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

### Типовий сценарій у check-скрипті

```js
import { createCheckReporter } from '../lib/check-reporter.mjs'

const reporter = createCheckReporter()

if (somethingWrong) {
  reporter.fail('Опис проблеми')
} else {
  reporter.pass('Усе ок')
}

// Важливо: викликати getExitCode() саме як функцію
process.exit(reporter.getExitCode())
// або: return reporter.getExitCode()
```

### Як використовується в `lint-docker` та інших споживачах

Один інстанс `reporter` створюється на запуск перевірки. У циклі по ресурсах (файлах, правилах, конфігах тощо) виконуються виклики `pass` / `fail` залежно від результату. По завершенні — одноразовий `getExitCode()`, значення якого передається в `process.exit(...)` або повертається з `async`-функції-точки входу.

### Антипатерн (нерекомендовано)

```js
// ❌ НЕ робити так — exitCode не «знімається» цим способом,
// бо це не геттер-властивість, а замикання поверх локальної змінної.
const { exitCode } = reporter
process.exit(exitCode) // буде undefined
```

Правильно:

```js
process.exit(reporter.getExitCode())
```

### Семантика exit code

- `0` — усі перевірки пройшли (або жодного `fail` не було).
- `1` — щонайменше один `fail`. Подальші виклики `fail` не «накопичують» вище 1 — це бінарний прапорець «була помилка / не було».

### Формат виводу

- Успіх: формат повністю делегований `pass` з `../utils/pass.mjs`.
- Помилка: `  ❌ <msg>` (два пробіли + ❌ + пробіл + повідомлення), завжди через `console.log` (stdout, з переведенням рядка).

### Ізольованість інстансів

Кожен виклик `createCheckReporter()` повертає новий незалежний об’єкт із власним `exitCode`. Це означає, що в одному процесі можна тримати кілька паралельних/незалежних репортерів — наприклад, по одному на правило/секцію — і агрегувати їхні фінальні коди вручну (через `Math.max` чи логічне OR), якщо потрібно.
