-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
183 lines (162 loc) · 5.52 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#!/usr/bin/env node
import inquirer from "inquirer";
import fs from "fs";
import OpenAI from "openai";
import dotenv from "dotenv";
import path from "path";
// Determine which .env file to use
const envFilePath = fs.existsSync(path.join(process.cwd(), ".env.local"))
? ".env.local"
: ".env";
// Load environment variables from the determined file
dotenv.config({ path: envFilePath });
// Initialize OpenAI with a placeholder API key
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY || "", // Empty key to handle errors later
});
// Function to ask for the API key source
const apiKeyQuestions = [
{
type: "list",
name: "envOption",
message: "How would you like to provide the OpenAI API key?",
choices: [
"Use .env file (recommended)",
"Use .env.local file",
"Paste the API key manually (not recommended)",
],
},
];
// Add the option to select the OpenAI model
const modelQuestion = [
{
type: "list",
name: "model",
message:
"Which OpenAI model do you want to use for generating the README? (Note: Mini is cheaper, 40 is more expensive but provides better output)",
choices: [
{ name: "gpt-4o-mini (Cheaper)", value: "gpt-4o-mini" },
{ name: "gpt-4o (Better Output)", value: "gpt-4o" },
],
},
];
// Main questions for README generation
const questions = [
{
type: "input",
name: "projectName",
message: "What is the name of your project?",
},
{
type: "input",
name: "description",
message:
"Describe your project (Tip: The more detailed your description, the better your README will be):",
},
{
type: "input",
name: "installation",
message:
"What are the installation steps? (Skipping this might lead to a 20% chance of inaccuracies)",
default: "",
},
{
type: "input",
name: "usage",
message:
"How do you use the project? (Skipping this might lead to a 20% chance of inaccuracies)",
default: "",
},
{
type: "list",
name: "license",
message: "Which license does your project use?",
choices: ["MIT", "GPLv3", "Apache License 2.0", "BSD 3-Clause", "None"],
},
{
type: "confirm",
name: "emojis",
message: "Do you want to include emojis in your README?",
default: true,
},
{
type: "input",
name: "customNotes",
message:
"Any specific preferences for the tone or style of the README? (e.g., witty, funny, arrogant, formal) [optional]",
default: "",
},
];
// Function to get the OpenAI response
async function getGPTResponse(prompt, model) {
const completion = await openai.chat.completions.create({
model,
messages: [{ role: "system", content: prompt }],
max_tokens: 1500,
});
return completion.choices[0].message.content;
}
// Function to generate README content based on user input and package.json
async function generateReadme(answers, model) {
const packageJsonPath = path.join(process.cwd(), "package.json");
let packageJsonContent = "";
if (fs.existsSync(packageJsonPath)) {
const packageJson = fs.readFileSync(packageJsonPath, "utf-8");
packageJsonContent = `Here is the content of package.json for reference:\n${packageJson}\n`;
}
const prompt = `
Create the most beautiful, articulate, and detailed README.md you can imagine.
Use this information to guide you:
Project name: ${answers.projectName}
Description: ${answers.description}
Installation steps: ${answers.installation || "N/A"}
Usage instructions: ${answers.usage || "N/A"}
License: ${answers.license}
${answers.emojis ? "Include emojis in each section." : "No emojis needed."}
Additional Notes: ${answers.customNotes || "None"}
${packageJsonContent}
Use the package.json as a reference to enhance the quality and technical accuracy of the README.
Make sure the README is professional, clear, and has a stunning structure, with sections for installation, usage, and any relevant notes about dependencies, project architecture, and any additional features.
`;
// Check how user wants to load API key (from env or manually)
const apiKeySource = await inquirer.prompt(apiKeyQuestions);
let apiKey;
if (apiKeySource.envOption === "Use .env file (recommended)") {
dotenv.config({ path: ".env" }); // Automatically load .env
apiKey = process.env.OPENAI_API_KEY;
} else if (apiKeySource.envOption === "Use .env.local file") {
dotenv.config({ path: ".env.local" }); // Automatically load .env.local
apiKey = process.env.OPENAI_API_KEY;
} else {
const apiKeyManual = await inquirer.prompt({
type: "input",
name: "apiKey",
message: "Paste your OpenAI API key:",
});
apiKey = apiKeyManual.apiKey;
}
// Handle missing API key scenario
if (!apiKey) {
console.log(
"API key not found. Please make sure it is provided correctly."
);
process.exit(1);
}
// Set the API key for OpenAI instance
openai.apiKey = apiKey;
const readmeContent = await getGPTResponse(prompt, model);
return readmeContent;
}
// Function to write the generated content to README.md
function createReadme(content) {
fs.writeFileSync("README.md", content);
console.log("README.md has been generated successfully!");
}
// Main CLI interaction
inquirer.prompt(questions).then(async (answers) => {
// Ask the user to select the model
const modelAnswer = await inquirer.prompt(modelQuestion);
// Generate the README based on the selected model and user answers
const readmeContent = await generateReadme(answers, modelAnswer.model);
createReadme(readmeContent);
});