# Довідник AfterPack CLI

Виклик npx afterpack@latest: необов'язковий шлях, кожен ключ конфігурації як прапорець, підкоманди verify, restore та audit і повний контракт кодів виходу.

Source: https://www.afterpack.dev/uk/docs/cli

`npx afterpack@latest` обфускує каталог збірки. Використовуйте його, коли для вашого бандлера немає плагіна, або в [CI](https://www.afterpack.dev/uk/docs/builds). Якщо для вашого фреймворку плагін є, встановіть замість цього `@afterpack/<fw>`: тоді ваша звичайна збірка одразу видає обфускований результат без окремого кроку. Див. [Фреймворки](https://www.afterpack.dev/uk/docs/frameworks).

Ця сторінка описує [аргумент](#usage), [приклади](#examples), [що робить запуск](#what-a-run-does), [`verify`](#afterpack-verify-dir), [`restore`](#afterpack-restore-dir), [`audit`](#afterpack-audit-url), [машиночитний вивід](#machine-readable-output) та [коди виходу](#exit-codes). Кожен параметр визначено один раз, на сторінці [Конфігурація](https://www.afterpack.dev/uk/docs/config).

## Використання

```
afterpack [path] [--<key>=<value> ...] [-h | --help] [-v | --version]
afterpack verify [dir]
afterpack restore [dir]
afterpack audit <url>
```

```bash
npx afterpack@latest
```

Шлях може бути одним із двох:

- каталогом, який обходиться рекурсивно в пошуках кожного файлу `.js`, `.mjs` і `.cjs`, або
- одним файлом `.js`, `.mjs` чи `.cjs`, який обфускується сам по собі.

Запустіть без шляху, і `afterpack` сам визначить результат вашої збірки: каталог, у який за домовленістю пише бандлер, названий у вашому `package.json` (Next.js → `.next/`, Nuxt → `.output/`, SvelteKit → `build/`, Electron → `out/`, будь-який інший підтримуваний бандлер → `dist/`), якщо цей каталог існує, інакше найновіший з `dist/`, `build/`, `out/`, `.output/` і `.next/`. Він ніколи не читає власний файл конфігурації вашого бандлера, тому нестандартний каталог виводу не визначається: якщо він у вас є, передайте шлях самі. Команда друкує, що знайшла і що збирається зробити, а потім виконується; у CI вона ніколи не ставить запитань. Якщо нічого не знайдено, вона друкує довідку швидкого старту і завершується з кодом `1`. Команда також читає ваш бандлер із `package.json` і наприкінці запуску друкує однорядкову підказку про [відповідний плагін](https://www.afterpack.dev/uk/docs/frameworks).

Вказуйте на результат роботи бандлера, а не на вихідний код. Більшість бандлерів ([Vite](https://www.afterpack.dev/uk/docs/frameworks/vite), [Rollup](https://www.afterpack.dev/uk/docs/frameworks/rollup), [esbuild](https://www.afterpack.dev/uk/docs/frameworks/esbuild), [webpack](https://www.afterpack.dev/uk/docs/frameworks/webpack), [Astro](https://www.afterpack.dev/uk/docs/frameworks/astro), [Parcel](https://www.afterpack.dev/uk/docs/frameworks/parcel)) пишуть у `dist/`. [Next.js](https://www.afterpack.dev/uk/docs/frameworks/nextjs) пише в `.next/`, [Nuxt](https://www.afterpack.dev/uk/docs/frameworks/nuxt) у `.output/`.

## Приклади

```bash
npx afterpack@latest                                        # detects the build output, light default
npx afterpack@latest dist/                                  # a directory you choose
npx afterpack@latest dist/ --preset=hard                    # heavier posture
npx afterpack@latest .next/ --seed=git                      # reproducible output, pinned to the commit
npx afterpack@latest build/widget.js                        # one file
npx afterpack@latest dist/ --diagnostics.level=all          # every diagnostic, not the rolled-up summary
AFTERPACK_complexity=40 npx afterpack@latest dist/           # any flag also works as an env var
```

## Що робить запуск

1. Збирає JavaScript за шляхом `<path>`. Якщо шлях є каталогом, обходить його рекурсивно, пропускає власні [копії `.backup.<hash>`](#files) і пропускає `node_modules/`, якщо ви не включили його через [`--paths.include='**/node_modules/**'`](https://www.afterpack.dev/uk/docs/config#paths-include). Якщо нічого не зібрано, збірка завершується помилкою.
2. Не допускає `.afterpack/` у git за допомогою `.gitignore` усередині нього; цей файл записується, щойно він уперше знадобиться. Ваш власний `.gitignore` ніколи не редагується.
3. Обфускує кожен зібраний файл на місці, на запитаному [пресеті](https://www.afterpack.dev/uk/docs/config#preset) або на [`--complexity`](https://www.afterpack.dev/uk/docs/config#complexity), якщо ви задали його явно. На збірці Next.js, Angular, Vite або webpack він також перейменовує кожен файл із хешем вмісту відповідно до його обфускованих байтів і переписує кожне посилання на нього; на будь-якому іншому результаті імена лишаються такими, як їх записав ваш бандлер. Див. [Імена файлів із хешем вмісту](#content-hashed-file-names).
4. Записує артефакти, які дозволяють прапорці, і завжди [квитанцію захисту](#files). Об'єднана [Protection Map](https://www.afterpack.dev/uk/docs/protection-map) завжди потрапляє в `.afterpack/protectionMap.html`, внесений у gitignore і ніколи не роздається сервером, бо містить ваш оригінальний вихідний код. Source map або резервна копія містить увесь ваш вихідний код. Ніколи не розгортайте ні те, ні інше. Якщо щось із цього потрапляє під сегмент шляху, який роздається сервером, CLI попереджає один раз.
5. Друкує [діагностику](https://www.afterpack.dev/uk/docs/diagnostics), а потім підказку про бандлер, якщо знайшла його.

> **Запуски не ідемпотентні**
>
> Команда перезаписує результат вашої збірки на місці і не зберігає копії, з якої можна було б обфускувати повторно. Зберіть, потім запустіть її один раз. У [CI](https://www.afterpack.dev/uk/docs/builds) такий порядок забезпечується автоматично.

### Не запускайте двічі на тому самому результаті

AfterPack відмовляється обфускувати файл, який уже містить його власний обфускований результат попереднього запуску: він зіставляє зібрані файли з [квитанцією захисту](#afterpack-verify-dir) за хешем вмісту і завершує збірку помилкою `DIAG_ALREADY_OBFUSCATED`, хоч з якого каталогу ви його запускаєте, замість того щоб обфускувати вже обфускований код. Копію захищеного результату, яку зробив фреймворк, наприклад `build/` у SvelteKit, теж буде відхилено. Спочатку перезберіть із вихідного коду: видаліть каталог виводу або виконайте крок очищення вашого бандлера.

### Імена файлів із хешем вмісту

Бандлери називають чанк за хешем його вмісту, наприклад `index-4f9a2c1e.js`, щоб сервер міг кешувати його на рік із `Cache-Control: immutable`. Обфускація змінює байти, тож на збірках нижче запуск дає кожному файлу з хешем вмісту новий хеш в імені й переписує кожне посилання на нього в HTML, маніфестах та інших чанках. Ім'я ніколи не вказує на інші байти, тож браузер, CDN чи сервіс-воркер ніколи не віддасть застарілу копію під повторно використаним ім'ям. Новий хеш виводиться з початкового разом із сідом, версією рушія та вашими налаштуваннями, так само як [плагін](https://www.afterpack.dev/uk/docs/frameworks) називає свої файли; що сід означає для вашого кешу, описано в [Імена файлів і кешування](https://www.afterpack.dev/uk/docs/builds#file-names-and-caching).

| Збірка | На що спрямувати CLI | Що перейменовує запуск |
|---|---|---|
| [Next.js](https://www.afterpack.dev/uk/docs/frameworks/nextjs), на webpack або Turbopack | `.next/`, `.next/static/` або `.next/static/chunks/`; `out/` для статичного експорту | Чанки в `static/chunks/` |
| Application builder [Angular](https://www.afterpack.dev/uk/docs/frameworks/angular) | `dist/<app>/browser/` або `dist/<app>/` | Кожен файл із хешем. Запуск також перераховує атрибути `integrity` і таблицю хешів `ngsw.json` сервіс-воркера |
| [Vite](https://www.afterpack.dev/uk/docs/frameworks/vite) | Каталог з `index.html` або `.vite/manifest.json` | Скрипти й таблиці стилів `name-<hash>` в `assets/` або в теках, які називає маніфест |
| [webpack](https://www.afterpack.dev/uk/docs/frameworks/webpack) | Каталог, чанки якого завантажує рантайм webpack | Файли з шістнадцятковим хешем вмісту в імені |

Імена з хешем вмісту лишаються такими, як їх записав ваш бандлер, і запуск друкує одне повідомлення, коли:

- шлях — це один файл або результат іншого бандлера;
- бандлер збірки Next.js не вдається визначити;
- на збірці Vite або webpack на файл із хешем немає посилання зсередини каталогу збірки, два хеші неможливо розрізнити, або тека поруч із каталогом збірки, як-от серверний бандл, `.svelte-kit/` чи `.output/`, називає файли з хешем чи завелика для перевірки;
- маніфест попереднього кешування, як-от у Workbox, перелічує файли за ревізією.

Для довготривалого кешування на такій збірці використовуйте [плагін](https://www.afterpack.dev/uk/docs/frameworks) вашого фреймворку або зафіксуйте сталий [`--seed`](https://www.afterpack.dev/uk/docs/config#seed).

Серверну збірку Angular, чий `angular-app-manifest.mjs` містить хеші ресурсів, відхилено з кодом `1`, а результат лишається таким, як його записав збирач. Обфускуйте браузерний результат збірки без SSR.

## Прапорці

Кожен ключ конфігурації є прапорцем: `--<key>=<value>`, наприклад `--complexity=40` або `--identifiers.reserved=Hls,Foo` для списку. Булевий прапорець без значення означає `true` (`--build.backup`), а `=false` вимикає його (`--protectionMap.enabled=false`). `-h, --help` і `-v, --version` друкують відповідний текст і завершуються з кодом `0`.

Кожен скалярний ключ або ключ-список із [довідника параметрів](https://www.afterpack.dev/uk/docs/config) працює як прапорець саме так. Структуровані значення належать у `afterpack.json`. Змінні середовища мають ті самі назви з крапками, заміненими на підкреслення, див. [Конфігурація](https://www.afterpack.dev/uk/docs/config), наприклад [`AFTERPACK_key`](https://www.afterpack.dev/uk/docs/config#key), [`AFTERPACK_preset`](https://www.afterpack.dev/uk/docs/config#preset) і [`AFTERPACK_telemetry_enabled`](https://www.afterpack.dev/uk/docs/config#telemetry-enabled).

## Файли

| Шлях | Роль |
|---|---|
| `afterpack.json` | Файл конфігурації. AfterPack піднімається від робочого каталогу вгору до найближчого збігу. Він містить усю [конфігурацію рушія](https://www.afterpack.dev/uk/docs/config#example-afterpackjson): параметри збірки, [`key`](https://www.afterpack.dev/uk/docs/config#key), усе. |
| `.afterpack/receipts/<build dir>.json` | Квитанція захисту для одного каталогу збірки, наприклад `.afterpack/receipts/dist.json` або `.afterpack/receipts/.next.json`. Довгий або незвичний шлях отримує скорочену назву з хешем. Вона містить кожен вихідний файл із хешем записаних байтів, версію рушія та сід. [`afterpack verify`](#afterpack-verify-dir) повторно хешує файли і звіряє з нею, і через неї наступний запуск на тому самому неперезібраному результаті буде відхилено. |
| `.afterpack/protectionMap.html` | Об'єднана [Protection Map](https://www.afterpack.dev/uk/docs/protection-map). Автоматично вноситься в gitignore. Містить ваш оригінальний вихідний код. Ніколи не комітьте і не роздавайте її сервером. |
| `.afterpack/backups/<build dir>/` | Ваші оригінали для одного каталогу збірки, без змін, наприклад `.afterpack/backups/dist/`, з маніфестом кожного файлу, який запуск створив, змінив, перейменував чи видалив. Кожен каталог збірки має власну резервну копію і власне [блокування](#parallel-runs-and-locks), тож збірки різних застосунків в одному репозиторії ніколи не ділять одну копію. Записується під час кожного запуску ([`--build.backup=false`](https://www.afterpack.dev/uk/docs/config#build-backup) вимикає), і [`afterpack restore`](#afterpack-restore-dir) читає її, щоб скасувати запуск. Запуск друкує її шлях, коли завершується. Це ваш вихідний код. Ніколи не комітьте і не розгортайте її. |
| `<file>.js.map` | Згенерований source map, коли увімкнено [`sourceMap.enabled`](https://www.afterpack.dev/uk/docs/config#sourceMap-enabled). За замовчуванням вимкнено: запуск є [продакшн-запуском](https://www.afterpack.dev/uk/docs/config#build-mode), якщо він не позначений як запуск для розробки, а продакшн-запуск також видаляє source map, які записав ваш бандлер, зокрема CSS-карти. Опублікований source map відображає результат прямо назад у ваш вихідний код. |

`.afterpack/` містить квитанції, Protection Map і резервні копії. AfterPack знаходить його від каталогу збірки, хоч з якого каталогу ви запускаєте. Він піднімається вгору до найближчої папки, де є lock-файл (`package-lock.json`, `npm-shrinkwrap.json`, `pnpm-lock.yaml`, `yarn.lock`, `bun.lock` або `bun.lockb`), `afterpack.json` або `.git`. Якщо такої немає, він бере найближчу папку з `package.json`, а якщо немає й такої, кладе його поруч із каталогом збірки. Саме ця папка на цих сторінках є коренем вашого проєкту. `.afterpack/` ніколи не лежить усередині результату збірки.

Запуск завершується помилкою, нічого не перезаписавши, коли знаходить папку `.afterpack/` усередині результату збірки (`DIAG_AFTERPACK_DIR_IN_OUTPUT`: видаліть цю папку і зберіть знову) або не може записати квитанцію (`DIAG_RECEIPT_UNWRITABLE`). Файл `.afterpack-protection.json`, який залишила в результаті старіша версія, видаляється під час наступного запуску.

## `afterpack verify [dir]`

Ворота перед розгортанням. Кожна захищена збірка записує квитанцію захисту в [`.afterpack/receipts/`](#files). `verify` знаходить квитанцію для `[dir]` так само, як і запуск, тож працює з будь-якого каталогу. Вона повторно хешує кожен файл, названий у квитанції, і завершується помилкою, коли якийсь із них більше не збігається, коли квитанції немає або коли вона з іншої збірки.

```bash
npx afterpack@latest verify .        # a project root: looks in ./ then ./.next/
npx afterpack@latest verify dist     # or the build output directory itself
npx afterpack@latest verify build    # SvelteKit's adapter copy; also .output/public, out/
```

Каталог, який фреймворк скопіював зі свого результату збірки, наприклад `build/` у SvelteKit, `.output/public/` у Nuxt або `out/` у Next, перевіряється за квитанцією каталогу, з якого його скопійовано. `verify` зіставляє копію з цією квитанцією за її файлами і перевіряє кожен хеш, тож змінений файл спричиняє помилку і називається. Вказуйте саме корінь розгортання. Текстовий вивід тоді додає `· copy of <source dir>/`.

Вона не читає конфігурацію рушія, лише [`--diagnostics.format`](#machine-readable-output) і `--diagnostics.level`. З `--diagnostics.format=json` поле `receipt` у підсумку називає квитанцію, яку вона перевірила, а `copiedFrom` називає каталог, з якого зроблено копію. Запускайте її останнім кроком перед розгортанням; див. [Збірки та CI](https://www.afterpack.dev/uk/docs/builds).

Вона також завершується помилкою, коли зупинений запуск чи відновлення лишили в каталозі збірки тимчасовий файл `.afterpack-tmp`. Див. [Запуск, що зупинився на півдорозі](#a-run-that-stopped-partway).

## `afterpack restore [dir]`

Скасування. Перш ніж щось записати, запуск копіює ваші оригінали в `.afterpack/backups/<build dir>/` і записує кожен файл, який він створить, змінить, перейменує чи видалить. `restore` повертає кожен файл під його початковим ім'ям і з початковими байтами, скасовує перейменування та переписані посилання і видаляє резервну копію та квитанцію, яку записав запуск.

```bash
npx afterpack@latest restore          # every backup under the project root
npx afterpack@latest restore dist     # only the run over dist/
```

Спрямована на каталог збірки, вона відновлює лише запуски над цим каталогом, над каталогом усередині нього або над збіркою, що його містить. Спрямована на корінь проєкту, вона відновлює всі резервні копії, що там є. Коли жодна резервна копія не покриває шлях, вона завершується помилкою і перелічує каталоги, які мають копію. Вона знаходить `.afterpack/` від `[dir]` так само, як запуск, і також читає теку `.afterpack/backup/`, яку записав попередній випуск.

Вона зупиняється з помилкою (fail closed): кожен записаний файл перевіряється, *перш ніж* щось буде записано, тому файл, який ви редагували чи перезібрали після запуску, зупиняє відновлення, нічого не відновлюється, а команда називає файл і завершується з кодом `1`. Без резервної копії вона відмовляється працювати одразу. Відновлення, що зупинилося на півдорозі, завершує наступний `restore`. Не читає конфігурацію рушія, окрім [`--diagnostics.format`](#machine-readable-output).

### Запуск, що зупинився на півдорозі

Запуск, що завершується помилкою, відкочує власні записи перед виходом. Кожен файл спершу записується в тимчасовий `<file>.afterpack-tmp`, а тоді перейменовується на місце, тож перерваний запуск ніколи не лишає наполовину записаного файлу. Резервна копія перерваного запуску лишається позначеною як незавершена, і наступний запуск `afterpack` над тим самим каталогом спершу перевіряє результат:

| Що містить результат збірки | Наступний запуск |
|---|---|
| Лише те, що записав ваш бандлер, і те, що записав зупинений запуск | Завершується з кодом `1`. Виконайте `afterpack restore`, щоб повернути результат до стану, який записав ваш бандлер, або перезберіть із вихідного коду й запустіть знову. |
| Нову збірку або точно те, що записав ваш бандлер, без жодного сліду зупиненого запуску | Відкидає застарілу резервну копію з повідомленням і виконується. |
| Суміш: частину файлів перезібрано, інші досі містять результат зупиненого запуску | Завершується з кодом `1` і називає перезібрані файли, а `restore` теж відмовляється. Перезберіть увесь результат із вихідного коду й запустіть знову або скопіюйте оригінали інших файлів із теки резервної копії, яку називає повідомлення. |

З [`--build.backup=false`](https://www.afterpack.dev/uk/docs/config#build-backup) резервна копія не записується, тож перерваний запуск неможливо скасувати: перезберіть із вихідного коду. AfterPack не скидає свої записи на диск примусово, тож після втрати живлення під час запуску чи відновлення так само перезберіть із вихідного коду.

### Паралельні запуски та блокування

Запуск і відновлення тримають блокування свого каталогу збірки, `.afterpack/backups/<build dir>/lock`, доки не завершаться. Запуски над різними каталогами збірки, як-от двома застосунками в одному репозиторії, ідуть паралельно. Другий запуск над тією самою збіркою, зокрема над каталогом усередині неї, як-от `.next/static/chunks/`, поки захищається `.next/`, завершується з кодом `1` і називає запуск, що тримає блокування. Блокування, процес якого на цій машині вже завершився або яке старше за дві години, перебирається з повідомленням. Якщо жоден запуск не триває, а блокування лишається, видаліть файл, який називає повідомлення.

## `afterpack audit <url>`

Сканує **розгорнутий** сайт на витоки секретів, відкритий вихідний код і незахищений JavaScript, передаючи знахідки потоком у процесі сканування. Команда не читає конфігурацію і не надсилає нічого, крім URL. Повний довідник команди див. на сторінці [Аудит](https://www.afterpack.dev/uk/docs/audit).

```bash
npx afterpack@latest audit example.com
```

## Машиночитний вивід

`--diagnostics.format=json` виводить у stdout рівно один JSON-документ і більше нічого; кожен рядок для людини переходить у stderr. Працює через прапорець, через `AFTERPACK_diagnostics_format=json` або через `diagnostics.format` у `afterpack.json`, і `verify` та `audit` також його враховують. Поєднайте його з `diagnostics.level=none`, щоб запуск не друкував нічого, крім документа. Саме цю форму мають читати кроки CI та AI-агенти замість розбору текстового виводу; пакет також містить `SKILL.md`, який описує CLI для агента, що викликає його напряму.

```bash
npx afterpack@latest dist/ --diagnostics.format=json --diagnostics.level=none
```

## Коди виходу

| Код | Значення |
|---|---|
| `0` | Успіх. Кожен зібраний файл обфусковано і записано. Також повертається для [`--help` і `--version`](#usage). |
| `1` | Помилка. Нічого придатного не створено: шлях не існує, під ним не знайдено JavaScript, будь-яка помилка рушія, невдалий `verify`, невдале сканування `audit` або збірка з ключем Pro, чий хмарний виклик не вдався. |
| `2` | Частково. Зарезервовано для збірки з вичерпаною квотою; сьогодні жодна збірка його не повертає. |
| `3` | Обмеження розміру. [`inflation.max`](https://www.afterpack.dev/uk/docs/config#inflation-max) не дозволив досягти цільової складності (`DIAG_SIZE_CAP_REACHED`). |
| `4` | Потрібен Pro. Запис [`regions`](https://www.afterpack.dev/uk/docs/config#regions) підвищує захист понад конфігурацію всієї програми й потребує [`key`](https://www.afterpack.dev/uk/docs/config#key) (`DIAG_PRO_DIRECTIVE_REQUIRES_KEY`). CLI не читає директив із вихідного коду, тож до цього виходу веде лише `regions`. |
| `5` | Рефлексія. Виявлено патерн рефлексії під час виконання без [`reflection.allow`](https://www.afterpack.dev/uk/docs/config#reflection-allow) (`DIAG_REFLECTION_NOT_ACKNOWLEDGED`). |
| `6` | Потрібне оновлення. Хмарі AfterPack або цьому `afterpack` потрібен новіший `@afterpack/core`. Нічого не записано. |
| `64` | Неправильне використання. Невідомий прапорець або команда, некоректне значення або продубльований аргумент шляху. |

Використовуйте [`paths.exclude`](https://www.afterpack.dev/uk/docs/config#paths-exclude), щоб виділити файл, який має вийти незмінним.

Збірка Pro з розпізнаним [`key`](https://www.afterpack.dev/uk/docs/config#key) зупиняється з помилкою (fail closed). Якщо хмарний виклик не вдався, збірка зупиняється замість того, щоб повертатися до результату рівня Free. Код `4` — вихід Free-збірки із записом `regions`, що потребує ключа; код `5` — вихід для непідтвердженого патерну рефлексії на будь-якій збірці, Free чи Pro; код `2` зарезервовано для майбутньої збірки з вичерпаною квотою, і сьогодні жодна збірка його не повертає. Повний контракт див. у розділі [Коди виходу](https://www.afterpack.dev/uk/docs/diagnostics#exit-codes).

## Далі

- [Конфігурація](https://www.afterpack.dev/uk/docs/config): кожен параметр і чотири форми, якими його можна задати.
- [Пресети](https://www.afterpack.dev/uk/docs/presets): драбина з п'яти щаблів і ціна кожного щабля.
- [Аудит](https://www.afterpack.dev/uk/docs/audit): повний довідник `afterpack audit`.
- [Діагностика](https://www.afterpack.dev/uk/docs/diagnostics#exit-codes): контракт кодів виходу, правило зупинки з помилкою (fail closed) і кожен код `DIAG_*`.
- [Фреймворки](https://www.afterpack.dev/uk/docs/frameworks): шлях через плагін, кращий, коли плагін для вашого стека існує.
- [Швидкий старт](https://www.afterpack.dev/uk/docs/quickstart): найкоротший шлях від встановлення до [Protection Map](https://www.afterpack.dev/uk/docs/quickstart#check-the-result).
