@entro314labs/ai-changelog-generator 3.0.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/CHANGELOG.md +801 -0
- package/LICENSE +21 -0
- package/README.md +393 -0
- package/ai-changelog-mcp.sh +93 -0
- package/ai-changelog.sh +103 -0
- package/bin/ai-changelog-dxt.js +35 -0
- package/bin/ai-changelog-mcp.js +34 -0
- package/bin/ai-changelog.js +18 -0
- package/package.json +135 -0
- package/src/ai-changelog-generator.js +258 -0
- package/src/application/orchestrators/changelog.orchestrator.js +730 -0
- package/src/application/services/application.service.js +301 -0
- package/src/cli.js +157 -0
- package/src/domains/ai/ai-analysis.service.js +486 -0
- package/src/domains/analysis/analysis.engine.js +445 -0
- package/src/domains/changelog/changelog.service.js +1761 -0
- package/src/domains/changelog/workspace-changelog.service.js +505 -0
- package/src/domains/git/git-repository.analyzer.js +588 -0
- package/src/domains/git/git.service.js +302 -0
- package/src/infrastructure/cli/cli.controller.js +517 -0
- package/src/infrastructure/config/configuration.manager.js +538 -0
- package/src/infrastructure/interactive/interactive-workflow.service.js +444 -0
- package/src/infrastructure/mcp/mcp-server.service.js +540 -0
- package/src/infrastructure/metrics/metrics.collector.js +362 -0
- package/src/infrastructure/providers/core/base-provider.js +184 -0
- package/src/infrastructure/providers/implementations/anthropic.js +329 -0
- package/src/infrastructure/providers/implementations/azure.js +296 -0
- package/src/infrastructure/providers/implementations/bedrock.js +393 -0
- package/src/infrastructure/providers/implementations/dummy.js +112 -0
- package/src/infrastructure/providers/implementations/google.js +320 -0
- package/src/infrastructure/providers/implementations/huggingface.js +301 -0
- package/src/infrastructure/providers/implementations/lmstudio.js +189 -0
- package/src/infrastructure/providers/implementations/mock.js +275 -0
- package/src/infrastructure/providers/implementations/ollama.js +151 -0
- package/src/infrastructure/providers/implementations/openai.js +273 -0
- package/src/infrastructure/providers/implementations/vertex.js +438 -0
- package/src/infrastructure/providers/provider-management.service.js +415 -0
- package/src/infrastructure/providers/provider-manager.service.js +363 -0
- package/src/infrastructure/providers/utils/base-provider-helpers.js +660 -0
- package/src/infrastructure/providers/utils/model-config.js +610 -0
- package/src/infrastructure/providers/utils/provider-utils.js +286 -0
- package/src/shared/constants/colors.js +370 -0
- package/src/shared/utils/cli-entry-utils.js +525 -0
- package/src/shared/utils/error-classes.js +423 -0
- package/src/shared/utils/json-utils.js +318 -0
- package/src/shared/utils/utils.js +1997 -0
- package/types/index.d.ts +464 -0
|
@@ -0,0 +1,525 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Entry Point Utilities
|
|
3
|
+
* Provides process error handlers, startup tips, and common CLI patterns
|
|
4
|
+
* Provides CLI error handling, validation, and user interface utilities
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import { GitError, ConfigError, NetworkError, ErrorContext } from './error-classes.js';
|
|
10
|
+
import colors from '../constants/colors.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Enhanced error handling for CLI applications with context-aware tips
|
|
14
|
+
* @param {Error} error - The error that occurred
|
|
15
|
+
* @param {string} context - Context where the error occurred
|
|
16
|
+
* @param {Object} options - Error handling options
|
|
17
|
+
*/
|
|
18
|
+
export function handleCLIError(error, context = 'application', options = {}) {
|
|
19
|
+
const { exitOnError = true, showTips = true, showStack = false } = options;
|
|
20
|
+
|
|
21
|
+
console.error(colors.errorMessage(`❌ Failed to ${context}: ${error.message}`));
|
|
22
|
+
|
|
23
|
+
if (showStack && error.stack) {
|
|
24
|
+
console.error(colors.gray(error.stack));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (showTips) {
|
|
28
|
+
const tips = getContextualTips(error, context);
|
|
29
|
+
if (tips.length > 0) {
|
|
30
|
+
tips.forEach(tip => console.error(colors.infoMessage(`💡 Tip: ${tip}`)));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (exitOnError) {
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get contextual tips based on error type and message
|
|
41
|
+
* @param {Error} error - The error that occurred
|
|
42
|
+
* @param {string} context - Context where the error occurred
|
|
43
|
+
* @returns {Array} Array of helpful tip strings
|
|
44
|
+
*/
|
|
45
|
+
function getContextualTips(error, context) {
|
|
46
|
+
const tips = [];
|
|
47
|
+
const message = error.message.toLowerCase();
|
|
48
|
+
|
|
49
|
+
// Git-related tips
|
|
50
|
+
if (error instanceof GitError || message.includes('git')) {
|
|
51
|
+
if (message.includes('not a git repository')) {
|
|
52
|
+
tips.push('Make sure you\'re in a git repository directory');
|
|
53
|
+
tips.push('Run `git init` to initialize a new repository');
|
|
54
|
+
} else if (message.includes('no commits')) {
|
|
55
|
+
tips.push('Make at least one commit before generating a changelog');
|
|
56
|
+
} else if (message.includes('remote')) {
|
|
57
|
+
tips.push('Check your git remote configuration with `git remote -v`');
|
|
58
|
+
} else {
|
|
59
|
+
tips.push('Ensure git is properly installed and configured');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Provider/API related tips
|
|
64
|
+
if (error instanceof ConfigError || message.includes('provider') || message.includes('api key')) {
|
|
65
|
+
tips.push('Configure at least one AI provider in your .env.local file');
|
|
66
|
+
tips.push('Check the documentation for provider-specific setup instructions');
|
|
67
|
+
tips.push('Verify your API keys are valid and have sufficient quota');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Network related tips
|
|
71
|
+
if (error instanceof NetworkError || message.includes('enotfound') || message.includes('network') || message.includes('timeout')) {
|
|
72
|
+
tips.push('Check your internet connection');
|
|
73
|
+
tips.push('If using a proxy, verify your proxy settings');
|
|
74
|
+
tips.push('Some providers may be temporarily unavailable - try again later');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Permission related tips
|
|
78
|
+
if (message.includes('permission') || message.includes('eacces')) {
|
|
79
|
+
tips.push('Check file and directory permissions');
|
|
80
|
+
tips.push('Try running with appropriate privileges (but avoid sudo if possible)');
|
|
81
|
+
tips.push('Ensure the current user has write access to the working directory');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// File system tips
|
|
85
|
+
if (message.includes('enoent') || message.includes('file not found')) {
|
|
86
|
+
tips.push('Verify the file or directory exists');
|
|
87
|
+
tips.push('Check the file path spelling and case sensitivity');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Memory/resource tips
|
|
91
|
+
if (message.includes('out of memory') || message.includes('heap')) {
|
|
92
|
+
tips.push('Try processing fewer commits at once');
|
|
93
|
+
tips.push('Increase Node.js memory limit with --max-old-space-size');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Context-specific tips
|
|
97
|
+
if (context.includes('changelog')) {
|
|
98
|
+
tips.push('Try using a smaller commit range or batch processing');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (context.includes('mcp')) {
|
|
102
|
+
tips.push('Ensure MCP server dependencies are installed');
|
|
103
|
+
tips.push('Check MCP server configuration and permissions');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return tips;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Comprehensive process error handlers for CLI applications
|
|
111
|
+
* @param {string} appName - Name of the application for error messages
|
|
112
|
+
* @param {Object} options - Handler options
|
|
113
|
+
*/
|
|
114
|
+
export function setupProcessErrorHandlers(appName = 'Application', options = {}) {
|
|
115
|
+
const { gracefulShutdown = true, logErrors = true, showStack = false } = options;
|
|
116
|
+
|
|
117
|
+
process.on('uncaughtException', (error) => {
|
|
118
|
+
if (logErrors) {
|
|
119
|
+
console.error(colors.errorMessage(`💥 Uncaught Exception in ${appName}:`), error.message);
|
|
120
|
+
if (showStack) {
|
|
121
|
+
console.error(colors.gray('Stack trace:'), error.stack);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const errorContext = new ErrorContext()
|
|
126
|
+
.add('type', 'uncaughtException')
|
|
127
|
+
.add('appName', appName)
|
|
128
|
+
.build();
|
|
129
|
+
|
|
130
|
+
handleCLIError(error, 'handle uncaught exception', {
|
|
131
|
+
exitOnError: true,
|
|
132
|
+
showTips: true,
|
|
133
|
+
showStack
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
process.on('unhandledRejection', (reason, promise) => {
|
|
138
|
+
if (logErrors) {
|
|
139
|
+
console.error(colors.errorMessage(`💥 Unhandled Rejection in ${appName}:`));
|
|
140
|
+
console.error('Promise:', promise);
|
|
141
|
+
console.error('Reason:', reason);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const error = reason instanceof Error ? reason : new Error(String(reason));
|
|
145
|
+
handleCLIError(error, 'handle unhandled promise rejection', {
|
|
146
|
+
exitOnError: true,
|
|
147
|
+
showTips: true,
|
|
148
|
+
showStack
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
if (gracefulShutdown) {
|
|
153
|
+
// Graceful shutdown handling
|
|
154
|
+
process.on('SIGINT', () => {
|
|
155
|
+
console.log(colors.infoMessage(`\n👋 ${appName} interrupted by user. Shutting down gracefully...`));
|
|
156
|
+
process.exit(0);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
process.on('SIGTERM', () => {
|
|
160
|
+
console.log(colors.infoMessage(`\n👋 ${appName} terminated. Shutting down gracefully...`));
|
|
161
|
+
process.exit(0);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Enhanced CLI application wrapper with comprehensive startup handling
|
|
168
|
+
* @param {string} appName - Name of the application
|
|
169
|
+
* @param {string} version - Version string
|
|
170
|
+
* @param {Function} initFn - Initialization function to run
|
|
171
|
+
* @param {Object} options - Application options
|
|
172
|
+
*/
|
|
173
|
+
export async function runCLIApplication(appName, version, initFn, options = {}) {
|
|
174
|
+
const {
|
|
175
|
+
showStartupMessage = true,
|
|
176
|
+
setupErrorHandlers = true,
|
|
177
|
+
debugMode = process.env.DEBUG === 'true',
|
|
178
|
+
showTips = true,
|
|
179
|
+
validateGit = false,
|
|
180
|
+
requiredEnvVars = [],
|
|
181
|
+
startupTips = []
|
|
182
|
+
} = options;
|
|
183
|
+
|
|
184
|
+
if (setupErrorHandlers) {
|
|
185
|
+
setupProcessErrorHandlers(appName, {
|
|
186
|
+
gracefulShutdown: true,
|
|
187
|
+
logErrors: true,
|
|
188
|
+
showStack: debugMode
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (showStartupMessage) {
|
|
193
|
+
displayStartupMessage(appName, version, { debugMode });
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Pre-flight checks
|
|
197
|
+
if (validateGit && !validateGitRepository()) {
|
|
198
|
+
console.error(colors.errorMessage('❌ Not in a git repository'));
|
|
199
|
+
console.error(colors.infoMessage('💡 Tip: Navigate to a git repository or run `git init`'));
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (requiredEnvVars.length > 0 && !validateEnvironment(requiredEnvVars)) {
|
|
204
|
+
process.exit(1);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (showTips && startupTips.length > 0) {
|
|
208
|
+
showStartupTips(appName, startupTips);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
await initFn();
|
|
213
|
+
} catch (error) {
|
|
214
|
+
handleCLIError(error, `start ${appName}`, {
|
|
215
|
+
exitOnError: true,
|
|
216
|
+
showTips: true,
|
|
217
|
+
showStack: debugMode
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Enhanced MCP Server startup wrapper
|
|
224
|
+
* @param {string} serverName - Name of the MCP server
|
|
225
|
+
* @param {string} version - Version string
|
|
226
|
+
* @param {Function} serverClass - MCP Server class constructor
|
|
227
|
+
* @param {Object} options - Server options
|
|
228
|
+
*/
|
|
229
|
+
export async function runMCPServer(serverName, version, serverClass, options = {}) {
|
|
230
|
+
const {
|
|
231
|
+
debugMode = process.env.DEBUG === 'true',
|
|
232
|
+
showTools = true,
|
|
233
|
+
tools = [],
|
|
234
|
+
showCapabilities = true,
|
|
235
|
+
capabilities = []
|
|
236
|
+
} = options;
|
|
237
|
+
|
|
238
|
+
displayStartupMessage(serverName, version, {
|
|
239
|
+
type: 'MCP Server',
|
|
240
|
+
debugMode
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
console.log(colors.processingMessage('🔌 Starting MCP server...'));
|
|
244
|
+
|
|
245
|
+
if (showTools && tools.length > 0) {
|
|
246
|
+
console.log(colors.infoMessage(`🎯 Available tools: ${tools.join(', ')}`));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (showCapabilities && capabilities.length > 0) {
|
|
250
|
+
console.log(colors.infoMessage(`⚡ Capabilities: ${capabilities.join(', ')}`));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
try {
|
|
254
|
+
console.log(colors.processingMessage('✅ MCP server initializing...'));
|
|
255
|
+
|
|
256
|
+
const server = new serverClass();
|
|
257
|
+
await server.run();
|
|
258
|
+
|
|
259
|
+
console.log(colors.successMessage('🚀 MCP server started successfully'));
|
|
260
|
+
|
|
261
|
+
} catch (error) {
|
|
262
|
+
handleCLIError(error, 'initialize MCP server', {
|
|
263
|
+
exitOnError: true,
|
|
264
|
+
showTips: true,
|
|
265
|
+
showStack: debugMode
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Display formatted startup message
|
|
272
|
+
* @param {string} name - Application name
|
|
273
|
+
* @param {string} version - Version string
|
|
274
|
+
* @param {Object} options - Display options
|
|
275
|
+
*/
|
|
276
|
+
function displayStartupMessage(name, version, options = {}) {
|
|
277
|
+
const { type = 'CLI Tool', debugMode = false } = options;
|
|
278
|
+
|
|
279
|
+
console.log(colors.header(`🤖 ${name}`));
|
|
280
|
+
console.log(colors.label(`📦 Version: ${colors.highlight(version)}`));
|
|
281
|
+
console.log(colors.label(`🏷️ Type: ${colors.value(type)}`));
|
|
282
|
+
|
|
283
|
+
if (debugMode) {
|
|
284
|
+
console.log(colors.warningMessage('🐛 Debug mode enabled'));
|
|
285
|
+
console.log(colors.label(`📁 Working directory: ${colors.path(process.cwd())}`));
|
|
286
|
+
console.log(colors.label(`⚙️ Node.js: ${colors.highlight(process.version)}`));
|
|
287
|
+
console.log(colors.label(`🖥️ Platform: ${colors.value(process.platform)} ${process.arch}`));
|
|
288
|
+
}
|
|
289
|
+
console.log('');
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Enhanced CLI argument validation with detailed feedback
|
|
294
|
+
* @param {Array} requiredArgs - Required argument names
|
|
295
|
+
* @param {Object} argv - Parsed arguments object
|
|
296
|
+
* @param {Object} options - Validation options
|
|
297
|
+
* @returns {boolean} Whether all required arguments are present
|
|
298
|
+
*/
|
|
299
|
+
export function validateRequiredArgs(requiredArgs, argv, options = {}) {
|
|
300
|
+
const { showUsage = true } = options;
|
|
301
|
+
const missing = requiredArgs.filter(arg => !argv[arg]);
|
|
302
|
+
|
|
303
|
+
if (missing.length > 0) {
|
|
304
|
+
console.error(colors.errorMessage(`❌ Missing required arguments: ${missing.join(', ')}`));
|
|
305
|
+
|
|
306
|
+
if (showUsage) {
|
|
307
|
+
console.error(colors.infoMessage('💡 Tip: Use --help to see usage information'));
|
|
308
|
+
|
|
309
|
+
// Show specific argument descriptions if available
|
|
310
|
+
missing.forEach(arg => {
|
|
311
|
+
const description = getArgumentDescription(arg);
|
|
312
|
+
if (description) {
|
|
313
|
+
console.error(colors.gray(` --${arg}: ${description}`));
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return true;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Get description for common CLI arguments
|
|
326
|
+
* @param {string} arg - Argument name
|
|
327
|
+
* @returns {string} Argument description
|
|
328
|
+
*/
|
|
329
|
+
function getArgumentDescription(arg) {
|
|
330
|
+
const descriptions = {
|
|
331
|
+
'version': 'Version to use for changelog generation',
|
|
332
|
+
'since': 'Git reference to start changelog from',
|
|
333
|
+
'provider': 'AI provider to use (openai, anthropic, etc.)',
|
|
334
|
+
'model': 'AI model to use for analysis',
|
|
335
|
+
'output': 'Output file path for generated changelog',
|
|
336
|
+
'format': 'Output format (markdown, json)',
|
|
337
|
+
'config': 'Configuration file path'
|
|
338
|
+
};
|
|
339
|
+
return descriptions[arg] || '';
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Enhanced environment validation with helpful guidance
|
|
344
|
+
* @param {Array} requiredEnvVars - Required environment variable names
|
|
345
|
+
* @param {Object} options - Validation options
|
|
346
|
+
* @returns {boolean} Whether all required environment variables are set
|
|
347
|
+
*/
|
|
348
|
+
export function validateEnvironment(requiredEnvVars = [], options = {}) {
|
|
349
|
+
const { showExamples = true } = options;
|
|
350
|
+
const missing = requiredEnvVars.filter(envVar => !process.env[envVar]);
|
|
351
|
+
|
|
352
|
+
if (missing.length > 0) {
|
|
353
|
+
console.error(colors.errorMessage(`❌ Missing required environment variables: ${missing.join(', ')}`));
|
|
354
|
+
console.error(colors.infoMessage('💡 Tip: Check your .env.local file or environment configuration'));
|
|
355
|
+
|
|
356
|
+
if (showExamples) {
|
|
357
|
+
console.error(colors.gray('\nExample .env.local configuration:'));
|
|
358
|
+
missing.forEach(envVar => {
|
|
359
|
+
const example = getEnvVarExample(envVar);
|
|
360
|
+
if (example) {
|
|
361
|
+
console.error(colors.gray(`${envVar}=${example}`));
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Get example values for common environment variables
|
|
374
|
+
* @param {string} envVar - Environment variable name
|
|
375
|
+
* @returns {string} Example value
|
|
376
|
+
*/
|
|
377
|
+
function getEnvVarExample(envVar) {
|
|
378
|
+
const examples = {
|
|
379
|
+
'OPENAI_API_KEY': 'sk-...',
|
|
380
|
+
'ANTHROPIC_API_KEY': 'sk-ant-...',
|
|
381
|
+
'AZURE_OPENAI_API_KEY': 'your-azure-key',
|
|
382
|
+
'AZURE_OPENAI_ENDPOINT': 'https://your-resource.openai.azure.com/',
|
|
383
|
+
'GOOGLE_AI_API_KEY': 'your-google-ai-key',
|
|
384
|
+
'HUGGINGFACE_API_KEY': 'hf_...',
|
|
385
|
+
'DATABASE_URL': 'postgresql://user:pass@localhost:5432/db',
|
|
386
|
+
'DEBUG': 'true'
|
|
387
|
+
};
|
|
388
|
+
return examples[envVar] || 'your-value-here';
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Enhanced git repository validation
|
|
393
|
+
* @param {string} pathToCheck - Path to check (defaults to current directory)
|
|
394
|
+
* @param {Object} options - Validation options
|
|
395
|
+
* @returns {Object} Validation result with details
|
|
396
|
+
*/
|
|
397
|
+
export function validateGitRepository(pathToCheck = process.cwd(), options = {}) {
|
|
398
|
+
const { checkCommits = false, showDetails = false } = options;
|
|
399
|
+
|
|
400
|
+
try {
|
|
401
|
+
const gitPath = path.join(pathToCheck, '.git');
|
|
402
|
+
const isGitRepo = fs.existsSync(gitPath);
|
|
403
|
+
|
|
404
|
+
if (!isGitRepo) {
|
|
405
|
+
return { valid: false, reason: 'not_git_repository' };
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const result = { valid: true, path: pathToCheck };
|
|
409
|
+
|
|
410
|
+
if (checkCommits) {
|
|
411
|
+
// Git validation requires command execution
|
|
412
|
+
result.hasCommits = true; // Assume true for basic validation
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (showDetails) {
|
|
416
|
+
console.log(colors.successMessage(`✅ Valid git repository: ${pathToCheck}`));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return result;
|
|
420
|
+
|
|
421
|
+
} catch (error) {
|
|
422
|
+
return {
|
|
423
|
+
valid: false,
|
|
424
|
+
reason: 'access_error',
|
|
425
|
+
error: error.message
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Display helpful startup tips
|
|
432
|
+
* @param {string} appName - Name of the application
|
|
433
|
+
* @param {Array} tips - Array of tip strings to display
|
|
434
|
+
*/
|
|
435
|
+
export function showStartupTips(appName, tips = []) {
|
|
436
|
+
if (tips.length === 0) return;
|
|
437
|
+
|
|
438
|
+
console.log(colors.header(`💡 ${appName} Tips:`));
|
|
439
|
+
tips.forEach((tip, index) => {
|
|
440
|
+
console.log(colors.infoMessage(` ${index + 1}. ${tip}`));
|
|
441
|
+
});
|
|
442
|
+
console.log('');
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Enhanced version information display
|
|
447
|
+
* @param {string} name - Application name
|
|
448
|
+
* @param {string} version - Version string
|
|
449
|
+
* @param {Object} additional - Additional version info
|
|
450
|
+
*/
|
|
451
|
+
export function displayVersionInfo(name, version, additional = {}) {
|
|
452
|
+
console.log(colors.header(`${name} v${version}`));
|
|
453
|
+
|
|
454
|
+
if (additional.nodeVersion !== false) {
|
|
455
|
+
console.log(colors.label(`Node.js: ${colors.highlight(process.version)}`));
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if (additional.platform !== false) {
|
|
459
|
+
console.log(colors.label(`Platform: ${colors.value(process.platform)} ${process.arch}`));
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (additional.gitVersion && additional.gitVersion !== false) {
|
|
463
|
+
console.log(colors.label(`Git: ${colors.highlight(additional.gitVersion || 'Available')}`));
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
Object.entries(additional).forEach(([key, value]) => {
|
|
467
|
+
if (typeof value === 'string' && !['nodeVersion', 'platform', 'gitVersion'].includes(key)) {
|
|
468
|
+
console.log(colors.label(`${key}: ${colors.value(value)}`));
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Create startup tips for AI changelog generator
|
|
475
|
+
* @returns {Array} Array of helpful tips
|
|
476
|
+
*/
|
|
477
|
+
export function getDefaultStartupTips() {
|
|
478
|
+
return [
|
|
479
|
+
'Ensure you have at least one AI provider configured in .env.local',
|
|
480
|
+
'Use --help to see all available commands and options',
|
|
481
|
+
'Run in a git repository with existing commits for best results',
|
|
482
|
+
'Try --analysis-mode detailed for comprehensive changelog generation',
|
|
483
|
+
'Use --interactive for guided changelog creation'
|
|
484
|
+
];
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Validate common CLI preconditions
|
|
489
|
+
* @param {Object} requirements - Requirements to validate
|
|
490
|
+
* @returns {Object} Validation result
|
|
491
|
+
*/
|
|
492
|
+
export function validateCLIPreconditions(requirements = {}) {
|
|
493
|
+
const {
|
|
494
|
+
gitRepository = false,
|
|
495
|
+
envVars = [],
|
|
496
|
+
args = [],
|
|
497
|
+
argv = {}
|
|
498
|
+
} = requirements;
|
|
499
|
+
|
|
500
|
+
const results = {
|
|
501
|
+
valid: true,
|
|
502
|
+
errors: [],
|
|
503
|
+
warnings: []
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
if (gitRepository) {
|
|
507
|
+
const gitResult = validateGitRepository();
|
|
508
|
+
if (!gitResult.valid) {
|
|
509
|
+
results.valid = false;
|
|
510
|
+
results.errors.push('Not in a git repository');
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
if (envVars.length > 0 && !validateEnvironment(envVars, { showExamples: false })) {
|
|
515
|
+
results.valid = false;
|
|
516
|
+
results.errors.push('Missing required environment variables');
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
if (args.length > 0 && !validateRequiredArgs(args, argv, { showUsage: false })) {
|
|
520
|
+
results.valid = false;
|
|
521
|
+
results.errors.push('Missing required arguments');
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
return results;
|
|
525
|
+
}
|