@atlashub/smartstack-cli 1.25.0 → 1.27.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/.documentation/commands.html +8 -8
- package/.documentation/efcore.html +13 -13
- package/.documentation/index.html +7 -7
- package/.documentation/installation.html +62 -121
- package/README.md +27 -49
- package/dist/index.js +133 -35
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/scripts/health-check.sh +167 -0
- package/scripts/postinstall.js +18 -0
package/dist/index.js
CHANGED
|
@@ -112862,29 +112862,28 @@ var installCommand = new Command("install").alias("i").description("Install Smar
|
|
|
112862
112862
|
`Files installed: ${source_default.cyan(result.installed)}`,
|
|
112863
112863
|
`Files skipped: ${source_default.yellow(result.skipped)} (use --force to overwrite)`,
|
|
112864
112864
|
"",
|
|
112865
|
-
"Available
|
|
112865
|
+
"Available skills in Claude Code:",
|
|
112866
112866
|
"",
|
|
112867
112867
|
source_default.bold("GitFlow:"),
|
|
112868
|
-
` ${source_default.cyan("/gitflow")}
|
|
112869
|
-
` ${source_default.cyan("/gitflow
|
|
112870
|
-
` ${source_default.cyan("/gitflow
|
|
112871
|
-
` ${source_default.cyan("/gitflow
|
|
112868
|
+
` ${source_default.cyan("/gitflow")} - Full GitFlow workflow`,
|
|
112869
|
+
` ${source_default.cyan("/gitflow start")} - Start feature/release/hotfix`,
|
|
112870
|
+
` ${source_default.cyan("/gitflow commit")} - Smart commit`,
|
|
112871
|
+
` ${source_default.cyan("/gitflow finish")} - Finish and merge`,
|
|
112872
112872
|
"",
|
|
112873
112873
|
source_default.bold("Development:"),
|
|
112874
|
-
` ${source_default.cyan("/apex")}
|
|
112875
|
-
` ${source_default.cyan("/
|
|
112876
|
-
` ${source_default.cyan("/
|
|
112874
|
+
` ${source_default.cyan("/apex")} - APEX methodology`,
|
|
112875
|
+
` ${source_default.cyan("/debug")} - Systematic debugging`,
|
|
112876
|
+
` ${source_default.cyan("/refactor")} - Code refactoring`,
|
|
112877
112877
|
"",
|
|
112878
112878
|
source_default.bold("Business Analysis:"),
|
|
112879
|
-
` ${source_default.cyan("/business-analyse")}
|
|
112879
|
+
` ${source_default.cyan("/business-analyse")} - Full BA workflow`,
|
|
112880
112880
|
"",
|
|
112881
112881
|
source_default.bold("EF Core:"),
|
|
112882
|
-
` ${source_default.cyan("/efcore")}
|
|
112883
|
-
` ${source_default.cyan("/efcore
|
|
112882
|
+
` ${source_default.cyan("/efcore")} - EF Core orchestrator`,
|
|
112883
|
+
` ${source_default.cyan("/efcore migration")} - Migration management`,
|
|
112884
112884
|
"",
|
|
112885
112885
|
source_default.bold("Ralph Loop:"),
|
|
112886
|
-
` ${source_default.cyan("/ralph-loop")}
|
|
112887
|
-
` ${source_default.cyan("/cancel-ralph")} - Cancel active loop`,
|
|
112886
|
+
` ${source_default.cyan("/ralph-loop")} - Start iterative loop`,
|
|
112888
112887
|
...pluginSummary
|
|
112889
112888
|
];
|
|
112890
112889
|
logger.box(summary, "success");
|
|
@@ -115575,6 +115574,65 @@ function validateCSharpNamespace(name) {
|
|
|
115575
115574
|
}
|
|
115576
115575
|
return { valid: true };
|
|
115577
115576
|
}
|
|
115577
|
+
async function detectProjectContext(name, here) {
|
|
115578
|
+
const cwd = process.cwd();
|
|
115579
|
+
if (name && !here) {
|
|
115580
|
+
const projectDir = (0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(cwd, name);
|
|
115581
|
+
const projectName = (0, import_path4.basename)(name);
|
|
115582
|
+
return { projectName, projectDir, inPlace: false };
|
|
115583
|
+
}
|
|
115584
|
+
const parentDir = (0, import_path4.dirname)(cwd);
|
|
115585
|
+
const currentFolderName = (0, import_path4.basename)(cwd);
|
|
115586
|
+
let detectedName;
|
|
115587
|
+
const gitflowConfigPath = (0, import_path4.join)(cwd, ".claude", "gitflow", "config.json");
|
|
115588
|
+
if (await import_fs_extra3.default.pathExists(gitflowConfigPath)) {
|
|
115589
|
+
try {
|
|
115590
|
+
const config = await import_fs_extra3.default.readJson(gitflowConfigPath);
|
|
115591
|
+
if (config.repository?.name) {
|
|
115592
|
+
detectedName = config.repository.name;
|
|
115593
|
+
}
|
|
115594
|
+
} catch {
|
|
115595
|
+
}
|
|
115596
|
+
}
|
|
115597
|
+
if (!detectedName) {
|
|
115598
|
+
const bareDir = (0, import_path4.join)(parentDir, ".bare");
|
|
115599
|
+
if (await import_fs_extra3.default.pathExists(bareDir)) {
|
|
115600
|
+
detectedName = (0, import_path4.basename)(parentDir);
|
|
115601
|
+
}
|
|
115602
|
+
}
|
|
115603
|
+
if (!detectedName) {
|
|
115604
|
+
const worktreePatterns = /^(\d+-)?(?:main|master|develop|development)$/i;
|
|
115605
|
+
if (worktreePatterns.test(currentFolderName)) {
|
|
115606
|
+
detectedName = (0, import_path4.basename)(parentDir);
|
|
115607
|
+
} else {
|
|
115608
|
+
detectedName = currentFolderName;
|
|
115609
|
+
}
|
|
115610
|
+
}
|
|
115611
|
+
return {
|
|
115612
|
+
projectName: detectedName,
|
|
115613
|
+
projectDir: cwd,
|
|
115614
|
+
inPlace: true
|
|
115615
|
+
};
|
|
115616
|
+
}
|
|
115617
|
+
async function validateInPlaceDirectory(projectDir) {
|
|
115618
|
+
if (await import_fs_extra3.default.pathExists((0, import_path4.join)(projectDir, ".smartstack", "config.json"))) {
|
|
115619
|
+
return 'SmartStack is already initialized in this directory. Use "ss update" to update.';
|
|
115620
|
+
}
|
|
115621
|
+
const files = await import_fs_extra3.default.readdir(projectDir);
|
|
115622
|
+
const hasSln = files.some((f) => f.endsWith(".sln"));
|
|
115623
|
+
if (hasSln) {
|
|
115624
|
+
return "A .NET solution already exists in this directory. Cannot initialize SmartStack here.";
|
|
115625
|
+
}
|
|
115626
|
+
const srcDir = (0, import_path4.join)(projectDir, "src");
|
|
115627
|
+
if (await import_fs_extra3.default.pathExists(srcDir)) {
|
|
115628
|
+
const srcFiles = await import_fs_extra3.default.readdir(srcDir);
|
|
115629
|
+
const hasCsproj = srcFiles.some((f) => f.endsWith(".csproj") || import_fs_extra3.default.statSync((0, import_path4.join)(srcDir, f)).isDirectory());
|
|
115630
|
+
if (hasCsproj) {
|
|
115631
|
+
return "A src/ directory with projects already exists. Cannot initialize SmartStack here.";
|
|
115632
|
+
}
|
|
115633
|
+
}
|
|
115634
|
+
return void 0;
|
|
115635
|
+
}
|
|
115578
115636
|
async function checkMcpServers() {
|
|
115579
115637
|
const result = {
|
|
115580
115638
|
smartstack: { installed: false },
|
|
@@ -115713,7 +115771,7 @@ async function createDualDbContextStructure(projectDir, projectName, dryRun) {
|
|
|
115713
115771
|
}
|
|
115714
115772
|
async function createBackendStructure(config, dryRun) {
|
|
115715
115773
|
const { name } = config;
|
|
115716
|
-
const projectDir = (0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name);
|
|
115774
|
+
const projectDir = config.projectDir ?? ((0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name));
|
|
115717
115775
|
const projectName = (0, import_path4.basename)(name);
|
|
115718
115776
|
const srcDir = (0, import_path4.join)(projectDir, "src");
|
|
115719
115777
|
const slnPath = (0, import_path4.join)(projectDir, `${projectName}.sln`);
|
|
@@ -115837,9 +115895,10 @@ EndGlobal
|
|
|
115837
115895
|
]
|
|
115838
115896
|
}
|
|
115839
115897
|
];
|
|
115898
|
+
const prereleaseFlag = config.preview ? " --prerelease" : "";
|
|
115840
115899
|
for (const { project, packages } of nugetPackages) {
|
|
115841
115900
|
for (const pkg2 of packages) {
|
|
115842
|
-
execCommand(`dotnet add "${(0, import_path4.join)(srcDir, project)}" package ${pkg2}`, void 0, dryRun);
|
|
115901
|
+
execCommand(`dotnet add "${(0, import_path4.join)(srcDir, project)}" package ${pkg2}${prereleaseFlag}`, void 0, dryRun);
|
|
115843
115902
|
}
|
|
115844
115903
|
}
|
|
115845
115904
|
if (!dryRun) {
|
|
@@ -115904,7 +115963,7 @@ app.Run();
|
|
|
115904
115963
|
}
|
|
115905
115964
|
async function createConfigFiles(config, dryRun) {
|
|
115906
115965
|
const { name } = config;
|
|
115907
|
-
const projectDir = (0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name);
|
|
115966
|
+
const projectDir = config.projectDir ?? ((0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name));
|
|
115908
115967
|
const projectName = (0, import_path4.basename)(name);
|
|
115909
115968
|
if (dryRun) {
|
|
115910
115969
|
logger.info("[DRY RUN] Would create configuration files");
|
|
@@ -116303,7 +116362,7 @@ Generated with [SmartStack CLI](https://atlashub.io/products/smartstack-cli)
|
|
|
116303
116362
|
}
|
|
116304
116363
|
async function createFrontendStructure(config, dryRun) {
|
|
116305
116364
|
const { name } = config;
|
|
116306
|
-
const projectDir = (0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name);
|
|
116365
|
+
const projectDir = config.projectDir ?? ((0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name));
|
|
116307
116366
|
const projectName = (0, import_path4.basename)(name);
|
|
116308
116367
|
const webDir = (0, import_path4.join)(projectDir, "web", `${projectName.toLowerCase()}-web`);
|
|
116309
116368
|
logger.info("Creating React frontend structure...");
|
|
@@ -116320,6 +116379,7 @@ async function createFrontendStructure(config, dryRun) {
|
|
|
116320
116379
|
await import_fs_extra3.default.ensureDir((0, import_path4.join)(webDir, "src", "types"));
|
|
116321
116380
|
await import_fs_extra3.default.ensureDir((0, import_path4.join)(webDir, "src", "i18n"));
|
|
116322
116381
|
await import_fs_extra3.default.ensureDir((0, import_path4.join)(webDir, "public"));
|
|
116382
|
+
const smartstackNpmTag = config.preview ? "next" : "latest";
|
|
116323
116383
|
const packageJson = {
|
|
116324
116384
|
name: `${projectName.toLowerCase()}-web`,
|
|
116325
116385
|
private: true,
|
|
@@ -116334,7 +116394,7 @@ async function createFrontendStructure(config, dryRun) {
|
|
|
116334
116394
|
preview: "vite preview"
|
|
116335
116395
|
},
|
|
116336
116396
|
dependencies: {
|
|
116337
|
-
"@atlashub/smartstack":
|
|
116397
|
+
"@atlashub/smartstack": smartstackNpmTag,
|
|
116338
116398
|
"@microsoft/signalr": "latest",
|
|
116339
116399
|
"@tailwindcss/vite": "latest",
|
|
116340
116400
|
axios: "latest",
|
|
@@ -116647,13 +116707,21 @@ Thumbs.db
|
|
|
116647
116707
|
}
|
|
116648
116708
|
async function initializeGit(config, dryRun) {
|
|
116649
116709
|
const { name } = config;
|
|
116650
|
-
const projectDir = (0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name);
|
|
116651
|
-
|
|
116652
|
-
|
|
116653
|
-
|
|
116654
|
-
|
|
116710
|
+
const projectDir = config.projectDir ?? ((0, import_path4.isAbsolute)(name) ? name : (0, import_path4.join)(process.cwd(), name));
|
|
116711
|
+
const gitDir = (0, import_path4.join)(projectDir, ".git");
|
|
116712
|
+
const isGitInitialized = await import_fs_extra3.default.pathExists(gitDir);
|
|
116713
|
+
if (isGitInitialized) {
|
|
116714
|
+
logger.info("Git repository already initialized, adding SmartStack files...");
|
|
116715
|
+
execCommand("git add .", projectDir, dryRun);
|
|
116716
|
+
execCommand('git commit -m "feat: initialize SmartStack project structure"', projectDir, dryRun);
|
|
116717
|
+
} else {
|
|
116718
|
+
logger.info("Initializing Git repository...");
|
|
116719
|
+
execCommand("git init", projectDir, dryRun);
|
|
116720
|
+
execCommand("git add .", projectDir, dryRun);
|
|
116721
|
+
execCommand('git commit -m "chore: initial SmartStack project setup"', projectDir, dryRun);
|
|
116722
|
+
}
|
|
116655
116723
|
}
|
|
116656
|
-
var initCommand = new Command("init").description("Initialize a new SmartStack project").argument("
|
|
116724
|
+
var initCommand = new Command("init").description("Initialize a new SmartStack project").argument("[name]", "Project name (optional, uses current folder if not provided)").option("--dry-run", "Show what would be created without actually creating").option("-y, --yes", "Skip prompts and use defaults").option("--skip-mcp-check", "Skip MCP servers verification").option("--multi-tenant", "Enable multi-tenant mode").option("--b2c", "Enable B2C (user tenant management)").option("--preview", "Use preview/prerelease versions (NuGet --prerelease + npm @next)").option("--here", "Initialize in current directory (use folder name as project name)").action(async (name, options) => {
|
|
116657
116725
|
logger.header("SmartStack Project Initialization");
|
|
116658
116726
|
if (!options.skipMcpCheck) {
|
|
116659
116727
|
logger.info("Checking MCP servers...");
|
|
@@ -116712,8 +116780,37 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
|
|
|
116712
116780
|
logger.error(".NET SDK not found. Please install .NET 10.0 or later.");
|
|
116713
116781
|
process.exit(1);
|
|
116714
116782
|
}
|
|
116715
|
-
const
|
|
116716
|
-
const projectName =
|
|
116783
|
+
const context = await detectProjectContext(name, options.here ?? false);
|
|
116784
|
+
const { projectName, projectDir, inPlace } = context;
|
|
116785
|
+
if (inPlace) {
|
|
116786
|
+
logger.info(`Detected project: ${source_default.cyan(projectName)}`);
|
|
116787
|
+
logger.info(`Directory: ${source_default.cyan(projectDir)}`);
|
|
116788
|
+
const inPlaceError = await validateInPlaceDirectory(projectDir);
|
|
116789
|
+
if (inPlaceError) {
|
|
116790
|
+
logger.error(inPlaceError);
|
|
116791
|
+
process.exit(1);
|
|
116792
|
+
}
|
|
116793
|
+
if (!options.yes) {
|
|
116794
|
+
const { confirm } = await lib_default.prompt([
|
|
116795
|
+
{
|
|
116796
|
+
type: "confirm",
|
|
116797
|
+
name: "confirm",
|
|
116798
|
+
message: `Initialize SmartStack project "${projectName}" in current directory?`,
|
|
116799
|
+
default: true
|
|
116800
|
+
}
|
|
116801
|
+
]);
|
|
116802
|
+
if (!confirm) {
|
|
116803
|
+
logger.info("Cancelled by user.");
|
|
116804
|
+
process.exit(0);
|
|
116805
|
+
}
|
|
116806
|
+
}
|
|
116807
|
+
} else {
|
|
116808
|
+
if (await import_fs_extra3.default.pathExists(projectDir)) {
|
|
116809
|
+
logger.error(`Directory '${projectDir}' already exists.`);
|
|
116810
|
+
logger.info(`Tip: Use ${source_default.cyan("--here")} to initialize in the current directory instead.`);
|
|
116811
|
+
process.exit(1);
|
|
116812
|
+
}
|
|
116813
|
+
}
|
|
116717
116814
|
const validation = validateCSharpNamespace(projectName);
|
|
116718
116815
|
if (!validation.valid) {
|
|
116719
116816
|
logger.error(`Invalid project name: ${validation.error}`);
|
|
@@ -116722,16 +116819,14 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
|
|
|
116722
116819
|
}
|
|
116723
116820
|
process.exit(1);
|
|
116724
116821
|
}
|
|
116725
|
-
if (await import_fs_extra3.default.pathExists(projectDir)) {
|
|
116726
|
-
logger.error(`Directory '${projectDir}' already exists.`);
|
|
116727
|
-
process.exit(1);
|
|
116728
|
-
}
|
|
116729
116822
|
let config;
|
|
116730
116823
|
if (options.yes) {
|
|
116731
116824
|
config = {
|
|
116732
|
-
name,
|
|
116733
|
-
nameLower:
|
|
116825
|
+
name: projectName,
|
|
116826
|
+
nameLower: projectName.toLowerCase(),
|
|
116734
116827
|
database: "sqlserver",
|
|
116828
|
+
preview: options.preview ?? false,
|
|
116829
|
+
projectDir: inPlace ? projectDir : void 0,
|
|
116735
116830
|
multiTenant: {
|
|
116736
116831
|
enabled: options.multiTenant ?? true,
|
|
116737
116832
|
enableB2C: options.b2c ?? true,
|
|
@@ -116771,9 +116866,11 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
|
|
|
116771
116866
|
}
|
|
116772
116867
|
]);
|
|
116773
116868
|
config = {
|
|
116774
|
-
name,
|
|
116775
|
-
nameLower:
|
|
116869
|
+
name: projectName,
|
|
116870
|
+
nameLower: projectName.toLowerCase(),
|
|
116776
116871
|
database: "sqlserver",
|
|
116872
|
+
preview: options.preview ?? false,
|
|
116873
|
+
projectDir: inPlace ? projectDir : void 0,
|
|
116777
116874
|
multiTenant: {
|
|
116778
116875
|
enabled: answers.multiTenantEnabled ?? true,
|
|
116779
116876
|
enableB2C: answers.enableB2C ?? true,
|
|
@@ -116790,6 +116887,7 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
|
|
|
116790
116887
|
console.log();
|
|
116791
116888
|
logger.info(`Project: ${source_default.cyan(config.name)}`);
|
|
116792
116889
|
logger.info(`Database: ${source_default.cyan("SQL Server")}`);
|
|
116890
|
+
logger.info(`Preview mode: ${config.preview ? source_default.yellow("Enabled (prerelease)") : source_default.gray("Disabled (stable)")}`);
|
|
116793
116891
|
logger.info(`Multi-Tenant: ${config.multiTenant.enabled ? source_default.green("Enabled") : source_default.gray("Disabled")}`);
|
|
116794
116892
|
if (config.multiTenant.enabled) {
|
|
116795
116893
|
logger.info(` B2C (User Tenants): ${config.multiTenant.enableB2C ? source_default.green("Enabled") : source_default.gray("Disabled")}`);
|
|
@@ -116797,7 +116895,7 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
|
|
|
116797
116895
|
}
|
|
116798
116896
|
console.log();
|
|
116799
116897
|
try {
|
|
116800
|
-
if (!dryRun) {
|
|
116898
|
+
if (!dryRun && !inPlace) {
|
|
116801
116899
|
await import_fs_extra3.default.ensureDir(projectDir);
|
|
116802
116900
|
}
|
|
116803
116901
|
await createBackendStructure(config, dryRun);
|