aerocoding 0.1.28 → 0.1.29
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 +247 -104
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1115,8 +1115,12 @@ var projectConfigSchema = z.object({
|
|
|
1115
1115
|
$schema: z.string().optional().default("https://aerocoding.dev/schema.json"),
|
|
1116
1116
|
/** Project UUID from aerocoding.dev */
|
|
1117
1117
|
projectId: z.string().uuid(),
|
|
1118
|
-
/** Template ID for architecture generation */
|
|
1118
|
+
/** Template ID for architecture generation (legacy, prefer backendTemplateId/frontendTemplateId) */
|
|
1119
1119
|
templateId: z.string().min(1),
|
|
1120
|
+
/** Backend template ID */
|
|
1121
|
+
backendTemplateId: z.string().min(1).optional(),
|
|
1122
|
+
/** Frontend template ID */
|
|
1123
|
+
frontendTemplateId: z.string().min(1).optional(),
|
|
1120
1124
|
/** Template version at project creation */
|
|
1121
1125
|
templateVersion: z.string().optional(),
|
|
1122
1126
|
/** Root namespace/package name */
|
|
@@ -1149,6 +1153,8 @@ function createProjectConfig(options) {
|
|
|
1149
1153
|
$schema: "https://aerocoding.dev/schema.json",
|
|
1150
1154
|
projectId: options.projectId,
|
|
1151
1155
|
templateId: options.templateId,
|
|
1156
|
+
backendTemplateId: options.backendTemplateId,
|
|
1157
|
+
frontendTemplateId: options.frontendTemplateId,
|
|
1152
1158
|
templateVersion: options.templateVersion,
|
|
1153
1159
|
namespace: options.namespace,
|
|
1154
1160
|
organizationId: options.organizationId,
|
|
@@ -1316,32 +1322,65 @@ async function createCommand(projectName, options) {
|
|
|
1316
1322
|
}
|
|
1317
1323
|
} catch {
|
|
1318
1324
|
}
|
|
1319
|
-
let
|
|
1320
|
-
|
|
1325
|
+
let backendTemplateId = options.template;
|
|
1326
|
+
const hasBackend = !!project.backendFramework;
|
|
1327
|
+
if (hasBackend && !backendTemplateId) {
|
|
1321
1328
|
const templateSpinner = p.spinner();
|
|
1322
|
-
templateSpinner.start("Loading templates...");
|
|
1329
|
+
templateSpinner.start("Loading backend templates...");
|
|
1323
1330
|
const templateResult = await apiClient.getTemplates({
|
|
1324
1331
|
category: "backend",
|
|
1325
1332
|
language: project.backendFramework || void 0
|
|
1326
1333
|
});
|
|
1327
|
-
templateSpinner.stop("
|
|
1334
|
+
templateSpinner.stop("Backend templates loaded");
|
|
1328
1335
|
if (templateResult.templates.length === 0) {
|
|
1329
|
-
p.
|
|
1330
|
-
|
|
1336
|
+
p.log.warn("No backend templates available for this project's framework.");
|
|
1337
|
+
} else {
|
|
1338
|
+
const selectedTemplate = await p.select({
|
|
1339
|
+
message: "Select backend architecture template",
|
|
1340
|
+
options: templateResult.templates.map((tmpl) => ({
|
|
1341
|
+
value: tmpl.id,
|
|
1342
|
+
label: tmpl.name,
|
|
1343
|
+
hint: tmpl.description || `${tmpl.tier} tier`
|
|
1344
|
+
}))
|
|
1345
|
+
});
|
|
1346
|
+
if (p.isCancel(selectedTemplate)) {
|
|
1347
|
+
p.cancel("Operation cancelled.");
|
|
1348
|
+
process.exit(0);
|
|
1349
|
+
}
|
|
1350
|
+
backendTemplateId = selectedTemplate;
|
|
1331
1351
|
}
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1352
|
+
}
|
|
1353
|
+
let frontendTemplateId;
|
|
1354
|
+
const hasFrontend = !!project.frontendFramework;
|
|
1355
|
+
if (hasFrontend) {
|
|
1356
|
+
const frontendSpinner = p.spinner();
|
|
1357
|
+
frontendSpinner.start("Loading frontend templates...");
|
|
1358
|
+
const frontendResult = await apiClient.getTemplates({
|
|
1359
|
+
category: "frontend",
|
|
1360
|
+
framework: project.frontendFramework || void 0
|
|
1339
1361
|
});
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1362
|
+
frontendSpinner.stop("Frontend templates loaded");
|
|
1363
|
+
if (frontendResult.templates.length === 0) {
|
|
1364
|
+
p.log.warn("No frontend templates available for this project's framework.");
|
|
1365
|
+
} else {
|
|
1366
|
+
const selectedFrontend = await p.select({
|
|
1367
|
+
message: "Select frontend architecture template",
|
|
1368
|
+
options: frontendResult.templates.map((tmpl) => ({
|
|
1369
|
+
value: tmpl.id,
|
|
1370
|
+
label: tmpl.name,
|
|
1371
|
+
hint: tmpl.description || `${tmpl.tier} tier`
|
|
1372
|
+
}))
|
|
1373
|
+
});
|
|
1374
|
+
if (p.isCancel(selectedFrontend)) {
|
|
1375
|
+
p.cancel("Operation cancelled.");
|
|
1376
|
+
process.exit(0);
|
|
1377
|
+
}
|
|
1378
|
+
frontendTemplateId = selectedFrontend;
|
|
1343
1379
|
}
|
|
1344
|
-
|
|
1380
|
+
}
|
|
1381
|
+
if (!backendTemplateId && !frontendTemplateId) {
|
|
1382
|
+
p.cancel("No templates selected. At least one backend or frontend template is required.");
|
|
1383
|
+
process.exit(1);
|
|
1345
1384
|
}
|
|
1346
1385
|
const diagrams = project.schema?.diagrams || [];
|
|
1347
1386
|
const hasMultipleDiagrams = diagrams.length > 1;
|
|
@@ -1401,50 +1440,72 @@ async function createCommand(projectName, options) {
|
|
|
1401
1440
|
const useContexts = archStyleChoice === "bounded-contexts";
|
|
1402
1441
|
const estimateSpinner = p.spinner();
|
|
1403
1442
|
estimateSpinner.start("Calculating credit cost...");
|
|
1404
|
-
let estimatedCredits = 0;
|
|
1405
1443
|
let creditsRemaining = 0;
|
|
1406
|
-
let
|
|
1407
|
-
let
|
|
1444
|
+
let backendEstimatedCredits = 0;
|
|
1445
|
+
let backendEstimatedFiles = [];
|
|
1446
|
+
let backendEstimatedEntities = 0;
|
|
1447
|
+
let frontendEstimatedCredits = 0;
|
|
1448
|
+
let frontendEstimatedFiles = [];
|
|
1449
|
+
let frontendEstimatedEntities = 0;
|
|
1408
1450
|
const estimateDiagramIds = selectedDiagramIds.length < diagrams.length ? selectedDiagramIds : void 0;
|
|
1451
|
+
const featureFlags = {
|
|
1452
|
+
includeDtos: true,
|
|
1453
|
+
includeUseCases: true,
|
|
1454
|
+
includeMappers: true,
|
|
1455
|
+
includeControllers: true,
|
|
1456
|
+
includeEfConfig: true,
|
|
1457
|
+
includeValidation: true,
|
|
1458
|
+
includeDtoValidation: true,
|
|
1459
|
+
includeUnitTests: true,
|
|
1460
|
+
includeIntegrationTests: true,
|
|
1461
|
+
includeStarterFiles: true,
|
|
1462
|
+
includeReactions: true,
|
|
1463
|
+
includeOutbox: true,
|
|
1464
|
+
includeInbox: true
|
|
1465
|
+
};
|
|
1409
1466
|
try {
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1467
|
+
if (backendTemplateId) {
|
|
1468
|
+
const backendEstimate = await apiClient.estimateCreditCost({
|
|
1469
|
+
projectId,
|
|
1470
|
+
templateId: backendTemplateId,
|
|
1471
|
+
options: {
|
|
1472
|
+
featureFlags,
|
|
1473
|
+
useContexts,
|
|
1474
|
+
diagramIds: estimateDiagramIds
|
|
1475
|
+
}
|
|
1476
|
+
});
|
|
1477
|
+
backendEstimatedCredits = backendEstimate.estimatedCredits;
|
|
1478
|
+
backendEstimatedFiles = backendEstimate.files || [];
|
|
1479
|
+
backendEstimatedEntities = backendEstimate.entities || 0;
|
|
1480
|
+
}
|
|
1481
|
+
if (frontendTemplateId) {
|
|
1482
|
+
const frontendEstimate = await apiClient.estimateCreditCost({
|
|
1483
|
+
projectId,
|
|
1484
|
+
templateId: frontendTemplateId,
|
|
1485
|
+
options: {
|
|
1486
|
+
featureFlags,
|
|
1487
|
+
useContexts,
|
|
1488
|
+
diagramIds: estimateDiagramIds
|
|
1489
|
+
}
|
|
1490
|
+
});
|
|
1491
|
+
frontendEstimatedCredits = frontendEstimate.estimatedCredits;
|
|
1492
|
+
frontendEstimatedFiles = frontendEstimate.files || [];
|
|
1493
|
+
frontendEstimatedEntities = frontendEstimate.entities || 0;
|
|
1494
|
+
}
|
|
1436
1495
|
const creditUsage = await apiClient.getCreditUsage(organizationId);
|
|
1437
1496
|
creditsRemaining = creditUsage.remaining;
|
|
1438
1497
|
estimateSpinner.stop("Credit estimate calculated");
|
|
1439
1498
|
} catch {
|
|
1440
1499
|
estimateSpinner.stop("Could not estimate credits (will be calculated on generation)");
|
|
1441
1500
|
}
|
|
1442
|
-
const
|
|
1501
|
+
const totalEstimatedCredits = backendEstimatedCredits + frontendEstimatedCredits;
|
|
1502
|
+
const totalEstimatedFiles = backendEstimatedFiles.length + frontendEstimatedFiles.length;
|
|
1503
|
+
const totalEstimatedEntities = backendEstimatedEntities + frontendEstimatedEntities;
|
|
1504
|
+
const hasEnoughCredits = totalEstimatedCredits === 0 || creditsRemaining >= totalEstimatedCredits;
|
|
1443
1505
|
console.log("");
|
|
1444
1506
|
console.log(chalk7.bold(" Generation Summary"));
|
|
1445
1507
|
console.log(chalk7.gray(" \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"));
|
|
1446
1508
|
console.log(chalk7.gray(" Project:"), chalk7.white(project.name));
|
|
1447
|
-
console.log(chalk7.gray(" Template:"), chalk7.cyan(templateId));
|
|
1448
1509
|
console.log(chalk7.gray(" Namespace:"), chalk7.cyan(namespace));
|
|
1449
1510
|
console.log(chalk7.gray(" Directory:"), chalk7.cyan(`${safeName}/`));
|
|
1450
1511
|
console.log(
|
|
@@ -1461,14 +1522,45 @@ async function createCommand(projectName, options) {
|
|
|
1461
1522
|
console.log(chalk7.gray(" Bounded Contexts:"), chalk7.cyan(`${selectedCount}/${totalCount} (${selectedNames})`));
|
|
1462
1523
|
}
|
|
1463
1524
|
}
|
|
1464
|
-
|
|
1525
|
+
console.log("");
|
|
1526
|
+
console.log(chalk7.bold(" Templates"));
|
|
1527
|
+
console.log(chalk7.gray(" \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"));
|
|
1528
|
+
if (backendTemplateId) {
|
|
1529
|
+
console.log(chalk7.gray(" Backend:"), chalk7.cyan(backendTemplateId));
|
|
1530
|
+
}
|
|
1531
|
+
if (frontendTemplateId) {
|
|
1532
|
+
console.log(chalk7.gray(" Frontend:"), chalk7.cyan(frontendTemplateId));
|
|
1533
|
+
}
|
|
1534
|
+
if (backendEstimatedFiles.length > 0) {
|
|
1535
|
+
console.log("");
|
|
1536
|
+
console.log(chalk7.bold(` Backend Files (${backendTemplateId})`));
|
|
1537
|
+
console.log(chalk7.gray(" \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"));
|
|
1538
|
+
const backendCategories = categorizeFilePaths(backendEstimatedFiles);
|
|
1539
|
+
const backendMaxNameLength = Math.max(...backendCategories.map((c) => c.name.length), 8);
|
|
1540
|
+
for (const category of backendCategories) {
|
|
1541
|
+
const padding = " ".repeat(backendMaxNameLength - category.name.length + 2);
|
|
1542
|
+
const countStr = category.count.toString().padStart(3, " ");
|
|
1543
|
+
console.log(
|
|
1544
|
+
chalk7.gray(` ${category.name}${padding}`),
|
|
1545
|
+
chalk7.cyan(`${countStr} files`)
|
|
1546
|
+
);
|
|
1547
|
+
}
|
|
1548
|
+
console.log(chalk7.gray(" \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"));
|
|
1549
|
+
const subtotalPadding = " ".repeat(backendMaxNameLength - 8 + 2);
|
|
1550
|
+
const subtotalStr = backendEstimatedFiles.length.toString().padStart(3, " ");
|
|
1551
|
+
console.log(
|
|
1552
|
+
chalk7.white(` Subtotal${subtotalPadding}`),
|
|
1553
|
+
chalk7.bold.cyan(`${subtotalStr} files`)
|
|
1554
|
+
);
|
|
1555
|
+
}
|
|
1556
|
+
if (frontendEstimatedFiles.length > 0) {
|
|
1465
1557
|
console.log("");
|
|
1466
|
-
console.log(chalk7.bold(
|
|
1558
|
+
console.log(chalk7.bold(` Frontend Files (${frontendTemplateId})`));
|
|
1467
1559
|
console.log(chalk7.gray(" \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"));
|
|
1468
|
-
const
|
|
1469
|
-
const
|
|
1470
|
-
for (const category of
|
|
1471
|
-
const padding = " ".repeat(
|
|
1560
|
+
const frontendCategories = categorizeFilePaths(frontendEstimatedFiles);
|
|
1561
|
+
const frontendMaxNameLength = Math.max(...frontendCategories.map((c) => c.name.length), 8);
|
|
1562
|
+
for (const category of frontendCategories) {
|
|
1563
|
+
const padding = " ".repeat(frontendMaxNameLength - category.name.length + 2);
|
|
1472
1564
|
const countStr = category.count.toString().padStart(3, " ");
|
|
1473
1565
|
console.log(
|
|
1474
1566
|
chalk7.gray(` ${category.name}${padding}`),
|
|
@@ -1476,21 +1568,43 @@ async function createCommand(projectName, options) {
|
|
|
1476
1568
|
);
|
|
1477
1569
|
}
|
|
1478
1570
|
console.log(chalk7.gray(" \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"));
|
|
1479
|
-
const
|
|
1480
|
-
const
|
|
1571
|
+
const subtotalPadding = " ".repeat(frontendMaxNameLength - 8 + 2);
|
|
1572
|
+
const subtotalStr = frontendEstimatedFiles.length.toString().padStart(3, " ");
|
|
1573
|
+
console.log(
|
|
1574
|
+
chalk7.white(` Subtotal${subtotalPadding}`),
|
|
1575
|
+
chalk7.bold.cyan(`${subtotalStr} files`)
|
|
1576
|
+
);
|
|
1577
|
+
}
|
|
1578
|
+
if (backendEstimatedFiles.length > 0 && frontendEstimatedFiles.length > 0) {
|
|
1579
|
+
console.log("");
|
|
1580
|
+
console.log(chalk7.gray(" \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"));
|
|
1481
1581
|
console.log(
|
|
1482
|
-
chalk7.white(
|
|
1483
|
-
chalk7.bold.
|
|
1582
|
+
chalk7.bold.white(" TOTAL "),
|
|
1583
|
+
chalk7.bold.green(`${totalEstimatedFiles.toString().padStart(3, " ")} files`)
|
|
1484
1584
|
);
|
|
1485
|
-
console.log(chalk7.gray(" Entities:"), chalk7.cyan(
|
|
1585
|
+
console.log(chalk7.gray(" Entities:"), chalk7.cyan(totalEstimatedEntities));
|
|
1586
|
+
} else if (totalEstimatedFiles > 0) {
|
|
1587
|
+
console.log(chalk7.gray(" Entities:"), chalk7.cyan(totalEstimatedEntities));
|
|
1486
1588
|
}
|
|
1487
1589
|
console.log("");
|
|
1488
1590
|
console.log(chalk7.bold(" Credits"));
|
|
1489
1591
|
console.log(chalk7.gray(" \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"));
|
|
1490
|
-
if (
|
|
1592
|
+
if (backendEstimatedCredits > 0) {
|
|
1593
|
+
console.log(
|
|
1594
|
+
chalk7.gray(" Backend:"),
|
|
1595
|
+
chalk7.yellow(`${backendEstimatedCredits} credits`)
|
|
1596
|
+
);
|
|
1597
|
+
}
|
|
1598
|
+
if (frontendEstimatedCredits > 0) {
|
|
1491
1599
|
console.log(
|
|
1492
|
-
chalk7.
|
|
1493
|
-
|
|
1600
|
+
chalk7.gray(" Frontend:"),
|
|
1601
|
+
chalk7.yellow(`${frontendEstimatedCredits} credits`)
|
|
1602
|
+
);
|
|
1603
|
+
}
|
|
1604
|
+
if (totalEstimatedCredits > 0) {
|
|
1605
|
+
console.log(
|
|
1606
|
+
chalk7.white(" Total Cost:"),
|
|
1607
|
+
hasEnoughCredits ? chalk7.bold.yellow(`${totalEstimatedCredits} credits`) : chalk7.bold.red(`${totalEstimatedCredits} credits`)
|
|
1494
1608
|
);
|
|
1495
1609
|
}
|
|
1496
1610
|
console.log(
|
|
@@ -1500,12 +1614,12 @@ async function createCommand(projectName, options) {
|
|
|
1500
1614
|
console.log("");
|
|
1501
1615
|
if (!hasEnoughCredits) {
|
|
1502
1616
|
console.log(chalk7.red(" \u26A0 Not enough credits for this generation."));
|
|
1503
|
-
console.log(chalk7.gray(` Need ${
|
|
1617
|
+
console.log(chalk7.gray(` Need ${totalEstimatedCredits - creditsRemaining} more credits.
|
|
1504
1618
|
`));
|
|
1505
1619
|
process.exit(1);
|
|
1506
1620
|
}
|
|
1507
1621
|
const proceed = await p.confirm({
|
|
1508
|
-
message:
|
|
1622
|
+
message: totalEstimatedCredits > 0 ? `Proceed with generation? (~${totalEstimatedCredits} credits)` : "Proceed with generation?",
|
|
1509
1623
|
initialValue: true
|
|
1510
1624
|
});
|
|
1511
1625
|
if (p.isCancel(proceed) || !proceed) {
|
|
@@ -1516,47 +1630,68 @@ async function createCommand(projectName, options) {
|
|
|
1516
1630
|
dirSpinner.start(`Creating ${safeName}/...`);
|
|
1517
1631
|
await mkdir(projectDir, { recursive: true });
|
|
1518
1632
|
dirSpinner.stop(`Created ${safeName}/`);
|
|
1519
|
-
const
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
// Filter by selected bounded contexts
|
|
1633
|
+
const allGeneratedFiles = [];
|
|
1634
|
+
let totalCreditsUsed = 0;
|
|
1635
|
+
let totalCreditsRemaining = creditsRemaining;
|
|
1636
|
+
if (backendTemplateId) {
|
|
1637
|
+
const backendSpinner = ora2({ text: "Generating backend architecture...", color: "cyan" }).start();
|
|
1638
|
+
const backendResult = await apiClient.generateCode({
|
|
1639
|
+
projectId,
|
|
1640
|
+
templateId: backendTemplateId,
|
|
1641
|
+
options: {
|
|
1642
|
+
includeValidations: true,
|
|
1643
|
+
includeComments: true,
|
|
1644
|
+
featureFlags,
|
|
1645
|
+
useContexts,
|
|
1646
|
+
diagramIds: estimateDiagramIds
|
|
1647
|
+
}
|
|
1648
|
+
});
|
|
1649
|
+
const backendFiles = (backendResult.files || []).map((file) => ({
|
|
1650
|
+
...file,
|
|
1651
|
+
path: `backend/${file.path}`
|
|
1652
|
+
}));
|
|
1653
|
+
allGeneratedFiles.push(...backendFiles);
|
|
1654
|
+
if (backendResult.creditsUsed !== void 0) {
|
|
1655
|
+
totalCreditsUsed += backendResult.creditsUsed;
|
|
1656
|
+
totalCreditsRemaining = backendResult.creditsRemaining ?? totalCreditsRemaining;
|
|
1544
1657
|
}
|
|
1545
|
-
|
|
1546
|
-
|
|
1658
|
+
backendSpinner.succeed(chalk7.green(`Backend: ${backendFiles.length} files generated`));
|
|
1659
|
+
}
|
|
1660
|
+
if (frontendTemplateId) {
|
|
1661
|
+
const frontendSpinner = ora2({ text: "Generating frontend architecture...", color: "cyan" }).start();
|
|
1662
|
+
const frontendResult = await apiClient.generateCode({
|
|
1663
|
+
projectId,
|
|
1664
|
+
templateId: frontendTemplateId,
|
|
1665
|
+
options: {
|
|
1666
|
+
includeValidations: true,
|
|
1667
|
+
includeComments: true,
|
|
1668
|
+
featureFlags,
|
|
1669
|
+
useContexts,
|
|
1670
|
+
diagramIds: estimateDiagramIds
|
|
1671
|
+
}
|
|
1672
|
+
});
|
|
1673
|
+
const frontendFiles = (frontendResult.files || []).map((file) => ({
|
|
1674
|
+
...file,
|
|
1675
|
+
path: `frontend/${file.path}`
|
|
1676
|
+
}));
|
|
1677
|
+
allGeneratedFiles.push(...frontendFiles);
|
|
1678
|
+
if (frontendResult.creditsUsed !== void 0) {
|
|
1679
|
+
totalCreditsUsed += frontendResult.creditsUsed;
|
|
1680
|
+
totalCreditsRemaining = frontendResult.creditsRemaining ?? totalCreditsRemaining;
|
|
1681
|
+
}
|
|
1682
|
+
frontendSpinner.succeed(chalk7.green(`Frontend: ${frontendFiles.length} files generated`));
|
|
1683
|
+
}
|
|
1547
1684
|
const writeSpinner = p.spinner();
|
|
1548
1685
|
writeSpinner.start("Writing files...");
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
path: `backend/${file.path}`
|
|
1552
|
-
}));
|
|
1553
|
-
await writeGeneratedFiles(organizedFiles, projectDir, false);
|
|
1554
|
-
writeSpinner.stop(`Wrote ${organizedFiles.length} files`);
|
|
1686
|
+
await writeGeneratedFiles(allGeneratedFiles, projectDir, false);
|
|
1687
|
+
writeSpinner.stop(`Wrote ${allGeneratedFiles.length} files`);
|
|
1555
1688
|
const configSpinner = p.spinner();
|
|
1556
1689
|
configSpinner.start("Creating config files...");
|
|
1557
1690
|
const projectConfig = createProjectConfig({
|
|
1558
1691
|
projectId,
|
|
1559
|
-
templateId,
|
|
1692
|
+
templateId: backendTemplateId || frontendTemplateId || "",
|
|
1693
|
+
backendTemplateId,
|
|
1694
|
+
frontendTemplateId,
|
|
1560
1695
|
templateVersion: "1.0.0",
|
|
1561
1696
|
// TODO: get from template
|
|
1562
1697
|
namespace,
|
|
@@ -1565,7 +1700,7 @@ async function createCommand(projectName, options) {
|
|
|
1565
1700
|
});
|
|
1566
1701
|
await saveProjectConfig(projectConfig, projectDir);
|
|
1567
1702
|
let manifest = createEmptyManifest("1.0.0");
|
|
1568
|
-
for (const file of
|
|
1703
|
+
for (const file of allGeneratedFiles) {
|
|
1569
1704
|
const hash = hashString(file.content);
|
|
1570
1705
|
manifest = setManifestFile(manifest, file.path, {
|
|
1571
1706
|
hash,
|
|
@@ -1590,13 +1725,21 @@ async function createCommand(projectName, options) {
|
|
|
1590
1725
|
console.log(chalk7.bold(" Project Created Successfully!"));
|
|
1591
1726
|
console.log(chalk7.gray(" \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"));
|
|
1592
1727
|
console.log(chalk7.gray(" Directory:"), chalk7.cyan(safeName + "/"));
|
|
1593
|
-
|
|
1728
|
+
const backendFileCount = allGeneratedFiles.filter((f) => f.path.startsWith("backend/")).length;
|
|
1729
|
+
const frontendFileCount = allGeneratedFiles.filter((f) => f.path.startsWith("frontend/")).length;
|
|
1730
|
+
if (backendFileCount > 0 && frontendFileCount > 0) {
|
|
1731
|
+
console.log(chalk7.gray(" Backend:"), chalk7.cyan(`${backendFileCount} files`));
|
|
1732
|
+
console.log(chalk7.gray(" Frontend:"), chalk7.cyan(`${frontendFileCount} files`));
|
|
1733
|
+
console.log(chalk7.gray(" Total:"), chalk7.bold.cyan(`${allGeneratedFiles.length} files`));
|
|
1734
|
+
} else {
|
|
1735
|
+
console.log(chalk7.gray(" Files:"), chalk7.cyan(allGeneratedFiles.length));
|
|
1736
|
+
}
|
|
1594
1737
|
console.log(chalk7.gray(" Config:"), chalk7.cyan(PROJECT_CONFIG_FILENAME));
|
|
1595
1738
|
console.log(chalk7.gray(" Manifest:"), chalk7.cyan(MANIFEST_FILENAME));
|
|
1596
|
-
if (
|
|
1739
|
+
if (totalCreditsUsed > 0) {
|
|
1597
1740
|
console.log("");
|
|
1598
|
-
console.log(chalk7.gray(" Credits used:"), chalk7.yellow(
|
|
1599
|
-
console.log(chalk7.gray(" Credits remaining:"), chalk7.green(
|
|
1741
|
+
console.log(chalk7.gray(" Credits used:"), chalk7.yellow(totalCreditsUsed));
|
|
1742
|
+
console.log(chalk7.gray(" Credits remaining:"), chalk7.green(totalCreditsRemaining));
|
|
1600
1743
|
}
|
|
1601
1744
|
p.outro(
|
|
1602
1745
|
chalk7.green("Project ready!") + "\n\n" + chalk7.gray(" Next steps:\n") + chalk7.cyan(` cd ${safeName}
|