diff --git a/.changeset/tangy-streets-hide.md b/.changeset/tangy-streets-hide.md new file mode 100644 index 0000000..18148db --- /dev/null +++ b/.changeset/tangy-streets-hide.md @@ -0,0 +1,7 @@ +--- +"@naverpay/code-style-cli": minor +--- + +[code-style-cli] 패키지 설치 및 설정 파일 생성 CLI 도구 추가 + +PR: [[code-style-cli] 패키지 설치 및 설정 파일 생성 CLI 도구 추가](https://github.com/NaverPayDev/code-style/pull/139) diff --git a/README.md b/README.md index 7f7d293..aca4ad7 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,12 @@ 네이버페이의 일관된 코드 스타일을 유지하기 위한 레포입니다. 해당 레포는 모노레포 구조로 여러 패키지를 포함하며, 필요에 맞게 선택하여 사용하실 수 있습니다. -- [@naverpay/eslint-config](./packages/eslint-config/README.md): ESLint config 를 제공하는 패키지입니다. +- [@naverpay/code-style-cli](./packages/code-style-cli/README.md): 패키지 설치 및 설정 파일 생성을 위한 CLI 도구입니다. +- [@naverpay/eslint-config](./packages/eslint-config/README.md): ESLint config를 제공하는 패키지입니다. - [@naverpay/eslint-plugin](./packages/eslint-plugin/README.md): ESLint plugin 을 제공하는 패키지입니다. - [@naverpay/oxlint-config](./packages/oxlint-config/README.md): oxlint config 를 제공하는 패키지입니다. - [@naverpay/prettier-config](./packages/prettier-config/README.md): Prettier config 를 제공하는 패키지입니다. -- [@naverpay/stylelint-config](./packages/stylelint-config/README.md): Stylelint config 를 제공하는 패키지 입니다. +- [@naverpay/biome-config](./packages/biome-config/README.md): Biome config 를 제공하는 패키지입니다. +- [@naverpay/stylelint-config](./packages/stylelint-config/README.md): Stylelint config 를 제공하는 패키지입니다. - [@naverpay/editorconfig](./packages/editorconfig/README.md): IDE 일관된 코딩 스타일로 작성할 수 있도록 `.editorconfig` 를 제공하는 패키지입니다. - [@naverpay/markdown-lint](./packages/markdown-lint/README.md): 마크다운(Markdown) 파일의 스타일을 검사하는 패키지 입니다. diff --git a/packages/code-style-cli/README.md b/packages/code-style-cli/README.md new file mode 100644 index 0000000..cb04e15 --- /dev/null +++ b/packages/code-style-cli/README.md @@ -0,0 +1,118 @@ +# @naverpay/code-style-cli + +네이버페이 코드 스타일 패키지를 쉽게 설치하고 설정할 수 있는 CLI 도구입니다. + +> pnpm v10+에서는 보안상의 이유로 postinstall 스크립트가 기본적으로 실행되지 않습니다. 이 CLI를 사용하면 패키지 설치와 설정 파일 생성을 한 번에 처리할 수 있습니다. + +## 사용 방법 + +프로젝트 루트에서 실행합니다. + +```bash +npx @naverpay/code-style-cli +``` + +1. 패키지 매니저를 자동으로 감지합니다. (npm, yarn, pnpm) +2. 설치할 패키지를 선택합니다. +3. 선택한 패키지가 설치되고 설정 파일이 자동으로 생성됩니다. + +## 지원 패키지 + +| 패키지 | 설정 파일 | +|--------|-----------| +| [@naverpay/eslint-config](../eslint-config/README.md) | - | +| [@naverpay/eslint-plugin](../eslint-plugin/README.md) | - | +| [@naverpay/prettier-config](../prettier-config/README.md) | `.prettierrc` | +| [@naverpay/stylelint-config](../stylelint-config/README.md) | `stylelint.config.mjs` | +| [@naverpay/markdown-lint](../markdown-lint/README.md) | `.markdownlint.jsonc` | +| [@naverpay/editorconfig](../editorconfig/README.md) | `.editorconfig` | +| [@naverpay/oxlint-config](../oxlint-config/README.md) | `.oxlintrc.json` | +| [@naverpay/biome-config](../biome-config/README.md) | `biome.json` | +| [oxfmt](#oxfmt-가이드) | `.oxfmtrc.json` | + +> eslint-config, eslint-plugin은 설정이 복잡하여 설정 파일을 자동 생성하지 않습니다. + +## 설치 후 설정 + +CLI는 기본 설정 파일만 생성합니다. 추가 설정이 필요한 경우: + +- **설정 변경**: 생성된 설정 파일을 직접 수정하세요. +- **CLI 명령어**: 각 패키지 README의 "CLI" 섹션을 참고하세요. +- **IDE 설정**: 각 패키지 README의 "Integrating with IDE" 섹션을 참고하세요. + +## 주의 사항 + +- 프로젝트 루트에 `package.json`이 있어야 합니다. +- 이미 설정 파일이 존재하는 경우 덮어쓰지 않습니다. + +--- + +## oxfmt 가이드 + +> oxfmt는 Prettier 호환 포매터로, Rust로 작성되어 빠른 속도를 제공합니다. +> +> **Note:** oxfmt는 현재 **alpha** 단계입니다. VSCode Extension 지원도 experimental 상태입니다. + +oxfmt는 현재 `extends` 옵션을 지원하지 않아 별도 config 패키지가 없습니다. CLI에서 네이버페이 권장 설정이 포함된 `.oxfmtrc.json`을 생성합니다. + +### 설정 + +필요에 따라 `ignorePatterns`를 추가합니다. + +```json +{ + "$schema": "./node_modules/oxfmt/configuration_schema.json", + "singleQuote": true, + "semi": false, + "useTabs": false, + "tabWidth": 4, + "endOfLine": "lf", + "bracketSpacing": false, + "arrowParens": "always", + "bracketSameLine": false, + "printWidth": 120, + "trailingComma": "all", + "ignorePatterns": ["dist", "pnpm-lock.yaml", ".github"] +} +``` + +### CLI + +package.json에 스크립트를 추가하여 format 검사를 할 수 있습니다. + +```json +{ + "scripts": { + "format": "oxfmt", + "format:check": "oxfmt --check" + } +} +``` + +### Integrating with IDE + +#### VSCode + +> **Warning:** oxfmt의 VSCode 지원은 현재 **experimental** 단계입니다. + +1. [oxc Extension](https://marketplace.visualstudio.com/items?itemName=oxc.oxc-vscode)을 설치합니다. +2. `settings.json`에 아래 설정을 추가합니다. + +```json +{ + "oxc.enable": true, + "oxc.fmt.experimental": true, + "editor.defaultFormatter": "oxc.oxc-vscode", + "editor.formatOnSave": true, + "[typescript]": { + "editor.defaultFormatter": "oxc.oxc-vscode" + }, + "[javascript]": { + "editor.defaultFormatter": "oxc.oxc-vscode" + } +} +``` + +#### WebStorm + +[oxc-intellij-plugin](https://plugins.jetbrains.com/plugin/27061-oxc) (v0.0.21 이상)을 설치하여 사용할 수 있습니다. diff --git a/packages/code-style-cli/cli.js b/packages/code-style-cli/cli.js new file mode 100755 index 0000000..c015c17 --- /dev/null +++ b/packages/code-style-cli/cli.js @@ -0,0 +1,104 @@ +#!/usr/bin/env node +/* eslint-disable no-console */ + +import {execSync} from 'child_process' +import fs from 'fs' + +import {checkbox, confirm} from '@inquirer/prompts' + +import {PACKAGE_MANAGERS, TOOLS, TOOLS_MAP} from './configs.js' + +// 1. package.json 존재 확인 +if (!fs.existsSync('package.json')) { + console.error('❌ package.json이 없습니다. 프로젝트 루트에서 실행해주세요.') + process.exit(1) +} + +// 2. 패키지 매니저 감지 +function detectPackageManager() { + for (const [name, {lockFile}] of Object.entries(PACKAGE_MANAGERS)) { + if (fs.existsSync(lockFile)) return name + } + return 'npm' +} + +const pm = detectPackageManager() +console.log(`📦 패키지 매니저: ${pm}`) + +// 3. 설치된 패키지 확인 +const pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf-8')) +const installedPkgs = {...pkgJson.dependencies, ...pkgJson.devDependencies} + +// 4. 패키지 선택 UI +const choices = TOOLS.map((tool) => { + const isInstalled = tool.packages.some((pkg) => installedPkgs[pkg]) + return { + ...tool, + name: isInstalled ? `${tool.value} (설치됨)` : tool.value, + } +}) + +const selected = await checkbox({ + message: '설치할 패키지를 선택하세요 (이미 설치된 패키지 선택 시 업데이트)', + choices, + pageSize: choices.length, +}) + +if (selected.length === 0) { + console.log('⚠️ 선택된 패키지가 없습니다.') + process.exit(0) +} + +const selectedTools = selected.map((value) => TOOLS_MAP[value]) +console.log('✅ 선택된 패키지:', selected) + +// 5. 패키지 설치 +const packagesToInstall = selectedTools.flatMap((tool) => tool.packages) + +if (packagesToInstall.length > 0) { + console.log('\n📥 패키지 설치 중...') + try { + execSync(`${PACKAGE_MANAGERS[pm].installCmd} ${packagesToInstall.join(' ')}`, {stdio: 'inherit'}) + console.log('✅ 패키지 설치 완료!') + } catch { + console.error('❌ 패키지 설치 실패. 네트워크 연결을 확인하거나 수동으로 설치해주세요.') + process.exit(1) + } +} + +// 6. 설정 파일 생성 +for (const tool of selectedTools) { + if (!tool.configFile) continue + + if (fs.existsSync(tool.configFile)) { + const overwrite = await confirm({ + message: `${tool.configFile} 이미 존재합니다. 덮어쓰시겠습니까?`, + default: false, + }) + if (!overwrite) { + console.log(`⏭️ ${tool.configFile} 스킵`) + continue + } + } + + if (tool.copyFrom) { + if (!fs.existsSync(tool.copyFrom)) { + console.error(`❌ ${tool.copyFrom} 파일을 찾을 수 없습니다.`) + continue + } + const content = fs.readFileSync(tool.copyFrom, 'utf-8') + fs.writeFileSync(tool.configFile, content) + } else if (tool.getContent) { + const content = tool.getContent() + if (!content) { + console.error(`❌ ${tool.configFile} 생성에 필요한 정보를 찾을 수 없습니다.`) + continue + } + fs.writeFileSync(tool.configFile, content) + } else if (tool.configContent) { + fs.writeFileSync(tool.configFile, tool.configContent) + } + console.log(`✅ ${tool.configFile} 생성 완료`) +} + +console.log('\n🎉 완료!') diff --git a/packages/code-style-cli/configs.js b/packages/code-style-cli/configs.js new file mode 100644 index 0000000..a886aaa --- /dev/null +++ b/packages/code-style-cli/configs.js @@ -0,0 +1,114 @@ +import fs from 'fs' + +// 설정 파일 내용 +const PRETTIERRC_CONTENT = '"@naverpay/prettier-config"' + +const STYLELINT_CONTENT = `/** @type {import('stylelint').Config} */ +const config = { + extends: ['@naverpay/stylelint-config'], + defaultSeverity: 'error', + rules: {}, +} + +export default config +` + +const MARKDOWNLINT_CONTENT = JSON.stringify( + { + extends: '@naverpay/markdown-lint', + }, + null, + 4, +) + +const OXLINTRC_CONTENT = JSON.stringify( + { + $schema: './node_modules/oxlint/configuration_schema.json', + extends: ['./node_modules/@naverpay/oxlint-config/node/.oxlintrc.json'], + }, + null, + 4, +) + +function getBiomeContent() { + const pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf-8')) + const version = pkgJson.devDependencies?.['@biomejs/biome']?.replace(/[\^~]/, '') + if (!version) return null + return JSON.stringify( + { + $schema: `https://biomejs.dev/schemas/${version}/schema.json`, + extends: ['@naverpay/biome-config'], + }, + null, + 4, + ) +} + +const OXFMTRC_CONTENT = JSON.stringify( + { + $schema: './node_modules/oxfmt/configuration_schema.json', + singleQuote: true, + semi: false, + useTabs: false, + tabWidth: 4, + endOfLine: 'lf', + bracketSpacing: false, + arrowParens: 'always', + bracketSameLine: false, + printWidth: 120, + trailingComma: 'all', + }, + null, + 4, +) + +// 패키지 목록 +export const TOOLS = [ + {value: 'eslint-config', packages: ['@naverpay/eslint-config']}, + {value: 'eslint-plugin', packages: ['@naverpay/eslint-plugin']}, + { + value: 'prettier-config', + packages: ['@naverpay/prettier-config'], + configFile: '.prettierrc', + configContent: PRETTIERRC_CONTENT, + }, + { + value: 'stylelint-config', + packages: ['@naverpay/stylelint-config', 'stylelint'], + configFile: 'stylelint.config.mjs', + configContent: STYLELINT_CONTENT, + }, + { + value: 'markdown-lint', + packages: ['@naverpay/markdown-lint'], + configFile: '.markdownlint.jsonc', + configContent: MARKDOWNLINT_CONTENT, + }, + { + value: 'editorconfig', + packages: ['@naverpay/editorconfig'], + configFile: '.editorconfig', + copyFrom: 'node_modules/@naverpay/editorconfig/.editorconfig', + }, + { + value: 'oxlint-config', + packages: ['@naverpay/oxlint-config', 'oxlint'], + configFile: '.oxlintrc.json', + configContent: OXLINTRC_CONTENT, + }, + { + value: 'biome-config', + packages: ['@naverpay/biome-config', '@biomejs/biome'], + configFile: 'biome.json', + getContent: getBiomeContent, + }, + {value: 'oxfmt', packages: ['oxfmt'], configFile: '.oxfmtrc.json', configContent: OXFMTRC_CONTENT}, +] + +export const TOOLS_MAP = Object.fromEntries(TOOLS.map((t) => [t.value, t])) + +export const PACKAGE_MANAGERS = { + npm: {lockFile: 'package-lock.json', installCmd: 'npm install -D'}, + yarn: {lockFile: 'yarn.lock', installCmd: 'yarn add -D'}, + pnpm: {lockFile: 'pnpm-lock.yaml', installCmd: 'pnpm add -D'}, +} diff --git a/packages/code-style-cli/package.json b/packages/code-style-cli/package.json new file mode 100644 index 0000000..4b6bf69 --- /dev/null +++ b/packages/code-style-cli/package.json @@ -0,0 +1,25 @@ +{ + "name": "@naverpay/code-style-cli", + "version": "0.0.1", + "description": "NaverPay code-style CLI tool", + "keywords": [ + "code-style", + "cli", + "naverpay" + ], + "homepage": "https://github.com/NaverPayDev/code-style", + "repository": { + "type": "git", + "url": "https://github.com/NaverPayDev/code-style.git", + "directory": "packages/code-style-cli" + }, + "license": "MIT", + "author": "@NaverPayDev/frontend", + "type": "module", + "bin": { + "code-style": "cli.js" + }, + "dependencies": { + "@inquirer/prompts": "^8.1.0" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d2e6013..8fd76c5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -54,6 +54,12 @@ importers: specifier: ^2.0.6 version: 2.2.6 + packages/code-style-cli: + dependencies: + '@inquirer/prompts': + specifier: ^8.1.0 + version: 8.1.0 + packages/editorconfig: {} packages/eslint-config: @@ -1335,6 +1341,140 @@ packages: resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} engines: {node: '>=18.18'} + '@inquirer/ansi@2.0.2': + resolution: {integrity: sha512-SYLX05PwJVnW+WVegZt1T4Ip1qba1ik+pNJPDiqvk6zS5Y/i8PhRzLpGEtVd7sW0G8cMtkD8t4AZYhQwm8vnww==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + + '@inquirer/checkbox@5.0.3': + resolution: {integrity: sha512-xtQP2eXMFlOcAhZ4ReKP2KZvDIBb1AnCfZ81wWXG3DXLVH0f0g4obE0XDPH+ukAEMRcZT0kdX2AS1jrWGXbpxw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/confirm@6.0.3': + resolution: {integrity: sha512-lyEvibDFL+NA5R4xl8FUmNhmu81B+LDL9L/MpKkZlQDJZXzG8InxiqYxiAlQYa9cqLLhYqKLQwZqXmSTqCLjyw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/core@11.1.0': + resolution: {integrity: sha512-+jD/34T1pK8M5QmZD/ENhOfXdl9Zr+BrQAUc5h2anWgi7gggRq15ZbiBeLoObj0TLbdgW7TAIQRU2boMc9uOKQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/editor@5.0.3': + resolution: {integrity: sha512-wYyQo96TsAqIciP/r5D3cFeV8h4WqKQ/YOvTg5yOfP2sqEbVVpbxPpfV3LM5D0EP4zUI3EZVHyIUIllnoIa8OQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/expand@5.0.3': + resolution: {integrity: sha512-2oINvuL27ujjxd95f6K2K909uZOU2x1WiAl7Wb1X/xOtL8CgQ1kSxzykIr7u4xTkXkXOAkCuF45T588/YKee7w==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/external-editor@2.0.2': + resolution: {integrity: sha512-X/fMXK7vXomRWEex1j8mnj7s1mpnTeP4CO/h2gysJhHLT2WjBnLv4ZQEGpm/kcYI8QfLZ2fgW+9kTKD+jeopLg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/figures@2.0.2': + resolution: {integrity: sha512-qXm6EVvQx/FmnSrCWCIGtMHwqeLgxABP8XgcaAoywsL0NFga9gD5kfG0gXiv80GjK9Hsoz4pgGwF/+CjygyV9A==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + + '@inquirer/input@5.0.3': + resolution: {integrity: sha512-4R0TdWl53dtp79Vs6Df2OHAtA2FVNqya1hND1f5wjHWxZJxwDMSNB1X5ADZJSsQKYAJ5JHCTO+GpJZ42mK0Otw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/number@4.0.3': + resolution: {integrity: sha512-TjQLe93GGo5snRlu83JxE38ZPqj5ZVggL+QqqAF2oBA5JOJoxx25GG3EGH/XN/Os5WOmKfO8iLVdCXQxXRZIMQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/password@5.0.3': + resolution: {integrity: sha512-rCozGbUMAHedTeYWEN8sgZH4lRCdgG/WinFkit6ZPsp8JaNg2T0g3QslPBS5XbpORyKP/I+xyBO81kFEvhBmjA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/prompts@8.1.0': + resolution: {integrity: sha512-LsZMdKcmRNF5LyTRuZE5nWeOjganzmN3zwbtNfcs6GPh3I2TsTtF1UYZlbxVfhxd+EuUqLGs/Lm3Xt4v6Az1wA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/rawlist@5.1.0': + resolution: {integrity: sha512-yUCuVh0jW026Gr2tZlG3kHignxcrLKDR3KBp+eUgNz+BAdSeZk0e18yt2gyBr+giYhj/WSIHCmPDOgp1mT2niQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/search@4.0.3': + resolution: {integrity: sha512-lzqVw0YwuKYetk5VwJ81Ba+dyVlhseHPx9YnRKQgwXdFS0kEavCz2gngnNhnMIxg8+j1N/rUl1t5s1npwa7bqg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/select@5.0.3': + resolution: {integrity: sha512-M+ynbwS0ecQFDYMFrQrybA0qL8DV0snpc4kKevCCNaTpfghsRowRY7SlQBeIYNzHqXtiiz4RG9vTOeb/udew7w==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/type@4.0.2': + resolution: {integrity: sha512-cae7mzluplsjSdgFA6ACLygb5jC8alO0UUnFPyu0E7tNRPrL+q/f8VcSXp+cjZQ7l5CMpDpi2G1+IQvkOiL1Lw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -2127,6 +2267,9 @@ packages: chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + chardet@2.1.1: + resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} + check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} @@ -2150,6 +2293,10 @@ packages: resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} engines: {node: '>=4'} + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + cliui@6.0.0: resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} @@ -2398,6 +2545,9 @@ packages: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} engines: {node: '>=12'} + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2817,6 +2967,10 @@ 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.2.4: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} @@ -2979,6 +3133,10 @@ packages: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} + iconv-lite@0.7.1: + resolution: {integrity: sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==} + engines: {node: '>=0.10.0'} + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -3668,6 +3826,10 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + mute-stream@3.0.0: + resolution: {integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==} + engines: {node: ^20.17.0 || >=22.9.0} + mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} @@ -4415,6 +4577,10 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + string.prototype.includes@2.0.1: resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} engines: {node: '>= 0.4'} @@ -4952,6 +5118,10 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} + 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==} @@ -6241,6 +6411,97 @@ snapshots: '@humanwhocodes/retry@0.4.1': {} + '@inquirer/ansi@2.0.2': {} + + '@inquirer/checkbox@5.0.3': + dependencies: + '@inquirer/ansi': 2.0.2 + '@inquirer/core': 11.1.0 + '@inquirer/figures': 2.0.2 + '@inquirer/type': 4.0.2 + + '@inquirer/confirm@6.0.3': + dependencies: + '@inquirer/core': 11.1.0 + '@inquirer/type': 4.0.2 + + '@inquirer/core@11.1.0': + dependencies: + '@inquirer/ansi': 2.0.2 + '@inquirer/figures': 2.0.2 + '@inquirer/type': 4.0.2 + cli-width: 4.1.0 + mute-stream: 3.0.0 + signal-exit: 4.1.0 + wrap-ansi: 9.0.2 + + '@inquirer/editor@5.0.3': + dependencies: + '@inquirer/core': 11.1.0 + '@inquirer/external-editor': 2.0.2 + '@inquirer/type': 4.0.2 + + '@inquirer/expand@5.0.3': + dependencies: + '@inquirer/core': 11.1.0 + '@inquirer/type': 4.0.2 + + '@inquirer/external-editor@2.0.2': + dependencies: + chardet: 2.1.1 + iconv-lite: 0.7.1 + + '@inquirer/figures@2.0.2': {} + + '@inquirer/input@5.0.3': + dependencies: + '@inquirer/core': 11.1.0 + '@inquirer/type': 4.0.2 + + '@inquirer/number@4.0.3': + dependencies: + '@inquirer/core': 11.1.0 + '@inquirer/type': 4.0.2 + + '@inquirer/password@5.0.3': + dependencies: + '@inquirer/ansi': 2.0.2 + '@inquirer/core': 11.1.0 + '@inquirer/type': 4.0.2 + + '@inquirer/prompts@8.1.0': + dependencies: + '@inquirer/checkbox': 5.0.3 + '@inquirer/confirm': 6.0.3 + '@inquirer/editor': 5.0.3 + '@inquirer/expand': 5.0.3 + '@inquirer/input': 5.0.3 + '@inquirer/number': 4.0.3 + '@inquirer/password': 5.0.3 + '@inquirer/rawlist': 5.1.0 + '@inquirer/search': 4.0.3 + '@inquirer/select': 5.0.3 + + '@inquirer/rawlist@5.1.0': + dependencies: + '@inquirer/core': 11.1.0 + '@inquirer/type': 4.0.2 + + '@inquirer/search@4.0.3': + dependencies: + '@inquirer/core': 11.1.0 + '@inquirer/figures': 2.0.2 + '@inquirer/type': 4.0.2 + + '@inquirer/select@5.0.3': + dependencies: + '@inquirer/ansi': 2.0.2 + '@inquirer/core': 11.1.0 + '@inquirer/figures': 2.0.2 + '@inquirer/type': 4.0.2 + + '@inquirer/type@4.0.2': {} + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -7208,6 +7469,8 @@ snapshots: chardet@0.7.0: {} + chardet@2.1.1: {} + check-error@2.1.1: {} chokidar@4.0.3: @@ -7224,6 +7487,8 @@ snapshots: dependencies: escape-string-regexp: 1.0.5 + cli-width@4.1.0: {} + cliui@6.0.0: dependencies: string-width: 4.2.3 @@ -7458,6 +7723,8 @@ snapshots: emittery@0.13.1: {} + emoji-regex@10.6.0: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -8093,6 +8360,8 @@ snapshots: get-caller-file@2.0.5: {} + get-east-asian-width@1.4.0: {} + get-intrinsic@1.2.4: dependencies: es-errors: 1.3.0 @@ -8253,6 +8522,10 @@ snapshots: dependencies: safer-buffer: 2.1.2 + iconv-lite@0.7.1: + dependencies: + safer-buffer: 2.1.2 + ieee754@1.2.1: {} ignore@5.3.2: {} @@ -9074,6 +9347,8 @@ snapshots: ms@2.1.3: {} + mute-stream@3.0.0: {} + mz@2.7.0: dependencies: any-promise: 1.3.0 @@ -9799,6 +10074,12 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.0 + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.4.0 + strip-ansi: 7.1.0 + string.prototype.includes@2.0.1: dependencies: call-bind: 1.0.7 @@ -10405,6 +10686,12 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.0 + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.1.0 + wrappy@1.0.2: {} write-file-atomic@4.0.2: