@nemo-cli/git 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["HELP_MESSAGE","formatBranch","HELP_MESSAGE","commitTypeOption","commitScopeOption","HELP_MESSAGE"],"sources":["../src/constants/index.ts","../src/utils.ts","../src/commands/branch.ts","../src/commands/checkout.ts","../src/commands/commit-options.ts","../src/commands/push.ts","../src/commands/commit.ts","../src/commands/diff.ts","../src/commands/list.ts","../src/commands/merge.ts","../src/commands/pull.ts","../src/constants/stash.ts","../src/commands/stash.ts","../src/index.ts"],"sourcesContent":["import { createHelpExample } from '@nemo-cli/shared'\n\nexport const HELP_MESSAGE = {\n main: createHelpExample('ng --version', 'ng --help', 'ng <command> [option]'),\n branch: createHelpExample('ng branch --version', 'ng branch --help', 'ng branch <command> [option]'),\n branchDelete: createHelpExample(\n 'ng branch delete --version',\n 'ng branch delete --help',\n 'ng branch delete <command> [option]'\n ),\n branchClean: createHelpExample('ng branch clean --version', 'ng branch clean --help'),\n}\n","import { spawn } from 'node:child_process'\nimport { unlinkSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\n\nimport {\n colors,\n createConfirm,\n createNote,\n createSpinner,\n getCurrentBranch,\n handleError,\n log,\n x,\n xASync,\n} from '@nemo-cli/shared'\n\nconst remotePrefix = /^origin\\//\n\n// creatordate committerdate authordate\nexport const getRemoteBranches = async (): Promise<{ branches: string[] }> => {\n const originBranches = await x('git', ['branch', '-r', '--sort=-committerdate'])\n const branches = originBranches.stdout\n .split('\\n')\n .filter((line) => line.trim() && !line.includes('->'))\n .map((line) => line.trim().replace(remotePrefix, ''))\n\n return { branches }\n}\n\nconst currentBranchPrefix = /^\\* /\nconst formatBranch = (branch?: string) => branch?.trim().replace(currentBranchPrefix, '')\n\nexport const getLocalBranches = async (): Promise<{ branches: string[]; currentBranch: string | undefined }> => {\n const originBranches = await x('git', ['branch', '--sort=-committerdate'])\n const list = originBranches.stdout.split('\\n')\n const currentBranch = list.find((line) => line.includes('*'))\n\n const branches = list\n .filter((line) => line.trim() && !line.includes('->'))\n .map((line) => line.trim().replace(currentBranchPrefix, ''))\n\n return {\n branches,\n currentBranch: formatBranch(currentBranch),\n }\n}\n\nexport const getRemoteOptions = async () => {\n const { branches } = await getRemoteBranches()\n const currentBranch = await getCurrentBranch()\n const options = branches.map((branch) => ({\n label: branch,\n value: branch,\n hint: branch === currentBranch ? 'current branch' : undefined,\n }))\n return {\n options,\n currentBranch,\n } as const\n}\n\nexport const getLocalOptions = async () => {\n const { branches, currentBranch } = await getLocalBranches()\n const options = branches.map((branch) => ({\n label: branch,\n value: branch,\n hint: branch === currentBranch ? 'current branch' : undefined,\n }))\n return {\n options,\n currentBranch,\n } as const\n}\n\nexport const getGitDiffFiles = async (branch: string) => {\n const [error, result] = await xASync('git', ['diff', branch, '--name-only'])\n if (error) return []\n return result.stdout.split('\\n').filter((line) => line.trim())\n}\n\n/**\n * 处理合并提交信息\n */\nconst handleMergeCommit = async () => {\n try {\n // 检查是否有待提交的合并\n const [error, result] = await xASync('git', ['status', '--porcelain'])\n if (error) return\n const statusOutput = result.stdout\n const hasUncommittedChanges = statusOutput.trim().length > 0\n\n if (!hasUncommittedChanges) {\n return\n }\n\n log.show('\\n📝 Merge commit detected. You can customize the commit message.', { type: 'info' })\n\n const shouldCustomize = await createConfirm({\n message: 'Do you want to customize the merge commit message?',\n })\n\n if (!shouldCustomize) {\n // 使用默认的合并提交信息\n await xASync('git', ['commit', '--no-edit'])\n log.show('Using default merge commit message.', { type: 'info' })\n return\n }\n\n // 获取默认的合并提交信息\n const [processError, processResult] = await xASync('git', ['log', '--format=%B', '-n', '1', 'HEAD'])\n if (processError) return\n const defaultMessage = processResult.stdout\n\n // 创建临时文件用于编辑\n const tempFile = join(tmpdir(), `merge-commit-${Date.now()}.txt`)\n writeFileSync(tempFile, defaultMessage)\n\n // 打开编辑器让用户编辑\n const editor = process.env.EDITOR || process.env.VISUAL || 'vim'\n\n log.show(`Opening ${editor} to edit commit message...`, { type: 'info' })\n log.show('Save and close the editor to continue, or close without saving to cancel.', { type: 'info' })\n\n const editProcess = spawn(editor, [tempFile], {\n stdio: 'inherit',\n shell: true,\n })\n\n const editExitCode = await new Promise<number>((resolve) => {\n editProcess.on('close', (code) => {\n resolve(code || 0)\n })\n })\n\n if (editExitCode !== 0) {\n log.show('Editor was closed without saving. Using default commit message.', { type: 'warn' })\n await xASync('git', ['commit', '--no-edit'])\n unlinkSync(tempFile)\n return\n }\n\n // 读取编辑后的提交信息\n const { readFileSync } = await import('node:fs')\n const editedMessage = readFileSync(tempFile, 'utf-8')\n unlinkSync(tempFile)\n\n if (!editedMessage.trim()) {\n log.show('Commit message is empty. Using default commit message.', { type: 'warn' })\n await xASync('git', ['commit', '--no-edit'])\n return\n }\n\n // 使用编辑后的提交信息进行提交\n const commitProcess = spawn('git', ['commit', '-F', '-'], {\n stdio: ['pipe', 'pipe', 'pipe'],\n shell: true,\n })\n\n commitProcess.stdin?.write(editedMessage)\n commitProcess.stdin?.end()\n\n const commitExitCode = await new Promise<number>((resolve) => {\n commitProcess.on('close', (code) => {\n resolve(code || 0)\n })\n })\n\n if (commitExitCode === 0) {\n log.show('Merge commit completed with custom message.', { type: 'success' })\n } else {\n throw new Error('Failed to create merge commit with custom message')\n }\n } catch (error) {\n log.show('Error handling merge commit:', { type: 'error' })\n log.error(error)\n\n // 如果出错,尝试使用默认提交\n try {\n await xASync('git', ['commit', '--no-edit'])\n log.show('Fallback: Using default merge commit message.', { type: 'info' })\n } catch (fallbackError) {\n log.show('Failed to create merge commit. Please handle manually.', { type: 'error' })\n throw fallbackError\n }\n }\n}\n\nexport type PullOptions = {\n rebase?: boolean\n}\n\nexport const handleGitPull = async (branch: string, options: PullOptions = {}) => {\n const { rebase = false } = options\n const modeText = rebase ? 'rebase' : 'merge'\n log.show(`Pulling from remote (${modeText} mode)...`, { type: 'step' })\n\n try {\n // 构建 git pull 命令参数\n const args = rebase ? ['pull', '--rebase', 'origin', branch] : ['pull', 'origin', branch]\n\n const [error, result] = await xASync('git', args, {\n nodeOptions: {\n stdio: 'inherit',\n },\n })\n if (error) {\n log.show(`Failed to pull from remote. Command exited with code ${error.message}.`, { type: 'error' })\n return\n }\n\n if (!rebase && (result.stdout.includes('Merge branch') || result.stdout.includes('Merge made by'))) {\n // 仅在 merge 模式下检查合并提交\n await handleMergeCommit()\n }\n\n log.show(`Successfully pulled from remote: ${colors.bgGreen(branch)} (${modeText})`, { type: 'success' })\n } catch (error) {\n log.error(error)\n return\n }\n}\nexport const _handleGitPull = async (branch: string, _stash = false) => {\n const spinner = createSpinner('Pulling from remote')\n try {\n // 使用 stdio: 'inherit' 来支持交互式操作\n const process = spawn('git', ['pull', 'origin', branch], {\n stdio: ['inherit', 'pipe', 'pipe'],\n shell: true,\n })\n\n let stdout = ''\n let stderr = ''\n\n process.stdout?.on('data', (data) => {\n const output = data.toString()\n stdout += output\n log.show(output)\n spinner.message(output)\n })\n\n process.stderr?.on('data', (data) => {\n const output = data.toString()\n stderr += output\n log.show(output, { type: 'warn' })\n })\n\n const exitCode = await new Promise<number>((resolve) => {\n process.on('close', (code) => {\n resolve(code || 0)\n })\n })\n\n if (exitCode) {\n log.show(`Failed to pull from remote. Command exited with code ${exitCode}.`, { type: 'error' })\n spinner.stop('Pull failed')\n throw new Error(stderr)\n }\n\n if (stdout.includes('Merge branch') || stdout.includes('Merge made by')) {\n // 检查是否有合并提交信息需要处理\n await handleMergeCommit()\n }\n\n spinner.stop(colors.green(`Successfully pulled from remote: ${colors.bgGreen(branch)}`))\n } catch (error) {\n spinner.stop('Pull failed')\n log.error(error)\n throw error\n }\n}\n\nconst createStashName = () => `NEMO-CLI-STASH:${Date.now()}`\nexport const handleGitStash = async (name: string = createStashName()): Promise<null | string> => {\n const [error, result] = await xASync('git', ['stash', 'save', name])\n if (error) {\n log.show(`Failed to stash changes. ${name}`, { type: 'error' })\n return null\n }\n if (result?.stdout.includes(name)) {\n log.show(`Successfully stashed changes. ${name}`, { type: 'success' })\n return name\n }\n log.show('No file changes.')\n return null\n}\n\nexport const handleGitStashCheck = async (): Promise<string[]> => {\n const [error, result] = await xASync('git', ['stash', 'list'])\n if (error) return []\n return result.stdout.split('\\n').filter((line) => line.trim())\n}\n\nexport const handleGitPop = async (branch: string) => {\n const stashes = await handleGitStashCheck()\n const stashName = stashes.find((stash) => stash.includes(branch))\n if (!stashName) {\n log.show(`No stash found for this branch: ${colors.bgRed(branch)}.`, { type: 'warn' })\n return\n }\n const name = stashName.split(':')[0]\n if (!name) {\n log.error(name, 'is not valid')\n return\n }\n const [error, result] = await xASync('git', ['stash', 'pop', name])\n if (!error) {\n createNote({ message: result.stdout, title: 'Successfully popped changes.' })\n }\n}\n\n/**\n * Check if a branch has been merged into remote main branch\n * @param branch - The branch name to check\n * @returns Promise<boolean> - true if merged, false if not merged\n */\nexport type BranchInfo = { isMerged: boolean; branch: string }\nexport const isBranchMergedToMain = async (branches: string[]): Promise<BranchInfo[]> => {\n const spinner = createSpinner('Fetching latest changes from remote')\n const [fetchError] = await xASync('git', ['fetch', 'origin', '--prune'])\n if (fetchError) {\n spinner.stop('Failed to fetch latest changes from remote. Proceeding with local information.')\n } else {\n spinner.stop('Fetching latest changes from remote Done')\n }\n\n // const [error, result] = await xASync('git', ['branch', '--merged', 'origin/main'])\n const remoteMainBranch = await getRemoteMainBranch()\n\n if (!remoteMainBranch) return []\n return Promise.all<BranchInfo>(\n branches.map(async (branch) => {\n const [error, result] = await xASync('git', ['log', `${remoteMainBranch}..${branch}`], { quiet: true })\n if (error) return { branch, isMerged: false }\n // const [_, result] = await xASync('git', ['merge-base', '--is-ancestor', branch, remoteMainBranch], {\n // quiet: true,\n // })\n return { branch, isMerged: !result?.stdout.trim() }\n })\n )\n}\n\nexport const getGitRoot = async () => {\n const [error, result] = await xASync('git', ['rev-parse', '--show-toplevel'])\n if (error) return ''\n return result.stdout.trim()\n}\nexport const checkGitRepository = async () => {\n try {\n const [error, result] = await xASync('git', ['rev-parse', '--is-inside-work-tree'], { quiet: true })\n if (error) return false\n const output = result.stdout.trim()\n return output === 'true'\n } catch (err) {\n return false\n }\n}\n\nexport const getRemoteMainBranch = async () => {\n const [error, result] = await xASync('git', ['symbolic-ref', 'refs/remotes/origin/HEAD'])\n if (error) return null\n const branches = result.stdout.trim().split('/')\n return branches.splice(2).join('/')\n}\n\nexport const guessLocalMainBranch = async () => {\n try {\n // 获取所有本地分支列表\n const [error, result] = await xASync('git', ['branch', '--list'])\n if (error) return null\n const branches = result.stdout.trim().split('\\n')\n if (branches.includes('main')) {\n return 'main'\n }\n if (branches.includes('master')) {\n return 'master'\n }\n return null\n } catch (error) {\n handleError(error, 'Failed to guess local main branch')\n return null\n }\n}\n\nexport const getBranchCommitTime = async (branch: string) => {\n const [_, result] = await xASync('git', ['show', '--format=%at', `${branch}`])\n return result?.stdout.split('\\n')[0] ?? Date.now()\n}\n","import {\n type Command,\n colors,\n createCheckbox,\n createConfirm,\n createNote,\n createSelect,\n createSpinner,\n log,\n type Result,\n x,\n} from '@nemo-cli/shared'\nimport { ErrorMessage, Message } from '@nemo-cli/ui'\nimport { HELP_MESSAGE } from '../constants'\nimport {\n type BranchInfo,\n getBranchCommitTime,\n getLocalBranches,\n getRemoteBranches,\n isBranchMergedToMain,\n} from '../utils'\n\nconst formatTime = (time: number) => new Date(time * 1000).toLocaleString()\nconst formatBranch = (branch: string) => (branch.startsWith('origin/') ? branch.slice(7) : branch)\n\nconst handleDelete = async (branch: BranchInfo, { isRemote }: { isRemote: boolean }) => {\n if (!branch.isMerged) {\n const confirm = await createConfirm({\n message: `Branch ${branch.branch} is not merged to main. Are you sure you want to delete it?`,\n })\n if (!confirm) return\n }\n\n const spinner = createSpinner(`Deleting branch ${branch.branch}...`)\n const process: Result = x(\n 'git',\n isRemote ? ['push', 'origin', '--delete', formatBranch(branch.branch)] : ['branch', '-D', branch.branch]\n )\n\n for await (const line of process) {\n spinner.message(line)\n }\n\n const code = process.exitCode\n if (code) {\n spinner.stop(`Failed to delete branch ${branch}. Command exited with code ${process.exitCode}.`)\n } else {\n spinner.stop(`Successfully deleted branch ${branch.branch}`)\n }\n}\n\nconst excludeBranch = ['main', 'master', 'develop']\nconst oneDay = 60 * 60 * 24 // 秒\nexport function branchCommand(command: Command) {\n const subCommand = command\n .command('branch')\n .description('Git branch management')\n .addHelpText('after', HELP_MESSAGE.branch)\n\n subCommand\n .command('clean')\n .description('Git branch clean merged to main')\n .addHelpText('after', HELP_MESSAGE.branchClean)\n .action(async () => {\n // 1. 选择时间范围: 1个月, 1年, 3个月\n const timeRange = await createSelect({\n message: 'Select the time range',\n options: [\n { label: 'all', value: 0 },\n { label: '1 month', value: oneDay * 30 },\n { label: '1 year', value: oneDay * 365 },\n { label: '3 months', value: oneDay * 90 },\n ],\n })\n // 2. 获得所有已经合并的分支\n const { branches } = await getLocalBranches()\n const mergeInfoList: BranchInfo[] = await isBranchMergedToMain(\n branches.filter((branch) => !excludeBranch.includes(branch))\n )\n // 3. 获取分支最后提交时间, 并过滤掉时间范围内的分支\n const mergedBranches = mergeInfoList.filter((branch) => branch.isMerged).map((branch) => branch.branch)\n\n const lastCommitBranches = await Promise.all(\n mergedBranches.map(async (branch) => {\n const time = await getBranchCommitTime(branch)\n return {\n branch,\n lastCommitTime: Number(time),\n }\n })\n )\n const now = Date.now() / 1000\n const deleteBranches = lastCommitBranches.filter((branch) => now - branch.lastCommitTime >= timeRange)\n if (deleteBranches.length === 0) {\n Message({ text: 'No branches to delete. Please check your git repository.' })\n return\n }\n // 4. 创建提示\n createNote({\n message: `Found ${deleteBranches.length} branches, will delete\\n${deleteBranches.map((branch) => colors.red(branch.branch)).join('\\n')}`,\n title: 'Delete Branches',\n })\n // 5. 确认删除\n const confirm = await createConfirm({ message: 'Are you sure you want to delete these branches?' })\n if (!confirm) return\n // 6. 删除分支\n await Promise.all(\n deleteBranches.map((branch) => handleDelete({ branch: branch.branch, isMerged: true }, { isRemote: false }))\n )\n Message({ text: 'Successfully deleted branches' })\n })\n\n subCommand\n .command('delete')\n .description('Git branch delete')\n .addHelpText('after', HELP_MESSAGE.branchDelete)\n .option('-r, --remote', 'remote branch')\n .action(async (options: { remote?: boolean }) => {\n const { branches } = options.remote ? await getRemoteBranches() : await getLocalBranches()\n if (!branches || branches.length === 0) {\n ErrorMessage({ text: 'No branches found. Please check your git repository.' })\n return\n }\n const mergeInfoList: BranchInfo[] = await isBranchMergedToMain(\n (options.remote ? branches.map((branch) => `origin/${branch}`) : branches).filter(\n (branch) => !excludeBranch.includes(branch)\n )\n )\n\n if (mergeInfoList.length === 0) {\n ErrorMessage({ text: 'No branches to delete. Please check your git repository.' })\n return\n }\n\n const enhancedOptions = await Promise.all(\n mergeInfoList.map(async (branch) => {\n const lastCommitTime = await getBranchCommitTime(branch.branch)\n return {\n label: `${branch.branch} ${branch.isMerged ? colors.green('(merged)') : colors.yellow('(not merged)')}`,\n value: {\n lastCommitTime,\n branch: branch.branch,\n isMerged: branch.isMerged,\n },\n hint: `last commit: ${formatTime(Number(lastCommitTime))}`,\n }\n })\n )\n\n const deleteBranches = await createCheckbox({\n message: 'Select the branch to delete',\n options: enhancedOptions,\n })\n\n if (!deleteBranches.length) {\n log.error('No branch selected. Aborting delete operation.')\n return\n }\n await Promise.all(\n deleteBranches.map((branch) =>\n handleDelete({ branch: branch.branch, isMerged: true }, { isRemote: options.remote ?? false })\n )\n )\n Message({ text: 'Successfully deleted branches' })\n })\n}\n","import type { Command } from '@nemo-cli/shared'\nimport {\n colors,\n createConfirm,\n createInput,\n createOptions,\n createSelect,\n isEmpty,\n isString,\n log,\n x,\n} from '@nemo-cli/shared'\nimport { getLocalOptions, getRemoteOptions, handleGitPop, handleGitStash } from '../utils'\n\nconst handleCheckout = async (\n branch: string,\n { isNew = false, isRemote = false }: { isNew?: boolean; isRemote?: boolean } = {}\n) => {\n const args = ['checkout']\n\n if (isNew || isRemote) {\n args.push('-b')\n }\n\n args.push(branch)\n\n if (isRemote) {\n args.push(`origin/${branch}`)\n }\n\n const stashName = await handleGitStash(branch)\n\n const process = x('git', args)\n\n for await (const line of process) {\n log.show(line)\n }\n\n const { exitCode, stderr } = await process\n if (exitCode) {\n log.show(`Failed to checkout branch ${branch}. Command exited with code ${exitCode}.`, { type: 'error' })\n log.show(stderr, { type: 'error' })\n } else {\n log.show(`Successfully checked out branch ${branch}.`, { type: 'success' })\n }\n\n stashName && handleGitPop(stashName)\n}\n\nexport function checkoutCommand(command: Command) {\n command\n .command('checkout')\n .alias('co')\n .option('-l, --local', 'Checkout a local branch', true)\n .option('-r, --remote', 'Checkout a remote branch')\n .option('-b, --branch [branch]', 'Create and checkout a new branch')\n .description('Checkout a branch')\n .action(async (params: { local?: boolean; remote?: boolean; branch?: string | true }) => {\n let isLocal = params.local && !params.remote\n const branch = params.branch\n if (branch) {\n if (isString(branch)) {\n handleCheckout(branch, { isNew: true })\n return\n }\n const branchType = await createSelect({\n message: 'Enter the new branch name:',\n options: createOptions(['feature/PRIME-', 'feature/', 'bugfix/']),\n })\n const branchName = await createInput({\n message: 'Enter the new branch name:',\n validate: (value) => {\n if (!value?.trim()) return 'Branch name is required'\n if (value.length > 15) return 'Branch name must be less than 15 characters'\n },\n })\n handleCheckout(`${branchType}${branchName}`, { isNew: true })\n return\n }\n\n if (isEmpty(params)) {\n isLocal = await createSelect({\n message: 'Select the branch type',\n options: [\n { label: 'Remote', value: false },\n { label: 'Local', value: true },\n ],\n initialValue: true,\n })\n }\n\n if (isLocal) {\n const { options } = await getLocalOptions()\n const selectedBranch = await createSelect({\n message: `Select the ${colors.bgGreen(' local ')} branch to checkout`,\n options,\n })\n handleCheckout(selectedBranch)\n } else {\n const { options } = await getRemoteOptions()\n const selectedBranch = await createSelect({\n message: `Select the ${colors.bgYellow(' remote ')} branch to checkout`,\n options,\n })\n\n const check = await createConfirm({\n message: `Do you want to checkout ${colors.bgRed(selectedBranch)}?`,\n })\n\n if (check) handleCheckout(selectedBranch, { isRemote: true })\n }\n })\n}\n","const commitScopeOptions = [\n {\n value: 'app',\n label: 'app',\n },\n {\n value: 'shared',\n label: 'shared',\n },\n {\n value: 'server',\n label: 'server',\n },\n {\n value: 'tools',\n label: 'tools',\n },\n {\n value: '',\n label: 'none',\n },\n]\nconst commitTypeOptions = [\n {\n value: 'feat',\n label: 'feat',\n hint: 'A new feature',\n emoji: '🌟',\n trailer: 'Changelog: feature',\n },\n {\n value: 'fix',\n label: 'fix',\n hint: 'A bug fix',\n emoji: '🐛',\n trailer: 'Changelog: fix',\n },\n {\n value: 'docs',\n label: 'docs',\n hint: 'Documentation only changes',\n emoji: '📚',\n trailer: 'Changelog: documentation',\n },\n {\n value: 'refactor',\n label: 'refactor',\n hint: 'A code change that neither fixes a bug nor adds a feature',\n emoji: '🔨',\n trailer: 'Changelog: refactor',\n },\n {\n value: 'perf',\n label: 'perf',\n hint: 'A code change that improves performance',\n emoji: '🚀',\n trailer: 'Changelog: performance',\n },\n {\n value: 'test',\n label: 'test',\n hint: 'Adding missing tests or correcting existing tests',\n emoji: '🚨',\n trailer: 'Changelog: test',\n },\n {\n value: 'build',\n label: 'build',\n hint: 'Changes that affect the build system or external dependencies',\n emoji: '🚧',\n trailer: 'Changelog: build',\n },\n {\n value: 'ci',\n label: 'ci',\n hint: 'Changes to our CI configuration files and scripts',\n emoji: '🤖',\n trailer: 'Changelog: ci',\n },\n {\n value: 'chore',\n label: 'chore',\n hint: 'Other changes that do not modify src or test files',\n emoji: '🧹',\n trailer: 'Changelog: chore',\n },\n {\n value: 'revert',\n label: 'revert',\n hint: 'Revert a previous commit',\n emoji: '🔙',\n trailer: 'Changelog: revert',\n },\n {\n value: '',\n label: 'none',\n },\n]\nexport const commitOptions = {\n check_status: true,\n commit_type: {\n enable: true,\n initial_value: 'feat',\n max_items: 20,\n infer_type_from_branch: true,\n append_emoji_to_label: false,\n append_emoji_to_commit: false,\n emoji_commit_position: 'Start',\n options: commitTypeOptions,\n },\n commit_scope: {\n enable: true,\n custom_scope: false,\n max_items: 20,\n initial_value: 'app',\n options: commitScopeOptions,\n },\n check_ticket: {\n infer_ticket: true,\n confirm_ticket: true,\n add_to_title: true,\n append_hashtag: false,\n prepend_hashtag: 'Never',\n surround: '',\n title_position: 'start',\n },\n commit_title: {\n max_size: 70,\n },\n commit_body: {\n enable: true,\n required: false,\n },\n commit_footer: {\n enable: true,\n initial_value: [],\n options: ['closes', 'trailer', 'breaking-change', 'deprecated', 'custom'],\n },\n breaking_change: {\n add_exclamation_to_title: false,\n },\n cache_last_value: true,\n confirm_with_editor: false,\n confirm_commit: true,\n print_commit_output: true,\n branch_pre_commands: [],\n branch_post_commands: [],\n worktree_pre_commands: [],\n worktree_post_commands: [],\n branch_user: {\n enable: true,\n required: false,\n separator: '/',\n },\n branch_type: {\n enable: true,\n separator: '/',\n },\n branch_version: {\n enable: false,\n required: false,\n separator: '/',\n },\n branch_ticket: {\n enable: true,\n required: false,\n separator: '-',\n },\n branch_description: {\n max_length: 70,\n separator: '',\n },\n branch_action_default: 'branch',\n branch_order: ['user', 'version', 'type', 'ticket', 'description'],\n enable_worktrees: true,\n overrides: {},\n}\n\nexport const commitlintConfig = {\n extends: ['@commitlint/config-conventional'],\n rules: {\n 'subject-empty': [2, 'never'], // subject不能为空\n 'type-empty': [2, 'never'], // type不能为空\n 'type-enum': [\n 2,\n 'always',\n ['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'build', 'ci', 'chore', 'revert', 'wip', 'release'],\n ],\n 'scope-empty': [1, 'always'], // scop 可选\n 'scope-enum': [1, 'always', ['app', 'shared', 'server', 'tools', '']],\n },\n}\n\nexport type CommitlintConfigType = typeof commitlintConfig\nexport const mergeCommitTypeEnumOptions = (options: string[]) => {\n // 与 commitTypeOptions 进行对比,如果 options 中存在,则返回 options 中的 value 和 label\n return options.map((option) => {\n const commitTypeOption = commitTypeOptions.find((commitTypeOption) => commitTypeOption.value === option)\n return {\n value: commitTypeOption?.value ?? option,\n label: commitTypeOption?.label ?? option,\n hint: commitTypeOption?.hint,\n emoji: commitTypeOption?.emoji,\n trailer: commitTypeOption?.trailer,\n }\n })\n}\n\nexport const mergeCommitScopeEnumOptions = (options: string[]) => {\n // 与 commitScopeOptions 进行对比,如果 options 中存在,则返回 options 中的 value 和 label\n const result = options.includes('none') ? options : options.concat('none')\n return result.map((option) => {\n const commitScopeOption = commitScopeOptions.find((commitScopeOption) => commitScopeOption.label === option)\n return {\n value: commitScopeOption?.value ?? option,\n label: commitScopeOption?.label ?? option,\n }\n })\n}\n","import type { Command } from '@nemo-cli/shared'\nimport { colors, createConfirm, createSelect, createSpinner, getCurrentBranch, log, x } from '@nemo-cli/shared'\nimport { BigText } from '@nemo-cli/ui'\nimport { getRemoteOptions } from '../utils'\n\nconst handlePush = async (branch: string) => {\n const spinner = createSpinner(`Pushing branch ${branch} to remote...`)\n try {\n const process = x('git', ['push', 'origin', branch])\n for await (const line of process) {\n spinner.message(line)\n }\n\n const code = process.exitCode\n if (code) {\n throw new Error(`Failed code ${code}`)\n }\n spinner.stop(colors.green(`Successfully pushed branch ${colors.bgGreen(branch)} to remote.`))\n } catch (error) {\n spinner.stop()\n BigText({ text: `Failed to push branch ${branch}.` })\n log.error(error)\n }\n}\n\nexport function pushCommand(command: Command) {\n command\n .command('push')\n .alias('ps')\n .description('Push current branch to remote')\n .action(async () => {\n await pushInteractive()\n })\n}\n\nexport const pushInteractive = async () => {\n const currentBranch = await getCurrentBranch()\n if (!currentBranch) {\n log.error('No branch selected. Aborting push operation.')\n return\n }\n const check = await createConfirm({\n message: `Do you want to push ${colors.bgGreen(currentBranch)} to remote?`,\n })\n\n if (check) {\n await handlePush(currentBranch)\n return\n }\n\n const { options } = await getRemoteOptions()\n const selectedBranch = await createSelect({\n message: 'Select the branch to push',\n options,\n initialValue: 'main',\n })\n await handlePush(selectedBranch)\n}\n","import type { LoadConfigResult } from 'unconfig'\n\nimport type { Command } from '@nemo-cli/shared'\nimport {\n addFiles,\n colors,\n createCheckbox,\n createConfirm,\n createInput,\n createNote,\n createOptions,\n createSelect,\n createSpinner,\n exit,\n getCurrentBranch,\n getGitStatus,\n intro,\n loadConfig,\n log,\n outro,\n xASync,\n} from '@nemo-cli/shared'\nimport { ErrorMessage } from '@nemo-cli/ui'\nimport {\n type CommitlintConfigType,\n commitlintConfig,\n mergeCommitScopeEnumOptions,\n mergeCommitTypeEnumOptions,\n} from './commit-options'\nimport { pushInteractive } from './push'\n\nconst lintHandle = async () => {\n const [error, result] = await xASync('lint-staged')\n if (error?.message === 'spawn lint-staged ENOENT') return true\n if (error) return false\n return true\n}\nconst handleCommit = async (message: string) => {\n const spinner = createSpinner('Committing...')\n const [error, _result] = await xASync('git', ['commit', '-m', message])\n if (error) {\n spinner.stop('Failed to commit')\n } else {\n spinner.stop('Committed')\n }\n}\nconst handleLint = async () => {\n const spinner = createSpinner('run lint-staged linting...')\n const lintResult = await lintHandle()\n if (!lintResult) {\n const confirm = await createConfirm({\n message: 'Lint failed. Do you want to continue?',\n initialValue: false,\n })\n !confirm && exit(0)\n }\n spinner.stop('lint-staged done')\n}\n\nexport const commitCommand = (command: Command) => {\n command\n .command('commit')\n .description('Commit a message')\n .action(async () => {\n console.clear()\n const title = colors.bgRed(` ${await getCurrentBranch()} `)\n intro(`${colors.bgCyan(' Current Branch: ')} ${title}`)\n\n // 1. 获取Git状态并展示工作区和暂存区文件\n const { staged, unstaged } = await getGitStatus()\n\n if (staged.length === 0 && unstaged.length === 0) {\n // 如果没有任何文件变更,提示用户\n ErrorMessage({ text: 'No changes detected. Nothing to commit.' })\n exit(0)\n }\n\n // 创建选项对象,用于分组多选\n\n log.show(`Changes to be committed:\\n${staged.map((text) => colors.green(text)).join('\\n')}`, { type: 'success' })\n const selectedStaged = staged\n\n if (unstaged.length > 0) {\n // 工作区文件组(可选择)\n const selectedFiles = await createCheckbox({\n message: 'Select files to stage for commit (optional):',\n options: createOptions(unstaged),\n required: false,\n })\n\n selectedStaged.push(...selectedFiles)\n\n if (selectedFiles.length > 0) {\n // 2. 将选择的工作区文件添加到暂存区\n await addFiles(selectedFiles)\n createNote({\n message: `Added ${selectedFiles.length} unstaged file(s) to staging area.\\n${selectedFiles.map((file) => colors.green(file)).join('\\n')}`,\n title: 'Add Files',\n })\n }\n }\n\n if (selectedStaged.length === 0) {\n ErrorMessage({ text: 'No staged files. Nothing to commit.' })\n exit(0)\n }\n\n await handleLint()\n\n const options: LoadConfigResult<CommitlintConfigType> = await loadConfig({\n sources: [\n {\n files: 'commitlint.config',\n extensions: ['js', 'ts', 'cjs', 'mjs', 'json', ''],\n },\n ],\n })\n\n //3. 获取当前cwd文件夹下 commitlint 文件中的 type-enum 进行选择\n const commitType = await createSelect({\n message: 'Select type:',\n options: mergeCommitTypeEnumOptions((options.config ?? commitlintConfig)!.rules['type-enum'][2] as string[]),\n })\n // 4. 获取当前cwd文件夹下 commitlint 文件中的 scope-enum 进行选择\n const commitScope = await createSelect({\n message: 'Select scope:',\n options: mergeCommitScopeEnumOptions((options.config ?? commitlintConfig)!.rules['scope-enum'][2] as string[]),\n })\n //5. 用户输入 Write a brief title describing the commit , 限制 80个字符\n const commitTitle = await createInput({\n message: 'Write a brief title describing the commit:',\n validate(value) {\n if (!value?.trim()) return 'Title is required'\n if (value.length > 80) return 'Title must be less than 80 characters'\n },\n })\n //6. 用户输入 Write a detailed description of the changes (optional), 无字数限制\n const commitBody = await createInput({\n message: 'Write a detailed description of the changes (optional):',\n })\n const ticket = await getTicket()\n\n const scopeMessage = commitScope ? `(${commitScope})` : ''\n const message = `${commitType}${scopeMessage}: ${ticket} ${commitTitle}\\n${commitBody}`\n const previewMessage = `${colors.blue(commitType)}${colors.green(scopeMessage)}: ${colors.redBright(ticket)} ${commitTitle}\\n${commitBody}`\n createNote({ message: previewMessage, title: 'Commit Message' })\n\n const confirm = await createConfirm({ message: 'Are you sure you want to commit?' })\n\n // 7. 发送 git commit 命令\n if (!confirm) return\n await handleCommit(message)\n\n // 8. 发送 git push 命令\n const confirmPush = await createConfirm({ message: 'Do you want to push to remote?' })\n confirmPush && (await pushInteractive())\n outro(colors.bgGreen(' Git Commit Success '))\n })\n}\n\nexport const REGEX_SLASH_TAG = new RegExp(/\\/(\\w+-\\d+)/)\nexport const REGEX_START_TAG = new RegExp(/^(\\w+-\\d+)/)\nexport const REGEX_START_UND = new RegExp(/^([A-Z]+-[[a-zA-Z\\]\\d]+)_/)\nexport const REGEX_SLASH_UND = new RegExp(/\\/([A-Z]+-[[a-zA-Z\\]\\d]+)_/)\nexport const REGEX_SLASH_NUM = new RegExp(/\\/(\\d+)/)\nexport const REGEX_START_NUM = new RegExp(/^(\\d+)/)\n\nconst getTicket = async () => {\n const branch = await getCurrentBranch()\n const chain = [REGEX_START_UND, REGEX_SLASH_UND, REGEX_SLASH_TAG, REGEX_SLASH_NUM, REGEX_START_TAG, REGEX_START_NUM]\n for (const regex of chain) {\n const match = branch.match(regex)\n if (match) return match[1]\n }\n return branch\n}\n","import { type Command, createOptions, createSelect, getCurrentBranch, log, type Result, x } from '@nemo-cli/shared'\nimport { getLocalBranches, getRemoteBranches } from '../utils'\n\nconst handleDiff = async (branch: string, { isLocal }: { isLocal: boolean }) => {\n console.log('🚀 : handleDiff : branch:', branch, isLocal)\n\n // Get current branch for comparison\n const currentBranch = await getCurrentBranch()\n if (!currentBranch) {\n log.error('Could not determine current branch')\n return\n }\n\n // If selected branch is the same as current, show diff with working directory\n const diffArgs = branch === currentBranch ? ['diff'] : ['diff', `${branch}...${currentBranch}`]\n\n log.show(\n `Showing diff between ${branch === currentBranch ? 'working directory and HEAD' : `${branch} and ${currentBranch}`}`\n )\n\n const process: Result = x('git', diffArgs)\n\n let hasOutput = false\n for await (const line of process) {\n hasOutput = true\n log.show(line)\n }\n\n const { exitCode, stderr } = await process\n\n if (exitCode) {\n log.error(`Failed to diff. Command exited with code ${exitCode}.`)\n if (stderr) {\n log.error(stderr)\n }\n } else if (!hasOutput) {\n log.show('No differences found.', { type: 'info' })\n }\n}\n\nexport function diffCommand(command: Command) {\n command\n .command('diff')\n .alias('di')\n .description('Show differences between branches or working directory')\n .option('-l, --local', 'Diff local branch', true)\n .option('-r, --remote', 'Diff remote branch')\n .action(async (options: { local?: boolean; remote?: boolean }) => {\n const { branches } = options.remote ? await getRemoteBranches() : await getLocalBranches()\n if (!branches || branches.length === 0) {\n log.error('No branches found. Please check your git repository.')\n return\n }\n const selectedBranch = await createSelect({\n message: 'Select the branch to diff',\n options: createOptions(branches),\n })\n if (!selectedBranch) {\n log.error('No branch selected. Aborting diff operation.')\n return\n }\n await handleDiff(selectedBranch, { isLocal: !options.remote })\n })\n}\n","import { type Command, colors, log } from '@nemo-cli/shared'\n\nimport { getLocalBranches, getRemoteBranches } from '../utils'\n\nexport function listCommand(command: Command) {\n command\n .command('list')\n .alias('ls')\n .description('List git branches')\n .option('-l, --local', 'List local branches')\n .option('-r, --remote', 'List remote branches')\n .option('-a, --all', 'List all branches', true)\n .action(async (options: { local?: boolean; remote?: boolean; all?: boolean }) => {\n if (options.all) {\n const { branches: localBranches, currentBranch } = await getLocalBranches()\n const { branches: remoteBranches } = await getRemoteBranches()\n if (!localBranches.length && !remoteBranches.length) {\n log.error('No branches found. Please check your git repository.')\n return\n }\n\n log.show(`Local ${localBranches.length} branches`, { symbol: '🔖', colors: colors.bgGreen })\n for (const branch of localBranches) {\n if (branch === currentBranch) {\n log.show(`${branch} (current)`, { type: 'info' })\n } else {\n log.show(branch, { type: 'step' })\n }\n }\n log.show(`Remote ${remoteBranches.length} branches`, { symbol: '🔖', colors: colors.bgYellow })\n for (const branch of remoteBranches) {\n if (branch === currentBranch) {\n log.show(`${branch} (current)`, { type: 'info' })\n } else {\n log.show(branch, { type: 'step' })\n }\n }\n } else if (options.local) {\n const { branches } = await getLocalBranches()\n if (!branches || branches.length === 0) {\n log.error('No local branches found. Please check your git repository.')\n return\n }\n log.info(`Found ${branches.length} local branches:`)\n for (const branch of branches) {\n log.info(branch)\n }\n } else {\n const { branches } = await getRemoteBranches()\n if (!branches || branches.length === 0) {\n log.error('No remote branches found. Please check your git repository.')\n return\n }\n log.info(`Found ${branches.length} remote branches:`)\n for (const branch of branches) {\n log.info(branch)\n }\n }\n })\n}\n","import type { Command } from '@nemo-cli/shared'\nimport { colors, createConfirm, createSearch, createSelect, createSpinner, isEmpty, xASync } from '@nemo-cli/shared'\n\nimport { getLocalOptions, getRemoteOptions, handleGitPop, handleGitStash } from '../utils'\n\nconst handleMerge = async (branch: string) => {\n const spinner = createSpinner(`Merging branch ${branch}...`)\n const args = ['merge', branch]\n\n const stashName = await handleGitStash()\n\n // 使用 stdio: 'inherit' 来支持交互式合并确认\n const [error] = await xASync('git', args, {\n nodeOptions: {\n stdio: 'inherit',\n },\n })\n if (error) return\n\n spinner.stop(`Successfully merged branch ${branch}.`)\n\n stashName && handleGitPop(stashName)\n}\n\nexport function mergeCommand(command: Command) {\n command\n .command('merge')\n .alias('mg')\n .argument('[branch]', 'The branch to merge')\n .option('-l, --local', 'Merge a local branch')\n .option('-r, --remote', 'Merge a remote branch')\n .option('-b, --branch <branch>', 'Create and merge a new branch')\n .description('Merge a branch')\n .action(async (branch, params: { local?: boolean; remote?: boolean }) => {\n let isLocal = params.local\n\n if (branch) {\n handleMerge(branch)\n return\n }\n\n if (isEmpty(params)) {\n isLocal = await createSelect({\n message: 'Select the branch type',\n options: [\n { label: 'Remote', value: false },\n { label: 'Local', value: true },\n ],\n initialValue: false,\n })\n }\n\n if (isLocal) {\n const { options } = await getLocalOptions()\n const selectedBranch = await createSearch({\n message: 'Select the branch to merge',\n options,\n })\n handleMerge(selectedBranch)\n } else {\n const { options } = await getRemoteOptions()\n const selectedBranch = await createSearch({\n message: 'Select the branch to merge',\n options,\n })\n\n const check = await createConfirm({\n message: `Do you want to merge ${colors.bgRed(selectedBranch)}?`,\n })\n\n if (check) handleMerge(selectedBranch)\n }\n })\n}\n","import { type Command, createSelect, log } from '@nemo-cli/shared'\nimport { getRemoteOptions, handleGitPop, handleGitPull, handleGitStash } from '../utils'\n\nexport function pullCommand(command: Command) {\n command\n .command('pull')\n .alias('pl')\n .description('Pull git branch')\n .option('-r, --rebase', 'Use rebase mode instead of merge')\n .option('-m, --merge', 'Use merge mode (default)')\n .action(async (options: { rebase?: boolean; merge?: boolean }) => {\n const { options: branchOptions, currentBranch } = await getRemoteOptions()\n if (!branchOptions.length) {\n log.error('No branches found. Please check your git repository.')\n return\n }\n\n const selectedBranch = await createSelect({\n message: 'Select the branch to pull',\n options: branchOptions,\n initialValue: currentBranch,\n })\n if (!selectedBranch) {\n log.error('No branch selected. Aborting pull operation.')\n return\n }\n\n // 确定 pull 模式:如果命令行指定了 --rebase 或 --merge,直接使用;否则询问用户\n let useRebase = options.rebase === true\n\n if (!options.rebase && !options.merge) {\n const pullMode = await createSelect({\n message: 'Select pull mode',\n options: [\n { label: 'Merge (default)', value: 'merge', hint: 'git pull origin <branch>' },\n { label: 'Rebase', value: 'rebase', hint: 'git pull --rebase origin <branch>' },\n ],\n initialValue: 'merge',\n })\n useRebase = pullMode === 'rebase'\n }\n\n const stashName = await handleGitStash()\n\n await handleGitPull(selectedBranch, { rebase: useRebase })\n\n stashName && handleGitPop(stashName)\n })\n}\n","import { createHelpExample } from '@nemo-cli/shared'\n\nexport const HELP_MESSAGE = {\n main: createHelpExample(\n 'ng stash',\n 'ng stash save \"work in progress\"',\n 'ng stash ls',\n 'ng stash pop',\n 'ng stash drop'\n ),\n save: createHelpExample('ng stash save \"work in progress\"'),\n list: createHelpExample('ng stash ls'),\n pop: createHelpExample('ng stash pop'),\n drop: createHelpExample('ng stash drop'),\n}\n\nexport const ERROR_MESSAGE = {\n notRootWorkspace: \"It's not workspace root directory, Please open this command in the workspace root directory\",\n}\n","import type { Command } from '@nemo-cli/shared'\nimport { colors, createCheckbox, createOptions, exit, log, xASync } from '@nemo-cli/shared'\nimport { HELP_MESSAGE } from '../constants/stash'\nimport { handleGitStash, handleGitStashCheck } from '../utils'\n\nenum StashCommand {\n POP = 'pop',\n LIST = 'list',\n SAVE = 'save',\n DROP = 'drop',\n}\n\nconst handleCheck =\n <T extends (stashes: string[]) => unknown>(callback: T) =>\n async () => {\n const stashes = await handleGitStashCheck()\n if (stashes.length === 0) {\n log.show('No stash found.', { type: 'error' })\n return\n }\n return callback(stashes)\n }\n\n/**\n * 获取 stash 中的文件列表\n * @param stashRef - stash 引用,如 \"stash@{0}\"\n */\nconst getStashFiles = async (stashRef: string): Promise<string[]> => {\n const [error, result] = await xASync('git', ['stash', 'show', stashRef, '--name-only'], { quiet: true })\n if (error) return []\n return result.stdout.split('\\n').filter((line) => line.trim())\n}\n\n/**\n * 从 stash 条目中提取 stash 引用\n * @param stashEntry - 完整的 stash 条目,如 \"stash@{0}: On main: message\"\n */\nconst extractStashRef = (stashEntry: string): string => {\n const match = stashEntry.match(/^(stash@\\{\\d+\\})/)\n if (match?.[1]) return match[1]\n return stashEntry.split(':')[0] ?? stashEntry\n}\n\nconst handlePop = handleCheck(async (stashes: string[]) => {\n const selectedStashes = await createCheckbox({\n message: 'Select the stash to pop',\n options: stashes.map((stash) => ({ label: stash, value: stash })),\n })\n for await (const stash of selectedStashes) {\n const stashRef = extractStashRef(stash)\n const [error] = await xASync('git', ['stash', 'pop', stashRef])\n if (error) {\n log.show('Failed to pop stash.', { type: 'error' })\n } else {\n log.show('Successfully popped changes.', { type: 'success' })\n }\n }\n})\n\nconst handleList = handleCheck(async (stashes: string[]) => {\n log.show(`\\n${colors.bold(`📦 Found ${stashes.length} stash(es)`)}\\n`)\n\n for await (const stash of stashes) {\n const stashRef = extractStashRef(stash)\n const files = await getStashFiles(stashRef)\n\n // 显示 stash 标题\n log.show(colors.cyan(`━━━ ${stash} ━━━`))\n\n if (files.length > 0) {\n log.show(colors.dim(` ${files.length} file(s) changed:`))\n for (const file of files) {\n log.show(colors.yellow(` • ${file}`))\n }\n } else {\n log.show(colors.dim(' (no files)'))\n }\n log.show('') // 空行分隔\n }\n})\n\nconst handleDrop = handleCheck(async (stashes: string[]) => {\n const selectedStashes = await createCheckbox({\n message: 'Select the stash to clear',\n options: createOptions(stashes),\n })\n\n for await (const stash of selectedStashes) {\n const stashRef = extractStashRef(stash)\n if (!stashRef) {\n log.show('Invalid stash name.', { type: 'error' })\n exit(0)\n }\n\n const [error] = await xASync('git', ['stash', StashCommand.DROP, stashRef])\n if (error) {\n log.show('Failed to drop stash.', { type: 'error' })\n } else {\n log.show(`Successfully dropped stash: ${stashRef}`, { type: 'success' })\n }\n }\n})\n\nconst handleClear = handleCheck(async () => {\n const [error] = await xASync('git', ['stash', 'clear'])\n if (error) {\n log.show('Failed to clear stashes.', { type: 'error' })\n } else {\n log.show('Successfully cleared stashes.', { type: 'success' })\n }\n})\n\nexport const stashCommand = (command: Command) => {\n // 创建主 stash 命令\n const stashCmd = command\n .command('stash')\n .alias('st')\n .description('Git stash management')\n .addHelpText('after', HELP_MESSAGE.main)\n\n // 子命令:保存 stash\n stashCmd\n .command('save [message]')\n .alias('s')\n .description('Save current changes to stash')\n .action(async (message: string) => {\n await handleGitStash(message)\n })\n\n // 子命令:列出 stash\n stashCmd\n .command('list')\n .alias('ls')\n .alias('l')\n .description('List all stashes')\n .action(async () => {\n await handleList()\n })\n\n // 子命令:弹出 stash\n stashCmd\n .command('pop')\n .alias('p')\n .description('Pop the most recent stash')\n .action(async () => {\n await handlePop()\n })\n\n // 子命令:删除 stash\n stashCmd\n .command('drop')\n .alias('d')\n .description('Drop/clear stashes')\n .action(async () => {\n await handleDrop()\n })\n\n stashCmd\n .command('clear')\n .alias('c')\n .description('clear stashes')\n .action(async () => {\n await handleClear()\n })\n\n return stashCmd\n}\n","import { createCommand, exit, readPackage } from '@nemo-cli/shared'\nimport { ErrorMessage } from '@nemo-cli/ui'\n\nimport { branchCommand } from './commands/branch'\nimport { checkoutCommand } from './commands/checkout'\nimport { commitCommand } from './commands/commit'\nimport { diffCommand } from './commands/diff'\nimport { listCommand } from './commands/list'\nimport { mergeCommand } from './commands/merge'\nimport { pullCommand } from './commands/pull'\nimport { pushCommand } from './commands/push'\nimport { stashCommand } from './commands/stash'\nimport { HELP_MESSAGE } from './constants'\nimport { checkGitRepository } from './utils'\n\nexport const pkg = readPackage(import.meta, '..')\n\nexport const init = () => {\n const command = createCommand('ng')\n .version(pkg.version)\n .description(`${pkg.name} CLI helper for git`)\n .addHelpText('after', HELP_MESSAGE.main)\n\n pullCommand(command)\n listCommand(command)\n pushCommand(command)\n checkoutCommand(command)\n branchCommand(command)\n diffCommand(command)\n mergeCommand(command)\n stashCommand(command)\n commitCommand(command)\n\n return command\n}\n\nexport const run = async () => {\n const isGitRepository = await checkGitRepository()\n if (!isGitRepository) {\n ErrorMessage({ text: 'Not a git repository' })\n exit(0)\n }\n\n const command = init()\n command.parse(process.argv)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["HELP_MESSAGE","formatBranch","HELP_MESSAGE","HELP_MESSAGE"],"sources":["../src/commands/blame.ts","../src/constants/index.ts","../src/utils/stash-index.ts","../src/utils.ts","../src/commands/branch.ts","../src/commands/checkout.ts","../src/commands/commit-options.ts","../src/commands/push.ts","../src/commands/commit.ts","../src/commands/config.ts","../src/commands/diff.ts","../src/commands/hist.ts","../src/commands/list.ts","../src/commands/merge.ts","../src/commands/pull.ts","../src/constants/stash.ts","../src/commands/stash.ts","../src/commands/status.ts","../src/index.ts"],"sourcesContent":["import path from 'node:path'\nimport readline from 'node:readline'\n\nimport type { Command } from '@nemo-cli/shared'\nimport { colors, createCheckbox, createInput, exit, log, xASync } from '@nemo-cli/shared'\n\n// Constants\nconst MAX_DIFF_LINES = 50 // Limit to prevent terminal overflow\n\n/**\n * Commit data structure\n */\nexport interface Commit {\n hash: string\n author: string\n date: string\n message: string\n diff: string\n}\n\n/**\n * Registers the 'ng blame' command for viewing file commit history with interactive navigation\n * @param command - The commander Command instance\n * @returns The modified command instance\n */\nexport const blameCommand = (command: Command) => {\n command\n .command('blame [file]')\n .description('View file commit history with interactive navigation')\n .action(async (file?: string) => {\n if (!file) {\n log.show('Please specify a file path.', { type: 'error' })\n return\n }\n\n await handleBlame(file)\n })\n\n return command\n}\n\n// Cache for commits keyed by file path to avoid repeated git log calls\nconst commitCache = new Map<string, Array<Commit>>()\n\n/**\n * Finalizes a commit object from partial data\n * @param currentCommit - Partial commit data\n * @param diffLines - Array of diff lines\n * @returns Complete Commit object or null if invalid\n */\nconst finalizeCommit = (currentCommit: Partial<Commit> | null, diffLines: string[]): Commit | null => {\n if (!currentCommit?.hash || !currentCommit.author || !currentCommit.message) {\n return null\n }\n return {\n hash: currentCommit.hash,\n author: currentCommit.author,\n date: currentCommit.date ?? '',\n message: currentCommit.message,\n diff: diffLines.join('\\n'),\n }\n}\n\nconst handleBlame = async (filePath: string) => {\n // F1: CRITICAL - Resolve and validate path is within current working directory\n const resolvedPath = path.resolve(filePath)\n const cwd = process.cwd()\n\n if (!resolvedPath.startsWith(cwd + path.sep) && resolvedPath !== cwd) {\n log.show('❌ Error: File path must be within current directory', { type: 'error' })\n return\n }\n\n // Check if file exists\n const [statError] = await xASync('test', ['-f', resolvedPath], { quiet: true })\n if (statError) {\n log.show(`❌ Error: File not found: ${filePath}`, { type: 'error' })\n return\n }\n\n // F3: HIGH - Use Map keyed by filePath for proper cache isolation\n if (!commitCache.has(resolvedPath)) {\n const prettyFormat = '%H%x00%an%x00%ad%x00%s'\n const [error, result] = await xASync('git', [\n 'log',\n '--follow',\n '-p',\n `--pretty=format:${prettyFormat}`,\n '--',\n resolvedPath,\n ])\n\n if (error) {\n handleGitError(error, 'git log')\n return\n }\n\n commitCache.set(resolvedPath, parseCommitsFromLog(result.stdout))\n }\n\n const commits = commitCache.get(resolvedPath)!\n\n if (commits.length === 0) {\n log.show(`No git history found for ${filePath}`, { type: 'warn' })\n return\n }\n\n // Show welcome message\n log.show(colors.bold(`Found ${commits.length} commits for ${filePath}`))\n log.show(colors.dim('Use [n/p] to navigate, [j] to jump, [q] to quit'))\n\n await enterInteractiveBlameMode(resolvedPath, commits)\n}\n\n/**\n * Parses git log output into structured Commit objects\n * @param logOutput - Raw git log output with null separators\n * @returns Array of parsed Commit objects\n */\nexport const parseCommitsFromLog = (logOutput: string): Array<Commit> => {\n const commits: Array<Commit> = []\n\n // Git log -p output format:\n // <hash>\\x00<author>\\x00<date>\\x00<message>\n // diff --git a/file b/file\n // ... (diff content)\n // <hash>\\x00<author>\\x00<date>\\x00<message>\n // diff --git a/file b/file\n // ... (diff content)\n\n const lines = logOutput.split('\\n')\n\n let currentCommit: Partial<Commit> | null = null\n let diffLines: string[] = []\n\n for (const line of lines) {\n // Check if this line is a commit header (contains null separators)\n if (line.includes('\\x00')) {\n // F10: LOW - Extract duplicate commit push logic to finalizeCommit helper\n const finalized = finalizeCommit(currentCommit, diffLines)\n if (finalized) {\n commits.push(finalized)\n }\n\n // Parse new commit header\n const [hash, author, date, message] = line.split('\\x00')\n\n // Only start a new commit if we have a valid hash\n if (hash && hash.length >= 8) {\n currentCommit = {\n hash: hash.substring(0, 8),\n author: author?.trim() ?? '',\n date: date?.trim() ?? '',\n message: message?.trim() ?? '',\n }\n diffLines = []\n }\n } else if (currentCommit) {\n // This is diff content for the current commit\n diffLines.push(line)\n }\n }\n\n // Don't forget the last commit\n const finalized = finalizeCommit(currentCommit, diffLines)\n if (finalized) {\n commits.push(finalized)\n }\n\n return commits\n}\n\nconst showCommit = (commit: Commit, index: number, total: number) => {\n // Clear screen before showing commit\n log.clearScreen()\n\n // Show commit header\n log.show(`📝 Commit ${index}/${total}`)\n log.show(`${colors.cyan(commit.hash)} - ${colors.yellow(commit.author)} - ${colors.dim(commit.date)}`)\n log.show(`${commit.message}`)\n log.show(colors.bold('--- Diff ---'))\n\n // Check if binary file\n const isBinary = commit.diff.includes('Binary files differ')\n if (isBinary) {\n log.show('📄 Binary file - diff not available')\n log.show(commit.diff)\n } else {\n // F9: LOW - Extract magic number to constant\n const diffLines = commit.diff.split('\\n')\n if (diffLines.length > MAX_DIFF_LINES) {\n log.show(colors.dim(`(Showing first ${MAX_DIFF_LINES} lines of ${diffLines.length})`))\n log.show(diffLines.slice(0, MAX_DIFF_LINES).join('\\n'))\n log.show(colors.dim('\\n... (truncated)'))\n } else {\n log.show(commit.diff)\n }\n }\n\n // Show navigation hints\n log.show(colors.bold('\\n--- Actions ---'))\n log.show('[n] Next commit [p] Previous commit [j] Jump [q] Quit')\n}\n\nconst enterInteractiveBlameMode = async (filePath: string, commits: Array<Commit>) => {\n if (commits.length === 0) {\n log.show('No commits to display', { type: 'warn' })\n return\n }\n\n let currentIndex = 0\n\n while (true) {\n // Show current commit\n const currentCommit = commits[currentIndex]\n if (!currentCommit) break // Should never happen, but TypeScript needs it\n\n await showCommit(currentCommit, currentIndex + 1, commits.length)\n\n // F4: HIGH - Add error handling for createCheckbox\n let input: string[] | undefined\n try {\n input = await createCheckbox({\n message: 'Enter action:',\n options: [\n {\n label: currentIndex < commits.length - 1 ? 'Next commit' : 'Next commit (already at latest)',\n value: 'n',\n },\n {\n label: currentIndex > 0 ? 'Previous commit' : 'Previous commit (already at earliest)',\n value: 'p',\n },\n { label: 'Jump to commit', value: 'j' },\n { label: 'Quit', value: 'q' },\n ],\n })\n } catch (error) {\n log.show('Error reading input. Exiting...', { type: 'error' })\n return\n }\n\n // F5: MEDIUM - Add safety check for empty input to prevent infinite loop\n if (!input || input.length === 0) {\n log.show('No input received. Exiting...', { type: 'warn' })\n break\n }\n\n // Handle action\n if (input[0] === 'q') {\n exit(0)\n }\n\n if (input[0] === 'n' && currentIndex < commits.length - 1) {\n currentIndex++\n } else if (input[0] === 'p' && currentIndex > 0) {\n currentIndex--\n } else if (input[0] === 'j') {\n // Jump to specific commit\n log.show(`\\nEnter commit number (1-${commits.length}):`)\n const jumpInput = await readUserInput()\n const jumpNum = Number.parseInt(jumpInput, 10)\n\n if (!isNaN(jumpNum) && jumpNum >= 1 && jumpNum <= commits.length) {\n currentIndex = jumpNum - 1\n } else {\n log.show(`Invalid number. Please enter 1-${commits.length}`, { type: 'error' })\n // Brief pause to show error\n await new Promise((resolve) => setTimeout(resolve, 1500))\n }\n }\n }\n}\n\n// F2: CRITICAL - Add proper cleanup on SIGINT to prevent resource leak\nconst readUserInput = (): Promise<string> => {\n return new Promise((resolve) => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n })\n\n const cleanup = () => {\n rl.close()\n rl.removeAllListeners()\n }\n\n rl.on('SIGINT', () => {\n cleanup()\n exit(0)\n })\n\n rl.question('', (answer) => {\n cleanup()\n resolve(answer.trim())\n })\n })\n}\n\nconst handleGitError = (error: Error, context: string) => {\n const errorMessage = error.message || String(error)\n\n if (errorMessage.includes('not a git repository')) {\n log.show('❌ Error: Not in a git repository', { type: 'error' })\n return\n }\n\n if (errorMessage.includes('does not exist') || errorMessage.includes('no such file')) {\n log.show('❌ Error: File not found', { type: 'error' })\n return\n }\n\n log.show(`❌ Error: ${errorMessage}`, { type: 'error' })\n}\n","import { createHelpExample } from '@nemo-cli/shared'\n\nexport const HELP_MESSAGE = {\n main: createHelpExample('ng --version', 'ng --help', 'ng <command> [option]'),\n branch: createHelpExample('ng branch --version', 'ng branch --help', 'ng branch <command> [option]'),\n branchDelete: createHelpExample(\n 'ng branch delete --version',\n 'ng branch delete --help',\n 'ng branch delete <command> [option]'\n ),\n branchClean: createHelpExample('ng branch clean --version', 'ng branch clean --help'),\n}\n","import { mkdir, readFile, rename, writeFile } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\n\nimport { log } from '@nemo-cli/shared'\nimport { getGitRoot } from '../utils'\n\n/**\n * Stash 元数据接口\n */\nexport interface StashMetadata {\n /** Stash 引用,如 \"stash@{0}\" */\n stashRef: string\n /** ISO 8601 格式的时间戳 */\n timestamp: string\n /** ISO 8601 格式的创建时间 */\n createdAt: string\n /** Stash 消息 */\n message: string\n // New optional fields (backward compatible)\n /** 内部唯一标识符 */\n internalId?: string\n /** 触发 stash 的操作类型 */\n operation?: 'pull' | 'checkout' | 'merge' | 'manual'\n /** 创建 stash 时的当前分支 */\n currentBranch?: string\n /** 目标分支 (checkout/merge 操作) */\n targetBranch?: string\n /** stash 包含的文件列表 */\n files?: string[]\n /** stash 状态 */\n status?: 'active' | 'popped' | 'dropped' | 'not_found'\n /** 错误信息 */\n error?: string\n /** stash 对应的 commit hash */\n commitHash?: string\n}\n\n/**\n * Stash 索引数据结构\n * 键为分支名称,值为该分支的 Stash 元数据数组\n */\nexport interface StashIndex {\n [branchName: string]: StashMetadata[]\n}\n\n/**\n * Stash 索引文件路径\n */\nconst STASH_INDEX_FILENAME = 'ng-stash-index.json'\n\n/**\n * 获取 Stash 索引文件的完整路径\n * @returns Stash 索引文件路径,如果不在 Git 仓库中则返回 null\n */\nexport async function getStashIndexPath(): Promise<string | null> {\n const gitRoot = await getGitRoot()\n if (!gitRoot) {\n return null\n }\n return join(gitRoot, '.git', STASH_INDEX_FILENAME)\n}\n\n/**\n * 读取 Stash 索引文件\n * @returns Stash 索引对象,如果文件不存在或读取失败则返回空对象\n */\nexport async function readStashIndex(): Promise<StashIndex> {\n const indexPath = await getStashIndexPath()\n if (!indexPath) {\n log.show('Not in a Git repository. Cannot read stash index.', { type: 'error' })\n return {}\n }\n\n try {\n const content = await readFile(indexPath, 'utf-8')\n const index = JSON.parse(content) as StashIndex\n\n // 验证数据结构\n if (typeof index !== 'object' || index === null || Array.isArray(index)) {\n throw new Error('Invalid stash index format: expected an object')\n }\n\n // 验证每个分支的数据结构\n for (const [branchName, stashes] of Object.entries(index)) {\n if (!Array.isArray(stashes)) {\n throw new Error(`Invalid stash index format: branch \"${branchName}\" should have an array of stashes`)\n }\n\n for (const stash of stashes) {\n if (\n typeof stash.stashRef !== 'string' ||\n typeof stash.timestamp !== 'string' ||\n typeof stash.createdAt !== 'string' ||\n typeof stash.message !== 'string'\n ) {\n throw new Error(\n `Invalid stash index format: stash metadata for branch \"${branchName}\" is missing required fields`\n )\n }\n }\n }\n\n return index\n } catch (error) {\n const err = error as NodeJS.ErrnoException\n\n // 文件不存在时返回空对象(这是正常情况)\n if (err.code === 'ENOENT') {\n return {}\n }\n\n // JSON 解析错误\n if (err instanceof SyntaxError) {\n log.show(`Failed to parse stash index file: ${err.message}. The file may be corrupted.`, { type: 'error' })\n return {}\n }\n\n // 其他错误\n log.show(`Failed to read stash index file: ${err.message}`, { type: 'error' })\n return {}\n }\n}\n\n/**\n * 写入 Stash 索引文件\n * @param index - Stash 索引对象\n * @throws 如果写入失败会抛出错误\n */\nexport async function writeStashIndex(index: StashIndex): Promise<void> {\n const indexPath = await getStashIndexPath()\n if (!indexPath) {\n throw new Error('Not in a Git repository. Cannot write stash index.')\n }\n\n try {\n const dirPath = dirname(indexPath)\n await mkdir(dirPath, { recursive: true })\n\n const content = JSON.stringify(index, null, 2)\n await writeFile(indexPath, content, 'utf-8')\n } catch (error) {\n const err = error as NodeJS.ErrnoException\n log.show(`Failed to write stash index file: ${err.message}`, { type: 'error' })\n throw new Error(`Failed to write stash index: ${err.message}`)\n }\n}\n\n/**\n * 为分支添加 Stash 元数据\n * @param branchName - 分支名称\n * @param metadata - Stash 元数据\n */\nexport async function addStashMetadata(branchName: string, metadata: StashMetadata): Promise<void> {\n const index = await readStashIndex()\n\n // 如果分支不存在,创建空数组\n if (!index[branchName]) {\n index[branchName] = []\n }\n\n // 添加新的 stash 元数据\n index[branchName].push(metadata)\n\n // 写入文件\n await writeStashIndex(index)\n}\n\n/**\n * 获取分支的所有 Stash 元数据\n * @param branchName - 分支名称\n * @returns Stash 元数据数组,如果分支不存在则返回空数组\n */\nexport async function getBranchStashes(branchName: string): Promise<StashMetadata[]> {\n const index = await readStashIndex()\n return index[branchName] ?? []\n}\n\n/**\n * 从索引中移除指定的 Stash 元数据\n * @param branchName - 分支名称\n * @param stashRef - Stash 引用\n */\nexport async function removeStashMetadata(branchName: string, stashRef: string): Promise<void> {\n const index = await readStashIndex()\n\n if (!index[branchName]) {\n return\n }\n\n // 过滤掉指定的 stash\n index[branchName] = index[branchName].filter((stash) => stash.stashRef !== stashRef)\n\n // 如果分支的 stash 数组为空,删除该分支的键\n if (index[branchName].length === 0) {\n delete index[branchName]\n }\n\n // 写入文件\n await writeStashIndex(index)\n}\n\nexport async function addStashMetadataWithDetails(branchName: string, metadata: StashMetadata): Promise<void> {\n const index = await readStashIndex()\n\n if (!index[branchName]) {\n index[branchName] = []\n }\n index[branchName].push(metadata)\n\n const indexPath = await getStashIndexPath()\n if (!indexPath) {\n throw new Error('Not in a Git repository')\n }\n\n const tmpPath = `${indexPath}.tmp.${Date.now()}`\n const dirPath = dirname(indexPath)\n await mkdir(dirPath, { recursive: true })\n await writeFile(tmpPath, JSON.stringify(index, null, 2), 'utf-8')\n\n try {\n await rename(tmpPath, indexPath)\n } catch (renameError) {\n const err = renameError as NodeJS.ErrnoException\n if (err.code === 'EACCES' || err.code === 'EBUSY' || err.code === 'ENOENT') {\n for (let i = 0; i < 3; i++) {\n await new Promise((resolve) => setTimeout(resolve, 100))\n try {\n await rename(tmpPath, indexPath)\n return\n } catch {\n if (i === 2) {\n throw new Error(`Failed to write stash index after 3 retries: ${err.message}`)\n }\n }\n }\n } else {\n throw err\n }\n }\n}\n\nexport async function updateStashStatus(\n branchName: string,\n internalId: string,\n status: 'popped' | 'dropped' | 'not_found',\n error?: string\n): Promise<void> {\n const index = await readStashIndex()\n\n if (!index[branchName]) {\n return\n }\n\n const stash = index[branchName].find((s) => s.internalId === internalId)\n if (!stash) {\n return\n }\n\n stash.status = status\n if (error) {\n stash.error = error\n }\n\n await writeStashIndex(index)\n}\n\nexport async function cleanOldStashes(days = 30): Promise<number> {\n const index = await readStashIndex()\n const cutoffDate = Date.now() - days * 24 * 60 * 60 * 1000\n let count = 0\n\n for (const [branchName, stashes] of Object.entries(index)) {\n const before = stashes.length\n index[branchName] = stashes.filter((stash) => {\n if (stash.status === 'active') {\n return true\n }\n const stashDate = new Date(stash.timestamp).getTime()\n return stashDate >= cutoffDate\n })\n count += before - index[branchName].length\n\n if (index[branchName].length === 0) {\n delete index[branchName]\n }\n }\n\n await writeStashIndex(index)\n return count\n}\n\nexport async function getAllStashes(\n filterStatus?: 'active' | 'popped' | 'dropped' | 'not_found'\n): Promise<StashMetadata[]> {\n const index = await readStashIndex()\n const allStashes: StashMetadata[] = []\n\n for (const stashes of Object.values(index)) {\n allStashes.push(...stashes)\n }\n\n if (filterStatus) {\n return allStashes.filter((s) => s.status === filterStatus)\n }\n\n return allStashes\n}\n\nexport async function findStashByInternalId(\n internalId: string\n): Promise<{ branchName: string; metadata: StashMetadata } | null> {\n const index = await readStashIndex()\n\n for (const [branchName, stashes] of Object.entries(index)) {\n const found = stashes.find((s) => s.internalId === internalId)\n if (found) {\n return { branchName, metadata: found }\n }\n }\n\n return null\n}\n","import { spawn } from 'node:child_process'\nimport { unlinkSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\n\nimport {\n colors,\n createConfirm,\n createNote,\n createSpinner,\n getCurrentBranch,\n handleError,\n log,\n x,\n xASync,\n} from '@nemo-cli/shared'\nimport type { StashMetadata } from './utils/stash-index'\nimport { addStashMetadataWithDetails, updateStashStatus } from './utils/stash-index'\n\nexport { getBranchStashes } from './utils/stash-index'\n\nconst remotePrefix = /^origin\\//\n\nexport const getRemotes = async (): Promise<{ remotes: string[] }> => {\n const [error, result] = await xASync('git', ['remote'])\n if (error) {\n throw new Error(`Failed to get remote repositories: ${error instanceof Error ? error.message : String(error)}`)\n }\n const remotes = result.stdout.split('\\n').filter((line) => line.trim())\n return { remotes }\n}\n\n// creatordate committerdate authordate\nexport const getRemoteBranches = async (): Promise<{ branches: string[] }> => {\n const originBranches = await x('git', ['branch', '-r', '--sort=-committerdate'])\n const branches = originBranches.stdout\n .split('\\n')\n .filter((line) => line.trim() && !line.includes('->'))\n .map((line) => line.trim().replace(remotePrefix, ''))\n\n return { branches }\n}\n\nconst currentBranchPrefix = /^\\* /\nconst formatBranch = (branch?: string) => branch?.trim().replace(currentBranchPrefix, '')\n\nexport const getLocalBranches = async (): Promise<{ branches: string[]; currentBranch: string | undefined }> => {\n const originBranches = await x('git', ['branch', '--sort=-committerdate'])\n const list = originBranches.stdout.split('\\n')\n const currentBranch = list.find((line) => line.includes('*'))\n\n const branches = list\n .filter((line) => line.trim() && !line.includes('->'))\n .map((line) => line.trim().replace(currentBranchPrefix, ''))\n\n return {\n branches,\n currentBranch: formatBranch(currentBranch),\n }\n}\n\nexport const getRemoteOptions = async () => {\n const { branches } = await getRemoteBranches()\n const currentBranch = await getCurrentBranch()\n const options = branches.map((branch) => ({\n label: branch,\n value: branch,\n hint: branch === currentBranch ? 'current branch' : undefined,\n }))\n return {\n options,\n currentBranch,\n } as const\n}\n\nexport const getLocalOptions = async () => {\n const { branches, currentBranch } = await getLocalBranches()\n const options = branches.map((branch) => ({\n label: branch,\n value: branch,\n hint: branch === currentBranch ? 'current branch' : undefined,\n }))\n return {\n options,\n currentBranch,\n } as const\n}\n\nexport const getRemoteOptionsForRemotes = async () => {\n const { remotes } = await getRemotes()\n // Validate and filter out empty/whitespace-only remote names\n const validRemotes = remotes.filter((remote) => remote.trim().length > 0)\n // Remove duplicates while preserving order\n const uniqueRemotes = Array.from(new Set(validRemotes))\n\n const options = uniqueRemotes.map((remote) => ({\n label: remote,\n value: remote,\n }))\n return {\n options,\n remotes: uniqueRemotes,\n } as const\n}\n\nexport const getGitDiffFiles = async (branch: string) => {\n const [error, result] = await xASync('git', ['diff', branch, '--name-only'])\n if (error) return []\n return result.stdout.split('\\n').filter((line) => line.trim())\n}\n\n/**\n * 处理合并提交信息\n */\nconst handleMergeCommit = async () => {\n try {\n // 检查是否有待提交的合并\n const [error, result] = await xASync('git', ['status', '--porcelain'])\n if (error) return\n const statusOutput = result.stdout\n const hasUncommittedChanges = statusOutput.trim().length > 0\n\n if (!hasUncommittedChanges) {\n return\n }\n\n log.show('\\n📝 Merge commit detected. You can customize the commit message.', { type: 'info' })\n\n const shouldCustomize = await createConfirm({\n message: 'Do you want to customize the merge commit message?',\n })\n\n if (!shouldCustomize) {\n // 使用默认的合并提交信息\n await xASync('git', ['commit', '--no-edit'])\n log.show('Using default merge commit message.', { type: 'info' })\n return\n }\n\n // 获取默认的合并提交信息\n const [processError, processResult] = await xASync('git', ['log', '--format=%B', '-n', '1', 'HEAD'])\n if (processError) return\n const defaultMessage = processResult.stdout\n\n // 创建临时文件用于编辑\n const tempFile = join(tmpdir(), `merge-commit-${Date.now()}.txt`)\n writeFileSync(tempFile, defaultMessage)\n\n // 打开编辑器让用户编辑\n const editor = process.env.EDITOR || process.env.VISUAL || 'vim'\n\n log.show(`Opening ${editor} to edit commit message...`, { type: 'info' })\n log.show('Save and close the editor to continue, or close without saving to cancel.', { type: 'info' })\n\n const editProcess = spawn(editor, [tempFile], {\n stdio: 'inherit',\n shell: true,\n })\n\n const editExitCode = await new Promise<number>((resolve) => {\n editProcess.on('close', (code) => {\n resolve(code || 0)\n })\n })\n\n if (editExitCode !== 0) {\n log.show('Editor was closed without saving. Using default commit message.', { type: 'warn' })\n await xASync('git', ['commit', '--no-edit'])\n unlinkSync(tempFile)\n return\n }\n\n // 读取编辑后的提交信息\n const { readFileSync } = await import('node:fs')\n const editedMessage = readFileSync(tempFile, 'utf-8')\n unlinkSync(tempFile)\n\n if (!editedMessage.trim()) {\n log.show('Commit message is empty. Using default commit message.', { type: 'warn' })\n await xASync('git', ['commit', '--no-edit'])\n return\n }\n\n // 使用编辑后的提交信息进行提交\n const commitProcess = spawn('git', ['commit', '-F', '-'], {\n stdio: ['pipe', 'pipe', 'pipe'],\n shell: true,\n })\n\n commitProcess.stdin?.write(editedMessage)\n commitProcess.stdin?.end()\n\n const commitExitCode = await new Promise<number>((resolve) => {\n commitProcess.on('close', (code) => {\n resolve(code || 0)\n })\n })\n\n if (commitExitCode === 0) {\n log.show('Merge commit completed with custom message.', { type: 'success' })\n } else {\n throw new Error('Failed to create merge commit with custom message')\n }\n } catch (error) {\n log.show('Error handling merge commit:', { type: 'error' })\n log.error(error)\n\n // 如果出错,尝试使用默认提交\n try {\n await xASync('git', ['commit', '--no-edit'])\n log.show('Fallback: Using default merge commit message.', { type: 'info' })\n } catch (fallbackError) {\n log.show('Failed to create merge commit. Please handle manually.', { type: 'error' })\n throw fallbackError\n }\n }\n}\n\nexport type PullOptions = {\n rebase?: boolean\n}\n\nexport const handleGitPull = async (branch: string, options: PullOptions = {}) => {\n const { rebase = false } = options\n const modeText = rebase ? 'rebase' : 'merge'\n log.show(`Pulling from remote (${modeText} mode)...`, { type: 'step' })\n\n try {\n // 构建 git pull 命令参数\n const args = rebase ? ['pull', '--rebase', 'origin', branch] : ['pull', 'origin', branch]\n\n const [error, result] = await xASync('git', args, {\n nodeOptions: {\n stdio: 'inherit',\n },\n })\n if (error) {\n log.show(`Failed to pull from remote. Command exited with code ${error.message}.`, { type: 'error' })\n return\n }\n\n if (!rebase && (result.stdout.includes('Merge branch') || result.stdout.includes('Merge made by'))) {\n // 仅在 merge 模式下检查合并提交\n await handleMergeCommit()\n }\n\n log.show(`Successfully pulled from remote: ${colors.bgGreen(branch)} (${modeText})`, { type: 'success' })\n } catch (error) {\n log.error(error)\n return\n }\n}\n\nexport type StashResult = {\n metadata: StashMetadata\n stashName: string\n}\n\nexport const handleGitStash = async (\n message?: string,\n options?: {\n branch?: string\n operation?: 'pull' | 'checkout' | 'merge' | 'manual'\n }\n): Promise<StashResult | null> => {\n const [unstagedError, unstagedResult] = await xASync('git', ['diff', '--name-only'])\n const unstagedFiles = unstagedError ? [] : unstagedResult.stdout.split('\\n').filter(Boolean)\n\n const [stagedError, stagedResult] = await xASync('git', ['diff', '--cached', '--name-only'])\n const stagedFiles = stagedError ? [] : stagedResult.stdout.split('\\n').filter(Boolean)\n\n const [untrackedError, untrackedResult] = await xASync('git', ['ls-files', '--others', '--exclude-standard'])\n const untrackedFiles = untrackedError ? [] : untrackedResult.stdout.split('\\n').filter(Boolean)\n\n const files = [...new Set([...unstagedFiles, ...stagedFiles, ...untrackedFiles])]\n\n if (files.length === 0) {\n log.show('No file changes to stash.')\n return null\n }\n\n const [, commitResult] = await xASync('git', ['rev-parse', 'HEAD'])\n const commitHash = commitResult?.stdout.trim() || ''\n\n const currentBranch = await getCurrentBranch()\n const { branch = undefined, operation = 'manual' } = options || {}\n\n // Generate stash name\n const now = new Date()\n let stashName: string\n if (message && message.trim()) {\n stashName = message.trim()\n } else {\n const formattedTime = now.toISOString().replace(/[:.]/g, '-').slice(0, 19)\n stashName = `${operation}:${currentBranch}@${formattedTime}`\n }\n\n const timestamp = Date.now()\n const encodedBranch = currentBranch.replace(/[/]/g, '_')\n const internalId = `${timestamp}_${operation}_${encodedBranch}`\n\n const [error, result] = await xASync('git', ['stash', 'save', '-u', stashName])\n if (error) {\n log.show(`Failed to stash changes. ${stashName}`, { type: 'error' })\n return null\n }\n\n if (!result?.stdout.includes(stashName)) {\n log.show('No file changes to stash.')\n return null\n }\n\n const stashRefMatch = result.stdout.match(/stash@\\{(\\d+)\\}/)\n const stashRef = stashRefMatch ? stashRefMatch[0] : 'stash@{0}'\n\n const metadata: StashMetadata = {\n stashRef,\n timestamp: now.toISOString(),\n createdAt: now.toISOString(),\n message: stashName,\n internalId,\n operation,\n currentBranch,\n targetBranch: branch,\n files,\n status: 'active',\n commitHash,\n }\n\n await addStashMetadataWithDetails(currentBranch, metadata)\n\n log.show(`Successfully stashed changes. ${stashName}`, { type: 'success' })\n return {\n metadata,\n stashName,\n }\n}\n\nexport const handleGitStashCheck = async (): Promise<string[]> => {\n const [error, result] = await xASync('git', ['stash', 'list'])\n if (error) return []\n return result.stdout.split('\\n').filter((line) => line.trim())\n}\n\nexport const handleGitPop = async (stashOrResult: string | StashResult): Promise<void> => {\n // Handle StashResult input (precise lookup)\n if (typeof stashOrResult !== 'string') {\n const { metadata } = stashOrResult\n\n // Try to pop using stashRef\n const [error, result] = await xASync('git', ['stash', 'pop', metadata.stashRef])\n\n if (error) {\n // Pop failed\n log.show(`Failed to pop stash: ${error.message}`, { type: 'error' })\n if (metadata.internalId && metadata.currentBranch) {\n await updateStashStatus(metadata.currentBranch, metadata.internalId, 'popped', error.message)\n }\n return\n }\n\n // Pop succeeded\n createNote({ message: result.stdout, title: 'Successfully popped changes.' })\n if (metadata.internalId && metadata.currentBranch) {\n await updateStashStatus(metadata.currentBranch, metadata.internalId, 'popped')\n }\n return\n }\n\n // Handle string input (backward compatibility - fuzzy match)\n const branch = stashOrResult\n const stashes = await handleGitStashCheck()\n const stashName = stashes.find((stash) => stash.includes(branch))\n if (!stashName) {\n log.show(`No stash found for this branch: ${colors.bgRed(branch)}.`, { type: 'warn' })\n return\n }\n const name = stashName.split(':')[0]\n if (!name) {\n log.error(name, 'is not valid')\n return\n }\n const [error, result] = await xASync('git', ['stash', 'pop', name])\n if (!error) {\n createNote({ message: result.stdout, title: 'Successfully popped changes.' })\n }\n}\n\n/**\n * Check if a branch has been merged into remote main branch\n * @param branch - The branch name to check\n * @returns Promise<boolean> - true if merged, false if not merged\n */\nexport type BranchInfo = { isMerged: boolean; branch: string }\nexport const isBranchMergedToMain = async (branches: string[]): Promise<BranchInfo[]> => {\n const spinner = createSpinner('Fetching latest changes from remote')\n const [fetchError] = await xASync('git', ['fetch', 'origin', '--prune'])\n if (fetchError) {\n spinner.stop('Failed to fetch latest changes from remote. Proceeding with local information.')\n } else {\n spinner.stop('Fetching latest changes from remote Done')\n }\n\n // const [error, result] = await xASync('git', ['branch', '--merged', 'origin/main'])\n const remoteMainBranch = await getRemoteMainBranch()\n\n if (!remoteMainBranch) return []\n return Promise.all<BranchInfo>(\n branches.map(async (branch) => {\n const [error, result] = await xASync('git', ['log', `${remoteMainBranch}..${branch}`], { quiet: true })\n if (error) return { branch, isMerged: false }\n // const [_, result] = await xASync('git', ['merge-base', '--is-ancestor', branch, remoteMainBranch], {\n // quiet: true,\n // })\n return { branch, isMerged: !result?.stdout.trim() }\n })\n )\n}\n\nexport const getGitRoot = async () => {\n const [error, result] = await xASync('git', ['rev-parse', '--show-toplevel'])\n if (error) return ''\n return result.stdout.trim()\n}\nexport const checkGitRepository = async () => {\n try {\n const [error, result] = await xASync('git', ['rev-parse', '--is-inside-work-tree'], { quiet: true })\n if (error) return false\n const output = result.stdout.trim()\n return output === 'true'\n } catch (_err) {\n return false\n }\n}\n\nexport const getRemoteMainBranch = async () => {\n const [error, result] = await xASync('git', ['symbolic-ref', 'refs/remotes/origin/HEAD'])\n if (error) return null\n const branches = result.stdout.trim().split('/')\n return branches.splice(2).join('/')\n}\n\nexport const guessLocalMainBranch = async () => {\n try {\n // 获取所有本地分支列表\n const [error, result] = await xASync('git', ['branch', '--list'])\n if (error) return null\n const branches = result.stdout.trim().split('\\n')\n if (branches.includes('main')) {\n return 'main'\n }\n if (branches.includes('master')) {\n return 'master'\n }\n return null\n } catch (error) {\n handleError(error, 'Failed to guess local main branch')\n return null\n }\n}\n\nexport const getBranchCommitTime = async (branch: string) => {\n const [_, result] = await xASync('git', ['show', '--format=%at', `${branch}`])\n return result?.stdout.split('\\n')[0] ?? Date.now()\n}\n","import {\n type Command,\n colors,\n createCheckbox,\n createConfirm,\n createNote,\n createSelect,\n createSpinner,\n log,\n type Result,\n x,\n} from '@nemo-cli/shared'\nimport { ErrorMessage, Message } from '@nemo-cli/ui'\nimport { HELP_MESSAGE } from '../constants'\nimport {\n type BranchInfo,\n getBranchCommitTime,\n getLocalBranches,\n getRemoteBranches,\n isBranchMergedToMain,\n} from '../utils'\n\nconst formatTime = (time: number) => new Date(time * 1000).toLocaleString()\nconst formatBranch = (branch: string) => (branch.startsWith('origin/') ? branch.slice(7) : branch)\n\nconst handleDelete = async (branch: BranchInfo, { isRemote }: { isRemote: boolean }) => {\n if (!branch.isMerged) {\n const confirm = await createConfirm({\n message: `Branch ${branch.branch} is not merged to main. Are you sure you want to delete it?`,\n })\n if (!confirm) return\n }\n\n const spinner = createSpinner(`Deleting branch ${branch.branch}...`)\n const process: Result = x(\n 'git',\n isRemote ? ['push', 'origin', '--delete', formatBranch(branch.branch)] : ['branch', '-D', branch.branch]\n )\n\n for await (const line of process) {\n spinner.message(line)\n }\n\n const code = process.exitCode\n if (code) {\n spinner.stop(`Failed to delete branch ${branch}. Command exited with code ${process.exitCode}.`)\n } else {\n spinner.stop(`Successfully deleted branch ${branch.branch}`)\n }\n}\n\nconst excludeBranch = ['main', 'master', 'develop']\nconst oneDay = 60 * 60 * 24 // 秒\nexport function branchCommand(command: Command) {\n const subCommand = command\n .command('branch')\n .description('Git branch management')\n .addHelpText('after', HELP_MESSAGE.branch)\n\n subCommand\n .command('clean')\n .description('Git branch clean merged to main')\n .addHelpText('after', HELP_MESSAGE.branchClean)\n .action(async () => {\n // 1. 选择时间范围: 1个月, 1年, 3个月\n const timeRange = await createSelect({\n message: 'Select the time range',\n options: [\n { label: 'all', value: 0 },\n { label: '1 month', value: oneDay * 30 },\n { label: '1 year', value: oneDay * 365 },\n { label: '3 months', value: oneDay * 90 },\n ],\n })\n // 2. 获得所有已经合并的分支\n const { branches } = await getLocalBranches()\n const mergeInfoList: BranchInfo[] = await isBranchMergedToMain(\n branches.filter((branch) => !excludeBranch.includes(branch))\n )\n // 3. 获取分支最后提交时间, 并过滤掉时间范围内的分支\n const mergedBranches = mergeInfoList.filter((branch) => branch.isMerged).map((branch) => branch.branch)\n\n const lastCommitBranches = await Promise.all(\n mergedBranches.map(async (branch) => {\n const time = await getBranchCommitTime(branch)\n return {\n branch,\n lastCommitTime: Number(time),\n }\n })\n )\n const now = Date.now() / 1000\n const deleteBranches = lastCommitBranches.filter((branch) => now - branch.lastCommitTime >= timeRange)\n if (deleteBranches.length === 0) {\n Message({ text: 'No branches to delete. Please check your git repository.' })\n return\n }\n // 4. 创建提示\n createNote({\n message: `Found ${deleteBranches.length} branches, will delete\\n${deleteBranches.map((branch) => colors.red(branch.branch)).join('\\n')}`,\n title: 'Delete Branches',\n })\n // 5. 确认删除\n const confirm = await createConfirm({ message: 'Are you sure you want to delete these branches?' })\n if (!confirm) return\n // 6. 删除分支\n await Promise.all(\n deleteBranches.map((branch) => handleDelete({ branch: branch.branch, isMerged: true }, { isRemote: false }))\n )\n Message({ text: 'Successfully deleted branches' })\n })\n\n subCommand\n .command('delete')\n .description('Git branch delete')\n .addHelpText('after', HELP_MESSAGE.branchDelete)\n .option('-r, --remote', 'remote branch')\n .action(async (options: { remote?: boolean }) => {\n const { branches } = options.remote ? await getRemoteBranches() : await getLocalBranches()\n if (!branches || branches.length === 0) {\n ErrorMessage({ text: 'No branches found. Please check your git repository.' })\n return\n }\n const mergeInfoList: BranchInfo[] = await isBranchMergedToMain(\n (options.remote ? branches.map((branch) => `origin/${branch}`) : branches).filter(\n (branch) => !excludeBranch.includes(branch)\n )\n )\n\n if (mergeInfoList.length === 0) {\n ErrorMessage({ text: 'No branches to delete. Please check your git repository.' })\n return\n }\n\n const enhancedOptions = await Promise.all(\n mergeInfoList.map(async (branch) => {\n const lastCommitTime = await getBranchCommitTime(branch.branch)\n return {\n label: `${branch.branch} ${branch.isMerged ? colors.green('(merged)') : colors.yellow('(not merged)')}`,\n value: {\n lastCommitTime,\n branch: branch.branch,\n isMerged: branch.isMerged,\n },\n hint: `last commit: ${formatTime(Number(lastCommitTime))}`,\n }\n })\n )\n\n const deleteBranches = await createCheckbox({\n message: 'Select the branch to delete',\n options: enhancedOptions,\n })\n\n if (!deleteBranches.length) {\n log.error('No branch selected. Aborting delete operation.')\n return\n }\n await Promise.all(\n deleteBranches.map((branch) =>\n handleDelete({ branch: branch.branch, isMerged: true }, { isRemote: options.remote ?? false })\n )\n )\n Message({ text: 'Successfully deleted branches' })\n })\n}\n","import type { Command } from '@nemo-cli/shared'\nimport {\n colors,\n createConfirm,\n createInput,\n createOptions,\n createSelect,\n getCurrentBranch,\n isEmpty,\n isString,\n log,\n x,\n} from '@nemo-cli/shared'\nimport { getBranchStashes, getLocalOptions, getRemoteOptions, handleGitPop, handleGitStash } from '../utils'\nimport type { StashMetadata } from '../utils/stash-index'\n\n/**\n * 查找并恢复当前分支的 stash\n * 当用户 checkout 回之前的分支时,自动恢复该分支的 stash\n */\nconst restoreBranchStash = async (branchName: string) => {\n try {\n const branchStashes = await getBranchStashes(branchName)\n\n // 找到该分支最新的 active stash\n const activeStashes = branchStashes\n .filter((s: StashMetadata) => s.status === 'active' && s.operation === 'checkout')\n .sort((a: StashMetadata, b: StashMetadata) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime())\n\n if (activeStashes.length === 0) {\n return\n }\n\n // 恢复最新的 stash\n const latestStash = activeStashes[0]\n if (!latestStash) {\n return\n }\n\n log.show(\n `Found stashed changes from previous checkout to ${colors.bgYellow(latestStash.targetBranch || 'unknown')}. Restoring...`,\n { type: 'info' }\n )\n\n await handleGitPop({ metadata: latestStash, stashName: latestStash.message })\n } catch (_error) {\n log.show(`Failed to restore stash for branch ${branchName}`, { type: 'warn' })\n }\n}\n\nconst handleCheckout = async (\n branch: string,\n { isNew = false, isRemote = false }: { isNew?: boolean; isRemote?: boolean } = {}\n) => {\n const currentBranchName = await getCurrentBranch()\n\n const args = ['checkout']\n\n if (isNew || isRemote) {\n args.push('-b')\n }\n\n args.push(branch)\n\n if (isRemote) {\n args.push(`origin/${branch}`)\n }\n\n // 如果目标分支和当前分支不同,才执行 stash\n const shouldStash = branch !== currentBranchName\n const stashResult = shouldStash ? await handleGitStash(undefined, { branch, operation: 'checkout' }) : null\n\n const process = x('git', args)\n log.show(stashResult?.stashName, { type: 'info' })\n\n for await (const line of process) {\n log.show(line)\n }\n\n const { exitCode, stderr } = await process\n if (exitCode) {\n log.show(`Failed to checkout branch ${branch}. Command exited with code ${exitCode}.`, { type: 'error' })\n log.show(stderr, { type: 'error' })\n } else {\n log.show(`Successfully checked out branch ${branch}.`, { type: 'success' })\n\n // Checkout 成功后,检查是否有该分支的 stash 需要恢复\n await restoreBranchStash(branch)\n }\n}\n\nexport function checkoutCommand(command: Command) {\n command\n .command('checkout')\n .alias('co')\n .option('-l, --local', 'Checkout a local branch', true)\n .option('-r, --remote', 'Checkout a remote branch')\n .option('-b, --branch [branch]', 'Create and checkout a new branch')\n .description('Checkout a branch')\n .action(async (params: { local?: boolean; remote?: boolean; branch?: string | true }) => {\n let isLocal = params.local && !params.remote\n const branch = params.branch\n if (branch) {\n if (isString(branch)) {\n handleCheckout(branch, { isNew: true })\n return\n }\n const branchType = await createSelect({\n message: 'Enter the new branch name:',\n options: createOptions(['feature/PRIME-', 'feature/', 'bugfix/']),\n })\n const branchName = await createInput({\n message: 'Enter the new branch name:',\n validate: (value) => {\n if (!value?.trim()) return 'Branch name is required'\n if (value.length > 15) return 'Branch name must be less than 15 characters'\n },\n })\n handleCheckout(`${branchType}${branchName}`, { isNew: true })\n return\n }\n\n if (isEmpty(params)) {\n isLocal = await createSelect({\n message: 'Select the branch type',\n options: [\n { label: 'Remote', value: false },\n { label: 'Local', value: true },\n ],\n initialValue: true,\n })\n }\n\n if (isLocal) {\n const { options } = await getLocalOptions()\n const selectedBranch = await createSelect({\n message: `Select the ${colors.bgGreen(' local ')} branch to checkout`,\n options,\n })\n handleCheckout(selectedBranch)\n } else {\n const { options } = await getRemoteOptions()\n const selectedBranch = await createSelect({\n message: `Select the ${colors.bgYellow(' remote ')} branch to checkout`,\n options,\n })\n\n const check = await createConfirm({\n message: `Do you want to checkout ${colors.bgRed(selectedBranch)}?`,\n })\n\n if (check) handleCheckout(selectedBranch, { isRemote: true })\n }\n })\n}\n","const commitScopeOptions = [\n {\n value: 'app',\n label: 'app',\n },\n {\n value: 'shared',\n label: 'shared',\n },\n {\n value: 'server',\n label: 'server',\n },\n {\n value: 'tools',\n label: 'tools',\n },\n {\n value: '',\n label: 'none',\n },\n]\nconst commitTypeOptions = [\n {\n value: 'feat',\n label: 'feat',\n hint: 'A new feature',\n emoji: '🌟',\n trailer: 'Changelog: feature',\n },\n {\n value: 'fix',\n label: 'fix',\n hint: 'A bug fix',\n emoji: '🐛',\n trailer: 'Changelog: fix',\n },\n {\n value: 'docs',\n label: 'docs',\n hint: 'Documentation only changes',\n emoji: '📚',\n trailer: 'Changelog: documentation',\n },\n {\n value: 'refactor',\n label: 'refactor',\n hint: 'A code change that neither fixes a bug nor adds a feature',\n emoji: '🔨',\n trailer: 'Changelog: refactor',\n },\n {\n value: 'perf',\n label: 'perf',\n hint: 'A code change that improves performance',\n emoji: '🚀',\n trailer: 'Changelog: performance',\n },\n {\n value: 'test',\n label: 'test',\n hint: 'Adding missing tests or correcting existing tests',\n emoji: '🚨',\n trailer: 'Changelog: test',\n },\n {\n value: 'build',\n label: 'build',\n hint: 'Changes that affect the build system or external dependencies',\n emoji: '🚧',\n trailer: 'Changelog: build',\n },\n {\n value: 'ci',\n label: 'ci',\n hint: 'Changes to our CI configuration files and scripts',\n emoji: '🤖',\n trailer: 'Changelog: ci',\n },\n {\n value: 'chore',\n label: 'chore',\n hint: 'Other changes that do not modify src or test files',\n emoji: '🧹',\n trailer: 'Changelog: chore',\n },\n {\n value: 'revert',\n label: 'revert',\n hint: 'Revert a previous commit',\n emoji: '🔙',\n trailer: 'Changelog: revert',\n },\n {\n value: '',\n label: 'none',\n },\n]\nexport const commitOptions = {\n check_status: true,\n commit_type: {\n enable: true,\n initial_value: 'feat',\n max_items: 20,\n infer_type_from_branch: true,\n append_emoji_to_label: false,\n append_emoji_to_commit: false,\n emoji_commit_position: 'Start',\n options: commitTypeOptions,\n },\n commit_scope: {\n enable: true,\n custom_scope: false,\n max_items: 20,\n initial_value: 'app',\n options: commitScopeOptions,\n },\n check_ticket: {\n infer_ticket: true,\n confirm_ticket: true,\n add_to_title: true,\n append_hashtag: false,\n prepend_hashtag: 'Never',\n surround: '',\n title_position: 'start',\n },\n commit_title: {\n max_size: 70,\n },\n commit_body: {\n enable: true,\n required: false,\n },\n commit_footer: {\n enable: true,\n initial_value: [],\n options: ['closes', 'trailer', 'breaking-change', 'deprecated', 'custom'],\n },\n breaking_change: {\n add_exclamation_to_title: false,\n },\n cache_last_value: true,\n confirm_with_editor: false,\n confirm_commit: true,\n print_commit_output: true,\n branch_pre_commands: [],\n branch_post_commands: [],\n worktree_pre_commands: [],\n worktree_post_commands: [],\n branch_user: {\n enable: true,\n required: false,\n separator: '/',\n },\n branch_type: {\n enable: true,\n separator: '/',\n },\n branch_version: {\n enable: false,\n required: false,\n separator: '/',\n },\n branch_ticket: {\n enable: true,\n required: false,\n separator: '-',\n },\n branch_description: {\n max_length: 70,\n separator: '',\n },\n branch_action_default: 'branch',\n branch_order: ['user', 'version', 'type', 'ticket', 'description'],\n enable_worktrees: true,\n overrides: {},\n}\n\nexport const commitlintConfig = {\n extends: ['@commitlint/config-conventional'],\n rules: {\n 'subject-empty': [2, 'never'], // subject不能为空\n 'type-empty': [2, 'never'], // type不能为空\n 'type-enum': [\n 2,\n 'always',\n ['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'build', 'ci', 'chore', 'revert', 'wip', 'release'],\n ],\n 'scope-empty': [1, 'always'], // scop 可选\n 'scope-enum': [1, 'always', ['app', 'shared', 'server', 'tools', '']],\n },\n}\n\nexport type CommitlintConfigType = typeof commitlintConfig\nexport const mergeCommitTypeEnumOptions = (options: string[]) => {\n // 与 commitTypeOptions 进行对比,如果 options 中存在,则返回 options 中的 value 和 label\n return options.map((option) => {\n const commitTypeOption = commitTypeOptions.find((commitTypeOption) => commitTypeOption.value === option)\n return {\n value: commitTypeOption?.value ?? option,\n label: commitTypeOption?.label ?? option,\n hint: commitTypeOption?.hint,\n emoji: commitTypeOption?.emoji,\n trailer: commitTypeOption?.trailer,\n }\n })\n}\n\nexport const mergeCommitScopeEnumOptions = (options: string[]) => {\n // 与 commitScopeOptions 进行对比,如果 options 中存在,则返回 options 中的 value 和 label\n const result = options.includes('none') ? options : options.concat('none')\n return result.map((option) => {\n const commitScopeOption = commitScopeOptions.find((commitScopeOption) => commitScopeOption.label === option)\n return {\n value: commitScopeOption?.value ?? option,\n label: commitScopeOption?.label ?? option,\n }\n })\n}\n","import type { Command } from '@nemo-cli/shared'\nimport { colors, createConfirm, createSelect, createSpinner, getCurrentBranch, log, xASync } from '@nemo-cli/shared'\nimport { BigText } from '@nemo-cli/ui'\nimport { getRemoteOptions, getRemoteOptionsForRemotes } from '../utils'\n\nconst handlePush = async (branch: string, remote = 'origin') => {\n const spinner = createSpinner(`Pushing branch ${branch} to ${remote}...`)\n try {\n const [error, result] = await xASync('git', ['push', remote, branch])\n\n if (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n throw new Error(`Failed with error: ${errorMessage}`)\n }\n\n spinner.stop(colors.green(`Successfully pushed branch ${colors.bgGreen(branch)} to ${remote}.`))\n } catch (error) {\n spinner.stop()\n BigText({ text: `Failed to push branch ${branch} to ${remote}.` })\n log.error(error)\n }\n}\n\nexport function pushCommand(command: Command) {\n command\n .command('push')\n .alias('ps')\n .description('Push current branch to remote')\n .action(async () => {\n await pushInteractive()\n })\n}\n\nexport const pushInteractive = async () => {\n const currentBranch = await getCurrentBranch()\n if (!currentBranch) {\n log.error('No branch selected. Aborting push operation.')\n return\n }\n\n // Get available remotes\n let remotes: string[]\n try {\n const result = await getRemoteOptionsForRemotes()\n remotes = result.remotes\n } catch (error) {\n log.error(`Failed to get remote repositories: ${error instanceof Error ? error.message : String(error)}`)\n log.show(\"Hint: Make sure you're in a git repository and have configured remotes.\", { type: 'info' })\n return\n }\n\n if (remotes.length === 0) {\n log.error('No remote repositories found. Aborting push operation.')\n log.show('Hint: Run `git remote add <name> <url>` to add a remote repository.', { type: 'info' })\n return\n }\n\n // Select remote if multiple remotes exist\n let selectedRemote = remotes[0]\n if (remotes.length > 1) {\n selectedRemote = await createSelect({\n message: 'Select remote repository',\n options: remotes.map((remote) => ({ label: remote, value: remote })),\n initialValue: remotes[0],\n })\n }\n\n const check = await createConfirm({\n message: `Do you want to push ${colors.bgGreen(currentBranch)} to ${selectedRemote}?`,\n })\n\n if (check) {\n await handlePush(currentBranch, selectedRemote)\n return\n }\n\n const { options } = await getRemoteOptions()\n const selectedBranch = await createSelect({\n message: 'Select the branch to push',\n options,\n initialValue: 'main',\n })\n\n // Allow remote re-selection if multiple remotes exist\n let pushRemote = selectedRemote\n if (remotes.length > 1) {\n const changeRemote = await createConfirm({\n message: `Push ${colors.bgGreen(selectedBranch)} to ${selectedRemote}?`,\n })\n\n if (!changeRemote) {\n pushRemote = await createSelect({\n message: 'Select remote repository',\n options: remotes.map((remote) => ({ label: remote, value: remote })),\n initialValue: selectedRemote,\n })\n }\n }\n\n await handlePush(selectedBranch, pushRemote)\n}\n","import type { LoadConfigResult } from 'unconfig'\n\nimport type { Command } from '@nemo-cli/shared'\nimport {\n addFiles,\n colors,\n createCheckbox,\n createConfirm,\n createInput,\n createNote,\n createOptions,\n createSelect,\n createSpinner,\n exit,\n getCurrentBranch,\n getGitStatus,\n intro,\n loadConfig,\n log,\n outro,\n xASync,\n} from '@nemo-cli/shared'\nimport { ErrorMessage } from '@nemo-cli/ui'\nimport {\n type CommitlintConfigType,\n commitlintConfig,\n mergeCommitScopeEnumOptions,\n mergeCommitTypeEnumOptions,\n} from './commit-options'\nimport { pushInteractive } from './push'\n\nconst lintHandle = async () => {\n const [error, result] = await xASync('lint-staged')\n if (error?.message === 'spawn lint-staged ENOENT') return true\n if (error) return false\n return true\n}\nconst handleCommit = async (message: string) => {\n const spinner = createSpinner('Committing...')\n const [error, _result] = await xASync('git', ['commit', '-m', message])\n if (error) {\n spinner.stop('Failed to commit')\n } else {\n spinner.stop('Committed')\n }\n}\nconst handleLint = async () => {\n const spinner = createSpinner('run lint-staged linting...')\n const lintResult = await lintHandle()\n if (!lintResult) {\n const confirm = await createConfirm({\n message: 'Lint failed. Do you want to continue?',\n initialValue: false,\n })\n !confirm && exit(0)\n }\n spinner.stop('lint-staged done')\n}\n\nexport const commitCommand = (command: Command) => {\n command\n .command('commit')\n .description('Commit a message')\n .action(async () => {\n console.clear()\n const title = colors.bgRed(` ${await getCurrentBranch()} `)\n intro(`${colors.bgCyan(' Current Branch: ')} ${title}`)\n\n // 1. 获取Git状态并展示工作区和暂存区文件\n const { staged, unstaged } = await getGitStatus()\n\n if (staged.length === 0 && unstaged.length === 0) {\n // 如果没有任何文件变更,提示用户\n ErrorMessage({ text: 'No changes detected. Nothing to commit.' })\n exit(0)\n }\n\n // 创建选项对象,用于分组多选\n\n log.show(`Changes to be committed:\\n${staged.map((text) => colors.green(text)).join('\\n')}`, { type: 'success' })\n const selectedStaged = staged\n\n if (unstaged.length > 0) {\n // 工作区文件组(可选择)\n const selectedFiles = await createCheckbox({\n message: 'Select files to stage for commit (optional):',\n options: createOptions(unstaged),\n required: false,\n })\n\n selectedStaged.push(...selectedFiles)\n\n if (selectedFiles.length > 0) {\n // 2. 将选择的工作区文件添加到暂存区\n await addFiles(selectedFiles)\n createNote({\n message: `Added ${selectedFiles.length} unstaged file(s) to staging area.\\n${selectedFiles.map((file) => colors.green(file)).join('\\n')}`,\n title: 'Add Files',\n })\n }\n }\n\n if (selectedStaged.length === 0) {\n ErrorMessage({ text: 'No staged files. Nothing to commit.' })\n exit(0)\n }\n\n await handleLint()\n\n const options: LoadConfigResult<CommitlintConfigType> = await loadConfig({\n sources: [\n {\n files: 'commitlint.config',\n extensions: ['js', 'ts', 'cjs', 'mjs', 'json', ''],\n },\n ],\n })\n\n //3. 获取当前cwd文件夹下 commitlint 文件中的 type-enum 进行选择\n const commitType = await createSelect({\n message: 'Select type:',\n options: mergeCommitTypeEnumOptions((options.config ?? commitlintConfig)!.rules['type-enum'][2] as string[]),\n })\n // 4. 获取当前cwd文件夹下 commitlint 文件中的 scope-enum 进行选择\n const commitScope = await createSelect({\n message: 'Select scope:',\n options: mergeCommitScopeEnumOptions((options.config ?? commitlintConfig)!.rules['scope-enum'][2] as string[]),\n })\n //5. 用户输入 Write a brief title describing the commit , 限制 80个字符\n const commitTitle = await createInput({\n message: 'Write a brief title describing the commit:',\n validate(value) {\n if (!value?.trim()) return 'Title is required'\n if (value.length > 80) return 'Title must be less than 80 characters'\n },\n })\n //6. 用户输入 Write a detailed description of the changes (optional), 无字数限制\n const commitBody = await createInput({\n message: 'Write a detailed description of the changes (optional):',\n })\n const ticket = await getTicket()\n\n const scopeMessage = commitScope ? `(${commitScope})` : ''\n const message = `${commitType}${scopeMessage}: ${ticket} ${commitTitle}\\n${commitBody}`\n const previewMessage = `${colors.blue(commitType)}${colors.green(scopeMessage)}: ${colors.redBright(ticket)} ${commitTitle}\\n${commitBody}`\n createNote({ message: previewMessage, title: 'Commit Message' })\n\n const confirm = await createConfirm({ message: 'Are you sure you want to commit?' })\n\n // 7. 发送 git commit 命令\n if (!confirm) return\n await handleCommit(message)\n\n // 8. 发送 git push 命令\n const confirmPush = await createConfirm({ message: 'Do you want to push to remote?' })\n confirmPush && (await pushInteractive())\n outro(colors.bgGreen(' Git Commit Success '))\n })\n}\n\nexport const REGEX_SLASH_TAG = new RegExp(/\\/(\\w+-\\d+)/)\nexport const REGEX_START_TAG = new RegExp(/^(\\w+-\\d+)/)\nexport const REGEX_START_UND = new RegExp(/^([A-Z]+-[[a-zA-Z\\]\\d]+)_/)\nexport const REGEX_SLASH_UND = new RegExp(/\\/([A-Z]+-[[a-zA-Z\\]\\d]+)_/)\nexport const REGEX_SLASH_NUM = new RegExp(/\\/(\\d+)/)\nexport const REGEX_START_NUM = new RegExp(/^(\\d+)/)\n\nconst getTicket = async () => {\n const branch = await getCurrentBranch()\n const chain = [REGEX_START_UND, REGEX_SLASH_UND, REGEX_SLASH_TAG, REGEX_SLASH_NUM, REGEX_START_TAG, REGEX_START_NUM]\n for (const regex of chain) {\n const match = branch.match(regex)\n if (match) return match[1]\n }\n return branch\n}\n","/** biome-ignore-all lint/suspicious/noExplicitAny: need any */\nimport { readFileSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nimport {\n type Command,\n createCheckbox,\n createConfirm,\n createInput,\n createSelect,\n createSpinner,\n log,\n} from '@nemo-cli/shared'\nimport { Message } from '@nemo-cli/ui'\n\ninterface GitConfig {\n user?: {\n name?: string\n email?: string\n }\n init?: {\n defaultBranch?: string\n }\n pull?: {\n rebase?: boolean | string\n }\n push?: {\n default?: string\n autoSetupRemote?: boolean\n }\n rebase?: {\n autoStash?: boolean\n }\n color?: {\n ui?: boolean | string\n }\n alias?: Record<string, string>\n [key: string]: any\n}\n\nconst GITCONFIG_PATH = join(homedir(), '.gitconfig')\n\n// 读取 gitconfig 文件\nconst readGitConfig = (): GitConfig => {\n try {\n const content = readFileSync(GITCONFIG_PATH, 'utf-8')\n const config: GitConfig = {}\n let currentSection: string | null = null\n let subsection: string | null = null\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim()\n\n // 跳过注释和空行\n if (!trimmed || trimmed.startsWith('#')) continue\n\n // 匹配节 [section]\n const sectionMatch = trimmed.match(/^\\[([^\\]]+)\\]$/)\n if (sectionMatch) {\n currentSection = sectionMatch[1] || null\n subsection = null\n if (currentSection && !config[currentSection]) {\n config[currentSection] = {}\n }\n continue\n }\n\n // 匹配子节 [section \"subsection\"]\n const subsectionMatch = trimmed.match(/^\\[([^\\s]+) \"([^\"]+)\"\\]$/)\n if (subsectionMatch) {\n currentSection = subsectionMatch[1] || null\n subsection = subsectionMatch[2] || null\n if (currentSection && !config[currentSection]) {\n config[currentSection] = {}\n }\n if (subsection && currentSection && typeof config[currentSection] === 'object') {\n if (!config[currentSection][subsection]) {\n ;(config[currentSection] as Record<string, any>)[subsection] = {}\n }\n }\n continue\n }\n\n // 匹配键值对 key = value\n const keyValueMatch = trimmed.match(/^(\\w+)\\s*=\\s*(.+)$/)\n if (keyValueMatch && currentSection) {\n const key = keyValueMatch[1]\n const value = keyValueMatch[2]\n let target = config[currentSection]\n\n // 如果有子节,设置到子节中\n if (subsection && typeof target === 'object') {\n if (!target[subsection]) {\n ;(target as Record<string, any>)[subsection] = {}\n }\n target = (target as Record<string, any>)[subsection]\n }\n\n // 处理布尔值\n if (key && value === 'true') {\n target[key] = true\n } else if (key && value === 'false') {\n target[key] = false\n } else if (key) {\n target[key] = value\n }\n }\n }\n\n return config\n } catch {\n // 文件不存在或读取失败\n return {}\n }\n}\n\n// 写入 gitconfig 文件\nconst writeGitConfig = (config: GitConfig) => {\n const lines: string[] = []\n\n const sections = Object.keys(config).sort()\n\n for (const section of sections) {\n const value = config[section]\n\n // 跳过空对象\n if (!value || typeof value !== 'object') continue\n if (Object.keys(value).length === 0) continue\n\n // 处理普通节 [section]\n let isSubsection = false\n for (const key of Object.keys(value)) {\n if (typeof value[key] === 'object' && key !== 'alias') {\n // 这是子节\n isSubsection = true\n break\n }\n }\n\n if (isSubsection) {\n // 处理带子节的配置\n for (const [subsection, subValue] of Object.entries(value)) {\n if (typeof subValue !== 'object' || subValue === null) continue\n\n lines.push(`[${section} \"${subsection}\"]`)\n for (const [key, val] of Object.entries(subValue)) {\n lines.push(`\\t${key} = ${val}`)\n }\n lines.push('') // 空行分隔\n }\n } else {\n // 普通节\n lines.push(`[${section}]`)\n for (const [key, val] of Object.entries(value)) {\n if (typeof val === 'object' && val !== null) {\n // 处理 alias 等嵌套对象\n for (const [subKey, subVal] of Object.entries(val)) {\n lines.push(`\\t${subKey} = ${subVal}`)\n }\n } else {\n lines.push(`\\t${key} = ${val}`)\n }\n }\n lines.push('') // 空行分隔\n }\n }\n\n writeFileSync(GITCONFIG_PATH, lines.join('\\n'), 'utf-8')\n}\n\n// 格式化显示配置\nconst displayConfig = (config: GitConfig) => {\n const lines: string[] = []\n\n if (config.user) {\n lines.push('👤 User Information:')\n if (config.user.name) lines.push(` Name: ${config.user.name}`)\n if (config.user.email) lines.push(` Email: ${config.user.email}`)\n lines.push('')\n }\n\n if (config.init?.defaultBranch) {\n lines.push('🌳 Initial Branch:')\n lines.push(` Default: ${config.init.defaultBranch}`)\n lines.push('')\n }\n\n if (config.pull) {\n lines.push('📥 Pull Strategy:')\n if (config.pull.rebase !== undefined) {\n lines.push(` Rebase: ${config.pull.rebase}`)\n }\n lines.push('')\n }\n\n if (config.push) {\n lines.push('📤 Push Strategy:')\n if (config.push.default) lines.push(` Default: ${config.push.default}`)\n if (config.push.autoSetupRemote !== undefined) {\n lines.push(` Auto Setup Remote: ${config.push.autoSetupRemote}`)\n }\n lines.push('')\n }\n\n if (config.color) {\n lines.push('🎨 Color:')\n if (config.color.ui !== undefined) {\n lines.push(` UI: ${config.color.ui}`)\n }\n lines.push('')\n }\n\n if (config.alias && Object.keys(config.alias).length > 0) {\n lines.push('⚡ Aliases:')\n for (const [alias, command] of Object.entries(config.alias)) {\n lines.push(` ${alias} = ${String(command)}`)\n }\n lines.push('')\n }\n\n return lines.join('\\n')\n}\n\n// 配置用户信息\nconst configureUserInfo = async (config: GitConfig) => {\n const action = await createSelect({\n message: 'What would you like to configure?',\n options: [\n { label: 'Name', value: 'name' },\n { label: 'Email', value: 'email' },\n { label: 'Both', value: 'both' },\n ],\n })\n\n if (action === 'name' || action === 'both') {\n const name = await createInput({\n message: 'Enter your name:',\n initialValue: config.user?.name || '',\n placeholder: config.user?.name || 'Your name',\n })\n if (!config.user) config.user = {}\n config.user.name = name || config.user.name\n }\n\n if (action === 'email' || action === 'both') {\n const email = await createInput({\n message: 'Enter your email:',\n initialValue: config.user?.email || '',\n placeholder: config.user?.email || 'your@email.com',\n })\n if (!config.user) config.user = {}\n config.user.email = email || config.user.email\n }\n\n return config\n}\n\n// 配置常用选项\nconst configureCommonOptions = async (config: GitConfig) => {\n const options = await createCheckbox({\n message: 'Select options to configure:',\n options: [\n { label: 'Default branch name', value: 'defaultBranch' },\n { label: 'Pull rebase strategy', value: 'pullRebase' },\n { label: 'Push default strategy', value: 'pushDefault' },\n { label: 'Enable color output', value: 'colorUi' },\n { label: 'Auto stash on rebase', value: 'autoStash' },\n ],\n required: false,\n })\n\n for (const option of options) {\n switch (option) {\n case 'defaultBranch': {\n const branch = await createInput({\n message: 'Enter default branch name:',\n initialValue: config.init?.defaultBranch || 'main',\n placeholder: 'main',\n })\n if (!config.init) config.init = {}\n config.init.defaultBranch = branch || config.init.defaultBranch || 'main'\n break\n }\n case 'pullRebase': {\n const rebase = await createSelect({\n message: 'Select pull rebase strategy:',\n options: [\n { label: 'False (merge)', value: 'false' },\n { label: 'True (rebase)', value: 'true' },\n { label: 'Interactive', value: 'interactive' },\n ],\n })\n if (!config.pull) config.pull = {}\n config.pull.rebase = rebase === 'false' ? false : rebase\n break\n }\n case 'pushDefault': {\n const pushDefault = await createSelect({\n message: 'Select push default strategy:',\n options: [\n { label: 'current', value: 'current' },\n { label: 'upstream', value: 'upstream' },\n { label: 'simple', value: 'simple' },\n { label: 'matching', value: 'matching' },\n ],\n })\n if (!config.push) config.push = {}\n config.push.default = pushDefault\n break\n }\n case 'colorUi': {\n const color = await createSelect({\n message: 'Select color output:',\n options: [\n { label: 'Auto', value: 'auto' },\n { label: 'Always', value: 'always' },\n { label: 'Never', value: 'false' },\n ],\n })\n if (!config.color) config.color = {}\n config.color.ui = color === 'false' ? false : color\n break\n }\n case 'autoStash': {\n const autoStash = (await createConfirm({\n message: 'Enable auto stash on rebase?',\n initialValue: config.rebase?.autoStash === true,\n })) as boolean\n if (!config.rebase) config.rebase = {}\n config.rebase.autoStash = autoStash\n break\n }\n }\n }\n\n return config\n}\n\n// 配置别名\nconst configureAliases = async (config: GitConfig) => {\n const action = await createSelect({\n message: 'What would you like to do?',\n options: [\n { label: 'Add new alias', value: 'add' },\n { label: 'Remove alias', value: 'remove' },\n { label: 'List all aliases', value: 'list' },\n ],\n })\n\n if (action === 'add') {\n const alias = await createInput({\n message: 'Enter alias name:',\n initialValue: '',\n placeholder: 'st',\n })\n\n const command = await createInput({\n message: 'Enter git command:',\n initialValue: '',\n placeholder: 'status',\n })\n\n // 验证输入不为空\n if (!alias || !command) {\n Message({ text: 'Alias name and command cannot be empty.' })\n return config\n }\n\n if (!config.alias) config.alias = {}\n config.alias[alias] = command\n\n Message({ text: `Added alias: ${alias} = ${command}` })\n } else if (action === 'remove') {\n if (!config.alias || Object.keys(config.alias).length === 0) {\n Message({ text: 'No aliases to remove.' })\n return config\n }\n\n const aliases = Object.keys(config.alias).map((key) => ({\n label: `${key} = ${config.alias![key]}`,\n value: key,\n }))\n\n const toRemove = await createSelect({\n message: 'Select alias to remove:',\n options: aliases,\n })\n\n delete config.alias[toRemove]\n Message({ text: `Removed alias: ${toRemove}` })\n } else if (action === 'list') {\n if (!config.alias || Object.keys(config.alias).length === 0) {\n Message({ text: 'No aliases configured.' })\n } else {\n const aliasList = Object.entries(config.alias)\n .map(([alias, command]) => `${alias} = ${command}`)\n .join('\\n')\n log.show(aliasList, { type: 'info' })\n }\n }\n\n return config\n}\n\n// 快速初始化配置\nconst initializeConfig = async (config: GitConfig) => {\n Message({ text: \"🚀 Let's set up your git configuration!\" })\n\n // 1. 用户名\n const name = await createInput({\n message: 'What is your name?',\n initialValue: config.user?.name || '',\n placeholder: 'GaoZimeng',\n })\n if (name) {\n if (!config.user) config.user = {}\n config.user.name = name\n }\n\n // 2. 邮箱\n const email = await createInput({\n message: 'What is your email?',\n initialValue: config.user?.email || '',\n placeholder: 'your@email.com',\n })\n if (email) {\n if (!config.user) config.user = {}\n config.user.email = email\n }\n\n // 3. 默认分支\n const defaultBranch = await createInput({\n message: 'What should be the default branch name?',\n initialValue: config.init?.defaultBranch || 'main',\n placeholder: 'main',\n })\n if (defaultBranch) {\n if (!config.init) config.init = {}\n config.init.defaultBranch = defaultBranch\n }\n\n // 4. 是否启用颜色\n const enableColor = (await createConfirm({\n message: 'Enable colored output?',\n initialValue: config.color?.ui !== false,\n })) as boolean\n if (!config.color) config.color = {}\n config.color.ui = enableColor ? 'auto' : false\n\n // 5. 自动设置远程分支\n const autoSetupRemote = (await createConfirm({\n message: 'Automatically setup remote branch when pushing?',\n initialValue: config.push?.autoSetupRemote !== false,\n })) as boolean\n if (!config.push) config.push = {}\n config.push.autoSetupRemote = autoSetupRemote\n\n // 6. rebase 时自动 stash\n const autoStash = (await createConfirm({\n message: 'Auto stash before rebase?',\n initialValue: config.rebase?.autoStash !== false,\n })) as boolean\n if (!config.rebase) config.rebase = {}\n config.rebase.autoStash = autoStash\n\n return config\n}\n\nexport const configCommand = (command: Command) => {\n const subCommand = command.command('config').description('Interactive git configuration manager')\n\n subCommand\n .command('init')\n .description('Quick setup basic git configuration')\n .action(async () => {\n const config = readGitConfig()\n const updatedConfig = await initializeConfig(config)\n\n const spinner = createSpinner('Saving configuration...')\n writeGitConfig(updatedConfig)\n spinner.stop('✓ Git configuration initialized successfully!')\n\n // 显示配置结果\n const display = displayConfig(updatedConfig)\n if (display) {\n log.show(`\\n${display}`)\n }\n })\n\n subCommand.action(async () => {\n let continueRunning = true\n\n while (continueRunning) {\n // 主菜单\n const action = await createSelect({\n message: 'What would you like to do?',\n options: [\n { label: '📖 View current config', value: 'view' },\n { label: '👤 Configure user info', value: 'user' },\n { label: '⚙️ Configure options', value: 'options' },\n { label: '⚡ Manage aliases', value: 'aliases' },\n { label: '🧹 Clear all config', value: 'clear' },\n { label: '❌ Exit', value: 'exit' },\n ],\n })\n\n if (action === 'exit') {\n continueRunning = false\n continue\n }\n\n if (action === 'view') {\n const config = readGitConfig()\n const display = displayConfig(config)\n\n if (display) {\n log.show(`\\n${display}`)\n } else {\n Message({ text: 'No configuration found.' })\n }\n } else if (action === 'user') {\n const config = readGitConfig()\n const updatedConfig = await configureUserInfo(config)\n\n const spinner = createSpinner('Saving configuration...')\n writeGitConfig(updatedConfig)\n spinner.stop('✓ Configuration saved successfully!')\n } else if (action === 'options') {\n const config = readGitConfig()\n const updatedConfig = await configureCommonOptions(config)\n\n const spinner = createSpinner('Saving configuration...')\n writeGitConfig(updatedConfig)\n spinner.stop('✓ Configuration saved successfully!')\n } else if (action === 'aliases') {\n const config = readGitConfig()\n const updatedConfig = await configureAliases(config)\n\n const spinner = createSpinner('Saving configuration...')\n writeGitConfig(updatedConfig)\n spinner.stop('✓ Configuration saved successfully!')\n } else if (action === 'clear') {\n const confirm = await createConfirm({\n message: 'Are you sure you want to clear all git configuration?',\n })\n\n if (confirm) {\n const spinner = createSpinner('Clearing configuration...')\n writeGitConfig({})\n spinner.stop('✓ Configuration cleared successfully!')\n }\n }\n }\n })\n\n return command\n}\n","import { type Command, createOptions, createSelect, getCurrentBranch, log, type Result, x } from '@nemo-cli/shared'\nimport { getLocalBranches, getRemoteBranches } from '../utils'\n\nconst handleDiff = async (branch: string, { isLocal }: { isLocal: boolean }) => {\n console.log('🚀 : handleDiff : branch:', branch, isLocal)\n\n // Get current branch for comparison\n const currentBranch = await getCurrentBranch()\n if (!currentBranch) {\n log.error('Could not determine current branch')\n return\n }\n\n // If selected branch is the same as current, show diff with working directory\n const diffArgs = branch === currentBranch ? ['diff'] : ['diff', `${branch}...${currentBranch}`]\n\n log.show(\n `Showing diff between ${branch === currentBranch ? 'working directory and HEAD' : `${branch} and ${currentBranch}`}`\n )\n\n const process: Result = x('git', diffArgs)\n\n let hasOutput = false\n for await (const line of process) {\n hasOutput = true\n log.show(line)\n }\n\n const { exitCode, stderr } = await process\n\n if (exitCode) {\n log.error(`Failed to diff. Command exited with code ${exitCode}.`)\n if (stderr) {\n log.error(stderr)\n }\n } else if (!hasOutput) {\n log.show('No differences found.', { type: 'info' })\n }\n}\n\nexport function diffCommand(command: Command) {\n command\n .command('diff')\n .alias('di')\n .description('Show differences between branches or working directory')\n .option('-l, --local', 'Diff local branch', true)\n .option('-r, --remote', 'Diff remote branch')\n .action(async (options: { local?: boolean; remote?: boolean }) => {\n const { branches } = options.remote ? await getRemoteBranches() : await getLocalBranches()\n if (!branches || branches.length === 0) {\n log.error('No branches found. Please check your git repository.')\n return\n }\n const selectedBranch = await createSelect({\n message: 'Select the branch to diff',\n options: createOptions(branches),\n })\n if (!selectedBranch) {\n log.error('No branch selected. Aborting diff operation.')\n return\n }\n await handleDiff(selectedBranch, { isLocal: !options.remote })\n })\n}\n","import type { Command } from '@nemo-cli/shared'\nimport { renderHistViewer } from '@nemo-cli/ui'\n\nexport const histCommand = (command: Command) => {\n command\n .command('hist')\n .alias('history')\n .description('Show git history with beautiful graph format')\n .option('-n, --number <count>', 'Limit number of commits to show')\n .action(async (options: { number?: string }) => {\n const maxCount = options.number ? Number.parseInt(options.number, 10) : undefined\n await renderHistViewer(maxCount)\n })\n\n return command\n}\n","import { type Command, colors, log } from '@nemo-cli/shared'\n\nimport { getLocalBranches, getRemoteBranches } from '../utils'\n\nexport function listCommand(command: Command) {\n command\n .command('list')\n .alias('ls')\n .description('List git branches')\n .option('-l, --local', 'List local branches')\n .option('-r, --remote', 'List remote branches')\n .option('-a, --all', 'List all branches', true)\n .action(async (options: { local?: boolean; remote?: boolean; all?: boolean }) => {\n if (options.all) {\n const { branches: localBranches, currentBranch } = await getLocalBranches()\n const { branches: remoteBranches } = await getRemoteBranches()\n if (!localBranches.length && !remoteBranches.length) {\n log.error('No branches found. Please check your git repository.')\n return\n }\n\n log.show(`Local ${localBranches.length} branches`, { symbol: '🔖', colors: colors.bgGreen })\n for (const branch of localBranches) {\n if (branch === currentBranch) {\n log.show(`${branch} (current)`, { type: 'info' })\n } else {\n log.show(branch, { type: 'step' })\n }\n }\n log.show(`Remote ${remoteBranches.length} branches`, { symbol: '🔖', colors: colors.bgYellow })\n for (const branch of remoteBranches) {\n if (branch === currentBranch) {\n log.show(`${branch} (current)`, { type: 'info' })\n } else {\n log.show(branch, { type: 'step' })\n }\n }\n } else if (options.local) {\n const { branches } = await getLocalBranches()\n if (!branches || branches.length === 0) {\n log.error('No local branches found. Please check your git repository.')\n return\n }\n log.info(`Found ${branches.length} local branches:`)\n for (const branch of branches) {\n log.info(branch)\n }\n } else {\n const { branches } = await getRemoteBranches()\n if (!branches || branches.length === 0) {\n log.error('No remote branches found. Please check your git repository.')\n return\n }\n log.info(`Found ${branches.length} remote branches:`)\n for (const branch of branches) {\n log.info(branch)\n }\n }\n })\n}\n","import type { Command } from '@nemo-cli/shared'\nimport {\n colors,\n createConfirm,\n createSearch,\n createSelect,\n createSpinner,\n isEmpty,\n log,\n xASync,\n} from '@nemo-cli/shared'\nimport { getLocalOptions, getRemoteOptions, handleGitPop, handleGitStash } from '../utils'\n\nconst handleMerge = async (branch: string) => {\n const spinner = createSpinner(`Merging branch ${branch}...`)\n const args = ['merge', branch]\n\n const stashResult = await handleGitStash(undefined, { branch, operation: 'merge' })\n\n try {\n // 使用 stdio: 'inherit' 来支持交互式合并确认\n const [error] = await xASync('git', args, {\n nodeOptions: {\n stdio: 'inherit',\n },\n })\n\n if (error) {\n log.show(`Failed to merge branch ${branch}.`, { type: 'error' })\n } else {\n spinner.stop(`Successfully merged branch ${branch}.`)\n }\n } finally {\n stashResult && handleGitPop(stashResult)\n }\n}\n\nexport function mergeCommand(command: Command) {\n command\n .command('merge')\n .alias('mg')\n .argument('[branch]', 'The branch to merge')\n .option('-l, --local', 'Merge a local branch')\n .option('-r, --remote', 'Merge a remote branch')\n .option('-b, --branch <branch>', 'Create and merge a new branch')\n .description('Merge a branch')\n .action(async (branch, params: { local?: boolean; remote?: boolean }) => {\n let isLocal = params.local\n\n if (branch) {\n handleMerge(branch)\n return\n }\n\n if (isEmpty(params)) {\n isLocal = await createSelect({\n message: 'Select the branch type',\n options: [\n { label: 'Remote', value: false },\n { label: 'Local', value: true },\n ],\n initialValue: false,\n })\n }\n\n if (isLocal) {\n const { options } = await getLocalOptions()\n const selectedBranch = await createSearch({\n message: 'Select the branch to merge',\n options,\n })\n handleMerge(selectedBranch)\n } else {\n const { options } = await getRemoteOptions()\n const selectedBranch = await createSearch({\n message: 'Select the branch to merge',\n options,\n })\n\n const check = await createConfirm({\n message: `Do you want to merge ${colors.bgRed(selectedBranch)}?`,\n })\n\n if (check) handleMerge(selectedBranch)\n }\n })\n}\n","import { type Command, createSelect, log } from '@nemo-cli/shared'\nimport { getRemoteOptions, handleGitPop, handleGitPull, handleGitStash } from '../utils'\n\nexport function pullCommand(command: Command) {\n command\n .command('pull')\n .alias('pl')\n .description('Pull git branch')\n .option('-r, --rebase', 'Use rebase mode instead of merge')\n .option('-m, --merge', 'Use merge mode (default)')\n .action(async (options: { rebase?: boolean; merge?: boolean }) => {\n const { options: branchOptions, currentBranch } = await getRemoteOptions()\n if (!branchOptions.length) {\n log.error('No branches found. Please check your git repository.')\n return\n }\n\n const selectedBranch = await createSelect({\n message: 'Select the branch to pull',\n options: branchOptions,\n initialValue: currentBranch,\n })\n if (!selectedBranch) {\n log.error('No branch selected. Aborting pull operation.')\n return\n }\n\n // 确定 pull 模式:如果命令行指定了 --rebase 或 --merge,直接使用;否则询问用户\n let useRebase = options.rebase === true\n\n if (!options.rebase && !options.merge) {\n const pullMode = await createSelect({\n message: 'Select pull mode',\n options: [\n { label: 'Merge (default)', value: 'merge', hint: 'git pull origin <branch>' },\n { label: 'Rebase', value: 'rebase', hint: 'git pull --rebase origin <branch>' },\n ],\n initialValue: 'merge',\n })\n useRebase = pullMode === 'rebase'\n }\n\n const stashResult = await handleGitStash(undefined, { branch: selectedBranch, operation: 'pull' })\n\n await handleGitPull(selectedBranch, { rebase: useRebase })\n\n stashResult && handleGitPop(stashResult)\n })\n}\n","import { createHelpExample } from '@nemo-cli/shared'\n\nexport const HELP_MESSAGE = {\n main: createHelpExample(\n 'ng stash',\n 'ng blame [file]',\n 'ng blame [file] [line]',\n 'ng stash save \"work in progress\"',\n 'ng stash ls',\n 'ng stash pop',\n 'ng stash drop'\n ),\n save: createHelpExample('ng stash save \"work in progress\"'),\n list: createHelpExample('ng stash ls'),\n pop: createHelpExample('ng stash pop'),\n drop: createHelpExample('ng stash drop'),\n}\n\nexport const ERROR_MESSAGE = {\n notRootWorkspace: \"It's not workspace root directory, Please open this command in the workspace root directory\",\n}\n","import type { Command } from '@nemo-cli/shared'\nimport {\n colors,\n createCheckbox,\n createInput,\n createOptions,\n exit,\n getCurrentBranch,\n log,\n xASync,\n} from '@nemo-cli/shared'\nimport type { StashItem } from '@nemo-cli/ui'\nimport { renderStashList } from '@nemo-cli/ui'\nimport { HELP_MESSAGE } from '../constants/stash'\nimport { handleGitStash, handleGitStashCheck } from '../utils'\nimport { cleanOldStashes, getAllStashes } from '../utils/stash-index'\n\nenum StashCommand {\n POP = 'pop',\n LIST = 'list',\n SAVE = 'save',\n DROP = 'drop',\n}\n\nconst handleCheck =\n <T extends (stashes: string[]) => unknown>(callback: T) =>\n async () => {\n const stashes = await handleGitStashCheck()\n if (stashes.length === 0) {\n log.show('No stash found.', { type: 'error' })\n return\n }\n return callback(stashes)\n }\n\n/**\n * 获取 stash 中的文件列表\n * @param stashRef - stash 引用,如 \"stash@{0}\"\n */\nconst getStashFiles = async (stashRef: string): Promise<string[]> => {\n const [error, result] = await xASync('git', ['stash', 'show', stashRef, '--name-only'], { quiet: true })\n if (error) return []\n return result.stdout.split('\\n').filter((line) => line.trim())\n}\n\n/**\n * 从 stash 条目中提取 stash 引用\n * @param stashEntry - 完整的 stash 条目,如 \"stash@{0}: On main: message\"\n */\nconst extractStashRef = (stashEntry: string): string => {\n const match = stashEntry.match(/^(stash@\\{\\d+\\})/)\n if (match?.[1]) return match[1]\n return stashEntry.split(':')[0] ?? stashEntry\n}\n\nconst handlePop = handleCheck(async (stashes: string[]) => {\n const selectedStashes = await createCheckbox({\n message: 'Select the stash to pop',\n options: stashes.map((stash) => ({ label: stash, value: stash })),\n })\n for await (const stash of selectedStashes) {\n const stashRef = extractStashRef(stash)\n const [error] = await xASync('git', ['stash', 'pop', stashRef])\n if (error) {\n log.show('Failed to pop stash.', { type: 'error' })\n } else {\n log.show('Successfully popped changes.', { type: 'success' })\n }\n }\n})\n\n/**\n * 解析 stash 条目获取详细信息\n * @param stashEntry - 完整的 stash 条目,如 \"stash@{0}: On main: message\"\n */\ninterface StashInfo {\n ref: string // stash@{0}\n branch: string // main\n message: string // checkout:main@2026-02-04T10-24-57\n}\n\nconst parseStashEntry = (stashEntry: string): StashInfo => {\n // 匹配格式: stash@{0}: On main: message\n const match = stashEntry.match(/^(stash@\\{\\d+\\}):\\s+On\\s+(\\S+):\\s+(.+)$/)\n\n if (match) {\n return {\n ref: match[1] || stashEntry,\n branch: match[2] || 'unknown',\n message: match[3] || stashEntry,\n }\n }\n\n // 兼容旧格式或其他格式\n const refMatch = stashEntry.match(/^(stash@\\{\\d+\\})/)\n return {\n ref: refMatch?.[1] ?? stashEntry.split(':')[0] ?? stashEntry,\n branch: 'unknown',\n message: stashEntry,\n }\n}\n\nconst handleList = handleCheck(async (stashes: string[]) => {\n // 转换为 ink 组件需要的格式\n const stashItems: StashItem[] = await Promise.all(\n stashes.map(async (stash) => {\n const stashInfo = parseStashEntry(stash)\n const files = await getStashFiles(stashInfo.ref)\n\n return {\n ref: stashInfo.ref,\n branch: stashInfo.branch,\n message: stashInfo.message,\n files,\n fileCount: files.length,\n }\n })\n )\n\n // 使用 ink 组件渲染\n await renderStashList(stashItems)\n})\n\nconst handleDrop = handleCheck(async (stashes: string[]) => {\n const selectedStashes = await createCheckbox({\n message: 'Select the stash to clear',\n options: createOptions(stashes),\n })\n\n for await (const stash of selectedStashes) {\n const stashRef = extractStashRef(stash)\n if (!stashRef) {\n log.show('Invalid stash name.', { type: 'error' })\n exit(0)\n }\n\n const [error] = await xASync('git', ['stash', StashCommand.DROP, stashRef])\n if (error) {\n log.show('Failed to drop stash.', { type: 'error' })\n } else {\n log.show(`Successfully dropped stash: ${stashRef}`, { type: 'success' })\n }\n }\n})\n\nconst handleClear = handleCheck(async () => {\n const [error] = await xASync('git', ['stash', 'clear'])\n if (error) {\n log.show('Failed to clear stashes.', { type: 'error' })\n } else {\n log.show('Successfully cleared stashes.', { type: 'success' })\n }\n})\n\nconst handleHistory = async (options: { all?: boolean; active?: boolean; clean?: string }) => {\n // Clean mode\n if (options.clean) {\n const days = Number.parseInt(options.clean, 10) || 30\n const count = await cleanOldStashes(days)\n log.show(`Cleaned ${count} old stash records (${days} days)`, { type: 'success' })\n return\n }\n\n // Fetch stashes\n const stashes = await getAllStashes(options.active ? 'active' : undefined)\n const displayList = options.all ? stashes : stashes.slice(0, 10)\n\n // Sort by timestamp (newest first)\n displayList.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())\n\n if (displayList.length === 0) {\n log.show('No stash records found.', { type: 'info' })\n return\n }\n\n log.show(`\\n${colors.bold(`📚 Stash History (${displayList.length} records)`)}\\n`)\n\n for (const stash of displayList) {\n const statusEmoji = stash.status === 'active' ? '📦' : '✅'\n const statusColor = stash.status === 'active' ? colors.yellow : colors.green\n\n log.show(colors.cyan(`━━━ ${statusEmoji} ${stash.message} ━━━`))\n log.show(colors.dim(` Operation: ${stash.operation || 'unknown'}`))\n log.show(colors.dim(` Status: ${statusColor(stash.status || 'unknown')}`))\n log.show(colors.dim(` Branch: ${stash.currentBranch || 'unknown'}`))\n log.show(colors.dim(` Time: ${new Date(stash.timestamp).toLocaleString()}`))\n\n if (stash.files && stash.files.length > 0) {\n log.show(colors.dim(` Files (${stash.files.length}):`))\n // Show first 5 files\n const filesToShow = stash.files.slice(0, 5)\n for (const file of filesToShow) {\n log.show(colors.yellow(` • ${file}`))\n }\n if (stash.files.length > 5) {\n log.show(colors.dim(` ... and ${stash.files.length - 5} more`))\n }\n }\n\n if (stash.error) {\n log.show(colors.red(` Error: ${stash.error}`))\n }\n log.show('') // Empty line separator\n }\n\n if (!options.all && stashes.length > 10) {\n log.show(colors.dim(`\\nShowing 10 of ${stashes.length} records. Use --all to see all.\\n`))\n }\n}\n\nexport const stashCommand = (command: Command) => {\n // 创建主 stash 命令\n const stashCmd = command\n .command('stash')\n .alias('st')\n .description('Git stash management')\n .addHelpText('after', HELP_MESSAGE.main)\n\n // 直接执行 stash(自动命名,不提示用户)\n stashCmd.action(async () => {\n const result = await handleGitStash(undefined, { operation: 'manual' })\n if (!result) {\n log.show('No changes to stash.', { type: 'info' })\n }\n })\n\n // 子命令:保存 stash\n stashCmd\n .command('save [message]')\n .alias('s')\n .description('Save current changes to stash')\n .action(async (message?: string) => {\n if (message) {\n // 如果提供了 message 参数,直接使用\n const result = await handleGitStash(message, { operation: 'manual' })\n if (!result) {\n log.show('No changes to stash.', { type: 'info' })\n }\n } else {\n // 如果没有提供 message,提示用户输入(带默认值)\n try {\n const userMessage = await createInput({\n message: 'Enter stash message (press Enter to use default)',\n validate: (value) => {\n if (!value?.trim()) return 'Message cannot be empty'\n return undefined\n },\n })\n\n const result = await handleGitStash(userMessage, { operation: 'manual' })\n if (!result) {\n log.show('No changes to stash.', { type: 'info' })\n }\n } catch (error) {\n // User cancelled the prompt\n log.show('Stash cancelled.', { type: 'info' })\n }\n }\n })\n\n // 子命令:列出 stash\n stashCmd\n .command('list')\n .alias('ls')\n .alias('l')\n .description('List all stashes')\n .action(async () => {\n await handleList()\n })\n\n // 子命令:弹出 stash\n stashCmd\n .command('pop')\n .alias('p')\n .description('Pop the most recent stash')\n .action(async () => {\n await handlePop()\n })\n\n // 子命令:删除 stash\n stashCmd\n .command('drop')\n .alias('d')\n .description('Drop/clear stashes')\n .action(async () => {\n await handleDrop()\n })\n\n stashCmd\n .command('clear')\n .alias('c')\n .description('clear stashes')\n .action(async () => {\n await handleClear()\n })\n\n // 子命令:查看 stash 历史\n stashCmd\n .command('history')\n .alias('his')\n .alias('h')\n .description('View stash history from persistent index')\n .option('--all', 'Show all records (no limit)')\n .option('--active', 'Show only active records')\n .option('--clean [days]', 'Clean old records (default: 30 days)')\n .action(async (options: { all?: boolean; active?: boolean; clean?: string }) => {\n await handleHistory(options)\n })\n\n return stashCmd\n}\n","import type { Command } from '@nemo-cli/shared'\nimport { log, xASync } from '@nemo-cli/shared'\nimport type { StatusFile } from '@nemo-cli/ui'\nimport { renderStatusViewer } from '@nemo-cli/ui'\n\n/**\n * 获取修改的文件列表\n */\nconst getStatusFiles = async (): Promise<StatusFile[]> => {\n const [error, result] = await xASync('git', ['status', '--porcelain'], { quiet: true })\n if (error) return []\n\n const lines = result.stdout.split('\\n').filter((line) => line.trim())\n const files: StatusFile[] = []\n\n for (const line of lines) {\n if (line.length < 3) continue\n\n const stagedStatus = line[0] ?? ' '\n const unstagedStatus = line[1] ?? ' '\n const path = line.slice(3).trim()\n\n // 确定文件的最终状态\n let status = unstagedStatus\n let staged = false\n\n if (unstagedStatus === ' ' && stagedStatus !== ' ' && stagedStatus !== '?') {\n // 已暂存\n status = stagedStatus\n staged = true\n } else if (unstagedStatus !== ' ') {\n // 未暂存的修改\n status = unstagedStatus\n staged = false\n }\n\n // 跳过未跟踪的文件(可选)\n if (status === '?') continue\n\n files.push({ path, status, staged })\n }\n\n return files\n}\n\nexport const statusCommand = (command: Command) => {\n command\n .command('status')\n .alias('s')\n .description('Show working tree status (interactive viewer)')\n .action(async () => {\n const files = await getStatusFiles()\n\n if (files.length === 0) {\n log.show('✓ Working directory clean', { type: 'success' })\n return\n }\n\n renderStatusViewer(files)\n })\n\n return command\n}\n","import { createCommand, exit, readPackage } from '@nemo-cli/shared'\nimport { ErrorMessage } from '@nemo-cli/ui'\nimport { blameCommand } from './commands/blame'\nimport { branchCommand } from './commands/branch'\nimport { checkoutCommand } from './commands/checkout'\nimport { commitCommand } from './commands/commit'\nimport { configCommand } from './commands/config'\nimport { diffCommand } from './commands/diff'\nimport { histCommand } from './commands/hist'\nimport { listCommand } from './commands/list'\nimport { mergeCommand } from './commands/merge'\nimport { pullCommand } from './commands/pull'\nimport { pushCommand } from './commands/push'\nimport { stashCommand } from './commands/stash'\nimport { statusCommand } from './commands/status'\nimport { HELP_MESSAGE } from './constants'\nimport { checkGitRepository } from './utils'\n\nexport const pkg = readPackage(import.meta, '..')\n\nexport const init = () => {\n const command = createCommand('ng')\n .version(pkg.version)\n .description(`${pkg.name} CLI helper for git`)\n .addHelpText('after', HELP_MESSAGE.main)\n\n pullCommand(command)\n listCommand(command)\n pushCommand(command)\n checkoutCommand(command)\n branchCommand(command)\n diffCommand(command)\n mergeCommand(command)\n stashCommand(command)\n blameCommand(command)\n commitCommand(command)\n statusCommand(command)\n histCommand(command)\n configCommand(command)\n\n return command\n}\n\nexport const run = async () => {\n const isGitRepository = await checkGitRepository()\n if (!isGitRepository) {\n ErrorMessage({ text: 'Not a git repository' })\n exit(0)\n }\n\n const command = init()\n command.parse(process.argv)\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nemo-cli/git",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "git flow handle",
5
5
  "author": "gaozimeng <gaozimeng0425@gmail.com>",
6
6
  "homepage": "https://github.com/GaoZimeng0425/nemo-cli#readme",
@@ -23,15 +23,6 @@
23
23
  "engines": {
24
24
  "node": "^20.19.0 || >=22.12.0"
25
25
  },
26
- "scripts": {
27
- "dev": "rolldown --watch -c ./rolldown.config.ts",
28
- "build": "rolldown -c ./rolldown.config.ts",
29
- "test": "vitest",
30
- "coverage": "vitest run --coverage",
31
- "check": "tsc --incremental --noEmit",
32
- "prepublish": "npm run build",
33
- "prepack": "rolldown"
34
- },
35
26
  "exports": {
36
27
  ".": {
37
28
  "import": "./dist/index.mjs"
@@ -46,7 +37,15 @@
46
37
  "url": "https://github.com/GaoZimeng0425/nemo-cli/issues"
47
38
  },
48
39
  "dependencies": {
49
- "@nemo-cli/shared": "workspace:*",
50
- "@nemo-cli/ui": "workspace:*"
40
+ "@nemo-cli/shared": "0.1.3",
41
+ "@nemo-cli/ui": "0.1.3"
42
+ },
43
+ "scripts": {
44
+ "dev": "rolldown --watch -c ./rolldown.config.ts",
45
+ "build": "rolldown -c ./rolldown.config.ts",
46
+ "test": "vitest",
47
+ "coverage": "vitest run --coverage",
48
+ "check": "tsc --incremental --noEmit",
49
+ "prepublish": "npm run build"
51
50
  }
52
- }
51
+ }