xuanwu-cli 1.0.0

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.
Files changed (45) hide show
  1. package/README.md +171 -0
  2. package/bin/xuanwu +20 -0
  3. package/dist/api/client.d.ts +30 -0
  4. package/dist/api/client.js +332 -0
  5. package/dist/commands/build.d.ts +5 -0
  6. package/dist/commands/build.js +57 -0
  7. package/dist/commands/connect.d.ts +5 -0
  8. package/dist/commands/connect.js +67 -0
  9. package/dist/commands/deploy.d.ts +5 -0
  10. package/dist/commands/deploy.js +85 -0
  11. package/dist/commands/env.d.ts +5 -0
  12. package/dist/commands/env.js +119 -0
  13. package/dist/commands/logs.d.ts +5 -0
  14. package/dist/commands/logs.js +39 -0
  15. package/dist/commands/pods.d.ts +5 -0
  16. package/dist/commands/pods.js +56 -0
  17. package/dist/commands/scale.d.ts +5 -0
  18. package/dist/commands/scale.js +32 -0
  19. package/dist/commands/svc.d.ts +5 -0
  20. package/dist/commands/svc.js +100 -0
  21. package/dist/config/store.d.ts +18 -0
  22. package/dist/config/store.js +108 -0
  23. package/dist/config/types.d.ts +86 -0
  24. package/dist/config/types.js +5 -0
  25. package/dist/index.d.ts +4 -0
  26. package/dist/index.js +142 -0
  27. package/dist/output/formatter.d.ts +15 -0
  28. package/dist/output/formatter.js +95 -0
  29. package/docs/DESIGN.md +363 -0
  30. package/docs//345/276/205/344/274/230/345/214/226.md +89 -0
  31. package/package.json +31 -0
  32. package/src/api/client.ts +380 -0
  33. package/src/commands/build.ts +67 -0
  34. package/src/commands/connect.ts +75 -0
  35. package/src/commands/deploy.ts +90 -0
  36. package/src/commands/env.ts +144 -0
  37. package/src/commands/logs.ts +47 -0
  38. package/src/commands/pods.ts +60 -0
  39. package/src/commands/scale.ts +35 -0
  40. package/src/commands/svc.ts +114 -0
  41. package/src/config/store.ts +86 -0
  42. package/src/config/types.ts +99 -0
  43. package/src/index.ts +127 -0
  44. package/src/output/formatter.ts +112 -0
  45. package/tsconfig.json +17 -0
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ /**
3
+ * xuanwu-cli 类型定义
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ /**
2
+ * xuanwu-cli 主入口
3
+ */
4
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ /**
3
+ * xuanwu-cli 主入口
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const commander_1 = require("commander");
40
+ const connect_1 = require("./commands/connect");
41
+ const env_1 = require("./commands/env");
42
+ const deploy_1 = require("./commands/deploy");
43
+ const svc_1 = require("./commands/svc");
44
+ const build_1 = require("./commands/build");
45
+ const scale_1 = require("./commands/scale");
46
+ const logs_1 = require("./commands/logs");
47
+ const pods_1 = require("./commands/pods");
48
+ const program = new commander_1.Command();
49
+ program
50
+ .name('xuanwu')
51
+ .description('玄武工厂平台 CLI 工具')
52
+ .version('1.0.0')
53
+ .option('-o, --output <format>', 'Output format (human|json)', 'human');
54
+ // 添加子命令
55
+ program.addCommand((0, connect_1.makeConnectCommand)());
56
+ program.addCommand((0, env_1.makeEnvCommand)());
57
+ program.addCommand((0, deploy_1.makeDeployCommand)());
58
+ program.addCommand((0, svc_1.makeSvcCommand)());
59
+ program.addCommand((0, build_1.makeBuildCommand)());
60
+ program.addCommand((0, scale_1.makeScaleCommand)());
61
+ program.addCommand((0, logs_1.makeLogsCommand)());
62
+ program.addCommand((0, pods_1.makePodsCommand)());
63
+ // 快捷命令:直接 deploy 也支持
64
+ program
65
+ .command('up <namespace> <service-name>')
66
+ .description('Build and deploy a service')
67
+ .action(async (namespace, serviceName) => {
68
+ const { makeBuildCommand } = await Promise.resolve().then(() => __importStar(require('./commands/build')));
69
+ const buildCmd = makeBuildCommand();
70
+ // 简化:只调用部署
71
+ console.log('Use: xuanwu build <namespace> <service-name> && xuanwu deploy <namespace> <service-name>');
72
+ });
73
+ // restart 命令
74
+ program
75
+ .command('restart <namespace> <service-name>')
76
+ .description('Restart a service')
77
+ .action(async (namespace, serviceName) => {
78
+ console.log('Restarting service... (not implemented)');
79
+ });
80
+ // exec 命令
81
+ program
82
+ .command('exec <namespace> <service-name>')
83
+ .description('Execute command in container')
84
+ .option('-c, --command <cmd>', 'Command to execute', 'ls -la')
85
+ .option('-p, --pod <pod-name>', 'Specific pod name')
86
+ .action(async (namespace, serviceName, options) => {
87
+ const { configStore } = await Promise.resolve().then(() => __importStar(require('./config/store')));
88
+ const { createClient } = await Promise.resolve().then(() => __importStar(require('./api/client')));
89
+ const { OutputFormatter } = await Promise.resolve().then(() => __importStar(require('./output/formatter')));
90
+ const conn = configStore.getDefaultConnection();
91
+ if (!conn) {
92
+ OutputFormatter.error('No connection configured');
93
+ return;
94
+ }
95
+ const client = createClient(conn);
96
+ const result = await client.exec(namespace, serviceName, options.command, options.pod);
97
+ if (!result.success) {
98
+ OutputFormatter.error(result.error.message);
99
+ return;
100
+ }
101
+ const data = result.data;
102
+ if (data.stdout)
103
+ console.log(data.stdout);
104
+ if (data.stderr)
105
+ console.error(data.stderr);
106
+ if (data.exitCode !== 0) {
107
+ process.exit(data.exitCode);
108
+ }
109
+ });
110
+ // top 命令
111
+ program
112
+ .command('top <namespace> <service-name>')
113
+ .description('Show resource usage')
114
+ .option('-p, --pod <pod-name>', 'Specific pod name')
115
+ .action(async (namespace, serviceName, options) => {
116
+ const { configStore } = await Promise.resolve().then(() => __importStar(require('./config/store')));
117
+ const { createClient } = await Promise.resolve().then(() => __importStar(require('./api/client')));
118
+ const { OutputFormatter } = await Promise.resolve().then(() => __importStar(require('./output/formatter')));
119
+ const conn = configStore.getDefaultConnection();
120
+ if (!conn) {
121
+ OutputFormatter.error('No connection configured');
122
+ return;
123
+ }
124
+ const client = createClient(conn);
125
+ const result = await client.getMetrics(namespace, serviceName, options.pod);
126
+ if (!result.success) {
127
+ OutputFormatter.error(result.error.message);
128
+ return;
129
+ }
130
+ const pods = result.data?.pods || [];
131
+ if (pods.length === 0) {
132
+ OutputFormatter.info('No pod metrics found');
133
+ return;
134
+ }
135
+ OutputFormatter.table(['Pod Name', 'CPU', 'Memory'], pods.map((p) => [
136
+ p.name,
137
+ p.containers?.[0]?.cpuRaw || 'N/A',
138
+ p.containers?.[0]?.memoryRaw || 'N/A'
139
+ ]));
140
+ });
141
+ // 解析参数
142
+ program.parse(process.argv);
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 输出格式化
3
+ */
4
+ import { CLIResult } from '../config/types';
5
+ export type OutputFormat = 'human' | 'json';
6
+ export declare class OutputFormatter {
7
+ static format<T>(result: CLIResult<T>, format?: OutputFormat): string;
8
+ private static formatHuman;
9
+ private static formatItem;
10
+ private static formatObject;
11
+ static success(message: string): void;
12
+ static error(message: string): void;
13
+ static info(message: string): void;
14
+ static table(headers: string[], rows: string[][]): void;
15
+ }
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ /**
3
+ * 输出格式化
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.OutputFormatter = void 0;
7
+ class OutputFormatter {
8
+ static format(result, format = 'human') {
9
+ if (format === 'json') {
10
+ return JSON.stringify(result, null, 2);
11
+ }
12
+ return this.formatHuman(result);
13
+ }
14
+ static formatHuman(result) {
15
+ if (!result.success) {
16
+ const error = result.error;
17
+ return `✗ Error: ${error.message}`;
18
+ }
19
+ const data = result.data;
20
+ // 数组列表
21
+ if (Array.isArray(data)) {
22
+ if (data.length === 0) {
23
+ return '(empty)';
24
+ }
25
+ return data.map(item => this.formatItem(item)).join('\n');
26
+ }
27
+ // 对象详情
28
+ if (typeof data === 'object' && data !== null) {
29
+ return this.formatObject(data);
30
+ }
31
+ return String(data);
32
+ }
33
+ static formatItem(item) {
34
+ if (item.name) {
35
+ return `${item.name}`;
36
+ }
37
+ return JSON.stringify(item);
38
+ }
39
+ static formatObject(obj) {
40
+ const lines = [];
41
+ // Namespace 列表
42
+ if (obj.identifier !== undefined || obj.name !== undefined) {
43
+ lines.push(`Name: ${obj.identifier || obj.name}`);
44
+ if (obj.status)
45
+ lines.push(`Status: ${obj.status}`);
46
+ if (obj.environment)
47
+ lines.push(`Environment: ${obj.environment}`);
48
+ return lines.join('\n');
49
+ }
50
+ // Service 列表
51
+ if (Array.isArray(obj)) {
52
+ return obj.map((s) => {
53
+ let line = [
54
+ s.name,
55
+ s.type ? `(${s.type})` : '',
56
+ s.status ? `→ ${s.status}` : ''
57
+ ].filter(Boolean).join(' ');
58
+ if (s.endpoint)
59
+ line += `\n ${s.endpoint}`;
60
+ return line;
61
+ }).join('\n\n');
62
+ }
63
+ // 单个对象
64
+ for (const [key, value] of Object.entries(obj)) {
65
+ if (value !== undefined && value !== null) {
66
+ lines.push(`${key}: ${JSON.stringify(value)}`);
67
+ }
68
+ }
69
+ return lines.join('\n');
70
+ }
71
+ // 打印成功消息
72
+ static success(message) {
73
+ console.log(`✓ ${message}`);
74
+ }
75
+ // 打印错误消息
76
+ static error(message) {
77
+ console.error(`✗ ${message}`);
78
+ }
79
+ // 打印信息
80
+ static info(message) {
81
+ console.log(message);
82
+ }
83
+ // 打印表格
84
+ static table(headers, rows) {
85
+ const colWidths = headers.map((h, i) => Math.max(h.length, ...rows.map(r => String(r[i] || '').length)));
86
+ // Header
87
+ console.log(headers.map((h, i) => h.padEnd(colWidths[i])).join(' '));
88
+ console.log(colWidths.map(w => '-'.repeat(w)).join(' '));
89
+ // Rows
90
+ for (const row of rows) {
91
+ console.log(row.map((c, i) => String(c || '').padEnd(colWidths[i])).join(' '));
92
+ }
93
+ }
94
+ }
95
+ exports.OutputFormatter = OutputFormatter;
package/docs/DESIGN.md ADDED
@@ -0,0 +1,363 @@
1
+ # xuanwu-cli 设计文档
2
+
3
+ ## 一、概述
4
+
5
+ xuanwu-cli 是玄武工厂平台的命令行工具,用于通过命令行快速管理 K8s 环境和服务。支持环境创建、服务部署(应用/数据库/镜像)、构建、调试等操作。
6
+
7
+ ### 设计原则
8
+
9
+ - **平台转发**: CLI 通过玄武工厂平台 API 转发请求,不直接连接 K8s
10
+ - **K8s 优先**: 状态实时查询 K8s,无缓存
11
+ - **最小配置**: 本地只保存连接信息
12
+ - **权限由平台控制**: 用户可访问的空间由平台 RBAC 配置决定
13
+
14
+ ---
15
+
16
+ ## 二、架构
17
+
18
+ ```
19
+ ┌─────────────────────────────────────────────────────────────┐
20
+ │ xuanwu-cli │
21
+ │ │ │
22
+ │ ┌─────────────┴─────────────┐ │
23
+ │ │ 玄武工厂平台 API │ │
24
+ │ │ (endpoint + token) │ │
25
+ │ └─────────────┬─────────────┘ │
26
+ │ │ │
27
+ │ ┌─────────────┴─────────────┐ │
28
+ │ │ K8s (平台已配置) │ │
29
+ │ │ 权限由平台 RBAC 控制 │ │
30
+ │ └───────────────────────────┘ │
31
+ └─────────────────────────────────────────────────────────────┘
32
+ ```
33
+
34
+ ---
35
+
36
+ ## 三、安装与配置
37
+
38
+ ### 安装
39
+
40
+ ```bash
41
+ npm install -g xuanwu-cli
42
+ ```
43
+
44
+ ### 连接配置
45
+
46
+ ```bash
47
+ # 配置平台连接
48
+ xuanwu connect add <name> --endpoint <url> --token <api-token>
49
+
50
+ # 示例
51
+ xuanwu connect add prod --endpoint https://xuanwu.company.com --token sk-xxxxx
52
+
53
+ # 列出连接
54
+ xuanwu connect ls
55
+
56
+ # 使用连接
57
+ xuanwu connect use prod
58
+
59
+ # 删除连接
60
+ xuanwu connect rm prod
61
+ ```
62
+
63
+ ### 配置文件
64
+
65
+ 存储位置: `~/.xuanwu/config.json`
66
+
67
+ ```json
68
+ {
69
+ "version": "1.0",
70
+ "connections": [
71
+ {
72
+ "name": "prod",
73
+ "endpoint": "https://xuanwu.company.com",
74
+ "token": "sk-xxxxx",
75
+ "isDefault": true
76
+ }
77
+ ]
78
+ }
79
+ ```
80
+
81
+ ---
82
+
83
+ ## 四、命令参考
84
+
85
+ ### 1. 环境管理 (env)
86
+
87
+ ```bash
88
+ # 列出可访问的环境
89
+ xuanwu env ls
90
+
91
+ # 创建环境(K8s namespace)
92
+ xuanwu env create <namespace>
93
+
94
+ # 查看环境详情
95
+ xuanwu env info <namespace>
96
+
97
+ # 删除环境
98
+ xuanwu env rm <namespace>
99
+ ```
100
+
101
+ ### 2. 服务部署 (deploy)
102
+
103
+ ```bash
104
+ # 部署应用(源码构建)
105
+ xuanwu deploy <namespace> <service-name> \
106
+ --type application \
107
+ --git <repo-url> \
108
+ --git-branch <branch> \
109
+ --build-type template \
110
+ --language <java-springboot|nodejs|python|golang>
111
+
112
+ # 部署应用(Dockerfile)
113
+ xuanwu deploy <namespace> <service-name> \
114
+ --type application \
115
+ --git <repo-url> \
116
+ --build-type dockerfile \
117
+ --dockerfile-path <path>
118
+
119
+ # 部署数据库
120
+ xuanwu deploy <namespace> <service-name> \
121
+ --type database \
122
+ --db-type <mysql|redis|postgres|elasticsearch> \
123
+ --db-version <version>
124
+
125
+ # 部署镜像
126
+ xuanwu deploy <namespace> <service-name> \
127
+ --type image \
128
+ --image <image:tag>
129
+
130
+ # 通用参数
131
+ --port <port> # 端口
132
+ --replicas <num> # 副本数
133
+ --cpu <value> # CPU 限制
134
+ --memory <value> # 内存限制
135
+ --domain <prefix> # 域名前缀
136
+ --env KEY=VALUE # 环境变量
137
+ --volume <path:size> # 持久化卷
138
+ ```
139
+
140
+ ### 3. 服务管理 (svc)
141
+
142
+ ```bash
143
+ # 列出服务
144
+ xuanwu svc ls <namespace>
145
+
146
+ # 服务状态
147
+ xuanwu svc status <namespace> <service-name>
148
+
149
+ # 服务详情
150
+ xuanwu svc describe <namespace> <service-name>
151
+
152
+ # 删除服务
153
+ xuanwu svc rm <namespace> <service-name>
154
+ ```
155
+
156
+ ### 4. 构建 (build)
157
+
158
+ ```bash
159
+ # 构建服务
160
+ xuanwu build <namespace> <service-name>
161
+
162
+ # 构建状态
163
+ xuanwu build status <namespace> <service-name>
164
+ ```
165
+
166
+ ### 5. 服务控制
167
+
168
+ ```bash
169
+ # 扩缩容
170
+ xuanwu scale <namespace> <service-name> -r <num>
171
+
172
+ # 重启
173
+ xuanwu restart <namespace> <service-name>
174
+
175
+ # 启动
176
+ xuanwu start <namespace> <service-name>
177
+
178
+ # 停止
179
+ xuanwu stop <namespace> <service-name>
180
+ ```
181
+
182
+ ### 6. 调试 (logs/exec)
183
+
184
+ ```bash
185
+ # 查看日志
186
+ xuanwu logs <namespace> <service-name>
187
+ xuanwu logs <namespace> <service-name> -f # 实时
188
+ xuanwu logs <namespace> <service-name> -n 100 # 最近100行
189
+
190
+ # 执行命令
191
+ xuanwu exec <namespace> <service-name>
192
+ xuanwu exec <namespace> <service-name> -- <command>
193
+
194
+ # Pod 列表
195
+ xuanwu pods <namespace> <service-name>
196
+
197
+ # 资源使用
198
+ xuanwu top <namespace> <service-name>
199
+ ```
200
+
201
+ ---
202
+
203
+ ## 五、使用示例
204
+
205
+ ### 示例1: 部署 MySQL
206
+
207
+ ```bash
208
+ # 1. 配置连接
209
+ xuanwu connect add dev --endpoint http://localhost:3000 --token dev-token
210
+
211
+ # 2. 创建环境
212
+ xuanwu env create shop-dev
213
+
214
+ # 3. 部署 MySQL
215
+ xuanwu deploy shop-dev mysql \
216
+ --type database \
217
+ --db-type mysql \
218
+ --db-version 8.0 \
219
+ --root-password mysecret
220
+
221
+ # 4. 查看状态
222
+ xuanwu svc status shop-dev mysql
223
+ ```
224
+
225
+ ### 示例2: 部署 Spring Boot 应用
226
+
227
+ ```bash
228
+ # 1. 部署应用(源码构建)
229
+ xuanwu deploy shop-dev api \
230
+ --type application \
231
+ --git https://gitlab.com/user/shop-api.git \
232
+ --git-branch main \
233
+ --build-type template \
234
+ --language java-springboot \
235
+ --env DB_HOST=mysql \
236
+ --env DB_PASSWORD=mysecret
237
+
238
+ # 2. 构建
239
+ xuanwu build shop-dev api
240
+
241
+ # 3. 部署
242
+ xuanwu deploy shop-dev api
243
+
244
+ # 4. 查看状态
245
+ xuanwu svc status shop-dev api
246
+ ```
247
+
248
+ ### 示例3: 部署 Nginx
249
+
250
+ ```bash
251
+ xuanwu deploy shop-dev nginx \
252
+ --type image \
253
+ --image nginx:latest \
254
+ --port 80 \
255
+ --domain web
256
+ ```
257
+
258
+ ---
259
+
260
+ ## 六、输出格式
261
+
262
+ ### 人类可读(默认)
263
+
264
+ ```
265
+ ✓ Service deployed successfully
266
+ Namespace: shop-dev
267
+ Service: api
268
+ Type: application
269
+ Status: Running
270
+ Replicas: 2/2
271
+ Endpoint: https://api.shop-dev.dev.aimstek.cn
272
+ ```
273
+
274
+ ### JSON 模式 (-o json)
275
+
276
+ ```json
277
+ {
278
+ "success": true,
279
+ "namespace": "shop-dev",
280
+ "service": "api",
281
+ "type": "application",
282
+ "status": "Running",
283
+ "replicas": "2/2",
284
+ "image": "registry.com/api:v1.0.0",
285
+ "endpoint": "https://api.shop-dev.dev.aimstek.cn",
286
+ "updatedAt": "2026-03-09T10:30:00Z"
287
+ }
288
+ ```
289
+
290
+ ---
291
+
292
+ ## 七、API 映射
293
+
294
+ | CLI 命令 | 平台 API | 说明 |
295
+ |----------|----------|------|
296
+ | `env ls` | `GET /api/deploy-spaces` | 列出空间 |
297
+ | `env create` | `POST /api/deploy-spaces` | 创建空间 |
298
+ | `env rm` | `DELETE /api/deploy-spaces/{id}` | 删除空间 |
299
+ | `deploy` | `POST /api/services` + 部署 | 创建并部署服务 |
300
+ | `svc ls` | `GET /api/k8s/deployments` | 列出服务 |
301
+ | `svc status` | `GET /api/k8s/deployments/{name}` | 服务状态 |
302
+ | `svc rm` | `DELETE /api/services/{id}` | 删除服务 |
303
+ | `build` | `POST /api/applications/{id}/build` | 构建 |
304
+ | `scale` | `POST /api/service-deploy-configs/{id}/scale` | 扩缩容 |
305
+ | `logs` | `GET /api/k8s/logs` | 日志 |
306
+ | `exec` | `POST /api/debug/pod-exec` | 容器执行 |
307
+ | `pods` | `GET /api/k8s/pods` | Pod 列表 |
308
+
309
+ ---
310
+
311
+ ## 八、错误处理
312
+
313
+ ```json
314
+ {
315
+ "success": false,
316
+ "error": {
317
+ "code": "UNAUTHORIZED",
318
+ "message": "Invalid or expired token",
319
+ "details": "Please run 'xuanwu connect use <name>' to set a valid connection"
320
+ }
321
+ }
322
+ ```
323
+
324
+ ---
325
+
326
+ ## 九、环境变量
327
+
328
+ | 变量 | 说明 |
329
+ |------|------|
330
+ | `XUANWU_ENDPOINT` | 平台 API 地址 |
331
+ | `XUANWU_TOKEN` | API Token |
332
+ | `XUANWU_OUTPUT` | 输出格式 (human/json) |
333
+
334
+ ---
335
+
336
+ ## 十、文件结构
337
+
338
+ ```
339
+ xuanwu-cli/
340
+ ├── bin/
341
+ │ └── xuanwu # 入口脚本
342
+ ├── src/
343
+ │ ├── index.ts # 主入口
344
+ │ ├── commands/
345
+ │ │ ├── connect.ts # 连接管理
346
+ │ │ ├── env.ts # 环境管理
347
+ │ │ ├── deploy.ts # 部署
348
+ │ │ ├── svc.ts # 服务管理
349
+ │ │ ├── build.ts # 构建
350
+ │ │ ├── scale.ts # 扩缩容
351
+ │ │ ├── logs.ts # 日志
352
+ │ │ └── exec.ts # 执行
353
+ │ ├── api/
354
+ │ │ └── client.ts # HTTP 客户端
355
+ │ ├── config/
356
+ │ │ ├── store.ts # 配置存储
357
+ │ │ └── types.ts # 类型定义
358
+ │ └── output/
359
+ │ └── formatter.ts # 输出格式化
360
+ ├── package.json
361
+ ├── tsconfig.json
362
+ └── README.md
363
+ ```