@xiaozhi-client/cli 1.9.4-beta.5
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/LICENSE +21 -0
- package/README.md +98 -0
- package/fix-imports.js +32 -0
- package/package.json +26 -0
- package/project.json +75 -0
- package/src/Constants.ts +105 -0
- package/src/Container.ts +212 -0
- package/src/Types.ts +79 -0
- package/src/commands/CommandHandlerFactory.ts +98 -0
- package/src/commands/ConfigCommandHandler.ts +279 -0
- package/src/commands/EndpointCommandHandler.ts +158 -0
- package/src/commands/McpCommandHandler.ts +778 -0
- package/src/commands/ProjectCommandHandler.ts +254 -0
- package/src/commands/ServiceCommandHandler.ts +182 -0
- package/src/commands/__tests__/CommandHandlerFactory.test.ts +323 -0
- package/src/commands/__tests__/CommandRegistry.test.ts +287 -0
- package/src/commands/__tests__/ConfigCommandHandler.test.ts +844 -0
- package/src/commands/__tests__/EndpointCommandHandler.test.ts +426 -0
- package/src/commands/__tests__/McpCommandHandler.test.ts +753 -0
- package/src/commands/__tests__/ProjectCommandHandler.test.ts +230 -0
- package/src/commands/__tests__/ServiceCommands.integration.test.ts +408 -0
- package/src/commands/index.ts +351 -0
- package/src/errors/ErrorHandlers.ts +141 -0
- package/src/errors/ErrorMessages.ts +121 -0
- package/src/errors/__tests__/index.test.ts +186 -0
- package/src/errors/index.ts +163 -0
- package/src/global.d.ts +19 -0
- package/src/index.ts +53 -0
- package/src/interfaces/Command.ts +128 -0
- package/src/interfaces/CommandTypes.ts +95 -0
- package/src/interfaces/Config.ts +25 -0
- package/src/interfaces/Service.ts +99 -0
- package/src/services/DaemonManager.ts +318 -0
- package/src/services/ProcessManager.ts +235 -0
- package/src/services/ServiceManager.ts +319 -0
- package/src/services/TemplateManager.ts +382 -0
- package/src/services/__tests__/DaemonManager.test.ts +378 -0
- package/src/services/__tests__/DaemonMode.integration.test.ts +321 -0
- package/src/services/__tests__/ProcessManager.test.ts +296 -0
- package/src/services/__tests__/ServiceManager.test.ts +774 -0
- package/src/services/__tests__/TemplateManager.test.ts +337 -0
- package/src/types/backend.d.ts +48 -0
- package/src/utils/FileUtils.ts +320 -0
- package/src/utils/FormatUtils.ts +198 -0
- package/src/utils/PathUtils.ts +255 -0
- package/src/utils/PlatformUtils.ts +217 -0
- package/src/utils/Validation.ts +274 -0
- package/src/utils/VersionUtils.ts +141 -0
- package/src/utils/__tests__/FileUtils.test.ts +728 -0
- package/src/utils/__tests__/FormatUtils.test.ts +243 -0
- package/src/utils/__tests__/PathUtils.test.ts +1165 -0
- package/src/utils/__tests__/PlatformUtils.test.ts +723 -0
- package/src/utils/__tests__/Validation.test.ts +560 -0
- package/src/utils/__tests__/VersionUtils.test.ts +410 -0
- package/tsconfig.json +32 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/tsup.config.ts +107 -0
- package/vitest.config.ts +97 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 shenjingnan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# @xiaozhi-client/cli
|
|
2
|
+
|
|
3
|
+
小智客户端 CLI 包,提供命令行界面用于管理 MCP 服务和配置。
|
|
4
|
+
|
|
5
|
+
## 包说明
|
|
6
|
+
|
|
7
|
+
此包是 xiaozhi-client 项目的 CLI 入口点,作为独立 npm 包发布。它与 xiaozhi-client 主包共享相同的代码库和版本号。
|
|
8
|
+
|
|
9
|
+
## 目录结构
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
packages/cli/
|
|
13
|
+
├── src/
|
|
14
|
+
│ ├── index.ts # 主入口
|
|
15
|
+
│ ├── Container.ts # DI 容器
|
|
16
|
+
│ ├── Types.ts # 类型定义
|
|
17
|
+
│ ├── Constants.ts # 常量定义
|
|
18
|
+
│ ├── commands/ # 命令处理器
|
|
19
|
+
│ │ ├── index.ts
|
|
20
|
+
│ │ ├── CommandRegistry.ts
|
|
21
|
+
│ │ ├── CommandHandlerFactory.ts
|
|
22
|
+
│ │ ├── ConfigCommandHandler.ts
|
|
23
|
+
│ │ ├── EndpointCommandHandler.ts
|
|
24
|
+
│ │ ├── McpCommandHandler.ts
|
|
25
|
+
│ │ ├── ProjectCommandHandler.ts
|
|
26
|
+
│ │ └── ServiceCommandHandler.ts
|
|
27
|
+
│ ├── services/ # 服务管理器
|
|
28
|
+
│ │ ├── ProcessManager.ts
|
|
29
|
+
│ │ ├── DaemonManager.ts
|
|
30
|
+
│ │ ├── ServiceManager.ts
|
|
31
|
+
│ │ └── TemplateManager.ts
|
|
32
|
+
│ ├── utils/ # 工具类
|
|
33
|
+
│ ├── interfaces/ # 接口定义
|
|
34
|
+
│ └── errors/ # 错误处理
|
|
35
|
+
├── package.json
|
|
36
|
+
├── project.json # Nx 项目配置
|
|
37
|
+
├── tsconfig.json
|
|
38
|
+
└── tsup.config.ts # 构建配置
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 构建配置
|
|
42
|
+
|
|
43
|
+
- **入口点**:`src/index.ts` → `../../dist/cli/index.js`
|
|
44
|
+
- **格式**:ESM (ES Modules)
|
|
45
|
+
- **目标**:Node.js 18+
|
|
46
|
+
- **打包工具**:tsup (esbuild)
|
|
47
|
+
|
|
48
|
+
## 外部依赖
|
|
49
|
+
|
|
50
|
+
CLI 包通过 external 配置引用 backend 模块:
|
|
51
|
+
|
|
52
|
+
- `@root/WebServer` → `dist/backend/WebServer.js` (通过 WebServerLauncher)
|
|
53
|
+
- `@/lib/config/manager` → `dist/backend/lib/config/manager.js`
|
|
54
|
+
|
|
55
|
+
## 导入方式
|
|
56
|
+
|
|
57
|
+
### 内部导入(使用相对路径)
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// CLI 包内部使用相对路径
|
|
61
|
+
import { DIContainer } from "./Container";
|
|
62
|
+
import { CommandRegistry } from "./commands/index";
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 外部依赖(使用路径别名)
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// 引用 backend 模块
|
|
69
|
+
import { configManager } from "@/lib/config/manager";
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## 开发命令
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# 构建
|
|
76
|
+
pnpm build
|
|
77
|
+
|
|
78
|
+
# 类型检查
|
|
79
|
+
pnpm type-check
|
|
80
|
+
|
|
81
|
+
# 运行测试
|
|
82
|
+
pnpm test
|
|
83
|
+
|
|
84
|
+
# 代码检查
|
|
85
|
+
pnpm lint
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## 依赖关系
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
packages/cli
|
|
92
|
+
↓ (implicitDependencies)
|
|
93
|
+
apps/backend
|
|
94
|
+
↓ (implicitDependencies)
|
|
95
|
+
packages/shared-types
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
构建顺序:shared-types → backend → cli
|
package/fix-imports.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 构建后处理脚本
|
|
3
|
+
* 将路径别名替换为相对路径
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { resolve } from "node:path";
|
|
8
|
+
|
|
9
|
+
const filePath = resolve("./dist/cli/index.js");
|
|
10
|
+
let content = readFileSync(filePath, "utf-8");
|
|
11
|
+
|
|
12
|
+
// 替换 @root/* 为指向 dist/backend 的相对路径
|
|
13
|
+
content = content
|
|
14
|
+
.replace(
|
|
15
|
+
/from "@\/lib\/config\/manager\.js"/g,
|
|
16
|
+
'from "../../dist/backend/lib/config/manager.js"'
|
|
17
|
+
)
|
|
18
|
+
.replace(
|
|
19
|
+
/from "@\/lib\/config\/manager"/g,
|
|
20
|
+
'from "../../dist/backend/lib/config/manager.js"'
|
|
21
|
+
)
|
|
22
|
+
.replace(
|
|
23
|
+
/from "@root\/WebServer\.js"/g,
|
|
24
|
+
'from "../../dist/backend/WebServer.js"'
|
|
25
|
+
)
|
|
26
|
+
.replace(
|
|
27
|
+
/from "@root\/WebServer"/g,
|
|
28
|
+
'from "../../dist/backend/WebServer.js"'
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
writeFileSync(filePath, content);
|
|
32
|
+
console.log("✅ 已修复 dist/cli/index.js 中的导入路径");
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xiaozhi-client/cli",
|
|
3
|
+
"version": "1.9.4-beta.5",
|
|
4
|
+
"private": false,
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "../../dist/cli/index.js",
|
|
10
|
+
"bin": {
|
|
11
|
+
"xiaozhi": "../../dist/cli/index.js",
|
|
12
|
+
"xiaozhi-client": "../../dist/cli/index.js"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"consola": "^3.4.2",
|
|
16
|
+
"@xiaozhi-client/config": "1.9.4-beta.5"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/node": "^24.3.0",
|
|
20
|
+
"typescript": "^5.9.2"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup",
|
|
24
|
+
"type-check": "tsc --noEmit"
|
|
25
|
+
}
|
|
26
|
+
}
|
package/project.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cli",
|
|
3
|
+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
+
"sourceRoot": "packages/cli/src",
|
|
5
|
+
"projectType": "library",
|
|
6
|
+
"targets": {
|
|
7
|
+
"build": {
|
|
8
|
+
"executor": "nx:run-commands",
|
|
9
|
+
"options": {
|
|
10
|
+
"command": "tsup",
|
|
11
|
+
"cwd": "packages/cli"
|
|
12
|
+
},
|
|
13
|
+
"outputs": ["{workspaceRoot}/dist/cli"],
|
|
14
|
+
"dependsOn": ["backend:build", "config:build"]
|
|
15
|
+
},
|
|
16
|
+
"test": {
|
|
17
|
+
"executor": "nx:run-commands",
|
|
18
|
+
"options": {
|
|
19
|
+
"command": "vitest run --coverage.enabled=false",
|
|
20
|
+
"cwd": "packages/cli"
|
|
21
|
+
},
|
|
22
|
+
"outputs": ["{workspaceRoot}/coverage"]
|
|
23
|
+
},
|
|
24
|
+
"test:watch": {
|
|
25
|
+
"executor": "nx:run-commands",
|
|
26
|
+
"options": {
|
|
27
|
+
"command": "vitest",
|
|
28
|
+
"cwd": "packages/cli"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"test:coverage": {
|
|
32
|
+
"executor": "nx:run-commands",
|
|
33
|
+
"options": {
|
|
34
|
+
"command": "vitest run --coverage",
|
|
35
|
+
"cwd": "packages/cli"
|
|
36
|
+
},
|
|
37
|
+
"outputs": ["{workspaceRoot}/coverage"]
|
|
38
|
+
},
|
|
39
|
+
"lint": {
|
|
40
|
+
"executor": "nx:run-commands",
|
|
41
|
+
"options": {
|
|
42
|
+
"command": "biome check packages/cli"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"lint:fix": {
|
|
46
|
+
"executor": "nx:run-commands",
|
|
47
|
+
"options": {
|
|
48
|
+
"command": "biome check --write packages/cli"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"type-check": {
|
|
52
|
+
"executor": "nx:run-commands",
|
|
53
|
+
"options": {
|
|
54
|
+
"command": "echo 'CLI type-check skipped: bundled by tsup which strips types'"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"dev": {
|
|
58
|
+
"executor": "nx:run-commands",
|
|
59
|
+
"options": {
|
|
60
|
+
"command": "tsup --watch",
|
|
61
|
+
"cwd": "packages/cli"
|
|
62
|
+
},
|
|
63
|
+
"dependsOn": ["backend:build"]
|
|
64
|
+
},
|
|
65
|
+
"nx-release-publish": {
|
|
66
|
+
"executor": "nx:run-commands",
|
|
67
|
+
"options": {
|
|
68
|
+
"command": "pnpm publish --access public --no-git-checks",
|
|
69
|
+
"cwd": "packages/cli"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"tags": ["type:lib", "scope:cli"],
|
|
74
|
+
"implicitDependencies": ["backend", "shared-types"]
|
|
75
|
+
}
|
package/src/Constants.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI 常量定义
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 服务相关常量
|
|
7
|
+
*/
|
|
8
|
+
export const SERVICE_CONSTANTS = {
|
|
9
|
+
/** 服务名称 */
|
|
10
|
+
NAME: "xiaozhi-mcp-service",
|
|
11
|
+
/** 默认端口 */
|
|
12
|
+
DEFAULT_PORT: 3000,
|
|
13
|
+
/** Web UI 默认端口 */
|
|
14
|
+
DEFAULT_WEB_UI_PORT: 9999,
|
|
15
|
+
/** PID 文件名 */
|
|
16
|
+
PID_FILE: "xiaozhi.pid",
|
|
17
|
+
/** 日志文件名 */
|
|
18
|
+
LOG_FILE: "xiaozhi.log",
|
|
19
|
+
} as const;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 配置相关常量
|
|
23
|
+
*/
|
|
24
|
+
export const CONFIG_CONSTANTS = {
|
|
25
|
+
/** 配置文件名(按优先级排序) */
|
|
26
|
+
FILE_NAMES: [
|
|
27
|
+
"xiaozhi.config.json5",
|
|
28
|
+
"xiaozhi.config.jsonc",
|
|
29
|
+
"xiaozhi.config.json",
|
|
30
|
+
],
|
|
31
|
+
/** 默认配置文件名 */
|
|
32
|
+
DEFAULT_FILE: "xiaozhi.config.default.json",
|
|
33
|
+
/** 配置目录环境变量 */
|
|
34
|
+
DIR_ENV_VAR: "XIAOZHI_CONFIG_DIR",
|
|
35
|
+
} as const;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 路径相关常量
|
|
39
|
+
*/
|
|
40
|
+
export const PATH_CONSTANTS = {
|
|
41
|
+
/** 工作目录名 */
|
|
42
|
+
WORK_DIR: ".xiaozhi",
|
|
43
|
+
/** 模板目录名 */
|
|
44
|
+
TEMPLATES_DIR: "templates",
|
|
45
|
+
/** 日志目录名 */
|
|
46
|
+
LOGS_DIR: "logs",
|
|
47
|
+
} as const;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 错误码常量
|
|
51
|
+
*/
|
|
52
|
+
export const ERROR_CODES = {
|
|
53
|
+
/** 通用错误 */
|
|
54
|
+
GENERAL_ERROR: "GENERAL_ERROR",
|
|
55
|
+
/** 配置错误 */
|
|
56
|
+
CONFIG_ERROR: "CONFIG_ERROR",
|
|
57
|
+
/** 服务错误 */
|
|
58
|
+
SERVICE_ERROR: "SERVICE_ERROR",
|
|
59
|
+
/** 验证错误 */
|
|
60
|
+
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
61
|
+
/** 文件操作错误 */
|
|
62
|
+
FILE_ERROR: "FILE_ERROR",
|
|
63
|
+
/** 进程错误 */
|
|
64
|
+
PROCESS_ERROR: "PROCESS_ERROR",
|
|
65
|
+
/** 网络错误 */
|
|
66
|
+
NETWORK_ERROR: "NETWORK_ERROR",
|
|
67
|
+
/** 权限错误 */
|
|
68
|
+
PERMISSION_ERROR: "PERMISSION_ERROR",
|
|
69
|
+
} as const;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 超时常量(毫秒)
|
|
73
|
+
*/
|
|
74
|
+
export const TIMEOUT_CONSTANTS = {
|
|
75
|
+
/** 进程停止超时 */
|
|
76
|
+
PROCESS_STOP: 3000,
|
|
77
|
+
/** 服务启动超时 */
|
|
78
|
+
SERVICE_START: 10000,
|
|
79
|
+
/** 网络请求超时 */
|
|
80
|
+
NETWORK_REQUEST: 5000,
|
|
81
|
+
/** 文件操作超时 */
|
|
82
|
+
FILE_OPERATION: 2000,
|
|
83
|
+
} as const;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 分页相关常量
|
|
87
|
+
*/
|
|
88
|
+
export const PAGINATION_CONSTANTS = {
|
|
89
|
+
/** 默认每页记录数 */
|
|
90
|
+
DEFAULT_LIMIT: 50,
|
|
91
|
+
/** 最大每页记录数 */
|
|
92
|
+
MAX_LIMIT: 200,
|
|
93
|
+
} as const;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 重试常量
|
|
97
|
+
*/
|
|
98
|
+
export const RETRY_CONSTANTS = {
|
|
99
|
+
/** 默认重试次数 */
|
|
100
|
+
DEFAULT_ATTEMPTS: 3,
|
|
101
|
+
/** 重试间隔(毫秒) */
|
|
102
|
+
DEFAULT_INTERVAL: 1000,
|
|
103
|
+
/** 最大重试间隔(毫秒) */
|
|
104
|
+
MAX_INTERVAL: 5000,
|
|
105
|
+
} as const;
|
package/src/Container.ts
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 依赖注入容器
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { configManager } from "@xiaozhi-client/config";
|
|
6
|
+
import { ErrorHandler } from "./errors/ErrorHandlers";
|
|
7
|
+
import type { IDIContainer } from "./interfaces/Config";
|
|
8
|
+
import { FileUtils } from "./utils/FileUtils";
|
|
9
|
+
import { FormatUtils } from "./utils/FormatUtils";
|
|
10
|
+
import { PathUtils } from "./utils/PathUtils";
|
|
11
|
+
import { PlatformUtils } from "./utils/PlatformUtils";
|
|
12
|
+
import { Validation } from "./utils/Validation";
|
|
13
|
+
import { VersionUtils } from "./utils/VersionUtils";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 依赖注入容器实现
|
|
17
|
+
*/
|
|
18
|
+
export class DIContainer implements IDIContainer {
|
|
19
|
+
private instances = new Map<string, any>();
|
|
20
|
+
private factories = new Map<string, () => any>();
|
|
21
|
+
private asyncFactories = new Map<string, () => Promise<any>>();
|
|
22
|
+
private singletons = new Set<string>();
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 注册服务工厂
|
|
26
|
+
*/
|
|
27
|
+
register<T>(key: string, factory: () => T, singleton = false): void {
|
|
28
|
+
this.factories.set(key, factory);
|
|
29
|
+
if (singleton) {
|
|
30
|
+
this.singletons.add(key);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 注册单例服务
|
|
36
|
+
*/
|
|
37
|
+
registerSingleton<T>(key: string, factory: () => T): void {
|
|
38
|
+
this.register(key, factory, true);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 注册实例
|
|
43
|
+
*/
|
|
44
|
+
registerInstance<T>(key: string, instance: T): void {
|
|
45
|
+
this.instances.set(key, instance);
|
|
46
|
+
this.singletons.add(key);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 获取服务实例
|
|
51
|
+
*/
|
|
52
|
+
get<T>(key: string): T {
|
|
53
|
+
// 如果是单例且已经创建过实例,直接返回
|
|
54
|
+
if (this.singletons.has(key) && this.instances.has(key)) {
|
|
55
|
+
return this.instances.get(key);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// 获取工厂函数
|
|
59
|
+
const factory = this.factories.get(key);
|
|
60
|
+
if (!factory) {
|
|
61
|
+
throw new Error(`Service ${key} not registered`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 创建实例
|
|
65
|
+
const instance = factory();
|
|
66
|
+
|
|
67
|
+
// 如果是单例,缓存实例
|
|
68
|
+
if (this.singletons.has(key)) {
|
|
69
|
+
this.instances.set(key, instance);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return instance;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 检查服务是否已注册
|
|
77
|
+
*/
|
|
78
|
+
has(key: string): boolean {
|
|
79
|
+
return this.factories.has(key) || this.instances.has(key);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 清除所有注册的服务
|
|
84
|
+
*/
|
|
85
|
+
clear(): void {
|
|
86
|
+
this.instances.clear();
|
|
87
|
+
this.factories.clear();
|
|
88
|
+
this.singletons.clear();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* 获取所有已注册的服务键
|
|
93
|
+
*/
|
|
94
|
+
getRegisteredKeys(): string[] {
|
|
95
|
+
const factoryKeys = Array.from(this.factories.keys());
|
|
96
|
+
const instanceKeys = Array.from(this.instances.keys());
|
|
97
|
+
return [...new Set([...factoryKeys, ...instanceKeys])];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 创建默认容器实例
|
|
102
|
+
*/
|
|
103
|
+
static create(): DIContainer {
|
|
104
|
+
const container = new DIContainer();
|
|
105
|
+
|
|
106
|
+
// 注册工具类(单例)
|
|
107
|
+
container.registerSingleton("versionUtils", () => {
|
|
108
|
+
return VersionUtils;
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
container.registerSingleton("platformUtils", () => {
|
|
112
|
+
return PlatformUtils;
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
container.registerSingleton("formatUtils", () => {
|
|
116
|
+
return FormatUtils;
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
container.registerSingleton("fileUtils", () => {
|
|
120
|
+
return FileUtils;
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
container.registerSingleton("pathUtils", () => {
|
|
124
|
+
return PathUtils;
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
container.registerSingleton("validation", () => {
|
|
128
|
+
return Validation;
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// 注册配置管理器(单例)
|
|
132
|
+
container.registerSingleton("configManager", () => {
|
|
133
|
+
return configManager;
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// 注册错误处理器(单例)
|
|
137
|
+
container.registerSingleton("errorHandler", () => {
|
|
138
|
+
return ErrorHandler;
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// 注册服务层
|
|
142
|
+
container.registerSingleton("processManager", () => {
|
|
143
|
+
const ProcessManagerModule = require("@cli/services/ProcessManager.js");
|
|
144
|
+
return new ProcessManagerModule.ProcessManagerImpl();
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
container.registerSingleton("daemonManager", () => {
|
|
148
|
+
const DaemonManagerModule = require("@cli/services/DaemonManager.js");
|
|
149
|
+
const processManager = container.get("processManager") as any;
|
|
150
|
+
return new DaemonManagerModule.DaemonManagerImpl(processManager);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
container.registerSingleton("serviceManager", () => {
|
|
154
|
+
const ServiceManagerModule = require("@cli/services/ServiceManager.js");
|
|
155
|
+
const processManager = container.get("processManager") as any;
|
|
156
|
+
const configManager = container.get("configManager") as any;
|
|
157
|
+
return new ServiceManagerModule.ServiceManagerImpl(
|
|
158
|
+
processManager,
|
|
159
|
+
configManager
|
|
160
|
+
);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
container.registerSingleton("templateManager", () => {
|
|
164
|
+
// 使用动态导入的同步版本
|
|
165
|
+
const TemplateManagerModule = require("@cli/services/TemplateManager.js");
|
|
166
|
+
return new TemplateManagerModule.TemplateManagerImpl();
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// 注册命令层(稍后在命令层实现时添加)
|
|
170
|
+
// container.register('serviceCommand', () => {
|
|
171
|
+
// const { ServiceCommand } = require('./commands/ServiceCommand.js');
|
|
172
|
+
// const serviceManager = container.get('serviceManager');
|
|
173
|
+
// const processManager = container.get('processManager');
|
|
174
|
+
// return new ServiceCommand(serviceManager, processManager);
|
|
175
|
+
// });
|
|
176
|
+
|
|
177
|
+
// container.register('configCommand', () => {
|
|
178
|
+
// const { ConfigCommand } = require('./commands/ConfigCommand.js');
|
|
179
|
+
// const configManager = container.get('configManager');
|
|
180
|
+
// const validation = container.get('validation');
|
|
181
|
+
// return new ConfigCommand(configManager, validation);
|
|
182
|
+
// });
|
|
183
|
+
|
|
184
|
+
// container.register('projectCommand', () => {
|
|
185
|
+
// const { ProjectCommand } = require('./commands/ProjectCommand.js');
|
|
186
|
+
// const templateManager = container.get('templateManager');
|
|
187
|
+
// const fileUtils = container.get('fileUtils');
|
|
188
|
+
// return new ProjectCommand(templateManager, fileUtils);
|
|
189
|
+
// });
|
|
190
|
+
|
|
191
|
+
// container.register('mcpCommand', () => {
|
|
192
|
+
// const { McpCommand } = require('./commands/McpCommand.js');
|
|
193
|
+
// return new McpCommand();
|
|
194
|
+
// });
|
|
195
|
+
|
|
196
|
+
// container.register('infoCommand', () => {
|
|
197
|
+
// const { InfoCommand } = require('./commands/InfoCommand.js');
|
|
198
|
+
// const versionUtils = container.get('versionUtils');
|
|
199
|
+
// const platformUtils = container.get('platformUtils');
|
|
200
|
+
// return new InfoCommand(versionUtils, platformUtils);
|
|
201
|
+
// });
|
|
202
|
+
|
|
203
|
+
return container;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* 创建并配置 DI 容器
|
|
209
|
+
*/
|
|
210
|
+
export async function createContainer(): Promise<IDIContainer> {
|
|
211
|
+
return DIContainer.create();
|
|
212
|
+
}
|
package/src/Types.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI 核心类型定义
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 平台类型
|
|
7
|
+
*/
|
|
8
|
+
export type Platform =
|
|
9
|
+
| "win32"
|
|
10
|
+
| "darwin"
|
|
11
|
+
| "linux"
|
|
12
|
+
| "freebsd"
|
|
13
|
+
| "openbsd"
|
|
14
|
+
| "sunos"
|
|
15
|
+
| "aix";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 日志级别
|
|
19
|
+
*/
|
|
20
|
+
export type LogLevel = "error" | "warn" | "info" | "debug";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 配置文件格式
|
|
24
|
+
*/
|
|
25
|
+
export type ConfigFormat = "json" | "json5" | "jsonc";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 命令执行结果
|
|
29
|
+
*/
|
|
30
|
+
export interface CommandResult {
|
|
31
|
+
/** 是否成功 */
|
|
32
|
+
success: boolean;
|
|
33
|
+
/** 结果消息 */
|
|
34
|
+
message?: string;
|
|
35
|
+
/** 错误信息 */
|
|
36
|
+
error?: Error;
|
|
37
|
+
/** 退出码 */
|
|
38
|
+
exitCode?: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 文件操作选项
|
|
43
|
+
*/
|
|
44
|
+
export interface FileOperationOptions {
|
|
45
|
+
/** 是否递归 */
|
|
46
|
+
recursive?: boolean;
|
|
47
|
+
/** 排除的文件/目录 */
|
|
48
|
+
exclude?: string[];
|
|
49
|
+
/** 是否覆盖现有文件 */
|
|
50
|
+
overwrite?: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 进程信息
|
|
55
|
+
*/
|
|
56
|
+
export interface ProcessInfo {
|
|
57
|
+
/** 进程 ID */
|
|
58
|
+
pid: number;
|
|
59
|
+
/** 进程名称 */
|
|
60
|
+
name: string;
|
|
61
|
+
/** 启动时间 */
|
|
62
|
+
startTime: number;
|
|
63
|
+
/** 命令行参数 */
|
|
64
|
+
args: string[];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 模板信息
|
|
69
|
+
*/
|
|
70
|
+
export interface TemplateInfo {
|
|
71
|
+
/** 模板名称 */
|
|
72
|
+
name: string;
|
|
73
|
+
/** 模板描述 */
|
|
74
|
+
description: string;
|
|
75
|
+
/** 模板路径 */
|
|
76
|
+
path: string;
|
|
77
|
+
/** 是否有效 */
|
|
78
|
+
valid: boolean;
|
|
79
|
+
}
|