@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/o/p.js ADDED
@@ -0,0 +1,89 @@
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.generatePrDesc = generatePrDesc;
40
+ const fs = __importStar(require("fs"));
41
+ const simple_git_1 = __importDefault(require("simple-git"));
42
+ const ai_1 = require("../ai");
43
+ async function generatePrDesc(inputDir, outputFile, apiKey, aiOptions, gitOptions) {
44
+ console.log('Analyzing git changes...');
45
+ const git = (0, simple_git_1.default)(inputDir);
46
+ try {
47
+ const diffArgs = [];
48
+ if (gitOptions?.base) {
49
+ if (gitOptions.head) {
50
+ diffArgs.push(`${gitOptions.base}...${gitOptions.head}`);
51
+ }
52
+ else {
53
+ diffArgs.push(gitOptions.base);
54
+ }
55
+ console.log(` Comparing: ${diffArgs[0]}`);
56
+ }
57
+ // Get diff summary with compact format
58
+ const diff = await git.diffSummary(diffArgs);
59
+ const diffText = await git.diff(diffArgs);
60
+ const fileChanges = diff.files.map((f) => {
61
+ const ins = 'insertions' in f ? f.insertions : 0;
62
+ const del = 'deletions' in f ? f.deletions : 0;
63
+ return `- ${f.file} (+${ins}/-${del})`;
64
+ }).join('\n');
65
+ // Build compact summary for token efficiency
66
+ const compactSummary = `Files changed: ${diff.files.length}
67
+ Insertions: ${diff.insertions}
68
+ Deletions: ${diff.deletions}
69
+
70
+ Changed files:
71
+ ${fileChanges}`;
72
+ // Limit diff size for token efficiency
73
+ const diffPreview = diffText.length > 5000
74
+ ? diffText.slice(0, 5000) + '\n\n... (diff truncated for brevity)'
75
+ : diffText;
76
+ const snippet = `${compactSummary}\n\nDiff preview:\n${diffPreview}`;
77
+ console.log(` ${diff.files.length} files changed (${diff.insertions} insertions, ${diff.deletions} deletions)`);
78
+ console.log('Generating PR description...');
79
+ const desc = await (0, ai_1.generateDocSection)(snippet, 'pr', apiKey, undefined, aiOptions, compactSummary);
80
+ fs.writeFileSync(outputFile, desc);
81
+ console.log(`PR description saved to ${outputFile}`);
82
+ }
83
+ catch (error) {
84
+ if (error.message.includes('not a git repository')) {
85
+ throw new Error('Not a git repository. Please run this command in a git repository.');
86
+ }
87
+ throw error;
88
+ }
89
+ }
package/dist/o/r.js ADDED
@@ -0,0 +1,111 @@
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.generateReadme = generateReadme;
37
+ const handlebars = __importStar(require("handlebars"));
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const ai_1 = require("../ai");
41
+ const a_1 = require("../a");
42
+ const merger_1 = require("../utils/merger");
43
+ async function generateReadme(inputDir, outputFile, apiKey, aiOptions, customTemplatePath) {
44
+ console.log('Analyzing codebase...');
45
+ const analysis = (0, a_1.analyzeCode)(inputDir);
46
+ console.log(` Found ${analysis.fileCount} files, ${analysis.totalLines} lines`);
47
+ console.log(` Functions: ${analysis.functions.length}, Classes: ${analysis.classes.length}`);
48
+ // Show compact summary if available
49
+ if (analysis.compactSummary) {
50
+ console.log('\nProject Structure:');
51
+ console.log(analysis.compactSummary.split('\n').map(l => ` ${l}`).join('\n'));
52
+ }
53
+ console.log('\nGenerating documentation...');
54
+ // Use compact summary for better token efficiency
55
+ const contextSnippet = analysis.compactSummary
56
+ ? `${analysis.compactSummary}\n\nCode samples:\n${analysis.snippets.slice(0, 4000)}`
57
+ : analysis.snippets;
58
+ const overview = await (0, ai_1.generateDocSection)(contextSnippet, 'readme', apiKey, undefined, aiOptions, analysis.compactSummary);
59
+ const usage = await (0, ai_1.generateDocSection)(contextSnippet, 'readme', apiKey, 'Generate practical usage examples with code snippets showing how to use this project', aiOptions, analysis.compactSummary);
60
+ // Generate API docs for top functions/classes (limit to avoid rate limits)
61
+ const topItems = [...analysis.functions, ...analysis.classes].slice(0, 8);
62
+ const apis = topItems.map(name => ({
63
+ name,
64
+ desc: `${name} - Core functionality (see code for details)`,
65
+ }));
66
+ // Try to read project name from package.json
67
+ let projectName = 'Your Project';
68
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
69
+ if (fs.existsSync(packageJsonPath)) {
70
+ try {
71
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
72
+ projectName = pkg.name || projectName;
73
+ }
74
+ catch (error) {
75
+ // Ignore
76
+ }
77
+ }
78
+ // Load template
79
+ const resolvedTemplatePath = customTemplatePath
80
+ ? path.resolve(process.cwd(), customTemplatePath)
81
+ : path.join(__dirname, '../t/r.hbs');
82
+ if (!fs.existsSync(resolvedTemplatePath)) {
83
+ throw new Error(`Template file not found: ${resolvedTemplatePath}`);
84
+ }
85
+ const template = handlebars.compile(fs.readFileSync(resolvedTemplatePath, 'utf-8'));
86
+ const content = template({
87
+ projectName,
88
+ overview,
89
+ usage,
90
+ apis,
91
+ stats: {
92
+ fileCount: analysis.fileCount,
93
+ totalLines: analysis.totalLines,
94
+ functions: analysis.functions.length,
95
+ classes: analysis.classes.length,
96
+ totalSize: (analysis.totalSize / 1024).toFixed(1),
97
+ complexity: analysis.complexity.toFixed(1),
98
+ },
99
+ });
100
+ let finalContent = content;
101
+ if (fs.existsSync(outputFile)) {
102
+ try {
103
+ const existingContent = fs.readFileSync(outputFile, 'utf-8');
104
+ finalContent = (0, merger_1.mergeContent)(existingContent, content);
105
+ }
106
+ catch (error) {
107
+ console.warn(`Failed to merge content, overwriting instead: ${error.message}`);
108
+ }
109
+ }
110
+ fs.writeFileSync(outputFile, finalContent);
111
+ }
package/dist/t/r.hbs ADDED
@@ -0,0 +1,53 @@
1
+ # {{projectName}}
2
+
3
+ ## 📋 Overview
4
+ <!-- lazydocs:start:overview -->
5
+ {{{overview}}}
6
+ <!-- lazydocs:end:overview -->
7
+
8
+ <!-- lazydocs:start:stats -->
9
+ {{#if stats}}
10
+ ## 📊 Project Statistics
11
+ - **Files analyzed:** {{stats.fileCount}}
12
+ - **Total lines of code:** {{stats.totalLines}}
13
+ - **Total size:** {{stats.totalSize}} KB
14
+ - **Functions:** {{stats.functions}}
15
+ - **Classes:** {{stats.classes}}
16
+ - **Avg complexity:** {{stats.complexity}}
17
+ {{/if}}
18
+ <!-- lazydocs:end:stats -->
19
+
20
+ ## 🚀 Installation
21
+
22
+ ```bash
23
+ npm install {{projectName}}
24
+ ```
25
+
26
+ ## 💡 Usage
27
+ <!-- lazydocs:start:usage -->
28
+ {{{usage}}}
29
+ <!-- lazydocs:end:usage -->
30
+
31
+ <!-- lazydocs:start:api -->
32
+ {{#if apis.length}}
33
+ ## 📚 API Reference
34
+
35
+ | Function/Class | Description |
36
+ |----------------|-------------|
37
+ {{#each apis}}
38
+ | `{{name}}` | {{{desc}}} |
39
+ {{/each}}
40
+ {{/if}}
41
+ <!-- lazydocs:end:api -->
42
+
43
+ ## 🤝 Contributing
44
+
45
+ Contributions are welcome! Please feel free to submit a Pull Request.
46
+
47
+ ## 📄 License
48
+
49
+ This project is licensed under the MIT License.
50
+
51
+ ---
52
+
53
+ *Documentation generated with ❤️ by [LazyDocs](https://github.com/kedar49/lazydocs)*
@@ -0,0 +1,184 @@
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.configExists = exports.deleteConfig = exports.listConfig = exports.getConfigValue = exports.setConfig = exports.getConfig = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const os = __importStar(require("os"));
40
+ const CONFIG_FILE = path.join(os.homedir(), '.lazydocs');
41
+ class ConfigError extends Error {
42
+ constructor(message) {
43
+ super(message);
44
+ this.name = 'ConfigError';
45
+ }
46
+ }
47
+ const parseAssert = (name, condition, message) => {
48
+ if (!condition) {
49
+ throw new ConfigError(`Invalid config property ${name}: ${message}`);
50
+ }
51
+ };
52
+ const configParsers = {
53
+ GROQ_API_KEY(key) {
54
+ if (!key) {
55
+ throw new ConfigError('Please set your Groq API key via `lazydocs config set GROQ_API_KEY=<your token>`');
56
+ }
57
+ parseAssert('GROQ_API_KEY', key.startsWith('gsk_'), 'Must start with "gsk_"');
58
+ parseAssert('GROQ_API_KEY', key.length > 20, 'Invalid API key format');
59
+ return key;
60
+ },
61
+ DEFAULT_MODEL(model) {
62
+ if (!model || model.length === 0) {
63
+ return 'llama-3.3-70b-versatile';
64
+ }
65
+ return model;
66
+ },
67
+ MAX_TOKENS(tokens) {
68
+ if (!tokens) {
69
+ return 2048;
70
+ }
71
+ const value = typeof tokens === 'string' ? tokens : String(tokens);
72
+ parseAssert('MAX_TOKENS', /^\d+$/.test(value), 'Must be an integer');
73
+ const parsed = Number(value);
74
+ parseAssert('MAX_TOKENS', parsed >= 100, 'Must be at least 100');
75
+ parseAssert('MAX_TOKENS', parsed <= 131072, 'Must be at most 131072');
76
+ return parsed;
77
+ },
78
+ TEMPERATURE(temp) {
79
+ if (!temp) {
80
+ return 0.7;
81
+ }
82
+ const value = typeof temp === 'string' ? temp : String(temp);
83
+ parseAssert('TEMPERATURE', /^[0-9.]+$/.test(value), 'Must be a number');
84
+ const parsed = Number(value);
85
+ parseAssert('TEMPERATURE', parsed >= 0, 'Must be at least 0');
86
+ parseAssert('TEMPERATURE', parsed <= 2, 'Must be at most 2');
87
+ return parsed;
88
+ },
89
+ GENERATE_COUNT(count) {
90
+ if (!count) {
91
+ return 1;
92
+ }
93
+ const value = typeof count === 'string' ? count : String(count);
94
+ parseAssert('GENERATE_COUNT', /^\d+$/.test(value), 'Must be an integer');
95
+ const parsed = Number(value);
96
+ parseAssert('GENERATE_COUNT', parsed > 0, 'Must be greater than 0');
97
+ parseAssert('GENERATE_COUNT', parsed <= 5, 'Must be at most 5');
98
+ return parsed;
99
+ },
100
+ TIMEOUT(timeout) {
101
+ if (!timeout) {
102
+ return 30000; // 30 seconds
103
+ }
104
+ const value = typeof timeout === 'string' ? timeout : String(timeout);
105
+ parseAssert('TIMEOUT', /^\d+$/.test(value), 'Must be an integer');
106
+ const parsed = Number(value);
107
+ parseAssert('TIMEOUT', parsed >= 1000, 'Must be at least 1000ms (1 second)');
108
+ parseAssert('TIMEOUT', parsed <= 300000, 'Must be at most 300000ms (5 minutes)');
109
+ return parsed;
110
+ },
111
+ };
112
+ const readConfigFile = () => {
113
+ try {
114
+ if (!fs.existsSync(CONFIG_FILE)) {
115
+ return {};
116
+ }
117
+ const content = fs.readFileSync(CONFIG_FILE, 'utf-8');
118
+ return JSON.parse(content);
119
+ }
120
+ catch (error) {
121
+ console.warn('Failed to read config file, using defaults');
122
+ return {};
123
+ }
124
+ };
125
+ const getConfig = (cliConfig, suppressErrors = false) => {
126
+ const fileConfig = readConfigFile();
127
+ const envConfig = {
128
+ GROQ_API_KEY: process.env.GROQ_API_KEY,
129
+ };
130
+ const parsedConfig = {};
131
+ for (const key of Object.keys(configParsers)) {
132
+ const parser = configParsers[key];
133
+ // Priority: CLI > Env > File
134
+ const value = cliConfig?.[key] ?? envConfig[key] ?? fileConfig[key];
135
+ if (suppressErrors) {
136
+ try {
137
+ parsedConfig[key] = parser(value);
138
+ }
139
+ catch (error) {
140
+ // Silently use default
141
+ }
142
+ }
143
+ else {
144
+ parsedConfig[key] = parser(value);
145
+ }
146
+ }
147
+ return parsedConfig;
148
+ };
149
+ exports.getConfig = getConfig;
150
+ const setConfig = (key, value) => {
151
+ if (!(key in configParsers)) {
152
+ throw new ConfigError(`Invalid config property: ${key}`);
153
+ }
154
+ // Validate the value
155
+ const parser = configParsers[key];
156
+ const parsed = parser(value);
157
+ // Read existing config
158
+ const config = readConfigFile();
159
+ // Update config
160
+ config[key] = parsed;
161
+ // Write back
162
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');
163
+ };
164
+ exports.setConfig = setConfig;
165
+ const getConfigValue = (key) => {
166
+ const config = readConfigFile();
167
+ const value = config[key];
168
+ return value !== undefined ? String(value) : undefined;
169
+ };
170
+ exports.getConfigValue = getConfigValue;
171
+ const listConfig = () => {
172
+ return readConfigFile();
173
+ };
174
+ exports.listConfig = listConfig;
175
+ const deleteConfig = (key) => {
176
+ const config = readConfigFile();
177
+ delete config[key];
178
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');
179
+ };
180
+ exports.deleteConfig = deleteConfig;
181
+ const configExists = () => {
182
+ return fs.existsSync(CONFIG_FILE);
183
+ };
184
+ exports.configExists = configExists;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mergeContent = mergeContent;
4
+ /**
5
+ * Smartly merges newly generated documentation content into existing documentation content
6
+ * by replacing content between comment anchors.
7
+ *
8
+ * Anchors are in the format:
9
+ * <!-- lazydocs:start:<section> -->
10
+ * <!-- lazydocs:end:<section> -->
11
+ *
12
+ * If the existing content contains no matching anchors, the function returns the new content completely
13
+ * (falling back to a full overwrite).
14
+ */
15
+ function mergeContent(existingContent, newContent) {
16
+ // Regex to find all start blocks in the new content
17
+ const startRegex = /<!-- lazydocs:start:([\w-]+) -->/g;
18
+ let match;
19
+ let mergedContent = existingContent;
20
+ const sections = {};
21
+ // Find all sections in the new generated content
22
+ while ((match = startRegex.exec(newContent)) !== null) {
23
+ const sectionName = match[1];
24
+ const startTag = `<!-- lazydocs:start:${sectionName} -->`;
25
+ const endTag = `<!-- lazydocs:end:${sectionName} -->`;
26
+ const startIndex = newContent.indexOf(startTag);
27
+ const endIndex = newContent.indexOf(endTag);
28
+ if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) {
29
+ // Extract the content inside the tags
30
+ const newSectionContent = newContent.substring(startIndex + startTag.length, endIndex);
31
+ sections[sectionName] = newSectionContent;
32
+ }
33
+ }
34
+ // If the existing content doesn't contain any of the lazydocs start tags,
35
+ // return the new content completely (overwrite)
36
+ let hasAnyAnchor = false;
37
+ for (const sectionName of Object.keys(sections)) {
38
+ const startTag = `<!-- lazydocs:start:${sectionName} -->`;
39
+ if (existingContent.includes(startTag)) {
40
+ hasAnyAnchor = true;
41
+ break;
42
+ }
43
+ }
44
+ if (!hasAnyAnchor) {
45
+ return newContent;
46
+ }
47
+ // Replace only the matched sections in the existing content
48
+ for (const [sectionName, newSectionContent] of Object.entries(sections)) {
49
+ const startTag = `<!-- lazydocs:start:${sectionName} -->`;
50
+ const endTag = `<!-- lazydocs:end:${sectionName} -->`;
51
+ const startIndex = mergedContent.indexOf(startTag);
52
+ const endIndex = mergedContent.indexOf(endTag);
53
+ if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) {
54
+ const before = mergedContent.substring(0, startIndex + startTag.length);
55
+ const after = mergedContent.substring(endIndex);
56
+ mergedContent = before + newSectionContent + after;
57
+ }
58
+ }
59
+ return mergedContent;
60
+ }
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@lazykedar/lazydocs",
3
+ "version": "1.3.0",
4
+ "description": "AI-powered documentation generator using Groq. Generate READMEs, PR descriptions, and changelogs in seconds.",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "lazydocs": "./dist/cli.js"
8
+ },
9
+ "scripts": {
10
+ "start": "npx -y serve web",
11
+ "build": "tsc && npm run copy-templates",
12
+ "copy-templates": "node -e \"const fs=require('fs');const path=require('path');const src='src/t';const dest='dist/t';if(!fs.existsSync(dest))fs.mkdirSync(dest,{recursive:true});fs.readdirSync(src).forEach(f=>{if(f.endsWith('.hbs'))fs.copyFileSync(path.join(src,f),path.join(dest,f))})\"",
13
+ "test": "jest",
14
+ "test:watch": "jest --watch",
15
+ "test:coverage": "jest --coverage",
16
+ "dev": "tsc --watch",
17
+ "prepublishOnly": "npm run build && npm test",
18
+ "postinstall": "echo 'LazyDocs installed! Run: lazydocs --help'"
19
+ },
20
+ "keywords": [
21
+ "ai",
22
+ "documentation",
23
+ "groq",
24
+ "readme",
25
+ "changelog",
26
+ "pr",
27
+ "generator",
28
+ "cli",
29
+ "markdown",
30
+ "llm",
31
+ "typescript",
32
+ "javascript"
33
+ ],
34
+ "author": "Kedar Sathe <kedarsathe49@gmail.com>",
35
+ "license": "MIT",
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "https://github.com/kedar49/lazydocs.git"
39
+ },
40
+ "engines": {
41
+ "node": ">=18"
42
+ },
43
+ "devDependencies": {
44
+ "@types/commander": "^2.12.0",
45
+ "@types/inquirer": "^9.0.9",
46
+ "@types/jest": "^30.0.0",
47
+ "@types/node": "^24.7.0",
48
+ "jest": "^30.2.0",
49
+ "ts-jest": "^29.4.4",
50
+ "typescript": "^5.9.3"
51
+ },
52
+ "dependencies": {
53
+ "@babel/parser": "^7.28.4",
54
+ "commander": "^14.0.1",
55
+ "groq-sdk": "^0.33.0",
56
+ "handlebars": "^4.7.8",
57
+ "inquirer": "^12.9.6",
58
+ "simple-git": "^3.28.0"
59
+ }
60
+ }