ops-toolkit 1.2.0 → 1.2.2

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 文件。
@@ -0,0 +1,172 @@
1
+ # Publishing to npm
2
+
3
+ ## Quick Start
4
+
5
+ To publish a new version to npm, run one of the following commands:
6
+
7
+ ```bash
8
+ # Patch version (bug fixes): 1.2.1 → 1.2.2
9
+ bun run publish:patch
10
+
11
+ # Minor version (new features): 1.2.1 → 1.3.0
12
+ bun run publish:minor
13
+
14
+ # Major version (breaking changes): 1.2.1 → 2.0.0
15
+ bun run publish:major
16
+ ```
17
+
18
+ ## What Happens When You Publish
19
+
20
+ The `publish:*` commands automatically:
21
+
22
+ 1. **Quality Checks**
23
+ - Run ESLint to check code quality
24
+ - Run TypeScript type checking
25
+
26
+ 2. **Version Bump**
27
+ - Increment version number in package.json
28
+ - Create git tag (e.g., v1.2.2)
29
+ - Create git commit with changelog
30
+
31
+ 3. **Build**
32
+ - Build the project
33
+ - Generate distribution files in `dist/`
34
+
35
+ 4. **Changelog**
36
+ - Update CHANGELOG.md with changes
37
+ - Based on git commit history
38
+
39
+ 5. **Publish**
40
+ - Publish package to npm registry
41
+ - Create GitHub release
42
+ - Push git tags and commits to remote
43
+
44
+ ## Prerequisites
45
+
46
+ Before publishing, make sure:
47
+
48
+ 1. **Code is committed**
49
+ - All changes are committed to git
50
+ - Working directory is clean
51
+
52
+ 2. **Tests pass**
53
+
54
+ ```bash
55
+ bun test
56
+ ```
57
+
58
+ 3. **Build succeeds**
59
+
60
+ ```bash
61
+ bun run build
62
+ ```
63
+
64
+ 4. **You're logged in to npm**
65
+ ```bash
66
+ npm login
67
+ ```
68
+
69
+ ## Version Guidelines
70
+
71
+ ### Patch (bug fixes)
72
+
73
+ ```bash
74
+ bun run publish:patch
75
+ ```
76
+
77
+ Use for:
78
+
79
+ - Bug fixes
80
+ - Small improvements
81
+ - Non-breaking changes
82
+ - Documentation updates
83
+
84
+ ### Minor (new features)
85
+
86
+ ```bash
87
+ bun run publish:minor
88
+ ```
89
+
90
+ Use for:
91
+
92
+ - New features
93
+ - Backwards compatible changes
94
+ - Adding functionality
95
+
96
+ ### Major (breaking changes)
97
+
98
+ ```bash
99
+ bun run publish:major
100
+ ```
101
+
102
+ Use for:
103
+
104
+ - Breaking changes
105
+ - API changes
106
+ - Removing features
107
+
108
+ ## Troubleshooting
109
+
110
+ ### "Git working directory not clean"
111
+
112
+ ```bash
113
+ # Commit your changes first
114
+ git add .
115
+ git commit -m "your commit message"
116
+ ```
117
+
118
+ ### "403 Forbidden - You cannot publish over previously published versions"
119
+
120
+ This means the version already exists on npm. The publish commands will automatically bump the version, so you shouldn't see this error.
121
+
122
+ ### Build errors
123
+
124
+ ```bash
125
+ # Check build output
126
+ bun run build
127
+
128
+ # Fix any errors, then try publishing again
129
+ bun run publish:patch
130
+ ```
131
+
132
+ ## Manual Publishing
133
+
134
+ If you need more control, you can use `release-it` directly:
135
+
136
+ ```bash
137
+ # Interactive release
138
+ npx release-it
139
+
140
+ # Specific version
141
+ npx release-it 1.2.5
142
+
143
+ # Skip git operations
144
+ npx release-it --no-git --no-github
145
+ ```
146
+
147
+ ## After Publishing
148
+
149
+ Once published, users can install your package:
150
+
151
+ ```bash
152
+ # Global installation
153
+ npm install -g ops-toolkit
154
+
155
+ # Or using bun
156
+ bun install -g ops-toolkit
157
+
158
+ # Run the CLI
159
+ ops --help
160
+ ```
161
+
162
+ ## Configuration
163
+
164
+ Publishing behavior is configured in `.release-it.json`:
165
+
166
+ - **Git**: Automatic commits and tags
167
+ - **NPM**: Automatic publishing to public registry
168
+ - **GitHub**: Automatic releases
169
+ - **Hooks**: Pre-publish checks and post-build actions
170
+ - **Changelog**: Auto-generated from commit history
171
+
172
+ For more details, see [release-it documentation](https://github.com/release-it/release-it).