@atlashub/smartstack-cli 4.69.0 → 4.71.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.
@@ -1,95 +1,75 @@
1
- {
2
- "$schema": "https://atlashub.ch/schemas/claude-gitflow-config.json",
3
- "version": "2.0.0",
4
- "worktrees": {
5
- "enabled": true,
6
- "mode": "organized",
7
- "structure": {
8
- "features": "../features",
9
- "releases": "../releases",
10
- "hotfixes": "../hotfixes"
11
- }
12
- },
13
- "git": {
14
- "branches": {
15
- "main": "main",
16
- "develop": "develop",
17
- "featurePrefix": "feature/",
18
- "releasePrefix": "release/",
19
- "hotfixPrefix": "hotfix/"
20
- },
21
- "remote": "origin",
22
- "mergeStrategy": "--no-ff",
23
- "tagPrefix": "v",
24
- "protectedBranches": ["main", "develop"],
25
- "requireLinearHistory": false
26
- },
27
- "efcore": {
28
- "enabled": true,
29
- "autoDetect": true,
30
- "contexts": [
31
- {
32
- "name": "ApplicationDbContext",
33
- "projectPath": "auto-detect",
34
- "startupProject": "auto-detect",
35
- "migrationsFolder": "Migrations",
36
- "migrationsAssembly": null
37
- }
38
- ],
39
- "scripts": {
40
- "generateOnRelease": true,
41
- "generateOnHotfix": true,
42
- "idempotent": true,
43
- "outputPath": "./scripts/migrations",
44
- "namingPattern": "{type}_{version}_{timestamp}.sql"
45
- },
46
- "validation": {
47
- "validateBeforeCommit": true,
48
- "validateBeforeMerge": true,
49
- "checkModelSnapshotConflicts": true,
50
- "requireBuildSuccess": true,
51
- "warnOnPendingMigrations": true
52
- },
53
- "backup": {
54
- "enabled": true,
55
- "beforeRebase": true,
56
- "beforeMerge": true,
57
- "retentionDays": 7
58
- },
59
- "naming": {
60
- "migrationPrefix": "",
61
- "hotfixPrefix": "Hotfix_",
62
- "timestampFormat": "yyyyMMddHHmmss"
63
- }
64
- },
65
- "workflow": {
66
- "requireConfirmation": true,
67
- "autoDeleteBranch": false,
68
- "createCheckpoints": true,
69
- "verboseLogging": false,
70
- "interactiveMode": true,
71
- "commitConventions": {
72
- "enabled": true,
73
- "migration": "db(migrations): ",
74
- "feature": "feat: ",
75
- "fix": "fix: ",
76
- "release": "release: ",
77
- "hotfix": "hotfix: ",
78
- "chore": "chore: "
79
- },
80
- "hooks": {
81
- "prePlan": null,
82
- "postPlan": null,
83
- "preExec": null,
84
- "postExec": null,
85
- "preCommit": null,
86
- "postCommit": null
87
- }
88
- },
89
- "ui": {
90
- "colors": true,
91
- "showProgress": true,
92
- "compactMode": false,
93
- "language": "fr"
94
- }
95
- }
1
+ {
2
+ "$schema": "https://atlashub.ch/schemas/claude-gitflow-config.json",
3
+ "version": "2.1.0",
4
+ "platform": {
5
+ "detected": "",
6
+ "shell": "",
7
+ "detectedAt": ""
8
+ },
9
+ "workspace": {
10
+ "path": "",
11
+ "name": ""
12
+ },
13
+ "repository": {
14
+ "name": "",
15
+ "rootFolder": "",
16
+ "nameVariants": {
17
+ "pascalCaseDot": "",
18
+ "pascalCase": "",
19
+ "kebabCase": "",
20
+ "snakeCase": "",
21
+ "displayName": ""
22
+ },
23
+ "defaultBranch": "main",
24
+ "remoteUrl": ""
25
+ },
26
+ "git": {
27
+ "provider": "",
28
+ "branches": {
29
+ "main": "main",
30
+ "develop": "develop"
31
+ },
32
+ "prefixes": {
33
+ "feature": "feature/",
34
+ "release": "release/",
35
+ "hotfix": "hotfix/"
36
+ }
37
+ },
38
+ "worktrees": {
39
+ "enabled": true,
40
+ "mode": "organized",
41
+ "structure": {
42
+ "main": "",
43
+ "develop": "",
44
+ "features": "",
45
+ "releases": "",
46
+ "hotfixes": ""
47
+ }
48
+ },
49
+ "versioning": {
50
+ "strategy": "semver",
51
+ "current": "0.0.0",
52
+ "tagPrefix": "v",
53
+ "sources": ["csproj", "package.json", "VERSION"]
54
+ },
55
+ "efcore": {
56
+ "enabled": true,
57
+ "validateOnCommit": true,
58
+ "blockDestructive": true,
59
+ "migrationNaming": "{context}_v{version}_{sequence}_{Description}",
60
+ "migrationNamingSquash": "{context}_v{version}",
61
+ "squashBeforePR": true
62
+ },
63
+ "workflow": {
64
+ "push": {
65
+ "afterCommit": "worktree"
66
+ },
67
+ "pr": {
68
+ "autoLabels": true,
69
+ "requireReview": true
70
+ }
71
+ },
72
+ "language": {
73
+ "code": "en"
74
+ }
75
+ }
package/dist/index.js CHANGED
@@ -112390,7 +112390,8 @@ async function readClaudeSettings() {
112390
112390
  return null;
112391
112391
  }
112392
112392
  const raw = await import_fs_extra.default.readFile(settingsPath, "utf-8");
112393
- return JSON.parse(raw);
112393
+ const cleaned = stripJsonComments(raw);
112394
+ return JSON.parse(cleaned);
112394
112395
  } catch {
112395
112396
  return null;
112396
112397
  }
@@ -112424,7 +112425,11 @@ async function registerMcpInClaudeSettings(servers) {
112424
112425
  try {
112425
112426
  logger.debug(`Home directory: ${(0, import_os.homedir)()}`);
112426
112427
  logger.debug(`Target settings path: ${settingsPath}`);
112427
- const settings = await readClaudeSettings() || {};
112428
+ const existingSettings = await readClaudeSettings();
112429
+ if (existingSettings === null && await import_fs_extra.default.pathExists(settingsPath)) {
112430
+ return { success: false, path: settingsPath, error: "Cannot parse existing settings.json" };
112431
+ }
112432
+ const settings = existingSettings || {};
112428
112433
  const mcpServers = settings["mcpServers"] || {};
112429
112434
  for (const server of servers) {
112430
112435
  mcpServers[server.name] = {
@@ -112482,7 +112487,12 @@ async function unregisterMcpFromClaudeSettings(serverNames) {
112482
112487
  async function configureClaudeEnvironment() {
112483
112488
  const settingsPath = getClaudeSettingsPath();
112484
112489
  try {
112485
- const settings = await readClaudeSettings() || {};
112490
+ const existingSettings = await readClaudeSettings();
112491
+ if (existingSettings === null && await import_fs_extra.default.pathExists(settingsPath)) {
112492
+ logger.warning("Cannot parse existing settings.json \u2014 skipping to avoid data loss");
112493
+ return { success: false, path: settingsPath, error: "Cannot parse existing settings.json" };
112494
+ }
112495
+ const settings = existingSettings || {};
112486
112496
  const env2 = settings["env"] || {};
112487
112497
  let changed = false;
112488
112498
  if (env2["CLAUDE_CODE_MAX_OUTPUT_TOKENS"] !== "64000") {
@@ -116869,7 +116879,9 @@ EndGlobal
116869
116879
  "Microsoft.AspNetCore.Authentication.JwtBearer",
116870
116880
  "Microsoft.EntityFrameworkCore.Design",
116871
116881
  // Required for EF Core migrations
116872
- "Swashbuckle.AspNetCore"
116882
+ "Swashbuckle.AspNetCore",
116883
+ "Microsoft.AspNetCore.SignalR.StackExchangeRedis"
116884
+ // SignalR Redis backplane (not transitive from SmartStack NuGet)
116873
116885
  ]
116874
116886
  }
116875
116887
  ];
@@ -117877,7 +117889,7 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
117877
117889
  ]);
117878
117890
  if (!continueWithoutMcp) {
117879
117891
  logger.info("Install MCP servers and try again.");
117880
- process.exit(0);
117892
+ return;
117881
117893
  }
117882
117894
  } else {
117883
117895
  logger.warning("Continuing without MCP servers (--yes mode)");
@@ -117930,18 +117942,21 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
117930
117942
  logger.error("Installation completed but .NET SDK still not detected.");
117931
117943
  logger.info("You may need to restart your terminal, then run ss init again.");
117932
117944
  showInstallHelp();
117933
- process.exit(1);
117945
+ process.exitCode = 1;
117946
+ return;
117934
117947
  }
117935
117948
  } catch {
117936
117949
  logger.error("winget installation failed.");
117937
117950
  showInstallHelp();
117938
- process.exit(1);
117951
+ process.exitCode = 1;
117952
+ return;
117939
117953
  }
117940
117954
  } else {
117941
117955
  logger.info("");
117942
117956
  logger.info(`Install manually: ${source_default.cyan(wingetCmd)}`);
117943
117957
  showInstallHelp();
117944
- process.exit(1);
117958
+ process.exitCode = 1;
117959
+ return;
117945
117960
  }
117946
117961
  } else {
117947
117962
  logger.info(`Installing .NET SDK ${MIN_DOTNET_MAJOR}.0 via winget...`);
@@ -117957,17 +117972,20 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
117957
117972
  logger.error("Installation completed but .NET SDK still not detected.");
117958
117973
  logger.info("Restart your terminal, then run ss init again.");
117959
117974
  showInstallHelp();
117960
- process.exit(1);
117975
+ process.exitCode = 1;
117976
+ return;
117961
117977
  }
117962
117978
  } catch {
117963
117979
  logger.error("Automatic installation failed.");
117964
117980
  showInstallHelp();
117965
- process.exit(1);
117981
+ process.exitCode = 1;
117982
+ return;
117966
117983
  }
117967
117984
  }
117968
117985
  } else {
117969
117986
  showInstallHelp();
117970
- process.exit(1);
117987
+ process.exitCode = 1;
117988
+ return;
117971
117989
  }
117972
117990
  } else {
117973
117991
  logger.success(`.NET SDK ${prereqs.dotnetVersion} detected`);
@@ -117981,7 +117999,8 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
117981
117999
  const inPlaceResult = await validateInPlaceDirectory(projectDir);
117982
118000
  if (inPlaceResult.error) {
117983
118001
  logger.error(inPlaceResult.error);
117984
- process.exit(1);
118002
+ process.exitCode = 1;
118003
+ return;
117985
118004
  }
117986
118005
  if (inPlaceResult.isResume) {
117987
118006
  resumeState = inPlaceResult.existingState;
@@ -117997,7 +118016,7 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
117997
118016
  ]);
117998
118017
  if (!confirmResume) {
117999
118018
  logger.info("Cancelled by user.");
118000
- process.exit(0);
118019
+ return;
118001
118020
  }
118002
118021
  }
118003
118022
  } else {
@@ -118012,7 +118031,7 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
118012
118031
  ]);
118013
118032
  if (!confirm) {
118014
118033
  logger.info("Cancelled by user.");
118015
- process.exit(0);
118034
+ return;
118016
118035
  }
118017
118036
  }
118018
118037
  }
@@ -118020,7 +118039,8 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
118020
118039
  if (await import_fs_extra6.default.pathExists(projectDir)) {
118021
118040
  logger.error(`Directory '${projectDir}' already exists.`);
118022
118041
  logger.info(`Tip: Use ${source_default.cyan("--here")} to initialize in the current directory instead.`);
118023
- process.exit(1);
118042
+ process.exitCode = 1;
118043
+ return;
118024
118044
  }
118025
118045
  }
118026
118046
  let finalProjectName = projectName;
@@ -118043,14 +118063,16 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
118043
118063
  } else {
118044
118064
  logger.error(`Cannot continue with invalid project name.`);
118045
118065
  logger.info(`Tip: Rename folder to use only letters, digits, and underscores.`);
118046
- process.exit(1);
118066
+ process.exitCode = 1;
118067
+ return;
118047
118068
  }
118048
118069
  } else if (validation.suggestion && options.yes) {
118049
118070
  finalProjectName = validation.suggestion;
118050
118071
  logger.info(`Auto-converted to "${finalProjectName}" for C# compatibility`);
118051
118072
  } else {
118052
118073
  logger.error(`Invalid project name: ${validation.error}`);
118053
- process.exit(1);
118074
+ process.exitCode = 1;
118075
+ return;
118054
118076
  }
118055
118077
  }
118056
118078
  if (!inPlace && finalProjectName !== projectName) {
@@ -118059,7 +118081,8 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
118059
118081
  logger.info(`Project directory updated to: ${source_default.cyan(finalProjectDir)}`);
118060
118082
  if (await import_fs_extra6.default.pathExists(finalProjectDir)) {
118061
118083
  logger.error(`Directory '${finalProjectDir}' already exists.`);
118062
- process.exit(1);
118084
+ process.exitCode = 1;
118085
+ return;
118063
118086
  }
118064
118087
  }
118065
118088
  let config;
@@ -118220,7 +118243,8 @@ var initCommand = new Command("init").description("Initialize a new SmartStack p
118220
118243
  console.log();
118221
118244
  logger.info(`Fix the issue and re-run: ${source_default.cyan("ss init --here")}`);
118222
118245
  logger.info("Your progress has been saved and will be resumed automatically.");
118223
- process.exit(1);
118246
+ process.exitCode = 1;
118247
+ return;
118224
118248
  }
118225
118249
  });
118226
118250
 
@@ -124987,6 +125011,32 @@ function isPlainObject(value) {
124987
125011
  return typeof value === "object" && value !== null && !Array.isArray(value);
124988
125012
  }
124989
125013
 
125014
+ // src/lib/required-packages.ts
125015
+ var REQUIRED_PACKAGES = [
125016
+ {
125017
+ suffix: "Domain",
125018
+ packages: []
125019
+ },
125020
+ {
125021
+ suffix: "Infrastructure",
125022
+ packages: [
125023
+ "Microsoft.EntityFrameworkCore",
125024
+ "Microsoft.EntityFrameworkCore.Design",
125025
+ "Microsoft.EntityFrameworkCore.SqlServer"
125026
+ ]
125027
+ },
125028
+ {
125029
+ suffix: "Api",
125030
+ packages: [
125031
+ "Microsoft.AspNetCore.OpenApi",
125032
+ "Microsoft.AspNetCore.Authentication.JwtBearer",
125033
+ "Microsoft.EntityFrameworkCore.Design",
125034
+ "Swashbuckle.AspNetCore",
125035
+ "Microsoft.AspNetCore.SignalR.StackExchangeRedis"
125036
+ ]
125037
+ }
125038
+ ];
125039
+
124990
125040
  // src/commands/upgrade.ts
124991
125041
  var TEMPLATES_DIR3 = (0, import_path8.join)((0, import_path8.dirname)(__dirname), "templates", "project");
124992
125042
  async function getLatestNuGetVersion2(packageName, prerelease) {
@@ -125060,16 +125110,45 @@ async function getLatestNpmVersion(packageName, prerelease) {
125060
125110
  async function detectSmartStackProject() {
125061
125111
  const cwd = process.cwd();
125062
125112
  const configPath = (0, import_path8.join)(cwd, ".smartstack", "config.json");
125063
- if (!await import_fs_extra7.default.pathExists(configPath)) {
125064
- return { isProject: false, projectDir: cwd };
125113
+ if (await import_fs_extra7.default.pathExists(configPath)) {
125114
+ try {
125115
+ const config = await import_fs_extra7.default.readJson(configPath);
125116
+ return { isProject: true, config, projectDir: cwd };
125117
+ } catch (error) {
125118
+ logger.warning("Could not read .smartstack/config.json");
125119
+ }
125065
125120
  }
125066
- try {
125067
- const config = await import_fs_extra7.default.readJson(configPath);
125068
- return { isProject: true, config, projectDir: cwd };
125069
- } catch (error) {
125070
- logger.warning("Could not read .smartstack/config.json");
125071
- return { isProject: false, projectDir: cwd };
125121
+ const srcDir = (0, import_path8.join)(cwd, "src");
125122
+ if (await import_fs_extra7.default.pathExists(srcDir)) {
125123
+ const folders = await import_fs_extra7.default.readdir(srcDir);
125124
+ for (const folder of folders) {
125125
+ const folderPath = (0, import_path8.join)(srcDir, folder);
125126
+ const stat = await import_fs_extra7.default.stat(folderPath);
125127
+ if (!stat.isDirectory()) continue;
125128
+ const csprojFiles = (await import_fs_extra7.default.readdir(folderPath)).filter((f) => f.endsWith(".csproj"));
125129
+ for (const csproj of csprojFiles) {
125130
+ const content = await import_fs_extra7.default.readFile((0, import_path8.join)(folderPath, csproj), "utf-8");
125131
+ const version2 = readPackageVersion(content, "SmartStack");
125132
+ if (version2) {
125133
+ const dotIndex = folder.lastIndexOf(".");
125134
+ const baseNamespace = dotIndex > 0 ? folder.substring(0, dotIndex) : folder;
125135
+ logger.warning("No .smartstack/config.json found \u2014 detected SmartStack project from .csproj files");
125136
+ logger.info(`Tip: Run ${source_default.cyan("ss init --here")} to create the config file.`);
125137
+ return {
125138
+ isProject: true,
125139
+ config: {
125140
+ projectType: "fullstack",
125141
+ dbContext: `${baseNamespace}DbContext`,
125142
+ baseNamespace,
125143
+ smartStackVersion: version2
125144
+ },
125145
+ projectDir: cwd
125146
+ };
125147
+ }
125148
+ }
125149
+ }
125072
125150
  }
125151
+ return { isProject: false, projectDir: cwd };
125073
125152
  }
125074
125153
  function readPackageVersion(csprojContent, packageName) {
125075
125154
  const regex2 = new RegExp(
@@ -125429,6 +125508,41 @@ async function syncDockerFiles(projectDir, baseNamespace, dryRun) {
125429
125508
  }
125430
125509
  return updated;
125431
125510
  }
125511
+ async function ensureRequiredPackages(projects, baseNamespace, dryRun) {
125512
+ const added = [];
125513
+ const failed = [];
125514
+ for (const rp of REQUIRED_PACKAGES) {
125515
+ if (rp.packages.length === 0) continue;
125516
+ const expectedFolder = `${baseNamespace}.${rp.suffix}`;
125517
+ const project = projects.find((p) => {
125518
+ const folderName = p.relPath.split(/[/\\]/).slice(-2, -1)[0];
125519
+ return folderName === expectedFolder;
125520
+ });
125521
+ if (!project) continue;
125522
+ const currentPackages = readAllPackageReferences(project.csprojContent);
125523
+ const currentNames = new Set(currentPackages.map((p) => p.name.toLowerCase()));
125524
+ for (const requiredPkg of rp.packages) {
125525
+ if (currentNames.has(requiredPkg.toLowerCase())) continue;
125526
+ try {
125527
+ if (dryRun) {
125528
+ logger.info(` [DRY RUN] Would add ${source_default.cyan(requiredPkg)} to ${source_default.cyan(expectedFolder)}`);
125529
+ } else {
125530
+ execCommand2(
125531
+ `dotnet add "${project.csprojPath}" package ${requiredPkg} --no-restore`,
125532
+ void 0,
125533
+ false
125534
+ );
125535
+ logger.success(` ${source_default.green("+")} Added ${source_default.cyan(requiredPkg)} to ${source_default.cyan(expectedFolder)}`);
125536
+ }
125537
+ added.push(`${expectedFolder} + ${requiredPkg}`);
125538
+ } catch {
125539
+ failed.push(`${expectedFolder} + ${requiredPkg}`);
125540
+ logger.error(` ${source_default.red("\u2717")} Failed to add ${requiredPkg} to ${expectedFolder}`);
125541
+ }
125542
+ }
125543
+ }
125544
+ return { added, failed };
125545
+ }
125432
125546
  var upgradeCommand = new Command("upgrade").description("Upgrade SmartStack packages to the latest version").option("--preview", "Upgrade to latest preview/prerelease version").option("--dry-run", "Show what would be upgraded without actually upgrading").option("--all-packages", "Also upgrade all other NuGet packages (slow, disabled by default)").action(async (options) => {
125433
125547
  logger.header("SmartStack Package Upgrade");
125434
125548
  const dryRun = options.dryRun || false;
@@ -125450,6 +125564,7 @@ var upgradeCommand = new Command("upgrade").description("Upgrade SmartStack pack
125450
125564
  testFrontendSynced: 0,
125451
125565
  residualsCleaned: 0,
125452
125566
  initStateFixed: false,
125567
+ requiredPkgAdded: 0,
125453
125568
  programCsIssues: []
125454
125569
  };
125455
125570
  if (dryRun) {
@@ -125460,7 +125575,8 @@ var upgradeCommand = new Command("upgrade").description("Upgrade SmartStack pack
125460
125575
  if (!detection.isProject) {
125461
125576
  logger.error("Not a SmartStack project. Run this command from a SmartStack project root.");
125462
125577
  logger.info("Tip: SmartStack projects contain a .smartstack/config.json file.");
125463
- process.exit(1);
125578
+ process.exitCode = 1;
125579
+ return;
125464
125580
  }
125465
125581
  const { config, projectDir } = detection;
125466
125582
  logger.info(`Project: ${source_default.cyan(config.baseNamespace)}`);
@@ -125476,7 +125592,8 @@ var upgradeCommand = new Command("upgrade").description("Upgrade SmartStack pack
125476
125592
  const npmVersion = await getLatestNpmVersion("@atlashub/smartstack", usePreview);
125477
125593
  if (!nugetVersion) {
125478
125594
  logger.error("Could not fetch latest NuGet version. Check your internet connection.");
125479
- process.exit(1);
125595
+ process.exitCode = 1;
125596
+ return;
125480
125597
  }
125481
125598
  logger.success(`Latest NuGet version: ${source_default.cyan(nugetVersion)}`);
125482
125599
  if (npmVersion) {
@@ -125538,10 +125655,37 @@ var upgradeCommand = new Command("upgrade").description("Upgrade SmartStack pack
125538
125655
  }
125539
125656
  console.log();
125540
125657
  }
125658
+ logger.info("Checking required NuGet packages...");
125659
+ if (result.nugetUpgraded > 0) {
125660
+ for (const project of allProjects) {
125661
+ if (project.currentVersion !== null) {
125662
+ project.csprojContent = await import_fs_extra7.default.readFile(project.csprojPath, "utf-8");
125663
+ }
125664
+ }
125665
+ }
125666
+ const requiredResult = await ensureRequiredPackages(
125667
+ allProjects,
125668
+ config.baseNamespace,
125669
+ dryRun
125670
+ );
125671
+ result.requiredPkgAdded = requiredResult.added.length;
125672
+ if (requiredResult.added.length > 0) {
125673
+ logger.success(`${requiredResult.added.length} required package(s) added`);
125674
+ if (!dryRun) {
125675
+ logger.info("Restoring NuGet packages...");
125676
+ tryExecCommand("dotnet restore", projectDir);
125677
+ }
125678
+ } else {
125679
+ logger.info(`Required packages ${source_default.green("\u2713")} all present`);
125680
+ }
125681
+ if (requiredResult.failed.length > 0) {
125682
+ logger.error(`${requiredResult.failed.length} required package(s) failed to add`);
125683
+ }
125684
+ console.log();
125541
125685
  if (options.allPackages) {
125542
125686
  logger.info("Checking other NuGet packages...");
125543
125687
  for (const project of allProjects) {
125544
- const content = result.nugetUpgraded > 0 && project.currentVersion !== null ? await import_fs_extra7.default.readFile(project.csprojPath, "utf-8") : project.csprojContent;
125688
+ const content = result.nugetUpgraded > 0 && project.currentVersion !== null || result.requiredPkgAdded > 0 ? await import_fs_extra7.default.readFile(project.csprojPath, "utf-8") : project.csprojContent;
125545
125689
  const allPackages = readAllPackageReferences(content);
125546
125690
  const otherPackages = allPackages.filter((p) => p.name !== "SmartStack");
125547
125691
  if (otherPackages.length === 0) continue;
@@ -125759,13 +125903,15 @@ var upgradeCommand = new Command("upgrade").description("Upgrade SmartStack pack
125759
125903
  console.log();
125760
125904
  }
125761
125905
  if (!dryRun && nugetVersion) {
125762
- config.smartStackVersion = nugetVersion;
125763
125906
  const configPath = (0, import_path8.join)(projectDir, ".smartstack", "config.json");
125764
- await import_fs_extra7.default.writeJson(configPath, config, { spaces: 2 });
125765
- logger.success(`Updated config version to ${source_default.cyan(nugetVersion)}`);
125907
+ if (await import_fs_extra7.default.pathExists(configPath)) {
125908
+ config.smartStackVersion = nugetVersion;
125909
+ await import_fs_extra7.default.writeJson(configPath, config, { spaces: 2 });
125910
+ logger.success(`Updated config version to ${source_default.cyan(nugetVersion)}`);
125911
+ }
125766
125912
  console.log();
125767
125913
  }
125768
- const totalChanged = result.nugetUpgraded + result.otherPkgUpdated + (result.npmUpgraded ? 1 : 0) + (result.npmOtherUpdated ? 1 : 0) + migrationSummary.totalApplied + result.configSynced + result.claudeSettingsSynced + result.dockerSynced + result.testFrontendSynced + result.residualsCleaned + (result.initStateFixed ? 1 : 0) + (result.ralphInitialized ? 1 : 0);
125914
+ const totalChanged = result.nugetUpgraded + result.requiredPkgAdded + result.otherPkgUpdated + (result.npmUpgraded ? 1 : 0) + (result.npmOtherUpdated ? 1 : 0) + migrationSummary.totalApplied + result.configSynced + result.claudeSettingsSynced + result.dockerSynced + result.testFrontendSynced + result.residualsCleaned + (result.initStateFixed ? 1 : 0) + (result.ralphInitialized ? 1 : 0);
125769
125915
  const allUpToDate = totalChanged === 0 && result.nugetFailed === 0 && result.otherPkgFailed === 0;
125770
125916
  const hasProgramIssues = result.programCsIssues.length > 0;
125771
125917
  if (allUpToDate && !hasProgramIssues) {
@@ -125802,6 +125948,9 @@ var upgradeCommand = new Command("upgrade").description("Upgrade SmartStack pack
125802
125948
  if (result.nugetFailed > 0) {
125803
125949
  lines.push(` ${source_default.red("\u2717")} SmartStack: ${result.nugetFailed} project(s) failed`);
125804
125950
  }
125951
+ if (result.requiredPkgAdded > 0) {
125952
+ lines.push(` ${source_default.green("\u2713")} Required packages: ${result.requiredPkgAdded} added`);
125953
+ }
125805
125954
  if (result.otherPkgUpdated > 0) {
125806
125955
  lines.push(` ${source_default.green("\u2713")} Other NuGet: ${result.otherPkgUpdated} package(s) updated`);
125807
125956
  }
@@ -130458,7 +130607,8 @@ async function main2() {
130458
130607
  \u2551 \u2551
130459
130608
  \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
130460
130609
  `));
130461
- process.exit(1);
130610
+ process.exitCode = 1;
130611
+ return;
130462
130612
  }
130463
130613
  if (result.warnings?.length) {
130464
130614
  for (const warning of result.warnings) {