@namewta/fastcli 1.0.1 → 1.0.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/README.md CHANGED
@@ -1,209 +1,209 @@
1
- # FastCLI
2
-
3
- 终端命令别名和交互式工作流管理工具。
4
-
5
- ## 功能
6
-
7
- - **命令别名**:将冗长的命令映射为简短易记的名称
8
- - **交互式工作流**:创建多步骤、分支式的命令选择流程
9
-
10
- ## 安装
11
-
12
- ```bash
13
- # 全局安装(推荐)
14
- npm install -g fastcli
15
-
16
- # 或使用 pnpm
17
- pnpm add -g fastcli
18
- ```
19
-
20
- ## 快速开始
21
-
22
- ```bash
23
- # 初始化配置文件
24
- fastcli config init
25
-
26
- # 添加一个别名
27
- fastcli alias add c "claude --port 3000"
28
-
29
- # 运行别名
30
- fastcli c
31
-
32
- # 预览命令(不执行)
33
- fastcli c --dry-run
34
- ```
35
-
36
- ## 命令参考
37
-
38
- ### 配置管理
39
-
40
- ```bash
41
- fastcli config init # 初始化配置文件
42
- fastcli config show # 显示配置内容
43
- fastcli config edit # 用编辑器打开配置文件
44
- ```
45
-
46
- ### 别名管理
47
-
48
- ```bash
49
- fastcli alias add <name> <command> # 添加别名
50
- fastcli alias add ga "git add ." -d "暂存所有" # 带描述
51
- fastcli alias rm <name> # 删除别名
52
- fastcli alias ls # 列出所有别名
53
- ```
54
-
55
- ### 工作流管理
56
-
57
- ```bash
58
- fastcli workflow ls # 列出所有工作流
59
- fastcli workflow show <name> # 显示工作流结构
60
- ```
61
-
62
- ### 运行别名或工作流
63
-
64
- ```bash
65
- fastcli <name> # 运行别名或工作流
66
- fastcli <name> --dry-run # 预览命令但不执行
67
- ```
68
-
69
- ## 配置文件
70
-
71
- 配置文件位于 `~/.fastcli/config.json`:
72
-
73
- ```json
74
- {
75
- "aliases": {
76
- "c": {
77
- "command": "claude --port 3000",
78
- "description": "启动 Claude"
79
- },
80
- "ga": {
81
- "command": "git add .",
82
- "description": "暂存所有更改"
83
- },
84
- "gp": {
85
- "command": "git push"
86
- }
87
- },
88
- "workflows": {
89
- "git-flow": {
90
- "description": "Git 提交工作流",
91
- "steps": [
92
- {
93
- "id": "action",
94
- "prompt": "选择操作",
95
- "options": [
96
- { "name": "暂存所有", "value": "add", "next": "commit-type" },
97
- { "name": "查看状态", "command": "git status" }
98
- ]
99
- },
100
- {
101
- "id": "commit-type",
102
- "prompt": "选择提交类型",
103
- "options": [
104
- { "name": "feat: 新功能", "command": "git add . && git commit -m \"feat: {{commit-type}}\"" },
105
- { "name": "fix: 修复", "command": "git add . && git commit -m \"fix: {{commit-type}}\"" }
106
- ]
107
- }
108
- ]
109
- }
110
- }
111
- }
112
- ```
113
-
114
- ### 工作流配置说明
115
-
116
- 每个工作流包含多个步骤(steps),每个步骤包含:
117
-
118
- - `id`:步骤唯一标识
119
- - `prompt`:显示给用户的提示
120
- - `options`:可选项列表
121
- - `name`:选项名称
122
- - `value`:存储到上下文的值(可选,默认为 name)
123
- - `next`:跳转到的下一个步骤 ID
124
- - `command`:终止命令(选择此项后执行命令并结束工作流)
125
-
126
- ### 变量替换
127
-
128
- 在 `command` 中可以使用 `{{step-id}}` 引用之前步骤选择的值:
129
-
130
- ```json
131
- {
132
- "id": "account",
133
- "prompt": "选择账号",
134
- "options": [
135
- { "name": "账号1", "value": "user1", "next": "action" }
136
- ]
137
- },
138
- {
139
- "id": "action",
140
- "prompt": "执行操作",
141
- "options": [
142
- { "name": "登录", "command": "login --user={{account}}" }
143
- ]
144
- }
145
- ```
146
-
147
- ## 示例:Copilot 账号切换工作流
148
-
149
- ```json
150
- {
151
- "workflows": {
152
- "copilot": {
153
- "description": "Copilot 账号切换",
154
- "steps": [
155
- {
156
- "id": "account",
157
- "prompt": "选择账号",
158
- "options": [
159
- { "name": "工作账号", "value": "work@example.com", "next": "action" },
160
- { "name": "个人账号", "value": "personal@gmail.com", "next": "action" }
161
- ]
162
- },
163
- {
164
- "id": "action",
165
- "prompt": "执行操作",
166
- "options": [
167
- { "name": "登录", "command": "gh auth login -h github.com -u {{account}}" },
168
- { "name": "查看状态", "command": "gh auth status" }
169
- ]
170
- }
171
- ]
172
- }
173
- }
174
- }
175
- ```
176
-
177
- 使用:`fastcli copilot`
178
-
179
- ## 开发
180
-
181
- ```bash
182
- # 安装依赖
183
- pnpm install
184
-
185
- # 开发模式(监听文件变化)
186
- pnpm dev
187
-
188
- # 构建
189
- pnpm build
190
-
191
- # 运行测试
192
- pnpm test
193
-
194
- # 本地链接(用于测试)
195
- pnpm link -g
196
- ```
197
-
198
- ## 技术栈
199
-
200
- - Node.js >= 18
201
- - TypeScript
202
- - Commander.js(CLI 框架)
203
- - @inquirer/prompts(交互式选择)
204
- - Vitest(测试)
205
- - tsup(构建)
206
-
207
- ## License
208
-
209
- MIT © [namewta](https://github.com/namewta)
1
+ # FastCLI
2
+
3
+ 终端命令别名和交互式工作流管理工具。
4
+
5
+ ## 功能
6
+
7
+ - **命令别名**:将冗长的命令映射为简短易记的名称
8
+ - **交互式工作流**:创建多步骤、分支式的命令选择流程
9
+
10
+ ## 安装
11
+
12
+ ```bash
13
+ # 全局安装(推荐)
14
+ npm install -g fastcli
15
+
16
+ # 或使用 pnpm
17
+ pnpm add -g fastcli
18
+ ```
19
+
20
+ ## 快速开始
21
+
22
+ ```bash
23
+ # 初始化配置文件
24
+ fastcli config init
25
+
26
+ # 添加一个别名
27
+ fastcli alias add c "claude --port 3000"
28
+
29
+ # 运行别名
30
+ fastcli c
31
+
32
+ # 预览命令(不执行)
33
+ fastcli c --dry-run
34
+ ```
35
+
36
+ ## 命令参考
37
+
38
+ ### 配置管理
39
+
40
+ ```bash
41
+ fastcli config init # 初始化配置文件
42
+ fastcli config show # 显示配置内容
43
+ fastcli config edit # 用编辑器打开配置文件
44
+ ```
45
+
46
+ ### 别名管理
47
+
48
+ ```bash
49
+ fastcli alias add <name> <command> # 添加别名
50
+ fastcli alias add ga "git add ." -d "暂存所有" # 带描述
51
+ fastcli alias rm <name> # 删除别名
52
+ fastcli alias ls # 列出所有别名
53
+ ```
54
+
55
+ ### 工作流管理
56
+
57
+ ```bash
58
+ fastcli workflow ls # 列出所有工作流
59
+ fastcli workflow show <name> # 显示工作流结构
60
+ ```
61
+
62
+ ### 运行别名或工作流
63
+
64
+ ```bash
65
+ fastcli <name> # 运行别名或工作流
66
+ fastcli <name> --dry-run # 预览命令但不执行
67
+ ```
68
+
69
+ ## 配置文件
70
+
71
+ 配置文件位于 `~/.fastcli/config.json`:
72
+
73
+ ```json
74
+ {
75
+ "aliases": {
76
+ "c": {
77
+ "command": "claude --port 3000",
78
+ "description": "启动 Claude"
79
+ },
80
+ "ga": {
81
+ "command": "git add .",
82
+ "description": "暂存所有更改"
83
+ },
84
+ "gp": {
85
+ "command": "git push"
86
+ }
87
+ },
88
+ "workflows": {
89
+ "git-flow": {
90
+ "description": "Git 提交工作流",
91
+ "steps": [
92
+ {
93
+ "id": "action",
94
+ "prompt": "选择操作",
95
+ "options": [
96
+ { "name": "暂存所有", "value": "add", "next": "commit-type" },
97
+ { "name": "查看状态", "command": "git status" }
98
+ ]
99
+ },
100
+ {
101
+ "id": "commit-type",
102
+ "prompt": "选择提交类型",
103
+ "options": [
104
+ { "name": "feat: 新功能", "command": "git add . && git commit -m \"feat: {{commit-type}}\"" },
105
+ { "name": "fix: 修复", "command": "git add . && git commit -m \"fix: {{commit-type}}\"" }
106
+ ]
107
+ }
108
+ ]
109
+ }
110
+ }
111
+ }
112
+ ```
113
+
114
+ ### 工作流配置说明
115
+
116
+ 每个工作流包含多个步骤(steps),每个步骤包含:
117
+
118
+ - `id`:步骤唯一标识
119
+ - `prompt`:显示给用户的提示
120
+ - `options`:可选项列表
121
+ - `name`:选项名称
122
+ - `value`:存储到上下文的值(可选,默认为 name)
123
+ - `next`:跳转到的下一个步骤 ID
124
+ - `command`:终止命令(选择此项后执行命令并结束工作流)
125
+
126
+ ### 变量替换
127
+
128
+ 在 `command` 中可以使用 `{{step-id}}` 引用之前步骤选择的值:
129
+
130
+ ```json
131
+ {
132
+ "id": "account",
133
+ "prompt": "选择账号",
134
+ "options": [
135
+ { "name": "账号1", "value": "user1", "next": "action" }
136
+ ]
137
+ },
138
+ {
139
+ "id": "action",
140
+ "prompt": "执行操作",
141
+ "options": [
142
+ { "name": "登录", "command": "login --user={{account}}" }
143
+ ]
144
+ }
145
+ ```
146
+
147
+ ## 示例:Copilot 账号切换工作流
148
+
149
+ ```json
150
+ {
151
+ "workflows": {
152
+ "copilot": {
153
+ "description": "Copilot 账号切换",
154
+ "steps": [
155
+ {
156
+ "id": "account",
157
+ "prompt": "选择账号",
158
+ "options": [
159
+ { "name": "工作账号", "value": "work@example.com", "next": "action" },
160
+ { "name": "个人账号", "value": "personal@gmail.com", "next": "action" }
161
+ ]
162
+ },
163
+ {
164
+ "id": "action",
165
+ "prompt": "执行操作",
166
+ "options": [
167
+ { "name": "登录", "command": "gh auth login -h github.com -u {{account}}" },
168
+ { "name": "查看状态", "command": "gh auth status" }
169
+ ]
170
+ }
171
+ ]
172
+ }
173
+ }
174
+ }
175
+ ```
176
+
177
+ 使用:`fastcli copilot`
178
+
179
+ ## 开发
180
+
181
+ ```bash
182
+ # 安装依赖
183
+ pnpm install
184
+
185
+ # 开发模式(监听文件变化)
186
+ pnpm dev
187
+
188
+ # 构建
189
+ pnpm build
190
+
191
+ # 运行测试
192
+ pnpm test
193
+
194
+ # 本地链接(用于测试)
195
+ pnpm link -g
196
+ ```
197
+
198
+ ## 技术栈
199
+
200
+ - Node.js >= 18
201
+ - TypeScript
202
+ - Commander.js(CLI 框架)
203
+ - @inquirer/prompts(交互式选择)
204
+ - Vitest(测试)
205
+ - tsup(构建)
206
+
207
+ ## License
208
+
209
+ MIT © [namewta](https://github.com/namewta)
package/dist/index.js CHANGED
@@ -302,8 +302,8 @@ async function executeCommand(command) {
302
302
  logger.preview(command);
303
303
  return new Promise((resolve) => {
304
304
  const isWindows = process.platform === "win32";
305
- const shell = isWindows ? "cmd.exe" : "/bin/sh";
306
- const shellArg = isWindows ? "/c" : "-c";
305
+ const shell = isWindows ? "powershell.exe" : "/bin/sh";
306
+ const shellArg = isWindows ? "-Command" : "-c";
307
307
  const child = spawn2(shell, [shellArg, command], {
308
308
  stdio: ["inherit", "pipe", "pipe"],
309
309
  env: process.env
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/config/init.ts","../src/utils/path.ts","../src/core/config-manager.ts","../src/types/index.ts","../src/utils/logger.ts","../src/commands/config/edit.ts","../src/commands/config/show.ts","../src/core/name-resolver.ts","../src/commands/alias/add.ts","../src/commands/alias/remove.ts","../src/commands/alias/list.ts","../src/commands/workflow/list.ts","../src/commands/workflow/show.ts","../src/commands/run.ts","../src/core/executor.ts","../src/core/workflow-runner.ts","../src/core/template-engine.ts"],"sourcesContent":["import { Command } from 'commander';\r\nimport { configInit, configEdit, configShow } from './commands/config/index.js';\r\nimport { aliasAdd, aliasRemove, aliasList } from './commands/alias/index.js';\r\nimport { workflowList, workflowShow } from './commands/workflow/index.js';\r\nimport { run } from './commands/run.js';\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name('fastcli')\r\n .description('终端命令别名和交互式工作流管理工具')\r\n .version('1.0.0');\r\n\r\n// config 命令组\r\nconst configCmd = program.command('config').description('配置管理');\r\n\r\nconfigCmd\r\n .command('init')\r\n .description('初始化配置文件')\r\n .action(configInit);\r\n\r\nconfigCmd\r\n .command('edit')\r\n .description('编辑配置文件')\r\n .action(configEdit);\r\n\r\nconfigCmd\r\n .command('show')\r\n .description('显示配置内容')\r\n .action(configShow);\r\n\r\n// alias 命令组\r\nconst aliasCmd = program.command('alias').description('别名管理');\r\n\r\naliasCmd\r\n .command('add <name> <command>')\r\n .description('添加新别名')\r\n .option('-d, --description <desc>', '别名描述')\r\n .action(aliasAdd);\r\n\r\naliasCmd\r\n .command('rm <name>')\r\n .description('删除别名')\r\n .action(aliasRemove);\r\n\r\naliasCmd\r\n .command('ls')\r\n .description('列出所有别名')\r\n .action(aliasList);\r\n\r\n// workflow 命令组\r\nconst workflowCmd = program.command('workflow').description('工作流管理');\r\n\r\nworkflowCmd\r\n .command('ls')\r\n .description('列出所有工作流')\r\n .action(workflowList);\r\n\r\nworkflowCmd\r\n .command('show <name>')\r\n .description('显示工作流结构')\r\n .action(workflowShow);\r\n\r\n// 默认命令:运行别名或工作流\r\nprogram\r\n .argument('[name]', '别名或工作流名称')\r\n .option('--dry-run', '预览命令但不执行')\r\n .action(async (name: string | undefined, options: { dryRun?: boolean }) => {\r\n if (!name) {\r\n program.help();\r\n return;\r\n }\r\n await run(name, { dryRun: options.dryRun });\r\n });\r\n\r\nprogram.parse();\r\n","import { existsSync } from 'node:fs';\r\nimport { getConfigPath } from '../../utils/path.js';\r\nimport { ensureConfigExists } from '../../core/config-manager.js';\r\nimport { logger } from '../../utils/logger.js';\r\n\r\nexport function configInit(): void {\r\n const configPath = getConfigPath();\r\n\r\n if (existsSync(configPath)) {\r\n logger.warn(`配置文件已存在: ${configPath}`);\r\n return;\r\n }\r\n\r\n ensureConfigExists(configPath);\r\n logger.success(`配置文件已创建: ${configPath}`);\r\n}\r\n","import { homedir } from 'node:os';\r\nimport { join } from 'node:path';\r\n\r\n/**\r\n * 获取配置目录路径\r\n * @returns ~/.fastcli/\r\n */\r\nexport function getConfigDir(): string {\r\n return join(homedir(), '.fastcli');\r\n}\r\n\r\n/**\r\n * 获取配置文件路径\r\n * @returns ~/.fastcli/config.json\r\n */\r\nexport function getConfigPath(): string {\r\n return join(getConfigDir(), 'config.json');\r\n}\r\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\r\nimport { dirname } from 'node:path';\r\nimport { getConfigPath } from '../utils/path.js';\r\nimport { DEFAULT_CONFIG, type Config, type ValidationResult } from '../types/index.js';\r\n\r\n/**\r\n * 加载配置文件\r\n * @param configPath - 配置文件路径(默认使用标准路径)\r\n */\r\nexport function loadConfig(configPath: string = getConfigPath()): Config {\r\n if (!existsSync(configPath)) {\r\n throw new Error(`配置文件不存在: ${configPath}\\n请运行 fastcli config init 初始化`);\r\n }\r\n\r\n const content = readFileSync(configPath, 'utf-8');\r\n try {\r\n return JSON.parse(content) as Config;\r\n } catch {\r\n throw new Error(`配置文件格式错误: ${configPath}`);\r\n }\r\n}\r\n\r\n/**\r\n * 保存配置文件\r\n * @param config - 配置对象\r\n * @param configPath - 配置文件路径(默认使用标准路径)\r\n */\r\nexport function saveConfig(\r\n config: Config,\r\n configPath: string = getConfigPath()\r\n): void {\r\n const dir = dirname(configPath);\r\n if (!existsSync(dir)) {\r\n mkdirSync(dir, { recursive: true });\r\n }\r\n writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');\r\n}\r\n\r\n/**\r\n * 确保配置文件存在,不存在则创建默认配置\r\n * @param configPath - 配置文件路径(默认使用标准路径)\r\n */\r\nexport function ensureConfigExists(configPath: string = getConfigPath()): void {\r\n if (!existsSync(configPath)) {\r\n saveConfig(DEFAULT_CONFIG, configPath);\r\n }\r\n}\r\n\r\n/**\r\n * 校验配置文件\r\n * @param config - 配置对象\r\n */\r\nexport function validateConfig(config: Config): ValidationResult {\r\n const errors: string[] = [];\r\n\r\n // 检查 aliases 和 workflows 名称冲突\r\n const aliasNames = Object.keys(config.aliases);\r\n const workflowNames = Object.keys(config.workflows);\r\n const conflicts = aliasNames.filter((name) => workflowNames.includes(name));\r\n\r\n if (conflicts.length > 0) {\r\n errors.push(`名称冲突: ${conflicts.join(', ')} 同时存在于 aliases 和 workflows 中`);\r\n }\r\n\r\n // 检查工作流步骤引用是否有效\r\n for (const [name, workflow] of Object.entries(config.workflows)) {\r\n const stepIds = new Set(workflow.steps.map((s) => s.id));\r\n for (const step of workflow.steps) {\r\n for (const option of step.options) {\r\n if (option.next && !stepIds.has(option.next)) {\r\n errors.push(`工作流 \"${name}\" 步骤 \"${step.id}\" 引用了不存在的步骤 \"${option.next}\"`);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors,\r\n };\r\n}\r\n","/**\r\n * 配置文件根结构\r\n */\r\nexport interface Config {\r\n aliases: Record<string, Alias>;\r\n workflows: Record<string, Workflow>;\r\n}\r\n\r\n/**\r\n * 命令别名\r\n */\r\nexport interface Alias {\r\n command: string;\r\n description?: string;\r\n}\r\n\r\n/**\r\n * 工作流定义\r\n */\r\nexport interface Workflow {\r\n description?: string;\r\n steps: WorkflowStep[];\r\n}\r\n\r\n/**\r\n * 工作流步骤\r\n */\r\nexport interface WorkflowStep {\r\n id: string;\r\n prompt: string;\r\n options: WorkflowOption[];\r\n}\r\n\r\n/**\r\n * 工作流选项\r\n */\r\nexport interface WorkflowOption {\r\n name: string;\r\n value?: string;\r\n next?: string;\r\n command?: string;\r\n}\r\n\r\n/**\r\n * 工作流运行时上下文\r\n */\r\nexport interface WorkflowContext {\r\n values: Record<string, string>;\r\n}\r\n\r\n/**\r\n * 名称解析结果\r\n */\r\nexport type ResolveResult =\r\n | { type: 'alias'; data: Alias }\r\n | { type: 'workflow'; data: Workflow };\r\n\r\n/**\r\n * 命令执行结果\r\n */\r\nexport interface ExecResult {\r\n success: boolean;\r\n code: number;\r\n stdout: string;\r\n stderr: string;\r\n}\r\n\r\n/**\r\n * 配置校验结果\r\n */\r\nexport interface ValidationResult {\r\n valid: boolean;\r\n errors: string[];\r\n}\r\n\r\n/**\r\n * 默认空配置\r\n */\r\nexport const DEFAULT_CONFIG: Config = {\r\n aliases: {},\r\n workflows: {},\r\n};\r\n","import pc from 'picocolors';\r\n\r\nexport const logger = {\r\n info(message: string): void {\r\n console.log(pc.blue('ℹ'), message);\r\n },\r\n\r\n success(message: string): void {\r\n console.log(pc.green('✓'), message);\r\n },\r\n\r\n error(message: string): void {\r\n console.error(pc.red('✗'), message);\r\n },\r\n\r\n warn(message: string): void {\r\n console.log(pc.yellow('⚠'), message);\r\n },\r\n\r\n preview(command: string): void {\r\n console.log(pc.cyan('→'), pc.dim('执行:'), command);\r\n },\r\n\r\n step(current: number, total: number, message: string): void {\r\n console.log(pc.dim(`[步骤 ${current}/${total}]`), message);\r\n },\r\n\r\n choice(message: string): void {\r\n console.log(pc.cyan('→'), pc.dim('选择:'), message);\r\n },\r\n};\r\n","import { spawn } from 'node:child_process';\r\nimport { existsSync } from 'node:fs';\r\nimport { getConfigPath } from '../../utils/path.js';\r\nimport { logger } from '../../utils/logger.js';\r\n\r\nexport function configEdit(): void {\r\n const configPath = getConfigPath();\r\n\r\n if (!existsSync(configPath)) {\r\n logger.error(`配置文件不存在: ${configPath}`);\r\n logger.info('请先运行: fastcli config init');\r\n return;\r\n }\r\n\r\n const isWindows = process.platform === 'win32';\r\n const editor = process.env.EDITOR || (isWindows ? 'notepad' : 'vi');\r\n\r\n logger.info(`使用 ${editor} 打开配置文件...`);\r\n\r\n const child = spawn(editor, [configPath], {\r\n stdio: 'inherit',\r\n shell: true,\r\n });\r\n\r\n child.on('error', (err) => {\r\n logger.error(`无法打开编辑器: ${err.message}`);\r\n });\r\n}\r\n","import { existsSync, readFileSync } from 'node:fs';\r\nimport { getConfigPath } from '../../utils/path.js';\r\nimport { logger } from '../../utils/logger.js';\r\n\r\nexport function configShow(): void {\r\n const configPath = getConfigPath();\r\n\r\n if (!existsSync(configPath)) {\r\n logger.error(`配置文件不存在: ${configPath}`);\r\n logger.info('请先运行: fastcli config init');\r\n return;\r\n }\r\n\r\n logger.info(`配置文件路径: ${configPath}`);\r\n console.log();\r\n console.log(readFileSync(configPath, 'utf-8'));\r\n}\r\n","import type { Config, ResolveResult } from '../types/index.js';\r\n\r\n/**\r\n * 解析名称,判断是别名还是工作流\r\n * @param name - 用户输入的名称\r\n * @param config - 配置对象\r\n * @returns 解析结果,不存在返回 null\r\n */\r\nexport function resolveName(name: string, config: Config): ResolveResult | null {\r\n if (name in config.aliases) {\r\n return { type: 'alias', data: config.aliases[name] };\r\n }\r\n\r\n if (name in config.workflows) {\r\n return { type: 'workflow', data: config.workflows[name] };\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * 检查名称是否可用(未被 alias 或 workflow 占用)\r\n * @param name - 要检查的名称\r\n * @param config - 配置对象\r\n */\r\nexport function isNameAvailable(name: string, config: Config): boolean {\r\n return !(name in config.aliases) && !(name in config.workflows);\r\n}\r\n\r\n/**\r\n * 获取所有已使用的名称\r\n * @param config - 配置对象\r\n */\r\nexport function getAllNames(config: Config): string[] {\r\n return [...Object.keys(config.aliases), ...Object.keys(config.workflows)];\r\n}\r\n\r\n/**\r\n * 查找相似名称(用于错误提示)\r\n * @param name - 用户输入的名称\r\n * @param config - 配置对象\r\n */\r\nexport function findSimilarNames(name: string, config: Config): string[] {\r\n const allNames = getAllNames(config);\r\n return allNames.filter(\r\n (n) => n.includes(name) || name.includes(n) || levenshteinDistance(n, name) <= 2\r\n );\r\n}\r\n\r\nfunction levenshteinDistance(a: string, b: string): number {\r\n const matrix: number[][] = [];\r\n for (let i = 0; i <= b.length; i++) {\r\n matrix[i] = [i];\r\n }\r\n for (let j = 0; j <= a.length; j++) {\r\n matrix[0][j] = j;\r\n }\r\n for (let i = 1; i <= b.length; i++) {\r\n for (let j = 1; j <= a.length; j++) {\r\n if (b.charAt(i - 1) === a.charAt(j - 1)) {\r\n matrix[i][j] = matrix[i - 1][j - 1];\r\n } else {\r\n matrix[i][j] = Math.min(\r\n matrix[i - 1][j - 1] + 1,\r\n matrix[i][j - 1] + 1,\r\n matrix[i - 1][j] + 1\r\n );\r\n }\r\n }\r\n }\r\n return matrix[b.length][a.length];\r\n}\r\n","import { loadConfig, saveConfig, ensureConfigExists } from '../../core/config-manager.js';\r\nimport { isNameAvailable } from '../../core/name-resolver.js';\r\nimport { logger } from '../../utils/logger.js';\r\nimport { getConfigPath } from '../../utils/path.js';\r\n\r\nexport function aliasAdd(\r\n name: string,\r\n command: string,\r\n options: { description?: string }\r\n): void {\r\n const configPath = getConfigPath();\r\n ensureConfigExists(configPath);\r\n\r\n const config = loadConfig(configPath);\r\n\r\n if (!isNameAvailable(name, config)) {\r\n logger.error(`名称 \"${name}\" 已被使用`);\r\n return;\r\n }\r\n\r\n config.aliases[name] = {\r\n command,\r\n description: options.description,\r\n };\r\n\r\n saveConfig(config, configPath);\r\n logger.success(`别名已添加: ${name} → ${command}`);\r\n}\r\n","import { loadConfig, saveConfig } from '../../core/config-manager.js';\r\nimport { logger } from '../../utils/logger.js';\r\nimport { getConfigPath } from '../../utils/path.js';\r\nimport { existsSync } from 'node:fs';\r\n\r\nexport function aliasRemove(name: string): void {\r\n const configPath = getConfigPath();\r\n\r\n if (!existsSync(configPath)) {\r\n logger.error('配置文件不存在,请先运行: fastcli config init');\r\n return;\r\n }\r\n\r\n const config = loadConfig(configPath);\r\n\r\n if (!(name in config.aliases)) {\r\n logger.error(`别名 \"${name}\" 不存在`);\r\n return;\r\n }\r\n\r\n delete config.aliases[name];\r\n saveConfig(config, configPath);\r\n logger.success(`别名已删除: ${name}`);\r\n}\r\n","import { existsSync } from 'node:fs';\r\nimport { loadConfig } from '../../core/config-manager.js';\r\nimport { logger } from '../../utils/logger.js';\r\nimport { getConfigPath } from '../../utils/path.js';\r\nimport pc from 'picocolors';\r\n\r\nexport function aliasList(): void {\r\n const configPath = getConfigPath();\r\n\r\n if (!existsSync(configPath)) {\r\n logger.error('配置文件不存在,请先运行: fastcli config init');\r\n return;\r\n }\r\n\r\n const config = loadConfig(configPath);\r\n const aliases = Object.entries(config.aliases);\r\n\r\n if (aliases.length === 0) {\r\n logger.info('暂无别名');\r\n return;\r\n }\r\n\r\n console.log();\r\n console.log(pc.bold('别名列表:'));\r\n console.log();\r\n\r\n for (const [name, alias] of aliases) {\r\n console.log(` ${pc.cyan(name)} → ${alias.command}`);\r\n if (alias.description) {\r\n console.log(` ${pc.dim(alias.description)}`);\r\n }\r\n }\r\n console.log();\r\n}\r\n","import { existsSync } from 'node:fs';\r\nimport { loadConfig } from '../../core/config-manager.js';\r\nimport { logger } from '../../utils/logger.js';\r\nimport { getConfigPath } from '../../utils/path.js';\r\nimport pc from 'picocolors';\r\n\r\nexport function workflowList(): void {\r\n const configPath = getConfigPath();\r\n\r\n if (!existsSync(configPath)) {\r\n logger.error('配置文件不存在,请先运行: fastcli config init');\r\n return;\r\n }\r\n\r\n const config = loadConfig(configPath);\r\n const workflows = Object.entries(config.workflows);\r\n\r\n if (workflows.length === 0) {\r\n logger.info('暂无工作流');\r\n return;\r\n }\r\n\r\n console.log();\r\n console.log(pc.bold('工作流列表:'));\r\n console.log();\r\n\r\n for (const [name, workflow] of workflows) {\r\n const stepCount = workflow.steps.length;\r\n console.log(` ${pc.cyan(name)} (${stepCount} 步)`);\r\n if (workflow.description) {\r\n console.log(` ${pc.dim(workflow.description)}`);\r\n }\r\n }\r\n console.log();\r\n}\r\n","import { existsSync } from 'node:fs';\r\nimport { loadConfig } from '../../core/config-manager.js';\r\nimport { logger } from '../../utils/logger.js';\r\nimport { getConfigPath } from '../../utils/path.js';\r\nimport pc from 'picocolors';\r\n\r\nexport function workflowShow(name: string): void {\r\n const configPath = getConfigPath();\r\n\r\n if (!existsSync(configPath)) {\r\n logger.error('配置文件不存在,请先运行: fastcli config init');\r\n return;\r\n }\r\n\r\n const config = loadConfig(configPath);\r\n\r\n if (!(name in config.workflows)) {\r\n logger.error(`工作流 \"${name}\" 不存在`);\r\n return;\r\n }\r\n\r\n const workflow = config.workflows[name];\r\n\r\n console.log();\r\n console.log(pc.bold(`工作流: ${name}`));\r\n if (workflow.description) {\r\n console.log(pc.dim(workflow.description));\r\n }\r\n console.log();\r\n\r\n for (const step of workflow.steps) {\r\n console.log(`${pc.cyan('●')} ${pc.bold(step.id)}: ${step.prompt}`);\r\n\r\n for (const option of step.options) {\r\n const arrow = option.next ? `→ ${pc.yellow(option.next)}` : '';\r\n const cmd = option.command ? `→ ${pc.green(option.command)}` : '';\r\n console.log(` └─ ${option.name} ${arrow}${cmd}`);\r\n }\r\n console.log();\r\n }\r\n}\r\n","import { existsSync } from 'node:fs';\r\nimport { loadConfig } from '../core/config-manager.js';\r\nimport { resolveName, findSimilarNames } from '../core/name-resolver.js';\r\nimport { executeCommand } from '../core/executor.js';\r\nimport { runWorkflow } from '../core/workflow-runner.js';\r\nimport { logger } from '../utils/logger.js';\r\nimport { getConfigPath } from '../utils/path.js';\r\n\r\nexport interface RunOptions {\r\n dryRun?: boolean;\r\n}\r\n\r\nexport async function run(name: string, options: RunOptions = {}): Promise<void> {\r\n const configPath = getConfigPath();\r\n\r\n if (!existsSync(configPath)) {\r\n logger.error('配置文件不存在');\r\n logger.info('请先运行: fastcli config init');\r\n return;\r\n }\r\n\r\n const config = loadConfig(configPath);\r\n const result = resolveName(name, config);\r\n\r\n if (!result) {\r\n logger.error(`未找到: ${name}`);\r\n\r\n const similar = findSimilarNames(name, config);\r\n if (similar.length > 0) {\r\n logger.info(`你是否想要: ${similar.join(', ')}?`);\r\n }\r\n return;\r\n }\r\n\r\n if (result.type === 'alias') {\r\n console.log();\r\n if (options.dryRun) {\r\n logger.preview(`将执行: ${result.data.command}`);\r\n } else {\r\n await executeCommand(result.data.command);\r\n }\r\n } else {\r\n await runWorkflow(result.data, options.dryRun);\r\n }\r\n}\r\n","import { spawn } from 'node:child_process';\r\nimport { logger } from '../utils/logger.js';\r\nimport type { ExecResult } from '../types/index.js';\r\n\r\n/**\r\n * 执行 shell 命令\r\n * @param command - 要执行的命令\r\n * @returns 执行结果\r\n */\r\nexport async function executeCommand(command: string): Promise<ExecResult> {\r\n logger.preview(command);\r\n\r\n return new Promise((resolve) => {\r\n const isWindows = process.platform === 'win32';\r\n const shell = isWindows ? 'cmd.exe' : '/bin/sh';\r\n const shellArg = isWindows ? '/c' : '-c';\r\n\r\n const child = spawn(shell, [shellArg, command], {\r\n stdio: ['inherit', 'pipe', 'pipe'],\r\n env: process.env,\r\n });\r\n\r\n let stdout = '';\r\n let stderr = '';\r\n\r\n child.stdout?.on('data', (data) => {\r\n const text = data.toString();\r\n stdout += text;\r\n process.stdout.write(text);\r\n });\r\n\r\n child.stderr?.on('data', (data) => {\r\n const text = data.toString();\r\n stderr += text;\r\n process.stderr.write(text);\r\n });\r\n\r\n child.on('close', (code) => {\r\n const success = code === 0;\r\n if (success) {\r\n logger.success('执行完成');\r\n } else {\r\n logger.error(`执行失败 (退出码: ${code})`);\r\n }\r\n\r\n resolve({\r\n success,\r\n code: code ?? 1,\r\n stdout,\r\n stderr,\r\n });\r\n });\r\n\r\n child.on('error', (err) => {\r\n logger.error(`执行出错: ${err.message}`);\r\n resolve({\r\n success: false,\r\n code: 1,\r\n stdout,\r\n stderr: err.message,\r\n });\r\n });\r\n });\r\n}\r\n","import { select } from '@inquirer/prompts';\r\nimport { logger } from '../utils/logger.js';\r\nimport { parseTemplate } from './template-engine.js';\r\nimport { executeCommand } from './executor.js';\r\nimport type { Workflow, WorkflowStep, WorkflowContext } from '../types/index.js';\r\n\r\n/**\r\n * 根据 ID 查找步骤\r\n */\r\nexport function findStepById(workflow: Workflow, id: string): WorkflowStep | undefined {\r\n return workflow.steps.find((s) => s.id === id);\r\n}\r\n\r\n/**\r\n * 构建最终命令(替换变量)\r\n */\r\nexport function buildFinalCommand(\r\n command: string,\r\n context: Record<string, string>\r\n): string {\r\n return parseTemplate(command, context);\r\n}\r\n\r\n/**\r\n * 计算从某步骤开始的最短路径长度(用于进度显示)\r\n */\r\nexport function calculateTotalSteps(workflow: Workflow, startId: string): number {\r\n const visited = new Set<string>();\r\n let minSteps = Infinity;\r\n\r\n function traverse(stepId: string, depth: number): void {\r\n if (visited.has(stepId)) return;\r\n visited.add(stepId);\r\n\r\n const step = findStepById(workflow, stepId);\r\n if (!step) return;\r\n\r\n for (const option of step.options) {\r\n if (option.command) {\r\n minSteps = Math.min(minSteps, depth);\r\n } else if (option.next) {\r\n traverse(option.next, depth + 1);\r\n }\r\n }\r\n\r\n visited.delete(stepId);\r\n }\r\n\r\n traverse(startId, 1);\r\n return minSteps === Infinity ? workflow.steps.length : minSteps;\r\n}\r\n\r\n/**\r\n * 运行工作流\r\n */\r\nexport async function runWorkflow(workflow: Workflow, dryRun = false): Promise<void> {\r\n if (workflow.steps.length === 0) {\r\n logger.error('工作流没有步骤');\r\n return;\r\n }\r\n\r\n const context: WorkflowContext = { values: {} };\r\n let currentStep = workflow.steps[0];\r\n let stepIndex = 1;\r\n const estimatedTotal = calculateTotalSteps(workflow, currentStep.id);\r\n\r\n console.log();\r\n if (workflow.description) {\r\n logger.info(workflow.description);\r\n }\r\n\r\n while (true) {\r\n logger.step(stepIndex, estimatedTotal, currentStep.prompt);\r\n\r\n const choices = currentStep.options.map((opt, index) => ({\r\n name: `${index + 1}. ${opt.name}`,\r\n value: opt,\r\n }));\r\n\r\n try {\r\n const selected = await select({\r\n message: '请选择',\r\n choices,\r\n });\r\n\r\n // 记录选择的值\r\n const value = selected.value ?? selected.name;\r\n context.values[currentStep.id] = value;\r\n logger.choice(selected.name);\r\n\r\n // 如果有 command,执行并结束\r\n if (selected.command) {\r\n const finalCommand = buildFinalCommand(selected.command, context.values);\r\n console.log();\r\n if (dryRun) {\r\n logger.preview(`将执行: ${finalCommand}`);\r\n } else {\r\n await executeCommand(finalCommand);\r\n }\r\n console.log();\r\n logger.success('工作流完成');\r\n return;\r\n }\r\n\r\n // 如果有 next,跳转到下一步\r\n if (selected.next) {\r\n const nextStep = findStepById(workflow, selected.next);\r\n if (!nextStep) {\r\n logger.error(`找不到步骤: ${selected.next}`);\r\n return;\r\n }\r\n currentStep = nextStep;\r\n stepIndex++;\r\n console.log();\r\n } else {\r\n // 既没有 command 也没有 next,工作流配置错误\r\n logger.error('工作流配置错误:选项缺少 command 或 next');\r\n return;\r\n }\r\n } catch {\r\n // 用户按 Ctrl+C 退出\r\n console.log();\r\n logger.warn('已取消');\r\n return;\r\n }\r\n }\r\n}\r\n","/**\r\n * 解析模板字符串,替换 {{variable}} 为上下文中的值\r\n * @param template - 包含 {{var}} 占位符的模板字符串\r\n * @param context - 变量名到值的映射\r\n * @returns 替换后的字符串\r\n */\r\nexport function parseTemplate(\r\n template: string,\r\n context: Record<string, string>\r\n): string {\r\n return template.replace(/\\{\\{([^}]+)\\}\\}/g, (match, key) => {\r\n const trimmedKey = key.trim();\r\n return trimmedKey in context ? context[trimmedKey] : match;\r\n });\r\n}\r\n"],"mappings":";;;AAAA,SAAS,eAAe;;;ACAxB,SAAS,cAAAA,mBAAkB;;;ACA3B,SAAS,eAAe;AACxB,SAAS,YAAY;AAMd,SAAS,eAAuB;AACrC,SAAO,KAAK,QAAQ,GAAG,UAAU;AACnC;AAMO,SAAS,gBAAwB;AACtC,SAAO,KAAK,aAAa,GAAG,aAAa;AAC3C;;;ACjBA,SAAS,cAAc,eAAe,YAAY,iBAAiB;AACnE,SAAS,eAAe;;;AC6EjB,IAAM,iBAAyB;AAAA,EACpC,SAAS,CAAC;AAAA,EACV,WAAW,CAAC;AACd;;;ADxEO,SAAS,WAAW,aAAqB,cAAc,GAAW;AACvE,MAAI,CAAC,WAAW,UAAU,GAAG;AAC3B,UAAM,IAAI,MAAM,+CAAY,UAAU;AAAA,0DAA+B;AAAA,EACvE;AAEA,QAAM,UAAU,aAAa,YAAY,OAAO;AAChD,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,UAAM,IAAI,MAAM,qDAAa,UAAU,EAAE;AAAA,EAC3C;AACF;AAOO,SAAS,WACd,QACA,aAAqB,cAAc,GAC7B;AACN,QAAM,MAAM,QAAQ,UAAU;AAC9B,MAAI,CAAC,WAAW,GAAG,GAAG;AACpB,cAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,EACpC;AACA,gBAAc,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,GAAG,OAAO;AACpE;AAMO,SAAS,mBAAmB,aAAqB,cAAc,GAAS;AAC7E,MAAI,CAAC,WAAW,UAAU,GAAG;AAC3B,eAAW,gBAAgB,UAAU;AAAA,EACvC;AACF;;;AE9CA,OAAO,QAAQ;AAER,IAAM,SAAS;AAAA,EACpB,KAAK,SAAuB;AAC1B,YAAQ,IAAI,GAAG,KAAK,QAAG,GAAG,OAAO;AAAA,EACnC;AAAA,EAEA,QAAQ,SAAuB;AAC7B,YAAQ,IAAI,GAAG,MAAM,QAAG,GAAG,OAAO;AAAA,EACpC;AAAA,EAEA,MAAM,SAAuB;AAC3B,YAAQ,MAAM,GAAG,IAAI,QAAG,GAAG,OAAO;AAAA,EACpC;AAAA,EAEA,KAAK,SAAuB;AAC1B,YAAQ,IAAI,GAAG,OAAO,QAAG,GAAG,OAAO;AAAA,EACrC;AAAA,EAEA,QAAQ,SAAuB;AAC7B,YAAQ,IAAI,GAAG,KAAK,QAAG,GAAG,GAAG,IAAI,eAAK,GAAG,OAAO;AAAA,EAClD;AAAA,EAEA,KAAK,SAAiB,OAAe,SAAuB;AAC1D,YAAQ,IAAI,GAAG,IAAI,iBAAO,OAAO,IAAI,KAAK,GAAG,GAAG,OAAO;AAAA,EACzD;AAAA,EAEA,OAAO,SAAuB;AAC5B,YAAQ,IAAI,GAAG,KAAK,QAAG,GAAG,GAAG,IAAI,eAAK,GAAG,OAAO;AAAA,EAClD;AACF;;;AJzBO,SAAS,aAAmB;AACjC,QAAM,aAAa,cAAc;AAEjC,MAAIC,YAAW,UAAU,GAAG;AAC1B,WAAO,KAAK,+CAAY,UAAU,EAAE;AACpC;AAAA,EACF;AAEA,qBAAmB,UAAU;AAC7B,SAAO,QAAQ,+CAAY,UAAU,EAAE;AACzC;;;AKfA,SAAS,aAAa;AACtB,SAAS,cAAAC,mBAAkB;AAIpB,SAAS,aAAmB;AACjC,QAAM,aAAa,cAAc;AAEjC,MAAI,CAACC,YAAW,UAAU,GAAG;AAC3B,WAAO,MAAM,+CAAY,UAAU,EAAE;AACrC,WAAO,KAAK,+CAA2B;AACvC;AAAA,EACF;AAEA,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,SAAS,QAAQ,IAAI,WAAW,YAAY,YAAY;AAE9D,SAAO,KAAK,gBAAM,MAAM,0CAAY;AAEpC,QAAM,QAAQ,MAAM,QAAQ,CAAC,UAAU,GAAG;AAAA,IACxC,OAAO;AAAA,IACP,OAAO;AAAA,EACT,CAAC;AAED,QAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,WAAO,MAAM,+CAAY,IAAI,OAAO,EAAE;AAAA,EACxC,CAAC;AACH;;;AC3BA,SAAS,cAAAC,aAAY,gBAAAC,qBAAoB;AAIlC,SAAS,aAAmB;AACjC,QAAM,aAAa,cAAc;AAEjC,MAAI,CAACC,YAAW,UAAU,GAAG;AAC3B,WAAO,MAAM,+CAAY,UAAU,EAAE;AACrC,WAAO,KAAK,+CAA2B;AACvC;AAAA,EACF;AAEA,SAAO,KAAK,yCAAW,UAAU,EAAE;AACnC,UAAQ,IAAI;AACZ,UAAQ,IAAIC,cAAa,YAAY,OAAO,CAAC;AAC/C;;;ACRO,SAAS,YAAY,MAAc,QAAsC;AAC9E,MAAI,QAAQ,OAAO,SAAS;AAC1B,WAAO,EAAE,MAAM,SAAS,MAAM,OAAO,QAAQ,IAAI,EAAE;AAAA,EACrD;AAEA,MAAI,QAAQ,OAAO,WAAW;AAC5B,WAAO,EAAE,MAAM,YAAY,MAAM,OAAO,UAAU,IAAI,EAAE;AAAA,EAC1D;AAEA,SAAO;AACT;AAOO,SAAS,gBAAgB,MAAc,QAAyB;AACrE,SAAO,EAAE,QAAQ,OAAO,YAAY,EAAE,QAAQ,OAAO;AACvD;AAMO,SAAS,YAAY,QAA0B;AACpD,SAAO,CAAC,GAAG,OAAO,KAAK,OAAO,OAAO,GAAG,GAAG,OAAO,KAAK,OAAO,SAAS,CAAC;AAC1E;AAOO,SAAS,iBAAiB,MAAc,QAA0B;AACvE,QAAM,WAAW,YAAY,MAAM;AACnC,SAAO,SAAS;AAAA,IACd,CAAC,MAAM,EAAE,SAAS,IAAI,KAAK,KAAK,SAAS,CAAC,KAAK,oBAAoB,GAAG,IAAI,KAAK;AAAA,EACjF;AACF;AAEA,SAAS,oBAAoB,GAAW,GAAmB;AACzD,QAAM,SAAqB,CAAC;AAC5B,WAAS,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;AAClC,WAAO,CAAC,IAAI,CAAC,CAAC;AAAA,EAChB;AACA,WAAS,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;AAClC,WAAO,CAAC,EAAE,CAAC,IAAI;AAAA,EACjB;AACA,WAAS,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;AAClC,aAAS,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;AAClC,UAAI,EAAE,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,CAAC,GAAG;AACvC,eAAO,CAAC,EAAE,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,MACpC,OAAO;AACL,eAAO,CAAC,EAAE,CAAC,IAAI,KAAK;AAAA,UAClB,OAAO,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI;AAAA,UACvB,OAAO,CAAC,EAAE,IAAI,CAAC,IAAI;AAAA,UACnB,OAAO,IAAI,CAAC,EAAE,CAAC,IAAI;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO,OAAO,EAAE,MAAM,EAAE,EAAE,MAAM;AAClC;;;AClEO,SAAS,SACd,MACA,SACA,SACM;AACN,QAAM,aAAa,cAAc;AACjC,qBAAmB,UAAU;AAE7B,QAAM,SAAS,WAAW,UAAU;AAEpC,MAAI,CAAC,gBAAgB,MAAM,MAAM,GAAG;AAClC,WAAO,MAAM,iBAAO,IAAI,4BAAQ;AAChC;AAAA,EACF;AAEA,SAAO,QAAQ,IAAI,IAAI;AAAA,IACrB;AAAA,IACA,aAAa,QAAQ;AAAA,EACvB;AAEA,aAAW,QAAQ,UAAU;AAC7B,SAAO,QAAQ,mCAAU,IAAI,WAAM,OAAO,EAAE;AAC9C;;;ACxBA,SAAS,cAAAC,mBAAkB;AAEpB,SAAS,YAAY,MAAoB;AAC9C,QAAM,aAAa,cAAc;AAEjC,MAAI,CAACA,YAAW,UAAU,GAAG;AAC3B,WAAO,MAAM,+FAAmC;AAChD;AAAA,EACF;AAEA,QAAM,SAAS,WAAW,UAAU;AAEpC,MAAI,EAAE,QAAQ,OAAO,UAAU;AAC7B,WAAO,MAAM,iBAAO,IAAI,sBAAO;AAC/B;AAAA,EACF;AAEA,SAAO,OAAO,QAAQ,IAAI;AAC1B,aAAW,QAAQ,UAAU;AAC7B,SAAO,QAAQ,mCAAU,IAAI,EAAE;AACjC;;;ACvBA,SAAS,cAAAC,mBAAkB;AAI3B,OAAOC,SAAQ;AAER,SAAS,YAAkB;AAChC,QAAM,aAAa,cAAc;AAEjC,MAAI,CAACC,YAAW,UAAU,GAAG;AAC3B,WAAO,MAAM,+FAAmC;AAChD;AAAA,EACF;AAEA,QAAM,SAAS,WAAW,UAAU;AACpC,QAAM,UAAU,OAAO,QAAQ,OAAO,OAAO;AAE7C,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO,KAAK,0BAAM;AAClB;AAAA,EACF;AAEA,UAAQ,IAAI;AACZ,UAAQ,IAAID,IAAG,KAAK,2BAAO,CAAC;AAC5B,UAAQ,IAAI;AAEZ,aAAW,CAAC,MAAM,KAAK,KAAK,SAAS;AACnC,YAAQ,IAAI,KAAKA,IAAG,KAAK,IAAI,CAAC,WAAM,MAAM,OAAO,EAAE;AACnD,QAAI,MAAM,aAAa;AACrB,cAAQ,IAAI,OAAOA,IAAG,IAAI,MAAM,WAAW,CAAC,EAAE;AAAA,IAChD;AAAA,EACF;AACA,UAAQ,IAAI;AACd;;;ACjCA,SAAS,cAAAE,mBAAkB;AAI3B,OAAOC,SAAQ;AAER,SAAS,eAAqB;AACnC,QAAM,aAAa,cAAc;AAEjC,MAAI,CAACC,YAAW,UAAU,GAAG;AAC3B,WAAO,MAAM,+FAAmC;AAChD;AAAA,EACF;AAEA,QAAM,SAAS,WAAW,UAAU;AACpC,QAAM,YAAY,OAAO,QAAQ,OAAO,SAAS;AAEjD,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO,KAAK,gCAAO;AACnB;AAAA,EACF;AAEA,UAAQ,IAAI;AACZ,UAAQ,IAAID,IAAG,KAAK,iCAAQ,CAAC;AAC7B,UAAQ,IAAI;AAEZ,aAAW,CAAC,MAAM,QAAQ,KAAK,WAAW;AACxC,UAAM,YAAY,SAAS,MAAM;AACjC,YAAQ,IAAI,KAAKA,IAAG,KAAK,IAAI,CAAC,KAAK,SAAS,UAAK;AACjD,QAAI,SAAS,aAAa;AACxB,cAAQ,IAAI,OAAOA,IAAG,IAAI,SAAS,WAAW,CAAC,EAAE;AAAA,IACnD;AAAA,EACF;AACA,UAAQ,IAAI;AACd;;;AClCA,SAAS,cAAAE,mBAAkB;AAI3B,OAAOC,SAAQ;AAER,SAAS,aAAa,MAAoB;AAC/C,QAAM,aAAa,cAAc;AAEjC,MAAI,CAACC,YAAW,UAAU,GAAG;AAC3B,WAAO,MAAM,+FAAmC;AAChD;AAAA,EACF;AAEA,QAAM,SAAS,WAAW,UAAU;AAEpC,MAAI,EAAE,QAAQ,OAAO,YAAY;AAC/B,WAAO,MAAM,uBAAQ,IAAI,sBAAO;AAChC;AAAA,EACF;AAEA,QAAM,WAAW,OAAO,UAAU,IAAI;AAEtC,UAAQ,IAAI;AACZ,UAAQ,IAAID,IAAG,KAAK,uBAAQ,IAAI,EAAE,CAAC;AACnC,MAAI,SAAS,aAAa;AACxB,YAAQ,IAAIA,IAAG,IAAI,SAAS,WAAW,CAAC;AAAA,EAC1C;AACA,UAAQ,IAAI;AAEZ,aAAW,QAAQ,SAAS,OAAO;AACjC,YAAQ,IAAI,GAAGA,IAAG,KAAK,QAAG,CAAC,IAAIA,IAAG,KAAK,KAAK,EAAE,CAAC,KAAK,KAAK,MAAM,EAAE;AAEjE,eAAW,UAAU,KAAK,SAAS;AACjC,YAAM,QAAQ,OAAO,OAAO,UAAKA,IAAG,OAAO,OAAO,IAAI,CAAC,KAAK;AAC5D,YAAM,MAAM,OAAO,UAAU,UAAKA,IAAG,MAAM,OAAO,OAAO,CAAC,KAAK;AAC/D,cAAQ,IAAI,kBAAQ,OAAO,IAAI,IAAI,KAAK,GAAG,GAAG,EAAE;AAAA,IAClD;AACA,YAAQ,IAAI;AAAA,EACd;AACF;;;ACxCA,SAAS,cAAAE,mBAAkB;;;ACA3B,SAAS,SAAAC,cAAa;AAStB,eAAsB,eAAe,SAAsC;AACzE,SAAO,QAAQ,OAAO;AAEtB,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,YAAY,QAAQ,aAAa;AACvC,UAAM,QAAQ,YAAY,YAAY;AACtC,UAAM,WAAW,YAAY,OAAO;AAEpC,UAAM,QAAQC,OAAM,OAAO,CAAC,UAAU,OAAO,GAAG;AAAA,MAC9C,OAAO,CAAC,WAAW,QAAQ,MAAM;AAAA,MACjC,KAAK,QAAQ;AAAA,IACf,CAAC;AAED,QAAI,SAAS;AACb,QAAI,SAAS;AAEb,UAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS;AACjC,YAAM,OAAO,KAAK,SAAS;AAC3B,gBAAU;AACV,cAAQ,OAAO,MAAM,IAAI;AAAA,IAC3B,CAAC;AAED,UAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS;AACjC,YAAM,OAAO,KAAK,SAAS;AAC3B,gBAAU;AACV,cAAQ,OAAO,MAAM,IAAI;AAAA,IAC3B,CAAC;AAED,UAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,YAAM,UAAU,SAAS;AACzB,UAAI,SAAS;AACX,eAAO,QAAQ,0BAAM;AAAA,MACvB,OAAO;AACL,eAAO,MAAM,iDAAc,IAAI,GAAG;AAAA,MACpC;AAEA,cAAQ;AAAA,QACN;AAAA,QACA,MAAM,QAAQ;AAAA,QACd;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,UAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,aAAO,MAAM,6BAAS,IAAI,OAAO,EAAE;AACnC,cAAQ;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,QACN;AAAA,QACA,QAAQ,IAAI;AAAA,MACd,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC;AACH;;;AC/DA,SAAS,cAAc;;;ACMhB,SAAS,cACd,UACA,SACQ;AACR,SAAO,SAAS,QAAQ,oBAAoB,CAAC,OAAO,QAAQ;AAC1D,UAAM,aAAa,IAAI,KAAK;AAC5B,WAAO,cAAc,UAAU,QAAQ,UAAU,IAAI;AAAA,EACvD,CAAC;AACH;;;ADLO,SAAS,aAAa,UAAoB,IAAsC;AACrF,SAAO,SAAS,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAC/C;AAKO,SAAS,kBACd,SACA,SACQ;AACR,SAAO,cAAc,SAAS,OAAO;AACvC;AAKO,SAAS,oBAAoB,UAAoB,SAAyB;AAC/E,QAAM,UAAU,oBAAI,IAAY;AAChC,MAAI,WAAW;AAEf,WAAS,SAAS,QAAgB,OAAqB;AACrD,QAAI,QAAQ,IAAI,MAAM,EAAG;AACzB,YAAQ,IAAI,MAAM;AAElB,UAAM,OAAO,aAAa,UAAU,MAAM;AAC1C,QAAI,CAAC,KAAM;AAEX,eAAW,UAAU,KAAK,SAAS;AACjC,UAAI,OAAO,SAAS;AAClB,mBAAW,KAAK,IAAI,UAAU,KAAK;AAAA,MACrC,WAAW,OAAO,MAAM;AACtB,iBAAS,OAAO,MAAM,QAAQ,CAAC;AAAA,MACjC;AAAA,IACF;AAEA,YAAQ,OAAO,MAAM;AAAA,EACvB;AAEA,WAAS,SAAS,CAAC;AACnB,SAAO,aAAa,WAAW,SAAS,MAAM,SAAS;AACzD;AAKA,eAAsB,YAAY,UAAoB,SAAS,OAAsB;AACnF,MAAI,SAAS,MAAM,WAAW,GAAG;AAC/B,WAAO,MAAM,4CAAS;AACtB;AAAA,EACF;AAEA,QAAM,UAA2B,EAAE,QAAQ,CAAC,EAAE;AAC9C,MAAI,cAAc,SAAS,MAAM,CAAC;AAClC,MAAI,YAAY;AAChB,QAAM,iBAAiB,oBAAoB,UAAU,YAAY,EAAE;AAEnE,UAAQ,IAAI;AACZ,MAAI,SAAS,aAAa;AACxB,WAAO,KAAK,SAAS,WAAW;AAAA,EAClC;AAEA,SAAO,MAAM;AACX,WAAO,KAAK,WAAW,gBAAgB,YAAY,MAAM;AAEzD,UAAM,UAAU,YAAY,QAAQ,IAAI,CAAC,KAAK,WAAW;AAAA,MACvD,MAAM,GAAG,QAAQ,CAAC,KAAK,IAAI,IAAI;AAAA,MAC/B,OAAO;AAAA,IACT,EAAE;AAEF,QAAI;AACF,YAAM,WAAW,MAAM,OAAO;AAAA,QAC5B,SAAS;AAAA,QACT;AAAA,MACF,CAAC;AAGD,YAAM,QAAQ,SAAS,SAAS,SAAS;AACzC,cAAQ,OAAO,YAAY,EAAE,IAAI;AACjC,aAAO,OAAO,SAAS,IAAI;AAG3B,UAAI,SAAS,SAAS;AACpB,cAAM,eAAe,kBAAkB,SAAS,SAAS,QAAQ,MAAM;AACvE,gBAAQ,IAAI;AACZ,YAAI,QAAQ;AACV,iBAAO,QAAQ,uBAAQ,YAAY,EAAE;AAAA,QACvC,OAAO;AACL,gBAAM,eAAe,YAAY;AAAA,QACnC;AACA,gBAAQ,IAAI;AACZ,eAAO,QAAQ,gCAAO;AACtB;AAAA,MACF;AAGA,UAAI,SAAS,MAAM;AACjB,cAAM,WAAW,aAAa,UAAU,SAAS,IAAI;AACrD,YAAI,CAAC,UAAU;AACb,iBAAO,MAAM,mCAAU,SAAS,IAAI,EAAE;AACtC;AAAA,QACF;AACA,sBAAc;AACd;AACA,gBAAQ,IAAI;AAAA,MACd,OAAO;AAEL,eAAO,MAAM,8FAA6B;AAC1C;AAAA,MACF;AAAA,IACF,QAAQ;AAEN,cAAQ,IAAI;AACZ,aAAO,KAAK,oBAAK;AACjB;AAAA,IACF;AAAA,EACF;AACF;;;AFlHA,eAAsB,IAAI,MAAc,UAAsB,CAAC,GAAkB;AAC/E,QAAM,aAAa,cAAc;AAEjC,MAAI,CAACC,YAAW,UAAU,GAAG;AAC3B,WAAO,MAAM,4CAAS;AACtB,WAAO,KAAK,+CAA2B;AACvC;AAAA,EACF;AAEA,QAAM,SAAS,WAAW,UAAU;AACpC,QAAM,SAAS,YAAY,MAAM,MAAM;AAEvC,MAAI,CAAC,QAAQ;AACX,WAAO,MAAM,uBAAQ,IAAI,EAAE;AAE3B,UAAM,UAAU,iBAAiB,MAAM,MAAM;AAC7C,QAAI,QAAQ,SAAS,GAAG;AACtB,aAAO,KAAK,mCAAU,QAAQ,KAAK,IAAI,CAAC,QAAG;AAAA,IAC7C;AACA;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,SAAS;AAC3B,YAAQ,IAAI;AACZ,QAAI,QAAQ,QAAQ;AAClB,aAAO,QAAQ,uBAAQ,OAAO,KAAK,OAAO,EAAE;AAAA,IAC9C,OAAO;AACL,YAAM,eAAe,OAAO,KAAK,OAAO;AAAA,IAC1C;AAAA,EACF,OAAO;AACL,UAAM,YAAY,OAAO,MAAM,QAAQ,MAAM;AAAA,EAC/C;AACF;;;AdtCA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,SAAS,EACd,YAAY,wGAAmB,EAC/B,QAAQ,OAAO;AAGlB,IAAM,YAAY,QAAQ,QAAQ,QAAQ,EAAE,YAAY,0BAAM;AAE9D,UACG,QAAQ,MAAM,EACd,YAAY,4CAAS,EACrB,OAAO,UAAU;AAEpB,UACG,QAAQ,MAAM,EACd,YAAY,sCAAQ,EACpB,OAAO,UAAU;AAEpB,UACG,QAAQ,MAAM,EACd,YAAY,sCAAQ,EACpB,OAAO,UAAU;AAGpB,IAAM,WAAW,QAAQ,QAAQ,OAAO,EAAE,YAAY,0BAAM;AAE5D,SACG,QAAQ,sBAAsB,EAC9B,YAAY,gCAAO,EACnB,OAAO,4BAA4B,0BAAM,EACzC,OAAO,QAAQ;AAElB,SACG,QAAQ,WAAW,EACnB,YAAY,0BAAM,EAClB,OAAO,WAAW;AAErB,SACG,QAAQ,IAAI,EACZ,YAAY,sCAAQ,EACpB,OAAO,SAAS;AAGnB,IAAM,cAAc,QAAQ,QAAQ,UAAU,EAAE,YAAY,gCAAO;AAEnE,YACG,QAAQ,IAAI,EACZ,YAAY,4CAAS,EACrB,OAAO,YAAY;AAEtB,YACG,QAAQ,aAAa,EACrB,YAAY,4CAAS,EACrB,OAAO,YAAY;AAGtB,QACG,SAAS,UAAU,kDAAU,EAC7B,OAAO,aAAa,kDAAU,EAC9B,OAAO,OAAO,MAA0B,YAAkC;AACzE,MAAI,CAAC,MAAM;AACT,YAAQ,KAAK;AACb;AAAA,EACF;AACA,QAAM,IAAI,MAAM,EAAE,QAAQ,QAAQ,OAAO,CAAC;AAC5C,CAAC;AAEH,QAAQ,MAAM;","names":["existsSync","existsSync","existsSync","existsSync","existsSync","readFileSync","existsSync","readFileSync","existsSync","existsSync","pc","existsSync","existsSync","pc","existsSync","existsSync","pc","existsSync","existsSync","spawn","spawn","existsSync"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/config/init.ts","../src/utils/path.ts","../src/core/config-manager.ts","../src/types/index.ts","../src/utils/logger.ts","../src/commands/config/edit.ts","../src/commands/config/show.ts","../src/core/name-resolver.ts","../src/commands/alias/add.ts","../src/commands/alias/remove.ts","../src/commands/alias/list.ts","../src/commands/workflow/list.ts","../src/commands/workflow/show.ts","../src/commands/run.ts","../src/core/executor.ts","../src/core/workflow-runner.ts","../src/core/template-engine.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { configInit, configEdit, configShow } from './commands/config/index.js';\nimport { aliasAdd, aliasRemove, aliasList } from './commands/alias/index.js';\nimport { workflowList, workflowShow } from './commands/workflow/index.js';\nimport { run } from './commands/run.js';\n\nconst program = new Command();\n\nprogram\n .name('fastcli')\n .description('终端命令别名和交互式工作流管理工具')\n .version('1.0.0');\n\n// config 命令组\nconst configCmd = program.command('config').description('配置管理');\n\nconfigCmd\n .command('init')\n .description('初始化配置文件')\n .action(configInit);\n\nconfigCmd\n .command('edit')\n .description('编辑配置文件')\n .action(configEdit);\n\nconfigCmd\n .command('show')\n .description('显示配置内容')\n .action(configShow);\n\n// alias 命令组\nconst aliasCmd = program.command('alias').description('别名管理');\n\naliasCmd\n .command('add <name> <command>')\n .description('添加新别名')\n .option('-d, --description <desc>', '别名描述')\n .action(aliasAdd);\n\naliasCmd\n .command('rm <name>')\n .description('删除别名')\n .action(aliasRemove);\n\naliasCmd\n .command('ls')\n .description('列出所有别名')\n .action(aliasList);\n\n// workflow 命令组\nconst workflowCmd = program.command('workflow').description('工作流管理');\n\nworkflowCmd\n .command('ls')\n .description('列出所有工作流')\n .action(workflowList);\n\nworkflowCmd\n .command('show <name>')\n .description('显示工作流结构')\n .action(workflowShow);\n\n// 默认命令:运行别名或工作流\nprogram\n .argument('[name]', '别名或工作流名称')\n .option('--dry-run', '预览命令但不执行')\n .action(async (name: string | undefined, options: { dryRun?: boolean }) => {\n if (!name) {\n program.help();\n return;\n }\n await run(name, { dryRun: options.dryRun });\n });\n\nprogram.parse();\n","import { existsSync } from 'node:fs';\nimport { getConfigPath } from '../../utils/path.js';\nimport { ensureConfigExists } from '../../core/config-manager.js';\nimport { logger } from '../../utils/logger.js';\n\nexport function configInit(): void {\n const configPath = getConfigPath();\n\n if (existsSync(configPath)) {\n logger.warn(`配置文件已存在: ${configPath}`);\n return;\n }\n\n ensureConfigExists(configPath);\n logger.success(`配置文件已创建: ${configPath}`);\n}\n","import { homedir } from 'node:os';\nimport { join } from 'node:path';\n\n/**\n * 获取配置目录路径\n * @returns ~/.fastcli/\n */\nexport function getConfigDir(): string {\n return join(homedir(), '.fastcli');\n}\n\n/**\n * 获取配置文件路径\n * @returns ~/.fastcli/config.json\n */\nexport function getConfigPath(): string {\n return join(getConfigDir(), 'config.json');\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { getConfigPath } from '../utils/path.js';\nimport { DEFAULT_CONFIG, type Config, type ValidationResult } from '../types/index.js';\n\n/**\n * 加载配置文件\n * @param configPath - 配置文件路径(默认使用标准路径)\n */\nexport function loadConfig(configPath: string = getConfigPath()): Config {\n if (!existsSync(configPath)) {\n throw new Error(`配置文件不存在: ${configPath}\\n请运行 fastcli config init 初始化`);\n }\n\n const content = readFileSync(configPath, 'utf-8');\n try {\n return JSON.parse(content) as Config;\n } catch {\n throw new Error(`配置文件格式错误: ${configPath}`);\n }\n}\n\n/**\n * 保存配置文件\n * @param config - 配置对象\n * @param configPath - 配置文件路径(默认使用标准路径)\n */\nexport function saveConfig(\n config: Config,\n configPath: string = getConfigPath()\n): void {\n const dir = dirname(configPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');\n}\n\n/**\n * 确保配置文件存在,不存在则创建默认配置\n * @param configPath - 配置文件路径(默认使用标准路径)\n */\nexport function ensureConfigExists(configPath: string = getConfigPath()): void {\n if (!existsSync(configPath)) {\n saveConfig(DEFAULT_CONFIG, configPath);\n }\n}\n\n/**\n * 校验配置文件\n * @param config - 配置对象\n */\nexport function validateConfig(config: Config): ValidationResult {\n const errors: string[] = [];\n\n // 检查 aliases 和 workflows 名称冲突\n const aliasNames = Object.keys(config.aliases);\n const workflowNames = Object.keys(config.workflows);\n const conflicts = aliasNames.filter((name) => workflowNames.includes(name));\n\n if (conflicts.length > 0) {\n errors.push(`名称冲突: ${conflicts.join(', ')} 同时存在于 aliases 和 workflows 中`);\n }\n\n // 检查工作流步骤引用是否有效\n for (const [name, workflow] of Object.entries(config.workflows)) {\n const stepIds = new Set(workflow.steps.map((s) => s.id));\n for (const step of workflow.steps) {\n for (const option of step.options) {\n if (option.next && !stepIds.has(option.next)) {\n errors.push(`工作流 \"${name}\" 步骤 \"${step.id}\" 引用了不存在的步骤 \"${option.next}\"`);\n }\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","/**\n * 配置文件根结构\n */\nexport interface Config {\n aliases: Record<string, Alias>;\n workflows: Record<string, Workflow>;\n}\n\n/**\n * 命令别名\n */\nexport interface Alias {\n command: string;\n description?: string;\n}\n\n/**\n * 工作流定义\n */\nexport interface Workflow {\n description?: string;\n steps: WorkflowStep[];\n}\n\n/**\n * 工作流步骤\n */\nexport interface WorkflowStep {\n id: string;\n prompt: string;\n options: WorkflowOption[];\n}\n\n/**\n * 工作流选项\n */\nexport interface WorkflowOption {\n name: string;\n value?: string;\n next?: string;\n command?: string;\n}\n\n/**\n * 工作流运行时上下文\n */\nexport interface WorkflowContext {\n values: Record<string, string>;\n}\n\n/**\n * 名称解析结果\n */\nexport type ResolveResult =\n | { type: 'alias'; data: Alias }\n | { type: 'workflow'; data: Workflow };\n\n/**\n * 命令执行结果\n */\nexport interface ExecResult {\n success: boolean;\n code: number;\n stdout: string;\n stderr: string;\n}\n\n/**\n * 配置校验结果\n */\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\n/**\n * 默认空配置\n */\nexport const DEFAULT_CONFIG: Config = {\n aliases: {},\n workflows: {},\n};\n","import pc from 'picocolors';\n\nexport const logger = {\n info(message: string): void {\n console.log(pc.blue('ℹ'), message);\n },\n\n success(message: string): void {\n console.log(pc.green('✓'), message);\n },\n\n error(message: string): void {\n console.error(pc.red('✗'), message);\n },\n\n warn(message: string): void {\n console.log(pc.yellow('⚠'), message);\n },\n\n preview(command: string): void {\n console.log(pc.cyan('→'), pc.dim('执行:'), command);\n },\n\n step(current: number, total: number, message: string): void {\n console.log(pc.dim(`[步骤 ${current}/${total}]`), message);\n },\n\n choice(message: string): void {\n console.log(pc.cyan('→'), pc.dim('选择:'), message);\n },\n};\n","import { spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { getConfigPath } from '../../utils/path.js';\nimport { logger } from '../../utils/logger.js';\n\nexport function configEdit(): void {\n const configPath = getConfigPath();\n\n if (!existsSync(configPath)) {\n logger.error(`配置文件不存在: ${configPath}`);\n logger.info('请先运行: fastcli config init');\n return;\n }\n\n const isWindows = process.platform === 'win32';\n const editor = process.env.EDITOR || (isWindows ? 'notepad' : 'vi');\n\n logger.info(`使用 ${editor} 打开配置文件...`);\n\n const child = spawn(editor, [configPath], {\n stdio: 'inherit',\n shell: true,\n });\n\n child.on('error', (err) => {\n logger.error(`无法打开编辑器: ${err.message}`);\n });\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { getConfigPath } from '../../utils/path.js';\nimport { logger } from '../../utils/logger.js';\n\nexport function configShow(): void {\n const configPath = getConfigPath();\n\n if (!existsSync(configPath)) {\n logger.error(`配置文件不存在: ${configPath}`);\n logger.info('请先运行: fastcli config init');\n return;\n }\n\n logger.info(`配置文件路径: ${configPath}`);\n console.log();\n console.log(readFileSync(configPath, 'utf-8'));\n}\n","import type { Config, ResolveResult } from '../types/index.js';\n\n/**\n * 解析名称,判断是别名还是工作流\n * @param name - 用户输入的名称\n * @param config - 配置对象\n * @returns 解析结果,不存在返回 null\n */\nexport function resolveName(name: string, config: Config): ResolveResult | null {\n if (name in config.aliases) {\n return { type: 'alias', data: config.aliases[name] };\n }\n\n if (name in config.workflows) {\n return { type: 'workflow', data: config.workflows[name] };\n }\n\n return null;\n}\n\n/**\n * 检查名称是否可用(未被 alias 或 workflow 占用)\n * @param name - 要检查的名称\n * @param config - 配置对象\n */\nexport function isNameAvailable(name: string, config: Config): boolean {\n return !(name in config.aliases) && !(name in config.workflows);\n}\n\n/**\n * 获取所有已使用的名称\n * @param config - 配置对象\n */\nexport function getAllNames(config: Config): string[] {\n return [...Object.keys(config.aliases), ...Object.keys(config.workflows)];\n}\n\n/**\n * 查找相似名称(用于错误提示)\n * @param name - 用户输入的名称\n * @param config - 配置对象\n */\nexport function findSimilarNames(name: string, config: Config): string[] {\n const allNames = getAllNames(config);\n return allNames.filter(\n (n) => n.includes(name) || name.includes(n) || levenshteinDistance(n, name) <= 2\n );\n}\n\nfunction levenshteinDistance(a: string, b: string): number {\n const matrix: number[][] = [];\n for (let i = 0; i <= b.length; i++) {\n matrix[i] = [i];\n }\n for (let j = 0; j <= a.length; j++) {\n matrix[0][j] = j;\n }\n for (let i = 1; i <= b.length; i++) {\n for (let j = 1; j <= a.length; j++) {\n if (b.charAt(i - 1) === a.charAt(j - 1)) {\n matrix[i][j] = matrix[i - 1][j - 1];\n } else {\n matrix[i][j] = Math.min(\n matrix[i - 1][j - 1] + 1,\n matrix[i][j - 1] + 1,\n matrix[i - 1][j] + 1\n );\n }\n }\n }\n return matrix[b.length][a.length];\n}\n","import { loadConfig, saveConfig, ensureConfigExists } from '../../core/config-manager.js';\nimport { isNameAvailable } from '../../core/name-resolver.js';\nimport { logger } from '../../utils/logger.js';\nimport { getConfigPath } from '../../utils/path.js';\n\nexport function aliasAdd(\n name: string,\n command: string,\n options: { description?: string }\n): void {\n const configPath = getConfigPath();\n ensureConfigExists(configPath);\n\n const config = loadConfig(configPath);\n\n if (!isNameAvailable(name, config)) {\n logger.error(`名称 \"${name}\" 已被使用`);\n return;\n }\n\n config.aliases[name] = {\n command,\n description: options.description,\n };\n\n saveConfig(config, configPath);\n logger.success(`别名已添加: ${name} → ${command}`);\n}\n","import { loadConfig, saveConfig } from '../../core/config-manager.js';\nimport { logger } from '../../utils/logger.js';\nimport { getConfigPath } from '../../utils/path.js';\nimport { existsSync } from 'node:fs';\n\nexport function aliasRemove(name: string): void {\n const configPath = getConfigPath();\n\n if (!existsSync(configPath)) {\n logger.error('配置文件不存在,请先运行: fastcli config init');\n return;\n }\n\n const config = loadConfig(configPath);\n\n if (!(name in config.aliases)) {\n logger.error(`别名 \"${name}\" 不存在`);\n return;\n }\n\n delete config.aliases[name];\n saveConfig(config, configPath);\n logger.success(`别名已删除: ${name}`);\n}\n","import { existsSync } from 'node:fs';\nimport { loadConfig } from '../../core/config-manager.js';\nimport { logger } from '../../utils/logger.js';\nimport { getConfigPath } from '../../utils/path.js';\nimport pc from 'picocolors';\n\nexport function aliasList(): void {\n const configPath = getConfigPath();\n\n if (!existsSync(configPath)) {\n logger.error('配置文件不存在,请先运行: fastcli config init');\n return;\n }\n\n const config = loadConfig(configPath);\n const aliases = Object.entries(config.aliases);\n\n if (aliases.length === 0) {\n logger.info('暂无别名');\n return;\n }\n\n console.log();\n console.log(pc.bold('别名列表:'));\n console.log();\n\n for (const [name, alias] of aliases) {\n console.log(` ${pc.cyan(name)} → ${alias.command}`);\n if (alias.description) {\n console.log(` ${pc.dim(alias.description)}`);\n }\n }\n console.log();\n}\n","import { existsSync } from 'node:fs';\nimport { loadConfig } from '../../core/config-manager.js';\nimport { logger } from '../../utils/logger.js';\nimport { getConfigPath } from '../../utils/path.js';\nimport pc from 'picocolors';\n\nexport function workflowList(): void {\n const configPath = getConfigPath();\n\n if (!existsSync(configPath)) {\n logger.error('配置文件不存在,请先运行: fastcli config init');\n return;\n }\n\n const config = loadConfig(configPath);\n const workflows = Object.entries(config.workflows);\n\n if (workflows.length === 0) {\n logger.info('暂无工作流');\n return;\n }\n\n console.log();\n console.log(pc.bold('工作流列表:'));\n console.log();\n\n for (const [name, workflow] of workflows) {\n const stepCount = workflow.steps.length;\n console.log(` ${pc.cyan(name)} (${stepCount} 步)`);\n if (workflow.description) {\n console.log(` ${pc.dim(workflow.description)}`);\n }\n }\n console.log();\n}\n","import { existsSync } from 'node:fs';\nimport { loadConfig } from '../../core/config-manager.js';\nimport { logger } from '../../utils/logger.js';\nimport { getConfigPath } from '../../utils/path.js';\nimport pc from 'picocolors';\n\nexport function workflowShow(name: string): void {\n const configPath = getConfigPath();\n\n if (!existsSync(configPath)) {\n logger.error('配置文件不存在,请先运行: fastcli config init');\n return;\n }\n\n const config = loadConfig(configPath);\n\n if (!(name in config.workflows)) {\n logger.error(`工作流 \"${name}\" 不存在`);\n return;\n }\n\n const workflow = config.workflows[name];\n\n console.log();\n console.log(pc.bold(`工作流: ${name}`));\n if (workflow.description) {\n console.log(pc.dim(workflow.description));\n }\n console.log();\n\n for (const step of workflow.steps) {\n console.log(`${pc.cyan('●')} ${pc.bold(step.id)}: ${step.prompt}`);\n\n for (const option of step.options) {\n const arrow = option.next ? `→ ${pc.yellow(option.next)}` : '';\n const cmd = option.command ? `→ ${pc.green(option.command)}` : '';\n console.log(` └─ ${option.name} ${arrow}${cmd}`);\n }\n console.log();\n }\n}\n","import { existsSync } from 'node:fs';\nimport { loadConfig } from '../core/config-manager.js';\nimport { resolveName, findSimilarNames } from '../core/name-resolver.js';\nimport { executeCommand } from '../core/executor.js';\nimport { runWorkflow } from '../core/workflow-runner.js';\nimport { logger } from '../utils/logger.js';\nimport { getConfigPath } from '../utils/path.js';\n\nexport interface RunOptions {\n dryRun?: boolean;\n}\n\nexport async function run(name: string, options: RunOptions = {}): Promise<void> {\n const configPath = getConfigPath();\n\n if (!existsSync(configPath)) {\n logger.error('配置文件不存在');\n logger.info('请先运行: fastcli config init');\n return;\n }\n\n const config = loadConfig(configPath);\n const result = resolveName(name, config);\n\n if (!result) {\n logger.error(`未找到: ${name}`);\n\n const similar = findSimilarNames(name, config);\n if (similar.length > 0) {\n logger.info(`你是否想要: ${similar.join(', ')}?`);\n }\n return;\n }\n\n if (result.type === 'alias') {\n console.log();\n if (options.dryRun) {\n logger.preview(`将执行: ${result.data.command}`);\n } else {\n await executeCommand(result.data.command);\n }\n } else {\n await runWorkflow(result.data, options.dryRun);\n }\n}\n","import { spawn } from 'node:child_process';\nimport { logger } from '../utils/logger.js';\nimport type { ExecResult } from '../types/index.js';\n\n/**\n * 执行 shell 命令\n * @param command - 要执行的命令\n * @returns 执行结果\n */\nexport async function executeCommand(command: string): Promise<ExecResult> {\n logger.preview(command);\n\n return new Promise((resolve) => {\n const isWindows = process.platform === 'win32';\n const shell = isWindows ? 'powershell.exe' : '/bin/sh';\n const shellArg = isWindows ? '-Command' : '-c';\n\n const child = spawn(shell, [shellArg, command], {\n stdio: ['inherit', 'pipe', 'pipe'],\n env: process.env,\n });\n\n let stdout = '';\n let stderr = '';\n\n child.stdout?.on('data', (data) => {\n const text = data.toString();\n stdout += text;\n process.stdout.write(text);\n });\n\n child.stderr?.on('data', (data) => {\n const text = data.toString();\n stderr += text;\n process.stderr.write(text);\n });\n\n child.on('close', (code) => {\n const success = code === 0;\n if (success) {\n logger.success('执行完成');\n } else {\n logger.error(`执行失败 (退出码: ${code})`);\n }\n\n resolve({\n success,\n code: code ?? 1,\n stdout,\n stderr,\n });\n });\n\n child.on('error', (err) => {\n logger.error(`执行出错: ${err.message}`);\n resolve({\n success: false,\n code: 1,\n stdout,\n stderr: err.message,\n });\n });\n });\n}\n","import { select } from '@inquirer/prompts';\nimport { logger } from '../utils/logger.js';\nimport { parseTemplate } from './template-engine.js';\nimport { executeCommand } from './executor.js';\nimport type { Workflow, WorkflowStep, WorkflowContext } from '../types/index.js';\n\n/**\n * 根据 ID 查找步骤\n */\nexport function findStepById(workflow: Workflow, id: string): WorkflowStep | undefined {\n return workflow.steps.find((s) => s.id === id);\n}\n\n/**\n * 构建最终命令(替换变量)\n */\nexport function buildFinalCommand(\n command: string,\n context: Record<string, string>\n): string {\n return parseTemplate(command, context);\n}\n\n/**\n * 计算从某步骤开始的最短路径长度(用于进度显示)\n */\nexport function calculateTotalSteps(workflow: Workflow, startId: string): number {\n const visited = new Set<string>();\n let minSteps = Infinity;\n\n function traverse(stepId: string, depth: number): void {\n if (visited.has(stepId)) return;\n visited.add(stepId);\n\n const step = findStepById(workflow, stepId);\n if (!step) return;\n\n for (const option of step.options) {\n if (option.command) {\n minSteps = Math.min(minSteps, depth);\n } else if (option.next) {\n traverse(option.next, depth + 1);\n }\n }\n\n visited.delete(stepId);\n }\n\n traverse(startId, 1);\n return minSteps === Infinity ? workflow.steps.length : minSteps;\n}\n\n/**\n * 运行工作流\n */\nexport async function runWorkflow(workflow: Workflow, dryRun = false): Promise<void> {\n if (workflow.steps.length === 0) {\n logger.error('工作流没有步骤');\n return;\n }\n\n const context: WorkflowContext = { values: {} };\n let currentStep = workflow.steps[0];\n let stepIndex = 1;\n const estimatedTotal = calculateTotalSteps(workflow, currentStep.id);\n\n console.log();\n if (workflow.description) {\n logger.info(workflow.description);\n }\n\n while (true) {\n logger.step(stepIndex, estimatedTotal, currentStep.prompt);\n\n const choices = currentStep.options.map((opt, index) => ({\n name: `${index + 1}. ${opt.name}`,\n value: opt,\n }));\n\n try {\n const selected = await select({\n message: '请选择',\n choices,\n });\n\n // 记录选择的值\n const value = selected.value ?? selected.name;\n context.values[currentStep.id] = value;\n logger.choice(selected.name);\n\n // 如果有 command,执行并结束\n if (selected.command) {\n const finalCommand = buildFinalCommand(selected.command, context.values);\n console.log();\n if (dryRun) {\n logger.preview(`将执行: ${finalCommand}`);\n } else {\n await executeCommand(finalCommand);\n }\n console.log();\n logger.success('工作流完成');\n return;\n }\n\n // 如果有 next,跳转到下一步\n if (selected.next) {\n const nextStep = findStepById(workflow, selected.next);\n if (!nextStep) {\n logger.error(`找不到步骤: ${selected.next}`);\n return;\n }\n currentStep = nextStep;\n stepIndex++;\n console.log();\n } else {\n // 既没有 command 也没有 next,工作流配置错误\n logger.error('工作流配置错误:选项缺少 command 或 next');\n return;\n }\n } catch {\n // 用户按 Ctrl+C 退出\n console.log();\n logger.warn('已取消');\n return;\n }\n }\n}\n","/**\n * 解析模板字符串,替换 {{variable}} 为上下文中的值\n * @param template - 包含 {{var}} 占位符的模板字符串\n * @param context - 变量名到值的映射\n * @returns 替换后的字符串\n */\nexport function parseTemplate(\n template: string,\n context: Record<string, string>\n): string {\n return template.replace(/\\{\\{([^}]+)\\}\\}/g, (match, key) => {\n const trimmedKey = key.trim();\n return trimmedKey in context ? context[trimmedKey] : match;\n });\n}\n"],"mappings":"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","names":["existsSync","existsSync","existsSync","existsSync","existsSync","readFileSync","existsSync","readFileSync","existsSync","existsSync","pc","existsSync","existsSync","pc","existsSync","existsSync","pc","existsSync","existsSync","spawn","spawn","existsSync"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namewta/fastcli",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "终端命令别名和交互式工作流管理工具",
5
5
  "type": "module",
6
6
  "author": {