cmp-standards 2.4.0 → 2.7.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.
- package/README.md +633 -611
- package/dist/cli/index.js +0 -0
- package/dist/db/drizzle-client.d.ts +3 -3
- package/dist/db/drizzle-client.d.ts.map +1 -1
- package/dist/db/drizzle-client.js +57 -58
- package/dist/db/drizzle-client.js.map +1 -1
- package/dist/db/turso-client.js +11 -11
- package/dist/eslint/rules/no-async-useeffect.js +6 -6
- package/dist/hooks/cloud-pre-tool-use.js +20 -20
- package/dist/hooks/cloud-session-start.d.ts +15 -3
- package/dist/hooks/cloud-session-start.d.ts.map +1 -1
- package/dist/hooks/cloud-session-start.js +135 -8
- package/dist/hooks/cloud-session-start.js.map +1 -1
- package/dist/hooks/session-start.d.ts +2 -1
- package/dist/hooks/session-start.d.ts.map +1 -1
- package/dist/hooks/session-start.js +99 -74
- package/dist/hooks/session-start.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +2 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/schema/plans.d.ts +194 -0
- package/dist/schema/plans.d.ts.map +1 -0
- package/dist/schema/plans.js +180 -0
- package/dist/schema/plans.js.map +1 -0
- package/dist/schema/tracking.d.ts +90 -90
- package/dist/services/ContextGenerator.d.ts +16 -0
- package/dist/services/ContextGenerator.d.ts.map +1 -0
- package/dist/services/ContextGenerator.js +62 -0
- package/dist/services/ContextGenerator.js.map +1 -0
- package/dist/services/PlanManager.d.ts +99 -0
- package/dist/services/PlanManager.d.ts.map +1 -0
- package/dist/services/PlanManager.js +372 -0
- package/dist/services/PlanManager.js.map +1 -0
- package/dist/services/ProjectScaffold.js +76 -76
- package/dist/services/context-injector.d.ts +111 -0
- package/dist/services/context-injector.d.ts.map +1 -0
- package/dist/services/context-injector.js +397 -0
- package/dist/services/context-injector.js.map +1 -0
- package/dist/services/index.d.ts +15 -15
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +18 -20
- package/dist/services/index.js.map +1 -1
- package/dist/services/memory-router.d.ts +122 -0
- package/dist/services/memory-router.d.ts.map +1 -0
- package/dist/services/memory-router.js +517 -0
- package/dist/services/memory-router.js.map +1 -0
- package/dist/services/pattern-tracker.d.ts +97 -0
- package/dist/services/pattern-tracker.d.ts.map +1 -0
- package/dist/services/pattern-tracker.js +425 -0
- package/dist/services/pattern-tracker.js.map +1 -0
- package/dist/services/semantic-search.d.ts +33 -35
- package/dist/services/semantic-search.d.ts.map +1 -1
- package/dist/services/semantic-search.js +207 -165
- package/dist/services/semantic-search.js.map +1 -1
- package/dist/types/index.d.ts +329 -4
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +186 -9
- package/dist/types/index.js.map +1 -1
- package/package.json +104 -100
- package/standards/README.md +50 -50
- package/standards/experts/expert-routing.md +215 -215
- package/standards/general/code-quality.md +86 -86
- package/standards/general/memory-usage.md +205 -205
- package/standards/general/sync-workflow.md +235 -235
- package/standards/general/workflow.md +82 -82
- package/standards/hooks/mandatory-tracking.md +446 -446
- package/standards/infrastructure/cloud-database.md +287 -287
- package/standards/mcp/server-design.md +243 -243
- package/standards/mcp/tool-patterns.md +354 -354
- package/standards/skills/skill-structure.md +286 -286
- package/standards/skills/workflow-design.md +323 -323
- package/standards/tools/tool-design.md +297 -297
- package/templates/agents/architecture-expert.md +61 -61
- package/templates/agents/database-expert.md +62 -62
- package/templates/agents/documentation-expert.md +57 -57
- package/templates/agents/memory-expert.md +88 -88
- package/templates/agents/performance-expert.md +61 -61
- package/templates/agents/security-expert.md +59 -59
- package/templates/agents/ux-expert.md +63 -63
- package/templates/agents/worker.md +75 -75
- package/templates/ai-skills/SKILL_TEMPLATE.md +55 -55
- package/templates/claude-settings.json +72 -72
- package/templates/commands/experts.md +138 -138
- package/templates/hooks/README.md +158 -158
- package/templates/hooks/project.config.json.template +77 -77
- package/templates/hooks/settings.local.json.template +57 -57
- package/templates/memory-config.json +56 -56
- package/templates/memory-config.schema.json +212 -212
- package/templates/settings.json +58 -58
- package/templates/skills/continue.md +205 -205
- package/templates/workflows/business-improvement.md +264 -264
- package/templates/workflows/expert-review.md +153 -153
- package/templates/workflows/internal-app.md +245 -245
- package/templates/workflows/sync-docs.md +187 -187
|
@@ -1,297 +1,297 @@
|
|
|
1
|
-
# Diseño de Tools Internas
|
|
2
|
-
|
|
3
|
-
## Qué es una Tool
|
|
4
|
-
|
|
5
|
-
Una **Tool** es una utilidad reutilizable que automatiza tareas comunes. Diferente de MCP tools, estas son funciones/scripts internos del proyecto.
|
|
6
|
-
|
|
7
|
-
## Categorías
|
|
8
|
-
|
|
9
|
-
### 1. CLI Tools
|
|
10
|
-
|
|
11
|
-
Scripts ejecutables desde terminal:
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
scripts/
|
|
15
|
-
├── checks/ # Validaciones
|
|
16
|
-
│ ├── typecheck.mjs
|
|
17
|
-
│ └── lint.mjs
|
|
18
|
-
├── migration/ # Migraciones
|
|
19
|
-
│ └── run-migration.mjs
|
|
20
|
-
└── ai/ # AI-related
|
|
21
|
-
└── generate.mjs
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
### 2. Build Tools
|
|
25
|
-
|
|
26
|
-
Parte del proceso de build:
|
|
27
|
-
|
|
28
|
-
```typescript
|
|
29
|
-
// tools/build/
|
|
30
|
-
├── compile.ts
|
|
31
|
-
├── bundle.ts
|
|
32
|
-
└── optimize.ts
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### 3. Dev Tools
|
|
36
|
-
|
|
37
|
-
Para desarrollo local:
|
|
38
|
-
|
|
39
|
-
```typescript
|
|
40
|
-
// tools/dev/
|
|
41
|
-
├── mock-server.ts
|
|
42
|
-
├── seed-db.ts
|
|
43
|
-
└── test-utils.ts
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Estructura de una CLI Tool
|
|
47
|
-
|
|
48
|
-
```typescript
|
|
49
|
-
#!/usr/bin/env node
|
|
50
|
-
// scripts/my-tool.mjs
|
|
51
|
-
|
|
52
|
-
import { parseArgs } from 'node:util'
|
|
53
|
-
|
|
54
|
-
// 1. Parse arguments
|
|
55
|
-
const { values, positionals } = parseArgs({
|
|
56
|
-
options: {
|
|
57
|
-
verbose: { type: 'boolean', short: 'v', default: false },
|
|
58
|
-
output: { type: 'string', short: 'o' }
|
|
59
|
-
},
|
|
60
|
-
allowPositionals: true
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
// 2. Validate input
|
|
64
|
-
if (positionals.length === 0) {
|
|
65
|
-
console.error('Usage: my-tool <input> [--verbose] [--output path]')
|
|
66
|
-
process.exit(1)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// 3. Execute
|
|
70
|
-
async function main() {
|
|
71
|
-
try {
|
|
72
|
-
const result = await doWork(positionals[0], values)
|
|
73
|
-
console.log('Done:', result)
|
|
74
|
-
process.exit(0)
|
|
75
|
-
} catch (error) {
|
|
76
|
-
console.error('Error:', error.message)
|
|
77
|
-
process.exit(1)
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
main()
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## Patrones Recomendados
|
|
85
|
-
|
|
86
|
-
### Patrón: Reporter
|
|
87
|
-
|
|
88
|
-
Para tools que analizan y reportan:
|
|
89
|
-
|
|
90
|
-
```typescript
|
|
91
|
-
interface ReportResult {
|
|
92
|
-
passed: boolean
|
|
93
|
-
items: ReportItem[]
|
|
94
|
-
summary: string
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
async function analyze(path: string): Promise<ReportResult> {
|
|
98
|
-
const items = await scanFiles(path)
|
|
99
|
-
const issues = items.filter(i => !i.valid)
|
|
100
|
-
|
|
101
|
-
return {
|
|
102
|
-
passed: issues.length === 0,
|
|
103
|
-
items: issues,
|
|
104
|
-
summary: `Found ${issues.length} issues in ${items.length} files`
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### Patrón: Transformer
|
|
110
|
-
|
|
111
|
-
Para tools que transforman archivos:
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
interface TransformOptions {
|
|
115
|
-
input: string
|
|
116
|
-
output: string
|
|
117
|
-
dryRun?: boolean
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
async function transform(options: TransformOptions): Promise<void> {
|
|
121
|
-
const content = await readFile(options.input, 'utf-8')
|
|
122
|
-
const transformed = applyTransformations(content)
|
|
123
|
-
|
|
124
|
-
if (options.dryRun) {
|
|
125
|
-
console.log('Would write to:', options.output)
|
|
126
|
-
console.log(transformed)
|
|
127
|
-
return
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
await writeFile(options.output, transformed)
|
|
131
|
-
}
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
### Patrón: Batch Processor
|
|
135
|
-
|
|
136
|
-
Para operaciones sobre múltiples archivos:
|
|
137
|
-
|
|
138
|
-
```typescript
|
|
139
|
-
async function processBatch(
|
|
140
|
-
files: string[],
|
|
141
|
-
processor: (file: string) => Promise<void>
|
|
142
|
-
): Promise<BatchResult> {
|
|
143
|
-
const results = await Promise.allSettled(
|
|
144
|
-
files.map(processor)
|
|
145
|
-
)
|
|
146
|
-
|
|
147
|
-
return {
|
|
148
|
-
total: files.length,
|
|
149
|
-
succeeded: results.filter(r => r.status === 'fulfilled').length,
|
|
150
|
-
failed: results.filter(r => r.status === 'rejected').length
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
## Configuración
|
|
156
|
-
|
|
157
|
-
### En package.json
|
|
158
|
-
|
|
159
|
-
```json
|
|
160
|
-
{
|
|
161
|
-
"scripts": {
|
|
162
|
-
"tool:analyze": "node scripts/analyze.mjs",
|
|
163
|
-
"tool:migrate": "node scripts/migrate.mjs",
|
|
164
|
-
"tool:generate": "node scripts/generate.mjs"
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
### Con argumentos
|
|
170
|
-
|
|
171
|
-
```json
|
|
172
|
-
{
|
|
173
|
-
"scripts": {
|
|
174
|
-
"lint:all": "npm run lint -- --fix",
|
|
175
|
-
"check:verbose": "npm run check -- --verbose"
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## Logging
|
|
181
|
-
|
|
182
|
-
```typescript
|
|
183
|
-
// Usar chalk para colores
|
|
184
|
-
import chalk from 'chalk'
|
|
185
|
-
|
|
186
|
-
function log(level: 'info' | 'warn' | 'error', msg: string) {
|
|
187
|
-
const prefix = {
|
|
188
|
-
info: chalk.blue('ℹ'),
|
|
189
|
-
warn: chalk.yellow('⚠'),
|
|
190
|
-
error: chalk.red('✖')
|
|
191
|
-
}
|
|
192
|
-
console.error(`${prefix[level]} ${msg}`)
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Usar stderr para logs, stdout para output
|
|
196
|
-
console.error('[INFO] Processing...') // logs
|
|
197
|
-
console.log(JSON.stringify(result)) // output (puede ser piped)
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
## Testing Tools
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
import { describe, it, expect } from 'vitest'
|
|
204
|
-
import { execSync } from 'child_process'
|
|
205
|
-
|
|
206
|
-
describe('my-tool', () => {
|
|
207
|
-
it('should process valid input', () => {
|
|
208
|
-
const result = execSync('node scripts/my-tool.mjs input.txt')
|
|
209
|
-
expect(result.toString()).toContain('Done')
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
it('should fail on invalid input', () => {
|
|
213
|
-
expect(() => {
|
|
214
|
-
execSync('node scripts/my-tool.mjs')
|
|
215
|
-
}).toThrow()
|
|
216
|
-
})
|
|
217
|
-
})
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
## Anti-Patterns
|
|
221
|
-
|
|
222
|
-
### NO: Hardcoded paths
|
|
223
|
-
|
|
224
|
-
```typescript
|
|
225
|
-
// MAL
|
|
226
|
-
const config = await readFile('/Users/carlos/project/config.json')
|
|
227
|
-
|
|
228
|
-
// BIEN
|
|
229
|
-
const config = await readFile(path.join(process.cwd(), 'config.json'))
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### NO: Silent failures
|
|
233
|
-
|
|
234
|
-
```typescript
|
|
235
|
-
// MAL
|
|
236
|
-
try {
|
|
237
|
-
await doWork()
|
|
238
|
-
} catch {
|
|
239
|
-
// silencio
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// BIEN
|
|
243
|
-
try {
|
|
244
|
-
await doWork()
|
|
245
|
-
} catch (error) {
|
|
246
|
-
console.error('Failed:', error.message)
|
|
247
|
-
process.exit(1)
|
|
248
|
-
}
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
### NO: Sin validación de input
|
|
252
|
-
|
|
253
|
-
```typescript
|
|
254
|
-
// MAL
|
|
255
|
-
async function main() {
|
|
256
|
-
await processFile(process.argv[2])
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// BIEN
|
|
260
|
-
async function main() {
|
|
261
|
-
const file = process.argv[2]
|
|
262
|
-
if (!file) {
|
|
263
|
-
console.error('Usage: tool <file>')
|
|
264
|
-
process.exit(1)
|
|
265
|
-
}
|
|
266
|
-
if (!existsSync(file)) {
|
|
267
|
-
console.error(`File not found: ${file}`)
|
|
268
|
-
process.exit(1)
|
|
269
|
-
}
|
|
270
|
-
await processFile(file)
|
|
271
|
-
}
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
## Documentación
|
|
275
|
-
|
|
276
|
-
Cada tool debe tener:
|
|
277
|
-
|
|
278
|
-
1. **JSDoc header** con descripción y ejemplos
|
|
279
|
-
2. **--help** flag que explica uso
|
|
280
|
-
3. **README** si es compleja
|
|
281
|
-
|
|
282
|
-
```typescript
|
|
283
|
-
/**
|
|
284
|
-
* @file Analyze TypeScript files for common issues
|
|
285
|
-
* @example
|
|
286
|
-
* ```bash
|
|
287
|
-
* # Analyze single file
|
|
288
|
-
* npm run tool:analyze src/index.ts
|
|
289
|
-
*
|
|
290
|
-
* # Analyze directory
|
|
291
|
-
* npm run tool:analyze src/ --recursive
|
|
292
|
-
*
|
|
293
|
-
* # Output JSON
|
|
294
|
-
* npm run tool:analyze src/ --format json > report.json
|
|
295
|
-
* ```
|
|
296
|
-
*/
|
|
297
|
-
```
|
|
1
|
+
# Diseño de Tools Internas
|
|
2
|
+
|
|
3
|
+
## Qué es una Tool
|
|
4
|
+
|
|
5
|
+
Una **Tool** es una utilidad reutilizable que automatiza tareas comunes. Diferente de MCP tools, estas son funciones/scripts internos del proyecto.
|
|
6
|
+
|
|
7
|
+
## Categorías
|
|
8
|
+
|
|
9
|
+
### 1. CLI Tools
|
|
10
|
+
|
|
11
|
+
Scripts ejecutables desde terminal:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
scripts/
|
|
15
|
+
├── checks/ # Validaciones
|
|
16
|
+
│ ├── typecheck.mjs
|
|
17
|
+
│ └── lint.mjs
|
|
18
|
+
├── migration/ # Migraciones
|
|
19
|
+
│ └── run-migration.mjs
|
|
20
|
+
└── ai/ # AI-related
|
|
21
|
+
└── generate.mjs
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 2. Build Tools
|
|
25
|
+
|
|
26
|
+
Parte del proceso de build:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
// tools/build/
|
|
30
|
+
├── compile.ts
|
|
31
|
+
├── bundle.ts
|
|
32
|
+
└── optimize.ts
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 3. Dev Tools
|
|
36
|
+
|
|
37
|
+
Para desarrollo local:
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
// tools/dev/
|
|
41
|
+
├── mock-server.ts
|
|
42
|
+
├── seed-db.ts
|
|
43
|
+
└── test-utils.ts
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Estructura de una CLI Tool
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
#!/usr/bin/env node
|
|
50
|
+
// scripts/my-tool.mjs
|
|
51
|
+
|
|
52
|
+
import { parseArgs } from 'node:util'
|
|
53
|
+
|
|
54
|
+
// 1. Parse arguments
|
|
55
|
+
const { values, positionals } = parseArgs({
|
|
56
|
+
options: {
|
|
57
|
+
verbose: { type: 'boolean', short: 'v', default: false },
|
|
58
|
+
output: { type: 'string', short: 'o' }
|
|
59
|
+
},
|
|
60
|
+
allowPositionals: true
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
// 2. Validate input
|
|
64
|
+
if (positionals.length === 0) {
|
|
65
|
+
console.error('Usage: my-tool <input> [--verbose] [--output path]')
|
|
66
|
+
process.exit(1)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 3. Execute
|
|
70
|
+
async function main() {
|
|
71
|
+
try {
|
|
72
|
+
const result = await doWork(positionals[0], values)
|
|
73
|
+
console.log('Done:', result)
|
|
74
|
+
process.exit(0)
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error('Error:', error.message)
|
|
77
|
+
process.exit(1)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
main()
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Patrones Recomendados
|
|
85
|
+
|
|
86
|
+
### Patrón: Reporter
|
|
87
|
+
|
|
88
|
+
Para tools que analizan y reportan:
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
interface ReportResult {
|
|
92
|
+
passed: boolean
|
|
93
|
+
items: ReportItem[]
|
|
94
|
+
summary: string
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function analyze(path: string): Promise<ReportResult> {
|
|
98
|
+
const items = await scanFiles(path)
|
|
99
|
+
const issues = items.filter(i => !i.valid)
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
passed: issues.length === 0,
|
|
103
|
+
items: issues,
|
|
104
|
+
summary: `Found ${issues.length} issues in ${items.length} files`
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Patrón: Transformer
|
|
110
|
+
|
|
111
|
+
Para tools que transforman archivos:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
interface TransformOptions {
|
|
115
|
+
input: string
|
|
116
|
+
output: string
|
|
117
|
+
dryRun?: boolean
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async function transform(options: TransformOptions): Promise<void> {
|
|
121
|
+
const content = await readFile(options.input, 'utf-8')
|
|
122
|
+
const transformed = applyTransformations(content)
|
|
123
|
+
|
|
124
|
+
if (options.dryRun) {
|
|
125
|
+
console.log('Would write to:', options.output)
|
|
126
|
+
console.log(transformed)
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
await writeFile(options.output, transformed)
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Patrón: Batch Processor
|
|
135
|
+
|
|
136
|
+
Para operaciones sobre múltiples archivos:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
async function processBatch(
|
|
140
|
+
files: string[],
|
|
141
|
+
processor: (file: string) => Promise<void>
|
|
142
|
+
): Promise<BatchResult> {
|
|
143
|
+
const results = await Promise.allSettled(
|
|
144
|
+
files.map(processor)
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
total: files.length,
|
|
149
|
+
succeeded: results.filter(r => r.status === 'fulfilled').length,
|
|
150
|
+
failed: results.filter(r => r.status === 'rejected').length
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Configuración
|
|
156
|
+
|
|
157
|
+
### En package.json
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"scripts": {
|
|
162
|
+
"tool:analyze": "node scripts/analyze.mjs",
|
|
163
|
+
"tool:migrate": "node scripts/migrate.mjs",
|
|
164
|
+
"tool:generate": "node scripts/generate.mjs"
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Con argumentos
|
|
170
|
+
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"scripts": {
|
|
174
|
+
"lint:all": "npm run lint -- --fix",
|
|
175
|
+
"check:verbose": "npm run check -- --verbose"
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Logging
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
// Usar chalk para colores
|
|
184
|
+
import chalk from 'chalk'
|
|
185
|
+
|
|
186
|
+
function log(level: 'info' | 'warn' | 'error', msg: string) {
|
|
187
|
+
const prefix = {
|
|
188
|
+
info: chalk.blue('ℹ'),
|
|
189
|
+
warn: chalk.yellow('⚠'),
|
|
190
|
+
error: chalk.red('✖')
|
|
191
|
+
}
|
|
192
|
+
console.error(`${prefix[level]} ${msg}`)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Usar stderr para logs, stdout para output
|
|
196
|
+
console.error('[INFO] Processing...') // logs
|
|
197
|
+
console.log(JSON.stringify(result)) // output (puede ser piped)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Testing Tools
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { describe, it, expect } from 'vitest'
|
|
204
|
+
import { execSync } from 'child_process'
|
|
205
|
+
|
|
206
|
+
describe('my-tool', () => {
|
|
207
|
+
it('should process valid input', () => {
|
|
208
|
+
const result = execSync('node scripts/my-tool.mjs input.txt')
|
|
209
|
+
expect(result.toString()).toContain('Done')
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
it('should fail on invalid input', () => {
|
|
213
|
+
expect(() => {
|
|
214
|
+
execSync('node scripts/my-tool.mjs')
|
|
215
|
+
}).toThrow()
|
|
216
|
+
})
|
|
217
|
+
})
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Anti-Patterns
|
|
221
|
+
|
|
222
|
+
### NO: Hardcoded paths
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
// MAL
|
|
226
|
+
const config = await readFile('/Users/carlos/project/config.json')
|
|
227
|
+
|
|
228
|
+
// BIEN
|
|
229
|
+
const config = await readFile(path.join(process.cwd(), 'config.json'))
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### NO: Silent failures
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
// MAL
|
|
236
|
+
try {
|
|
237
|
+
await doWork()
|
|
238
|
+
} catch {
|
|
239
|
+
// silencio
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// BIEN
|
|
243
|
+
try {
|
|
244
|
+
await doWork()
|
|
245
|
+
} catch (error) {
|
|
246
|
+
console.error('Failed:', error.message)
|
|
247
|
+
process.exit(1)
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### NO: Sin validación de input
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
// MAL
|
|
255
|
+
async function main() {
|
|
256
|
+
await processFile(process.argv[2])
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// BIEN
|
|
260
|
+
async function main() {
|
|
261
|
+
const file = process.argv[2]
|
|
262
|
+
if (!file) {
|
|
263
|
+
console.error('Usage: tool <file>')
|
|
264
|
+
process.exit(1)
|
|
265
|
+
}
|
|
266
|
+
if (!existsSync(file)) {
|
|
267
|
+
console.error(`File not found: ${file}`)
|
|
268
|
+
process.exit(1)
|
|
269
|
+
}
|
|
270
|
+
await processFile(file)
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Documentación
|
|
275
|
+
|
|
276
|
+
Cada tool debe tener:
|
|
277
|
+
|
|
278
|
+
1. **JSDoc header** con descripción y ejemplos
|
|
279
|
+
2. **--help** flag que explica uso
|
|
280
|
+
3. **README** si es compleja
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
/**
|
|
284
|
+
* @file Analyze TypeScript files for common issues
|
|
285
|
+
* @example
|
|
286
|
+
* ```bash
|
|
287
|
+
* # Analyze single file
|
|
288
|
+
* npm run tool:analyze src/index.ts
|
|
289
|
+
*
|
|
290
|
+
* # Analyze directory
|
|
291
|
+
* npm run tool:analyze src/ --recursive
|
|
292
|
+
*
|
|
293
|
+
* # Output JSON
|
|
294
|
+
* npm run tool:analyze src/ --format json > report.json
|
|
295
|
+
* ```
|
|
296
|
+
*/
|
|
297
|
+
```
|