ops-toolkit 1.1.0 → 1.2.1

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.
@@ -0,0 +1,554 @@
1
+ # Ops Toolkit 开发指南
2
+
3
+ ## 快速开始
4
+
5
+ ### 环境要求
6
+
7
+ - Node.js >= 18.0.0
8
+ - Bun >= 1.0.0
9
+ - TypeScript >= 5.3.0
10
+
11
+ ### 开发设置
12
+
13
+ ```bash
14
+ # 克隆项目
15
+ git clone <repository-url>
16
+ cd ops-toolkit
17
+
18
+ # 安装依赖
19
+ bun install
20
+
21
+ # 启动开发模式
22
+ bun run dev
23
+
24
+ # 构建项目
25
+ bun run build
26
+ ```
27
+
28
+ ## 项目结构
29
+
30
+ ```
31
+ ops-toolkit/
32
+ ├── bin/ # 可执行文件
33
+ │ └── ops-toolkit.ts # CLI入口点
34
+ ├── src/ # 源代码
35
+ │ ├── cli/ # CLI核心模块
36
+ │ │ ├── app.ts # CLI应用程序主类
37
+ │ │ ├── command-registry.ts # 命令注册系统
38
+ │ │ └── command-discovery.ts # 命令发现器
39
+ │ ├── commands/ # 命令实现
40
+ │ │ ├── monitor/ # 监控命令
41
+ │ │ ├── logs/ # 日志命令
42
+ │ │ ├── deploy/ # 部署命令
43
+ │ │ └── system/ # 系统命令
44
+ │ ├── utils/ # 工具类
45
+ │ │ ├── logger.ts # 日志系统
46
+ │ │ ├── config.ts # 配置管理
47
+ │ │ ├── error-handlers.ts # 错误处理
48
+ │ │ ├── error-reporter.ts # 错误报告
49
+ │ │ └── system.ts # 系统工具
50
+ │ ├── types/ # 类型定义
51
+ │ │ ├── commands.ts # 命令类型
52
+ │ │ ├── ui.ts # UI类型
53
+ │ │ └── system.ts # 系统类型
54
+ │ └── index.ts # 开发入口点
55
+ ├── docs/ # 文档
56
+ ├── tests/ # 测试文件
57
+ └── dist/ # 构建输出
58
+ ```
59
+
60
+ ## 开发规范
61
+
62
+ ### 代码风格
63
+
64
+ 项目使用严格的TypeScript配置和ESLint规则:
65
+
66
+ ```bash
67
+ # 类型检查
68
+ bun run typecheck
69
+
70
+ # 代码检查
71
+ bun run lint
72
+
73
+ # 自动修复
74
+ bun run lint:fix
75
+
76
+ # 代码格式化
77
+ bun run format
78
+ ```
79
+
80
+ ### 命名约定
81
+
82
+ - **文件名**:kebab-case(如:command-discovery.ts)
83
+ - **类名**:PascalCase(如:CommandRegistry)
84
+ - **方法名**:camelCase(如:registerCommand)
85
+ - **常量**:SCREAMING_SNAKE_CASE(如:LogLevel.ERROR)
86
+ - **接口**:PascalCase(如:CommandDefinition)
87
+
88
+ ### 注释规范
89
+
90
+ 所有公共API必须包含JSDoc注释:
91
+
92
+ ````typescript
93
+ /**
94
+ * 注册命令到系统中
95
+ * @param command 命令定义对象
96
+ * @throws {ConfigError} 当命令验证失败时
97
+ * @example
98
+ * ```typescript
99
+ * registry.register({
100
+ * name: 'test',
101
+ * description: '测试命令',
102
+ * action: async () => console.log('Hello')
103
+ * });
104
+ * ```
105
+ */
106
+ public register(command: CommandDefinition): void {
107
+ // 实现
108
+ }
109
+ ````
110
+
111
+ ## 组件开发
112
+
113
+ ### 创建新命令
114
+
115
+ 1. **创建命令目录**
116
+
117
+ ```bash
118
+ mkdir -p src/commands/my-command
119
+ ```
120
+
121
+ 2. **实现命令文件**
122
+
123
+ ```typescript
124
+ // src/commands/my-command/index.ts
125
+ import { type CommandDefinition } from '@/cli/command-registry';
126
+ import { Logger } from '@/utils/logger';
127
+
128
+ export const MyCommand: CommandDefinition = {
129
+ name: 'my-command',
130
+ description: '我的自定义命令',
131
+ alias: 'mc',
132
+ options: [
133
+ {
134
+ flags: '-f, --force',
135
+ description: '强制执行',
136
+ defaultValue: false,
137
+ },
138
+ ],
139
+ subcommands: [
140
+ {
141
+ name: 'sub1',
142
+ description: '子命令1',
143
+ action: async options => {
144
+ Logger.info('执行子命令1', options);
145
+ },
146
+ },
147
+ ],
148
+ action: async options => {
149
+ Logger.info('执行我的命令', options);
150
+ },
151
+ };
152
+
153
+ export default MyCommand;
154
+ ```
155
+
156
+ 3. **命令自动注册**
157
+ 命令发现器会自动扫描并注册新命令,无需手动注册。
158
+
159
+ ### 扩展工具类
160
+
161
+ ```typescript
162
+ // src/utils/my-util.ts
163
+ import { Logger } from './logger';
164
+
165
+ export class MyUtil {
166
+ /**
167
+ * 我的工具方法
168
+ */
169
+ static doSomething(input: string): string {
170
+ Logger.debug('MyUtil.doSomething', { input });
171
+ return input.toUpperCase();
172
+ }
173
+ }
174
+ ```
175
+
176
+ ### 添加新类型
177
+
178
+ ```typescript
179
+ // src/types/my-types.ts
180
+ export interface MyInterface {
181
+ id: string;
182
+ name: string;
183
+ metadata?: Record<string, unknown>;
184
+ }
185
+
186
+ export enum MyEnum {
187
+ FIRST = 'first',
188
+ SECOND = 'second',
189
+ }
190
+ ```
191
+
192
+ ## 配置管理
193
+
194
+ ### 配置结构
195
+
196
+ ```typescript
197
+ // 扩展配置接口
198
+ export interface OpsConfig {
199
+ // 现有配置...
200
+ myModule: {
201
+ enabled: boolean;
202
+ apiKey: string;
203
+ timeout: number;
204
+ };
205
+ }
206
+ ```
207
+
208
+ ### 配置验证器
209
+
210
+ ```typescript
211
+ import { ConfigValidator } from '@/utils/config';
212
+
213
+ class MyConfigValidator implements ConfigValidator {
214
+ validate(config: OpsConfig): boolean {
215
+ return !!(config.myModule?.apiKey?.length > 10);
216
+ }
217
+
218
+ getErrors(): string[] {
219
+ return this.errors || [];
220
+ }
221
+
222
+ private errors: string[] = [];
223
+ }
224
+
225
+ // 注册验证器
226
+ ConfigManager.registerValidator('myModule', new MyConfigValidator());
227
+ ```
228
+
229
+ ## 错误处理
230
+
231
+ ### 自定义错误类
232
+
233
+ ```typescript
234
+ import { CLIError } from '@/utils/error-handlers';
235
+
236
+ export class MyError extends CLIError {
237
+ constructor(message: string, details?: string) {
238
+ super(message, 'MY_ERROR_CODE');
239
+ this.name = 'MyError';
240
+ this.details = details;
241
+ }
242
+
243
+ details?: string;
244
+ }
245
+ ```
246
+
247
+ ### 错误处理模式
248
+
249
+ ```typescript
250
+ import { errorHandler, ErrorSeverity } from '@/utils/error-handlers';
251
+ import { withAsyncErrorHandling } from '@/utils/error-handlers';
252
+
253
+ // 模式1:直接处理
254
+ try {
255
+ // 业务逻辑
256
+ } catch (error) {
257
+ errorHandler(
258
+ error,
259
+ {
260
+ command: 'my-command',
261
+ action: 'execute',
262
+ },
263
+ ErrorSeverity.MEDIUM
264
+ );
265
+ }
266
+
267
+ // 模式2:包装函数
268
+ const safeExecute = withAsyncErrorHandling(
269
+ async (input: string) => {
270
+ // 业务逻辑
271
+ },
272
+ { command: 'my-command', action: 'execute' },
273
+ ErrorSeverity.LOW
274
+ );
275
+ ```
276
+
277
+ ## 日志系统
278
+
279
+ ### 日志级别
280
+
281
+ - **DEBUG**: 调试信息
282
+ - **INFO**: 一般信息
283
+ - **WARN**: 警告信息
284
+ - **ERROR**: 错误信息
285
+ - **CRITICAL**: 严重错误
286
+
287
+ ### 日志使用
288
+
289
+ ```typescript
290
+ import { Logger } from '@/utils/logger';
291
+
292
+ // 基本日志
293
+ Logger.info('操作开始');
294
+ Logger.success('操作完成');
295
+ Logger.warning('注意:配置缺失');
296
+ Logger.error('操作失败', error, { userId: 123 });
297
+ Logger.critical('系统崩溃', error);
298
+
299
+ // 带上下文
300
+ Logger.info('用户操作', { userId, action }, 'auth');
301
+ Logger.debug('详细调试信息', { request, response }, 'api');
302
+
303
+ // 结构化日志
304
+ Logger.configure({
305
+ level: LogLevel.DEBUG,
306
+ enableFileLogging: true,
307
+ logDirectory: './logs',
308
+ });
309
+ ```
310
+
311
+ ## 测试
312
+
313
+ ### 单元测试
314
+
315
+ ```typescript
316
+ // tests/utils/my-util.test.ts
317
+ import { describe, it, expect } from 'bun:test';
318
+ import { MyUtil } from '@/utils/my-util';
319
+
320
+ describe('MyUtil', () => {
321
+ it('should uppercase input', () => {
322
+ expect(MyUtil.doSomething('hello')).toBe('HELLO');
323
+ });
324
+
325
+ it('should handle empty input', () => {
326
+ expect(MyUtil.doSomething('')).toBe('');
327
+ });
328
+ });
329
+ ```
330
+
331
+ ### 集成测试
332
+
333
+ ```typescript
334
+ // tests/commands/my-command.test.ts
335
+ import { CLIApp } from '@/cli/app';
336
+
337
+ describe('MyCommand', () => {
338
+ it('should execute command successfully', async () => {
339
+ const app = new CLIApp();
340
+ await app.initialize();
341
+
342
+ // 测试命令执行
343
+ // 注意:需要模拟process.argv或直接调用命令
344
+ });
345
+ });
346
+ ```
347
+
348
+ ## 性能优化
349
+
350
+ ### 异步操作
351
+
352
+ ```typescript
353
+ // ✅ 正确:使用异步操作
354
+ export async function processLargeFile(filePath: string): Promise<void> {
355
+ const stream = fs.createReadStream(filePath);
356
+ for await (const chunk of stream) {
357
+ // 处理数据块
358
+ }
359
+ }
360
+
361
+ // ❌ 错误:阻塞操作
362
+ export function processLargeFile(filePath: string): void {
363
+ const data = fs.readFileSync(filePath);
364
+ // 处理整个文件 - 可能阻塞
365
+ }
366
+ ```
367
+
368
+ ### 内存管理
369
+
370
+ ```typescript
371
+ // 使用对象池
372
+ class ObjectPool<T> {
373
+ private pool: T[] = [];
374
+
375
+ acquire(): T {
376
+ return this.pool.pop() || this.createNew();
377
+ }
378
+
379
+ release(obj: T): void {
380
+ this.pool.push(obj);
381
+ }
382
+
383
+ private createNew(): T {
384
+ // 创建新实例
385
+ return {} as T;
386
+ }
387
+ }
388
+ ```
389
+
390
+ ## 调试
391
+
392
+ ### VS Code调试
393
+
394
+ 使用 `.vscode/launch.json` 中的配置进行调试:
395
+
396
+ ```json
397
+ {
398
+ "type": "node",
399
+ "request": "launch",
400
+ "name": "Debug Ops Toolkit",
401
+ "program": "${workspaceFolder}/src/index.ts",
402
+ "runtimeArgs": ["--inspect"],
403
+ "env": {
404
+ "NODE_ENV": "development",
405
+ "DEBUG": "true"
406
+ }
407
+ }
408
+ ```
409
+
410
+ ### 日志调试
411
+
412
+ ```typescript
413
+ // 启用详细日志
414
+ Logger.configure({
415
+ level: LogLevel.DEBUG,
416
+ enableFileLogging: true,
417
+ enableStructuredOutput: true,
418
+ });
419
+
420
+ // 使用调试日志
421
+ Logger.debug('进入函数', { functionName: 'myFunc', args });
422
+ Logger.debug('中间状态', { variable, step: 1 });
423
+ Logger.debug('函数结果', { result, duration: Date.now() - start });
424
+ ```
425
+
426
+ ## 部署
427
+
428
+ ### 构建流程
429
+
430
+ ```bash
431
+ # 开发构建
432
+ bun run build:dev
433
+
434
+ # 生产构建
435
+ bun run build:prod
436
+
437
+ # 版本发布
438
+ bun run release
439
+ ```
440
+
441
+ ### 发布检查清单
442
+
443
+ - [ ] 所有测试通过
444
+ - [ ] 类型检查无错误
445
+ - [ ] 代码检查无警告
446
+ - [ ] 文档已更新
447
+ - [ ] 版本号已更新
448
+ - [ ] CHANGELOG已更新
449
+
450
+ ## 最佳实践
451
+
452
+ ### 1. 错误优先处理
453
+
454
+ ```typescript
455
+ // ✅ 优先处理错误情况
456
+ async function processData(input: string): Promise<Result> {
457
+ if (!input) {
458
+ throw new ValidationError('输入不能为空');
459
+ }
460
+
461
+ if (input.length > MAX_LENGTH) {
462
+ throw new ValidationError('输入过长');
463
+ }
464
+
465
+ // 正常处理逻辑
466
+ }
467
+ ```
468
+
469
+ ### 2. 配置验证
470
+
471
+ ```typescript
472
+ // ✅ 启动时验证配置
473
+ async function initialize(): Promise<void> {
474
+ const config = ConfigManager.get();
475
+
476
+ if (!config.database.url) {
477
+ throw new ConfigError('数据库URL未配置');
478
+ }
479
+
480
+ await testDatabaseConnection(config.database);
481
+ }
482
+ ```
483
+
484
+ ### 3. 资源清理
485
+
486
+ ```typescript
487
+ // ✅ 使用 try-finally 确保资源清理
488
+ async function withConnection<T>(operation: (conn: Connection) => Promise<T>): Promise<T> {
489
+ const conn = await createConnection();
490
+ try {
491
+ return await operation(conn);
492
+ } finally {
493
+ await conn.close();
494
+ }
495
+ }
496
+ ```
497
+
498
+ ### 4. 类型安全
499
+
500
+ ```typescript
501
+ // ✅ 使用类型守卫
502
+ function isCommand(obj: unknown): obj is CommandDefinition {
503
+ return (
504
+ typeof obj === 'object' &&
505
+ obj !== null &&
506
+ 'name' in obj &&
507
+ 'description' in obj &&
508
+ 'action' in obj
509
+ );
510
+ }
511
+
512
+ // ✅ 使用 discriminated unions
513
+ type Result<T, E = Error> = { success: true; data: T } | { success: false; error: E };
514
+ ```
515
+
516
+ ## 常见问题
517
+
518
+ ### Q: 如何添加新的配置项?
519
+
520
+ A: 扩展 `OpsConfig` 接口,更新默认配置,可选添加验证器。
521
+
522
+ ### Q: 命令如何访问配置?
523
+
524
+ A: 使用 `ConfigManager.get(key)` 获取特定配置项。
525
+
526
+ ### Q: 如何处理长时间运行的任务?
527
+
528
+ A: 使用 `Logger.spinner()` 显示进度,并确保支持中断信号。
529
+
530
+ ### Q: 如何编写可测试的代码?
531
+
532
+ A: 依赖注入、避免全局状态、使用工厂函数。
533
+
534
+ ## 贡献指南
535
+
536
+ 1. Fork项目
537
+ 2. 创建功能分支
538
+ 3. 编写代码和测试
539
+ 4. 确保所有检查通过
540
+ 5. 提交Pull Request
541
+
542
+ 提交信息格式遵循Conventional Commits规范:
543
+
544
+ - `feat:` 新功能
545
+ - `fix:` 修复bug
546
+ - `refactor:` 重构
547
+ - `docs:` 文档更新
548
+ - `style:` 代码格式
549
+ - `test:` 测试相关
550
+ - `chore:` 构建/工具相关
551
+
552
+ ## 许可证
553
+
554
+ MIT License - 详见 LICENSE 文件。
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "ops-toolkit",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "A comprehensive DevOps CLI toolkit with terminal UI",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
- "ops": "./bin/ops-toolkit.ts",
8
- "ops-toolkit": "./bin/ops-toolkit.ts"
7
+ "ops": "./dist/bin/ops-toolkit.js",
8
+ "ops-toolkit": "./dist/bin/ops-toolkit.js"
9
9
  },
10
10
  "scripts": {
11
11
  "dev": "bun --watch src/index.ts",
12
- "build": "bun build src/index.ts --outdir dist --target node",
12
+ "build": "bun build src/index.ts --outdir dist --target node && bun build bin/ops-toolkit.ts --outdir dist/bin --target node && chmod +x dist/bin/ops-toolkit.js",
13
13
  "start": "bun src/index.ts",
14
14
  "lint": "eslint src bin",
15
15
  "lint:fix": "eslint src bin --fix",
@@ -37,12 +37,12 @@
37
37
  "license": "MIT",
38
38
  "repository": {
39
39
  "type": "git",
40
- "url": "https://github.com/username/ops-toolkit.git"
40
+ "url": "https://github.com/liangshaojie/ops-toolkit.git"
41
41
  },
42
42
  "bugs": {
43
- "url": "https://github.com/username/ops-toolkit/issues"
43
+ "url": "https://github.com/liangshaojie/ops-toolkit/issues"
44
44
  },
45
- "homepage": "https://github.com/username/ops-toolkit#readme",
45
+ "homepage": "https://github.com/liangshaojie/ops-toolkit#readme",
46
46
  "engines": {
47
47
  "node": ">=18.0.0",
48
48
  "bun": ">=1.0.0"