diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index c27d8893a..000000000 --- a/.husky/pre-commit +++ /dev/null @@ -1 +0,0 @@ -lint-staged diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ab67f516c..4d6c62142 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,6 +49,7 @@ - 文法およびフォーマットチェッカー - [ESLint](https://eslint.org/) - [Prettier](https://prettier.io/) + - [lefthook](https://github.com/evilmartians/lefthook): Git hooks 管理ツール(コミット前の自動フォーマット・リント) - Search Engine Optimization (SEO) 対策 - [Svelte Meta Tags](https://github.com/oekazuma/svelte-meta-tags): メタタグ、Open Graph などの設定 - [super-sitemap](https://github.com/jasongitmail/super-sitemap): SvelteKit 専用の sitemap ジェネレータ @@ -268,6 +269,35 @@ 6. プルリクエストを作成します。 +### Git Hooks(フォーマット・リント) + +本プロジェクトでは、[lefthook](https://github.com/evilmartians/lefthook)を使用して、コミット前に自動的にコードの書式チェック・フォーマットを行います。 + +- **Pre-commit Hook**: ステージ済みファイルのみに対して以下を実行 + - `prettier --write`: コード書式の自動修正(JavaScript、TypeScript、Markdown、Svelte) + - `eslint`: リント(JavaScript、TypeScript、Svelte) + +Hook は自動的にセットアップされるため、特別な操作は不要です。 + +#### Hook を実行したくない場合 + +環境変数 `LEFTHOOK=0` を設定して commit してください。 + +```bash +LEFTHOOK=0 git commit -m "コミットメッセージ" +``` + +#### (既存ユーザ向け) husky から lefthook への移行 + +husky でセットアップ済みの開発環境で新しい PR をマージした場合、以下を実行してください: + +```bash +git config --unset core.hooksPath +pnpm exec lefthook install +``` + +これにより、古い husky の設定をクリアして lefthook に切り替わります。 + ### トラブルシューティング - エラー: ローカル環境で開発用サーバを立ち上げても、ブラウザに表示されない @@ -283,6 +313,3 @@ - エラー: Docker Desktop で Vite を利用したときに Segmentation Fault が発生 - 対処方法: Docker Desktopで「Use Visualization Framework」のチェックを外す - 参考資料: https://qiita.com/naoto24kawa/items/160aad0ca58642216a0a - -- エラー: コミットを実行したときに、`hint: The '.husky/pre-commit' hook was ignored because it's not set as executable.`と表示される - - 対処方法: ターミナルで`chmod ug+x .husky/*`を実行する diff --git a/docs/dev-notes/2025-12-22/migrate-from-husky-and-lint-staged-to-lefthook/plan.md b/docs/dev-notes/2025-12-22/migrate-from-husky-and-lint-staged-to-lefthook/plan.md new file mode 100644 index 000000000..1c1f270bc --- /dev/null +++ b/docs/dev-notes/2025-12-22/migrate-from-husky-and-lint-staged-to-lefthook/plan.md @@ -0,0 +1,251 @@ +# husky and lint-staged から lefthook への移行計画 + +**Issue:** [#2988](https://github.com/AtCoder-NoviSteps/AtCoderNoviSteps/issues/2988) + +## 背景・目的 + +### 問題点 + +- **実行時間が遅い:** commit 時に約 30秒かかる(手動実行は 12.83秒) +- **ステージ済みファイルのみなのに全体をチェック:** 無関係なファイル処理で時間浪費 +- **npm ツールのオーバーヘッド:** JavaScript の起動時間が重い + +### 目的 + +- **高速化:** 30秒 → **5秒以下** +- **効率化:** ステージ済みファイルのみをチェック +- **メンテナンス性向上:** 高速で活発にメンテナンスされているツールに移行 + +--- + +## 現状分析 + +| 項目 | 詳細 | +| ---------------- | --------------------------------------------------------------------------------------------------- | +| **ツール** | husky 9.1.7 + lint-staged 16.2.7 | +| **実行内容** | `pnpm format` + `pnpm lint` (順序実行) | +| **実行時間** | 手動: 12.83秒、commit: 30秒 | +| **スコープ** | 全体ファイル | +| **チェック対象** | JS/TS: 146ファイル(47,688行)
Markdown: 42ファイル(16,623行)
Svelte: 73ファイル(5,565行) | + +--- + +## 代替ツール調査 + +### 調査結果 + +| ツール | 言語 | Stars | メンテナンス | 採用 | +| ---------------- | ---- | ----- | ------------ | ------- | +| **lefthook** | Go | 7.1k | ✅ 活発 | ✅ 採用 | +| simple-git-hooks | JS | 1.6k | ✅ 活発 | ❌ | +| rusty-hook | Rust | 228 | ❌ 中止 | ❌ | + +### 採用理由 + +✅ **Go 言語実装で高速** + +✅ **並列実行対応**で format + lint を同時実行可能 + +✅ **ステージ済みファイルのみをチェック**(`{staged_files}` 変数) + +✅ **設定ファイルが簡潔** (YAML ベース) + +✅ **Windows/WSL 対応** + +✅ **継続的にメンテナンス中**(v2.0.12、更新: 1 週間前) + +--- + +## Q&A + +### Q1: npm script はそのままにするのか? + +**A:** はい、現状のままにします。速度改善後、必要に応じて見直します。 + +- 現在: `pnpm format` = `prettier --write .` +- 修正時期: 後日検討 + +### Q2: Prettier の check と write は分離するのか? + +**A:** はい、以下のように分離して並列実行します。 + +- **format:** `prettier --write` (修正) +- **lint:** `prettier --check` + `eslint` (チェック) + +### Q3: `.gitignore` に lefthook 生成ファイルを追加する必要があるのか? + +**A:** いいえ、不要です。 + +lefthook は以下のように動作するため: + +- `lefthook.yml` → **git 管理**(設定ファイル) +- `.git/hooks/` → **自動生成**(git 管理外) + +`.gitignore` への追加は不要です。 + +### Q4: lefthook.yml で `exclude` に `node_modules/` 等を指定すべきか? + +**A:** いいえ、不要です。 + +理由: + +- ステージ済みファイルのみ(`{staged_files}`)なので、そもそも `node_modules/` は対象外 +- `exclude` はローカルのみで、CI では効果がない +- 除外ルールは `.gitignore` で一元管理が推奨 + +**結論:** `exclude` は削除し、設定ファイルをシンプルに保つ + +### Q5: package.json に lefthook 関連のコマンドを追加すべきか? + +**A:** いいえ、不要です。 + +理由: + +- husky の `"prepare": "husky"` は削除 +- lefthook は npm が自動でインストール・セットアップ +- package.json に `prepare` script は不要 + +**オプション:** チーム開発の場合、以下を任意で追加 + +```json +"scripts": { + "hooks:install": "lefthook install" // 手動セットアップ用 +} +``` + +--- + +## 実装計画 + +### タスク一覧 + +#### Phase 1: 準備 + +- [ ] lefthook をインストール(`pnpm add -D lefthook`)**30m** +- [ ] `lefthook.yml` を作成 **1h** +- [ ] ローカルで動作確認・実行時間測定 **1h** + +#### Phase 2: husky/lint-staged 削除 + +- [ ] `package.json` から以下を削除 **30m** + - `"lint-staged"` 設定 + - `"prepare": "husky"` スクリプト +- [ ] pnpm パッケージ削除(`pnpm remove husky lint-staged`) **15m** +- [ ] `.husky/` ディレクトリ削除 **10m** + +#### Phase 3: 環境構築 + +- [ ] lefthook をインストール(`lefthook install`) **30m** +- [ ] テスト commit で動作確認 **1h** + +#### Phase 4: ドキュメント更新 + +- [ ] `CONTRIBUTING.md` を更新 **30m** + +#### Phase 5: PR・レビュー・merge + +- [ ] PR 作成・レビュー待ち・merge **1~2h** + +**合計工数:** **5~7時間 = 1 日以内** + +--- + +## 実装詳細 + +### lefthook.yml(実装設定) + +```yaml +version: 2 + +pre-commit: + parallel: true + jobs: + - name: format + run: pnpm exec prettier --write {staged_files} + glob: '**/*.{js,jsx,ts,tsx,md,svelte}' + + - name: lint + run: pnpm exec sh -c 'prettier --check {staged_files} && eslint {staged_files}' + glob: '**/*.{js,jsx,ts,tsx,svelte}' +``` + +**注記:** npm scripts(`pnpm format`、`pnpm lint`)経由ではなく、prettier/eslint を直接呼び出しています。これにより、`{staged_files}` で指定したファイルのみを処理でき、高速化を実現しています。 + +### package.json 修正内容 + +**削除対象:** + +```json +"lint-staged": { ... }, +"prepare": "husky" +``` + +**削除パッケージ:** + +```bash +pnpm remove husky lint-staged +``` + +--- + +## 実装開始の判定 + +- ✅ 前提・調査内容の要約完了 +- ✅ 移行計画の確定 +- ✅ 実装内容の詳細化 +- ✅ 工数見積もり(1 日以内) + +**実装開始可能** + +--- + +## 実装完了報告 + +### 実装内容 + +**実施完了タスク:** + +- ✅ lefthook インストール +- ✅ lefthook.yml 作成 +- ✅ package.json から husky/lint-staged 削除 +- ✅ .husky ディレクトリ削除 +- ✅ lefthook セットアップ +- ✅ 動作確認・時間測定 +- ✅ CONTRIBUTING.md 更新 + +### パフォーマンス測定結果 + +| 項目 | 値 | +| ---------------------------- | ---------- | +| **Pre-commit hook 実行時間** | **0.69秒** | +| **Format 処理時間** | **0.55秒** | +| **改善前** | 約30秒 | +| **改善後** | 約0.7秒 | +| **削減率** | **97.7%** | + +### 教訓 + +1. **Go 言語実装による高速化の効果大** + - JavaScript ツール(husky)から Go 言語ツール(lefthook)への移行で、98%の時間削減を実現 + - 環境起動時間が大幅に削減される + +2. **Prettier/ESLint は直接呼び出しが必須** + - npm scripts 経由(`pnpm format`)では、全ファイル処理のため高速化できない + - `prettier --write {staged_files}` のように直接コマンド呼び出しすることで、ステージ済みファイルのみ処理可能 + +3. **Glob パターンとファイルリスト指定の組み合わせ** + - lefthook の `glob` で対象ファイル型を指定 + - `{staged_files}` で実行ファイルリストを動的に生成 + - この組み合わせにより、効率的かつ柔軟な hook 設定が可能 + +4. **Hook 設定ファイルのシンプル化** + - `.husky/` ディレクトリを削除し、`lefthook.yml` 1 ファイルで一元管理 + - 設定の可読性・メンテナンス性が向上 + +5. **並列実行による時間短縮** + - `parallel: true` で format と lint を同時実行 + - Sequential 実行なら 1.24秒かかるところ、0.7秒で完了 + +6. **Git config のクリーンアップが重要** + - husky の古い `core.hooksPath` 設定が残っていると、lefthook が正常に動作しない + - 環境切り替え時は既存設定の削除が必須 diff --git a/lefthook.yml b/lefthook.yml new file mode 100644 index 000000000..e36d7ca7d --- /dev/null +++ b/lefthook.yml @@ -0,0 +1,12 @@ +version: 2 + +pre-commit: + parallel: true + jobs: + - name: format + run: pnpm exec prettier --write {staged_files} + glob: '**/*.{js,jsx,ts,tsx,md,svelte}' + + - name: lint + run: pnpm exec sh -c 'prettier --check {staged_files} && eslint {staged_files}' + glob: '**/*.{js,jsx,ts,tsx,svelte}' diff --git a/package.json b/package.json index a0f297f20..6100c9663 100644 --- a/package.json +++ b/package.json @@ -6,12 +6,6 @@ "bugs": "https://github.com/AtCoder-NoviSteps/AtCoderNoviSteps/issues", "homepage": "", "license": "MIT", - "lint-staged": { - "**/*.{js,jsx,ts,tsx}": [ - "pnpm format", - "pnpm lint" - ] - }, "scripts": { "dev": "vite dev", "build": "prisma generate && vite build", @@ -26,7 +20,6 @@ "postinstall": "prisma generate", "db:seed": "pnpm exec tsx ./prisma/seed.ts", "db:studio": "pnpm exec prisma studio", - "prepare": "husky", "coverage": "vitest run --coverage" }, "devDependencies": { @@ -49,9 +42,8 @@ "eslint-config-prettier": "10.1.8", "eslint-plugin-svelte": "3.10.1", "globals": "16.5.0", - "husky": "9.1.7", "jsdom": "27.3.0", - "lint-staged": "16.2.7", + "lefthook": "2.0.12", "nock": "14.0.10", "pnpm": "10.26.2", "prettier": "3.7.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2b806ff9b..de131dd04 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -132,15 +132,12 @@ importers: globals: specifier: 16.5.0 version: 16.5.0 - husky: - specifier: 9.1.7 - version: 9.1.7 jsdom: specifier: 27.3.0 version: 27.3.0 - lint-staged: - specifier: 16.2.7 - version: 16.2.7 + lefthook: + specifier: 2.0.12 + version: 2.0.12 nock: specifier: 14.0.10 version: 14.0.10 @@ -2195,18 +2192,10 @@ packages: ajv@8.6.3: resolution: {integrity: sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==} - ansi-escapes@7.2.0: - resolution: {integrity: sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==} - engines: {node: '>=18'} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} - engines: {node: '>=12'} - ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -2219,10 +2208,6 @@ packages: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} - ansi-styles@6.2.3: - resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} - engines: {node: '>=12'} - ansis@4.2.0: resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} engines: {node: '>=14'} @@ -2513,14 +2498,6 @@ packages: class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} - cli-cursor@5.0.0: - resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} - engines: {node: '>=18'} - - cli-truncate@5.1.1: - resolution: {integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==} - engines: {node: '>=20'} - cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -2553,9 +2530,6 @@ packages: resolution: {integrity: sha512-RxmjYxbWemV9gKu4zPgiZagUxbH3RQpEIO77XoSSX0ivgABDZ+h8Zuash/EMFLTI4N9QgFPOJ6JQpPZKFxa+dA==} engines: {node: '>=18'} - colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -2958,9 +2932,6 @@ packages: embla-carousel@8.6.0: resolution: {integrity: sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==} - emoji-regex@10.6.0: - resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2982,10 +2953,6 @@ packages: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} - environment@1.1.0: - resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} - engines: {node: '>=18'} - error-ex@1.3.4: resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} @@ -3421,10 +3388,6 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-east-asian-width@1.4.0: - resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} - engines: {node: '>=18'} - get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -3543,11 +3506,6 @@ packages: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} - husky@9.1.7: - resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} - engines: {node: '>=18'} - hasBin: true - iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -3625,10 +3583,6 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-fullwidth-code-point@5.1.0: - resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} - engines: {node: '>=18'} - is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -3812,6 +3766,60 @@ packages: layout-base@2.0.1: resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} + lefthook-darwin-arm64@2.0.12: + resolution: {integrity: sha512-tuBz1sNLien+nKKb8BDopKjS6EnbXU8rQzhMVBY+bnVfsTiYDfbBr4wo/IzA5TcwoTL/b5somCJhljEw6DvSyg==} + cpu: [arm64] + os: [darwin] + + lefthook-darwin-x64@2.0.12: + resolution: {integrity: sha512-FnuUMPPRMJyTEPXg6PotSrFJ8qf8FDLhhD1zLh74D+9Cye5j9n3lcrCQEjXubPT8du/GZLxMBjjffRbcZ8eYDA==} + cpu: [x64] + os: [darwin] + + lefthook-freebsd-arm64@2.0.12: + resolution: {integrity: sha512-DXElB0qR5e6a8cXkFNYakhwCieypbfh6Y4QG39pzMnLsG03g/nhe093o6owfiUZ4mUFyDM6+0xmy0steOooF2g==} + cpu: [arm64] + os: [freebsd] + + lefthook-freebsd-x64@2.0.12: + resolution: {integrity: sha512-iJN1ZxFeaDi4Fi3b9jcW9wgyNl19LOv2NaVOaAi/tG6mlIn196cmSdXkOA3+943ZbqbdfV9I+bBcIKwneXDA3Q==} + cpu: [x64] + os: [freebsd] + + lefthook-linux-arm64@2.0.12: + resolution: {integrity: sha512-byvmO4Iri6P0COwM8c3lGgeCV3Q0hh1XJpRfrcZDr4Wslq9O63t6J3T6i87oOtY+UjC9pXLl6xGk6hlUcHZ3BQ==} + cpu: [arm64] + os: [linux] + + lefthook-linux-x64@2.0.12: + resolution: {integrity: sha512-KBaiinmf336rA+/dmYs7H7TTeAOByB0CyLA7k8IecTCuaiuKr6ez7ktSjht19poa5G+V0mts4GgEGcx6HViR0w==} + cpu: [x64] + os: [linux] + + lefthook-openbsd-arm64@2.0.12: + resolution: {integrity: sha512-1QBMXX1UW5rtgC4TB52OKWB7Rz/kCBRB+bKKLT/gDD79aPzLgJANTitQQzgFNIWoa7aM9UvzvIAJzOo6FcFIbg==} + cpu: [arm64] + os: [openbsd] + + lefthook-openbsd-x64@2.0.12: + resolution: {integrity: sha512-zPcvUzs65GexRA37UHmaZqWuEGSU/zpBaPIY98MybXzzcJfCIf+O0oUQe2riMllwYGvNW0B1y3NOYRziDNe/vA==} + cpu: [x64] + os: [openbsd] + + lefthook-windows-arm64@2.0.12: + resolution: {integrity: sha512-kgwxguS2GssoHM4SMTp+ArD/Gjg9q5MinD6iI5vSFpuJygD13ZWiXQQfESMHq9y/v1XkD0BdHTJej49dx8P+Vw==} + cpu: [arm64] + os: [win32] + + lefthook-windows-x64@2.0.12: + resolution: {integrity: sha512-Tf/VtSOtF3rBTc9dzRWROa+HuhqaiIV+Xp+1gzlx5+uCueLM0m87Rz6yd4IN5mL7TrDaNkiRXI3FvjCp0dUE4Q==} + cpu: [x64] + os: [win32] + + lefthook@2.0.12: + resolution: {integrity: sha512-I2FdA9cdnq1icwlNz4RADs7exuqe47q1N9+p2LmcP/WfchWh16mvTB82OAD7w7zK9GxblS9GpF7pASaOSl4c7A==} + hasBin: true + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -3830,15 +3838,6 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - lint-staged@16.2.7: - resolution: {integrity: sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow==} - engines: {node: '>=20.17'} - hasBin: true - - listr2@9.0.5: - resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==} - engines: {node: '>=20.0.0'} - local-pkg@1.1.2: resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==} engines: {node: '>=14'} @@ -3862,10 +3861,6 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - log-update@6.1.0: - resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} - engines: {node: '>=18'} - lru-cache@11.2.4: resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} engines: {node: 20 || >=22} @@ -3953,10 +3948,6 @@ packages: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} - mimic-function@5.0.1: - resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} - engines: {node: '>=18'} - min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -4027,10 +4018,6 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nano-spawn@2.0.0: - resolution: {integrity: sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==} - engines: {node: '>=20.17'} - nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -4134,10 +4121,6 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} - onetime@7.0.0: - resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} - engines: {node: '>=18'} - optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -4261,11 +4244,6 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} - pidtree@0.6.0: - resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} - engines: {node: '>=0.10'} - hasBin: true - pify@2.3.0: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} @@ -4627,10 +4605,6 @@ packages: engines: {node: '>= 0.4'} hasBin: true - restore-cursor@5.1.0: - resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} - engines: {node: '>=18'} - retry@0.13.1: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} engines: {node: '>= 4'} @@ -4639,9 +4613,6 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rfdc@1.4.1: - resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} @@ -4734,10 +4705,6 @@ packages: resolution: {integrity: sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==} engines: {node: '>=14'} - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - sirv@3.0.2: resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} engines: {node: '>=18'} @@ -4749,10 +4716,6 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - slice-ansi@7.1.2: - resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} - engines: {node: '>=18'} - smart-buffer@4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} @@ -4817,22 +4780,10 @@ packages: strict-event-emitter@0.5.1: resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} - string-argv@0.3.2: - resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} - engines: {node: '>=0.6.19'} - string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} - string-width@7.2.0: - resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} - engines: {node: '>=18'} - - string-width@8.1.0: - resolution: {integrity: sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==} - engines: {node: '>=20'} - string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -4840,10 +4791,6 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.2: - resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} - engines: {node: '>=12'} - strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} @@ -5408,10 +5355,6 @@ packages: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} - wrap-ansi@9.0.2: - resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} - engines: {node: '>=18'} - wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -7501,14 +7444,8 @@ snapshots: require-from-string: 2.0.2 uri-js: 4.4.1 - ansi-escapes@7.2.0: - dependencies: - environment: 1.1.0 - ansi-regex@5.0.1: {} - ansi-regex@6.2.2: {} - ansi-styles@3.2.1: dependencies: color-convert: 1.9.3 @@ -7519,8 +7456,6 @@ snapshots: ansi-styles@5.2.0: {} - ansi-styles@6.2.3: {} - ansis@4.2.0: {} antlr4@4.11.0: {} @@ -7812,15 +7747,6 @@ snapshots: dependencies: clsx: 2.1.1 - cli-cursor@5.0.0: - dependencies: - restore-cursor: 5.1.0 - - cli-truncate@5.1.1: - dependencies: - slice-ansi: 7.1.2 - string-width: 8.1.0 - cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -7849,8 +7775,6 @@ snapshots: dependencies: color-name: 2.0.2 - colorette@2.0.20: {} - combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -8238,8 +8162,6 @@ snapshots: embla-carousel@8.6.0: {} - emoji-regex@10.6.0: {} - emoji-regex@8.0.0: {} empathic@2.0.0: {} @@ -8256,8 +8178,6 @@ snapshots: env-paths@2.2.1: {} - environment@1.1.0: {} - error-ex@1.3.4: dependencies: is-arrayish: 0.2.1 @@ -8788,8 +8708,6 @@ snapshots: get-caller-file@2.0.5: {} - get-east-asian-width@1.4.0: {} - get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -8916,8 +8834,6 @@ snapshots: human-signals@2.1.0: {} - husky@9.1.7: {} - iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 @@ -8971,10 +8887,6 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-fullwidth-code-point@5.1.0: - dependencies: - get-east-asian-width: 1.4.0 - is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -9174,6 +9086,49 @@ snapshots: layout-base@2.0.1: {} + lefthook-darwin-arm64@2.0.12: + optional: true + + lefthook-darwin-x64@2.0.12: + optional: true + + lefthook-freebsd-arm64@2.0.12: + optional: true + + lefthook-freebsd-x64@2.0.12: + optional: true + + lefthook-linux-arm64@2.0.12: + optional: true + + lefthook-linux-x64@2.0.12: + optional: true + + lefthook-openbsd-arm64@2.0.12: + optional: true + + lefthook-openbsd-x64@2.0.12: + optional: true + + lefthook-windows-arm64@2.0.12: + optional: true + + lefthook-windows-x64@2.0.12: + optional: true + + lefthook@2.0.12: + optionalDependencies: + lefthook-darwin-arm64: 2.0.12 + lefthook-darwin-x64: 2.0.12 + lefthook-freebsd-arm64: 2.0.12 + lefthook-freebsd-x64: 2.0.12 + lefthook-linux-arm64: 2.0.12 + lefthook-linux-x64: 2.0.12 + lefthook-openbsd-arm64: 2.0.12 + lefthook-openbsd-x64: 2.0.12 + lefthook-windows-arm64: 2.0.12 + lefthook-windows-x64: 2.0.12 + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -9188,25 +9143,6 @@ snapshots: lines-and-columns@1.2.4: {} - lint-staged@16.2.7: - dependencies: - commander: 14.0.2 - listr2: 9.0.5 - micromatch: 4.0.8 - nano-spawn: 2.0.0 - pidtree: 0.6.0 - string-argv: 0.3.2 - yaml: 2.8.1 - - listr2@9.0.5: - dependencies: - cli-truncate: 5.1.1 - colorette: 2.0.20 - eventemitter3: 5.0.1 - log-update: 6.1.0 - rfdc: 1.4.1 - wrap-ansi: 9.0.2 - local-pkg@1.1.2: dependencies: mlly: 1.8.0 @@ -9227,14 +9163,6 @@ snapshots: lodash@4.17.21: {} - log-update@6.1.0: - dependencies: - ansi-escapes: 7.2.0 - cli-cursor: 5.0.0 - slice-ansi: 7.1.2 - strip-ansi: 7.1.2 - wrap-ansi: 9.0.2 - lru-cache@11.2.4: {} lru-cache@6.0.0: @@ -9328,8 +9256,6 @@ snapshots: mimic-fn@2.1.0: {} - mimic-function@5.0.1: {} - min-indent@1.0.1: {} mini-svg-data-uri@1.4.4: {} @@ -9390,8 +9316,6 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nano-spawn@2.0.0: {} - nanoid@3.3.11: {} natural-compare@1.4.0: {} @@ -9465,10 +9389,6 @@ snapshots: dependencies: mimic-fn: 2.1.0 - onetime@7.0.0: - dependencies: - mimic-function: 5.0.1 - optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -9586,8 +9506,6 @@ snapshots: picomatch@4.0.3: {} - pidtree@0.6.0: {} - pify@2.3.0: {} pino-abstract-transport@1.2.0: @@ -9905,17 +9823,10 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - restore-cursor@5.1.0: - dependencies: - onetime: 7.0.0 - signal-exit: 4.1.0 - retry@0.13.1: {} reusify@1.1.0: {} - rfdc@1.4.1: {} - robust-predicates@3.0.2: {} rolldown@1.0.0-beta.35: @@ -10048,8 +9959,6 @@ snapshots: signal-exit@4.0.2: {} - signal-exit@4.1.0: {} - sirv@3.0.2: dependencies: '@polka/url': 1.0.0-next.29 @@ -10060,11 +9969,6 @@ snapshots: slash@3.0.0: {} - slice-ansi@7.1.2: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 5.1.0 - smart-buffer@4.2.0: {} socks-proxy-agent@8.0.5: @@ -10134,25 +10038,12 @@ snapshots: strict-event-emitter@0.5.1: {} - string-argv@0.3.2: {} - string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - string-width@7.2.0: - dependencies: - emoji-regex: 10.6.0 - get-east-asian-width: 1.4.0 - strip-ansi: 7.1.2 - - string-width@8.1.0: - dependencies: - get-east-asian-width: 1.4.0 - strip-ansi: 7.1.2 - string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 @@ -10161,10 +10052,6 @@ snapshots: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.2: - dependencies: - ansi-regex: 6.2.2 - strip-final-newline@2.0.0: {} strip-indent@3.0.0: @@ -10794,12 +10681,6 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - wrap-ansi@9.0.2: - dependencies: - ansi-styles: 6.2.3 - string-width: 7.2.0 - strip-ansi: 7.1.2 - wrappy@1.0.2: {} ws@8.18.3: {} @@ -10829,7 +10710,8 @@ snapshots: yaml@1.10.2: {} - yaml@2.8.1: {} + yaml@2.8.1: + optional: true yargs-parser@21.1.1: {}