@codebakers/cli 3.8.1 → 3.8.3
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/commands/build.d.ts +27 -0
- package/dist/commands/build.js +325 -0
- package/dist/commands/init.d.ts +0 -3
- package/dist/commands/init.js +578 -550
- package/dist/commands/install.js +14 -15
- package/dist/commands/upgrade.d.ts +1 -1
- package/dist/commands/upgrade.js +57 -313
- package/dist/index.js +27 -154
- package/package.json +1 -1
- package/src/commands/build.ts +425 -0
- package/src/commands/init.ts +606 -559
- package/src/commands/install.ts +14 -15
- package/src/commands/upgrade.ts +60 -369
- package/src/index.ts +29 -188
package/src/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ import { pushPatterns, pushPatternsInteractive } from './commands/push-patterns.
|
|
|
23
23
|
import { go } from './commands/go.js';
|
|
24
24
|
import { extend } from './commands/extend.js';
|
|
25
25
|
import { billing } from './commands/billing.js';
|
|
26
|
+
import { build, buildStatus } from './commands/build.js';
|
|
26
27
|
import { getCachedUpdateInfo, setCachedUpdateInfo, getCliVersion, getCachedPatternInfo, setCachedPatternInfo, getApiKey, getApiUrl, getTrialState, hasValidAccess, shouldAttemptCliUpdate, setCliUpdateAttempt, isCliAutoUpdateDisabled } from './config.js';
|
|
27
28
|
import { execSync } from 'child_process';
|
|
28
29
|
import { checkForUpdates } from './lib/api.js';
|
|
@@ -164,180 +165,6 @@ async function autoUpdateCli(): Promise<void> {
|
|
|
164
165
|
}
|
|
165
166
|
}
|
|
166
167
|
|
|
167
|
-
// ============================================
|
|
168
|
-
// Automatic Pattern Updates
|
|
169
|
-
// ============================================
|
|
170
|
-
|
|
171
|
-
interface PatternVersionInfo {
|
|
172
|
-
version: string;
|
|
173
|
-
moduleCount: number;
|
|
174
|
-
updatedAt: string;
|
|
175
|
-
cliVersion: string;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
interface ContentResponse {
|
|
179
|
-
version: string;
|
|
180
|
-
router: string;
|
|
181
|
-
modules: Record<string, string>;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
function getLocalPatternVersion(): string | null {
|
|
185
|
-
const cwd = process.cwd();
|
|
186
|
-
const versionFile = join(cwd, '.claude', '.version.json');
|
|
187
|
-
|
|
188
|
-
if (!existsSync(versionFile)) return null;
|
|
189
|
-
|
|
190
|
-
try {
|
|
191
|
-
const content = readFileSync(versionFile, 'utf-8');
|
|
192
|
-
const info: PatternVersionInfo = JSON.parse(content);
|
|
193
|
-
return info.version;
|
|
194
|
-
} catch {
|
|
195
|
-
return null;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function isCodeBakersProject(): boolean {
|
|
200
|
-
const cwd = process.cwd();
|
|
201
|
-
return existsSync(join(cwd, 'CLAUDE.md')) || existsSync(join(cwd, '.claude'));
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
async function autoUpdatePatterns(): Promise<void> {
|
|
205
|
-
// Only auto-update if this is a CodeBakers project
|
|
206
|
-
if (!isCodeBakersProject()) return;
|
|
207
|
-
|
|
208
|
-
// Only auto-update if user has valid access
|
|
209
|
-
if (!hasValidAccess()) return;
|
|
210
|
-
|
|
211
|
-
const localVersion = getLocalPatternVersion();
|
|
212
|
-
|
|
213
|
-
// Check if we have a valid cached result first (fast path)
|
|
214
|
-
const cached = getCachedPatternInfo();
|
|
215
|
-
if (cached) {
|
|
216
|
-
// If local matches latest, nothing to do
|
|
217
|
-
if (localVersion === cached.latestVersion) return;
|
|
218
|
-
// If we know there's an update but haven't updated yet, do it now
|
|
219
|
-
if (localVersion !== cached.latestVersion) {
|
|
220
|
-
await performPatternUpdate(cached.latestVersion);
|
|
221
|
-
}
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Fetch from server to check for updates (with timeout)
|
|
226
|
-
try {
|
|
227
|
-
const controller = new AbortController();
|
|
228
|
-
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
229
|
-
|
|
230
|
-
const apiUrl = getApiUrl();
|
|
231
|
-
const apiKey = getApiKey();
|
|
232
|
-
const trial = getTrialState();
|
|
233
|
-
|
|
234
|
-
// Build authorization header
|
|
235
|
-
let authHeader = '';
|
|
236
|
-
if (apiKey) {
|
|
237
|
-
authHeader = `Bearer ${apiKey}`;
|
|
238
|
-
} else if (trial?.trialId) {
|
|
239
|
-
authHeader = `Trial ${trial.trialId}`;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if (!authHeader) return;
|
|
243
|
-
|
|
244
|
-
// First, check the version endpoint (lightweight)
|
|
245
|
-
const versionResponse = await fetch(`${apiUrl}/api/content/version`, {
|
|
246
|
-
method: 'GET',
|
|
247
|
-
headers: {
|
|
248
|
-
'Authorization': authHeader,
|
|
249
|
-
},
|
|
250
|
-
signal: controller.signal,
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
clearTimeout(timeout);
|
|
254
|
-
|
|
255
|
-
if (versionResponse.ok) {
|
|
256
|
-
const versionData = await versionResponse.json();
|
|
257
|
-
const serverVersion = versionData.version;
|
|
258
|
-
|
|
259
|
-
// Cache the version info
|
|
260
|
-
setCachedPatternInfo(serverVersion);
|
|
261
|
-
|
|
262
|
-
// If local version is different, update
|
|
263
|
-
if (localVersion !== serverVersion) {
|
|
264
|
-
await performPatternUpdate(serverVersion);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
} catch {
|
|
268
|
-
// Silently fail - don't block CLI for pattern check
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
async function performPatternUpdate(targetVersion: string): Promise<void> {
|
|
273
|
-
const cwd = process.cwd();
|
|
274
|
-
const claudeMdPath = join(cwd, 'CLAUDE.md');
|
|
275
|
-
const claudeDir = join(cwd, '.claude');
|
|
276
|
-
|
|
277
|
-
try {
|
|
278
|
-
const apiUrl = getApiUrl();
|
|
279
|
-
const apiKey = getApiKey();
|
|
280
|
-
const trial = getTrialState();
|
|
281
|
-
|
|
282
|
-
let authHeader = '';
|
|
283
|
-
if (apiKey) {
|
|
284
|
-
authHeader = `Bearer ${apiKey}`;
|
|
285
|
-
} else if (trial?.trialId) {
|
|
286
|
-
authHeader = `Trial ${trial.trialId}`;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if (!authHeader) return;
|
|
290
|
-
|
|
291
|
-
const controller = new AbortController();
|
|
292
|
-
const timeout = setTimeout(() => controller.abort(), 10000);
|
|
293
|
-
|
|
294
|
-
const response = await fetch(`${apiUrl}/api/content`, {
|
|
295
|
-
method: 'GET',
|
|
296
|
-
headers: {
|
|
297
|
-
'Authorization': authHeader,
|
|
298
|
-
},
|
|
299
|
-
signal: controller.signal,
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
clearTimeout(timeout);
|
|
303
|
-
|
|
304
|
-
if (!response.ok) return;
|
|
305
|
-
|
|
306
|
-
const content: ContentResponse = await response.json();
|
|
307
|
-
|
|
308
|
-
// Update CLAUDE.md
|
|
309
|
-
if (content.router) {
|
|
310
|
-
writeFileSync(claudeMdPath, content.router);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// Update pattern modules
|
|
314
|
-
if (content.modules && Object.keys(content.modules).length > 0) {
|
|
315
|
-
if (!existsSync(claudeDir)) {
|
|
316
|
-
mkdirSync(claudeDir, { recursive: true });
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
for (const [name, data] of Object.entries(content.modules)) {
|
|
320
|
-
writeFileSync(join(claudeDir, name), data);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Write version file
|
|
325
|
-
const moduleCount = Object.keys(content.modules || {}).length;
|
|
326
|
-
const versionInfo: PatternVersionInfo = {
|
|
327
|
-
version: content.version,
|
|
328
|
-
moduleCount,
|
|
329
|
-
updatedAt: new Date().toISOString(),
|
|
330
|
-
cliVersion: getCliVersion(),
|
|
331
|
-
};
|
|
332
|
-
writeFileSync(join(claudeDir, '.version.json'), JSON.stringify(versionInfo, null, 2));
|
|
333
|
-
|
|
334
|
-
// Show subtle notification
|
|
335
|
-
console.log(chalk.green(` ✓ Patterns auto-updated to v${content.version} (${moduleCount} modules)\n`));
|
|
336
|
-
|
|
337
|
-
} catch {
|
|
338
|
-
// Silently fail - don't block the user
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
168
|
|
|
342
169
|
// Show welcome message when no command is provided
|
|
343
170
|
function showWelcome(): void {
|
|
@@ -353,22 +180,23 @@ function showWelcome(): void {
|
|
|
353
180
|
|
|
354
181
|
console.log(chalk.white(' Getting Started:\n'));
|
|
355
182
|
console.log(chalk.cyan(' codebakers go') + chalk.gray(' Start free trial instantly (no signup!)'));
|
|
183
|
+
console.log(chalk.cyan(' codebakers build') + chalk.gray(' Describe your project → Get working code'));
|
|
356
184
|
console.log(chalk.cyan(' codebakers scaffold') + chalk.gray(' Create a new project from scratch'));
|
|
357
|
-
console.log(chalk.cyan(' codebakers init') + chalk.gray('
|
|
185
|
+
console.log(chalk.cyan(' codebakers init') + chalk.gray(' Set up CodeBakers in existing project\n'));
|
|
358
186
|
|
|
359
187
|
console.log(chalk.white(' Development:\n'));
|
|
360
188
|
console.log(chalk.cyan(' codebakers generate') + chalk.gray(' Generate components, APIs, services'));
|
|
361
|
-
console.log(chalk.cyan(' codebakers upgrade') + chalk.gray('
|
|
362
|
-
console.log(chalk.cyan(' codebakers status') + chalk.gray(' Check
|
|
189
|
+
console.log(chalk.cyan(' codebakers upgrade') + chalk.gray(' Check for CLI updates'));
|
|
190
|
+
console.log(chalk.cyan(' codebakers status') + chalk.gray(' Check project status'));
|
|
363
191
|
console.log(chalk.cyan(' codebakers config') + chalk.gray(' View or modify configuration\n'));
|
|
364
192
|
|
|
365
193
|
console.log(chalk.white(' Examples:\n'));
|
|
194
|
+
console.log(chalk.gray(' $ ') + chalk.cyan('codebakers build "SaaS for invoicing"'));
|
|
195
|
+
console.log(chalk.gray(' AI generates full project with auth, payments, dashboard\n'));
|
|
366
196
|
console.log(chalk.gray(' $ ') + chalk.cyan('codebakers scaffold'));
|
|
367
197
|
console.log(chalk.gray(' Create a new Next.js + Supabase + Drizzle project\n'));
|
|
368
198
|
console.log(chalk.gray(' $ ') + chalk.cyan('codebakers generate component Button'));
|
|
369
199
|
console.log(chalk.gray(' Generate a React component with TypeScript\n'));
|
|
370
|
-
console.log(chalk.gray(' $ ') + chalk.cyan('codebakers g api users'));
|
|
371
|
-
console.log(chalk.gray(' Generate a Next.js API route with validation\n'));
|
|
372
200
|
|
|
373
201
|
console.log(chalk.white(' Quality:\n'));
|
|
374
202
|
console.log(chalk.cyan(' codebakers audit') + chalk.gray(' Run automated code quality checks'));
|
|
@@ -376,9 +204,9 @@ function showWelcome(): void {
|
|
|
376
204
|
console.log(chalk.cyan(' codebakers doctor') + chalk.gray(' Check CodeBakers setup\n'));
|
|
377
205
|
|
|
378
206
|
console.log(chalk.white(' All Commands:\n'));
|
|
379
|
-
console.log(chalk.gray(' go, extend, billing,
|
|
380
|
-
console.log(chalk.gray(' audit, heal, doctor, config, login
|
|
381
|
-
console.log(chalk.gray('
|
|
207
|
+
console.log(chalk.gray(' go, extend, billing, build, build-status, setup, scaffold, init'));
|
|
208
|
+
console.log(chalk.gray(' generate, upgrade, status, audit, heal, doctor, config, login'));
|
|
209
|
+
console.log(chalk.gray(' serve, mcp-config, mcp-uninstall\n'));
|
|
382
210
|
|
|
383
211
|
console.log(chalk.gray(' Run ') + chalk.cyan('codebakers <command> --help') + chalk.gray(' for more info\n'));
|
|
384
212
|
}
|
|
@@ -409,6 +237,23 @@ program
|
|
|
409
237
|
.description('Manage subscription or upgrade to paid plan')
|
|
410
238
|
.action(billing);
|
|
411
239
|
|
|
240
|
+
// AI Build command - describe what you want, get working code
|
|
241
|
+
program
|
|
242
|
+
.command('build [description]')
|
|
243
|
+
.description('Build a project from description - AI generates actual files')
|
|
244
|
+
.option('-o, --output <dir>', 'Output directory (default: current directory)')
|
|
245
|
+
.option('-v, --verbose', 'Show detailed progress')
|
|
246
|
+
.action((description, options) => build({
|
|
247
|
+
description,
|
|
248
|
+
output: options.output,
|
|
249
|
+
verbose: options.verbose,
|
|
250
|
+
}));
|
|
251
|
+
|
|
252
|
+
program
|
|
253
|
+
.command('build-status')
|
|
254
|
+
.description('Check status of recent builds')
|
|
255
|
+
.action(buildStatus);
|
|
256
|
+
|
|
412
257
|
// Primary command - one-time setup (for paid users)
|
|
413
258
|
program
|
|
414
259
|
.command('setup')
|
|
@@ -549,14 +394,10 @@ program
|
|
|
549
394
|
// Add update check hook (runs before every command)
|
|
550
395
|
program.hook('preAction', async () => {
|
|
551
396
|
// Run CLI auto-update first (if enabled and conditions met)
|
|
552
|
-
// Then run pattern auto-update in parallel with update banner check
|
|
553
397
|
await autoUpdateCli();
|
|
554
398
|
|
|
555
|
-
//
|
|
556
|
-
await
|
|
557
|
-
checkForUpdatesInBackground(),
|
|
558
|
-
autoUpdatePatterns(),
|
|
559
|
-
]);
|
|
399
|
+
// Check for CLI updates in background
|
|
400
|
+
await checkForUpdatesInBackground();
|
|
560
401
|
});
|
|
561
402
|
|
|
562
403
|
// Show welcome if no command provided
|