@atlashub/smartstack-cli 4.35.0 → 4.37.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 +54 -100
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +54 -11
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/agents/efcore/migration.md +43 -0
- package/templates/agents/efcore/rebase-snapshot.md +36 -0
- package/templates/agents/efcore/squash.md +36 -0
- package/templates/skills/apex/references/checks/seed-checks.sh +1 -1
- package/templates/skills/apex/references/core-seed-data.md +39 -21
- package/templates/skills/application/references/application-roles-template.md +14 -8
- package/templates/skills/application/references/provider-template.md +32 -20
- package/templates/skills/application/templates-frontend.md +294 -2
- package/templates/skills/application/templates-seed.md +23 -11
- package/templates/skills/audit-route/SKILL.md +107 -0
- package/templates/skills/audit-route/references/routing-pattern.md +129 -0
- package/templates/skills/audit-route/steps/step-00-init.md +128 -0
- package/templates/skills/audit-route/steps/step-01-inventory.md +157 -0
- package/templates/skills/audit-route/steps/step-02-conformity.md +193 -0
- package/templates/skills/audit-route/steps/step-03-report.md +201 -0
- package/templates/skills/dev-start/SKILL.md +12 -2
- package/templates/skills/efcore/SKILL.md +219 -67
- package/templates/agents/efcore/conflicts.md +0 -114
- package/templates/agents/efcore/db-deploy.md +0 -86
- package/templates/agents/efcore/db-reset.md +0 -98
- package/templates/agents/efcore/db-seed.md +0 -73
- package/templates/agents/efcore/db-status.md +0 -97
- package/templates/agents/efcore/scan.md +0 -124
- package/templates/skills/efcore/references/both-contexts.md +0 -32
- package/templates/skills/efcore/references/destructive-operations.md +0 -38
- package/templates/skills/efcore/steps/db/step-deploy.md +0 -217
- package/templates/skills/efcore/steps/db/step-reset.md +0 -186
- package/templates/skills/efcore/steps/db/step-seed.md +0 -166
- package/templates/skills/efcore/steps/db/step-status.md +0 -173
- package/templates/skills/efcore/steps/migration/step-00-init.md +0 -102
- package/templates/skills/efcore/steps/migration/step-01-check.md +0 -164
- package/templates/skills/efcore/steps/migration/step-02-create.md +0 -160
- package/templates/skills/efcore/steps/migration/step-03-validate.md +0 -168
- package/templates/skills/efcore/steps/rebase-snapshot/step-00-init.md +0 -173
- package/templates/skills/efcore/steps/rebase-snapshot/step-01-backup.md +0 -100
- package/templates/skills/efcore/steps/rebase-snapshot/step-02-fetch.md +0 -115
- package/templates/skills/efcore/steps/rebase-snapshot/step-03-create.md +0 -112
- package/templates/skills/efcore/steps/rebase-snapshot/step-04-validate.md +0 -157
- package/templates/skills/efcore/steps/shared/step-00-init.md +0 -131
- package/templates/skills/efcore/steps/squash/step-00-init.md +0 -141
- package/templates/skills/efcore/steps/squash/step-01-backup.md +0 -120
- package/templates/skills/efcore/steps/squash/step-02-fetch.md +0 -168
- package/templates/skills/efcore/steps/squash/step-03-create.md +0 -184
- package/templates/skills/efcore/steps/squash/step-04-validate.md +0 -174
package/dist/mcp-entry.mjs
CHANGED
|
@@ -28009,7 +28009,7 @@ async function validateFrontendRoutes(structure, _config, result) {
|
|
|
28009
28009
|
const missingRoutes2 = [];
|
|
28010
28010
|
for (const nav of seedNavRoutes2) {
|
|
28011
28011
|
const segments = nav.route.split("/").filter(Boolean);
|
|
28012
|
-
const componentKey = segments.join(".");
|
|
28012
|
+
const componentKey = segments.map((s) => s.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()).join(".");
|
|
28013
28013
|
if (!registeredKeys.has(componentKey)) {
|
|
28014
28014
|
missingRoutes2.push(nav);
|
|
28015
28015
|
}
|
|
@@ -28039,15 +28039,24 @@ async function validateFrontendRoutes(structure, _config, result) {
|
|
|
28039
28039
|
});
|
|
28040
28040
|
return;
|
|
28041
28041
|
}
|
|
28042
|
+
const hasDynamicRouter = appContent.includes("DynamicRouter") || appContent.includes("<DynamicRouter");
|
|
28043
|
+
if (hasDynamicRouter) {
|
|
28044
|
+
result.warnings.push({
|
|
28045
|
+
type: "warning",
|
|
28046
|
+
category: "frontend-routes",
|
|
28047
|
+
message: "App.tsx uses DynamicRouter but componentRegistry.generated.ts was not found. Run scaffold_routes to generate it."
|
|
28048
|
+
});
|
|
28049
|
+
return;
|
|
28050
|
+
}
|
|
28042
28051
|
const hasApplicationRoutes = appContent.includes("applicationRoutes") || appContent.includes("clientRoutes");
|
|
28043
28052
|
const hasRouteComponents = /<Route\s/.test(appContent);
|
|
28044
28053
|
if (!hasApplicationRoutes && !hasRouteComponents) {
|
|
28045
28054
|
result.errors.push({
|
|
28046
28055
|
type: "error",
|
|
28047
28056
|
category: "frontend-routes",
|
|
28048
|
-
message: "App.tsx has no route definitions (neither applicationRoutes import nor <Route> components)",
|
|
28057
|
+
message: "App.tsx has no route definitions (neither DynamicRouter, applicationRoutes import, nor <Route> components)",
|
|
28049
28058
|
file: path8.relative(structure.root, appFiles[0]),
|
|
28050
|
-
suggestion:
|
|
28059
|
+
suggestion: 'For v3.7+: Use DynamicRouter with componentRegistry.generated.ts (run scaffold_routes outputFormat="componentRegistry"). For legacy: Import route configuration from generated routes file.'
|
|
28051
28060
|
});
|
|
28052
28061
|
return;
|
|
28053
28062
|
}
|
|
@@ -28576,6 +28585,7 @@ async function handleCheckMigrations(args, config2) {
|
|
|
28576
28585
|
);
|
|
28577
28586
|
}
|
|
28578
28587
|
await checkModelSnapshot(result, structure);
|
|
28588
|
+
await checkSqlObjectsInjection(result, structure);
|
|
28579
28589
|
result.hasConflicts = result.conflicts.length > 0;
|
|
28580
28590
|
generateSuggestions(result);
|
|
28581
28591
|
return formatResult2(result, currentBranch, input.compareBranch);
|
|
@@ -28745,6 +28755,24 @@ async function checkModelSnapshot(result, structure) {
|
|
|
28745
28755
|
}
|
|
28746
28756
|
}
|
|
28747
28757
|
}
|
|
28758
|
+
async function checkSqlObjectsInjection(result, structure) {
|
|
28759
|
+
if (!structure.migrations || !structure.infrastructure) return;
|
|
28760
|
+
const sqlObjectsPath = path9.join(structure.infrastructure, "Persistence", "SqlObjects");
|
|
28761
|
+
const sqlFiles = await findFiles("**/*.sql", { cwd: sqlObjectsPath }).catch(() => []);
|
|
28762
|
+
if (sqlFiles.length === 0) return;
|
|
28763
|
+
for (const migration of result.migrations) {
|
|
28764
|
+
const migrationPath = path9.join(structure.root, migration.file);
|
|
28765
|
+
const content = await readText(migrationPath).catch(() => "");
|
|
28766
|
+
if (content && !content.includes("SqlObjectHelper.ApplyAll")) {
|
|
28767
|
+
result.conflicts.push({
|
|
28768
|
+
type: "sql_objects",
|
|
28769
|
+
description: `Migration "${migration.name}" is MISSING SqlObjectHelper.ApplyAll(migrationBuilder) \u2014 ${sqlFiles.length} SQL object(s) found in SqlObjects/ will NOT be deployed`,
|
|
28770
|
+
files: [migration.file, ...sqlFiles.map((f) => path9.relative(structure.root, f))],
|
|
28771
|
+
resolution: 'Add "using SmartStack.Infrastructure.Persistence.SqlObjects;" at top and "SqlObjectHelper.ApplyAll(migrationBuilder);" at end of Up() method. Without this, TVFs/views/SPs will not exist in the database and cause runtime 500 errors.'
|
|
28772
|
+
});
|
|
28773
|
+
}
|
|
28774
|
+
}
|
|
28775
|
+
}
|
|
28748
28776
|
function generateSuggestions(result) {
|
|
28749
28777
|
if (result.conflicts.some((c) => c.type === "snapshot")) {
|
|
28750
28778
|
result.suggestions.push(
|
|
@@ -28761,6 +28789,11 @@ function generateSuggestions(result) {
|
|
|
28761
28789
|
"Ensure migrations are created in version order to avoid conflicts"
|
|
28762
28790
|
);
|
|
28763
28791
|
}
|
|
28792
|
+
if (result.conflicts.some((c) => c.type === "sql_objects")) {
|
|
28793
|
+
result.suggestions.push(
|
|
28794
|
+
"CRITICAL: Migrations missing SqlObjectHelper.ApplyAll(migrationBuilder) will cause ALL API endpoints to return 500 at runtime. Fix immediately."
|
|
28795
|
+
);
|
|
28796
|
+
}
|
|
28764
28797
|
if (result.migrations.length > 20) {
|
|
28765
28798
|
result.suggestions.push(
|
|
28766
28799
|
"Consider squashing old migrations to reduce complexity. Use: /efcore squash"
|
|
@@ -28794,7 +28827,7 @@ function formatResult2(result, currentBranch, compareBranch) {
|
|
|
28794
28827
|
lines.push("## Conflicts");
|
|
28795
28828
|
lines.push("");
|
|
28796
28829
|
for (const conflict of result.conflicts) {
|
|
28797
|
-
const icon = conflict.type === "snapshot" ? "\u{1F504}" : conflict.type === "order" ? "\u{1F4C5}" : conflict.type === "naming" ? "\u{1F4DD}" : "\u26A0\uFE0F";
|
|
28830
|
+
const icon = conflict.type === "snapshot" ? "\u{1F504}" : conflict.type === "order" ? "\u{1F4C5}" : conflict.type === "naming" ? "\u{1F4DD}" : conflict.type === "sql_objects" ? "\u{1F6A8}" : "\u26A0\uFE0F";
|
|
28798
28831
|
lines.push(`### ${icon} ${conflict.type.toUpperCase()}: ${conflict.description}`);
|
|
28799
28832
|
if (conflict.files.length > 0) {
|
|
28800
28833
|
lines.push(`- **Files**: ${conflict.files.map((f) => `\`${f}\``).join(", ")}`);
|
|
@@ -58588,12 +58621,16 @@ var init_scaffold_routes = __esm({
|
|
|
58588
58621
|
init_navroute_parser();
|
|
58589
58622
|
scaffoldRoutesTool = {
|
|
58590
58623
|
name: "scaffold_routes",
|
|
58591
|
-
description: `Generate
|
|
58624
|
+
description: `Generate frontend routing infrastructure from backend NavRoute attributes.
|
|
58592
58625
|
|
|
58593
|
-
Creates:
|
|
58626
|
+
Creates (v3.7+ DynamicRouter, default):
|
|
58627
|
+
- componentRegistry.generated.ts: PageRegistry.register() calls with lazy imports for DynamicRouter
|
|
58594
58628
|
- navRoutes.generated.ts: Registry of all routes with API paths and permissions
|
|
58595
|
-
|
|
58596
|
-
|
|
58629
|
+
|
|
58630
|
+
Creates (standalone, for non-SmartStack projects):
|
|
58631
|
+
- routes/index.tsx: createBrowserRouter() configuration with nested routes
|
|
58632
|
+
- navRoutes.generated.ts: Registry of all routes
|
|
58633
|
+
- Layout components and route guards (optional)
|
|
58597
58634
|
|
|
58598
58635
|
Example:
|
|
58599
58636
|
scaffold_routes source="controllers" scope="all"
|
|
@@ -59251,11 +59288,17 @@ var init_validate_frontend_routes = __esm({
|
|
|
59251
59288
|
name: "validate_frontend_routes",
|
|
59252
59289
|
description: `Validate frontend routes against backend NavRoute attributes.
|
|
59253
59290
|
|
|
59254
|
-
Checks:
|
|
59291
|
+
Checks (v3.7+ DynamicRouter pattern):
|
|
59292
|
+
- componentRegistry.generated.ts exists with all PageRegistry.register() entries
|
|
59293
|
+
- main.tsx imports componentRegistry.generated
|
|
59294
|
+
- Backend NavRoutes have matching component keys
|
|
59295
|
+
- API clients use getRoute() instead of hardcoded paths
|
|
59296
|
+
- No hardcoded navigate()/Link paths in page components
|
|
59297
|
+
|
|
59298
|
+
Checks (legacy pattern):
|
|
59255
59299
|
- navRoutes.generated.ts exists and is up-to-date
|
|
59256
|
-
- API clients use correct NavRoute paths
|
|
59257
59300
|
- React Router configuration matches backend routes
|
|
59258
|
-
-
|
|
59301
|
+
- App.tsx wiring is complete
|
|
59259
59302
|
|
|
59260
59303
|
Example:
|
|
59261
59304
|
validate_frontend_routes scope="all"
|