@atlashub/smartstack-cli 4.56.0 → 4.58.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 +62 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/project/Dockerfile.frontend.template +3 -3
- package/templates/skills/business-analyse/_shared.md +69 -21
- package/templates/skills/business-analyse/references/canonical-json-formats.md +1 -1
- package/templates/skills/business-analyse/references/naming-conventions.md +12 -2
- package/templates/skills/business-analyse/steps/step-00-init.md +54 -21
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +6 -2
- package/templates/skills/business-analyse/steps/step-02-structure.md +13 -3
- package/templates/skills/business-analyse/steps/step-03-specify.md +14 -1
- package/templates/skills/business-analyse/steps/step-04-consolidate.md +3 -1
- package/templates/skills/business-analyse-design/steps/step-01-screens.md +12 -1
- package/templates/skills/business-analyse-design/steps/step-03-navigation.md +4 -3
- package/templates/skills/business-analyse-handoff/steps/step-01-transform.md +2 -2
- package/templates/skills/business-analyse-handoff/steps/step-02-export.md +15 -13
- package/templates/skills/business-analyse-html/SKILL.md +14 -0
- package/templates/skills/business-analyse-html/steps/step-01-collect.md +12 -6
- package/templates/skills/business-analyse-html/steps/step-03-render.md +7 -4
- package/templates/skills/business-analyse-html/steps/step-04-verify.md +3 -3
- package/templates/skills/business-analyse-review/steps/step-00-init.md +7 -2
- package/templates/skills/business-analyse-review/steps/step-01-apply.md +6 -7
- package/templates/skills/business-analyse-status/SKILL.md +19 -8
package/dist/index.js
CHANGED
|
@@ -116339,6 +116339,12 @@ async function setupMailPitContainer() {
|
|
|
116339
116339
|
logger.info(`SMTP server: ${source_default.cyan("localhost:1025")}`);
|
|
116340
116340
|
logger.info(`Web interface: ${source_default.cyan("http://localhost:8025")}`);
|
|
116341
116341
|
}
|
|
116342
|
+
function toPascalCase(name) {
|
|
116343
|
+
return name.split(/[-_.\s]+/).filter(Boolean).map((part) => {
|
|
116344
|
+
if (/^\d+$/.test(part)) return part;
|
|
116345
|
+
return part.charAt(0).toUpperCase() + part.slice(1);
|
|
116346
|
+
}).join("");
|
|
116347
|
+
}
|
|
116342
116348
|
function validateCSharpNamespace(name) {
|
|
116343
116349
|
if (!name || name.trim().length === 0) {
|
|
116344
116350
|
return { valid: false, error: "Project name cannot be empty" };
|
|
@@ -116349,13 +116355,13 @@ function validateCSharpNamespace(name) {
|
|
|
116349
116355
|
return {
|
|
116350
116356
|
valid: false,
|
|
116351
116357
|
error: `Project name cannot start with a digit: '${firstChar}'`,
|
|
116352
|
-
suggestion:
|
|
116358
|
+
suggestion: toPascalCase("_" + name)
|
|
116353
116359
|
};
|
|
116354
116360
|
}
|
|
116355
116361
|
return {
|
|
116356
116362
|
valid: false,
|
|
116357
116363
|
error: `Project name cannot start with '${firstChar}'`,
|
|
116358
|
-
suggestion: name
|
|
116364
|
+
suggestion: toPascalCase(name)
|
|
116359
116365
|
};
|
|
116360
116366
|
}
|
|
116361
116367
|
const invalidChars = name.match(/[^a-zA-Z0-9_]/g);
|
|
@@ -116364,7 +116370,7 @@ function validateCSharpNamespace(name) {
|
|
|
116364
116370
|
return {
|
|
116365
116371
|
valid: false,
|
|
116366
116372
|
error: `Project name contains invalid characters for C# namespace: ${uniqueInvalid.map((c) => `'${c}'`).join(", ")}`,
|
|
116367
|
-
suggestion: name
|
|
116373
|
+
suggestion: toPascalCase(name)
|
|
116368
116374
|
};
|
|
116369
116375
|
}
|
|
116370
116376
|
const csharpKeywords = [
|
|
@@ -116453,6 +116459,14 @@ function validateCSharpNamespace(name) {
|
|
|
116453
116459
|
suggestion: `${name}_Project`
|
|
116454
116460
|
};
|
|
116455
116461
|
}
|
|
116462
|
+
const pascalVersion = toPascalCase(name);
|
|
116463
|
+
if (pascalVersion !== name) {
|
|
116464
|
+
return {
|
|
116465
|
+
valid: false,
|
|
116466
|
+
error: `Project name "${name}" is not PascalCase`,
|
|
116467
|
+
suggestion: pascalVersion
|
|
116468
|
+
};
|
|
116469
|
+
}
|
|
116456
116470
|
return { valid: true };
|
|
116457
116471
|
}
|
|
116458
116472
|
async function detectProjectContext(name, here) {
|
|
@@ -116742,7 +116756,8 @@ EndGlobal
|
|
|
116742
116756
|
"Program.cs",
|
|
116743
116757
|
"appsettings.json",
|
|
116744
116758
|
"appsettings.Development.json",
|
|
116745
|
-
(0, import_path7.join)("Properties", "launchSettings.json")
|
|
116759
|
+
(0, import_path7.join)("Properties", "launchSettings.json"),
|
|
116760
|
+
`${projectName}.Api.http`
|
|
116746
116761
|
];
|
|
116747
116762
|
for (const placeholder of apiPlaceholders) {
|
|
116748
116763
|
const placeholderPath = (0, import_path7.join)(apiDir, placeholder);
|
|
@@ -117184,6 +117199,7 @@ ${projectName}/
|
|
|
117184
117199
|
\u2502 \u2514\u2500\u2500 ${projectName}.Api/ # Web API controllers and configuration
|
|
117185
117200
|
\u251C\u2500\u2500 web/
|
|
117186
117201
|
\u2502 \u2514\u2500\u2500 ${projectName.toLowerCase()}-web/ # React frontend (Vite + TypeScript + Tailwind)
|
|
117202
|
+
\u251C\u2500\u2500 docker-images/ # Dockerfiles (backend + frontend)
|
|
117187
117203
|
\u2514\u2500\u2500 tests/ # Unit and integration tests
|
|
117188
117204
|
\`\`\`
|
|
117189
117205
|
|
|
@@ -117640,14 +117656,47 @@ Thumbs.db
|
|
|
117640
117656
|
logSafeWriteResult(webClaudeMd_relPath, webClaudeMd_result);
|
|
117641
117657
|
recordFile(state, "frontend", webClaudeMd_relPath, webClaudeMd_result.hash);
|
|
117642
117658
|
}
|
|
117659
|
+
const testFrontendDir = (0, import_path7.join)(TEMPLATES_DIR2, "test-frontend");
|
|
117660
|
+
if (await import_fs_extra6.default.pathExists(testFrontendDir)) {
|
|
117661
|
+
await import_fs_extra6.default.ensureDir((0, import_path7.join)(webDir, "src", "test", "msw"));
|
|
117662
|
+
const vitestContent = await import_fs_extra6.default.readFile((0, import_path7.join)(testFrontendDir, "vitest.config.ts"), "utf-8");
|
|
117663
|
+
const vitest_relPath = `${webRelPrefix}/vitest.config.ts`;
|
|
117664
|
+
const vitest_result = await safeWriteFile(
|
|
117665
|
+
(0, import_path7.join)(webDir, "vitest.config.ts"),
|
|
117666
|
+
vitestContent,
|
|
117667
|
+
findKnownHash(state, "frontend", vitest_relPath)
|
|
117668
|
+
);
|
|
117669
|
+
logSafeWriteResult(vitest_relPath, vitest_result);
|
|
117670
|
+
recordFile(state, "frontend", vitest_relPath, vitest_result.hash);
|
|
117671
|
+
const testFiles = [
|
|
117672
|
+
{ src: "setup.ts", dest: "src/test/setup.ts" },
|
|
117673
|
+
{ src: "test-utils.tsx", dest: "src/test/test-utils.tsx" },
|
|
117674
|
+
{ src: "msw/handlers.ts", dest: "src/test/msw/handlers.ts" },
|
|
117675
|
+
{ src: "msw/server.ts", dest: "src/test/msw/server.ts" }
|
|
117676
|
+
];
|
|
117677
|
+
for (const { src, dest } of testFiles) {
|
|
117678
|
+
const content = await import_fs_extra6.default.readFile((0, import_path7.join)(testFrontendDir, src), "utf-8");
|
|
117679
|
+
const relPath = `${webRelPrefix}/${dest}`;
|
|
117680
|
+
const result = await safeWriteFile(
|
|
117681
|
+
(0, import_path7.join)(webDir, dest),
|
|
117682
|
+
content,
|
|
117683
|
+
findKnownHash(state, "frontend", relPath)
|
|
117684
|
+
);
|
|
117685
|
+
logSafeWriteResult(relPath, result);
|
|
117686
|
+
recordFile(state, "frontend", relPath, result.hash);
|
|
117687
|
+
}
|
|
117688
|
+
}
|
|
117643
117689
|
logger.success("React frontend created at: " + webDir);
|
|
117644
117690
|
}
|
|
117645
117691
|
async function createDockerFiles(config, state, dryRun) {
|
|
117646
|
-
const
|
|
117647
|
-
const
|
|
117648
|
-
const
|
|
117692
|
+
const { name } = config;
|
|
117693
|
+
const projectDir = config.projectDir ?? ((0, import_path7.isAbsolute)(name) ? name : (0, import_path7.join)(process.cwd(), name));
|
|
117694
|
+
const projectName = (0, import_path7.basename)(name);
|
|
117695
|
+
if (!dryRun) {
|
|
117696
|
+
await import_fs_extra6.default.ensureDir((0, import_path7.join)(projectDir, "docker-images"));
|
|
117697
|
+
}
|
|
117649
117698
|
const backendDockerfile = await loadTemplate("Dockerfile.backend.template", projectName);
|
|
117650
|
-
const backendRelPath =
|
|
117699
|
+
const backendRelPath = "docker-images/Dockerfile.backend";
|
|
117651
117700
|
if (dryRun) {
|
|
117652
117701
|
logger.info(`Would create ${backendRelPath}`);
|
|
117653
117702
|
} else {
|
|
@@ -117660,7 +117709,7 @@ async function createDockerFiles(config, state, dryRun) {
|
|
|
117660
117709
|
recordFile(state, "docker", backendRelPath, backendResult.hash);
|
|
117661
117710
|
}
|
|
117662
117711
|
const frontendDockerfile = await loadTemplate("Dockerfile.frontend.template", projectName);
|
|
117663
|
-
const frontendRelPath =
|
|
117712
|
+
const frontendRelPath = "docker-images/Dockerfile.frontend";
|
|
117664
117713
|
if (dryRun) {
|
|
117665
117714
|
logger.info(`Would create ${frontendRelPath}`);
|
|
117666
117715
|
} else {
|
|
@@ -118054,7 +118103,7 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
|
|
|
118054
118103
|
try {
|
|
118055
118104
|
let cliVersion = "0.0.0";
|
|
118056
118105
|
try {
|
|
118057
|
-
const pkgPath = (0, import_path7.join)((0, import_path7.dirname)(
|
|
118106
|
+
const pkgPath = (0, import_path7.join)((0, import_path7.dirname)(__dirname), "package.json");
|
|
118058
118107
|
const pkg2 = JSON.parse(await import_fs_extra6.default.readFile(pkgPath, "utf-8"));
|
|
118059
118108
|
cliVersion = pkg2.version || "0.0.0";
|
|
118060
118109
|
} catch {
|
|
@@ -118119,8 +118168,8 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
|
|
|
118119
118168
|
` 3. Start dev server: ${source_default.cyan("npm run dev")}`,
|
|
118120
118169
|
"",
|
|
118121
118170
|
source_default.yellow("Docker:"),
|
|
118122
|
-
` Build backend: ${source_default.cyan(`docker build -t smartstack-${projectNameLower}-backend:latest -f
|
|
118123
|
-
` Build frontend: ${source_default.cyan(`docker build -t smartstack-${projectNameLower}-frontend:latest
|
|
118171
|
+
` Build backend: ${source_default.cyan(`docker build -t smartstack-${projectNameLower}-backend:latest -f docker-images/Dockerfile.backend .`)}`,
|
|
118172
|
+
` Build frontend: ${source_default.cyan(`docker build -t smartstack-${projectNameLower}-frontend:latest -f docker-images/Dockerfile.frontend .`)}`,
|
|
118124
118173
|
"",
|
|
118125
118174
|
source_default.yellow("Ralph (AI Automation):"),
|
|
118126
118175
|
` 1. Check MCP servers: ${source_default.cyan("smartstack check-mcp")}`,
|
|
@@ -129076,7 +129125,7 @@ Processing module: ${source_default.bold(moduleName)}`));
|
|
|
129076
129125
|
}
|
|
129077
129126
|
let cliVersion = "unknown";
|
|
129078
129127
|
try {
|
|
129079
|
-
const pkg2 = import_fs_extra15.default.readJsonSync((0, import_path16.join)(__dirname, "..", "
|
|
129128
|
+
const pkg2 = import_fs_extra15.default.readJsonSync((0, import_path16.join)(__dirname, "..", "package.json"));
|
|
129080
129129
|
cliVersion = pkg2.version ?? "unknown";
|
|
129081
129130
|
} catch {
|
|
129082
129131
|
}
|