@lazykedar/lazydocs 1.3.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/dist/ai.js ADDED
@@ -0,0 +1,223 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getDefaultModel = getDefaultModel;
37
+ exports.getFallbackModels = getFallbackModels;
38
+ exports.getAvailableModels = getAvailableModels;
39
+ exports.generateDocSection = generateDocSection;
40
+ const groq_sdk_1 = require("groq-sdk");
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const DEFAULT_MODEL = 'llama-3.3-70b-versatile';
44
+ // Fallback models for when API fetch fails
45
+ const FALLBACK_MODELS = [
46
+ 'llama-3.3-70b-versatile',
47
+ 'llama-3.1-8b-instant',
48
+ 'gemma2-9b-it',
49
+ 'mixtral-8x7b-32768',
50
+ 'llama-3.1-70b-versatile',
51
+ ];
52
+ function getDefaultModel() {
53
+ return DEFAULT_MODEL;
54
+ }
55
+ function getFallbackModels() {
56
+ return FALLBACK_MODELS;
57
+ }
58
+ async function getAvailableModels(apiKey) {
59
+ try {
60
+ const groq = new groq_sdk_1.Groq({ apiKey });
61
+ const models = await groq.models.list();
62
+ return models.data
63
+ .filter((model) => model.active !== false)
64
+ .map((model) => model.id)
65
+ .sort();
66
+ }
67
+ catch (error) {
68
+ console.warn('Failed to fetch models from API, using fallback list');
69
+ return FALLBACK_MODELS;
70
+ }
71
+ }
72
+ const logError = (message) => {
73
+ const logDir = path.join(process.cwd(), 'logs');
74
+ if (!fs.existsSync(logDir))
75
+ fs.mkdirSync(logDir);
76
+ const logFile = path.join(logDir, 'error.log');
77
+ fs.appendFileSync(logFile, `${new Date().toISOString()} - ${message}\n`);
78
+ };
79
+ // Enhanced prompt builder with structured requirements
80
+ function buildEnhancedPrompt(codeSnippet, type, compactSummary) {
81
+ const prompts = {
82
+ readme: `You are a technical documentation expert. Analyze this codebase and generate a comprehensive, professional README in Markdown.
83
+
84
+ ${compactSummary ? `PROJECT SUMMARY:\n${compactSummary}\n\n` : ''}CODE ANALYSIS:
85
+ ${codeSnippet}
86
+
87
+ Generate a complete README with these sections:
88
+ 1. Project title and tagline
89
+ 2. Overview - What the project does and why it exists
90
+ 3. Key Features - Bullet points of main capabilities
91
+ 4. Installation - Clear setup instructions
92
+ 5. Usage - Code examples showing how to use it
93
+ 6. API Reference - Document main functions/classes with descriptions
94
+ 7. Contributing - Brief guidelines
95
+ 8. License - Standard license section
96
+
97
+ Requirements:
98
+ - Use clear Markdown formatting with proper headers
99
+ - Include code blocks with syntax highlighting
100
+ - Keep it concise but comprehensive (800-1200 words)
101
+ - Use tables for API documentation
102
+ - Professional yet approachable tone
103
+ - Focus on what developers need to know`,
104
+ pr: `You are a code review expert. Analyze these code changes and generate a clear, professional Pull Request description in Markdown.
105
+
106
+ ${compactSummary ? `CHANGES SUMMARY:\n${compactSummary}\n\n` : ''}DIFF ANALYSIS:
107
+ ${codeSnippet}
108
+
109
+ Generate a PR description with these sections:
110
+ ## Summary
111
+ Brief overview of what changed and why
112
+
113
+ ## Changes Made
114
+ - Bullet points of specific changes
115
+ - Group related changes together
116
+ - Be specific about what was added/modified/removed
117
+
118
+ ## Impact
119
+ - How this affects the codebase
120
+ - Any breaking changes
121
+ - Performance implications
122
+
123
+ ## Testing
124
+ - How to verify these changes
125
+ - Test scenarios covered
126
+
127
+ Requirements:
128
+ - Clear, scannable format
129
+ - Use conventional commit style language
130
+ - Highlight breaking changes prominently
131
+ - Professional tone suitable for team review`,
132
+ changelog: `You are a release notes expert. Analyze these commits and generate a well-organized changelog entry in Markdown.
133
+
134
+ ${compactSummary ? `COMMIT SUMMARY:\n${compactSummary}\n\n` : ''}COMMIT HISTORY:
135
+ ${codeSnippet}
136
+
137
+ Generate a changelog following Keep a Changelog format:
138
+
139
+ ## [Version] - YYYY-MM-DD
140
+
141
+ ### 🚀 Features
142
+ - New user-facing features
143
+
144
+ ### 🐛 Bug Fixes
145
+ - Issues resolved
146
+
147
+ ### 📚 Documentation
148
+ - Doc updates
149
+
150
+ ### 🔧 Maintenance
151
+ - Internal improvements, refactoring, dependencies
152
+
153
+ ### ⚠️ Breaking Changes
154
+ - Changes that break backward compatibility
155
+
156
+ Requirements:
157
+ - Use emoji for visual scanning
158
+ - Group similar changes together
159
+ - Use imperative mood ("Add feature" not "Added feature")
160
+ - Be specific but concise
161
+ - Highlight breaking changes clearly
162
+ - Follow semantic versioning principles`,
163
+ };
164
+ return prompts[type];
165
+ }
166
+ async function generateDocSection(codeSnippet, type, apiKey, customPrompt, options = {}, compactSummary) {
167
+ const { model = DEFAULT_MODEL, temperature = 0.7, maxTokens = 2048, retries = 3, timeout = 30000, } = options;
168
+ // Build enhanced prompt with structured requirements
169
+ const prompt = customPrompt || buildEnhancedPrompt(codeSnippet, type, compactSummary);
170
+ // Retry logic with exponential backoff for reliability
171
+ for (let attempt = 1; attempt <= retries; attempt++) {
172
+ try {
173
+ const groq = new groq_sdk_1.Groq({
174
+ apiKey,
175
+ timeout,
176
+ });
177
+ const completion = await groq.chat.completions.create({
178
+ messages: [
179
+ { role: 'system', content: 'You are an expert technical writer who creates clear, professional documentation.' },
180
+ { role: 'user', content: prompt }
181
+ ],
182
+ model,
183
+ temperature,
184
+ max_tokens: maxTokens,
185
+ });
186
+ const content = completion.choices[0]?.message?.content;
187
+ if (!content) {
188
+ throw new Error('No content generated from AI');
189
+ }
190
+ return content;
191
+ }
192
+ catch (error) {
193
+ const errorMsg = `Attempt ${attempt}/${retries} failed: ${error.message}`;
194
+ logError(errorMsg);
195
+ // Last attempt - throw detailed error
196
+ if (attempt === retries) {
197
+ if (error.status === 401 || error.message?.includes('401')) {
198
+ throw new Error('Invalid API key. Get one from console.groq.com and set with: lazydocs config set GROQ_API_KEY=your_key');
199
+ }
200
+ if (error.status === 429 || error.message?.includes('rate_limit')) {
201
+ throw new Error('Rate limit exceeded. Try:\n' +
202
+ '1. Wait a few minutes and try again\n' +
203
+ '2. Use a faster model: --model llama-3.1-8b-instant\n' +
204
+ '3. Reduce max tokens: --max-tokens 1024');
205
+ }
206
+ if (error.status === 413 || error.message?.includes('too large')) {
207
+ throw new Error('Request too large. Try:\n' +
208
+ '1. Analyze a smaller directory\n' +
209
+ '2. Use a model with larger context window\n' +
210
+ '3. Reduce the amount of code being analyzed');
211
+ }
212
+ if (error.code === 'ENOTFOUND') {
213
+ throw new Error(`Network error: Cannot connect to ${error.hostname}. Check your internet connection.`);
214
+ }
215
+ throw new Error(`AI generation failed after ${retries} attempts: ${error.message}`);
216
+ }
217
+ // Not last attempt - log warning and retry with backoff
218
+ console.warn(`⚠️ ${errorMsg} - retrying...`);
219
+ await new Promise(resolve => setTimeout(resolve, 1000 * attempt)); // Exponential backoff
220
+ }
221
+ }
222
+ return 'Error generating content after multiple attempts';
223
+ }
package/dist/cli.js ADDED
@@ -0,0 +1,379 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ const commander = __importStar(require("commander"));
38
+ const inquirer = __importStar(require("inquirer"));
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ const r_1 = require("./o/r");
42
+ const p_1 = require("./o/p");
43
+ const c_1 = require("./o/c");
44
+ const ai_1 = require("./ai");
45
+ const config_manager_1 = require("./utils/config-manager");
46
+ const logError = (message) => {
47
+ const logDir = path.join(process.cwd(), 'logs');
48
+ if (!fs.existsSync(logDir))
49
+ fs.mkdirSync(logDir);
50
+ const logFile = path.join(logDir, 'error.log');
51
+ fs.appendFileSync(logFile, `${new Date().toISOString()} - ${message}\n`);
52
+ };
53
+ const program = new commander.Command();
54
+ program
55
+ .name('lazydocs')
56
+ .description('AI-powered documentation generator using Groq')
57
+ .version('1.1.0');
58
+ // Config commands
59
+ const configCmd = program.command('config');
60
+ configCmd
61
+ .command('set')
62
+ .argument('<key=value>', 'Set config (e.g., GROQ_API_KEY=gsk_...)')
63
+ .action((kv) => {
64
+ try {
65
+ const [key, value] = kv.split('=');
66
+ if (!key || !value) {
67
+ throw new Error('Invalid format. Use: key=value');
68
+ }
69
+ (0, config_manager_1.setConfig)(key, value);
70
+ console.log(`Set ${key} in ~/.lazydocs`);
71
+ }
72
+ catch (error) {
73
+ logError(`Config set error: ${error.message}`);
74
+ console.error(`Error: ${error.message}`);
75
+ process.exit(1);
76
+ }
77
+ });
78
+ configCmd
79
+ .command('get')
80
+ .argument('<key>', 'Get config value')
81
+ .action((key) => {
82
+ try {
83
+ const value = (0, config_manager_1.getConfigValue)(key);
84
+ if (value) {
85
+ const displayValue = key.includes('KEY') ? value.substring(0, 10) + '***' : value;
86
+ console.log(displayValue);
87
+ }
88
+ else {
89
+ console.log('Not set');
90
+ }
91
+ }
92
+ catch (error) {
93
+ logError(`Config get error: ${error.message}`);
94
+ console.error(`Error: ${error.message}`);
95
+ process.exit(1);
96
+ }
97
+ });
98
+ configCmd
99
+ .command('list')
100
+ .description('List all configuration')
101
+ .action(() => {
102
+ try {
103
+ const config = (0, config_manager_1.listConfig)();
104
+ if (Object.keys(config).length === 0) {
105
+ console.log('Current Configuration: (empty - using defaults)');
106
+ }
107
+ else {
108
+ console.log('Current Configuration:\n');
109
+ Object.entries(config).forEach(([key, value]) => {
110
+ const displayValue = key.includes('KEY') ? String(value).substring(0, 10) + '***' : value;
111
+ console.log(` ${key}: ${displayValue}`);
112
+ });
113
+ }
114
+ }
115
+ catch (error) {
116
+ logError(`Config list error: ${error.message}`);
117
+ console.error(`Error: ${error.message}`);
118
+ process.exit(1);
119
+ }
120
+ });
121
+ configCmd
122
+ .command('delete')
123
+ .argument('<key>', 'Delete config value')
124
+ .action((key) => {
125
+ try {
126
+ const value = (0, config_manager_1.getConfigValue)(key);
127
+ if (value) {
128
+ (0, config_manager_1.deleteConfig)(key);
129
+ console.log(`Deleted ${key} from ~/.lazydocs`);
130
+ }
131
+ else {
132
+ console.log('Not set');
133
+ }
134
+ }
135
+ catch (error) {
136
+ logError(`Config delete error: ${error.message}`);
137
+ console.error(`Error: ${error.message}`);
138
+ process.exit(1);
139
+ }
140
+ });
141
+ // Generate command
142
+ program
143
+ .command('generate')
144
+ .description('Generate documentation')
145
+ .option('-i, --input <dir>', 'Input code directory', './src')
146
+ .option('-o, --output <file>', 'Output file')
147
+ .option('-t, --type <type>', 'Doc type: readme, pr, changelog', 'readme')
148
+ .option('-m, --model <model>', 'AI model to use', (0, ai_1.getDefaultModel)())
149
+ .option('--temperature <temp>', 'AI temperature (0-1)', parseFloat, 0.7)
150
+ .option('--max-tokens <tokens>', 'Maximum tokens', parseInt, 2048)
151
+ .option('--interactive', 'Interactive mode')
152
+ .option('--verbose', 'Verbose output')
153
+ .option('--template <path>', 'Custom Handlebars template file path')
154
+ .option('--base <branch>', 'Base branch for PR diff comparison')
155
+ .option('--head <branch>', 'Head branch for PR diff comparison')
156
+ .action(async (options) => {
157
+ try {
158
+ const startTime = Date.now();
159
+ // Interactive mode
160
+ if (options.interactive) {
161
+ let apiKey;
162
+ try {
163
+ const config = (0, config_manager_1.getConfig)({}, true);
164
+ apiKey = config.GROQ_API_KEY;
165
+ }
166
+ catch {
167
+ const keyAnswer = await inquirer.default.prompt([
168
+ {
169
+ type: 'password',
170
+ name: 'apiKey',
171
+ message: 'Enter your Groq API key (from console.groq.com):',
172
+ validate: (input) => (input ? true : 'API key is required!'),
173
+ },
174
+ ]);
175
+ apiKey = keyAnswer.apiKey;
176
+ }
177
+ console.log('Fetching available models...');
178
+ const availableModels = await (0, ai_1.getAvailableModels)(apiKey);
179
+ const answers = await inquirer.default.prompt([
180
+ {
181
+ type: 'list',
182
+ name: 'type',
183
+ message: 'What would you like to generate?',
184
+ choices: [
185
+ { name: 'README.md', value: 'readme' },
186
+ { name: 'PR Description', value: 'pr' },
187
+ { name: 'Changelog', value: 'changelog' },
188
+ ],
189
+ },
190
+ {
191
+ type: 'input',
192
+ name: 'input',
193
+ message: 'Input directory:',
194
+ default: './src',
195
+ },
196
+ {
197
+ type: 'list',
198
+ name: 'model',
199
+ message: 'Select AI model:',
200
+ choices: availableModels.map((m) => ({
201
+ name: m,
202
+ value: m,
203
+ })),
204
+ default: (0, ai_1.getDefaultModel)(),
205
+ },
206
+ ]);
207
+ Object.assign(options, answers);
208
+ }
209
+ // Set default output
210
+ if (!options.output) {
211
+ const defaults = {
212
+ readme: './README.md',
213
+ pr: './PR_DESCRIPTION.md',
214
+ changelog: './CHANGELOG.md',
215
+ };
216
+ options.output = defaults[options.type];
217
+ }
218
+ // Get API key
219
+ let apiKey;
220
+ try {
221
+ const config = (0, config_manager_1.getConfig)({}, true);
222
+ apiKey = config.GROQ_API_KEY;
223
+ }
224
+ catch {
225
+ const answers = await inquirer.default.prompt([
226
+ {
227
+ type: 'password',
228
+ name: 'apiKey',
229
+ message: 'Enter your Groq API key (from console.groq.com):',
230
+ validate: (input) => (input ? true : 'API key is required!'),
231
+ },
232
+ {
233
+ type: 'confirm',
234
+ name: 'save',
235
+ message: 'Save API key to ~/.lazydocs?',
236
+ default: true,
237
+ },
238
+ ]);
239
+ apiKey = answers.apiKey;
240
+ if (answers.save) {
241
+ (0, config_manager_1.setConfig)('GROQ_API_KEY', apiKey);
242
+ }
243
+ }
244
+ if (options.verbose) {
245
+ console.log('Configuration:');
246
+ console.log(` Type: ${options.type}`);
247
+ console.log(` Input: ${options.input}`);
248
+ console.log(` Output: ${options.output}`);
249
+ console.log(` Model: ${options.model}`);
250
+ console.log(` Temperature: ${options.temperature}`);
251
+ console.log(` Max Tokens: ${options.maxTokens}`);
252
+ }
253
+ console.log(`Generating ${options.type} from ${options.input}...`);
254
+ const aiOptions = {
255
+ model: options.model,
256
+ temperature: options.temperature,
257
+ maxTokens: options.maxTokens,
258
+ };
259
+ // Generate
260
+ if (options.type === 'readme') {
261
+ await (0, r_1.generateReadme)(options.input, options.output, apiKey, aiOptions, options.template);
262
+ }
263
+ else if (options.type === 'pr') {
264
+ const gitOptions = { base: options.base, head: options.head };
265
+ await (0, p_1.generatePrDesc)(options.input, options.output, apiKey, aiOptions, gitOptions);
266
+ }
267
+ else if (options.type === 'changelog') {
268
+ await (0, c_1.generateChangelog)(options.input, options.output, apiKey, aiOptions);
269
+ }
270
+ else {
271
+ throw new Error(`Invalid type: ${options.type}`);
272
+ }
273
+ const duration = ((Date.now() - startTime) / 1000).toFixed(1);
274
+ console.log(`Generated ${options.type} at ${options.output} (${duration}s)`);
275
+ if (fs.existsSync(options.output)) {
276
+ const stats = fs.statSync(options.output);
277
+ console.log(`File size: ${(stats.size / 1024).toFixed(1)} KB`);
278
+ }
279
+ }
280
+ catch (error) {
281
+ logError(`Generate error: ${error.message}`);
282
+ console.error(`Error: ${error.message}`);
283
+ if (options.verbose && error.stack) {
284
+ console.error(error.stack);
285
+ }
286
+ process.exit(1);
287
+ }
288
+ });
289
+ // Init command
290
+ program
291
+ .command('init')
292
+ .description('Initialize lazydocs in current project')
293
+ .action(async () => {
294
+ try {
295
+ const answers = await inquirer.default.prompt([
296
+ {
297
+ type: 'input',
298
+ name: 'projectName',
299
+ message: 'Project name:',
300
+ default: path.basename(process.cwd()),
301
+ },
302
+ {
303
+ type: 'input',
304
+ name: 'description',
305
+ message: 'Project description:',
306
+ },
307
+ {
308
+ type: 'checkbox',
309
+ name: 'features',
310
+ message: 'Select features to document:',
311
+ choices: [
312
+ 'Installation guide',
313
+ 'Usage examples',
314
+ 'API documentation',
315
+ 'Contributing guidelines',
316
+ 'License information',
317
+ ],
318
+ },
319
+ ]);
320
+ const projectConfig = {
321
+ projectName: answers.projectName,
322
+ description: answers.description,
323
+ features: answers.features,
324
+ createdAt: new Date().toISOString(),
325
+ };
326
+ fs.writeFileSync('.lazydocs.json', JSON.stringify(projectConfig, null, 2));
327
+ console.log('Initialized lazydocs configuration at .lazydocs.json');
328
+ }
329
+ catch (error) {
330
+ logError(`Init error: ${error.message}`);
331
+ console.error(`Error: ${error.message}`);
332
+ process.exit(1);
333
+ }
334
+ });
335
+ // Models command
336
+ program
337
+ .command('models')
338
+ .description('List available AI models')
339
+ .option('--refresh', 'Fetch latest models from API')
340
+ .action(async (options) => {
341
+ try {
342
+ if (options.refresh) {
343
+ let apiKey;
344
+ try {
345
+ const config = (0, config_manager_1.getConfig)({}, true);
346
+ apiKey = config.GROQ_API_KEY;
347
+ }
348
+ catch {
349
+ console.error('API key required. Set with: lazydocs config set GROQ_API_KEY=your_key');
350
+ process.exit(1);
351
+ }
352
+ console.log('Fetching latest models from Groq API...\n');
353
+ const models = await (0, ai_1.getAvailableModels)(apiKey);
354
+ console.log('Available AI Models:\n');
355
+ models.forEach((model, index) => {
356
+ const isDefault = model === (0, ai_1.getDefaultModel)();
357
+ const marker = isDefault ? '*' : ' ';
358
+ console.log(`${marker} ${index + 1}. ${model}${isDefault ? ' (default)' : ''}`);
359
+ });
360
+ console.log(`\nFound ${models.length} active models`);
361
+ }
362
+ else {
363
+ console.log('Available AI Models (fallback list):\n');
364
+ const models = (0, ai_1.getFallbackModels)();
365
+ models.forEach((model, index) => {
366
+ const isDefault = model === (0, ai_1.getDefaultModel)();
367
+ const marker = isDefault ? '*' : ' ';
368
+ console.log(`${marker} ${index + 1}. ${model}${isDefault ? ' (default)' : ''}`);
369
+ });
370
+ console.log('\nUse --refresh to fetch latest models from API');
371
+ }
372
+ }
373
+ catch (error) {
374
+ logError(`Models error: ${error.message}`);
375
+ console.error(`Error: ${error.message}`);
376
+ process.exit(1);
377
+ }
378
+ });
379
+ program.parse();
package/dist/o/c.js ADDED
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.generateChangelog = generateChangelog;
40
+ const fs = __importStar(require("fs"));
41
+ const simple_git_1 = __importDefault(require("simple-git"));
42
+ const ai_1 = require("../ai");
43
+ async function generateChangelog(inputDir, outputFile, apiKey, aiOptions) {
44
+ console.log('Analyzing git history...');
45
+ const git = (0, simple_git_1.default)(inputDir);
46
+ try {
47
+ // Get recent commits (last 50)
48
+ const logs = await git.log({ maxCount: 50 });
49
+ const snippet = `
50
+ Total commits analyzed: ${logs.total}
51
+
52
+ Recent commits:
53
+ ${logs.all
54
+ .map((l) => `
55
+ - ${l.date}: ${l.message}
56
+ Author: ${l.author_name}
57
+ Hash: ${l.hash.substring(0, 7)}
58
+ `)
59
+ .join('\n')}
60
+ `;
61
+ console.log(` Analyzed ${logs.total} commits`);
62
+ console.log('Generating changelog...');
63
+ const changelog = await (0, ai_1.generateDocSection)(snippet, 'changelog', apiKey, undefined, aiOptions);
64
+ // Prepend version and date
65
+ const today = new Date().toISOString().split('T')[0];
66
+ const fullChangelog = `# Changelog
67
+
68
+ ## [Unreleased] - ${today}
69
+
70
+ ${changelog}
71
+
72
+ ---
73
+ *Generated by LazyDocs*
74
+ `;
75
+ fs.writeFileSync(outputFile, fullChangelog);
76
+ }
77
+ catch (error) {
78
+ if (error.message.includes('not a git repository')) {
79
+ throw new Error('Not a git repository. Please run this command in a git repository.');
80
+ }
81
+ throw error;
82
+ }
83
+ }