gitguide
Version:
AI-powered README generator for any project directory
466 lines (431 loc) โข 18.1 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GeminiService = void 0;
const node_fetch_1 = __importDefault(require("node-fetch"));
class GeminiService {
constructor(apiKey) {
this.apiUrl = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent';
this.apiKey = apiKey;
}
async generateReadme(projectData) {
const prompt = this.buildPrompt(projectData);
const response = await (0, node_fetch_1.default)(`${this.apiUrl}?key=${this.apiKey}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
contents: [{
parts: [{
text: prompt
}]
}],
generationConfig: {
temperature: 0.7,
topK: 40,
topP: 0.95,
maxOutputTokens: 8000,
}
})
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(`Gemini API error: ${errorData.error?.message || 'Unknown error'}`);
}
const data = await response.json();
const content = data.candidates?.[0]?.content?.parts?.[0]?.text || '';
if (!content) {
throw new Error('No content generated by Gemini API');
}
const cleanedContent = this.cleanupGeneratedContent(content);
return {
content: cleanedContent,
sections: this.extractSections(cleanedContent)
};
}
buildPrompt(projectData) {
const techStack = this.detectTechStack(projectData);
const projectType = this.detectProjectType(projectData);
const codeAnalysis = this.analyzeCodeStructure(projectData);
const fileContents = projectData.files
.filter(file => file.content && file.type === 'file' && file.content.length > 10)
.slice(0, 20)
.map(file => `File: ${file.path}\n${file.content?.slice(0, 3000) || ''}`)
.join('\n\n---\n\n');
return `You are an expert technical writer and software developer creating a comprehensive README.md for a project.
CRITICAL INSTRUCTIONS:
- Analyze the actual code files to understand what this application DOES
- Write about the specific functionality, features, and purpose based on the code
- DO NOT use generic descriptions - be specific about this project's actual capabilities
- Include real installation steps based on the package.json and project structure
- Mention actual components, routes, APIs, or features found in the code
- If it's a CLI tool, describe the actual commands and options
- If it's a web app, describe the actual pages and functionality
PROJECT DETAILS:
Name: ${projectData.name}
Description: ${projectData.description || 'No description provided'}
Primary Language: ${projectData.language || 'Not specified'}
Version: ${projectData.version || '1.0.0'}
Tech Stack: ${techStack}
Project Type: ${projectType}
Code Analysis: ${codeAnalysis}
Files: ${projectData.structure.files} files across ${projectData.structure.directories} directories
KEY FILES CONTENT:
${fileContents}
Generate a comprehensive, professional README.md using ONLY pure markdown syntax (NO HTML tags).
REQUIRED STRUCTURE:
# ${projectData.name}
> **${this.generateTagline(projectData, projectType)}**
${projectData.description || `A ${projectData.language} project built with modern best practices`}
[](LICENSE)
[]()
## โจ Features
${this.generateFeatures(projectType, projectData)}
## ๐ Quick Start
### Prerequisites
${this.generatePrerequisites(projectData)}
### Installation
\`\`\`bash
${this.generateInstallCommands(projectData)}
\`\`\`
### Running the Application
${this.generateUsageExample(projectData, projectType)}
## ๐ Project Structure
\`\`\`
${this.generateProjectStructure(projectData)}
\`\`\`
## ๐ง Configuration
${this.generateConfigurationSection(projectData)}
## ๐ API Documentation
${this.generateApiDocumentation(projectData)}
## ๐ ๏ธ Tech Stack
${this.generateTechStackDetails(techStack)}
## ๐ Documentation
- [Getting Started](#-quick-start)
- [Configuration](#configuration)
- [API Reference](#api-reference)
- [Examples](#examples)
## ๐ค Contributing
1. Fork the repository
2. Create your feature branch (\`git checkout -b feature/amazing-feature\`)
3. Commit your changes (\`git commit -m 'Add amazing feature'\`)
4. Push to the branch (\`git push origin feature/amazing-feature\`)
5. Open a Pull Request
## ๐ License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## ๐ Acknowledgments
- Built with ${projectData.language}
- Thanks to all contributors
- Inspired by modern development practices
---
Made with โค๏ธ by the ${projectData.name} team
REQUIREMENTS:
1. ANALYZE THE ACTUAL CODE - Don't use generic descriptions
2. Write about what this specific application actually does
3. Include real features found in the code
4. Use actual file names, component names, and functionality
5. Provide accurate installation and usage instructions
6. Use ONLY markdown syntax (no HTML)
7. Make it comprehensive but scannable
8. Include proper code formatting with language-specific syntax highlighting
9. Focus on clarity and professionalism`;
}
generateTagline(projectData, projectType) {
const taglines = {
'Frontend Application': `๐ Modern ${projectData.language} application with sleek UI/UX`,
'Backend API': `โก High-performance ${projectData.language} API built for scale`,
'Full-Stack Application': `๐ฅ Complete full-stack solution powered by ${projectData.language}`,
'CLI Tool': `๐ ๏ธ Powerful command-line tool for developers`,
'Library': `๐ Essential ${projectData.language} library for modern development`,
'Python Application': `๐ Robust Python application with enterprise features`,
'JavaScript/Node.js Project': `โก Modern JavaScript solution for the web`,
'default': `๐ Professional ${projectData.language} project`
};
return taglines[projectType] || taglines.default;
}
analyzeCodeStructure(projectData) {
const analysis = [];
// Analyze package.json for scripts and dependencies
const packageJson = projectData.files.find(f => f.name === 'package.json');
if (packageJson?.content) {
try {
const pkg = JSON.parse(packageJson.content);
if (pkg.scripts) {
analysis.push(`Available scripts: ${Object.keys(pkg.scripts).join(', ')}`);
}
if (pkg.bin) {
analysis.push(`CLI commands: ${Object.keys(pkg.bin).join(', ')}`);
}
}
catch (error) {
// Ignore parse errors
}
}
// Analyze main source files
const sourceFiles = projectData.files.filter(f => f.type === 'file' &&
(f.path.includes('src/') || f.path.includes('lib/') || f.name.includes('index') || f.name.includes('main')));
if (sourceFiles.length > 0) {
analysis.push(`Main source files: ${sourceFiles.map(f => f.name).join(', ')}`);
}
// Look for specific patterns
const hasRoutes = projectData.files.some(f => f.content?.includes('route') || f.path.includes('route'));
const hasComponents = projectData.files.some(f => f.path.includes('component') || f.content?.includes('component'));
const hasAPI = projectData.files.some(f => f.path.includes('api') || f.content?.includes('express') || f.content?.includes('fastify'));
const hasCLI = projectData.files.some(f => f.content?.includes('commander') || f.content?.includes('yargs') || f.content?.includes('#!/usr/bin/env'));
if (hasRoutes)
analysis.push('Contains routing functionality');
if (hasComponents)
analysis.push('Uses component-based architecture');
if (hasAPI)
analysis.push('Includes API/server functionality');
if (hasCLI)
analysis.push('Command-line interface detected');
return analysis.length > 0 ? analysis.join(', ') : 'Standard project structure';
}
generateFeatures(projectType, projectData) {
const features = {
'Frontend Application': `- ๐จ Modern, responsive design
- โก Optimized performance
- ๐ฑ Mobile-first approach
- ๐ง Easy customization
- ๐ Cross-browser compatibility`,
'Backend API': `- ๐ RESTful API endpoints
- ๐ Secure authentication
- ๐ Built-in monitoring
- ๐ Scalable architecture
- ๐ Auto-generated documentation`,
'CLI Tool': `- โก Fast execution
- ๐ฏ Intuitive commands
- ๐ File system integration
- ๐ง Configurable options
- ๐ป Cross-platform support`,
'default': `- โจ Clean, modern architecture
- ๐ High performance
- ๐ง Easy to extend
- ๐ Well documented
- ๐งช Thoroughly tested`
};
// TODO: Analyze actual code to generate specific features
// This should be enhanced to read actual functionality from the code
return features[projectType] || features.default;
}
generatePrerequisites(projectData) {
if (projectData.files.some(f => f.name === 'package.json')) {
return `- Node.js (v16 or higher)
- npm or yarn package manager
- Git for version control`;
}
if (projectData.files.some(f => f.name === 'requirements.txt')) {
return `- Python 3.8 or higher
- pip package manager
- Virtual environment (recommended)`;
}
if (projectData.files.some(f => f.name === 'Cargo.toml')) {
return `- Rust (latest stable version)
- Cargo package manager`;
}
return `- Git for version control
- Your favorite code editor
- Terminal/command line interface`;
}
generateInstallCommands(projectData) {
if (projectData.files.some(f => f.name === 'package.json')) {
return `# Clone the repository
git clone <repository-url>
cd ${projectData.name}
# Install dependencies
npm install
# Start development server
npm run dev`;
}
if (projectData.files.some(f => f.name === 'requirements.txt')) {
return `# Clone the repository
git clone <repository-url>
cd ${projectData.name}
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\\Scripts\\activate
# Install dependencies
pip install -r requirements.txt
# Run the application
python main.py`;
}
return `# Clone the repository
git clone <repository-url>
cd ${projectData.name}
# Follow language-specific setup instructions`;
}
generateUsageExample(projectData, projectType) {
if (projectType === 'CLI Tool') {
return `\`\`\`bash
# Basic usage
${projectData.name} --help
# Run with options
${projectData.name} --config config.json
\`\`\``;
}
return `\`\`\`bash
# Start the application
npm start
# Or for development
npm run dev
\`\`\``;
}
generateProjectStructure(projectData) {
const structure = projectData.files
.filter(f => f.type === 'directory' || this.isImportantFile(f.name))
.slice(0, 20)
.map(f => {
const indent = f.path.split('/').length - 1;
const prefix = ' '.repeat(indent);
const icon = f.type === 'directory' ? '๐' : '๐';
return `${prefix}${icon} ${f.name}`;
})
.join('\n');
return structure || `๐ ${projectData.name}/
๐ README.md
๐ package.json
๐ src/
๐ index.js`;
}
generateConfigurationSection(projectData) {
const configFiles = projectData.files.filter(f => f.name.includes('config') ||
f.name.startsWith('.env') ||
f.name === 'tsconfig.json' ||
f.name === 'tailwind.config.js' ||
f.name === 'vite.config.js');
if (configFiles.length === 0) {
return 'No specific configuration required. The application works with default settings.';
}
const configList = configFiles.map(f => `- \`${f.name}\`: Configuration file`).join('\n');
return `The following configuration files are available:\n\n${configList}\n\nRefer to each file for specific configuration options.`;
}
generateApiDocumentation(projectData) {
const hasAPI = projectData.files.some(f => f.path.includes('api') ||
f.content?.includes('express') ||
f.content?.includes('fastify') ||
f.content?.includes('router'));
if (!hasAPI) {
return 'This project does not include API endpoints.';
}
return `API endpoints are available. Check the source code for specific routes and documentation.
Common endpoints may include:
- \`GET /\` - Main application route
- Additional routes as defined in the source code
Refer to the API source files for complete documentation.`;
}
generateTechStackDetails(techStack) {
return `**Core Technologies:**
${techStack.split(', ').map(tech => `- ${tech}`).join('\n')}
**Development Tools:**
- Version Control: Git
- Code Quality: ESLint, Prettier
- Testing: Jest, Testing Library
- Documentation: README, JSDoc`;
}
detectTechStack(projectData) {
const techStack = [];
const packageJson = projectData.files.find(f => f.name === 'package.json');
if (packageJson?.content) {
try {
const pkg = JSON.parse(packageJson.content);
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
if (deps.react)
techStack.push('React');
if (deps.vue)
techStack.push('Vue.js');
if (deps.angular)
techStack.push('Angular');
if (deps.next)
techStack.push('Next.js');
if (deps.express)
techStack.push('Express.js');
if (deps.typescript)
techStack.push('TypeScript');
if (deps.tailwindcss)
techStack.push('Tailwind CSS');
if (deps.sass)
techStack.push('Sass');
if (deps.webpack)
techStack.push('Webpack');
if (deps.vite)
techStack.push('Vite');
}
catch (error) {
// Ignore parse errors
}
}
if (projectData.files.some(f => f.name === 'requirements.txt'))
techStack.push('Python');
if (projectData.files.some(f => f.name === 'Cargo.toml'))
techStack.push('Rust');
if (projectData.files.some(f => f.name === 'go.mod'))
techStack.push('Go');
if (projectData.files.some(f => f.name === 'Dockerfile'))
techStack.push('Docker');
return techStack.length > 0 ? techStack.join(', ') : projectData.language || 'Various Technologies';
}
detectProjectType(projectData) {
const packageJson = projectData.files.find(f => f.name === 'package.json');
if (packageJson?.content) {
try {
const pkg = JSON.parse(packageJson.content);
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
if (deps.react || deps.vue || deps.angular)
return 'Frontend Application';
if (deps.next || deps.nuxt || deps.gatsby)
return 'Full-Stack Application';
if (deps.express || deps.fastify || deps.koa)
return 'Backend API';
if (pkg.bin)
return 'CLI Tool';
if (pkg.main && !deps.express)
return 'Library';
}
catch (error) {
// Ignore parse errors
}
}
if (projectData.files.some(f => f.name === 'requirements.txt'))
return 'Python Application';
if (projectData.files.some(f => f.name === 'Cargo.toml'))
return 'Rust Application';
if (projectData.files.some(f => f.name === 'go.mod'))
return 'Go Application';
return 'Software Project';
}
isImportantFile(fileName) {
const important = [
'package.json', 'tsconfig.json', 'next.config.js', 'vite.config.js',
'requirements.txt', 'setup.py', 'Cargo.toml', 'go.mod', 'Dockerfile',
'README.md', 'LICENSE', '.env.example', 'config.js', 'index.js', 'main.py'
];
return important.includes(fileName);
}
cleanupGeneratedContent(content) {
return content
.replace(/^```markdown\s*\n/, '')
.replace(/\n```$/, '')
.replace(/\n{3,}/g, '\n\n')
.trim();
}
extractSections(content) {
const sections = [];
const lines = content.split('\n');
for (const line of lines) {
const trimmedLine = line.trim();
if (trimmedLine.startsWith('# ') || trimmedLine.startsWith('## ')) {
const sectionName = trimmedLine.replace(/^#+\s*/, '').replace(/[^\w\s]/g, '').trim();
if (sectionName) {
sections.push(sectionName);
}
}
}
return sections;
}
}
exports.GeminiService = GeminiService;
//# sourceMappingURL=geminiService.js.map