@in-ch/setup
Version:
A tool for quick setup and configuration of essential project files.
1 lines ⢠96.2 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts","../src/lib/check-pkg-init.ts","../src/lib/get-package-info.ts","../src/const/error/error.ts","../src/utils/file-error-handle.ts","../src/commands/adb-remote.ts","../src/commands/commitlint.ts","../src/lib/commit-lint-config.ts","../src/lib/check-is-monorepo.ts","../src/lib/detect-package-manger.ts","../src/lib/get-global-package-path.ts","../src/lib/get-setting-file-path.ts","../src/commands/eslint.ts","../const/config.ts","../src/lib/utils.ts","../src/lib/package-manager.ts","../src/const/packagesMng.ts","../src/lib/eslint-config.ts","../src/lib/version-update.ts","../src/lib/check-latest-pkg-version.ts","../src/commands/pkgmng.ts","../src/commands/gitmessage.ts","../src/lib/gitmessage-config.ts","../src/commands/husky.ts","../src/lib/husky-config.ts","../src/commands/prettier.ts","../src/lib/prettier-config.ts","../src/commands/typescript.ts","../src/lib/typescript-config.ts","../src/const/commands.ts","../src/commands/cursor-rule.ts","../src/lib/check-is-vscode-project.ts","../src/lib/make-cursor-folder.ts","../src/commands/edit.ts","../src/lib/get-open-command.ts","../src/commands/env.ts","../src/commands/init.ts","../src/commands/latest.ts","../src/commands/lighthouse.ts","../src/lib/lighthouse-config.ts","../src/commands/list.ts","../src/lib/color-map.ts","../src/lib/convert-from-objects.ts","../src/lib/table-message.ts","../src/commands/update.ts","../src/commands/vscode-autoprefix.ts","../src/lib/update-vscode-setting.ts","../src/lib/check-vscode-extension-installed.ts","../src/lib/install-vscode-extension.ts"],"sourcesContent":["import { Command } from 'commander';\nimport checkPkgInit from 'lib/check-pkg-init.js';\nimport { getPackageInfo } from 'lib/get-package-info.ts';\nimport { adbRemoteCli } from 'src/commands/adb-remote.ts';\nimport { commitlintCli } from 'src/commands/commitlint.ts';\nimport { cursorRuleCli } from 'src/commands/cursor-rule.ts';\nimport { editCli } from 'src/commands/edit.ts';\nimport { envCli } from 'src/commands/env.ts';\nimport { eslintCli } from 'src/commands/eslint.ts';\nimport { gitmessageCli } from 'src/commands/gitmessage.ts';\nimport { huskyCli } from 'src/commands/husky.ts';\nimport { initCli } from 'src/commands/init.ts';\nimport { latestCli } from 'src/commands/latest.ts';\nimport { lighthouseCli } from 'src/commands/lighthouse.ts';\nimport { listCli } from 'src/commands/list.ts';\nimport { pkgmngCli } from 'src/commands/pkgmng.ts';\nimport { prettierCli } from 'src/commands/prettier.ts';\nimport { typescriptCli } from 'src/commands/typescript.ts';\nimport { updateCli } from 'src/commands/update.ts';\nimport { vsCodeAutoPrefixCli } from 'src/commands/vscode-autoprefix.ts';\n\nprocess.on('SIGINT', () => process.exit(0));\nprocess.on('SIGTERM', () => process.exit(0));\n\nasync function main() {\n const isPkginit = await checkPkgInit();\n if (isPkginit) {\n const packageInfo = await getPackageInfo();\n const program = new Command()\n .name('@in-ch/setup')\n .description('Quick config: Download and apply settings in seconds.')\n .version(`@in-ch/setup v${packageInfo.version || '1.0.0'}`, '-v, --version', 'display the version number');\n program.addCommand(listCli);\n program.addCommand(initCli);\n program.addCommand(eslintCli);\n program.addCommand(prettierCli);\n program.addCommand(editCli);\n program.addCommand(typescriptCli);\n program.addCommand(gitmessageCli);\n program.addCommand(huskyCli);\n program.addCommand(commitlintCli);\n program.addCommand(pkgmngCli);\n program.addCommand(lighthouseCli);\n program.addCommand(vsCodeAutoPrefixCli);\n program.addCommand(latestCli);\n program.addCommand(updateCli);\n program.addCommand(envCli);\n program.addCommand(cursorRuleCli);\n program.addCommand(adbRemoteCli);\n program.parse();\n } else {\n console.log('ā No package manager initialized in this directory.');\n console.log('š Run \"npm init\", \"yarn init\", or \"pnpm init\" to set up a project.');\n }\n}\n\nmain();\n","import fs from 'fs';\nimport path from 'path';\n\n/**\n * @description Check if a package manager is initialized in the given directory.\n * @param {string} [dir=process.cwd()] - Directory to check.\n * @returns {boolean} true if initialized, otherwise false.\n */\nexport default function checkPkgInit(dir = process.cwd()): boolean {\n const packageJson = path.join(dir, 'package.json');\n const yarnLock = path.join(dir, 'yarn.lock');\n const pnpmLock = path.join(dir, 'pnpm-lock.yaml');\n\n return fs.existsSync(packageJson) || fs.existsSync(yarnLock) || fs.existsSync(pnpmLock);\n}\n","import { execSync } from 'child_process';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport fileErrorHandle from 'src/utils/file-error-handle.ts';\n\nexport function getPackageInfo(packageName = '@in-ch/setup') {\n try {\n const globalRoot = execSync('npm root -g', { encoding: 'utf-8' }).trim();\n const packageJsonPath = path.join(globalRoot, packageName, 'package.json');\n if (fs.existsSync(packageJsonPath)) {\n return JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n } else {\n throw new Error('package.json not found');\n }\n } catch (error: unknown) {\n fileErrorHandle(error, 'Failed to get package info');\n return null;\n }\n}\n","const FILE_ERROR = {\n EACCES: 'Permission denied. Try running the command with administrator privileges.',\n ENOENT: 'Directory not found. Ensure you are in the correct project directory.',\n ENOSPC: 'No space left on device. The disk is full. Free up some disk space and try again.',\n UNKNOWN: 'An unexpected file system error occurred.',\n};\n\nexport default FILE_ERROR;\n","import FILE_ERROR from 'src/const/error/error.ts';\n\nexport default function fileErrorHandle(error: unknown, message: string) {\n if (error instanceof Error) {\n console.error(`š„² š„² š„² ${message}`);\n if (FILE_ERROR[error.code as keyof typeof FILE_ERROR]) {\n console.error(`Reason: ${FILE_ERROR[error.code as keyof typeof FILE_ERROR]}`);\n } else {\n console.error(`Reason: ${error.message}`);\n }\n process.exit(1);\n }\n}\n","#!/usr/bin/env node\nimport { exec } from 'child_process';\nimport { Command } from 'commander';\nimport { promisify } from 'util';\n\nconst execAsync = promisify(exec);\n\n/**\n * @description\n * This command will connect to ADB device wirelessly\n */\nexport const adbRemoteCli = new Command()\n .command('adb-remote')\n .description('Connect to ADB device wirelessly')\n .action(async () => {\n try {\n console.log(`Checking connected ADB devices...`);\n\n const { stdout: devicesOutput } = await execAsync('adb devices');\n const devices = devicesOutput\n .split('\\n')\n .filter(line => line.includes('\\tdevice'))\n .map(line => line.split('\\t')[0])\n .filter(device => device?.trim() !== '');\n\n if (devices.length === 0) {\n console.log(`No ADB devices connected. \\nPlease connect a device via USB first.`);\n return;\n }\n\n console.log(`Found ${devices.length} connected device(s):`);\n devices.forEach(device => {\n console.log(` ${device}`);\n });\n\n console.log(`\\nGetting device IP address...`);\n\n const { stdout: ipOutput } = await execAsync('adb shell ip addr show wlan0');\n const ipMatch = ipOutput.match(/inet (\\d+\\.\\d+\\.\\d+\\.\\d+)/);\n\n if (!ipMatch) {\n console.log(`Could not find IP address for wlan0 interface.`);\n return;\n }\n\n const deviceIp = ipMatch[1];\n console.log(`Device IP address: ${deviceIp}`);\n console.log(`\\nEnabling TCP/IP mode on port 5555...`);\n\n await execAsync('adb tcpip 5555');\n console.log(`TCP/IP mode enabled on port 5555`);\n console.log(`\\nConnecting wirelessly...`);\n\n await execAsync(`adb connect ${deviceIp}:5555`);\n console.log(`Successfully connected to ${deviceIp}:5555`);\n console.log(`\\nVerifying wireless connection...`);\n\n const { stdout: finalDevicesOutput } = await execAsync('adb devices');\n console.log(`Current ADB devices:`);\n console.log(finalDevicesOutput);\n\n console.log(`\\n ADB remote connection established successfully!`);\n console.log(`You can now disconnect the USB cable and use ADB wirelessly.`);\n } catch (error) {\n console.error(`Error: ${error instanceof Error ? error.message : 'Unknown error occurred'}`);\n\n if (error instanceof Error && error.message.includes('adb: command not found')) {\n console.log(`Make sure ADB is installed and added to your PATH.`);\n console.log(`You can install it via Android SDK Platform Tools.`);\n }\n }\n });\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { existsSync } from 'fs';\nimport { createConfigFiles, installDependencies } from 'lib/commit-lint-config.ts';\nimport versionCheckAndUpdate from 'lib/version-update.ts';\nimport { husky } from 'src/commands/husky.ts';\nimport { confirm } from '@inquirer/prompts';\n\nexport const commitlintCli = new Command()\n .command('commitlint')\n .alias('cl')\n .description('Setup commit lint')\n .action(async () => commitLint());\nexport const commitLint = async () => {\n await versionCheckAndUpdate();\n\n const isInitHusky = existsSync('.husky');\n if (!isInitHusky) {\n const isInitHusky = await confirm({\n message: 'Husky is not initialized. Would you like to initialize it?',\n });\n if (!isInitHusky) {\n console.log('canceled!');\n return;\n }\n await husky();\n }\n installDependencies();\n createConfigFiles();\n};\n","import { execSync } from 'child_process';\nimport fs from 'fs';\nimport checkIsMonorepo from 'lib/check-is-monorepo.ts';\nimport detectPackageManager from 'lib/detect-package-manger.ts';\nimport getSettingFilePath from 'lib/get-setting-file-path.ts';\nimport path from 'path';\nimport { COMMANDS } from 'src/const/commands.ts';\nimport { packageManagerInstallChoices } from 'src/const/packagesMng.ts';\nimport fileErrorHandle from 'src/utils/file-error-handle.ts';\nimport { select } from '@inquirer/prompts';\n\n/**\n * install dependencies\n * @returns {Promise<void>}\n */\nconst installDependencies = async (): Promise<void> => {\n console.log('\\nInstalling eslint dependencies...\\n');\n try {\n const dependencies = ['@commitlint/config-conventional', '@commitlint/cli', 'lint-staged'];\n let packageMng = detectPackageManager();\n if (packageMng === 'default') {\n console.log(\n 'The package manager could not be detected. \\n\\n1. If this is not the project root, please run the command from the root directory. \\n2. If you have not installed the packages beforehand, please install them first and then try again.\\n\\n'\n );\n if (packageMng === 'default') {\n const answer = await select({\n message: 'Which package manager would you like to use for installation? \\n',\n choices: packageManagerInstallChoices,\n });\n if (answer === 'cancel') {\n return;\n }\n packageMng = answer;\n }\n }\n const installCommand = `${packageMng} ${dependencies.join(' ')}`;\n execSync(`${installCommand} -D ${checkIsMonorepo() ? '-w' : ''}`, { stdio: 'inherit' });\n } catch (error) {\n console.error(\"š„² š„² š„² Failed to install commitlint's dependencies...\");\n process.exit(1);\n }\n};\n\nconst createConfigFiles = (): void => {\n const rootDir = process.cwd();\n const commitlintrcConfig = fs.readFileSync(getSettingFilePath(COMMANDS.COMMIT_LINT), 'utf-8');\n const lintStagedConfig = fs.readFileSync(getSettingFilePath(COMMANDS.LINT_STAGE), 'utf-8');\n try {\n fs.writeFileSync(path.join(rootDir, '.commitlintrc.json'), commitlintrcConfig, 'utf-8');\n fs.writeFileSync(path.join(rootDir, '.lintstagedrc.json'), lintStagedConfig, 'utf-8');\n\n console.log('\\nš Successfully created the Commitlint configuration file.');\n } catch (error: unknown) {\n fileErrorHandle(error, 'Failed to create commitlint.config.json file');\n }\n};\n\nexport { installDependencies, createConfigFiles };\n","import fs from 'fs';\nimport path from 'path';\n\n/**\n * Checks if the given directory is a monorepo workspace.\n * Supports Yarn, pnpm, Lerna, and Bun workspaces.\n *\n * @param {string} [basePath=process.cwd()] - The base path to check.\n * @returns {boolean} true if the directory is a monorepo workspace, false otherwise.\n */\nfunction checkIsMonorepo(basePath: string = process.cwd()): boolean {\n const packageJsonPath = path.join(basePath, 'package.json');\n if (!fs.existsSync(packageJsonPath)) {\n return false;\n }\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n if (packageJson.workspaces) {\n return true;\n }\n const pnpmWorkspacePath = path.join(basePath, 'pnpm-workspace.yaml');\n if (fs.existsSync(pnpmWorkspacePath)) {\n return true;\n }\n const lernaConfigPath = path.join(basePath, 'lerna.json');\n if (fs.existsSync(lernaConfigPath)) {\n return true;\n }\n const bunConfigPath = path.join(basePath, 'bunfig.toml');\n if (fs.existsSync(bunConfigPath)) {\n return true;\n }\n return false;\n}\n\nexport default checkIsMonorepo;\n","import fs from 'fs';\n\n\nexport type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'default';\n\n/**\n * After identifying the package manager being used in the project, return the appropriate installation command.\n * If the package manager cannot be found, it indicates either an unsupported environment or that the location\n * is not the project root.\n * @returns {string} Return install command\n */\nconst detectPackageManager = (): string => {\n const files = fs.readdirSync(process.cwd());\n \n if (files.includes('yarn.lock')) {\n return 'yarn add';\n }\n \n if (files.includes('pnpm-lock.yaml')) {\n return 'pnpm add';\n }\n \n if (files.includes('package-lock.json')) {\n return 'npm install';\n }\n \n return 'default';\n};\n\n/**\n * Detect the package manager type being used in the project.\n * If the package manager cannot be found, it indicates either an unsupported environment or that the location\n * is not the project root.\n * @returns {PackageManager} Return package manager type\n */\nexport const detectPackageManagerType = (): PackageManager => {\n const files = fs.readdirSync(process.cwd());\n \n if (files.includes('yarn.lock')) {\n return 'yarn';\n }\n \n if (files.includes('pnpm-lock.yaml')) {\n return 'pnpm';\n }\n \n if (files.includes('package-lock.json')) {\n return 'npm';\n }\n \n return 'default';\n};\n\nexport default detectPackageManager;\n","import { execSync } from 'child_process';\nimport path from 'path';\n\n/**\n * Get the global path of a given npm package\n * @param {string} packageName Name of the package\n * @returns {string | null} Path to the global package, or null if not found\n */\nexport default function getGlobalPackagePath(packageName: string): string | null {\n try {\n const globalNpmRoot = execSync('npm root -g', { encoding: 'utf8' }).trim();\n const packagePath = path.resolve(globalNpmRoot, packageName);\n return packagePath;\n } catch (error) {\n console.error('Error resolving global package path:', error);\n return null;\n }\n}\n","import getGlobalPackagePath from 'lib/get-global-package-path.ts';\nimport path from 'path';\nimport { extension } from 'src/const/commands.ts';\n\n/**\n * @param {string} file Config file name\n * @description Get config file's path\n * @returns {string} Full path to the config file\n */\nexport default function getSettingFilePath(file: string): string {\n if (!file) {\n throw new Error('File name is required');\n }\n\n const isDevMode = process.env.NODE_ENV === 'development';\n if (isDevMode) {\n return path.resolve(process.cwd(), 'const/config', file) + extension[file];\n } else {\n const globalPath = getGlobalPackagePath('@in-ch/setup');\n if (!globalPath) {\n throw new Error('Could not resolve global path for @in-ch/setup');\n }\n return path.resolve(globalPath, 'const/config', file) + extension[file];\n }\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { ESLINT_CONFIG_FILES } from 'const/config.ts';\nimport { setupEslintConfig } from 'lib/eslint-config.ts';\nimport versionCheckAndUpdate from 'lib/version-update.ts';\nimport { COMMANDS, eslintConfigTypeChoices } from 'src/const/commands.ts';\nimport { confirm, select } from '@inquirer/prompts';\nimport { fileExists } from 'lib/utils.ts';\n\nexport const eslintCli = new Command()\n .command('eslint')\n .alias('es')\n .description('Setup eslint file')\n .action(async () => eslint());\n\nexport const eslint = async () => {\n await versionCheckAndUpdate();\n\n const existingConfigs = ESLINT_CONFIG_FILES.filter(file => fileExists(file));\n \n if (existingConfigs.length > 0) {\n const overwrite = await confirm({\n message: 'At least one ESLint file exists. Do you still want to proceed with the setup?',\n });\n \n if (!overwrite) {\n console.log('canceled!');\n return;\n }\n }\n \n const eslintConfigType = await select({\n message: 'Choose an ESLint configuration type:',\n choices: eslintConfigTypeChoices,\n });\n\n const configTypeMap: Record<string, { type: string; command: string }> = {\n 'airbnb': { type: 'airbnb', command: COMMANDS.AIRBNB },\n 'google': { type: 'google', command: COMMANDS.GOOGLE },\n 'xo': { type: 'xo', command: COMMANDS.XO },\n };\n\n const config = configTypeMap[eslintConfigType] || { type: 'import-sort', command: COMMANDS.ESLINT };\n \n console.log(`Setting up ${config.type} ESLint configuration...`);\n const success = await setupEslintConfig(config.type, config.command);\n \n if (!success) {\n console.error('ā Failed to setup ESLint configuration');\n process.exit(1);\n }\n};\n","/**\n * ESlint Config Type\n */\nexport const ESLINT_CONFIG_TYPES = {\n IMPORT_SORT: 'import-sort',\n AIRBNB: 'airbnb',\n GOOGLE: 'google',\n XO: 'xo',\n} as const;\n\nexport type EslintConfigType = typeof ESLINT_CONFIG_TYPES[keyof typeof ESLINT_CONFIG_TYPES];\n\n/**\n * ESLint Config Type Choices\n */\nexport const eslintConfigTypeChoices = [\n { name: 'Import Sort', value: ESLINT_CONFIG_TYPES.IMPORT_SORT },\n { name: 'Airbnb', value: ESLINT_CONFIG_TYPES.AIRBNB },\n { name: 'Google', value: ESLINT_CONFIG_TYPES.GOOGLE },\n { name: 'XO', value: ESLINT_CONFIG_TYPES.XO },\n];\n\n/**\n * File Extension Mapping\n */\nexport const FILE_EXTENSIONS = {\n eslint: '.js',\n prettier: '.js',\n typescript: '.json',\n gitmessage: '.txt',\n commitlint: '.json',\n lintstage: '.json',\n airbnb: '.js',\n google: '.js',\n xo: '.js',\n} as const;\n\n/**\n * ESLint Config File List\n */\nexport const ESLINT_CONFIG_FILES = [\n '.eslintrc.js',\n '.eslintrc.json',\n '.eslintrc.yaml',\n '.eslintrc.yml',\n '.eslintrc.config.mjs',\n '.eslintrc',\n] as const;\n","import fs from 'fs';\nimport path from 'path';\n\n/**\n * Check if the file exists\n * @param {string} filePath File path\n * @returns {boolean} true or false\n */\nexport const fileExists = (filePath: string): boolean => {\n return fs.existsSync(filePath);\n};\n\n/**\n * Check if the directory exists\n * @param {string} dirPath Directory path\n * @returns {boolean} true or false\n */\nexport const directoryExists = (dirPath: string): boolean => {\n return fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory();\n};\n\n/**\n * Read the file\n * @param {string} filePath File path\n * @param {BufferEncoding} encoding Encoding (default: 'utf-8')\n * @returns {string | null} File content or null\n */\nexport const readFileSafely = (filePath: string, encoding: BufferEncoding = 'utf-8'): string | null => {\n try {\n return fs.readFileSync(filePath, encoding);\n } catch (error) {\n console.warn(`Failed to read file: ${filePath}`, error);\n return null;\n }\n};\n\n/**\n * Write the file\n * @param {string} filePath File path\n * @param {string} content File content\n * @param {BufferEncoding} encoding Encoding (default: 'utf-8')\n * @returns {boolean} true or false\n */\nexport const writeFileSafely = (\n filePath: string, \n content: string, \n encoding: BufferEncoding = 'utf-8'\n): boolean => {\n try {\n const dir = path.dirname(filePath);\n if (!directoryExists(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(filePath, content, encoding);\n return true;\n } catch (error) {\n console.error(`Failed to write file: ${filePath}`, error);\n return false;\n }\n};\n\n/**\n * Normalize the path\n * @param {string} filePath File path\n * @returns {string} Normalized path\n */\nexport const normalizePath = (filePath: string): string => {\n return path.normalize(filePath);\n};\n\n/**\n * Convert to absolute path\n * @param {string} filePath File path\n * @returns {string} Absolute path\n */\nexport const resolvePath = (filePath: string): string => {\n return path.resolve(filePath);\n};\n\n/**\n * Extract the file extension\n * @param {string} filePath File path\n * @returns {string} File extension\n */\nexport const getFileExtension = (filePath: string): string => {\n return path.extname(filePath);\n};\n\n/**\n * Extract the file name\n * @param {string} filePath File path\n * @returns {string} File name\n */\nexport const getFileName = (filePath: string): string => {\n return path.basename(filePath, path.extname(filePath));\n};\n","import { execSync } from 'child_process';\nimport checkIsMonorepo from 'lib/check-is-monorepo.js';\nimport detectPackageManager from 'lib/detect-package-manger.ts';\nimport { packageManagerInstallChoices } from 'src/const/packagesMng.ts';\nimport { select } from '@inquirer/prompts';\n\nexport interface PackageManagerOptions {\n dependencies: string;\n isDev?: boolean;\n workspace?: boolean;\n}\n\n/**\n * Install dependencies through the package manager\n * @param {PackageManagerOptions} options Installation options\n * @returns {Promise<void>}\n */\nexport const installDependencies = async (options: PackageManagerOptions): Promise<void> => {\n const { dependencies, isDev = true, workspace = false } = options;\n\n console.log('\\nInstalling dependencies...\\n');\n\n try {\n let packageMng = detectPackageManager();\n\n if (packageMng === 'default') {\n console.log(\n 'The package manager could not be detected. \\n\\n1. If this is not the project root, please run the command from the root directory. \\n2. If you have not installed the packages beforehand, please install them first and then try again.\\n\\n'\n );\n\n const answer = await select({\n message: 'Which package manager would you like to use for installation? \\n',\n choices: packageManagerInstallChoices,\n });\n\n if (answer === 'cancel') {\n return;\n }\n\n packageMng = answer;\n }\n\n const installCommand = `${packageMng} ${dependencies}`;\n const flags = [isDev ? '-D' : '', workspace && checkIsMonorepo() ? '-w' : ''].filter(Boolean).join(' ');\n\n execSync(`${installCommand} ${flags}`, { stdio: 'inherit' });\n } catch (error) {\n console.error('š„² š„² š„² Failed to install dependencies...');\n throw error;\n }\n};\n\n/**\n * Install ESLint dependencies\n * @param {string} configType ESLint config type\n * @returns {Promise<void>}\n */\nexport const installEslintDependencies = async (configType: string): Promise<void> => {\n const dependencyMap = {\n 'import-sort':\n 'eslint @types/eslint eslint-plugin-jsdoc eslint-plugin-no-for-of-array eslint-plugin-vue @eslint/js typescript-eslint globals',\n airbnb:\n 'eslint eslint-config-airbnb-base eslint-plugin-import @typescript-eslint/parser @typescript-eslint/eslint-plugin',\n google: 'eslint eslint-config-google',\n xo: 'eslint eslint-config-xo',\n };\n\n const dependencies = dependencyMap[configType as keyof typeof dependencyMap] || dependencyMap['import-sort'];\n\n await installDependencies({\n dependencies,\n isDev: true,\n workspace: true,\n });\n};\n","const PACKAGE_MANAGER = {\n NPM: 'npm',\n PNPM: 'pnpm',\n YARN: 'yarn',\n};\nconst PACKAGE_MANAGER_VALUE = {\n NPM: 'npm',\n PNPM: 'pnpm',\n YARN: 'yarn',\n};\nconst PACKAGE_MANAGER_VALUE_INSTALL = {\n NPM: 'npm install',\n PNPM: 'pnpm add',\n YARN: 'yarn add',\n};\ntype PackageManagerTypes = (typeof PACKAGE_MANAGER)[keyof typeof PACKAGE_MANAGER];\n\nconst packageManagerChoices = [\n { name: PACKAGE_MANAGER.NPM, value: PACKAGE_MANAGER_VALUE.NPM },\n { name: PACKAGE_MANAGER.PNPM, value: PACKAGE_MANAGER_VALUE.PNPM },\n { name: PACKAGE_MANAGER.YARN, value: PACKAGE_MANAGER_VALUE.YARN },\n { name: 'cancel', value: 'cancel' },\n];\n\nconst packageManagerInstallChoices = [\n { name: PACKAGE_MANAGER.NPM, value: PACKAGE_MANAGER_VALUE_INSTALL.NPM },\n { name: PACKAGE_MANAGER.PNPM, value: PACKAGE_MANAGER_VALUE_INSTALL.PNPM },\n { name: PACKAGE_MANAGER.YARN, value: PACKAGE_MANAGER_VALUE_INSTALL.YARN },\n { name: 'cancel', value: 'cancel' },\n];\n\nexport { PACKAGE_MANAGER, packageManagerChoices, packageManagerInstallChoices };\nexport type { PackageManagerTypes };\n","import getSettingFilePath from 'lib/get-setting-file-path.ts';\nimport { writeFileSafely } from 'lib/utils.ts';\nimport { installEslintDependencies } from 'lib/package-manager.ts';\n\n/**\n * eslint import sort install dependencies\n * @param {string} command Config Type\n * @returns {boolean} true or false\n */\nconst createConfigFiles = (command: string): boolean => {\n const rootDir = process.cwd();\n const configContent = getSettingFilePath(command);\n \n if (!configContent) {\n console.error('ā Failed to read ESLint configuration template');\n return false;\n }\n \n const configPath = `${rootDir}/eslint.config.mjs`;\n \n if (writeFileSafely(configPath, configContent)) {\n console.log('\\nš Successfully created the ESLint configuration file.');\n return true;\n } else {\n console.error('š„² š„² š„² Failed to setup eslint...');\n return false;\n }\n};\n\n/**\n * Set up ESLint Config \n * @param {string} configType Config Type\n * @param {string} command Command\n * @returns {Promise<boolean>} true or false\n */\nconst setupEslintConfig = async (configType: string, command: string): Promise<boolean> => {\n try {\n await installEslintDependencies(configType);\n return createConfigFiles(command);\n } catch (error) {\n console.error('Failed to setup ESLint configuration:', error);\n return false;\n }\n};\n\nexport {\n createConfigFiles,\n setupEslintConfig,\n};\n","import { execSync } from 'child_process';\nimport checkLatestPkgVersion from 'lib/check-latest-pkg-version.ts';\nimport { getPackageInfo } from 'lib/get-package-info.ts';\nimport { pkgmng } from 'src/commands/pkgmng.ts';\nimport { confirm } from '@inquirer/prompts';\n\nexport function initializePackageManager() {\n try {\n execSync('npm --version');\n } catch {\n pkgmng();\n }\n}\n\nexport default async function versionCheckAndUpdate() {\n initializePackageManager();\n\n const latestVersion = await checkLatestPkgVersion('@in-ch/setup');\n const currentVersion = await getPackageInfo().version;\n\n if (currentVersion !== latestVersion) {\n const isUpdateLatestVersion = await confirm({\n message: `The latest version is ${latestVersion}, but the current version is ${currentVersion}. An update is needed. Would you like to update?`,\n });\n if (isUpdateLatestVersion) {\n execSync('npm install @in-ch/setup@latest -g', { stdio: 'inherit' });\n console.log('Update completed successfully.');\n }\n }\n}\n","import { exec } from 'child_process';\n\n/**\n * @param {string} packageName package name\n * @returns {Promise<string>} latest version of the package\n */\nexport default function checkLatestPkgVersion(packageName: string): Promise<string> {\n return new Promise((resolve, reject) => {\n exec(`npm show ${packageName} version`, (error, stdout, stderr) => {\n if (error) {\n reject(`Error fetching latest version: ${error.message}`);\n return;\n }\n if (stderr) {\n reject(`Error: ${stderr}`);\n return;\n }\n resolve(stdout.trim());\n });\n });\n}\n","#!/usr/bin/env node\nimport { execSync } from 'child_process';\nimport { Command } from 'commander';\nimport { packageManagerChoices } from 'src/const/packagesMng.ts';\nimport { select } from '@inquirer/prompts';\n\nexport const pkgmngCli = new Command()\n .command('pkgmng')\n .alias('pm')\n .description('Initialize package manager')\n .action(async () => pkgmng());\nexport const pkgmng = async () => {\n try {\n const answer = await select({\n message: 'Which package manager would you like to use? \\n',\n choices: packageManagerChoices,\n });\n if (answer === 'cancel') {\n return;\n }\n execSync(`${answer} init`, { stdio: 'inherit' });\n } catch (error) {\n console.error('š„² š„² š„² Failed to init package manager... to\\n', error);\n process.exit(1);\n }\n};\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { existsSync } from 'fs';\nimport { createConfigFiles, initializeGit } from 'lib/gitmessage-config.ts';\nimport versionCheckAndUpdate from 'lib/version-update.ts';\nimport { confirm } from '@inquirer/prompts';\n\nexport const gitmessageCli = new Command()\n .command('gitmessage')\n .alias('gm')\n .description('Setup git message file')\n .action(async () => gitmessage());\nexport const gitmessage = async () => {\n await versionCheckAndUpdate();\n\n const isInitGit = existsSync('.git');\n if (!isInitGit) {\n const isOkInitGit = await confirm({\n message: 'Git is not initialized. Would you like to initialize it?',\n });\n if (!isOkInitGit) {\n console.log('canceled!');\n return;\n }\n await initializeGit();\n }\n createConfigFiles();\n};\n","import { execSync } from 'child_process';\nimport fs from 'fs';\nimport getSettingFilePath from 'lib/get-setting-file-path.ts';\nimport path from 'path';\nimport { COMMANDS } from 'src/const/commands.ts';\nimport fileErrorHandle from 'src/utils/file-error-handle.ts';\n\n/**\n * initialize git\n * @returns {Promise<void>}\n */\nconst initializeGit = async (): Promise<void> => {\n execSync(`git init`, { stdio: 'inherit' });\n};\n\nconst createConfigFiles = (): void => {\n const rootDir = process.cwd();\n const config = fs.readFileSync(getSettingFilePath(COMMANDS.GITMESSAGE), 'utf-8');\n try {\n fs.writeFileSync(path.join(rootDir, '.gitmessage'), config, 'utf-8');\n execSync('git config commit.template .gitmessage');\n execSync('git config init.defaultBranch main');\n console.log('š Successfully created the git message configuration file. š');\n console.log(\n 'You can now write commits following the template using the commit button in your IDE tool or the `git commit` command in the terminal.'\n );\n } catch (error: unknown) {\n fileErrorHandle(error, 'Failed to create git message configuration file');\n }\n};\n\nexport { initializeGit, createConfigFiles };\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { existsSync } from 'fs';\nimport { createConfigHusky, installDependencies, updatePackageJson } from 'lib/husky-config.ts';\nimport versionCheckAndUpdate from 'lib/version-update.ts';\nimport { confirm } from '@inquirer/prompts';\n\nexport const huskyCli = new Command()\n .command('husky')\n .alias('hk')\n .description('Setup husky')\n .action(async () => husky());\n\nexport const husky = async () => {\n await versionCheckAndUpdate();\n\n const huskyConfigFiles = ['.husky'];\n const existingConfigs = huskyConfigFiles.filter(file => existsSync(file));\n if (existingConfigs.length > 0) {\n const overwrite = await confirm({\n message: 'Husky settings are already configured. Do you still want to proceed with the setup?',\n });\n if (!overwrite) {\n console.log('canceled!');\n return;\n }\n }\n await installDependencies();\n await createConfigHusky();\n await updatePackageJson();\n};\n","import { execSync } from 'child_process';\nimport checkIsMonorepo from 'lib/check-is-monorepo.ts';\nimport detectPackageManager from 'lib/detect-package-manger.ts';\nimport path from 'path';\nimport { packageManagerInstallChoices } from 'src/const/packagesMng.ts';\nimport fileErrorHandle from 'src/utils/file-error-handle.ts';\nimport { select } from '@inquirer/prompts';\n\nconst installDependencies = async (): Promise<void> => {\n console.log('\\nInstalling husky dependencies...\\n');\n\n try {\n const dependencies = `husky -D`;\n let packageMng = detectPackageManager();\n if (packageMng === 'default') {\n console.log(\n 'The package manager could not be detected. \\n\\n1. If this is not the project root, please run the command from the root directory. \\n2. If you have not installed the packages beforehand, please install them first and then try again.\\n\\n'\n );\n if (packageMng === 'default') {\n const answer = await select({\n message: 'Which package manager would you like to use for installation? \\n',\n choices: packageManagerInstallChoices,\n });\n if (answer === 'cancel') {\n return;\n }\n packageMng = answer;\n }\n }\n const installCommand = `${packageMng} ${dependencies}`;\n execSync(`${installCommand} -D ${checkIsMonorepo() ? '-w' : ''}`, { stdio: 'inherit' });\n } catch (error) {\n console.error('š„² š„² š„² Failed to install dependencies...');\n process.exit(1);\n }\n};\n\nconst createConfigHusky = async (): Promise<void> => {\n execSync(`npx husky init`, { stdio: 'inherit' });\n};\n\nconst updatePackageJson = async (): Promise<void> => {\n const packageJsonPath = path.resolve(process.cwd(), 'package.json');\n const fs = await import('fs-extra');\n try {\n await fs.access(packageJsonPath);\n } catch (error) {\n console.error('Could not find the package.json file.');\n return;\n }\n\n try {\n const data = await fs.readFile(packageJsonPath, 'utf-8');\n const packageJson = JSON.parse(data);\n\n if (!packageJson.scripts) {\n packageJson.scripts = {};\n }\n\n packageJson.scripts.test = 'echo \"Error: no test specified\" && exit 1';\n\n await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf-8');\n console.log('package.json file updated successfully.');\n } catch (error: unknown) {\n fileErrorHandle(error, 'Failed to update package.json file');\n }\n};\n\nexport { createConfigHusky, installDependencies, updatePackageJson };\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { existsSync } from 'fs';\nimport { createConfigFiles, installDependencies } from 'lib/prettier-config.ts';\nimport versionCheckAndUpdate from 'lib/version-update.ts';\nimport { confirm } from '@inquirer/prompts';\n\nexport const prettierCli = new Command()\n .command('prettier')\n .alias('pt')\n .description('Setup prettier file')\n .action(async () => prettier());\nexport const prettier = async () => {\n await versionCheckAndUpdate();\n\n const prettierConfigFiles = [\n '.prettierrc',\n '.prettierrc.json',\n '.prettierrc.yml',\n '.prettierrc.yaml',\n '.prettierrc.js',\n '.prettierrc.cjs',\n 'prettier.config.js',\n 'prettier.config.cjs',\n ];\n const existingConfigs = prettierConfigFiles.filter(file => existsSync(file));\n if (existingConfigs.length > 0) {\n const overwrite = await confirm({\n message: 'At least one Prettier file exists. Do you still want to proceed with the setup?',\n });\n if (!overwrite) {\n console.log('canceled!');\n return;\n }\n }\n installDependencies();\n createConfigFiles();\n};\n","import { execSync } from 'child_process';\nimport fs from 'fs';\nimport checkIsMonorepo from 'lib/check-is-monorepo.ts';\nimport detectPackageManager from 'lib/detect-package-manger.ts';\nimport getSettingFilePath from 'lib/get-setting-file-path.ts';\nimport path from 'path';\nimport { COMMANDS } from 'src/const/commands.ts';\nimport { packageManagerInstallChoices } from 'src/const/packagesMng.ts';\nimport fileErrorHandle from 'src/utils/file-error-handle.ts';\nimport { select } from '@inquirer/prompts';\n\nconst installDependencies = async (): Promise<void> => {\n console.log('\\nInstalling prettier dependencies...\\n');\n try {\n const dependencies = 'prettier prettier-plugin-sort-re-exports @trivago/prettier-plugin-sort-imports';\n let packageMng = detectPackageManager();\n if (packageMng === 'default') {\n console.log(\n 'The package manager could not be detected. \\n\\n1. If this is not the project root, please run the command from the root directory. \\n2. If you have not installed the packages beforehand, please install them first and then try again.\\n\\n'\n );\n if (packageMng === 'default') {\n const answer = await select({\n message: 'Which package manager would you like to use for installation? \\n',\n choices: packageManagerInstallChoices,\n });\n if (answer === 'cancel') {\n return;\n }\n packageMng = answer;\n }\n }\n const installCommand = `${packageMng} ${dependencies}`;\n execSync(`${installCommand} -D ${checkIsMonorepo() ? '-w' : ''}`, { stdio: 'inherit' });\n } catch (error) {\n console.error('š„² Fail to install prettier dependencies.... to \\n' + error);\n process.exit(1);\n }\n};\n\nconst createConfigFiles = () => {\n const rootDir = process.cwd();\n const prettierConfig = fs.readFileSync(getSettingFilePath(COMMANDS.PRETTIER), 'utf-8');\n const prettierIgnore = `node_modules/\ndist/\nbuild/\ncoverage/\n*.min.js\n*.bundle.js\n*.config.js\n*.cjs\nlogs/\n*.log\n.vscode/\n.DS_Store\n.env\n.env.*\npackage-lock.json\nyarn.lock\npnpm-lock.yaml`;\n\n try {\n fs.writeFileSync(path.join(rootDir, '.prettierrc.cjs'), prettierConfig, 'utf-8');\n fs.writeFileSync(path.join(rootDir, '.prettierignore'), prettierIgnore, 'utf-8');\n console.log('š Prettier configuration file has been created.');\n } catch (error: unknown) {\n fileErrorHandle(error, `Failed to create prettier file}`);\n }\n};\n\nexport { installDependencies, createConfigFiles };\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { existsSync } from 'fs';\nimport { createConfigFiles, installDependencies } from 'lib/typescript-config.ts';\nimport versionCheckAndUpdate from 'lib/version-update.ts';\n\nexport const typescriptCli = new Command()\n .command('typescript')\n .alias('ts')\n .description('Setup typescript file')\n .action(async () => typescript());\nexport const typescript = async () => {\n await versionCheckAndUpdate();\n\n const typescriptConfigFiles = ['.tsconfig.json'];\n const existingConfigs = typescriptConfigFiles.filter(file => existsSync(file));\n if (existingConfigs.length > 0) {\n console.error('At least one Typescript file exists.');\n return;\n }\n installDependencies();\n createConfigFiles();\n};\n","import { execSync } from 'child_process';\nimport checkIsMonorepo from 'lib/check-is-monorepo.ts';\nimport detectPackageManager from 'lib/detect-package-manger.ts';\nimport { packageManagerInstallChoices } from 'src/const/packagesMng.ts';\nimport fileErrorHandle from 'src/utils/file-error-handle.ts';\nimport { select } from '@inquirer/prompts';\n\n/**\n * install dependencies\n * @returns {Promise<void>}\n */\nconst installDependencies = async (): Promise<void> => {\n console.log('\\nInstalling typescript dependencies...\\n');\n try {\n const dependencies = 'typescript @types/node @types/react';\n let packageMng = detectPackageManager();\n if (packageMng === 'default') {\n console.log(\n 'The package manager could not be detected. \\n\\n1. If this is not the project root, please run the command from the root directory. \\n2. If you have not installed the packages beforehand, please install them first and then try again.\\n\\n'\n );\n if (packageMng === 'default') {\n const answer = await select({\n message: 'Which package manager would you like to use for installation? \\n',\n choices: packageManagerInstallChoices,\n });\n if (answer === 'cancel') {\n return;\n }\n packageMng = answer;\n }\n }\n const installCommand = `${packageMng} ${dependencies}`;\n execSync(`${installCommand} -D ${checkIsMonorepo() ? '-w' : ''}`, { stdio: 'inherit' });\n } catch (error) {\n console.error('š„² š„² š„² Failed to install dependencies...');\n process.exit(1);\n }\n};\n\n/**\n * Setup typescript file\n * @returns {void}\n */\nconst createConfigFiles = (): void => {\n try {\n console.log('Configure Typescript');\n execSync(`npx tsc --init`);\n } catch (error: unknown) {\n fileErrorHandle(error, 'Failed to create typescript.config.json file');\n }\n};\n\nexport { installDependencies, createConfigFiles };\n","import { commitLint } from 'src/commands/commitlint.ts';\nimport { eslint } from 'src/commands/eslint.ts';\nimport { gitmessage } from 'src/commands/gitmessage.ts';\nimport { husky } from 'src/commands/husky.ts';\nimport { prettier } from 'src/commands/prettier.ts';\nimport { typescript } from 'src/commands/typescript.ts';\n\nconst COMMANDS = {\n ESLINT: 'eslint',\n PRETTIER: 'prettier',\n TYPESCRIPT: 'typescript',\n GITMESSAGE: 'gitmessage',\n HUSKY: 'husky',\n COMMIT_LINT: 'commitlint',\n LINT_STAGE: 'lintstage',\n AIRBNB: 'airbnb',\n GOOGLE: 'google',\n XO: 'xo',\n};\n\nconst filteredCommands = Object.entries(COMMANDS)\n .filter(([key]) => ![COMMANDS.AIRBNB, COMMANDS.GOOGLE, COMMANDS.XO].includes(key.toLowerCase()))\n .map(([key, value]) => ({ name: key, value }));\nconst filteredCommandChoices = filteredCommands.map(command => command.value);\n\ntype CommandsTypes = (typeof COMMANDS)[keyof typeof COMMANDS];\nconst commandFuc = {\n [COMMANDS.ESLINT]: () => eslint(),\n [COMMANDS.PRETTIER]: () => prettier(),\n [COMMANDS.TYPESCRIPT]: () => typescript(),\n [COMMANDS.GITMESSAGE]: () => gitmessage(),\n [COMMANDS.HUSKY]: () => husky(),\n [COMMANDS.COMMIT_LINT]: () => commitLint(),\n};\nconst extension = {\n [COMMANDS.ESLINT]: '.js',\n [COMMANDS.PRETTIER]: '.js',\n [COMMANDS.TYPESCRIPT]: '.json',\n [COMMANDS.GITMESSAGE]: '.txt',\n [COMMANDS.COMMIT_LINT]: '.json',\n [COMMANDS.LINT_STAGE]: '.json',\n [COMMANDS.AIRBNB]: '.js',\n [COMMANDS.GOOGLE]: '.js',\n [COMMANDS.XO]: '.js',\n};\nconst commandChoices = [\n { name: COMMANDS.ESLINT, value: COMMANDS.ESLINT },\n { name: COMMANDS.PRETTIER, value: COMMANDS.PRETTIER },\n { name: COMMANDS.TYPESCRIPT, value: COMMANDS.TYPESCRIPT },\n { name: COMMANDS.GITMESSAGE, value: COMMANDS.GITMESSAGE },\n { name: COMMANDS.HUSKY, value: COMMANDS.HUSKY },\n { name: COMMANDS.COMMIT_LINT, value: COMMANDS.COMMIT_LINT },\n];\nconst eslintConfigTypeChoices = [\n { name: 'Import Sort', value: 'import-sort' },\n { name: 'Airbnb', value: 'airbnb' },\n { name: 'Google', value: 'google' },\n { name: 'XO', value: 'xo' },\n];\n\nconst eslintConfigTypeChoicesValue = eslintConfigTypeChoices.reduce(\n (acc, choice) => {\n acc[choice.value] = choice.value;\n return acc;\n },\n {} as Record<string, string>\n);\n\nexport {\n COMMANDS,\n commandFuc,\n commandChoices,\n extension,\n eslintConfigTypeChoices,\n eslintConfigTypeChoicesValue,\n filteredCommands,\n filteredCommandChoices,\n};\nexport type { CommandsTypes };\n","import { Command } from 'commander';\nimport checkIsVscodeProject from 'lib/check-is-vscode-project.ts';\nimport makeCursorFolder from 'lib/make-cursor-folder.ts';\n\nexport const cursorRuleCli = new Command()\n .name('cursor-rule')\n .alias('cr')\n .description('Setup Cursor AI rules configuration')\n .action(async () => {\n console.log('šÆ Setting up Cursor AI rules...\\n');\n\n if (!checkIsVscodeProject()) {\n console.log('š„² .vscode directory not found\\n');\n console.log('Is this a cursor project?\\n');\n console.log('Please run `ics cursor-rule` in a cursor project\\n');\n return;\n }\n\n const cursorRulesDir = '.cursor/rules';\n const isCursorFolderCreated = await makeCursorFolder(cursorRulesDir);\n if (!isCursorFolderCreated) {\n console.log('š„² Cursor folder not created\\n');\n return;\n }\n });\n","import fs from 'fs';\n\n/**\n * Check if the current directory is a VSCode project\n *\n * @returns {boolean} - True if the current directory is a VSCode project, false otherwise\n */\nexport default function checkIsVscodeProject(): boolean {\n const isVscodeProject = fs.existsSync('.vscode');\n if (!isVscodeProject) {\n console.log('š„² .vscode directory not found');\n return false;\n }\n return true;\n}\n","import * as fs from 'fs-extra';\nimport { confirm } from '@inquirer/prompts';\n\n/**\n * Make a cursor folder\n *\n * @param {string} dir - The directory to make\n * @returns {Promise<boolean>} - True if the directory was created, false otherwise\n */\nexport default async function makeCursorFolder(dir: string): Promise<boolean> {\n const cursorRulesDir = '.cursor/rules';\n const dirExists = await fs.pathExists(cursorRulesDir);\n\n if (!dirExists) {\n const createDir = await confirm({\n message: `Directory ${dir} does not exist. Create it?`,\n default: true,\n });\n\n if (createDir) {\n await fs.ensureDir(cursorRulesDir);\n console.log(`ā
Created directory: ${cursorRulesDir}`);\n } else {\n return false;\n }\n }\n return true;\n}\n","import { exec } from 'child_process';\nimport { Command } from 'commander';\nimport getOpenCommand from 'lib/get-open-command.ts';\nimport getSettingFilePath from 'lib/get-setting-file-path.ts';\nimport versionCheckAndUpdate from 'lib/version-update.ts';\nimport { commandChoices, CommandsTypes } from 'src/const/commands.ts';\nimport { select } from '@inquirer/prompts';\n\nexport const editCli = new Command()\n .command('edit')\n .description('edit config file')\n .action(async () => {\n await versionCheckAndUpdate();\n\n const file: CommandsTypes = await select({\n message: 'What do you want to edit config file.',\n choices: commandChoices,\n });\n const path = getSettingFilePath(file);\n const command = getOpenCommand(path);\n exec(command, err => {\n if (err) {\n console.error('Failed to open file or folder:', err);\n } else {\n console.log(`Opened: ${path}`);\n }\n });\n });\n","import { execSync } from 'child_process';\nimport os from 'os';\n\n/**\n * @param {string} program program name\n *\n * @description Checks if the program specified as a parameter is installed.\n * @returns {boolean} Returns true if the specified program is installed, false otherwise.\n */\nconst isProgramAvailable = (program: string): boolean => {\n try {\n execSync(`which ${program}`, { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n};\n\n/**\n * @param {string} filepath File path\n * @description Get a command to open a file in VS Code or the default text editor, depending on the OS and availability\n * @returns {string} Command to open the file\n */\nexport default function getOpenCommand(filepath: string): string {\n const platform = os.platform();\n let command;\n\n if (platform === 'win32') {\n command = `start \"\" \"notepad\" \"${filepath}\"`;\n } else if (platform === 'darwin') {\n if (isProgramAvailable('code')) {\n command = `open -a \"Visual Studio Code\" \"${filepath}\"`;\n } else {\n command = `open -a \"TextEdit\" \"${filepath}\"`;\n }\n } else if (platform === 'linux') {\n if (isProgramAvailable('code')) {\n command = `code \"${filepath}\"`;\n } else {\n command = `xdg-open \"${filepath}\"`;\n }\n } else {\n console.error('Unsupported platform');\n return '';\n }\n return command;\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport fs, { existsSync } from 'fs';\nimport versionCheckAndUpdate from 'lib/version-update.js';\nimport path from 'path';\nimport { confirm, input } from '@inquirer/prompts';\n\nexport const envCli = new Command()\n .command('env')\n .description('create .env file')\n .action(async () => {\n await versionCheckAndUpdate();\n\n const envConfigFile = ['.env'];\n const existingEnv: string[] = envConfigFile.filter(file => existsSync(file));\n\n if (existingEnv.length > 0) {\n console.log('At least one env file exists.');\n } else {\n try {\n const rootDir = process.cwd();\n const envFilePath = path.join(rootDir, '.env');\n\n fs.writeFileSync(envFilePath, '', 'utf-8');\n console.log('Created .env file successfully');\n\n const addKeyValuePair = async () => {\n const response = await confirm({\n message: 'Would you like to add a key to the .env file?',\n });\n\n if (response) {\n const key = await input({\n message: 'Enter the key:',\n default: '',\n });\n\n const value = await input({\n message: 'Enter the value:',\n default: '',\n });\n\n const envContent = `${key}=${value}\\n`;\n fs.appendFileSync(envFilePath, envContent, 'utf-8');\n console.log(`Added ${key}=${value} to .env`);\n\n addKeyValuePair();\n } else {\n console.log('Finished adding key-value pairs.');\n }\n };\n addKeyValueP