@atlashub/smartstack-cli 3.20.0 → 3.22.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 -6
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +69 -3
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/project/api.ts.template +8 -29
- package/templates/project/appsettings.json.template +1 -0
- package/templates/skills/application/references/application-roles-template.md +2 -2
- package/templates/skills/application/steps/step-05-frontend.md +40 -35
- package/templates/skills/application/templates-frontend.md +64 -36
- package/templates/skills/business-analyse/html/ba-interactive.html +642 -156
- package/templates/skills/business-analyse/html/src/scripts/01-data-init.js +11 -6
- package/templates/skills/business-analyse/html/src/scripts/02-navigation.js +209 -4
- package/templates/skills/business-analyse/html/src/scripts/04-render-modules.js +2 -8
- package/templates/skills/business-analyse/html/src/scripts/05-render-specs.js +95 -8
- package/templates/skills/business-analyse/html/src/scripts/07-render-handoff.js +3 -1
- package/templates/skills/business-analyse/html/src/scripts/08-editing.js +112 -22
- package/templates/skills/business-analyse/html/src/scripts/11-review-panel.js +7 -0
- package/templates/skills/business-analyse/html/src/styles/02-layout.css +1 -1
- package/templates/skills/business-analyse/html/src/styles/03-navigation.css +89 -31
- package/templates/skills/business-analyse/html/src/styles/05-modules.css +64 -0
- package/templates/skills/business-analyse/html/src/styles/06-wireframes.css +42 -0
- package/templates/skills/business-analyse/html/src/template.html +8 -76
- package/templates/skills/business-analyse/references/acceptance-criteria.md +169 -0
- package/templates/skills/business-analyse/references/deploy-data-build.md +13 -9
- package/templates/skills/business-analyse/references/handoff-file-templates.md +2 -1
- package/templates/skills/business-analyse/references/html-data-mapping.md +20 -28
- package/templates/skills/business-analyse/references/naming-conventions.md +245 -0
- package/templates/skills/business-analyse/references/validate-incremental-html.md +28 -5
- package/templates/skills/business-analyse/references/validation-checklist.md +31 -11
- package/templates/skills/business-analyse/references/wireframe-svg-style-guide.md +335 -0
- package/templates/skills/business-analyse/steps/step-03b-ui.md +59 -0
- package/templates/skills/business-analyse/steps/step-03c-compile.md +169 -2
- package/templates/skills/business-analyse/steps/step-03d-validate.md +217 -28
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +189 -3
- package/templates/skills/business-analyse/steps/step-05b-deploy.md +55 -0
- package/templates/skills/ralph-loop/references/category-rules.md +5 -2
- package/templates/skills/ralph-loop/references/compact-loop.md +52 -1
- package/templates/skills/ralph-loop/references/core-seed-data.md +232 -21
- package/templates/skills/ralph-loop/steps/step-01-task.md +36 -4
- package/templates/skills/ralph-loop/steps/step-02-execute.md +81 -0
package/dist/mcp-entry.mjs
CHANGED
|
@@ -25773,6 +25773,7 @@ var init_types3 = __esm({
|
|
|
25773
25773
|
projectType: external_exports.enum(["client", "platform"]).default("platform"),
|
|
25774
25774
|
dbContext: external_exports.enum(["core", "extensions"]).default("core"),
|
|
25775
25775
|
baseNamespace: external_exports.string().optional(),
|
|
25776
|
+
tablePrefix: external_exports.string().optional().describe('Application-level table prefix (e.g., "rh_", "fi_", "crm_")'),
|
|
25776
25777
|
smartStackVersion: external_exports.string().optional(),
|
|
25777
25778
|
initialized: external_exports.string().optional(),
|
|
25778
25779
|
paths: external_exports.object({
|
|
@@ -57046,13 +57047,40 @@ async function scaffoldRoutes(input, config2) {
|
|
|
57046
57047
|
result.instructions.push("");
|
|
57047
57048
|
result.instructions.push("## App.tsx Wiring Instructions");
|
|
57048
57049
|
result.instructions.push("");
|
|
57049
|
-
result.instructions.push("
|
|
57050
|
-
result.instructions.push("Routes must be added in BOTH the standard block and the tenant-prefixed block (/t/:slug/...).");
|
|
57050
|
+
result.instructions.push("**Detect App.tsx pattern first**, then follow the matching instructions:");
|
|
57051
57051
|
result.instructions.push("");
|
|
57052
57052
|
const routeTree = buildRouteTree(navRoutes);
|
|
57053
|
+
result.instructions.push("### Pattern A: mergeRoutes (if App.tsx uses `contextRoutes: ContextRouteExtensions`)");
|
|
57054
|
+
result.instructions.push("");
|
|
57055
|
+
result.instructions.push("Add routes to `contextRoutes.{context}[]` with **RELATIVE** paths (no leading `/`):");
|
|
57056
|
+
result.instructions.push("");
|
|
57057
|
+
result.instructions.push("```tsx");
|
|
57058
|
+
result.instructions.push("const contextRoutes: ContextRouteExtensions = {");
|
|
57059
|
+
for (const [context, applications] of Object.entries(routeTree)) {
|
|
57060
|
+
result.instructions.push(` ${context}: [`);
|
|
57061
|
+
for (const [, modules] of Object.entries(applications)) {
|
|
57062
|
+
for (const route of modules) {
|
|
57063
|
+
const modulePath = route.navRoute.split(".").slice(1).join("/");
|
|
57064
|
+
const pageEntry = pageFiles.get(route.navRoute);
|
|
57065
|
+
const component = pageEntry?.[0]?.componentName || `${route.navRoute.split(".").map(capitalize).join("")}Page`;
|
|
57066
|
+
result.instructions.push(` { path: '${modulePath}', element: <${component} /> },`);
|
|
57067
|
+
}
|
|
57068
|
+
}
|
|
57069
|
+
result.instructions.push(" ],");
|
|
57070
|
+
}
|
|
57071
|
+
result.instructions.push("};");
|
|
57072
|
+
result.instructions.push("```");
|
|
57073
|
+
result.instructions.push("");
|
|
57074
|
+
result.instructions.push("Routes are automatically injected into BOTH standard and tenant-prefixed trees by `mergeRoutes()`.");
|
|
57075
|
+
result.instructions.push("**DO NOT** add business/platform/personal routes to `clientRoutes[]` \u2014 that array is only for routes outside SmartStack contexts.");
|
|
57076
|
+
result.instructions.push("");
|
|
57077
|
+
result.instructions.push('### Pattern B: JSX Routes (if App.tsx uses `<Route path="/{context}" element={<{Layout} />}>`)');
|
|
57078
|
+
result.instructions.push("");
|
|
57079
|
+
result.instructions.push("Insert `<Route>` children INSIDE the appropriate Layout wrapper:");
|
|
57080
|
+
result.instructions.push("");
|
|
57053
57081
|
for (const [context, applications] of Object.entries(routeTree)) {
|
|
57054
57082
|
const layoutName = getLayoutName(context);
|
|
57055
|
-
result.instructions.push(
|
|
57083
|
+
result.instructions.push(`#### ${capitalize(context)} context (inside \`<Route path="/${context}" element={<${layoutName} />}>\`):`);
|
|
57056
57084
|
result.instructions.push("");
|
|
57057
57085
|
result.instructions.push("```tsx");
|
|
57058
57086
|
for (const [, modules] of Object.entries(applications)) {
|
|
@@ -57546,6 +57574,7 @@ function generateClientRoutesConfig(routes, pageFiles, includeGuards) {
|
|
|
57546
57574
|
" */",
|
|
57547
57575
|
"",
|
|
57548
57576
|
"import type { RouteObject } from 'react-router-dom';",
|
|
57577
|
+
"import type { ContextRouteExtensions } from '@atlashub/smartstack';",
|
|
57549
57578
|
"import { Navigate } from 'react-router-dom';"
|
|
57550
57579
|
];
|
|
57551
57580
|
if (includeGuards) {
|
|
@@ -57647,6 +57676,24 @@ function generateClientRoutesConfig(routes, pageFiles, includeGuards) {
|
|
|
57647
57676
|
}
|
|
57648
57677
|
lines.push("};");
|
|
57649
57678
|
lines.push("");
|
|
57679
|
+
lines.push("/**");
|
|
57680
|
+
lines.push(" * Context route extensions for mergeRoutes() pattern.");
|
|
57681
|
+
lines.push(" * Import and spread into your App.tsx contextRoutes:");
|
|
57682
|
+
lines.push(" *");
|
|
57683
|
+
lines.push(" * ```tsx");
|
|
57684
|
+
lines.push(" * import { contextRouteExtensions } from './routes/clientRoutes.generated';");
|
|
57685
|
+
lines.push(" * const contextRoutes: ContextRouteExtensions = {");
|
|
57686
|
+
lines.push(" * ...contextRouteExtensions,");
|
|
57687
|
+
lines.push(" * // your additional routes...");
|
|
57688
|
+
lines.push(" * };");
|
|
57689
|
+
lines.push(" * ```");
|
|
57690
|
+
lines.push(" */");
|
|
57691
|
+
lines.push("export const contextRouteExtensions: ContextRouteExtensions = {");
|
|
57692
|
+
for (const context of contexts) {
|
|
57693
|
+
lines.push(` ${context}: ${context}Routes,`);
|
|
57694
|
+
}
|
|
57695
|
+
lines.push("};");
|
|
57696
|
+
lines.push("");
|
|
57650
57697
|
return lines.join("\n");
|
|
57651
57698
|
}
|
|
57652
57699
|
function getLayoutName(context) {
|
|
@@ -58027,6 +58074,25 @@ async function validateAppWiring(webPath, backendRoutes, result) {
|
|
|
58027
58074
|
result.appWiring.issues.push("App.tsx does not import any route configuration");
|
|
58028
58075
|
return;
|
|
58029
58076
|
}
|
|
58077
|
+
const caseMismatches = [];
|
|
58078
|
+
for (const route of backendRoutes) {
|
|
58079
|
+
const modulePath = route.webPath.replace(/^\//, "");
|
|
58080
|
+
if (modulePath !== modulePath.toLowerCase()) {
|
|
58081
|
+
const kebabPath = modulePath.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
58082
|
+
caseMismatches.push(
|
|
58083
|
+
`Route "${route.navRoute}" uses PascalCase in URL. Found: ${modulePath} \u2192 Expected: ${kebabPath}`
|
|
58084
|
+
);
|
|
58085
|
+
}
|
|
58086
|
+
}
|
|
58087
|
+
if (caseMismatches.length > 0) {
|
|
58088
|
+
result.appWiring.issues.push(
|
|
58089
|
+
`Case mismatch detected (${caseMismatches.length} routes with uppercase):`
|
|
58090
|
+
);
|
|
58091
|
+
result.appWiring.issues.push(...caseMismatches);
|
|
58092
|
+
result.appWiring.issues.push(
|
|
58093
|
+
"Fix: Use ToKebabCase() in NavigationSeedData route generation (see core-seed-data.md)"
|
|
58094
|
+
);
|
|
58095
|
+
}
|
|
58030
58096
|
for (const route of backendRoutes) {
|
|
58031
58097
|
const modulePath = route.navRoute.split(".").slice(1).join("/");
|
|
58032
58098
|
const lastSegment = route.navRoute.split(".").pop() || "";
|