@atlashub/smartstack-mcp 1.2.0 → 1.2.2
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/README.md +88 -199
- package/config/default-config.json +62 -62
- package/dist/index.js +89 -61
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/component.tsx.hbs +298 -298
- package/templates/controller.cs.hbs +166 -166
- package/templates/entity-extension.cs.hbs +87 -87
- package/templates/service-extension.cs.hbs +53 -53
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
#!/usr/bin/env node
|
|
3
2
|
|
|
4
3
|
// src/server.ts
|
|
5
4
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -149,7 +148,7 @@ var defaultConfig = {
|
|
|
149
148
|
"loc_",
|
|
150
149
|
"lic_"
|
|
151
150
|
],
|
|
152
|
-
migrationFormat: "
|
|
151
|
+
migrationFormat: "{context}_v{version}_{sequence}_{Description}",
|
|
153
152
|
namespaces: {
|
|
154
153
|
domain: "SmartStack.Domain",
|
|
155
154
|
application: "SmartStack.Application",
|
|
@@ -281,7 +280,7 @@ var ConventionsConfigSchema = z.object({
|
|
|
281
280
|
"loc_",
|
|
282
281
|
"lic_"
|
|
283
282
|
]),
|
|
284
|
-
migrationFormat: z.string().default("
|
|
283
|
+
migrationFormat: z.string().default("{context}_v{version}_{sequence}_{Description}"),
|
|
285
284
|
namespaces: z.object({
|
|
286
285
|
domain: z.string(),
|
|
287
286
|
application: z.string(),
|
|
@@ -533,7 +532,7 @@ async function findControllerFiles(apiPath) {
|
|
|
533
532
|
import path5 from "path";
|
|
534
533
|
var validateConventionsTool = {
|
|
535
534
|
name: "validate_conventions",
|
|
536
|
-
description: "Validate AtlasHub/SmartStack conventions: SQL schemas (core/extensions), domain table prefixes (auth_, nav_, ai_, etc.), migration naming (
|
|
535
|
+
description: "Validate AtlasHub/SmartStack conventions: SQL schemas (core/extensions), domain table prefixes (auth_, nav_, ai_, etc.), migration naming ({context}_v{version}_{sequence}_*), service interfaces (I*Service), namespace structure",
|
|
537
536
|
inputSchema: {
|
|
538
537
|
type: "object",
|
|
539
538
|
properties: {
|
|
@@ -675,7 +674,7 @@ async function validateMigrationNaming(structure, _config, result) {
|
|
|
675
674
|
return;
|
|
676
675
|
}
|
|
677
676
|
const migrationFiles = await findFiles("*.cs", { cwd: structure.migrations });
|
|
678
|
-
const migrationPattern = /^(\d
|
|
677
|
+
const migrationPattern = /^(\w+)_v(\d+\.\d+\.\d+)_(\d{3})_(.+)\.cs$/;
|
|
679
678
|
const designerPattern = /\.Designer\.cs$/;
|
|
680
679
|
for (const file of migrationFiles) {
|
|
681
680
|
const fileName = path5.basename(file);
|
|
@@ -688,7 +687,7 @@ async function validateMigrationNaming(structure, _config, result) {
|
|
|
688
687
|
category: "migrations",
|
|
689
688
|
message: `Migration "${fileName}" does not follow naming convention`,
|
|
690
689
|
file: path5.relative(structure.root, file),
|
|
691
|
-
suggestion: `Expected format:
|
|
690
|
+
suggestion: `Expected format: {context}_v{version}_{sequence}_{Description}.cs (e.g., core_v1.0.0_001_CreateAuthUsers.cs)`
|
|
692
691
|
});
|
|
693
692
|
}
|
|
694
693
|
}
|
|
@@ -696,14 +695,18 @@ async function validateMigrationNaming(structure, _config, result) {
|
|
|
696
695
|
for (let i = 1; i < orderedMigrations.length; i++) {
|
|
697
696
|
const prev = orderedMigrations[i - 1];
|
|
698
697
|
const curr = orderedMigrations[i];
|
|
699
|
-
const
|
|
700
|
-
const
|
|
701
|
-
if (
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
698
|
+
const prevMatch = migrationPattern.exec(prev);
|
|
699
|
+
const currMatch = migrationPattern.exec(curr);
|
|
700
|
+
if (prevMatch && currMatch) {
|
|
701
|
+
const prevVersion = prevMatch[2];
|
|
702
|
+
const currVersion = currMatch[2];
|
|
703
|
+
if (currVersion < prevVersion) {
|
|
704
|
+
result.warnings.push({
|
|
705
|
+
type: "warning",
|
|
706
|
+
category: "migrations",
|
|
707
|
+
message: `Migration order issue: "${curr}" (v${currVersion}) comes before "${prev}" (v${prevVersion})`
|
|
708
|
+
});
|
|
709
|
+
}
|
|
707
710
|
}
|
|
708
711
|
}
|
|
709
712
|
}
|
|
@@ -871,7 +874,7 @@ async function handleCheckMigrations(args, config) {
|
|
|
871
874
|
async function parseMigrations(migrationsPath, rootPath) {
|
|
872
875
|
const files = await findFiles("*.cs", { cwd: migrationsPath });
|
|
873
876
|
const migrations = [];
|
|
874
|
-
const pattern = /^(\d
|
|
877
|
+
const pattern = /^(\w+)_v(\d+\.\d+\.\d+)_(\d{3})_(.+)\.cs$/;
|
|
875
878
|
for (const file of files) {
|
|
876
879
|
const fileName = path6.basename(file);
|
|
877
880
|
if (fileName.includes(".Designer.") || fileName.includes("ModelSnapshot")) {
|
|
@@ -881,10 +884,13 @@ async function parseMigrations(migrationsPath, rootPath) {
|
|
|
881
884
|
if (match) {
|
|
882
885
|
migrations.push({
|
|
883
886
|
name: fileName.replace(".cs", ""),
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
887
|
+
context: match[1],
|
|
888
|
+
// DbContext (core, extensions, etc.)
|
|
889
|
+
version: match[2],
|
|
890
|
+
// Semver version (1.0.0, 1.2.0, etc.)
|
|
891
|
+
sequence: match[3],
|
|
892
|
+
// Sequence number (001, 002, etc.)
|
|
893
|
+
description: match[4],
|
|
888
894
|
file: path6.relative(rootPath, file),
|
|
889
895
|
applied: true
|
|
890
896
|
// We'd need DB connection to check this
|
|
@@ -892,8 +898,9 @@ async function parseMigrations(migrationsPath, rootPath) {
|
|
|
892
898
|
} else {
|
|
893
899
|
migrations.push({
|
|
894
900
|
name: fileName.replace(".cs", ""),
|
|
895
|
-
|
|
896
|
-
|
|
901
|
+
context: "Unknown",
|
|
902
|
+
version: "0.0.0",
|
|
903
|
+
sequence: "000",
|
|
897
904
|
description: fileName.replace(".cs", ""),
|
|
898
905
|
file: path6.relative(rootPath, file),
|
|
899
906
|
applied: true
|
|
@@ -901,51 +908,63 @@ async function parseMigrations(migrationsPath, rootPath) {
|
|
|
901
908
|
}
|
|
902
909
|
}
|
|
903
910
|
return migrations.sort((a, b) => {
|
|
904
|
-
const
|
|
905
|
-
if (
|
|
906
|
-
return a.
|
|
911
|
+
const versionCompare = compareVersions(a.version, b.version);
|
|
912
|
+
if (versionCompare !== 0) return versionCompare;
|
|
913
|
+
return a.sequence.localeCompare(b.sequence);
|
|
907
914
|
});
|
|
908
915
|
}
|
|
916
|
+
function compareVersions(a, b) {
|
|
917
|
+
const partsA = a.split(".").map(Number);
|
|
918
|
+
const partsB = b.split(".").map(Number);
|
|
919
|
+
for (let i = 0; i < 3; i++) {
|
|
920
|
+
if (partsA[i] > partsB[i]) return 1;
|
|
921
|
+
if (partsA[i] < partsB[i]) return -1;
|
|
922
|
+
}
|
|
923
|
+
return 0;
|
|
924
|
+
}
|
|
909
925
|
function checkNamingConventions(result, _config) {
|
|
910
926
|
for (const migration of result.migrations) {
|
|
911
|
-
if (
|
|
927
|
+
if (migration.context === "Unknown") {
|
|
912
928
|
result.conflicts.push({
|
|
913
929
|
type: "naming",
|
|
914
930
|
description: `Migration "${migration.name}" does not follow naming convention`,
|
|
915
931
|
files: [migration.file],
|
|
916
|
-
resolution: `Rename to format:
|
|
932
|
+
resolution: `Rename to format: {context}_v{version}_{sequence}_{Description} (e.g., core_v1.0.0_001_CreateAuthUsers)`
|
|
917
933
|
});
|
|
918
934
|
}
|
|
919
|
-
if (migration.
|
|
935
|
+
if (migration.version === "0.0.0") {
|
|
920
936
|
result.conflicts.push({
|
|
921
937
|
type: "naming",
|
|
922
|
-
description: `Migration "${migration.name}" missing
|
|
938
|
+
description: `Migration "${migration.name}" missing version number`,
|
|
923
939
|
files: [migration.file],
|
|
924
|
-
resolution: `Use format:
|
|
940
|
+
resolution: `Use format: {context}_v{version}_{sequence}_{Description} where version is semver (1.0.0, 1.2.0, etc.)`
|
|
925
941
|
});
|
|
926
942
|
}
|
|
927
943
|
}
|
|
928
944
|
}
|
|
929
945
|
function checkChronologicalOrder(result) {
|
|
930
|
-
const migrations = result.migrations.filter((m) => m.
|
|
946
|
+
const migrations = result.migrations.filter((m) => m.context !== "Unknown");
|
|
931
947
|
for (let i = 1; i < migrations.length; i++) {
|
|
932
948
|
const prev = migrations[i - 1];
|
|
933
949
|
const curr = migrations[i];
|
|
934
|
-
if (curr.
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
950
|
+
if (curr.context === prev.context) {
|
|
951
|
+
const versionCompare = compareVersions(curr.version, prev.version);
|
|
952
|
+
if (versionCompare < 0) {
|
|
953
|
+
result.conflicts.push({
|
|
954
|
+
type: "order",
|
|
955
|
+
description: `Migration "${curr.name}" (v${curr.version}) is versioned before "${prev.name}" (v${prev.version})`,
|
|
956
|
+
files: [curr.file, prev.file],
|
|
957
|
+
resolution: "Reorder migrations or update version numbers"
|
|
958
|
+
});
|
|
959
|
+
}
|
|
960
|
+
if (curr.version === prev.version && curr.sequence === prev.sequence) {
|
|
961
|
+
result.conflicts.push({
|
|
962
|
+
type: "order",
|
|
963
|
+
description: `Migrations "${curr.name}" and "${prev.name}" have same version and sequence`,
|
|
964
|
+
files: [curr.file, prev.file],
|
|
965
|
+
resolution: "Use different sequence numbers (001, 002, etc.) for migrations in the same version"
|
|
966
|
+
});
|
|
967
|
+
}
|
|
949
968
|
}
|
|
950
969
|
}
|
|
951
970
|
}
|
|
@@ -1000,7 +1019,7 @@ async function checkModelSnapshot(result, structure) {
|
|
|
1000
1019
|
}
|
|
1001
1020
|
const snapshotContent = await readText(snapshotFiles[0]);
|
|
1002
1021
|
for (const migration of result.migrations) {
|
|
1003
|
-
if (migration.
|
|
1022
|
+
if (migration.context !== "Unknown" && !snapshotContent.includes(migration.name)) {
|
|
1004
1023
|
result.conflicts.push({
|
|
1005
1024
|
type: "dependency",
|
|
1006
1025
|
description: `Migration "${migration.name}" not referenced in ModelSnapshot`,
|
|
@@ -1018,12 +1037,12 @@ function generateSuggestions(result) {
|
|
|
1018
1037
|
}
|
|
1019
1038
|
if (result.conflicts.some((c) => c.type === "naming")) {
|
|
1020
1039
|
result.suggestions.push(
|
|
1021
|
-
"Use convention:
|
|
1040
|
+
"Use convention: {context}_v{version}_{sequence}_{Description} for migration naming (e.g., core_v1.0.0_001_CreateAuthUsers)"
|
|
1022
1041
|
);
|
|
1023
1042
|
}
|
|
1024
1043
|
if (result.conflicts.some((c) => c.type === "order")) {
|
|
1025
1044
|
result.suggestions.push(
|
|
1026
|
-
"Ensure migrations are created in
|
|
1045
|
+
"Ensure migrations are created in version order to avoid conflicts"
|
|
1027
1046
|
);
|
|
1028
1047
|
}
|
|
1029
1048
|
if (result.migrations.length > 20) {
|
|
@@ -1047,11 +1066,11 @@ function formatResult2(result, currentBranch, compareBranch) {
|
|
|
1047
1066
|
lines.push("");
|
|
1048
1067
|
lines.push("## Migrations");
|
|
1049
1068
|
lines.push("");
|
|
1050
|
-
lines.push("| Name |
|
|
1051
|
-
lines.push("
|
|
1069
|
+
lines.push("| Name | Context | Version | Sequence | Description |");
|
|
1070
|
+
lines.push("|------|---------|---------|----------|-------------|");
|
|
1052
1071
|
for (const migration of result.migrations) {
|
|
1053
1072
|
lines.push(
|
|
1054
|
-
`| ${migration.name} | ${migration.
|
|
1073
|
+
`| ${migration.name} | ${migration.context} | ${migration.version} | ${migration.sequence} | ${migration.description} |`
|
|
1055
1074
|
);
|
|
1056
1075
|
}
|
|
1057
1076
|
lines.push("");
|
|
@@ -1978,28 +1997,37 @@ Migrations MUST follow this naming pattern:
|
|
|
1978
1997
|
${migrationFormat}
|
|
1979
1998
|
\`\`\`
|
|
1980
1999
|
|
|
2000
|
+
| Part | Description | Example |
|
|
2001
|
+
|------|-------------|---------|
|
|
2002
|
+
| \`{context}\` | DbContext name | \`core\`, \`extensions\` |
|
|
2003
|
+
| \`{version}\` | Semver version | \`v1.0.0\`, \`v1.2.0\` |
|
|
2004
|
+
| \`{sequence}\` | Order in version | \`001\`, \`002\` |
|
|
2005
|
+
| \`{Description}\` | Action (PascalCase) | \`CreateAuthUsers\` |
|
|
2006
|
+
|
|
1981
2007
|
**Examples:**
|
|
1982
|
-
- \`
|
|
1983
|
-
- \`
|
|
1984
|
-
- \`
|
|
2008
|
+
- \`core_v1.0.0_001_InitialSchema.cs\`
|
|
2009
|
+
- \`core_v1.0.0_002_CreateAuthUsers.cs\`
|
|
2010
|
+
- \`core_v1.2.0_001_AddUserProfiles.cs\`
|
|
2011
|
+
- \`extensions_v1.0.0_001_AddClientFeatures.cs\`
|
|
1985
2012
|
|
|
1986
2013
|
### Creating Migrations
|
|
1987
2014
|
|
|
1988
2015
|
\`\`\`bash
|
|
1989
2016
|
# Create a new migration
|
|
1990
|
-
dotnet ef migrations add
|
|
2017
|
+
dotnet ef migrations add core_v1.0.0_001_InitialSchema
|
|
1991
2018
|
|
|
1992
2019
|
# With context specified
|
|
1993
|
-
dotnet ef migrations add
|
|
2020
|
+
dotnet ef migrations add core_v1.2.0_001_AddUserProfiles --context ApplicationDbContext
|
|
1994
2021
|
\`\`\`
|
|
1995
2022
|
|
|
1996
2023
|
### Migration Rules
|
|
1997
2024
|
|
|
1998
2025
|
1. **One migration per feature** - Group related changes in a single migration
|
|
1999
|
-
2. **
|
|
2000
|
-
3. **Sequence numbers** - Use NNN (001, 002, etc.) for migrations
|
|
2001
|
-
4. **
|
|
2002
|
-
5. **
|
|
2026
|
+
2. **Version-based naming** - Use semver (v1.0.0, v1.2.0) to link migrations to releases
|
|
2027
|
+
3. **Sequence numbers** - Use NNN (001, 002, etc.) for migrations in the same version
|
|
2028
|
+
4. **Context prefix** - Use \`core_\` for platform tables, \`extensions_\` for client extensions
|
|
2029
|
+
5. **Descriptive names** - Use clear PascalCase descriptions (CreateAuthUsers, AddUserProfiles, etc.)
|
|
2030
|
+
6. **Schema must be specified** - All tables must specify their schema in ToTable()
|
|
2003
2031
|
|
|
2004
2032
|
---
|
|
2005
2033
|
|
|
@@ -2166,7 +2194,7 @@ public interface IUserServiceHooks
|
|
|
2166
2194
|
| Platform schema | \`${schemas.platform}\` | \`.ToTable("auth_Users", "${schemas.platform}")\` |
|
|
2167
2195
|
| Extensions schema | \`${schemas.extensions}\` | \`.ToTable("client_Custom", "${schemas.extensions}")\` |
|
|
2168
2196
|
| Table prefixes | \`${tablePrefixes.slice(0, 5).join(", ")}\`, etc. | \`auth_Users\`, \`nav_Modules\` |
|
|
2169
|
-
| Migration | \`
|
|
2197
|
+
| Migration | \`{context}_v{version}_{seq}_{Desc}\` | \`core_v1.0.0_001_CreateAuthUsers\` |
|
|
2170
2198
|
| Interface | \`I<Name>Service\` | \`IUserService\` |
|
|
2171
2199
|
| Implementation | \`<Name>Service\` | \`UserService\` |
|
|
2172
2200
|
| Domain namespace | \`${namespaces.domain}\` | - |
|