@codebakers/cli 1.0.10 → 1.1.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/index.js +70 -114
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import chalk2 from "chalk";
|
|
|
14
14
|
import inquirer from "inquirer";
|
|
15
15
|
import chalk from "chalk";
|
|
16
16
|
import ora from "ora";
|
|
17
|
-
import { writeFile, mkdir } from "fs/promises";
|
|
17
|
+
import { writeFile, mkdir, readFile } from "fs/promises";
|
|
18
18
|
import { existsSync } from "fs";
|
|
19
19
|
import { join } from "path";
|
|
20
20
|
|
|
@@ -63,7 +63,13 @@ async function validateApiKey(apiKey) {
|
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
65
|
if (response.ok) {
|
|
66
|
-
|
|
66
|
+
try {
|
|
67
|
+
const data = await response.json();
|
|
68
|
+
const user = data.user;
|
|
69
|
+
return { valid: true, userName: user?.name || void 0 };
|
|
70
|
+
} catch {
|
|
71
|
+
return { valid: true };
|
|
72
|
+
}
|
|
67
73
|
}
|
|
68
74
|
try {
|
|
69
75
|
const data = await response.json();
|
|
@@ -85,36 +91,15 @@ async function fetchPatterns(patterns) {
|
|
|
85
91
|
body: JSON.stringify({ patterns })
|
|
86
92
|
});
|
|
87
93
|
}
|
|
88
|
-
async function fetchAllPatterns() {
|
|
89
|
-
const list = await listPatterns();
|
|
90
|
-
const allPatterns = {};
|
|
91
|
-
const patternNames = list.patterns.map((p) => p.name);
|
|
92
|
-
for (let i = 0; i < patternNames.length; i += 5) {
|
|
93
|
-
const batch = patternNames.slice(i, i + 5);
|
|
94
|
-
const result = await fetchPatterns(batch);
|
|
95
|
-
Object.assign(allPatterns, result.patterns);
|
|
96
|
-
}
|
|
97
|
-
const routerResult = await fetchPatterns(["router"]);
|
|
98
|
-
Object.assign(allPatterns, routerResult.patterns);
|
|
99
|
-
return allPatterns;
|
|
100
|
-
}
|
|
101
94
|
|
|
102
95
|
// src/commands/setup.ts
|
|
103
96
|
var IDE_CONFIGS = {
|
|
104
97
|
cursor: {
|
|
105
|
-
file: ".
|
|
98
|
+
file: ".cursor/mcp.json",
|
|
106
99
|
description: "Cursor AI IDE"
|
|
107
100
|
},
|
|
108
|
-
windsurf: {
|
|
109
|
-
file: ".windsurfrules",
|
|
110
|
-
description: "Windsurf (Codeium) IDE"
|
|
111
|
-
},
|
|
112
|
-
aider: {
|
|
113
|
-
file: ".aider.conf.yml",
|
|
114
|
-
description: "Aider CLI"
|
|
115
|
-
},
|
|
116
101
|
"claude-code": {
|
|
117
|
-
file: "
|
|
102
|
+
file: ".claude/mcp.json",
|
|
118
103
|
description: "Claude Code"
|
|
119
104
|
}
|
|
120
105
|
};
|
|
@@ -172,6 +157,7 @@ Validation failed: ${validation.error || "Unknown error"}`));
|
|
|
172
157
|
}
|
|
173
158
|
process.exit(1);
|
|
174
159
|
}
|
|
160
|
+
const userName = validation.userName;
|
|
175
161
|
spinner.succeed("API key validated");
|
|
176
162
|
setApiKey(apiKey);
|
|
177
163
|
console.log(chalk.green("\n\u2713 API key saved\n"));
|
|
@@ -185,8 +171,6 @@ Validation failed: ${validation.error || "Unknown error"}`));
|
|
|
185
171
|
choices: [
|
|
186
172
|
{ name: "Cursor", value: "cursor" },
|
|
187
173
|
{ name: "Claude Code (VS Code extension or CLI)", value: "claude-code" },
|
|
188
|
-
{ name: "Windsurf (Codeium)", value: "windsurf" },
|
|
189
|
-
{ name: "Aider", value: "aider" },
|
|
190
174
|
{ name: "Skip for now", value: null }
|
|
191
175
|
]
|
|
192
176
|
}
|
|
@@ -196,9 +180,16 @@ Validation failed: ${validation.error || "Unknown error"}`));
|
|
|
196
180
|
if (ide) {
|
|
197
181
|
await configureIDE(ide, options.force);
|
|
198
182
|
}
|
|
183
|
+
const firstName = userName?.split(" ")[0];
|
|
184
|
+
const greeting = firstName ? `${firstName}, you're` : "You're";
|
|
199
185
|
console.log(chalk.bold.green("\n\u{1F389} Setup complete!\n"));
|
|
200
|
-
if (ide
|
|
201
|
-
console.log(chalk.green(
|
|
186
|
+
if (ide) {
|
|
187
|
+
console.log(chalk.green(`\u2713 ${greeting} ready to build!
|
|
188
|
+
`));
|
|
189
|
+
console.log(chalk.bold("How it works:"));
|
|
190
|
+
console.log(chalk.dim(" 1. Patterns are fetched securely from CodeBakers API"));
|
|
191
|
+
console.log(chalk.dim(" 2. No files stored locally - your subscription is protected"));
|
|
192
|
+
console.log(chalk.dim(" 3. Always get the latest patterns automatically\n"));
|
|
202
193
|
console.log(chalk.bold("You say:"));
|
|
203
194
|
console.log(chalk.cyan(' "Add a contact form"\n'));
|
|
204
195
|
console.log(chalk.bold("CodeBakers generates:"));
|
|
@@ -213,110 +204,75 @@ Validation failed: ${validation.error || "Unknown error"}`));
|
|
|
213
204
|
console.log(chalk.dim(" \u2502 ") + chalk.green("\u2713") + chalk.dim(" Accessible, responsive design \u2502"));
|
|
214
205
|
console.log(chalk.dim(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n"));
|
|
215
206
|
console.log(chalk.dim("Start building: just describe what you need.\n"));
|
|
216
|
-
} else if (ide) {
|
|
217
|
-
console.log(chalk.dim(`Pattern file created. Restart ${IDE_CONFIGS[ide].description} to load it.
|
|
218
|
-
`));
|
|
219
207
|
}
|
|
220
208
|
});
|
|
221
209
|
}
|
|
222
210
|
async function configureIDE(ide, force = false) {
|
|
223
211
|
const config = IDE_CONFIGS[ide];
|
|
224
|
-
const
|
|
225
|
-
const spinner = ora(`Fetching CodeBakers patterns...`).start();
|
|
212
|
+
const spinner = ora(`Configuring ${config.description}...`).start();
|
|
226
213
|
try {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
214
|
+
await configureMCP(ide, force, spinner);
|
|
215
|
+
} catch (error) {
|
|
216
|
+
spinner.fail("Failed to configure IDE");
|
|
217
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
218
|
+
console.log(chalk.red(`
|
|
219
|
+
Error: ${message}`));
|
|
220
|
+
process.exit(1);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
async function configureMCP(ide, force, spinner) {
|
|
224
|
+
const config = IDE_CONFIGS[ide];
|
|
225
|
+
const targetDir = join(process.cwd(), ide === "cursor" ? ".cursor" : ".claude");
|
|
226
|
+
const targetPath = join(targetDir, "mcp.json");
|
|
227
|
+
if (!existsSync(targetDir)) {
|
|
228
|
+
await mkdir(targetDir, { recursive: true });
|
|
229
|
+
}
|
|
230
|
+
let existingConfig = {};
|
|
231
|
+
if (existsSync(targetPath)) {
|
|
232
|
+
if (!force) {
|
|
234
233
|
spinner.stop();
|
|
235
|
-
const {
|
|
234
|
+
const { merge } = await inquirer.prompt([
|
|
236
235
|
{
|
|
237
236
|
type: "confirm",
|
|
238
|
-
name: "
|
|
239
|
-
message: `${config.file}
|
|
240
|
-
default:
|
|
237
|
+
name: "merge",
|
|
238
|
+
message: `${config.file} exists. Add CodeBakers to existing config?`,
|
|
239
|
+
default: true
|
|
241
240
|
}
|
|
242
241
|
]);
|
|
243
|
-
if (!
|
|
244
|
-
console.log(chalk.yellow("\nSetup cancelled.
|
|
242
|
+
if (!merge) {
|
|
243
|
+
console.log(chalk.yellow("\nSetup cancelled."));
|
|
245
244
|
return;
|
|
246
245
|
}
|
|
247
246
|
spinner.start();
|
|
248
247
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
if (ide === "claude-code") {
|
|
254
|
-
content = patterns["router"] || "";
|
|
255
|
-
for (const [name, patternContent] of Object.entries(patterns)) {
|
|
256
|
-
if (name !== "router") {
|
|
257
|
-
const patternPath = join(process.cwd(), ".claude", `${name}.md`);
|
|
258
|
-
await writeFile(patternPath, patternContent, "utf-8");
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
} else if (ide === "aider") {
|
|
262
|
-
content = generateAiderConfig(patterns);
|
|
263
|
-
} else {
|
|
264
|
-
content = generateRulesFile(patterns, patternList.version);
|
|
265
|
-
}
|
|
266
|
-
await writeFile(targetPath, content, "utf-8");
|
|
267
|
-
spinner.succeed(`Created ${config.file}`);
|
|
268
|
-
if (ide === "claude-code") {
|
|
269
|
-
console.log(chalk.dim(` + Created .claude/ folder with ${Object.keys(patterns).length - 1} pattern files`));
|
|
248
|
+
try {
|
|
249
|
+
const existing = await readFile(targetPath, "utf-8");
|
|
250
|
+
existingConfig = JSON.parse(existing);
|
|
251
|
+
} catch {
|
|
270
252
|
}
|
|
271
|
-
console.log(chalk.green(`
|
|
272
|
-
\u2713 ${IDE_CONFIGS[ide].description} configured`));
|
|
273
|
-
} catch (error) {
|
|
274
|
-
spinner.fail("Failed to configure IDE");
|
|
275
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
276
|
-
console.log(chalk.red(`
|
|
277
|
-
Error: ${message}`));
|
|
278
|
-
process.exit(1);
|
|
279
253
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
---
|
|
290
|
-
|
|
291
|
-
# PATTERN MODULES (Auto-loaded based on context)
|
|
292
|
-
|
|
293
|
-
`;
|
|
294
|
-
for (const [name, patternContent] of Object.entries(patterns)) {
|
|
295
|
-
if (name !== "router" && patternContent) {
|
|
296
|
-
content += `
|
|
297
|
-
## Module: ${name}
|
|
298
|
-
|
|
299
|
-
${patternContent}
|
|
300
|
-
|
|
301
|
-
---
|
|
302
|
-
`;
|
|
254
|
+
spinner.text = "Configuring MCP server...";
|
|
255
|
+
const mcpConfig = {
|
|
256
|
+
...existingConfig,
|
|
257
|
+
mcpServers: {
|
|
258
|
+
...existingConfig.mcpServers || {},
|
|
259
|
+
codebakers: {
|
|
260
|
+
command: "npx",
|
|
261
|
+
args: ["@codebakers/cli", "serve"]
|
|
262
|
+
}
|
|
303
263
|
}
|
|
264
|
+
};
|
|
265
|
+
await writeFile(targetPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
|
|
266
|
+
spinner.succeed(`Configured MCP server in ${config.file}`);
|
|
267
|
+
console.log(chalk.green(`
|
|
268
|
+
\u2713 ${config.description} configured with MCP`));
|
|
269
|
+
console.log(chalk.dim("\nPatterns are fetched securely from the API on-demand."));
|
|
270
|
+
console.log(chalk.dim("No pattern files are stored locally.\n"));
|
|
271
|
+
if (ide === "cursor") {
|
|
272
|
+
console.log(chalk.yellow("Restart Cursor to activate the MCP server.\n"));
|
|
273
|
+
} else {
|
|
274
|
+
console.log(chalk.yellow("Restart your IDE to activate the MCP server.\n"));
|
|
304
275
|
}
|
|
305
|
-
return content;
|
|
306
|
-
}
|
|
307
|
-
function generateAiderConfig(patterns) {
|
|
308
|
-
const router = patterns["router"] || "";
|
|
309
|
-
return `# CodeBakers Aider Configuration
|
|
310
|
-
# Generated by @codebakers/cli
|
|
311
|
-
# https://codebakers.ai
|
|
312
|
-
|
|
313
|
-
read:
|
|
314
|
-
- .codebakers-patterns.md
|
|
315
|
-
|
|
316
|
-
# System message with CodeBakers patterns
|
|
317
|
-
message: |
|
|
318
|
-
${router.split("\n").map((line) => " " + line).join("\n")}
|
|
319
|
-
`;
|
|
320
276
|
}
|
|
321
277
|
|
|
322
278
|
// src/commands/serve.ts
|