@haposoft/cafekit 0.13.4 โ†’ 0.14.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 (119) hide show
  1. package/README.md +2 -23
  2. package/bin/lib/i18n.js +2 -2
  3. package/bin/lib/manifest.js +15 -0
  4. package/bin/lib/opencode-install.js +0 -14
  5. package/bin/phases/claude-runtime.js +4 -1
  6. package/bin/phases/claude-settings.js +38 -7
  7. package/bin/phases/root-config.js +5 -24
  8. package/package.json +1 -1
  9. package/src/claude/agents/ui-ux-designer.md +4 -4
  10. package/src/claude/gitignore +4 -11
  11. package/src/claude/hooks/__tests__/privacy-block.test.js +79 -0
  12. package/src/claude/hooks/__tests__/session-writeenv.test.js +68 -0
  13. package/src/claude/hooks/__tests__/spec-gate.test.js +270 -0
  14. package/src/claude/hooks/privacy-block.cjs +22 -2
  15. package/src/claude/hooks/session.cjs +5 -1
  16. package/src/claude/hooks/spec-gate.cjs +173 -0
  17. package/src/claude/hooks/spec-state.cjs +10 -17
  18. package/src/claude/hooks/task-scaffold-guard.cjs +4 -2
  19. package/src/claude/migration-manifest.json +5 -5
  20. package/src/claude/rules/skill-domain-routing.md +2 -3
  21. package/src/claude/rules/skill-workflow-routing.md +2 -11
  22. package/src/claude/rules/state-sync.md +4 -0
  23. package/src/claude/runtime.json +4 -0
  24. package/src/claude/scripts/validate-docs.cjs +4 -7
  25. package/src/claude/scripts/validate-spec-output.cjs +29 -9
  26. package/src/claude/settings/settings.json +4 -0
  27. package/src/claude/skills/ai-multimodal/.env.example +11 -13
  28. package/src/claude/skills/ai-multimodal/SKILL.md +1 -1
  29. package/src/claude/skills/ai-multimodal/references/audio-processing.md +25 -27
  30. package/src/claude/skills/ai-multimodal/references/video-analysis.md +23 -27
  31. package/src/claude/skills/ai-multimodal/references/vision-understanding.md +26 -26
  32. package/src/claude/skills/ai-multimodal/scripts/check_setup.py +1 -1
  33. package/src/claude/skills/ai-multimodal/scripts/gemini_batch_process.py +7 -9
  34. package/src/claude/skills/brainstorm/SKILL.md +1 -2
  35. package/src/claude/skills/docx/SKILL.md +1 -1
  36. package/src/claude/skills/frontend-design/SKILL.md +1 -1
  37. package/src/claude/skills/frontend-design/references/ai-multimodal-overview.md +4 -4
  38. package/src/claude/skills/frontend-design/references/analysis-techniques.md +3 -3
  39. package/src/claude/skills/frontend-design/references/asset-generation.md +2 -2
  40. package/src/claude/skills/frontend-design/references/design-extraction-overview.md +4 -4
  41. package/src/claude/skills/frontend-design/references/extraction-best-practices.md +3 -3
  42. package/src/claude/skills/frontend-design/references/technical-accessibility.md +1 -1
  43. package/src/claude/skills/frontend-design/references/technical-optimization.md +1 -1
  44. package/src/claude/skills/frontend-design/references/technical-overview.md +2 -2
  45. package/src/claude/skills/frontend-design/references/technical-workflows.md +6 -6
  46. package/src/claude/skills/frontend-design/references/visual-analysis-overview.md +3 -3
  47. package/src/claude/skills/inspect/SKILL.md +3 -3
  48. package/src/claude/skills/inspect/references/external-gemini-inspection.md +9 -9
  49. package/src/claude/skills/pdf/SKILL.md +1 -1
  50. package/src/claude/skills/pptx/SKILL.md +1 -1
  51. package/src/claude/skills/specs/SKILL.md +1 -1
  52. package/src/claude/skills/xlsx/SKILL.md +1 -1
  53. package/src/opencode/AGENTS.md +1 -2
  54. package/src/opencode/plugins/session.ts +2 -2
  55. package/src/opencode/plugins/spec-state.ts +244 -0
  56. package/src/opencode/plugins/task-scaffold-guard.ts +161 -0
  57. package/src/claude/scripts/browser-tool.cjs +0 -138
  58. package/src/claude/skills/delegate/SKILL.md +0 -124
  59. package/src/claude/skills/delegate/references/codex-delegation.md +0 -71
  60. package/src/claude/skills/delegate/references/grok-delegation.md +0 -84
  61. package/src/claude/skills/generate-graph/LICENSE +0 -21
  62. package/src/claude/skills/generate-graph/README.md +0 -523
  63. package/src/claude/skills/generate-graph/SKILL.md +0 -429
  64. package/src/claude/skills/generate-graph/agentloop-core.svg +0 -101
  65. package/src/claude/skills/generate-graph/agents/openai.yaml +0 -4
  66. package/src/claude/skills/generate-graph/assets/samples/sample-style1-flat.png +0 -0
  67. package/src/claude/skills/generate-graph/assets/samples/sample-style2-dark.png +0 -0
  68. package/src/claude/skills/generate-graph/assets/samples/sample-style3-blueprint.png +0 -0
  69. package/src/claude/skills/generate-graph/assets/samples/sample-style4-notion.png +0 -0
  70. package/src/claude/skills/generate-graph/assets/samples/sample-style5-glass.png +0 -0
  71. package/src/claude/skills/generate-graph/assets/samples/sample-style6-claude.png +0 -0
  72. package/src/claude/skills/generate-graph/assets/samples/sample-style7-openai.png +0 -0
  73. package/src/claude/skills/generate-graph/fixtures/agent-memory-types-style4.json +0 -181
  74. package/src/claude/skills/generate-graph/fixtures/api-flow-style7.json +0 -40
  75. package/src/claude/skills/generate-graph/fixtures/mem0-style1.json +0 -297
  76. package/src/claude/skills/generate-graph/fixtures/microservices-style3.json +0 -64
  77. package/src/claude/skills/generate-graph/fixtures/multi-agent-style5.json +0 -45
  78. package/src/claude/skills/generate-graph/fixtures/system-architecture-style6.json +0 -48
  79. package/src/claude/skills/generate-graph/fixtures/tool-call-style2.json +0 -182
  80. package/src/claude/skills/generate-graph/package.json +0 -42
  81. package/src/claude/skills/generate-graph/references/icons.md +0 -281
  82. package/src/claude/skills/generate-graph/references/style-1-flat-icon.md +0 -108
  83. package/src/claude/skills/generate-graph/references/style-2-dark-terminal.md +0 -107
  84. package/src/claude/skills/generate-graph/references/style-3-blueprint.md +0 -113
  85. package/src/claude/skills/generate-graph/references/style-4-notion-clean.md +0 -94
  86. package/src/claude/skills/generate-graph/references/style-5-glassmorphism.md +0 -125
  87. package/src/claude/skills/generate-graph/references/style-6-claude-official.md +0 -209
  88. package/src/claude/skills/generate-graph/references/style-7-openai.md +0 -215
  89. package/src/claude/skills/generate-graph/references/style-diagram-matrix.md +0 -135
  90. package/src/claude/skills/generate-graph/references/svg-layout-best-practices.md +0 -100
  91. package/src/claude/skills/generate-graph/scripts/generate-diagram.sh +0 -157
  92. package/src/claude/skills/generate-graph/scripts/generate-from-template.py +0 -1556
  93. package/src/claude/skills/generate-graph/scripts/test-all-styles.sh +0 -135
  94. package/src/claude/skills/generate-graph/scripts/validate-svg.sh +0 -292
  95. package/src/claude/skills/generate-graph/templates/agent-architecture.svg +0 -28
  96. package/src/claude/skills/generate-graph/templates/architecture.svg +0 -23
  97. package/src/claude/skills/generate-graph/templates/comparison-matrix.svg +0 -14
  98. package/src/claude/skills/generate-graph/templates/data-flow.svg +0 -28
  99. package/src/claude/skills/generate-graph/templates/er-diagram.svg +0 -21
  100. package/src/claude/skills/generate-graph/templates/flowchart.svg +0 -21
  101. package/src/claude/skills/generate-graph/templates/sequence.svg +0 -20
  102. package/src/claude/skills/generate-graph/templates/state-machine.svg +0 -20
  103. package/src/claude/skills/generate-graph/templates/timeline.svg +0 -19
  104. package/src/claude/skills/generate-graph/templates/use-case.svg +0 -21
  105. package/src/claude/skills/impact-analysis/SKILL.md +0 -276
  106. package/src/claude/skills/impact-analysis/references/change-detection.md +0 -270
  107. package/src/claude/skills/impact-analysis/references/dependency-scouting.md +0 -338
  108. package/src/claude/skills/impact-analysis/references/edge-case-identification.md +0 -439
  109. package/src/claude/skills/impact-analysis/references/industry-techniques.md +0 -695
  110. package/src/claude/skills/impact-analysis/references/practical-techniques-guide.md +0 -753
  111. package/src/claude/skills/impact-analysis/references/project-detection.md +0 -704
  112. package/src/claude/skills/impact-analysis/references/react-native-customization.md +0 -508
  113. package/src/claude/skills/impact-analysis/references/report-template.md +0 -604
  114. package/src/claude/skills/impact-analysis/references/test-scenario-generation.md +0 -459
  115. package/src/claude/skills/impact-analysis/scripts/README.md +0 -476
  116. package/src/claude/skills/impact-analysis/scripts/ast-analyze.js +0 -403
  117. package/src/claude/skills/impact-analysis/scripts/calculate-risk.js +0 -475
  118. package/src/claude/skills/impact-analysis/scripts/find-dependencies.sh +0 -202
  119. package/src/claude/skills/impact-analysis/scripts/run-analysis.sh +0 -312
@@ -1,475 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Risk Calculation Script
5
- * ฤรกnh giรก mแปฉc ฤ‘แป™ risk cแปงa code changes
6
- *
7
- * Usage:
8
- * node calculate-risk.js
9
- * node calculate-risk.js --files "file1.ts,file2.ts"
10
- * node calculate-risk.js --json
11
- */
12
-
13
- const { execSync } = require('child_process');
14
- const fs = require('fs');
15
- const path = require('path');
16
-
17
- // Risk scoring configuration
18
- const RISK_CONFIG = {
19
- // File type weights
20
- fileTypes: {
21
- database: 5, // Schema, migrations
22
- api: 3, // API endpoints
23
- auth: 5, // Authentication
24
- payment: 5, // Payment processing
25
- security: 5, // Security-related
26
- config: 2, // Configuration
27
- frontend: 1, // UI components
28
- test: 0 // Test files
29
- },
30
-
31
- // Change size weights
32
- changeSize: {
33
- huge: { threshold: 500, weight: 3 },
34
- large: { threshold: 200, weight: 2 },
35
- medium: { threshold: 50, weight: 1 },
36
- small: { threshold: 0, weight: 0 }
37
- },
38
-
39
- // Dependency weights
40
- dependencies: {
41
- many: { threshold: 20, weight: 3 },
42
- some: { threshold: 10, weight: 2 },
43
- few: { threshold: 5, weight: 1 },
44
- none: { threshold: 0, weight: 0 }
45
- },
46
-
47
- // Risk levels
48
- levels: {
49
- critical: { threshold: 15, label: 'CRITICAL', emoji: 'โš ๏ธโš ๏ธโš ๏ธ' },
50
- high: { threshold: 10, label: 'HIGH', emoji: 'โš ๏ธโš ๏ธ' },
51
- medium: { threshold: 5, label: 'MEDIUM', emoji: 'โš ๏ธ' },
52
- low: { threshold: 0, label: 'LOW', emoji: 'โœ…' }
53
- }
54
- };
55
-
56
- function getChangedFiles(fileList) {
57
- if (fileList) {
58
- return fileList.split(',').map(f => f.trim());
59
- }
60
-
61
- try {
62
- const output = execSync('git diff HEAD --name-only', { encoding: 'utf-8' });
63
- return output.trim().split('\n').filter(f => f);
64
- } catch (e) {
65
- console.error('โŒ Error getting changed files:', e.message);
66
- return [];
67
- }
68
- }
69
-
70
- function getChangeStats(files) {
71
- const stats = {
72
- filesChanged: files.length,
73
- linesAdded: 0,
74
- linesRemoved: 0,
75
- totalLines: 0
76
- };
77
-
78
- try {
79
- const output = execSync('git diff HEAD --numstat', { encoding: 'utf-8' });
80
- const lines = output.trim().split('\n');
81
-
82
- lines.forEach(line => {
83
- const [added, removed] = line.split('\t').map(n => parseInt(n) || 0);
84
- stats.linesAdded += added;
85
- stats.linesRemoved += removed;
86
- });
87
-
88
- stats.totalLines = stats.linesAdded + stats.linesRemoved;
89
- } catch (e) {
90
- // Ignore errors
91
- }
92
-
93
- return stats;
94
- }
95
-
96
- function classifyFiles(files) {
97
- const classified = {
98
- database: [],
99
- api: [],
100
- auth: [],
101
- payment: [],
102
- security: [],
103
- config: [],
104
- frontend: [],
105
- test: [],
106
- other: []
107
- };
108
-
109
- files.forEach(file => {
110
- const lower = file.toLowerCase();
111
-
112
- if (lower.includes('test.') || lower.includes('spec.')) {
113
- classified.test.push(file);
114
- } else if (lower.includes('schema') || lower.includes('migration') || lower.includes('.sql')) {
115
- classified.database.push(file);
116
- } else if (lower.includes('/api/') || lower.includes('route') || lower.includes('endpoint')) {
117
- classified.api.push(file);
118
- } else if (lower.includes('auth') || lower.includes('login') || lower.includes('session')) {
119
- classified.auth.push(file);
120
- } else if (lower.includes('payment') || lower.includes('checkout') || lower.includes('stripe')) {
121
- classified.payment.push(file);
122
- } else if (lower.includes('security') || lower.includes('crypto') || lower.includes('encrypt')) {
123
- classified.security.push(file);
124
- } else if (lower.includes('config') || lower.includes('.env') || lower.includes('package.json')) {
125
- classified.config.push(file);
126
- } else if (lower.includes('component') || lower.includes('screen') || lower.includes('page')) {
127
- classified.frontend.push(file);
128
- } else {
129
- classified.other.push(file);
130
- }
131
- });
132
-
133
- return classified;
134
- }
135
-
136
- function countDependencies(files) {
137
- let totalDeps = 0;
138
-
139
- files.forEach(file => {
140
- if (!fs.existsSync(file)) return;
141
-
142
- try {
143
- const basename = path.basename(file, path.extname(file));
144
- const srcDir = 'src';
145
-
146
- if (!fs.existsSync(srcDir)) return;
147
-
148
- // Count imports of this file
149
- const grepCmd = `grep -r "from.*${basename}" ${srcDir} --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" 2>/dev/null | wc -l`;
150
- const count = parseInt(execSync(grepCmd, { encoding: 'utf-8' }).trim()) || 0;
151
- totalDeps += count;
152
- } catch (e) {
153
- // Ignore errors
154
- }
155
- });
156
-
157
- return totalDeps;
158
- }
159
-
160
- function detectBreakingChanges(files) {
161
- const breaking = [];
162
-
163
- files.forEach(file => {
164
- if (!fs.existsSync(file)) return;
165
-
166
- try {
167
- // Check git diff for breaking patterns
168
- const diffCmd = `git diff HEAD -- "${file}"`;
169
- const diff = execSync(diffCmd, { encoding: 'utf-8' });
170
-
171
- // Detect function signature changes
172
- if (diff.match(/^-.*function.*\(/m) && diff.match(/^\+.*function.*\(/m)) {
173
- breaking.push({
174
- file,
175
- type: 'function_signature',
176
- description: 'Function signature may have changed'
177
- });
178
- }
179
-
180
- // Detect interface changes
181
- if (diff.match(/^-.*interface/m) || diff.match(/^\+.*interface/m)) {
182
- breaking.push({
183
- file,
184
- type: 'interface_change',
185
- description: 'Interface definition changed'
186
- });
187
- }
188
-
189
- // Detect API endpoint changes
190
- if (diff.match(/^-.*\.(get|post|put|delete|patch)\(/m)) {
191
- breaking.push({
192
- file,
193
- type: 'api_endpoint',
194
- description: 'API endpoint may have changed'
195
- });
196
- }
197
- } catch (e) {
198
- // Ignore errors
199
- }
200
- });
201
-
202
- return breaking;
203
- }
204
-
205
- function calculateRiskScore(data) {
206
- let score = 0;
207
- const breakdown = [];
208
-
209
- // File type risk
210
- Object.entries(data.classified).forEach(([type, files]) => {
211
- if (files.length > 0 && RISK_CONFIG.fileTypes[type]) {
212
- const weight = RISK_CONFIG.fileTypes[type];
213
- const points = weight * Math.min(files.length, 3); // Cap at 3x
214
- score += points;
215
- breakdown.push({
216
- factor: `${type} files`,
217
- weight,
218
- count: files.length,
219
- points,
220
- description: `${files.length} ${type} file(s) changed`
221
- });
222
- }
223
- });
224
-
225
- // Change size risk
226
- const totalLines = data.stats.totalLines;
227
- for (const [size, config] of Object.entries(RISK_CONFIG.changeSize)) {
228
- if (totalLines >= config.threshold) {
229
- score += config.weight;
230
- breakdown.push({
231
- factor: 'change size',
232
- weight: config.weight,
233
- count: totalLines,
234
- points: config.weight,
235
- description: `${totalLines} lines changed (${size})`
236
- });
237
- break;
238
- }
239
- }
240
-
241
- // Dependency risk
242
- const depCount = data.dependencies;
243
- for (const [level, config] of Object.entries(RISK_CONFIG.dependencies)) {
244
- if (depCount >= config.threshold) {
245
- score += config.weight;
246
- breakdown.push({
247
- factor: 'dependencies',
248
- weight: config.weight,
249
- count: depCount,
250
- points: config.weight,
251
- description: `${depCount} files depend on changes (${level})`
252
- });
253
- break;
254
- }
255
- }
256
-
257
- // Breaking changes risk
258
- if (data.breakingChanges.length > 0) {
259
- const points = Math.min(data.breakingChanges.length * 2, 5);
260
- score += points;
261
- breakdown.push({
262
- factor: 'breaking changes',
263
- weight: 2,
264
- count: data.breakingChanges.length,
265
- points,
266
- description: `${data.breakingChanges.length} potential breaking change(s)`
267
- });
268
- }
269
-
270
- // Determine risk level
271
- let level = RISK_CONFIG.levels.low;
272
- for (const [name, config] of Object.entries(RISK_CONFIG.levels)) {
273
- if (score >= config.threshold) {
274
- level = config;
275
- }
276
- }
277
-
278
- return {
279
- score,
280
- maxScore: 25,
281
- level: level.label,
282
- emoji: level.emoji,
283
- breakdown
284
- };
285
- }
286
-
287
- function generateRecommendations(data, risk) {
288
- const recommendations = [];
289
-
290
- // High risk recommendations
291
- if (risk.level === 'CRITICAL' || risk.level === 'HIGH') {
292
- recommendations.push({
293
- priority: 'CRITICAL',
294
- action: 'Extensive testing required',
295
- description: 'Run full test suite including integration and E2E tests'
296
- });
297
-
298
- recommendations.push({
299
- priority: 'CRITICAL',
300
- action: 'Code review required',
301
- description: 'Get at least 2 senior developers to review changes'
302
- });
303
- }
304
-
305
- // Database changes
306
- if (data.classified.database.length > 0) {
307
- recommendations.push({
308
- priority: 'HIGH',
309
- action: 'Database migration plan',
310
- description: 'Create rollback script and test migration on staging'
311
- });
312
- }
313
-
314
- // API changes
315
- if (data.classified.api.length > 0) {
316
- recommendations.push({
317
- priority: 'HIGH',
318
- action: 'API documentation update',
319
- description: 'Update API docs and notify frontend team'
320
- });
321
- }
322
-
323
- // Auth changes
324
- if (data.classified.auth.length > 0) {
325
- recommendations.push({
326
- priority: 'CRITICAL',
327
- action: 'Security review',
328
- description: 'Review authentication flow and test all auth scenarios'
329
- });
330
- }
331
-
332
- // Payment changes
333
- if (data.classified.payment.length > 0) {
334
- recommendations.push({
335
- priority: 'CRITICAL',
336
- action: 'Payment testing',
337
- description: 'Test payment flow in sandbox environment'
338
- });
339
- }
340
-
341
- // Breaking changes
342
- if (data.breakingChanges.length > 0) {
343
- recommendations.push({
344
- priority: 'HIGH',
345
- action: 'Update all consumers',
346
- description: `Update ${data.dependencies} files that depend on changed code`
347
- });
348
- }
349
-
350
- // Many dependencies
351
- if (data.dependencies > 10) {
352
- recommendations.push({
353
- priority: 'MEDIUM',
354
- action: 'Regression testing',
355
- description: 'Test all affected features to prevent regression'
356
- });
357
- }
358
-
359
- return recommendations;
360
- }
361
-
362
- function printReport(data, risk, recommendations) {
363
- console.log('\n๐ŸŽฏ Risk Assessment Report\n');
364
- console.log('โ•'.repeat(60));
365
-
366
- // Risk score
367
- console.log(`\n๐Ÿ“Š Risk Score: ${risk.score}/${risk.maxScore}`);
368
- console.log(`๐ŸŽš๏ธ Risk Level: ${risk.emoji} ${risk.level}`);
369
-
370
- // Summary
371
- console.log(`\n๐Ÿ“‹ Summary:`);
372
- console.log(` Files changed: ${data.stats.filesChanged}`);
373
- console.log(` Lines changed: ${data.stats.totalLines} (+${data.stats.linesAdded}, -${data.stats.linesRemoved})`);
374
- console.log(` Dependencies: ${data.dependencies} files affected`);
375
- console.log(` Breaking changes: ${data.breakingChanges.length}`);
376
-
377
- // File classification
378
- console.log(`\n๐Ÿ“ File Classification:`);
379
- Object.entries(data.classified).forEach(([type, files]) => {
380
- if (files.length > 0) {
381
- const weight = RISK_CONFIG.fileTypes[type] || 0;
382
- const emoji = weight >= 5 ? '๐Ÿ”ด' : weight >= 3 ? '๐ŸŸก' : '๐ŸŸข';
383
- console.log(` ${emoji} ${type}: ${files.length} file(s)`);
384
- files.slice(0, 3).forEach(file => {
385
- console.log(` - ${file}`);
386
- });
387
- if (files.length > 3) {
388
- console.log(` ... and ${files.length - 3} more`);
389
- }
390
- }
391
- });
392
-
393
- // Risk breakdown
394
- console.log(`\nโš–๏ธ Risk Breakdown:`);
395
- risk.breakdown.forEach(item => {
396
- console.log(` โ€ข ${item.description}`);
397
- console.log(` Points: ${item.points} (weight: ${item.weight})`);
398
- });
399
-
400
- // Breaking changes
401
- if (data.breakingChanges.length > 0) {
402
- console.log(`\nโš ๏ธ Potential Breaking Changes:`);
403
- data.breakingChanges.forEach((change, i) => {
404
- console.log(` ${i + 1}. ${change.file}`);
405
- console.log(` Type: ${change.type}`);
406
- console.log(` ${change.description}`);
407
- });
408
- }
409
-
410
- // Recommendations
411
- console.log(`\n๐Ÿ’ก Recommendations:`);
412
- recommendations.forEach((rec, i) => {
413
- const emoji = rec.priority === 'CRITICAL' ? '๐Ÿ”ด' : rec.priority === 'HIGH' ? '๐ŸŸก' : '๐ŸŸข';
414
- console.log(` ${emoji} [${rec.priority}] ${rec.action}`);
415
- console.log(` ${rec.description}`);
416
- });
417
-
418
- console.log('\n' + 'โ•'.repeat(60));
419
- console.log('');
420
- }
421
-
422
- function printJSON(data, risk, recommendations) {
423
- const output = {
424
- risk,
425
- data,
426
- recommendations,
427
- timestamp: new Date().toISOString()
428
- };
429
- console.log(JSON.stringify(output, null, 2));
430
- }
431
-
432
- // Main
433
- const args = process.argv.slice(2);
434
- const fileList = args.includes('--files') ? args[args.indexOf('--files') + 1] : null;
435
- const jsonOutput = args.includes('--json');
436
-
437
- const files = getChangedFiles(fileList);
438
-
439
- if (files.length === 0) {
440
- console.error('โŒ No changed files found');
441
- console.error('Usage: node calculate-risk.js [--files "file1.ts,file2.ts"] [--json]');
442
- process.exit(1);
443
- }
444
-
445
- const stats = getChangeStats(files);
446
- const classified = classifyFiles(files);
447
- const dependencies = countDependencies(files);
448
- const breakingChanges = detectBreakingChanges(files);
449
-
450
- const data = {
451
- files,
452
- stats,
453
- classified,
454
- dependencies,
455
- breakingChanges
456
- };
457
-
458
- const risk = calculateRiskScore(data);
459
- const recommendations = generateRecommendations(data, risk);
460
-
461
- if (jsonOutput) {
462
- printJSON(data, risk, recommendations);
463
- } else {
464
- printReport(data, risk, recommendations);
465
- }
466
-
467
- // Export for programmatic use
468
- if (typeof module !== 'undefined' && module.exports) {
469
- module.exports = {
470
- calculateRiskScore,
471
- generateRecommendations,
472
- classifyFiles,
473
- getChangeStats
474
- };
475
- }
@@ -1,202 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Find Dependencies Script
4
- # Tรฌm tแบฅt cแบฃ files bแป‹ แบฃnh hฦฐแปŸng bแปŸi code changes
5
- #
6
- # Usage:
7
- # ./find-dependencies.sh <file-path>
8
- # ./find-dependencies.sh src/services/authService.ts
9
-
10
- set -e
11
-
12
- if [ $# -eq 0 ]; then
13
- echo "Usage: $0 <file-path>"
14
- echo "Example: $0 src/services/authService.ts"
15
- exit 1
16
- fi
17
-
18
- FILE_PATH="$1"
19
- FILE_NAME=$(basename "$FILE_PATH")
20
- FILE_BASE="${FILE_NAME%.*}"
21
- SRC_DIR="${SRC_DIR:-src}"
22
-
23
- echo "๐Ÿ” Finding dependencies for: $FILE_PATH"
24
- echo ""
25
-
26
- # 1. Find direct imports
27
- echo "๐Ÿ“ฆ Direct Imports:"
28
- echo "Files that import this module:"
29
- echo ""
30
-
31
- # TypeScript/JavaScript imports
32
- grep -r "from ['\"].*$FILE_BASE['\"]" "$SRC_DIR" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" 2>/dev/null | \
33
- grep -v "node_modules" | \
34
- grep -v ".test." | \
35
- grep -v ".spec." | \
36
- cut -d: -f1 | \
37
- sort -u | \
38
- while read -r file; do
39
- echo " - $file"
40
- done
41
-
42
- # Alternative import syntax
43
- grep -r "import.*from ['\"].*$FILE_BASE['\"]" "$SRC_DIR" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" 2>/dev/null | \
44
- grep -v "node_modules" | \
45
- grep -v ".test." | \
46
- grep -v ".spec." | \
47
- cut -d: -f1 | \
48
- sort -u | \
49
- while read -r file; do
50
- echo " - $file"
51
- done
52
-
53
- echo ""
54
-
55
- # 2. Find function/class usage
56
- echo "๐Ÿ”ง Function/Class Usage:"
57
- echo "Searching for common exports..."
58
- echo ""
59
-
60
- # Extract exported names from the file
61
- if [ -f "$FILE_PATH" ]; then
62
- # Find exported functions
63
- EXPORTS=$(grep -E "export (function|const|class|interface|type)" "$FILE_PATH" 2>/dev/null | \
64
- sed -E 's/export (function|const|class|interface|type) ([a-zA-Z0-9_]+).*/\2/' | \
65
- head -10)
66
-
67
- if [ -n "$EXPORTS" ]; then
68
- for export_name in $EXPORTS; do
69
- echo " Searching for: $export_name"
70
-
71
- # Find usage (excluding the source file itself)
72
- grep -r "\b$export_name\b" "$SRC_DIR" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" 2>/dev/null | \
73
- grep -v "node_modules" | \
74
- grep -v "$FILE_PATH" | \
75
- grep -v ".test." | \
76
- grep -v ".spec." | \
77
- cut -d: -f1 | \
78
- sort -u | \
79
- head -5 | \
80
- while read -r file; do
81
- echo " - $file"
82
- done
83
- done
84
- fi
85
- fi
86
-
87
- echo ""
88
-
89
- # 3. Find API endpoint usage (if this is an API file)
90
- if [[ "$FILE_PATH" == *"/api/"* ]] || [[ "$FILE_PATH" == *"routes"* ]]; then
91
- echo "๐ŸŒ API Endpoint Usage:"
92
- echo "Searching for API calls..."
93
- echo ""
94
-
95
- # Extract API endpoints from the file
96
- ENDPOINTS=$(grep -E "(get|post|put|delete|patch)\(['\"]" "$FILE_PATH" 2>/dev/null | \
97
- sed -E "s/.*['\"]([^'\"]+)['\"].*/\1/" | \
98
- head -5)
99
-
100
- if [ -n "$ENDPOINTS" ]; then
101
- for endpoint in $ENDPOINTS; do
102
- echo " Endpoint: $endpoint"
103
-
104
- # Find frontend calls to this endpoint
105
- grep -r "$endpoint" "$SRC_DIR" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" 2>/dev/null | \
106
- grep -v "node_modules" | \
107
- grep -v "$FILE_PATH" | \
108
- cut -d: -f1 | \
109
- sort -u | \
110
- head -5 | \
111
- while read -r file; do
112
- echo " - $file"
113
- done
114
- done
115
- fi
116
-
117
- echo ""
118
- fi
119
-
120
- # 4. Find component usage (if this is a React component)
121
- if [[ "$FILE_PATH" == *"components"* ]] || [[ "$FILE_PATH" == *".tsx" ]]; then
122
- echo "โš›๏ธ Component Usage:"
123
- echo "Searching for component references..."
124
- echo ""
125
-
126
- COMPONENT_NAME=$(basename "$FILE_PATH" .tsx)
127
- COMPONENT_NAME=$(basename "$COMPONENT_NAME" .jsx)
128
-
129
- # Find JSX usage
130
- grep -r "<$COMPONENT_NAME" "$SRC_DIR" --include="*.tsx" --include="*.jsx" 2>/dev/null | \
131
- grep -v "node_modules" | \
132
- grep -v "$FILE_PATH" | \
133
- cut -d: -f1 | \
134
- sort -u | \
135
- while read -r file; do
136
- echo " - $file"
137
- done
138
-
139
- echo ""
140
- fi
141
-
142
- # 5. Find test files
143
- echo "๐Ÿงช Related Tests:"
144
- echo "Test files for this module:"
145
- echo ""
146
-
147
- # Find test files with similar names
148
- find "$SRC_DIR" -type f \( -name "*$FILE_BASE*.test.*" -o -name "*$FILE_BASE*.spec.*" \) 2>/dev/null | \
149
- while read -r file; do
150
- echo " - $file"
151
- done
152
-
153
- # Find test files that import this module
154
- grep -r "from ['\"].*$FILE_BASE['\"]" "$SRC_DIR" --include="*.test.*" --include="*.spec.*" 2>/dev/null | \
155
- cut -d: -f1 | \
156
- sort -u | \
157
- while read -r file; do
158
- echo " - $file"
159
- done
160
-
161
- echo ""
162
-
163
- # 6. Summary
164
- echo "๐Ÿ“Š Summary:"
165
- echo ""
166
-
167
- IMPORT_COUNT=$(grep -r "from ['\"].*$FILE_BASE['\"]" "$SRC_DIR" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" 2>/dev/null | \
168
- grep -v "node_modules" | \
169
- grep -v ".test." | \
170
- grep -v ".spec." | \
171
- wc -l | tr -d ' ')
172
-
173
- TEST_COUNT=$(find "$SRC_DIR" -type f \( -name "*$FILE_BASE*.test.*" -o -name "*$FILE_BASE*.spec.*" \) 2>/dev/null | wc -l | tr -d ' ')
174
-
175
- echo " Direct imports: $IMPORT_COUNT"
176
- echo " Related tests: $TEST_COUNT"
177
- echo ""
178
-
179
- # 7. Recommendations
180
- echo "๐Ÿ’ก Recommendations:"
181
- echo ""
182
-
183
- if [ "$IMPORT_COUNT" -gt 10 ]; then
184
- echo " โš ๏ธ HIGH IMPACT: This file is imported by many files ($IMPORT_COUNT)"
185
- echo " โ†’ Test thoroughly before deploying"
186
- echo " โ†’ Consider backward compatibility"
187
- fi
188
-
189
- if [ "$TEST_COUNT" -eq 0 ]; then
190
- echo " โš ๏ธ NO TESTS: No test files found for this module"
191
- echo " โ†’ Add unit tests before deploying"
192
- fi
193
-
194
- if [[ "$FILE_PATH" == *"/api/"* ]]; then
195
- echo " โš ๏ธ API CHANGE: This is an API file"
196
- echo " โ†’ Check for breaking changes"
197
- echo " โ†’ Update API documentation"
198
- echo " โ†’ Test all API consumers"
199
- fi
200
-
201
- echo ""
202
- echo "โœ… Dependency analysis complete"