@mnci/cli 4.14.0 → 4.16.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/cli.js CHANGED
@@ -37,10 +37,6 @@ __export(main_exports, {
37
37
  module.exports = __toCommonJS(main_exports);
38
38
  var import_commander = require("commander");
39
39
 
40
- // src/project-scaffolding/add-project.use-case.ts
41
- var import_node_path20 = require("path");
42
- var import_prompts3 = require("@inquirer/prompts");
43
-
44
40
  // src/nx-workspace/nx.client.ts
45
41
  var import_cross_spawn = __toESM(require("cross-spawn"));
46
42
 
@@ -200,6 +196,10 @@ function runFormatter(cwd, target = ".") {
200
196
  }
201
197
  }
202
198
 
199
+ // src/workspace-overlay/overlay.use-case.ts
200
+ var import_node_fs2 = require("fs");
201
+ var import_node_path2 = require("path");
202
+
203
203
  // src/file-system/file-system.client.ts
204
204
  var import_node_fs = require("fs");
205
205
  var import_node_path = require("path");
@@ -282,22 +282,7 @@ function fileExists(path) {
282
282
  return (0, import_node_fs.existsSync)(path);
283
283
  }
284
284
 
285
- // src/project-name/project-name.validator.ts
286
- function assertValidProjectName(name, label) {
287
- if (!/^[a-z][a-z0-9-]*(?:\.[a-z0-9-]+)*$/.test(name)) {
288
- throw new Error(
289
- `${label} '${name}' is invalid \u2014 use lowercase letters, digits, hyphens and dots, starting with a letter, with no leading, trailing or repeated dot (e.g. 'my-project', 'my.service').`
290
- );
291
- }
292
- }
293
-
294
- // src/project-scaffolding/csharp.use-case.ts
295
- var import_node_fs4 = require("fs");
296
- var import_node_path4 = require("path");
297
-
298
285
  // src/workspace-overlay/overlay.use-case.ts
299
- var import_node_fs2 = require("fs");
300
- var import_node_path2 = require("path");
301
286
  var DEFAULT_STACK = { testRunner: "jest" };
302
287
  var TS_COMPILER_DEPENDENCIES = {
303
288
  "@typescript/native": "npm:typescript@^7.0.2",
@@ -435,6 +420,17 @@ ${feedShortKey}:email=npm-requires-this-and-never-uses-it
435
420
  }
436
421
  var VSCODE_EXTENSION_TAG = "type:vscode-extension";
437
422
  var GO_RELEASE_TAG = "release:go";
423
+ var GO_CGO_TAG = "build:cgo";
424
+ function hasNativeGoApp(workspaceRoot) {
425
+ return (0, import_node_fs2.globSync)("apps/*/project.json", { cwd: workspaceRoot }).some((projectJson) => {
426
+ try {
427
+ const { tags } = JSON.parse((0, import_node_fs2.readFileSync)((0, import_node_path2.join)(workspaceRoot, projectJson), "utf8"));
428
+ return (tags ?? []).includes(GO_CGO_TAG);
429
+ } catch {
430
+ return false;
431
+ }
432
+ });
433
+ }
438
434
  function releaseConfig(ci) {
439
435
  const githubReleases = ci === "github";
440
436
  return {
@@ -1035,7 +1031,126 @@ var FLUTTER_TOOL_PATH_GITHUB = `node -e "${FLUTTER_TOOL_PATH_PRELUDE}if(!process
1035
1031
  var FLUTTER_PUB_GET_GUARD = `node -e "const fs=require('node:fs');if(!fs.existsSync('pubspec.yaml')){console.log('No Flutter projects - skipping.');process.exit(0)}process.exit(require('node:child_process').spawnSync('flutter',['pub','get'],{stdio:'inherit',shell:process.platform==='win32'}).status ?? 1)"`;
1036
1032
  var NPM_AUDIT_STEP = `node -e "const cp=require('node:child_process');const r=cp.spawnSync('npm',['audit','--json'],{encoding:'utf8',shell:process.platform==='win32',maxBuffer:33554432});let d;try{d=JSON.parse(r.stdout)}catch{console.log('npm audit produced no JSON (exit '+r.status+') - not blocking on a broken audit.');process.exit(0)}const all=Object.values(d.vulnerabilities||{});const BLOCK=['critical','high','moderate'];const major=v=>v.fixAvailable&&typeof v.fixAvailable==='object'&&v.fixAvailable.isSemVerMajor;const act=all.filter(v=>v.fixAvailable&&BLOCK.includes(v.severity)&&!major(v));const rest=all.filter(v=>!act.includes(v));for(const v of rest)console.log(' note ['+v.severity+'] '+v.name+(!v.fixAvailable?' - NO fix available upstream, nothing to do here':major(v)?' - only a semver-major change would remove it (often a parent downgrade), not applied automatically':' - fix available, below the blocking threshold'));if(act.length===0){console.log('npm audit - '+all.length+' advisory(ies), none actionable at moderate or above.');process.exit(0)}for(const v of act)console.log(' BLOCKING ['+v.severity+'] '+v.name+' - fix available');console.log('Each has a published fix. Add a targeted overrides entry in package.json rather than npm audit fix --force.');process.exit(1)"`;
1037
1033
  var VERIFY_TARGETS = "lint,typecheck,test,build";
1038
- var AFFECTED_OR_ALL_GUARD = `node -e "const cp=require('node:child_process');const T='${VERIFY_TARGETS}';const all=()=>process.exit(cp.spawnSync('npx nx run-many -t '+T,{stdio:'inherit',shell:true}).status ?? 1);const ref=process.env.GITHUB_BASE_REF||process.env.SYSTEM_PULLREQUEST_TARGETBRANCH||'';if(!ref){console.log('Not a pull request - verifying EVERY project.');all()}const target=ref.replace('refs/heads/','');const mergeBase=r=>{const o=cp.spawnSync('git',['merge-base',r,'HEAD'],{encoding:'utf8'});return o.status===0?o.stdout.trim():''};let base=mergeBase('origin/'+target);if(!base){console.log('No origin/'+target+' ref - fetching it to resolve a merge-base.');cp.spawnSync('git',['fetch','--no-tags','origin',target],{stdio:'inherit'});base=mergeBase('FETCH_HEAD')}if(!base){console.log('Could not resolve a merge-base with '+target+' - verifying EVERY project.');all()}console.log('Pull request against '+target+' - verifying projects affected since '+base);process.exit(cp.spawnSync('npx nx affected -t '+T+' --base='+base,{stdio:'inherit',shell:true}).status ?? 1)"`;
1034
+ function affectedOrAllGuard(exclude = "") {
1035
+ const extra = exclude === "" ? "" : `+' ${exclude}'`;
1036
+ return `node -e "const cp=require('node:child_process');const T='${VERIFY_TARGETS}';const all=()=>process.exit(cp.spawnSync('npx nx run-many -t '+T${extra},{stdio:'inherit',shell:true}).status ?? 1);const ref=process.env.GITHUB_BASE_REF||process.env.SYSTEM_PULLREQUEST_TARGETBRANCH||'';if(!ref){console.log('Not a pull request - verifying EVERY project.');all()}const target=ref.replace('refs/heads/','');const mergeBase=r=>{const o=cp.spawnSync('git',['merge-base',r,'HEAD'],{encoding:'utf8'});return o.status===0?o.stdout.trim():''};let base=mergeBase('origin/'+target);if(!base){console.log('No origin/'+target+' ref - fetching it to resolve a merge-base.');cp.spawnSync('git',['fetch','--no-tags','origin',target],{stdio:'inherit'});base=mergeBase('FETCH_HEAD')}if(!base){console.log('Could not resolve a merge-base with '+target+' - verifying EVERY project.');all()}console.log('Pull request against '+target+' - verifying projects affected since '+base);process.exit(cp.spawnSync('npx nx affected -t '+T+' --base='+base${extra},{stdio:'inherit',shell:true}).status ?? 1)"`;
1037
+ }
1038
+ var AFFECTED_OR_ALL_GUARD = affectedOrAllGuard();
1039
+ var AFFECTED_OR_ALL_GUARD_WITHOUT_NATIVE = affectedOrAllGuard(`--exclude=tag:${GO_CGO_TAG}`);
1040
+ var NATIVE_BUILD_COMMAND = `npx nx run-many -t lint,test,build-native,package-native --projects=tag:${GO_CGO_TAG}`;
1041
+ var NATIVE_LINUX_PREREQUISITES = "sudo apt-get update && sudo apt-get install -y gcc pkg-config";
1042
+ function githubNativeJob(npmAuthName, npmAuthValue, onMain) {
1043
+ return `
1044
+ # Apps that need a C toolchain (mnci add go-app --cgo) cannot be cross-compiled
1045
+ # from the job above, so each is linted, tested, built and packaged here, on a
1046
+ # runner of every OS it ships for, and is left out of that job's verify step.
1047
+ native:
1048
+ name: native (\${{ matrix.os }})
1049
+ needs: ci
1050
+ runs-on: \${{ matrix.os }}
1051
+ strategy:
1052
+ fail-fast: false
1053
+ matrix:
1054
+ os: [windows-latest, macos-latest, ubuntu-latest]
1055
+ steps:
1056
+ - uses: actions/checkout@${ACTION_VERSIONS["actions/checkout"]}
1057
+ with:
1058
+ fetch-depth: 0
1059
+
1060
+ # The release tags name the version a native build is stamped with.
1061
+ - run: git fetch --all --prune --tags
1062
+ name: Fetch branches and release tags
1063
+
1064
+ - uses: actions/setup-node@${ACTION_VERSIONS["actions/setup-node"]}
1065
+ with:
1066
+ node-version: ${NODE_VERSION}
1067
+ cache: npm
1068
+
1069
+ - run: npm install -g npm@${NPM_VERSION}
1070
+ name: Pin npm to the major mnci verifies against
1071
+
1072
+ - run: npm ci
1073
+ name: Install dependencies
1074
+ env:
1075
+ ${npmAuthName}: ${npmAuthValue}
1076
+
1077
+ - run: ${GO_MODULE_DOWNLOAD_GUARD}
1078
+ name: Download Go module dependencies
1079
+
1080
+ - run: ${GOLANGCI_LINT_INSTALL_GUARD}
1081
+ name: Install golangci-lint
1082
+
1083
+ - run: ${GO_TOOL_PATH_GITHUB}
1084
+ name: Add Go tool bin to PATH
1085
+
1086
+ # A C compiler and pkg-config, which is all mnci can know a cgo app needs.
1087
+ # Add the -dev packages your app links to this line, for example
1088
+ # libgtk-3-dev and libayatana-appindicator3-dev for a system-tray icon.
1089
+ # macOS and Windows runners ship their toolchains.
1090
+ - run: ${NATIVE_LINUX_PREREQUISITES}
1091
+ name: Install native prerequisites (Linux)
1092
+ if: \${{ runner.os == 'Linux' }}
1093
+
1094
+ - run: ${NATIVE_BUILD_COMMAND}
1095
+ name: Lint, test, build and package the native apps
1096
+
1097
+ - uses: actions/upload-artifact@${ACTION_VERSIONS["actions/upload-artifact"]}
1098
+ with:
1099
+ name: native-\${{ matrix.os }}
1100
+ path: dist/drop
1101
+ if-no-files-found: ignore
1102
+
1103
+ # A releasable native app (--cgo with --release) gets this OS's zip attached to
1104
+ # the GitHub Release the ci job just created, stamped with the tag's version.
1105
+ - run: node tools/go-app-release.cjs assets --native
1106
+ name: Attach this OS's zip to the GitHub Release (releasable native apps)
1107
+ if: \${{ ${onMain} && hashFiles('tools/go-app-release.cjs') != '' }}
1108
+ env:
1109
+ GH_TOKEN: \${{ secrets.GITHUB_TOKEN }}
1110
+ `;
1111
+ }
1112
+ function indentYaml(text, spaces) {
1113
+ const pad = " ".repeat(spaces);
1114
+ return text.split("\n").map((line) => line === "" ? line : pad + line).join("\n");
1115
+ }
1116
+ function withAzureNativeJob(document, nativeSteps) {
1117
+ const poolAt = document.indexOf("\npool:\n");
1118
+ const variablesAt = document.indexOf("\nvariables:\n");
1119
+ const stepsAt = document.indexOf("\nsteps:\n");
1120
+ if (poolAt === -1 || variablesAt < poolAt || stepsAt < variablesAt) {
1121
+ throw new Error("The Azure pipeline no longer has its pool, variables and steps blocks in that order.");
1122
+ }
1123
+ const head = document.slice(0, poolAt + 1);
1124
+ const pool2 = document.slice(poolAt + "\npool:\n".length, variablesAt).replace(/\n+$/, "");
1125
+ const variables = document.slice(variablesAt + 1, stepsAt).replace(/\n+$/, "");
1126
+ const steps = document.slice(stepsAt + "\nsteps:\n".length).replace(/\n+$/, "");
1127
+ const matrix = Object.entries({ windows: "windows-latest", macos: "macos-latest", linux: "ubuntu-latest" }).map(([leg, image]) => ` ${leg}:
1128
+ legName: ${leg}
1129
+ vmImage: ${image}`).join("\n");
1130
+ return `${head}${variables}
1131
+
1132
+ jobs:
1133
+ - job: ci
1134
+ pool:
1135
+ ${indentYaml(pool2, 4)}
1136
+ steps:
1137
+ ${indentYaml(steps, 4)}
1138
+
1139
+ # Apps that need a C toolchain (mnci add go-app --cgo) cannot be cross-compiled
1140
+ # from the job above, so each is linted, tested, built and packaged here, on an
1141
+ # agent of every OS it ships for, and is left out of that job's verify step.
1142
+ - job: native
1143
+ displayName: Native apps (cgo)
1144
+ dependsOn: ci
1145
+ strategy:
1146
+ matrix:
1147
+ ${matrix}
1148
+ pool:
1149
+ vmImage: $(vmImage)
1150
+ steps:
1151
+ ${indentYaml(nativeSteps, 4)}
1152
+ `;
1153
+ }
1039
1154
  var PACK_APPS_GUARD = `node -e "const fs=require('node:fs');fs.mkdirSync('dist/drop',{recursive:true});const hasProjectJson=fs.globSync('apps/*/project.json').length>0;const hasInlineNx=fs.globSync('apps/*/package.json').some((f)=>{try{return Boolean(JSON.parse(fs.readFileSync(f,'utf8')).nx)}catch{return false}});const hasCsproj=fs.globSync('apps/*/*.csproj').length>0;if(!hasProjectJson&&!hasInlineNx&&!hasCsproj){console.log('No apps to pack - skipping.');process.exit(0)}process.exit(require('node:child_process').spawnSync('npx nx run-many -t package',{stdio:'inherit',shell:true}).status ?? 1)"`;
1040
1155
  var NPM_AUTH_PREFLIGHT = `node -e "const fs=require('node:fs'),cp=require('node:child_process');if(fs.globSync('packages/*/package.json').length===0){console.log('No npm packages to release - skipping.');process.exit(0)}if(!process.env.NODE_AUTH_TOKEN){console.error('NPM_TOKEN is empty or unset, so the publish would fail AFTER nx release has already tagged. Add it as a repository secret named exactly NPM_TOKEN - under Actions, not the Dependabot or Codespaces tab, and not an Environment secret. Use an npm Automation token - a Publish token is refused by 2FA in CI.');process.exit(1)}const r=cp.spawnSync('npm',['whoami','--registry=https://registry.npmjs.org/'],{encoding:'utf8',shell:process.platform==='win32'});if(r.status!==0){console.error('NPM_TOKEN is set but the registry rejected it - '+((r.stderr||'')+(r.stdout||'')).trim()+'. Check that it has not expired and that it grants publish rights on this scope.');process.exit(1)}console.log('npm auth OK as '+r.stdout.trim())"`;
1041
1156
  function npmAuthPreflight(registryKind) {
@@ -1076,7 +1191,7 @@ function npmAuthEnvVariable(registryKind, variableReference) {
1076
1191
  function poolBlock(agent) {
1077
1192
  return /^(?:ubuntu|windows|macos)-/i.test(agent) ? ` vmImage: ${agent}` : ` name: ${agent}`;
1078
1193
  }
1079
- function azurePipelinesYaml(agent, variableGroup, pythonPublishUrl2, registryKind = "azure-artifacts", nugetFeedUrl2, npmAuth = "pat") {
1194
+ function azurePipelinesYaml(agent, variableGroup, pythonPublishUrl2, registryKind = "azure-artifacts", nugetFeedUrl2, npmAuth = "pat", nativeApps = false) {
1080
1195
  const onMain = "and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'), eq(variables['Build.SourceBranchName'], 'main'))";
1081
1196
  const [npmAuthName, npmAuthValue] = npmAuthEnvVariable(registryKind, (name) => `$(${name})`);
1082
1197
  const buildIdentity = npmAuth === "build-identity" && registryKind === "azure-artifacts";
@@ -1094,7 +1209,7 @@ function azurePipelinesYaml(agent, variableGroup, pythonPublishUrl2, registryKin
1094
1209
  const npmCiEnv = buildIdentity ? "" : `
1095
1210
  env:
1096
1211
  ${npmAuthName}: ${npmAuthValue}`;
1097
- return `name: monorepo-ci-$(Date:yyyyMMdd)$(Rev:.r)
1212
+ const document = `name: monorepo-ci-$(Date:yyyyMMdd)$(Rev:.r)
1098
1213
 
1099
1214
  # Generated by MoNecromanCI. Deliberately thin: Nx builds, 'nx release'
1100
1215
  # versions from conventional commits and pushes ONLY a tag to main, and each
@@ -1305,7 +1420,7 @@ ${npmAuthenticateStep} - script: npm ci
1305
1420
  # 'npm run lint' is 'nx run-many -t lint', a strict subset of the targets
1306
1421
  # below, so adding it back as its own step would only duplicate work \u2014 and on
1307
1422
  # a pull request it would re-lint every project, discarding the point of this.
1308
- - script: ${AFFECTED_OR_ALL_GUARD}
1423
+ - script: ${nativeApps ? AFFECTED_OR_ALL_GUARD_WITHOUT_NATIVE : AFFECTED_OR_ALL_GUARD}
1309
1424
  displayName: Verify (affected on a PR, every project on main)
1310
1425
 
1311
1426
  # Pack every app into dist/drop/<type>-<name>.zip via each app's 'package'
@@ -1396,8 +1511,56 @@ ${npmAuthPreflight(registryKind) ? `
1396
1511
  displayName: Push release tags (nx release's own push never runs without a remote Release configured)
1397
1512
  condition: ${onMain}
1398
1513
  `;
1514
+ if (!nativeApps) {
1515
+ return document;
1516
+ }
1517
+ const nativeSteps = ` - checkout: self
1518
+ fetchDepth: 0
1519
+
1520
+ - task: UseNode@1
1521
+ inputs:
1522
+ version: 24.x
1523
+
1524
+ - task: Cache@2
1525
+ displayName: Cache npm packages
1526
+ inputs:
1527
+ key: 'npm | "$(Agent.OS)" | package-lock.json'
1528
+ restoreKeys: |
1529
+ npm | "$(Agent.OS)"
1530
+ path: $(npm_config_cache)
1531
+
1532
+ ${npmAuthenticateStep} - script: npm ci
1533
+ displayName: Install dependencies${npmCiEnv}
1534
+
1535
+ - script: ${GO_MODULE_DOWNLOAD_GUARD}
1536
+ displayName: Download Go module dependencies
1537
+
1538
+ - script: ${GOLANGCI_LINT_INSTALL_GUARD}
1539
+ displayName: Install golangci-lint
1540
+
1541
+ - script: ${GO_TOOL_PATH_AZURE}
1542
+ displayName: Add Go tool bin to PATH
1543
+
1544
+ # A C compiler and pkg-config, which is all mnci can know a cgo app needs. Add the
1545
+ # -dev packages your app links to this line, for example libgtk-3-dev and
1546
+ # libayatana-appindicator3-dev for a system-tray icon. macOS and Windows agents
1547
+ # ship their toolchains.
1548
+ - script: ${NATIVE_LINUX_PREREQUISITES}
1549
+ displayName: Install native prerequisites (Linux)
1550
+ condition: eq(variables['Agent.OS'], 'Linux')
1551
+
1552
+ - script: ${NATIVE_BUILD_COMMAND}
1553
+ displayName: Lint, test, build and package the native apps
1554
+
1555
+ - task: PublishBuildArtifacts@1
1556
+ displayName: Publish this OS's native zips
1557
+ inputs:
1558
+ PathtoPublish: $(Build.SourcesDirectory)/dist/drop
1559
+ ArtifactName: native-$(legName)
1560
+ `;
1561
+ return withAzureNativeJob(document, nativeSteps);
1399
1562
  }
1400
- function githubActionsYaml(agent, pythonPublishUrl2, registryKind = "azure-artifacts", ci = "github", nugetFeedUrl2) {
1563
+ function githubActionsYaml(agent, pythonPublishUrl2, registryKind = "azure-artifacts", ci = "github", nugetFeedUrl2, nativeApps = false) {
1401
1564
  const onMain = "github.event_name == 'push' && github.ref_name == 'main'";
1402
1565
  const [npmAuthName, npmAuthValue] = npmAuthEnvVariable(
1403
1566
  registryKind,
@@ -1566,7 +1729,7 @@ jobs:
1566
1729
  # below, so adding it back as its own step would only duplicate work \u2014 and
1567
1730
  # on a pull request it would re-lint every project, discarding the point
1568
1731
  # of this.
1569
- - run: ${AFFECTED_OR_ALL_GUARD}
1732
+ - run: ${nativeApps ? AFFECTED_OR_ALL_GUARD_WITHOUT_NATIVE : AFFECTED_OR_ALL_GUARD}
1570
1733
  name: Verify (affected on a PR, every project on main)
1571
1734
 
1572
1735
  # Pack every app into dist/drop/<type>-<name>.zip via each app's 'package'
@@ -1688,7 +1851,7 @@ ${githubReleases ? `
1688
1851
  - run: git push origin --tags
1689
1852
  name: Push release tags (nx release's own push never runs without a remote Release configured)
1690
1853
  if: \${{ ${onMain} }}
1691
- `}`;
1854
+ `}${nativeApps ? githubNativeJob(npmAuthName, npmAuthValue, onMain) : ""}`;
1692
1855
  }
1693
1856
  var PIP_PROJECT_GLOBS = ["apps", "python-packages", "libs"];
1694
1857
  var PUB_PROJECT_GLOBS = ["apps", "packages", "libs"];
@@ -2005,6 +2168,7 @@ function applyOverlay(workspaceRoot, options, onProgress = () => {
2005
2168
  }
2006
2169
  const publishUrl = pythonPublishUrl(options.registry);
2007
2170
  const nugetUrl = nugetFeedUrl(options.registry);
2171
+ const nativeApps = hasNativeGoApp(workspaceRoot);
2008
2172
  if (options.ci === "azure" || options.ci === "both") {
2009
2173
  onProgress("azure-pipelines.yml \u2014 build, verify, pack and release");
2010
2174
  writeFileEnsured(
@@ -2015,7 +2179,8 @@ function applyOverlay(workspaceRoot, options, onProgress = () => {
2015
2179
  publishUrl,
2016
2180
  options.registry.kind,
2017
2181
  nugetUrl,
2018
- options.npmAuth
2182
+ options.npmAuth,
2183
+ nativeApps
2019
2184
  )
2020
2185
  );
2021
2186
  }
@@ -2023,12 +2188,131 @@ function applyOverlay(workspaceRoot, options, onProgress = () => {
2023
2188
  onProgress(".github/workflows/ci.yml and dependabot.yml");
2024
2189
  writeFileEnsured(
2025
2190
  (0, import_node_path2.join)(workspaceRoot, ".github/workflows/ci.yml"),
2026
- githubActionsYaml(options.agent, publishUrl, options.registry.kind, options.ci, nugetUrl)
2191
+ githubActionsYaml(options.agent, publishUrl, options.registry.kind, options.ci, nugetUrl, nativeApps)
2027
2192
  );
2028
2193
  writeFileEnsured((0, import_node_path2.join)(workspaceRoot, ".github/dependabot.yml"), dependabotConfig(workspaceRoot));
2029
2194
  }
2030
2195
  }
2031
2196
 
2197
+ // src/ci-pipeline/ci-environment.client.ts
2198
+ function detectCiHost(environment) {
2199
+ if (environment.GITHUB_ACTIONS === "true") {
2200
+ return "github";
2201
+ }
2202
+ if (environment.TF_BUILD !== void 0 && environment.TF_BUILD !== "") {
2203
+ return "azure";
2204
+ }
2205
+ return "local";
2206
+ }
2207
+ function pullRequestTarget(environment) {
2208
+ const reference = environment.GITHUB_BASE_REF || environment.SYSTEM_PULLREQUEST_TARGETBRANCH || "";
2209
+ return reference === "" ? void 0 : reference.replace("refs/heads/", "");
2210
+ }
2211
+ function groupStart(host, title) {
2212
+ switch (host) {
2213
+ case "github": {
2214
+ return `::group::${title}`;
2215
+ }
2216
+ case "azure": {
2217
+ return `##[group]${title}`;
2218
+ }
2219
+ case "local": {
2220
+ return `
2221
+ \u25B8 ${title}`;
2222
+ }
2223
+ }
2224
+ }
2225
+ function groupEnd(host) {
2226
+ switch (host) {
2227
+ case "github": {
2228
+ return "::endgroup::";
2229
+ }
2230
+ case "azure": {
2231
+ return "##[endgroup]";
2232
+ }
2233
+ case "local": {
2234
+ return void 0;
2235
+ }
2236
+ }
2237
+ }
2238
+
2239
+ // src/ci-pipeline/verify.use-case.ts
2240
+ function runVerify(workspaceRoot, dependencies = {}) {
2241
+ const environment = dependencies.environment ?? process.env;
2242
+ const processes = dependencies.processes ?? {
2243
+ run: (command, arguments_) => runShell(command, arguments_, workspaceRoot),
2244
+ capture: (command, arguments_) => runCapture(command, arguments_, workspaceRoot)
2245
+ };
2246
+ const log = dependencies.log ?? ((message) => {
2247
+ console.log(message);
2248
+ });
2249
+ const host = detectCiHost(environment);
2250
+ const inGroup = (title, command, arguments_) => {
2251
+ log(groupStart(host, title));
2252
+ const status = processes.run(command, arguments_);
2253
+ const closing = groupEnd(host);
2254
+ if (closing !== void 0) {
2255
+ log(closing);
2256
+ }
2257
+ return status;
2258
+ };
2259
+ const synced = inGroup("Verify the workspace is synced", "npx", ["nx", "sync:check"]);
2260
+ if (synced !== 0) {
2261
+ log("The workspace is not synced: run 'npx nx sync' locally and commit the result.");
2262
+ return synced;
2263
+ }
2264
+ const exclude = hasNativeGoApp(workspaceRoot) ? [`--exclude=tag:${GO_CGO_TAG}`] : [];
2265
+ const everything = () => inGroup("Verify every project", "npx", ["nx", "run-many", "-t", VERIFY_TARGETS, ...exclude]);
2266
+ const target = pullRequestTarget(environment);
2267
+ if (target === void 0) {
2268
+ log("Not a pull request - verifying EVERY project.");
2269
+ return everything();
2270
+ }
2271
+ const mergeBase = (reference) => {
2272
+ const result = processes.capture("git", ["merge-base", reference, "HEAD"]);
2273
+ return result.status === 0 ? result.stdout.trim() : "";
2274
+ };
2275
+ let base = mergeBase(`origin/${target}`);
2276
+ if (base === "") {
2277
+ log(`No origin/${target} ref - fetching it to resolve a merge-base.`);
2278
+ processes.run("git", ["fetch", "--no-tags", "origin", target]);
2279
+ base = mergeBase("FETCH_HEAD");
2280
+ }
2281
+ if (base === "") {
2282
+ log(`Could not resolve a merge-base with ${target} - verifying EVERY project.`);
2283
+ return everything();
2284
+ }
2285
+ log(`Pull request against ${target} - verifying projects affected since ${base}`);
2286
+ return inGroup("Verify the affected projects", "npx", ["nx", "affected", "-t", VERIFY_TARGETS, `--base=${base}`, ...exclude]);
2287
+ }
2288
+
2289
+ // src/ci-pipeline/index.ts
2290
+ var CI_PHASES = ["verify"];
2291
+ function runCiPhase(phase, workspaceRoot, dependencies = {}) {
2292
+ switch (phase) {
2293
+ case "verify": {
2294
+ return runVerify(workspaceRoot, dependencies);
2295
+ }
2296
+ }
2297
+ }
2298
+
2299
+ // src/project-scaffolding/add-project.use-case.ts
2300
+ var import_node_path21 = require("path");
2301
+ var import_prompts3 = require("@inquirer/prompts");
2302
+
2303
+ // src/project-name/project-name.validator.ts
2304
+ function assertValidProjectName(name, label) {
2305
+ if (!/^[a-z][a-z0-9-]*(?:\.[a-z0-9-]+)*$/.test(name)) {
2306
+ throw new Error(
2307
+ `${label} '${name}' is invalid \u2014 use lowercase letters, digits, hyphens and dots, starting with a letter, with no leading, trailing or repeated dot (e.g. 'my-project', 'my.service').`
2308
+ );
2309
+ }
2310
+ }
2311
+
2312
+ // src/project-scaffolding/csharp.use-case.ts
2313
+ var import_node_fs4 = require("fs");
2314
+ var import_node_path4 = require("path");
2315
+
2032
2316
  // src/project-scaffolding/post-generation.use-case.ts
2033
2317
  var import_node_fs3 = require("fs");
2034
2318
  var import_node_path3 = require("path");
@@ -2617,12 +2901,44 @@ function addFlutterInternalLib(workspaceRoot, name) {
2617
2901
  }
2618
2902
 
2619
2903
  // src/project-scaffolding/go.use-case.ts
2620
- var import_node_fs6 = require("fs");
2621
- var import_node_path7 = require("path");
2904
+ var import_node_fs7 = require("fs");
2905
+ var import_node_path8 = require("path");
2622
2906
 
2623
- // src/project-scaffolding/go-release.use-case.ts
2907
+ // src/go-workspace/go-plugin.use-case.ts
2624
2908
  var import_node_fs5 = require("fs");
2625
2909
  var import_node_path6 = require("path");
2910
+ var NX_GO_PLUGIN = "@nx-go/nx-go";
2911
+ function hasGoProject(workspaceRoot) {
2912
+ const projectFiles = ["apps", "libs", "packages"].flatMap((directory) => (0, import_node_fs5.globSync)(`${directory}/*/project.json`, { cwd: workspaceRoot }));
2913
+ return projectFiles.some((projectFile) => {
2914
+ try {
2915
+ const { tags } = JSON.parse((0, import_node_fs5.readFileSync)((0, import_node_path6.join)(workspaceRoot, projectFile), "utf8"));
2916
+ return (tags ?? []).some((tag) => tag.startsWith("type:go-"));
2917
+ } catch {
2918
+ return false;
2919
+ }
2920
+ });
2921
+ }
2922
+ function isNxGoPluginRegistered(workspaceRoot) {
2923
+ const nxJsonPath = (0, import_node_path6.join)(workspaceRoot, "nx.json");
2924
+ if (!fileExists(nxJsonPath)) {
2925
+ return false;
2926
+ }
2927
+ return (readJson(nxJsonPath).plugins ?? []).some((entry) => (typeof entry === "string" ? entry : entry.plugin) === NX_GO_PLUGIN);
2928
+ }
2929
+ function registerNxGoPlugin(workspaceRoot) {
2930
+ const nxJsonPath = (0, import_node_path6.join)(workspaceRoot, "nx.json");
2931
+ if (!fileExists(nxJsonPath) || isNxGoPluginRegistered(workspaceRoot)) {
2932
+ return false;
2933
+ }
2934
+ const nxJson = readJson(nxJsonPath);
2935
+ writeFileEnsured(nxJsonPath, toJson({ ...nxJson, plugins: [...nxJson.plugins ?? [], NX_GO_PLUGIN] }));
2936
+ return true;
2937
+ }
2938
+
2939
+ // src/project-scaffolding/go-release.use-case.ts
2940
+ var import_node_fs6 = require("fs");
2941
+ var import_node_path7 = require("path");
2626
2942
  var GO_RELEASE_SCRIPT_PATH = "tools/go-app-release.cjs";
2627
2943
  var GO_RELEASE_SCRIPT = String.raw`#!/usr/bin/env node
2628
2944
  // Written by mnci: 'mnci add go-app --release' creates it and 'mnci upgrade'
@@ -2631,10 +2947,11 @@ var GO_RELEASE_SCRIPT = String.raw`#!/usr/bin/env node
2631
2947
  // A releasable Go app (tag release:go) is versioned from its git tag, with no
2632
2948
  // manifest, and its per-platform zips are attached to its GitHub Release:
2633
2949
  // release.version.versionActions this file, loaded by 'nx release'
2634
- // node tools/go-app-release.cjs assets
2950
+ // node tools/go-app-release.cjs assets the apps built for all six platforms
2951
+ // node tools/go-app-release.cjs assets --native the apps that need a C toolchain, this OS only
2635
2952
  'use strict'
2636
2953
  const { spawnSync } = require('node:child_process')
2637
- const { existsSync, readdirSync } = require('node:fs')
2954
+ const { existsSync, readdirSync, readFileSync } = require('node:fs')
2638
2955
  const { dirname, join } = require('node:path')
2639
2956
  const { VersionActions } = require('nx/release')
2640
2957
 
@@ -2691,17 +3008,28 @@ function nx (args, env) {
2691
3008
  return run(process.execPath, [join(dirname(manifest), entry), ...args], env)
2692
3009
  }
2693
3010
 
2694
- function releasableApps () {
2695
- return JSON.parse(nx(['show', 'projects', '--projects', 'tag:release:go', '--json'])).filter(Boolean)
3011
+ function releasableApps (native) {
3012
+ const names = existsSync('apps') ? readdirSync('apps') : []
3013
+
3014
+ return names.filter(name => {
3015
+ try {
3016
+ const tags = JSON.parse(readFileSync(join('apps', name, 'project.json'), 'utf8')).tags || []
3017
+
3018
+ return tags.includes('release:go') && tags.includes('build:cgo') === native
3019
+ } catch {
3020
+ return false
3021
+ }
3022
+ })
2696
3023
  }
2697
3024
 
2698
- function attachAssets () {
2699
- const apps = releasableApps()
3025
+ function attachAssets (native) {
3026
+ const apps = releasableApps(native)
2700
3027
  if (apps.length === 0) {
2701
- console.log('No releasable Go app - nothing to attach.')
3028
+ console.log('No releasable ' + (native ? 'native ' : '') + 'Go app - nothing to attach.')
2702
3029
 
2703
3030
  return
2704
3031
  }
3032
+ const target = native ? 'package-native' : 'package-all'
2705
3033
  const tags = run('git', ['tag', '--points-at', 'HEAD']).split(/\r?\n/).filter(Boolean)
2706
3034
  let attached = 0
2707
3035
  for (const app of apps) {
@@ -2711,11 +3039,11 @@ function attachAssets () {
2711
3039
  continue
2712
3040
  }
2713
3041
  const version = tag.slice(app.length + 1)
2714
- console.log(app + ': building the six platforms as ' + version)
2715
- nx(['run', app + ':package-all'], { VERSION: version })
3042
+ console.log(app + ': ' + (native ? 'building for this OS' : 'building the six platforms') + ' as ' + version)
3043
+ nx(['run', app + ':' + target], { VERSION: version })
2716
3044
  const prefix = 'go-app-' + app + '-'
2717
3045
  const zips = existsSync('dist/drop') ? readdirSync('dist/drop').filter(each => each.startsWith(prefix) && each.endsWith('.zip')) : []
2718
- if (zips.length === 0) fail(app + ': package-all produced no ' + prefix + '*.zip in dist/drop.')
3046
+ if (zips.length === 0) fail(app + ': ' + target + ' produced no ' + prefix + '*.zip in dist/drop.')
2719
3047
  const upload = spawnSync('gh', ['release', 'upload', tag, ...zips.map(each => join('dist/drop', each)), '--clobber'], { stdio: 'inherit', shell: process.platform === 'win32' })
2720
3048
  if (upload.status !== 0) fail(app + ': could not attach the zips to the ' + tag + ' release (exit ' + upload.status + ').')
2721
3049
  console.log(app + ': attached ' + zips.length + ' zips to ' + tag)
@@ -2725,8 +3053,8 @@ function attachAssets () {
2725
3053
  }
2726
3054
 
2727
3055
  if (require.main === module) {
2728
- if (process.argv[2] !== 'assets') fail('Usage: node tools/go-app-release.cjs assets')
2729
- attachAssets()
3056
+ if (process.argv[2] !== 'assets' || (process.argv[3] !== undefined && process.argv[3] !== '--native')) fail('Usage: node tools/go-app-release.cjs assets [--native]')
3057
+ attachAssets(process.argv[3] === '--native')
2730
3058
  }
2731
3059
  `;
2732
3060
  var GO_RELEASE_PUBLISH_TARGET = {
@@ -2736,7 +3064,7 @@ var GO_RELEASE_PUBLISH_TARGET = {
2736
3064
  }
2737
3065
  };
2738
3066
  function makeGoAppReleasable(workspaceRoot, name) {
2739
- const projectJsonPath = (0, import_node_path6.join)(workspaceRoot, "apps", name, "project.json");
3067
+ const projectJsonPath = (0, import_node_path7.join)(workspaceRoot, "apps", name, "project.json");
2740
3068
  if (!fileExists(projectJsonPath)) {
2741
3069
  throw new Error(`No Go app at apps/${name}: cannot make it releasable.`);
2742
3070
  }
@@ -2757,22 +3085,22 @@ function makeGoAppReleasable(workspaceRoot, name) {
2757
3085
  }
2758
3086
  })
2759
3087
  );
2760
- writeFileEnsured((0, import_node_path6.join)(workspaceRoot, GO_RELEASE_SCRIPT_PATH), GO_RELEASE_SCRIPT);
3088
+ writeFileEnsured((0, import_node_path7.join)(workspaceRoot, GO_RELEASE_SCRIPT_PATH), GO_RELEASE_SCRIPT);
2761
3089
  }
2762
3090
  function refreshGoReleaseScript(workspaceRoot) {
2763
- const apps = (0, import_node_path6.join)(workspaceRoot, "apps");
3091
+ const apps = (0, import_node_path7.join)(workspaceRoot, "apps");
2764
3092
  let entries;
2765
3093
  try {
2766
- entries = (0, import_node_fs5.readdirSync)(apps);
3094
+ entries = (0, import_node_fs6.readdirSync)(apps);
2767
3095
  } catch {
2768
3096
  return false;
2769
3097
  }
2770
3098
  const hasReleasableApp = entries.some((entry) => {
2771
- const projectJsonPath = (0, import_node_path6.join)(apps, entry, "project.json");
3099
+ const projectJsonPath = (0, import_node_path7.join)(apps, entry, "project.json");
2772
3100
  return fileExists(projectJsonPath) && (readJson(projectJsonPath).tags ?? []).includes(GO_RELEASE_TAG);
2773
3101
  });
2774
- const path = (0, import_node_path6.join)(workspaceRoot, GO_RELEASE_SCRIPT_PATH);
2775
- if (!hasReleasableApp || fileExists(path) && (0, import_node_fs5.readFileSync)(path, "utf8") === GO_RELEASE_SCRIPT) {
3102
+ const path = (0, import_node_path7.join)(workspaceRoot, GO_RELEASE_SCRIPT_PATH);
3103
+ if (!hasReleasableApp || fileExists(path) && (0, import_node_fs6.readFileSync)(path, "utf8") === GO_RELEASE_SCRIPT) {
2776
3104
  return false;
2777
3105
  }
2778
3106
  writeFileEnsured(path, GO_RELEASE_SCRIPT);
@@ -2806,7 +3134,7 @@ function ensureNxGoPlugin(workspaceRoot) {
2806
3134
  }
2807
3135
  }
2808
3136
  function ensureGoModule(workspaceRoot) {
2809
- if (fileExists((0, import_node_path7.join)(workspaceRoot, "go.mod"))) {
3137
+ if (fileExists((0, import_node_path8.join)(workspaceRoot, "go.mod"))) {
2810
3138
  return;
2811
3139
  }
2812
3140
  logger.step("Bootstrapping the workspace Go module (single root go.mod)");
@@ -2815,7 +3143,7 @@ function ensureGoModule(workspaceRoot) {
2815
3143
  }
2816
3144
  function goModulePath(workspaceRoot) {
2817
3145
  try {
2818
- const contents = (0, import_node_fs6.readFileSync)((0, import_node_path7.join)(workspaceRoot, "go.mod"), "utf8");
3146
+ const contents = (0, import_node_fs7.readFileSync)((0, import_node_path8.join)(workspaceRoot, "go.mod"), "utf8");
2819
3147
  return /^module\s+(\S+)/m.exec(contents)?.[1];
2820
3148
  } catch {
2821
3149
  return void 0;
@@ -2875,20 +3203,39 @@ function goPackageAllTarget(tag, name) {
2875
3203
  options: { command }
2876
3204
  };
2877
3205
  }
3206
+ var GO_HOST_PLATFORM = "const host=k=>spawnSync('go',['env',k],{encoding:'utf8'}).stdout.trim();const os=host('GOOS'),arch=host('GOARCH');";
3207
+ function goNativeBuildTarget(name) {
3208
+ const command = `node -e "const{spawnSync}=require('node:child_process');${GO_HOST_PLATFORM}const v=process.env.VERSION||'dev';const out='../../dist/platforms/${name}/'+os+'-'+arch+'/${name}'+(os==='windows'?'.exe':'');const r=spawnSync('go',['build','-trimpath','-ldflags','-s -w -X main.version='+v,'-o',out,'.'],{cwd:'apps/${name}',stdio:'inherit',env:{...process.env,CGO_ENABLED:'1'}});process.exit(r.status??1)"`;
3209
+ return {
3210
+ executor: "nx:run-commands",
3211
+ inputs: ["default", "^default", "{workspaceRoot}/go.mod", "{workspaceRoot}/go.sum", { env: "VERSION" }],
3212
+ outputs: [`{workspaceRoot}/dist/platforms/${name}`],
3213
+ options: { command }
3214
+ };
3215
+ }
3216
+ function goNativePackageTarget(name) {
3217
+ const command = `node -e "const fs=require('node:fs');const{spawnSync}=require('node:child_process');const A=require('adm-zip');${GO_HOST_PLATFORM}const d=os+'-'+arch;fs.mkdirSync('dist/drop',{recursive:true});const z=new A();z.addLocalFolder('dist/platforms/${name}/'+d);z.writeZip('dist/drop/go-app-${name}-'+d+'.zip')"`;
3218
+ return {
3219
+ executor: "nx:run-commands",
3220
+ dependsOn: ["build-native"],
3221
+ outputs: [`{workspaceRoot}/dist/drop/go-app-${name}-*.zip`],
3222
+ options: { command }
3223
+ };
3224
+ }
2878
3225
  function addGoPlatformTargets(workspaceRoot) {
2879
3226
  const changed = [];
2880
- const apps = (0, import_node_path7.join)(workspaceRoot, "apps");
3227
+ const apps = (0, import_node_path8.join)(workspaceRoot, "apps");
2881
3228
  if (!fileExists(apps)) {
2882
3229
  return changed;
2883
3230
  }
2884
- for (const name of (0, import_node_fs6.readdirSync)(apps)) {
2885
- const projectJsonPath = (0, import_node_path7.join)(apps, name, "project.json");
3231
+ for (const name of (0, import_node_fs7.readdirSync)(apps)) {
3232
+ const projectJsonPath = (0, import_node_path8.join)(apps, name, "project.json");
2886
3233
  if (!fileExists(projectJsonPath)) {
2887
3234
  continue;
2888
3235
  }
2889
- const project = JSON.parse((0, import_node_fs6.readFileSync)(projectJsonPath, "utf8"));
3236
+ const project = JSON.parse((0, import_node_fs7.readFileSync)(projectJsonPath, "utf8"));
2890
3237
  const tag = (project.tags ?? []).find((each) => each === "type:go-app" || each === "type:go-function-app")?.slice("type:".length);
2891
- if (tag === void 0) {
3238
+ if (tag === void 0 || (project.tags ?? []).includes(GO_CGO_TAG)) {
2892
3239
  continue;
2893
3240
  }
2894
3241
  const missing = {};
@@ -2922,8 +3269,8 @@ function goLibraryIdentifiers(projectName) {
2922
3269
  }
2923
3270
  function reshapeGoLibraryScaffold(projectRoot, projectName) {
2924
3271
  const { packageName, functionName, fileStem } = goLibraryIdentifiers(projectName);
2925
- (0, import_node_fs6.rmSync)((0, import_node_path7.join)(projectRoot, `${projectName}.go`), { force: true });
2926
- (0, import_node_fs6.rmSync)((0, import_node_path7.join)(projectRoot, `${projectName}_test.go`), { force: true });
3272
+ (0, import_node_fs7.rmSync)((0, import_node_path8.join)(projectRoot, `${projectName}.go`), { force: true });
3273
+ (0, import_node_fs7.rmSync)((0, import_node_path8.join)(projectRoot, `${projectName}_test.go`), { force: true });
2927
3274
  const files = [
2928
3275
  [
2929
3276
  "doc.go",
@@ -2933,14 +3280,14 @@ package ${packageName}
2933
3280
  `
2934
3281
  ],
2935
3282
  [
2936
- (0, import_node_path7.join)(packageName, "doc.go"),
3283
+ (0, import_node_path8.join)(packageName, "doc.go"),
2937
3284
  `// Package ${packageName} is the starter slice of ${projectName}: rename it after
2938
3285
  // the outcome it delivers, and add one package per further outcome.
2939
3286
  package ${packageName}
2940
3287
  `
2941
3288
  ],
2942
3289
  [
2943
- (0, import_node_path7.join)(packageName, `${fileStem}_use_case.go`),
3290
+ (0, import_node_path8.join)(packageName, `${fileStem}_use_case.go`),
2944
3291
  `package ${packageName}
2945
3292
 
2946
3293
  // ${functionName} is the generator's sample behaviour, kept so the slice builds and tests.
@@ -2950,7 +3297,7 @@ func ${functionName}(name string) string {
2950
3297
  `
2951
3298
  ],
2952
3299
  [
2953
- (0, import_node_path7.join)(packageName, `${fileStem}_use_case_test.go`),
3300
+ (0, import_node_path8.join)(packageName, `${fileStem}_use_case_test.go`),
2954
3301
  `package ${packageName}
2955
3302
 
2956
3303
  import "testing"
@@ -2964,7 +3311,7 @@ func Test${functionName}(t *testing.T) {
2964
3311
  ]
2965
3312
  ];
2966
3313
  for (const [relativePath, content] of files) {
2967
- const path = (0, import_node_path7.join)(projectRoot, relativePath);
3314
+ const path = (0, import_node_path8.join)(projectRoot, relativePath);
2968
3315
  if (!fileExists(path)) {
2969
3316
  writeFileEnsured(path, content);
2970
3317
  }
@@ -2976,8 +3323,12 @@ function prepareGo(workspaceRoot) {
2976
3323
  warnIfNoGolangciLint(workspaceRoot);
2977
3324
  ensureNxGoPlugin(workspaceRoot);
2978
3325
  ensureGoModule(workspaceRoot);
3326
+ if (registerNxGoPlugin(workspaceRoot)) {
3327
+ logger.step("Registering the Go plugin in nx.json, so Nx can see which Go project imports which");
3328
+ }
2979
3329
  }
2980
3330
  function addGoApp(workspaceRoot, name, options = {}) {
3331
+ const cgo = options.cgo === true;
2981
3332
  prepareGo(workspaceRoot);
2982
3333
  ensureAdmZip(workspaceRoot);
2983
3334
  runNx(
@@ -2986,24 +3337,31 @@ function addGoApp(workspaceRoot, name, options = {}) {
2986
3337
  "@nx-go/nx-go:application",
2987
3338
  `apps/${name}`,
2988
3339
  `--name=${name}`,
2989
- "--tags=type:go-app",
3340
+ cgo ? `--tags=type:go-app,${GO_CGO_TAG}` : "--tags=type:go-app",
2990
3341
  "--no-interactive"
2991
3342
  ],
2992
3343
  workspaceRoot
2993
3344
  );
2994
- addProjectJsonTargets((0, import_node_path7.join)(workspaceRoot, "apps", name, "project.json"), {
2995
- "build": goBuildTarget(name),
2996
- "test": goTestTarget(),
2997
- "lint": goLintTarget(),
2998
- "package": goPackageTarget("go-app", name),
2999
- "build-all": goBuildAllTarget(name),
3000
- "package-all": goPackageAllTarget("go-app", name),
3001
- "start": goStartTarget(name)
3345
+ addProjectJsonTargets((0, import_node_path8.join)(workspaceRoot, "apps", name, "project.json"), {
3346
+ build: goBuildTarget(name),
3347
+ test: goTestTarget(),
3348
+ lint: goLintTarget(),
3349
+ ...cgo ? { "build-native": goNativeBuildTarget(name), "package-native": goNativePackageTarget(name) } : {
3350
+ "package": goPackageTarget("go-app", name),
3351
+ "build-all": goBuildAllTarget(name),
3352
+ "package-all": goPackageAllTarget("go-app", name)
3353
+ },
3354
+ start: goStartTarget(name)
3002
3355
  });
3003
3356
  if (options.release === true) {
3004
3357
  makeGoAppReleasable(workspaceRoot, name);
3005
3358
  }
3006
3359
  registerProjectCommands(workspaceRoot, name, { build: true, start: `nx run ${name}:start` });
3360
+ if (cgo) {
3361
+ logger.warn(
3362
+ `${name} needs a C toolchain, so CI builds it on a runner of each OS. Run \`mnci upgrade\` to add the native job to your pipeline, and add the -dev packages it links to the Linux prerequisites step.`
3363
+ );
3364
+ }
3007
3365
  }
3008
3366
  function addGoFunctionApp(workspaceRoot, name) {
3009
3367
  prepareGo(workspaceRoot);
@@ -3019,7 +3377,7 @@ function addGoFunctionApp(workspaceRoot, name) {
3019
3377
  ],
3020
3378
  workspaceRoot
3021
3379
  );
3022
- addProjectJsonTargets((0, import_node_path7.join)(workspaceRoot, "apps", name, "project.json"), {
3380
+ addProjectJsonTargets((0, import_node_path8.join)(workspaceRoot, "apps", name, "project.json"), {
3023
3381
  "build": goBuildTarget(name),
3024
3382
  "test": goTestTarget(),
3025
3383
  "lint": goLintTarget(),
@@ -3042,11 +3400,11 @@ function addGoLib(workspaceRoot, name) {
3042
3400
  ],
3043
3401
  workspaceRoot
3044
3402
  );
3045
- addProjectJsonTargets((0, import_node_path7.join)(workspaceRoot, "packages", name, "project.json"), {
3403
+ addProjectJsonTargets((0, import_node_path8.join)(workspaceRoot, "packages", name, "project.json"), {
3046
3404
  test: goTestTarget(),
3047
3405
  lint: goLintTarget()
3048
3406
  });
3049
- const slice = reshapeGoLibraryScaffold((0, import_node_path7.join)(workspaceRoot, "packages", name), name);
3407
+ const slice = reshapeGoLibraryScaffold((0, import_node_path8.join)(workspaceRoot, "packages", name), name);
3050
3408
  registerProjectCommands(workspaceRoot, name, { build: false });
3051
3409
  const module2 = goModulePath(workspaceRoot);
3052
3410
  if (module2) {
@@ -3066,11 +3424,11 @@ function addGoInternalLib(workspaceRoot, name) {
3066
3424
  ],
3067
3425
  workspaceRoot
3068
3426
  );
3069
- addProjectJsonTargets((0, import_node_path7.join)(workspaceRoot, "libs", name, "project.json"), {
3427
+ addProjectJsonTargets((0, import_node_path8.join)(workspaceRoot, "libs", name, "project.json"), {
3070
3428
  test: goTestTarget(),
3071
3429
  lint: goLintTarget()
3072
3430
  });
3073
- const slice = reshapeGoLibraryScaffold((0, import_node_path7.join)(workspaceRoot, "libs", name), name);
3431
+ const slice = reshapeGoLibraryScaffold((0, import_node_path8.join)(workspaceRoot, "libs", name), name);
3074
3432
  registerProjectCommands(workspaceRoot, name, { build: false });
3075
3433
  const module2 = goModulePath(workspaceRoot);
3076
3434
  if (module2) {
@@ -3079,7 +3437,7 @@ function addGoInternalLib(workspaceRoot, name) {
3079
3437
  }
3080
3438
 
3081
3439
  // src/project-scaffolding/node.use-case.ts
3082
- var import_node_path8 = require("path");
3440
+ var import_node_path9 = require("path");
3083
3441
  function ensurePlugin2(workspaceRoot, packageName) {
3084
3442
  if (hasPlugin(workspaceRoot, packageName)) {
3085
3443
  return;
@@ -3103,12 +3461,12 @@ function runNodeApp(workspaceRoot, name, stack, framework) {
3103
3461
  ],
3104
3462
  workspaceRoot
3105
3463
  );
3106
- const appRoot = (0, import_node_path8.join)(workspaceRoot, "apps", name);
3464
+ const appRoot = (0, import_node_path9.join)(workspaceRoot, "apps", name);
3107
3465
  separateDeclarationOutput(appRoot);
3108
3466
  repairAssetMapping(appRoot, name);
3109
3467
  }
3110
3468
  function separateDeclarationOutput(appRoot) {
3111
- const tsconfigPath = (0, import_node_path8.join)(appRoot, "tsconfig.app.json");
3469
+ const tsconfigPath = (0, import_node_path9.join)(appRoot, "tsconfig.app.json");
3112
3470
  if (!fileExists(tsconfigPath)) {
3113
3471
  return;
3114
3472
  }
@@ -3130,7 +3488,7 @@ function separateDeclarationOutput(appRoot) {
3130
3488
  );
3131
3489
  }
3132
3490
  function repairAssetMapping(appRoot, name) {
3133
- const manifestPath = (0, import_node_path8.join)(appRoot, "package.json");
3491
+ const manifestPath = (0, import_node_path9.join)(appRoot, "package.json");
3134
3492
  if (!fileExists(manifestPath)) {
3135
3493
  return;
3136
3494
  }
@@ -3157,7 +3515,7 @@ function nodeAppPackageTarget(name) {
3157
3515
  function addNodeApp(workspaceRoot, name, stack, framework = "none") {
3158
3516
  runNodeApp(workspaceRoot, name, stack, framework);
3159
3517
  ensureAdmZip(workspaceRoot);
3160
- addNxTargets((0, import_node_path8.join)(workspaceRoot, "apps", name, "package.json"), {
3518
+ addNxTargets((0, import_node_path9.join)(workspaceRoot, "apps", name, "package.json"), {
3161
3519
  package: nodeAppPackageTarget(name)
3162
3520
  });
3163
3521
  removeGeneratedEslintConfig(workspaceRoot, `apps/${name}`);
@@ -3213,10 +3571,10 @@ describe('buildGreeting', () => {
3213
3571
  })
3214
3572
  `;
3215
3573
  function repairNodeFunctionAppManifest(nodeFunctionAppRoot, workspaceRoot) {
3216
- const manifestPath = (0, import_node_path8.join)(nodeFunctionAppRoot, "package.json");
3574
+ const manifestPath = (0, import_node_path9.join)(nodeFunctionAppRoot, "package.json");
3217
3575
  const manifest = readJson(manifestPath);
3218
3576
  const azureFunctionsVersion = readJson(
3219
- (0, import_node_path8.join)(workspaceRoot, "node_modules/@azure/functions/package.json")
3577
+ (0, import_node_path9.join)(workspaceRoot, "node_modules/@azure/functions/package.json")
3220
3578
  ).version;
3221
3579
  const dependencies = manifest.dependencies ?? {};
3222
3580
  writeFileEnsured(
@@ -3259,21 +3617,21 @@ function nodeFunctionAppStartTarget(name) {
3259
3617
  function addNodeFunctionApp(workspaceRoot, name, stack) {
3260
3618
  runNodeApp(workspaceRoot, name, stack, "none");
3261
3619
  ensureAzureFunctionsPackage(workspaceRoot);
3262
- const nodeFunctionAppRoot = (0, import_node_path8.join)(workspaceRoot, "apps", name);
3263
- writeFileEnsured((0, import_node_path8.join)(nodeFunctionAppRoot, "src/main.ts"), NODE_FUNCTION_APP_MAIN);
3264
- writeFileEnsured((0, import_node_path8.join)(nodeFunctionAppRoot, "src/functions/hello.ts"), NODE_FUNCTION_APP_HELLO);
3620
+ const nodeFunctionAppRoot = (0, import_node_path9.join)(workspaceRoot, "apps", name);
3621
+ writeFileEnsured((0, import_node_path9.join)(nodeFunctionAppRoot, "src/main.ts"), NODE_FUNCTION_APP_MAIN);
3622
+ writeFileEnsured((0, import_node_path9.join)(nodeFunctionAppRoot, "src/functions/hello.ts"), NODE_FUNCTION_APP_HELLO);
3265
3623
  writeFileEnsured(
3266
- (0, import_node_path8.join)(nodeFunctionAppRoot, "src/functions/greeting.ts"),
3624
+ (0, import_node_path9.join)(nodeFunctionAppRoot, "src/functions/greeting.ts"),
3267
3625
  NODE_FUNCTION_APP_GREETING
3268
3626
  );
3269
3627
  writeFileEnsured(
3270
- (0, import_node_path8.join)(nodeFunctionAppRoot, "src/functions/greeting.spec.ts"),
3628
+ (0, import_node_path9.join)(nodeFunctionAppRoot, "src/functions/greeting.spec.ts"),
3271
3629
  NODE_FUNCTION_APP_GREETING_SPEC
3272
3630
  );
3273
- writeFileEnsured((0, import_node_path8.join)(nodeFunctionAppRoot, "host.json"), NODE_FUNCTION_APP_HOST_JSON);
3631
+ writeFileEnsured((0, import_node_path9.join)(nodeFunctionAppRoot, "host.json"), NODE_FUNCTION_APP_HOST_JSON);
3274
3632
  repairNodeFunctionAppManifest(nodeFunctionAppRoot, workspaceRoot);
3275
3633
  ensureAdmZip(workspaceRoot);
3276
- addNxTargets((0, import_node_path8.join)(nodeFunctionAppRoot, "package.json"), {
3634
+ addNxTargets((0, import_node_path9.join)(nodeFunctionAppRoot, "package.json"), {
3277
3635
  package: nodeFunctionAppPackageTarget(name),
3278
3636
  prune: nodeFunctionAppPruneTarget(name),
3279
3637
  start: nodeFunctionAppStartTarget(name)
@@ -3283,11 +3641,11 @@ function addNodeFunctionApp(workspaceRoot, name, stack) {
3283
3641
  }
3284
3642
 
3285
3643
  // src/project-scaffolding/npm-lib.use-case.ts
3286
- var import_node_path12 = require("path");
3644
+ var import_node_path13 = require("path");
3287
3645
 
3288
3646
  // src/rollup-library/repair-publishable-manifest.use-case.ts
3289
- var import_node_fs7 = require("fs");
3290
- var import_node_path9 = require("path");
3647
+ var import_node_fs8 = require("fs");
3648
+ var import_node_path10 = require("path");
3291
3649
  var WRONG_TYPES_PATH = "./dist/index.esm.d.ts";
3292
3650
  var ACTUAL_TYPES_PATH = "./dist/src/index.d.ts";
3293
3651
  var DECLARATION_MAP_EXCLUSION = "!**/*.d.ts.map";
@@ -3310,14 +3668,14 @@ function repairPublishableManifest(manifestPath) {
3310
3668
  }
3311
3669
  function repairPublishableManifests(workspaceRoot) {
3312
3670
  const changed = [];
3313
- const manifests = (0, import_node_fs7.globSync)(["packages/*/package.json", "libs/*/package.json"], {
3671
+ const manifests = (0, import_node_fs8.globSync)(["packages/*/package.json", "libs/*/package.json"], {
3314
3672
  cwd: workspaceRoot
3315
3673
  });
3316
3674
  for (const relativePath of manifests) {
3317
- const manifestPath = (0, import_node_path9.join)(workspaceRoot, relativePath);
3318
- const before = (0, import_node_fs7.readFileSync)(manifestPath, "utf8");
3675
+ const manifestPath = (0, import_node_path10.join)(workspaceRoot, relativePath);
3676
+ const before = (0, import_node_fs8.readFileSync)(manifestPath, "utf8");
3319
3677
  repairPublishableManifest(manifestPath);
3320
- const after = (0, import_node_fs7.readFileSync)(manifestPath, "utf8");
3678
+ const after = (0, import_node_fs8.readFileSync)(manifestPath, "utf8");
3321
3679
  if (after !== before) {
3322
3680
  changed.push(relativePath.replaceAll("\\", "/"));
3323
3681
  }
@@ -3326,8 +3684,8 @@ function repairPublishableManifests(workspaceRoot) {
3326
3684
  }
3327
3685
 
3328
3686
  // src/rollup-library/repair-rollup-config.use-case.ts
3329
- var import_node_fs8 = require("fs");
3330
- var import_node_path10 = require("path");
3687
+ var import_node_fs9 = require("fs");
3688
+ var import_node_path11 = require("path");
3331
3689
 
3332
3690
  // src/rollup-library/rollup-config.algorithm.ts
3333
3691
  var ROLLUP_CONFIG_PLACEHOLDER = [
@@ -3529,12 +3887,12 @@ function withUpgradedDeclarationSpecifierPlugin(config) {
3529
3887
  // src/rollup-library/repair-rollup-config.use-case.ts
3530
3888
  function repairRollupSourceMaps(workspaceRoot) {
3531
3889
  const changed = [];
3532
- const configs = (0, import_node_fs8.globSync)(["packages/*/rollup.config.cjs", "libs/*/rollup.config.cjs"], {
3890
+ const configs = (0, import_node_fs9.globSync)(["packages/*/rollup.config.cjs", "libs/*/rollup.config.cjs"], {
3533
3891
  cwd: workspaceRoot
3534
3892
  });
3535
3893
  for (const relativePath of configs) {
3536
- const configPath = (0, import_node_path10.join)(workspaceRoot, relativePath);
3537
- const before = (0, import_node_fs8.readFileSync)(configPath, "utf8");
3894
+ const configPath = (0, import_node_path11.join)(workspaceRoot, relativePath);
3895
+ const before = (0, import_node_fs9.readFileSync)(configPath, "utf8");
3538
3896
  const after = withRollupSourceMaps(before);
3539
3897
  if (after !== before) {
3540
3898
  writeFileEnsured(configPath, after);
@@ -3545,12 +3903,12 @@ function repairRollupSourceMaps(workspaceRoot) {
3545
3903
  }
3546
3904
  function upgradeDeclarationSpecifierPlugins(workspaceRoot) {
3547
3905
  const changed = [];
3548
- const configs = (0, import_node_fs8.globSync)(["packages/*/rollup.config.cjs", "libs/*/rollup.config.cjs"], {
3906
+ const configs = (0, import_node_fs9.globSync)(["packages/*/rollup.config.cjs", "libs/*/rollup.config.cjs"], {
3549
3907
  cwd: workspaceRoot
3550
3908
  });
3551
3909
  for (const relativePath of configs) {
3552
- const configPath = (0, import_node_path10.join)(workspaceRoot, relativePath);
3553
- const before = (0, import_node_fs8.readFileSync)(configPath, "utf8");
3910
+ const configPath = (0, import_node_path11.join)(workspaceRoot, relativePath);
3911
+ const before = (0, import_node_fs9.readFileSync)(configPath, "utf8");
3554
3912
  const after = withUpgradedDeclarationSpecifierPlugin(before);
3555
3913
  if (after !== before) {
3556
3914
  writeFileEnsured(configPath, after);
@@ -3560,11 +3918,11 @@ function upgradeDeclarationSpecifierPlugins(workspaceRoot) {
3560
3918
  return changed;
3561
3919
  }
3562
3920
  function repairDeclarationSpecifiers(projectRoot) {
3563
- const configPath = (0, import_node_path10.join)(projectRoot, "rollup.config.cjs");
3921
+ const configPath = (0, import_node_path11.join)(projectRoot, "rollup.config.cjs");
3564
3922
  if (!fileExists(configPath)) {
3565
3923
  return;
3566
3924
  }
3567
- const config = (0, import_node_fs8.readFileSync)(configPath, "utf8");
3925
+ const config = (0, import_node_fs9.readFileSync)(configPath, "utf8");
3568
3926
  if (!config.includes(ROLLUP_CONFIG_PLACEHOLDER)) {
3569
3927
  return;
3570
3928
  }
@@ -3573,10 +3931,10 @@ function repairDeclarationSpecifiers(projectRoot) {
3573
3931
  }
3574
3932
 
3575
3933
  // src/rollup-library/rollup-config.repository.ts
3576
- var import_node_fs9 = require("fs");
3577
- var import_node_path11 = require("path");
3934
+ var import_node_fs10 = require("fs");
3935
+ var import_node_path12 = require("path");
3578
3936
  function resolveRequireTarget(fromDir, specifier) {
3579
- const base = (0, import_node_path11.join)(fromDir, specifier);
3937
+ const base = (0, import_node_path12.join)(fromDir, specifier);
3580
3938
  return [base, `${base}.cjs`, `${base}.js`].find((candidate) => fileExists(candidate));
3581
3939
  }
3582
3940
  function resolveRollupConfigText(configPath, visited = /* @__PURE__ */ new Set()) {
@@ -3586,7 +3944,7 @@ function resolveRollupConfigText(configPath, visited = /* @__PURE__ */ new Set()
3586
3944
  visited.add(configPath);
3587
3945
  let text;
3588
3946
  try {
3589
- text = (0, import_node_fs9.readFileSync)(configPath, "utf8");
3947
+ text = (0, import_node_fs10.readFileSync)(configPath, "utf8");
3590
3948
  } catch {
3591
3949
  return "";
3592
3950
  }
@@ -3594,15 +3952,15 @@ function resolveRollupConfigText(configPath, visited = /* @__PURE__ */ new Set()
3594
3952
  text.matchAll(/require\((['"])(\.[^'"]*)\1\)/g),
3595
3953
  (match) => match[2]
3596
3954
  );
3597
- const requiredText = specifiers.map((specifier) => resolveRequireTarget((0, import_node_path11.dirname)(configPath), specifier)).filter((target) => target !== void 0).map((target) => resolveRollupConfigText(target, visited));
3955
+ const requiredText = specifiers.map((specifier) => resolveRequireTarget((0, import_node_path12.dirname)(configPath), specifier)).filter((target) => target !== void 0).map((target) => resolveRollupConfigText(target, visited));
3598
3956
  return [text, ...requiredText].join("\n");
3599
3957
  }
3600
3958
 
3601
3959
  // src/project-scaffolding/npm-lib.use-case.ts
3602
3960
  async function addNpmLib(workspaceRoot, name, options, kindProvided, stack) {
3603
3961
  const scope = options.scope ?? (kindProvided ? defaultScope(workspaceRoot) : await promptText("npm scope for the published package", defaultScope(workspaceRoot)));
3604
- const projectRoot = (0, import_node_path12.join)(workspaceRoot, "packages", name);
3605
- const manifestPath = (0, import_node_path12.join)(projectRoot, "package.json");
3962
+ const projectRoot = (0, import_node_path13.join)(workspaceRoot, "packages", name);
3963
+ const manifestPath = (0, import_node_path13.join)(projectRoot, "package.json");
3606
3964
  runGeneratorAndRepair(
3607
3965
  workspaceRoot,
3608
3966
  [
@@ -3631,8 +3989,8 @@ async function addNpmLib(workspaceRoot, name, options, kindProvided, stack) {
3631
3989
  }
3632
3990
 
3633
3991
  // src/project-scaffolding/python.use-case.ts
3634
- var import_node_fs10 = require("fs");
3635
- var import_node_path13 = require("path");
3992
+ var import_node_fs11 = require("fs");
3993
+ var import_node_path14 = require("path");
3636
3994
  function ensurePython(workspaceRoot) {
3637
3995
  const hasPython = runShell("python3", ["--version"], workspaceRoot) === 0 || runShell("python", ["--version"], workspaceRoot) === 0;
3638
3996
  if (!hasPython) {
@@ -3655,7 +4013,7 @@ function ensurePythonPipPlugin(workspaceRoot) {
3655
4013
  registerPythonGraphPlugin(workspaceRoot);
3656
4014
  }
3657
4015
  function registerPythonGraphPlugin(workspaceRoot) {
3658
- const nxJsonPath = (0, import_node_path13.join)(workspaceRoot, "nx.json");
4016
+ const nxJsonPath = (0, import_node_path14.join)(workspaceRoot, "nx.json");
3659
4017
  if (!fileExists(nxJsonPath)) {
3660
4018
  return;
3661
4019
  }
@@ -3678,7 +4036,7 @@ pytest
3678
4036
  pip-audit
3679
4037
  `;
3680
4038
  function ensureRequirementsDev(workspaceRoot) {
3681
- const requirementsDevPath = (0, import_node_path13.join)(workspaceRoot, "requirements-dev.txt");
4039
+ const requirementsDevPath = (0, import_node_path14.join)(workspaceRoot, "requirements-dev.txt");
3682
4040
  if (!fileExists(requirementsDevPath)) {
3683
4041
  writeFileEnsured(requirementsDevPath, PYTHON_REQUIREMENTS_DEV);
3684
4042
  }
@@ -3738,8 +4096,8 @@ function addPythonApp(workspaceRoot, name) {
3738
4096
  ["g", "@mnci/nx-python-pip:application", name, `--directory=apps/${name}`, "--no-interactive"],
3739
4097
  workspaceRoot
3740
4098
  );
3741
- writeFileEnsured((0, import_node_path13.join)(workspaceRoot, "apps", name, "main.py"), pythonAppMain(name));
3742
- addProjectJsonTargets((0, import_node_path13.join)(workspaceRoot, "apps", name, "project.json"), {
4099
+ writeFileEnsured((0, import_node_path14.join)(workspaceRoot, "apps", name, "main.py"), pythonAppMain(name));
4100
+ addProjectJsonTargets((0, import_node_path14.join)(workspaceRoot, "apps", name, "project.json"), {
3743
4101
  package: pythonAppPackageTarget(name),
3744
4102
  start: pythonAppStartTarget(name)
3745
4103
  });
@@ -3761,7 +4119,7 @@ function addPythonFunctionApp(workspaceRoot, name) {
3761
4119
  workspaceRoot
3762
4120
  );
3763
4121
  const moduleDirectory = pythonModuleDirectory(name);
3764
- addProjectJsonTargets((0, import_node_path13.join)(workspaceRoot, "apps", name, "project.json"), {
4122
+ addProjectJsonTargets((0, import_node_path14.join)(workspaceRoot, "apps", name, "project.json"), {
3765
4123
  package: pythonFunctionAppPackageTarget(name, moduleDirectory),
3766
4124
  start: pythonFunctionAppStartTarget(name)
3767
4125
  });
@@ -3802,7 +4160,7 @@ function addPythonInternalLib(workspaceRoot, name) {
3802
4160
  var PYTHON_PROJECT_DIRS = ["apps", "python-packages", "libs"];
3803
4161
  function findPythonProjectDirectory(workspaceRoot, name) {
3804
4162
  return PYTHON_PROJECT_DIRS.find(
3805
- (directory) => fileExists((0, import_node_path13.join)(workspaceRoot, directory, name, "pyproject.toml"))
4163
+ (directory) => fileExists((0, import_node_path14.join)(workspaceRoot, directory, name, "pyproject.toml"))
3806
4164
  );
3807
4165
  }
3808
4166
  function parseVendorEntries(pyprojectToml) {
@@ -3841,7 +4199,7 @@ async function addPythonVendor(workspaceRoot, consumer, options, kindProvided) {
3841
4199
  `No Python project named '${consumer}' with a pyproject.toml found (checked apps/, python-packages/, libs/). A Python function app has no pyproject.toml \u2014 there is nothing to vendor into.`
3842
4200
  );
3843
4201
  }
3844
- if (!fileExists((0, import_node_path13.join)(workspaceRoot, "libs", lib, "pyproject.toml"))) {
4202
+ if (!fileExists((0, import_node_path14.join)(workspaceRoot, "libs", lib, "pyproject.toml"))) {
3845
4203
  throw new Error(
3846
4204
  `No internal Python library named '${lib}' found at libs/${lib}/pyproject.toml. Only an internal library (added via 'mnci add python-internal-lib') can be vendored.`
3847
4205
  );
@@ -3849,8 +4207,8 @@ async function addPythonVendor(workspaceRoot, consumer, options, kindProvided) {
3849
4207
  if (consumerDirectory === "libs" && consumer === lib) {
3850
4208
  throw new Error(`'${consumer}' cannot vendor itself.`);
3851
4209
  }
3852
- const pyprojectPath = (0, import_node_path13.join)(workspaceRoot, consumerDirectory, consumer, "pyproject.toml");
3853
- const pyprojectToml = (0, import_node_fs10.readFileSync)(pyprojectPath, "utf8");
4210
+ const pyprojectPath = (0, import_node_path14.join)(workspaceRoot, consumerDirectory, consumer, "pyproject.toml");
4211
+ const pyprojectToml = (0, import_node_fs11.readFileSync)(pyprojectPath, "utf8");
3854
4212
  if (parseVendorEntries(pyprojectToml).includes(lib)) {
3855
4213
  logger.info(`'${consumer}' already vendors '${lib}' \u2014 nothing to do.`);
3856
4214
  return;
@@ -3862,8 +4220,8 @@ async function addPythonVendor(workspaceRoot, consumer, options, kindProvided) {
3862
4220
  }
3863
4221
 
3864
4222
  // src/project-scaffolding/react-app.use-case.ts
3865
- var import_node_fs11 = require("fs");
3866
- var import_node_path14 = require("path");
4223
+ var import_node_fs12 = require("fs");
4224
+ var import_node_path15 = require("path");
3867
4225
  var REACT_ENVIRONMENTS = ["dev", "uat", "prod"];
3868
4226
  function reactEnvironmentFile(environment) {
3869
4227
  return `# Vite compiles VITE_-prefixed vars into the '${environment}' bundle at build time.
@@ -3900,12 +4258,12 @@ function reactAppTargets(name) {
3900
4258
  return targets;
3901
4259
  }
3902
4260
  function allowEnvFiles(workspaceRoot) {
3903
- const gitignorePath = (0, import_node_path14.join)(workspaceRoot, ".gitignore");
4261
+ const gitignorePath = (0, import_node_path15.join)(workspaceRoot, ".gitignore");
3904
4262
  if (!fileExists(gitignorePath)) {
3905
4263
  return;
3906
4264
  }
3907
4265
  const marker = "# MoNecromanCI: keep the committed per-environment Vite config (public VITE_ values)";
3908
- const current = (0, import_node_fs11.readFileSync)(gitignorePath, "utf8");
4266
+ const current = (0, import_node_fs12.readFileSync)(gitignorePath, "utf8");
3909
4267
  if (current.includes(marker)) {
3910
4268
  return;
3911
4269
  }
@@ -3932,24 +4290,24 @@ function addReactApp(workspaceRoot, name, stack) {
3932
4290
  workspaceRoot
3933
4291
  );
3934
4292
  ensureAdmZip(workspaceRoot);
3935
- const reactAppRoot = (0, import_node_path14.join)(workspaceRoot, "apps", name);
4293
+ const reactAppRoot = (0, import_node_path15.join)(workspaceRoot, "apps", name);
3936
4294
  for (const environment of REACT_ENVIRONMENTS) {
3937
- writeFileEnsured((0, import_node_path14.join)(reactAppRoot, `.env.${environment}`), reactEnvironmentFile(environment));
4295
+ writeFileEnsured((0, import_node_path15.join)(reactAppRoot, `.env.${environment}`), reactEnvironmentFile(environment));
3938
4296
  }
3939
4297
  allowEnvFiles(workspaceRoot);
3940
- addNxTargets((0, import_node_path14.join)(reactAppRoot, "package.json"), reactAppTargets(name));
4298
+ addNxTargets((0, import_node_path15.join)(reactAppRoot, "package.json"), reactAppTargets(name));
3941
4299
  removeGeneratedEslintConfig(workspaceRoot, `apps/${name}`);
3942
4300
  registerProjectCommands(workspaceRoot, name, { build: true, start: `nx run ${name}:serve` });
3943
4301
  }
3944
4302
 
3945
4303
  // src/project-scaffolding/react-lib.use-case.ts
3946
- var import_node_path15 = require("path");
4304
+ var import_node_path16 = require("path");
3947
4305
  var REACT_LIB_BUNDLER = "rollup";
3948
4306
  async function addReactLib(workspaceRoot, name, options, kindProvided, stack) {
3949
4307
  ensurePlugin(workspaceRoot, "@nx/react");
3950
4308
  const scope = options.scope ?? (kindProvided ? defaultScope(workspaceRoot) : await promptText("npm scope for the published package", defaultScope(workspaceRoot)));
3951
- const projectRoot = (0, import_node_path15.join)(workspaceRoot, "packages", name);
3952
- const publishableManifest = (0, import_node_path15.join)(projectRoot, "package.json");
4309
+ const projectRoot = (0, import_node_path16.join)(workspaceRoot, "packages", name);
4310
+ const publishableManifest = (0, import_node_path16.join)(projectRoot, "package.json");
3953
4311
  runGeneratorAndRepair(
3954
4312
  workspaceRoot,
3955
4313
  [
@@ -3978,8 +4336,8 @@ async function addReactLib(workspaceRoot, name, options, kindProvided, stack) {
3978
4336
  }
3979
4337
  function addReactInternalLib(workspaceRoot, name, stack) {
3980
4338
  ensurePlugin(workspaceRoot, "@nx/react");
3981
- const projectRoot = (0, import_node_path15.join)(workspaceRoot, "libs", name);
3982
- const privateManifest = (0, import_node_path15.join)(projectRoot, "package.json");
4339
+ const projectRoot = (0, import_node_path16.join)(workspaceRoot, "libs", name);
4340
+ const privateManifest = (0, import_node_path16.join)(projectRoot, "package.json");
3983
4341
  runGeneratorAndRepair(
3984
4342
  workspaceRoot,
3985
4343
  [
@@ -4005,8 +4363,8 @@ function addReactInternalLib(workspaceRoot, name, stack) {
4005
4363
  }
4006
4364
 
4007
4365
  // src/project-scaffolding/vscode-extension.use-case.ts
4008
- var import_node_fs12 = require("fs");
4009
- var import_node_path16 = require("path");
4366
+ var import_node_fs13 = require("fs");
4367
+ var import_node_path17 = require("path");
4010
4368
  var VSCODE_EXTENSION_SCRIPT_PATH = "tools/vscode-extension.cjs";
4011
4369
  var VSCODE_SIDECAR_TARGETS = {
4012
4370
  "win32-x64": "windows-amd64",
@@ -4190,8 +4548,8 @@ export const window = {
4190
4548
  var VSCODE_STUB_PATH = "test/vscode.stub.ts";
4191
4549
  function mapVscodeToStub(projectRoot, testRunner) {
4192
4550
  const [file, anchor, mapping] = testRunner === "jest" ? ["jest.config.cts", "testEnvironment: 'node',", `moduleNameMapper: { '^vscode$': '<rootDir>/${VSCODE_STUB_PATH}' },`] : ["vitest.config.mts", "environment: 'node',", `alias: { vscode: \`\${import.meta.dirname}/${VSCODE_STUB_PATH}\` },`];
4193
- const path = (0, import_node_path16.join)(projectRoot, file);
4194
- const content = fileExists(path) ? (0, import_node_fs12.readFileSync)(path, "utf8") : "";
4551
+ const path = (0, import_node_path17.join)(projectRoot, file);
4552
+ const content = fileExists(path) ? (0, import_node_fs13.readFileSync)(path, "utf8") : "";
4195
4553
  const line = content.split("\n").find((candidate) => candidate.trim() === anchor);
4196
4554
  if (line === void 0) {
4197
4555
  throw new Error(`${file} has no "${anchor}" line to map the vscode module after; map 'vscode' to ${VSCODE_STUB_PATH} by hand.`);
@@ -4211,11 +4569,11 @@ function ensureVscodeToolchain(workspaceRoot) {
4211
4569
  }
4212
4570
  }
4213
4571
  function defaultPublisher(workspaceRoot) {
4214
- const { name } = readJson((0, import_node_path16.join)(workspaceRoot, "package.json"));
4572
+ const { name } = readJson((0, import_node_path17.join)(workspaceRoot, "package.json"));
4215
4573
  return (name ?? "publisher").replace(/^@/, "").split("/", 1)[0];
4216
4574
  }
4217
4575
  function reshapeManifest(projectRoot, name, publisher, typesVersion) {
4218
- const manifestPath = (0, import_node_path16.join)(projectRoot, "package.json");
4576
+ const manifestPath = (0, import_node_path17.join)(projectRoot, "package.json");
4219
4577
  const manifest = readJson(manifestPath);
4220
4578
  const { nx = {}, ...rest } = manifest;
4221
4579
  const targets = { ...nx.targets };
@@ -4279,11 +4637,11 @@ function vscodeExtensionPublishTarget(name, sidecar) {
4279
4637
  };
4280
4638
  }
4281
4639
  function addDebugLaunch(workspaceRoot, name) {
4282
- const file = (0, import_node_fs12.readdirSync)(workspaceRoot).find((entry) => entry.endsWith(".code-workspace"));
4640
+ const file = (0, import_node_fs13.readdirSync)(workspaceRoot).find((entry) => entry.endsWith(".code-workspace"));
4283
4641
  if (file === void 0) {
4284
4642
  return;
4285
4643
  }
4286
- const path = (0, import_node_path16.join)(workspaceRoot, file);
4644
+ const path = (0, import_node_path17.join)(workspaceRoot, file);
4287
4645
  const workspace = readCodeWorkspace(path) ?? {};
4288
4646
  const folder = `\${workspaceFolder:${workspace.folders?.[0]?.name ?? file.replace(/\.code-workspace$/, "")}}`;
4289
4647
  const taskLabel = `${name}: build (development)`;
@@ -4316,39 +4674,39 @@ function addDebugLaunch(workspaceRoot, name) {
4316
4674
  );
4317
4675
  }
4318
4676
  function refreshVscodeExtensionScript(workspaceRoot) {
4319
- const apps = (0, import_node_path16.join)(workspaceRoot, "apps");
4677
+ const apps = (0, import_node_path17.join)(workspaceRoot, "apps");
4320
4678
  let entries;
4321
4679
  try {
4322
- entries = (0, import_node_fs12.readdirSync)(apps);
4680
+ entries = (0, import_node_fs13.readdirSync)(apps);
4323
4681
  } catch {
4324
4682
  return false;
4325
4683
  }
4326
4684
  const hasExtension = entries.some((entry) => {
4327
- const manifestPath = (0, import_node_path16.join)(apps, entry, "package.json");
4685
+ const manifestPath = (0, import_node_path17.join)(apps, entry, "package.json");
4328
4686
  if (!fileExists(manifestPath)) {
4329
4687
  return false;
4330
4688
  }
4331
4689
  const tags = readJson(manifestPath).nx?.tags ?? [];
4332
4690
  return tags.includes(VSCODE_EXTENSION_TAG);
4333
4691
  });
4334
- const path = (0, import_node_path16.join)(workspaceRoot, VSCODE_EXTENSION_SCRIPT_PATH);
4335
- if (!hasExtension || fileExists(path) && (0, import_node_fs12.readFileSync)(path, "utf8") === VSCODE_EXTENSION_SCRIPT) {
4692
+ const path = (0, import_node_path17.join)(workspaceRoot, VSCODE_EXTENSION_SCRIPT_PATH);
4693
+ if (!hasExtension || fileExists(path) && (0, import_node_fs13.readFileSync)(path, "utf8") === VSCODE_EXTENSION_SCRIPT) {
4336
4694
  return false;
4337
4695
  }
4338
4696
  writeFileEnsured(path, VSCODE_EXTENSION_SCRIPT);
4339
4697
  return true;
4340
4698
  }
4341
4699
  function pinVscodeExtensionProjectNames(workspaceRoot) {
4342
- const apps = (0, import_node_path16.join)(workspaceRoot, "apps");
4700
+ const apps = (0, import_node_path17.join)(workspaceRoot, "apps");
4343
4701
  let entries;
4344
4702
  try {
4345
- entries = (0, import_node_fs12.readdirSync)(apps);
4703
+ entries = (0, import_node_fs13.readdirSync)(apps);
4346
4704
  } catch {
4347
4705
  return [];
4348
4706
  }
4349
4707
  const updated = [];
4350
4708
  for (const entry of entries) {
4351
- const manifestPath = (0, import_node_path16.join)(apps, entry, "package.json");
4709
+ const manifestPath = (0, import_node_path17.join)(apps, entry, "package.json");
4352
4710
  if (!fileExists(manifestPath)) {
4353
4711
  continue;
4354
4712
  }
@@ -4368,23 +4726,23 @@ function refreshLockFile(workspaceRoot, name) {
4368
4726
  }
4369
4727
  function addVscodeExtension(workspaceRoot, name, stack, options = {}) {
4370
4728
  const { sidecar } = options;
4371
- if (sidecar !== void 0 && !fileExists((0, import_node_path16.join)(workspaceRoot, "apps", sidecar, "project.json"))) {
4729
+ if (sidecar !== void 0 && !fileExists((0, import_node_path17.join)(workspaceRoot, "apps", sidecar, "project.json"))) {
4372
4730
  throw new Error(`--sidecar ${sidecar}: no Go app at apps/${sidecar}. Add it first with \`mnci add go-app ${sidecar}\`.`);
4373
4731
  }
4374
4732
  runNodeApp(workspaceRoot, name, stack, "none");
4375
4733
  ensureVscodeToolchain(workspaceRoot);
4376
- const projectRoot = (0, import_node_path16.join)(workspaceRoot, "apps", name);
4377
- const typesVersion = readJson((0, import_node_path16.join)(workspaceRoot, "node_modules/@types/vscode/package.json")).version;
4734
+ const projectRoot = (0, import_node_path17.join)(workspaceRoot, "apps", name);
4735
+ const typesVersion = readJson((0, import_node_path17.join)(workspaceRoot, "node_modules/@types/vscode/package.json")).version;
4378
4736
  reshapeManifest(projectRoot, name, options.publisher ?? defaultPublisher(workspaceRoot), typesVersion);
4379
- addVscodeTypes((0, import_node_path16.join)(projectRoot, "tsconfig.app.json"));
4380
- addVscodeTypes((0, import_node_path16.join)(projectRoot, "tsconfig.spec.json"));
4381
- writeFileEnsured((0, import_node_path16.join)(projectRoot, "src/main.ts"), vscodeExtensionMain(name));
4382
- writeFileEnsured((0, import_node_path16.join)(projectRoot, "src/main.spec.ts"), vscodeExtensionMainSpec(name));
4383
- writeFileEnsured((0, import_node_path16.join)(projectRoot, VSCODE_STUB_PATH), VSCODE_STUB);
4737
+ addVscodeTypes((0, import_node_path17.join)(projectRoot, "tsconfig.app.json"));
4738
+ addVscodeTypes((0, import_node_path17.join)(projectRoot, "tsconfig.spec.json"));
4739
+ writeFileEnsured((0, import_node_path17.join)(projectRoot, "src/main.ts"), vscodeExtensionMain(name));
4740
+ writeFileEnsured((0, import_node_path17.join)(projectRoot, "src/main.spec.ts"), vscodeExtensionMainSpec(name));
4741
+ writeFileEnsured((0, import_node_path17.join)(projectRoot, VSCODE_STUB_PATH), VSCODE_STUB);
4384
4742
  mapVscodeToStub(projectRoot, stack.testRunner);
4385
- writeFileEnsured((0, import_node_path16.join)(projectRoot, ".vscodeignore"), VSCODE_IGNORE);
4386
- writeFileEnsured((0, import_node_path16.join)(workspaceRoot, VSCODE_EXTENSION_SCRIPT_PATH), VSCODE_EXTENSION_SCRIPT);
4387
- addNxTargets((0, import_node_path16.join)(projectRoot, "package.json"), {
4743
+ writeFileEnsured((0, import_node_path17.join)(projectRoot, ".vscodeignore"), VSCODE_IGNORE);
4744
+ writeFileEnsured((0, import_node_path17.join)(workspaceRoot, VSCODE_EXTENSION_SCRIPT_PATH), VSCODE_EXTENSION_SCRIPT);
4745
+ addNxTargets((0, import_node_path17.join)(projectRoot, "package.json"), {
4388
4746
  "package": vscodeExtensionPackageTarget(name, sidecar),
4389
4747
  "nx-release-publish": vscodeExtensionPublishTarget(name, sidecar)
4390
4748
  });
@@ -4395,11 +4753,11 @@ function addVscodeExtension(workspaceRoot, name, stack, options = {}) {
4395
4753
  }
4396
4754
 
4397
4755
  // src/dependency-management/sync-dependencies.use-case.ts
4398
- var import_node_path18 = require("path");
4756
+ var import_node_path19 = require("path");
4399
4757
 
4400
4758
  // src/dependency-management/manifest.repository.ts
4401
- var import_node_fs13 = require("fs");
4402
- var import_node_path17 = require("path");
4759
+ var import_node_fs14 = require("fs");
4760
+ var import_node_path18 = require("path");
4403
4761
  var ECOSYSTEMS = ["npm", "pip", "pub", "nuget", "go"];
4404
4762
  var ROOT_LABEL = "(root)";
4405
4763
  var MANIFEST_GLOBS = {
@@ -4432,23 +4790,23 @@ function projectOf(manifestRelativePath) {
4432
4790
  }
4433
4791
  function hasEcosystem(workspaceRoot, ecosystem) {
4434
4792
  if (ecosystem === "go") {
4435
- return fileExists((0, import_node_path17.join)(workspaceRoot, "go.mod"));
4793
+ return fileExists((0, import_node_path18.join)(workspaceRoot, "go.mod"));
4436
4794
  }
4437
4795
  if (ecosystem === "nuget") {
4438
- return (0, import_node_fs13.globSync)(MANIFEST_GLOBS.nuget, { cwd: workspaceRoot }).length > 0;
4796
+ return (0, import_node_fs14.globSync)(MANIFEST_GLOBS.nuget, { cwd: workspaceRoot }).length > 0;
4439
4797
  }
4440
4798
  const rootMarker = {
4441
4799
  npm: "package.json",
4442
4800
  pip: "requirements-dev.txt",
4443
4801
  pub: "pubspec.yaml"
4444
4802
  };
4445
- return fileExists((0, import_node_path17.join)(workspaceRoot, rootMarker[ecosystem])) || (0, import_node_fs13.globSync)(MANIFEST_GLOBS[ecosystem], { cwd: workspaceRoot }).length > 0;
4803
+ return fileExists((0, import_node_path18.join)(workspaceRoot, rootMarker[ecosystem])) || (0, import_node_fs14.globSync)(MANIFEST_GLOBS[ecosystem], { cwd: workspaceRoot }).length > 0;
4446
4804
  }
4447
4805
  function collectNpm(workspaceRoot) {
4448
4806
  const sites = [];
4449
- const relativePaths = ["package.json", ...(0, import_node_fs13.globSync)(MANIFEST_GLOBS.npm, { cwd: workspaceRoot })];
4807
+ const relativePaths = ["package.json", ...(0, import_node_fs14.globSync)(MANIFEST_GLOBS.npm, { cwd: workspaceRoot })];
4450
4808
  for (const relativePath of relativePaths) {
4451
- const manifestPath = (0, import_node_path17.join)(workspaceRoot, relativePath);
4809
+ const manifestPath = (0, import_node_path18.join)(workspaceRoot, relativePath);
4452
4810
  try {
4453
4811
  const manifest = readJson(manifestPath);
4454
4812
  sites.push(...npmManifestSites(manifest, relativePath, manifestPath));
@@ -4509,17 +4867,17 @@ function collectPip(workspaceRoot) {
4509
4867
  name: parsed.name,
4510
4868
  ecosystem: "pip",
4511
4869
  project: projectOf(relativePath),
4512
- manifestPath: (0, import_node_path17.join)(workspaceRoot, relativePath),
4870
+ manifestPath: (0, import_node_path18.join)(workspaceRoot, relativePath),
4513
4871
  section,
4514
4872
  spec: parsed.spec,
4515
4873
  rewritable: parsed.rewritable && parsed.spec !== ""
4516
4874
  });
4517
4875
  };
4518
- const pyprojectPaths = (0, import_node_fs13.globSync)(MANIFEST_GLOBS.pip, { cwd: workspaceRoot });
4876
+ const pyprojectPaths = (0, import_node_fs14.globSync)(MANIFEST_GLOBS.pip, { cwd: workspaceRoot });
4519
4877
  for (const relativePath of pyprojectPaths) {
4520
4878
  let content;
4521
4879
  try {
4522
- content = (0, import_node_fs13.readFileSync)((0, import_node_path17.join)(workspaceRoot, relativePath), "utf8");
4880
+ content = (0, import_node_fs14.readFileSync)((0, import_node_path18.join)(workspaceRoot, relativePath), "utf8");
4523
4881
  } catch {
4524
4882
  continue;
4525
4883
  }
@@ -4530,14 +4888,14 @@ function collectPip(workspaceRoot) {
4530
4888
  }
4531
4889
  const requirementsPaths = [
4532
4890
  "requirements-dev.txt",
4533
- ...(0, import_node_fs13.globSync)("apps/*/requirements.txt", { cwd: workspaceRoot })
4891
+ ...(0, import_node_fs14.globSync)("apps/*/requirements.txt", { cwd: workspaceRoot })
4534
4892
  ];
4535
4893
  for (const relativePath of requirementsPaths) {
4536
- if (!fileExists((0, import_node_path17.join)(workspaceRoot, relativePath))) {
4894
+ if (!fileExists((0, import_node_path18.join)(workspaceRoot, relativePath))) {
4537
4895
  continue;
4538
4896
  }
4539
4897
  const section = relativePath === "requirements-dev.txt" ? "devDep" : "dep";
4540
- const lines = (0, import_node_fs13.readFileSync)((0, import_node_path17.join)(workspaceRoot, relativePath), "utf8").split(/\r?\n/);
4898
+ const lines = (0, import_node_fs14.readFileSync)((0, import_node_path18.join)(workspaceRoot, relativePath), "utf8").split(/\r?\n/);
4541
4899
  for (const line of lines) {
4542
4900
  push(relativePath, section, line);
4543
4901
  }
@@ -4575,11 +4933,11 @@ function pyprojectDependencies(content) {
4575
4933
  }
4576
4934
  function collectPub(workspaceRoot) {
4577
4935
  const sites = [];
4578
- const pubspecPaths = (0, import_node_fs13.globSync)(MANIFEST_GLOBS.pub, { cwd: workspaceRoot });
4936
+ const pubspecPaths = (0, import_node_fs14.globSync)(MANIFEST_GLOBS.pub, { cwd: workspaceRoot });
4579
4937
  for (const relativePath of pubspecPaths) {
4580
4938
  let content;
4581
4939
  try {
4582
- content = (0, import_node_fs13.readFileSync)((0, import_node_path17.join)(workspaceRoot, relativePath), "utf8");
4940
+ content = (0, import_node_fs14.readFileSync)((0, import_node_path18.join)(workspaceRoot, relativePath), "utf8");
4583
4941
  } catch {
4584
4942
  continue;
4585
4943
  }
@@ -4589,7 +4947,7 @@ function collectPub(workspaceRoot) {
4589
4947
  name: entry.name,
4590
4948
  ecosystem: "pub",
4591
4949
  project: projectOf(relativePath),
4592
- manifestPath: (0, import_node_path17.join)(workspaceRoot, relativePath),
4950
+ manifestPath: (0, import_node_path18.join)(workspaceRoot, relativePath),
4593
4951
  section: block === "dependencies" ? "dep" : "devDep",
4594
4952
  spec: entry.spec,
4595
4953
  rewritable: entry.spec !== ""
@@ -4639,11 +4997,11 @@ function stripQuotes(value) {
4639
4997
  }
4640
4998
  function collectNuget(workspaceRoot) {
4641
4999
  const sites = [];
4642
- const csprojPaths = (0, import_node_fs13.globSync)(MANIFEST_GLOBS.nuget, { cwd: workspaceRoot });
5000
+ const csprojPaths = (0, import_node_fs14.globSync)(MANIFEST_GLOBS.nuget, { cwd: workspaceRoot });
4643
5001
  for (const relativePath of csprojPaths) {
4644
5002
  let content;
4645
5003
  try {
4646
- content = (0, import_node_fs13.readFileSync)((0, import_node_path17.join)(workspaceRoot, relativePath), "utf8");
5004
+ content = (0, import_node_fs14.readFileSync)((0, import_node_path18.join)(workspaceRoot, relativePath), "utf8");
4647
5005
  } catch {
4648
5006
  continue;
4649
5007
  }
@@ -4652,7 +5010,7 @@ function collectNuget(workspaceRoot) {
4652
5010
  name: entry.name,
4653
5011
  ecosystem: "nuget",
4654
5012
  project: projectOf(relativePath),
4655
- manifestPath: (0, import_node_path17.join)(workspaceRoot, relativePath),
5013
+ manifestPath: (0, import_node_path18.join)(workspaceRoot, relativePath),
4656
5014
  section: "dep",
4657
5015
  spec: entry.spec,
4658
5016
  // A plain SemVer string is rewritable; an MSBuild property reference
@@ -4677,13 +5035,13 @@ function csprojPackageReferences(content) {
4677
5035
  return entries;
4678
5036
  }
4679
5037
  function collectGo(workspaceRoot) {
4680
- const manifestPath = (0, import_node_path17.join)(workspaceRoot, "go.mod");
5038
+ const manifestPath = (0, import_node_path18.join)(workspaceRoot, "go.mod");
4681
5039
  if (!fileExists(manifestPath)) {
4682
5040
  return [];
4683
5041
  }
4684
5042
  let content;
4685
5043
  try {
4686
- content = (0, import_node_fs13.readFileSync)(manifestPath, "utf8");
5044
+ content = (0, import_node_fs14.readFileSync)(manifestPath, "utf8");
4687
5045
  } catch {
4688
5046
  return [];
4689
5047
  }
@@ -4740,7 +5098,7 @@ function rewriteSpec(site, spec) {
4740
5098
  writeFileEnsured(site.manifestPath, toJson(manifest));
4741
5099
  return true;
4742
5100
  }
4743
- const before = (0, import_node_fs13.readFileSync)(site.manifestPath, "utf8");
5101
+ const before = (0, import_node_fs14.readFileSync)(site.manifestPath, "utf8");
4744
5102
  const after = (() => {
4745
5103
  switch (site.ecosystem) {
4746
5104
  case "pip": {
@@ -4796,13 +5154,13 @@ function escapeForRegex(value) {
4796
5154
  function isWorkspaceProject(workspaceRoot, name) {
4797
5155
  const short = name.includes("/") ? name.split("/").at(-1) : name;
4798
5156
  return ["apps", "libs", "packages"].some(
4799
- (directory) => fileExists((0, import_node_path17.join)(workspaceRoot, directory, short ?? name, "package.json"))
5157
+ (directory) => fileExists((0, import_node_path18.join)(workspaceRoot, directory, short ?? name, "package.json"))
4800
5158
  );
4801
5159
  }
4802
5160
  function isAliasedInstall(workspaceRoot, name) {
4803
5161
  try {
4804
5162
  const installed = readJson(
4805
- (0, import_node_path17.join)(workspaceRoot, "node_modules", name, "package.json")
5163
+ (0, import_node_path18.join)(workspaceRoot, "node_modules", name, "package.json")
4806
5164
  );
4807
5165
  return installed.name !== void 0 && installed.name !== name;
4808
5166
  } catch {
@@ -4813,14 +5171,14 @@ function resolvedVersion(workspaceRoot, ecosystem, name) {
4813
5171
  if (ecosystem === "npm") {
4814
5172
  try {
4815
5173
  return readJson(
4816
- (0, import_node_path17.join)(workspaceRoot, "node_modules", name, "package.json")
5174
+ (0, import_node_path18.join)(workspaceRoot, "node_modules", name, "package.json")
4817
5175
  ).version;
4818
5176
  } catch {
4819
5177
  return void 0;
4820
5178
  }
4821
5179
  }
4822
5180
  if (ecosystem === "pub") {
4823
- const lockPath = (0, import_node_path17.join)(workspaceRoot, "pubspec.lock");
5181
+ const lockPath = (0, import_node_path18.join)(workspaceRoot, "pubspec.lock");
4824
5182
  if (!fileExists(lockPath)) {
4825
5183
  return void 0;
4826
5184
  }
@@ -4828,7 +5186,7 @@ function resolvedVersion(workspaceRoot, ecosystem, name) {
4828
5186
  const match = new RegExp(
4829
5187
  String.raw`^\s{2}${escapeForRegex(name)}:[^]*?^\s+version:\s*["']?([^"'\s]+)`,
4830
5188
  "m"
4831
- ).exec((0, import_node_fs13.readFileSync)(lockPath, "utf8"));
5189
+ ).exec((0, import_node_fs14.readFileSync)(lockPath, "utf8"));
4832
5190
  return match?.[1];
4833
5191
  } catch {
4834
5192
  return void 0;
@@ -5020,7 +5378,7 @@ function describe(finding) {
5020
5378
  return `${finding.name} \u2192 ${finding.target} (${finding.reason}); disagreeing: ${sites}`;
5021
5379
  }
5022
5380
  function runSync(workspaceRoot, options) {
5023
- if (!fileExists((0, import_node_path18.join)(workspaceRoot, "nx.json"))) {
5381
+ if (!fileExists((0, import_node_path19.join)(workspaceRoot, "nx.json"))) {
5024
5382
  throw new Error(
5025
5383
  `No nx.json found in ${workspaceRoot} \u2014 run 'mnci sync' from the workspace root.`
5026
5384
  );
@@ -5070,7 +5428,7 @@ function runSync(workspaceRoot, options) {
5070
5428
  }
5071
5429
 
5072
5430
  // src/dependency-management/update-dependencies.use-case.ts
5073
- var import_node_path19 = require("path");
5431
+ var import_node_path20 = require("path");
5074
5432
  var import_prompts2 = require("@inquirer/prompts");
5075
5433
 
5076
5434
  // src/dependency-management/registry.client.ts
@@ -5353,7 +5711,7 @@ function reinstall(workspaceRoot, ecosystems) {
5353
5711
  function hasPythonInstallScript(workspaceRoot) {
5354
5712
  try {
5355
5713
  const manifest = readJson(
5356
- (0, import_node_path19.join)(workspaceRoot, "package.json")
5714
+ (0, import_node_path20.join)(workspaceRoot, "package.json")
5357
5715
  );
5358
5716
  return manifest.scripts?.["python:install"] !== void 0;
5359
5717
  } catch {
@@ -5369,7 +5727,7 @@ function applyGoUpdates(workspaceRoot, entries) {
5369
5727
  }
5370
5728
  }
5371
5729
  async function runUp(workspaceRoot, options) {
5372
- if (!fileExists((0, import_node_path19.join)(workspaceRoot, "nx.json"))) {
5730
+ if (!fileExists((0, import_node_path20.join)(workspaceRoot, "nx.json"))) {
5373
5731
  throw new Error(`No nx.json found in ${workspaceRoot} \u2014 run 'mnci up' from the workspace root.`);
5374
5732
  }
5375
5733
  const ecosystems = resolveEcosystems(options.ecosystem);
@@ -5445,7 +5803,7 @@ var PROJECT_KINDS = [
5445
5803
  ];
5446
5804
  async function runAdd(kind, name, options) {
5447
5805
  const workspaceRoot = process.cwd();
5448
- if (!fileExists((0, import_node_path20.join)(workspaceRoot, "nx.json"))) {
5806
+ if (!fileExists((0, import_node_path21.join)(workspaceRoot, "nx.json"))) {
5449
5807
  throw new Error("No nx.json found here. Run `add` from the workspace root.");
5450
5808
  }
5451
5809
  const stack = readWorkspaceStack(workspaceRoot);
@@ -5454,8 +5812,10 @@ async function runAdd(kind, name, options) {
5454
5812
  message: "What kind of project?",
5455
5813
  choices: PROJECT_KINDS.map((value) => ({ name: value, value }))
5456
5814
  });
5457
- if (resolvedKind !== "go-app" && options.release === true) {
5458
- throw new Error(`--release applies to go-app only, not ${resolvedKind}.`);
5815
+ for (const [flag, requested] of [["--release", options.release], ["--cgo", options.cgo]]) {
5816
+ if (resolvedKind !== "go-app" && requested === true) {
5817
+ throw new Error(`${flag} applies to go-app only, not ${resolvedKind}.`);
5818
+ }
5459
5819
  }
5460
5820
  const resolvedName = name ?? await promptText("Project name");
5461
5821
  assertValidProjectName(resolvedName, "Project name");
@@ -5499,8 +5859,8 @@ async function runAdd(kind, name, options) {
5499
5859
  ],
5500
5860
  workspaceRoot
5501
5861
  );
5502
- markPrivate((0, import_node_path20.join)(workspaceRoot, "libs", resolvedName, "package.json"));
5503
- renameScaffoldPlaceholder((0, import_node_path20.join)(workspaceRoot, "libs", resolvedName), resolvedName);
5862
+ markPrivate((0, import_node_path21.join)(workspaceRoot, "libs", resolvedName, "package.json"));
5863
+ renameScaffoldPlaceholder((0, import_node_path21.join)(workspaceRoot, "libs", resolvedName), resolvedName);
5504
5864
  removeGeneratedEslintConfig(workspaceRoot, `libs/${resolvedName}`);
5505
5865
  registerProjectCommands(workspaceRoot, resolvedName, { build: true });
5506
5866
  break;
@@ -5522,7 +5882,7 @@ async function runAdd(kind, name, options) {
5522
5882
  break;
5523
5883
  }
5524
5884
  case "go-app": {
5525
- addGoApp(workspaceRoot, resolvedName, { release: options.release });
5885
+ addGoApp(workspaceRoot, resolvedName, { release: options.release, cgo: options.cgo });
5526
5886
  break;
5527
5887
  }
5528
5888
  case "go-function-app": {
@@ -5592,7 +5952,7 @@ async function runAdd(kind, name, options) {
5592
5952
  }
5593
5953
  function readWorkspaceStack(workspaceRoot) {
5594
5954
  const nxJson = readJson(
5595
- (0, import_node_path20.join)(workspaceRoot, "nx.json")
5955
+ (0, import_node_path21.join)(workspaceRoot, "nx.json")
5596
5956
  );
5597
5957
  const stack = nxJson.mnci?.stack;
5598
5958
  return {
@@ -5601,15 +5961,16 @@ function readWorkspaceStack(workspaceRoot) {
5601
5961
  }
5602
5962
 
5603
5963
  // src/workspace-diagnostics/check-invariants.use-case.ts
5604
- var import_node_fs14 = require("fs");
5605
- var import_node_path21 = require("path");
5964
+ var import_node_child_process = require("child_process");
5965
+ var import_node_fs15 = require("fs");
5966
+ var import_node_path22 = require("path");
5606
5967
  var SUPPORTED_ESLINT_MAJOR = ESLINT_VERSION.replace(/^\D*/, "").split(".", 1)[0];
5607
5968
  function toPosix2(path) {
5608
5969
  return path.replaceAll("\\", "/");
5609
5970
  }
5610
5971
  function checkEslintConfigs(workspaceRoot) {
5611
- const rootConfigs = (0, import_node_fs14.globSync)("eslint.config.{js,mjs,cjs,ts,mts,cts}", { cwd: workspaceRoot });
5612
- const projectConfigs = (0, import_node_fs14.globSync)("{apps,libs,packages}/*/eslint.config.{js,mjs,cjs,ts,mts,cts}", {
5972
+ const rootConfigs = (0, import_node_fs15.globSync)("eslint.config.{js,mjs,cjs,ts,mts,cts}", { cwd: workspaceRoot });
5973
+ const projectConfigs = (0, import_node_fs15.globSync)("{apps,libs,packages}/*/eslint.config.{js,mjs,cjs,ts,mts,cts}", {
5613
5974
  cwd: workspaceRoot
5614
5975
  }).map((config) => toPosix2(config));
5615
5976
  return [
@@ -5629,10 +5990,10 @@ function checkEslintConfigs(workspaceRoot) {
5629
5990
  ];
5630
5991
  }
5631
5992
  function checkEslintEntryPointReachesTheRules(workspaceRoot) {
5632
- const rules = (0, import_node_path21.join)(workspaceRoot, ESLINT_MNCI_FILENAME);
5633
- if (!(0, import_node_fs14.existsSync)(rules)) return [];
5634
- const entryPoint = (0, import_node_path21.join)(workspaceRoot, ESLINT_USER_FILENAME);
5635
- const source = (0, import_node_fs14.existsSync)(entryPoint) ? (0, import_node_fs14.readFileSync)(entryPoint, "utf8") : "";
5993
+ const rules = (0, import_node_path22.join)(workspaceRoot, ESLINT_MNCI_FILENAME);
5994
+ if (!(0, import_node_fs15.existsSync)(rules)) return [];
5995
+ const entryPoint = (0, import_node_path22.join)(workspaceRoot, ESLINT_USER_FILENAME);
5996
+ const source = (0, import_node_fs15.existsSync)(entryPoint) ? (0, import_node_fs15.readFileSync)(entryPoint, "utf8") : "";
5636
5997
  return [
5637
5998
  {
5638
5999
  check: `${ESLINT_USER_FILENAME} imports the mnci rules`,
@@ -5645,7 +6006,7 @@ function checkEslintEntryPointReachesTheRules(workspaceRoot) {
5645
6006
  function declaredDevDependencies(workspaceRoot) {
5646
6007
  try {
5647
6008
  const manifest = readJson(
5648
- (0, import_node_path21.join)(workspaceRoot, "package.json")
6009
+ (0, import_node_path22.join)(workspaceRoot, "package.json")
5649
6010
  );
5650
6011
  return manifest.devDependencies ?? {};
5651
6012
  } catch {
@@ -5653,7 +6014,7 @@ function declaredDevDependencies(workspaceRoot) {
5653
6014
  }
5654
6015
  }
5655
6016
  function checkNoRetiredFormatter(workspaceRoot) {
5656
- const files = RETIRED_FORMATTER_FILES.filter((file) => fileExists((0, import_node_path21.join)(workspaceRoot, file)));
6017
+ const files = RETIRED_FORMATTER_FILES.filter((file) => fileExists((0, import_node_path22.join)(workspaceRoot, file)));
5657
6018
  const declared = ["prettier", "eslint-config-prettier", "oxlint", "oxfmt", "@mnci/oxlint-config"].filter((name) => declaredDevDependencies(workspaceRoot)[name] !== void 0);
5658
6019
  const stale = [...files, ...declared];
5659
6020
  if (stale.length === 0) {
@@ -5679,7 +6040,7 @@ function checkEslintPlugin(nxJson) {
5679
6040
  };
5680
6041
  }
5681
6042
  function checkResolvedEslint(workspaceRoot) {
5682
- const manifestPath = (0, import_node_path21.join)(workspaceRoot, "node_modules/eslint/package.json");
6043
+ const manifestPath = (0, import_node_path22.join)(workspaceRoot, "node_modules/eslint/package.json");
5683
6044
  if (!fileExists(manifestPath)) {
5684
6045
  return void 0;
5685
6046
  }
@@ -5697,11 +6058,11 @@ function checkResolvedEslint(workspaceRoot) {
5697
6058
  }
5698
6059
  }
5699
6060
  function checkNpmrc(workspaceRoot, registry, scope) {
5700
- const npmrcPath = (0, import_node_path21.join)(workspaceRoot, ".npmrc");
6061
+ const npmrcPath = (0, import_node_path22.join)(workspaceRoot, ".npmrc");
5701
6062
  if (!registry || !fileExists(npmrcPath)) {
5702
6063
  return void 0;
5703
6064
  }
5704
- const npmrc = (0, import_node_fs14.readFileSync)(npmrcPath, "utf8");
6065
+ const npmrc = (0, import_node_fs15.readFileSync)(npmrcPath, "utf8");
5705
6066
  if (registry.kind === "npm") {
5706
6067
  return {
5707
6068
  check: ".npmrc authenticates the public registry",
@@ -5718,11 +6079,11 @@ function checkNpmrc(workspaceRoot, registry, scope) {
5718
6079
  };
5719
6080
  }
5720
6081
  function checkNpmrcCredentialResolves(workspaceRoot, environment = process.env) {
5721
- const npmrcPath = (0, import_node_path21.join)(workspaceRoot, ".npmrc");
6082
+ const npmrcPath = (0, import_node_path22.join)(workspaceRoot, ".npmrc");
5722
6083
  if (!fileExists(npmrcPath)) {
5723
6084
  return void 0;
5724
6085
  }
5725
- const npmrc = (0, import_node_fs14.readFileSync)(npmrcPath, "utf8");
6086
+ const npmrc = (0, import_node_fs15.readFileSync)(npmrcPath, "utf8");
5726
6087
  const credentials = npmrc.split("\n").filter((line) => !line.trimStart().startsWith(";") && !line.trimStart().startsWith("#")).filter((line) => /(?:_authToken|_password|_auth)\s*=/u.test(line));
5727
6088
  const referenced = [
5728
6089
  ...new Set(
@@ -5746,13 +6107,13 @@ function checkNpmrcCredentialResolves(workspaceRoot, environment = process.env)
5746
6107
  };
5747
6108
  }
5748
6109
  function checkNpmAuthMatchesPipeline(workspaceRoot, registry) {
5749
- const npmrcPath = (0, import_node_path21.join)(workspaceRoot, ".npmrc");
5750
- const pipelinePath = (0, import_node_path21.join)(workspaceRoot, "azure-pipelines.yml");
6110
+ const npmrcPath = (0, import_node_path22.join)(workspaceRoot, ".npmrc");
6111
+ const pipelinePath = (0, import_node_path22.join)(workspaceRoot, "azure-pipelines.yml");
5751
6112
  if (registry?.kind !== "azure-artifacts" || !fileExists(npmrcPath) || !fileExists(pipelinePath)) {
5752
6113
  return void 0;
5753
6114
  }
5754
- const holdsCredentials = (0, import_node_fs14.readFileSync)(npmrcPath, "utf8").split("\n").filter((line) => !line.trimStart().startsWith(";") && !line.trimStart().startsWith("#")).some((line) => /(?:_authToken|_password|_auth)\s*=/u.test(line));
5755
- const runsTask = (0, import_node_fs14.readFileSync)(pipelinePath, "utf8").includes("npmAuthenticate@0");
6115
+ const holdsCredentials = (0, import_node_fs15.readFileSync)(npmrcPath, "utf8").split("\n").filter((line) => !line.trimStart().startsWith(";") && !line.trimStart().startsWith("#")).some((line) => /(?:_authToken|_password|_auth)\s*=/u.test(line));
6116
+ const runsTask = (0, import_node_fs15.readFileSync)(pipelinePath, "utf8").includes("npmAuthenticate@0");
5756
6117
  if (!holdsCredentials && !runsTask) {
5757
6118
  return {
5758
6119
  check: "npm auth: .npmrc and azure-pipelines.yml agree",
@@ -5797,13 +6158,13 @@ function npmjsCredentialShape(credentials, environment) {
5797
6158
  }
5798
6159
  function checkVersionActions(workspaceRoot) {
5799
6160
  const candidates = [
5800
- ...(0, import_node_fs14.globSync)("packages/*/pubspec.yaml", { cwd: workspaceRoot }),
5801
- ...(0, import_node_fs14.globSync)("packages/*/*.csproj", { cwd: workspaceRoot }),
5802
- ...(0, import_node_fs14.globSync)("python-packages/*/pyproject.toml", { cwd: workspaceRoot })
6161
+ ...(0, import_node_fs15.globSync)("packages/*/pubspec.yaml", { cwd: workspaceRoot }),
6162
+ ...(0, import_node_fs15.globSync)("packages/*/*.csproj", { cwd: workspaceRoot }),
6163
+ ...(0, import_node_fs15.globSync)("python-packages/*/pyproject.toml", { cwd: workspaceRoot })
5803
6164
  ].map((manifest) => toPosix2(manifest));
5804
6165
  return candidates.flatMap((manifest) => {
5805
6166
  const projectRoot = manifest.slice(0, manifest.lastIndexOf("/"));
5806
- const projectJsonPath = (0, import_node_path21.join)(workspaceRoot, projectRoot, "project.json");
6167
+ const projectJsonPath = (0, import_node_path22.join)(workspaceRoot, projectRoot, "project.json");
5807
6168
  let hasOverride = false;
5808
6169
  try {
5809
6170
  const projectJson = readJson(projectJsonPath);
@@ -5832,7 +6193,7 @@ function declaredTargets(workspaceRoot, projectRoot) {
5832
6193
  ]) {
5833
6194
  try {
5834
6195
  const targets = extract(
5835
- readJson((0, import_node_path21.join)(workspaceRoot, projectRoot, file))
6196
+ readJson((0, import_node_path22.join)(workspaceRoot, projectRoot, file))
5836
6197
  );
5837
6198
  if (targets && typeof targets === "object") {
5838
6199
  sources.push({
@@ -5848,8 +6209,8 @@ function declaredTargets(workspaceRoot, projectRoot) {
5848
6209
  function checkTargetFilesExist(workspaceRoot) {
5849
6210
  const projectRoots = new Set(
5850
6211
  [
5851
- ...(0, import_node_fs14.globSync)("{apps,libs,packages}/*/project.json", { cwd: workspaceRoot }),
5852
- ...(0, import_node_fs14.globSync)("{apps,libs,packages}/*/package.json", { cwd: workspaceRoot })
6212
+ ...(0, import_node_fs15.globSync)("{apps,libs,packages}/*/project.json", { cwd: workspaceRoot }),
6213
+ ...(0, import_node_fs15.globSync)("{apps,libs,packages}/*/package.json", { cwd: workspaceRoot })
5853
6214
  ].map((manifest) => toPosix2(manifest).split("/").slice(0, 2).join("/"))
5854
6215
  );
5855
6216
  return [...projectRoots].flatMap(
@@ -5864,7 +6225,7 @@ function checkOneTargetsFiles(workspaceRoot, source, targetName, target) {
5864
6225
  return TARGET_FILE_OPTIONS.flatMap((option) => {
5865
6226
  const value = target?.options?.[option];
5866
6227
  const checkable = typeof value === "string" && !value.includes("{");
5867
- if (!checkable || fileExists((0, import_node_path21.join)(workspaceRoot, value))) {
6228
+ if (!checkable || fileExists((0, import_node_path22.join)(workspaceRoot, value))) {
5868
6229
  return [];
5869
6230
  }
5870
6231
  return [
@@ -5885,8 +6246,45 @@ function checkSync(workspaceRoot) {
5885
6246
  remedy: "run `npx nx sync` and commit the result"
5886
6247
  };
5887
6248
  }
6249
+ function hasCCompiler() {
6250
+ const candidates = [process.env.CC?.split(" ", 1)[0], "gcc", "clang", "cc"];
6251
+ return candidates.some((command) => command !== void 0 && command !== "" && (0, import_node_child_process.spawnSync)(command, ["--version"], { stdio: "ignore" }).status === 0);
6252
+ }
6253
+ function checkGoPluginRegistered(workspaceRoot) {
6254
+ if (!hasGoProject(workspaceRoot)) {
6255
+ return void 0;
6256
+ }
6257
+ return {
6258
+ check: `${NX_GO_PLUGIN} is registered in nx.json, so Nx knows which Go project imports which`,
6259
+ ok: isNxGoPluginRegistered(workspaceRoot),
6260
+ detail: `${NX_GO_PLUGIN} is not in nx.json plugins: the project graph has no Go edge, so \`nx affected\` skips an app that imports a changed library`,
6261
+ remedy: "run `mnci upgrade`"
6262
+ };
6263
+ }
6264
+ function checkNativeApps(workspaceRoot) {
6265
+ if (!hasNativeGoApp(workspaceRoot)) {
6266
+ return [];
6267
+ }
6268
+ const pipelines = [
6269
+ { file: ".github/workflows/ci.yml", marker: "native (${{ matrix.os }})" },
6270
+ { file: "azure-pipelines.yml", marker: "- job: native" }
6271
+ ];
6272
+ const findings = pipelines.filter(({ file }) => fileExists((0, import_node_path22.join)(workspaceRoot, file))).map(({ file, marker }) => ({
6273
+ check: `${file} builds the native apps on every OS`,
6274
+ ok: (0, import_node_fs15.readFileSync)((0, import_node_path22.join)(workspaceRoot, file), "utf8").includes(marker),
6275
+ detail: `${file} has no native job: CI would verify a cgo app on the one agent that cannot build it`,
6276
+ remedy: "run `mnci upgrade`"
6277
+ }));
6278
+ findings.push({
6279
+ check: "a C compiler is installed (cgo needs one)",
6280
+ ok: hasCCompiler(),
6281
+ detail: "none of CC, gcc, clang or cc answered --version, so nx run <app>:build-native cannot build here",
6282
+ remedy: "install one: Xcode command line tools on macOS, build-essential on Linux, MinGW-w64 (gcc) on Windows"
6283
+ });
6284
+ return findings;
6285
+ }
5888
6286
  function checkNoRootRuntimeDependencies(workspaceRoot) {
5889
- const manifestPath = (0, import_node_path21.join)(workspaceRoot, "package.json");
6287
+ const manifestPath = (0, import_node_path22.join)(workspaceRoot, "package.json");
5890
6288
  if (!fileExists(manifestPath)) {
5891
6289
  return void 0;
5892
6290
  }
@@ -5906,14 +6304,14 @@ function checkNoRootRuntimeDependencies(workspaceRoot) {
5906
6304
  };
5907
6305
  }
5908
6306
  function checkRollupSourceMaps(workspaceRoot) {
5909
- const configs = (0, import_node_fs14.globSync)(["packages/*/rollup.config.cjs", "libs/*/rollup.config.cjs"], {
6307
+ const configs = (0, import_node_fs15.globSync)(["packages/*/rollup.config.cjs", "libs/*/rollup.config.cjs"], {
5910
6308
  cwd: workspaceRoot
5911
6309
  }).map((config) => toPosix2(config));
5912
6310
  return configs.flatMap((relativePath) => {
5913
- const configPath = (0, import_node_path21.join)(workspaceRoot, relativePath);
6311
+ const configPath = (0, import_node_path22.join)(workspaceRoot, relativePath);
5914
6312
  let config;
5915
6313
  try {
5916
- config = (0, import_node_fs14.readFileSync)(configPath, "utf8");
6314
+ config = (0, import_node_fs15.readFileSync)(configPath, "utf8");
5917
6315
  } catch {
5918
6316
  return [];
5919
6317
  }
@@ -5928,11 +6326,11 @@ function checkRollupSourceMaps(workspaceRoot) {
5928
6326
  });
5929
6327
  }
5930
6328
  function checkDeclarationSpecifiers(workspaceRoot) {
5931
- const configs = (0, import_node_fs14.globSync)(["packages/*/rollup.config.cjs", "libs/*/rollup.config.cjs"], {
6329
+ const configs = (0, import_node_fs15.globSync)(["packages/*/rollup.config.cjs", "libs/*/rollup.config.cjs"], {
5932
6330
  cwd: workspaceRoot
5933
6331
  }).map((config) => toPosix2(config));
5934
6332
  return configs.flatMap((relativePath) => {
5935
- const configPath = (0, import_node_path21.join)(workspaceRoot, relativePath);
6333
+ const configPath = (0, import_node_path22.join)(workspaceRoot, relativePath);
5936
6334
  if (!fileExists(configPath)) {
5937
6335
  return [];
5938
6336
  }
@@ -5966,7 +6364,7 @@ function checkDeclarationSpecifiers(workspaceRoot) {
5966
6364
  });
5967
6365
  }
5968
6366
  function collectFindings(workspaceRoot) {
5969
- const nxJsonPath = (0, import_node_path21.join)(workspaceRoot, "nx.json");
6367
+ const nxJsonPath = (0, import_node_path22.join)(workspaceRoot, "nx.json");
5970
6368
  if (!fileExists(nxJsonPath)) {
5971
6369
  throw new Error(
5972
6370
  `No nx.json found in ${workspaceRoot} \u2014 run 'mnci doctor' from the workspace root.`
@@ -5986,7 +6384,9 @@ function collectFindings(workspaceRoot) {
5986
6384
  ...checkDeclarationSpecifiers(workspaceRoot),
5987
6385
  ...checkVersionActions(workspaceRoot),
5988
6386
  ...checkTargetFilesExist(workspaceRoot),
5989
- checkSync(workspaceRoot)
6387
+ checkSync(workspaceRoot),
6388
+ checkGoPluginRegistered(workspaceRoot),
6389
+ ...checkNativeApps(workspaceRoot)
5990
6390
  ].filter((finding) => finding !== void 0);
5991
6391
  }
5992
6392
  function runDoctor(workspaceRoot) {
@@ -6011,8 +6411,8 @@ function runDoctor(workspaceRoot) {
6011
6411
  }
6012
6412
 
6013
6413
  // src/workspace-creation/adopt-directory.use-case.ts
6014
- var import_node_fs15 = require("fs");
6015
- var import_node_path22 = require("path");
6414
+ var import_node_fs16 = require("fs");
6415
+ var import_node_path23 = require("path");
6016
6416
  var NEVER_COPIED = /* @__PURE__ */ new Set([".git", "node_modules"]);
6017
6417
  var AGENT_AND_CI_ENTRIES = [
6018
6418
  "AGENTS.md",
@@ -6043,13 +6443,13 @@ var PREFLIGHT_BLOCKERS = [
6043
6443
  "packages"
6044
6444
  ];
6045
6445
  function assertAdoptableDirectory(target) {
6046
- if (!(0, import_node_fs15.existsSync)(target)) {
6446
+ if (!(0, import_node_fs16.existsSync)(target)) {
6047
6447
  throw new Error(`--into '${target}' does not exist. Create or clone it first.`);
6048
6448
  }
6049
- if (!(0, import_node_fs15.statSync)(target).isDirectory()) {
6449
+ if (!(0, import_node_fs16.statSync)(target).isDirectory()) {
6050
6450
  throw new Error(`--into '${target}' is not a directory.`);
6051
6451
  }
6052
- const blockers = PREFLIGHT_BLOCKERS.filter((entry) => (0, import_node_fs15.existsSync)((0, import_node_path22.join)(target, entry)));
6452
+ const blockers = PREFLIGHT_BLOCKERS.filter((entry) => (0, import_node_fs16.existsSync)((0, import_node_path23.join)(target, entry)));
6053
6453
  if (blockers.length > 0) {
6054
6454
  throw new Error(
6055
6455
  `--into '${target}' already holds ${blockers.join(", ")}, so it is a project already. Use \`mnci upgrade\` to re-apply the overlay to an existing workspace, or point --into at an empty checkout.`
@@ -6057,15 +6457,15 @@ function assertAdoptableDirectory(target) {
6057
6457
  }
6058
6458
  }
6059
6459
  function mergeGitignore(generatedFile, targetFile) {
6060
- const existing = (0, import_node_fs15.readFileSync)(targetFile, "utf8");
6460
+ const existing = (0, import_node_fs16.readFileSync)(targetFile, "utf8");
6061
6461
  const present = new Set(existing.split("\n").map((line) => line.trim()));
6062
- const additions = (0, import_node_fs15.readFileSync)(generatedFile, "utf8").split("\n").map((line) => line.trimEnd()).filter((line) => {
6462
+ const additions = (0, import_node_fs16.readFileSync)(generatedFile, "utf8").split("\n").map((line) => line.trimEnd()).filter((line) => {
6063
6463
  const trimmed = line.trim();
6064
6464
  return trimmed !== "" && !trimmed.startsWith("#") && !present.has(trimmed);
6065
6465
  });
6066
6466
  if (additions.length === 0) return false;
6067
6467
  const separator = existing.endsWith("\n") ? "" : "\n";
6068
- (0, import_node_fs15.writeFileSync)(
6468
+ (0, import_node_fs16.writeFileSync)(
6069
6469
  targetFile,
6070
6470
  `${existing}${separator}
6071
6471
  # Added by mnci (Nx workspace)
@@ -6075,9 +6475,9 @@ ${additions.join("\n")}
6075
6475
  return true;
6076
6476
  }
6077
6477
  function adoptGeneratedWorkspace(generatedRoot, target) {
6078
- const entries = (0, import_node_fs15.readdirSync)(generatedRoot).filter((entry) => !NEVER_COPIED.has(entry));
6478
+ const entries = (0, import_node_fs16.readdirSync)(generatedRoot).filter((entry) => !NEVER_COPIED.has(entry));
6079
6479
  const collisions = entries.filter(
6080
- (entry) => (0, import_node_fs15.existsSync)((0, import_node_path22.join)(target, entry)) && !EXISTING_WINS.has(entry) && entry !== ".gitignore"
6480
+ (entry) => (0, import_node_fs16.existsSync)((0, import_node_path23.join)(target, entry)) && !EXISTING_WINS.has(entry) && entry !== ".gitignore"
6081
6481
  );
6082
6482
  if (collisions.length > 0) {
6083
6483
  throw new Error(
@@ -6086,28 +6486,28 @@ function adoptGeneratedWorkspace(generatedRoot, target) {
6086
6486
  }
6087
6487
  const result = { copied: [], kept: [], mergedGitignore: false };
6088
6488
  for (const entry of entries) {
6089
- const from = (0, import_node_path22.join)(generatedRoot, entry);
6090
- const to = (0, import_node_path22.join)(target, entry);
6091
- if (entry === ".gitignore" && (0, import_node_fs15.existsSync)(to)) {
6489
+ const from = (0, import_node_path23.join)(generatedRoot, entry);
6490
+ const to = (0, import_node_path23.join)(target, entry);
6491
+ if (entry === ".gitignore" && (0, import_node_fs16.existsSync)(to)) {
6092
6492
  result.mergedGitignore = mergeGitignore(from, to);
6093
6493
  result.kept.push(entry);
6094
6494
  continue;
6095
6495
  }
6096
- if ((0, import_node_fs15.existsSync)(to)) {
6496
+ if ((0, import_node_fs16.existsSync)(to)) {
6097
6497
  result.kept.push(entry);
6098
6498
  continue;
6099
6499
  }
6100
- (0, import_node_fs15.cpSync)(from, to, { recursive: true });
6500
+ (0, import_node_fs16.cpSync)(from, to, { recursive: true });
6101
6501
  result.copied.push(entry);
6102
6502
  }
6103
- (0, import_node_fs15.rmSync)(generatedRoot, { recursive: true, force: true });
6503
+ (0, import_node_fs16.rmSync)(generatedRoot, { recursive: true, force: true });
6104
6504
  return result;
6105
6505
  }
6106
6506
 
6107
6507
  // src/workspace-creation/create-workspace.use-case.ts
6108
- var import_node_fs16 = require("fs");
6508
+ var import_node_fs17 = require("fs");
6109
6509
  var import_node_os = require("os");
6110
- var import_node_path23 = require("path");
6510
+ var import_node_path24 = require("path");
6111
6511
  function nxCloudProviderValue(ci) {
6112
6512
  return ci === "azure" ? "azure" : "github";
6113
6513
  }
@@ -6143,9 +6543,9 @@ async function resolveRegistry(options) {
6143
6543
  return await promptRegistry();
6144
6544
  }
6145
6545
  async function runNew(name, options) {
6146
- const adoptTarget = options.into === void 0 ? void 0 : (0, import_node_path23.resolve)(process.cwd(), options.into);
6546
+ const adoptTarget = options.into === void 0 ? void 0 : (0, import_node_path24.resolve)(process.cwd(), options.into);
6147
6547
  if (adoptTarget !== void 0) assertAdoptableDirectory(adoptTarget);
6148
- const workspaceName = name ?? (adoptTarget === void 0 ? await promptText("Workspace name") : (0, import_node_path23.basename)(adoptTarget));
6548
+ const workspaceName = name ?? (adoptTarget === void 0 ? await promptText("Workspace name") : (0, import_node_path24.basename)(adoptTarget));
6149
6549
  assertValidProjectName(workspaceName, "Workspace name");
6150
6550
  const scope = options.scope ?? (options.yes ? `@${workspaceName}` : await promptText("npm scope for publishable packages", `@${workspaceName}`));
6151
6551
  const registry = await resolveRegistry(options);
@@ -6158,8 +6558,8 @@ async function runNew(name, options) {
6158
6558
  const npmAuth = resolveNpmAuth(options.npmAuth, registry, ci);
6159
6559
  const stack = await resolveStack(options);
6160
6560
  const nxCloud = options.nxCloud ?? (options.yes ? false : await promptNxCloud());
6161
- const stagingParent = adoptTarget === void 0 ? process.cwd() : (0, import_node_fs16.mkdtempSync)((0, import_node_path23.join)((0, import_node_os.tmpdir)(), "mnci-new-"));
6162
- let workspaceRoot = (0, import_node_path23.join)(stagingParent, workspaceName);
6561
+ const stagingParent = adoptTarget === void 0 ? process.cwd() : (0, import_node_fs17.mkdtempSync)((0, import_node_path24.join)((0, import_node_os.tmpdir)(), "mnci-new-"));
6562
+ let workspaceRoot = (0, import_node_path24.join)(stagingParent, workspaceName);
6163
6563
  try {
6164
6564
  logger.step(`Creating Nx workspace '${workspaceName}' (preset: ts)`);
6165
6565
  runNpx(
@@ -6182,7 +6582,7 @@ async function runNew(name, options) {
6182
6582
  workspaceRoot = adoptTarget;
6183
6583
  }
6184
6584
  } finally {
6185
- if (adoptTarget !== void 0) (0, import_node_fs16.rmSync)(stagingParent, { recursive: true, force: true });
6585
+ if (adoptTarget !== void 0) (0, import_node_fs17.rmSync)(stagingParent, { recursive: true, force: true });
6186
6586
  }
6187
6587
  logger.step(
6188
6588
  "Applying MoNecromanCI overlay (VS Code workspace, release config, .npmrc, commitlint, pipeline, stack)"
@@ -6192,8 +6592,8 @@ async function runNew(name, options) {
6192
6592
  { workspaceName, scope, registry, agent, variableGroup, ci, stack, ...npmAuth && { npmAuth } },
6193
6593
  logger.detail
6194
6594
  );
6195
- (0, import_node_fs16.rmSync)((0, import_node_path23.join)(workspaceRoot, "node_modules"), { recursive: true, force: true });
6196
- (0, import_node_fs16.rmSync)((0, import_node_path23.join)(workspaceRoot, "package-lock.json"), { force: true });
6595
+ (0, import_node_fs17.rmSync)((0, import_node_path24.join)(workspaceRoot, "node_modules"), { recursive: true, force: true });
6596
+ (0, import_node_fs17.rmSync)((0, import_node_path24.join)(workspaceRoot, "package-lock.json"), { force: true });
6197
6597
  logger.step("Installing the toolchain (commitlint + husky + linting/formatting)");
6198
6598
  const installStatus = runShell(
6199
6599
  "npm",
@@ -6224,12 +6624,12 @@ async function runNew(name, options) {
6224
6624
  }
6225
6625
 
6226
6626
  // src/workspace-creation/interactive-wizard.use-case.ts
6227
- var import_node_path25 = require("path");
6627
+ var import_node_path26 = require("path");
6228
6628
  var import_prompts4 = require("@inquirer/prompts");
6229
6629
 
6230
6630
  // src/workspace-upgrade/upgrade-workspace.use-case.ts
6231
- var import_node_fs17 = require("fs");
6232
- var import_node_path24 = require("path");
6631
+ var import_node_fs18 = require("fs");
6632
+ var import_node_path25 = require("path");
6233
6633
  function resolveRegistry2(options, persisted) {
6234
6634
  if (options.registry === "azure-artifacts" || options.organization && options.artifactsFeed) {
6235
6635
  const persistedAzure = persisted?.kind === "azure-artifacts" ? persisted : void 0;
@@ -6258,7 +6658,7 @@ function resolveWorkspaceName(workspaceRoot, persisted) {
6258
6658
  return persisted.workspaceName;
6259
6659
  }
6260
6660
  try {
6261
- const existing = (0, import_node_fs17.readdirSync)(workspaceRoot).find(
6661
+ const existing = (0, import_node_fs18.readdirSync)(workspaceRoot).find(
6262
6662
  (file) => file.endsWith(".code-workspace") && file !== "undefined.code-workspace"
6263
6663
  );
6264
6664
  if (existing) {
@@ -6266,11 +6666,11 @@ function resolveWorkspaceName(workspaceRoot, persisted) {
6266
6666
  }
6267
6667
  } catch {
6268
6668
  }
6269
- return (0, import_node_path24.basename)(workspaceRoot);
6669
+ return (0, import_node_path25.basename)(workspaceRoot);
6270
6670
  }
6271
6671
  function detectNpmAuth(workspaceRoot) {
6272
6672
  try {
6273
- return (0, import_node_fs17.readFileSync)((0, import_node_path24.join)(workspaceRoot, "azure-pipelines.yml"), "utf8").includes("npmAuthenticate@0") ? "build-identity" : void 0;
6673
+ return (0, import_node_fs18.readFileSync)((0, import_node_path25.join)(workspaceRoot, "azure-pipelines.yml"), "utf8").includes("npmAuthenticate@0") ? "build-identity" : void 0;
6274
6674
  } catch {
6275
6675
  return void 0;
6276
6676
  }
@@ -6317,7 +6717,7 @@ function resolveOverlayOptions(workspaceRoot, options, persisted) {
6317
6717
  };
6318
6718
  }
6319
6719
  function runUpgrade(workspaceRoot, options) {
6320
- if (!fileExists((0, import_node_path24.join)(workspaceRoot, "nx.json"))) {
6720
+ if (!fileExists((0, import_node_path25.join)(workspaceRoot, "nx.json"))) {
6321
6721
  throw new Error(
6322
6722
  `No nx.json found in ${workspaceRoot} \u2014 this does not look like an Nx workspace. Run 'mnci upgrade' from the workspace root.`
6323
6723
  );
@@ -6362,6 +6762,10 @@ function runUpgrade(workspaceRoot, options) {
6362
6762
  logger.step("Updating the releasable Go app script");
6363
6763
  logger.detail(`updated ${GO_RELEASE_SCRIPT_PATH}`);
6364
6764
  }
6765
+ if (hasGoProject(workspaceRoot) && registerNxGoPlugin(workspaceRoot)) {
6766
+ logger.step("Registering the Go plugin in nx.json, so Nx can see which Go project imports which");
6767
+ logger.detail("updated nx.json");
6768
+ }
6365
6769
  const upgradedDtsPlugins = upgradeDeclarationSpecifierPlugins(workspaceRoot);
6366
6770
  if (upgradedDtsPlugins.length > 0) {
6367
6771
  logger.step("Upgrading declaration specifiers to resolve under nodenext");
@@ -6378,7 +6782,7 @@ function runUpgrade(workspaceRoot, options) {
6378
6782
 
6379
6783
  // src/workspace-creation/interactive-wizard.use-case.ts
6380
6784
  async function runInteractive() {
6381
- const inWorkspace = fileExists((0, import_node_path25.join)(process.cwd(), "nx.json"));
6785
+ const inWorkspace = fileExists((0, import_node_path26.join)(process.cwd(), "nx.json"));
6382
6786
  const choiceNew = { name: "Create a new monorepo", value: "new" };
6383
6787
  const choiceAdd = { name: "Add a project to this workspace", value: "add" };
6384
6788
  const choiceUpgrade = {
@@ -6399,8 +6803,8 @@ async function runInteractive() {
6399
6803
  }
6400
6804
 
6401
6805
  // src/cli-version/check-for-update.use-case.ts
6402
- var import_node_fs18 = require("fs");
6403
- var import_node_path26 = require("path");
6806
+ var import_node_fs19 = require("fs");
6807
+ var import_node_path27 = require("path");
6404
6808
  var import_cross_spawn2 = __toESM(require("cross-spawn"));
6405
6809
  var PACKAGE_NAME = "@mnci/cli";
6406
6810
  var REGISTRY_TIMEOUT_MS = 2e3;
@@ -6456,8 +6860,8 @@ function releaseTriple(version) {
6456
6860
  }
6457
6861
  function readCliVersion(packageDirectory) {
6458
6862
  try {
6459
- const manifestPath = (0, import_node_path26.join)(packageDirectory, "..", "package.json");
6460
- const manifest = JSON.parse((0, import_node_fs18.readFileSync)(manifestPath, "utf8"));
6863
+ const manifestPath = (0, import_node_path27.join)(packageDirectory, "..", "package.json");
6864
+ const manifest = JSON.parse((0, import_node_fs19.readFileSync)(manifestPath, "utf8"));
6461
6865
  return manifest.version ?? "0.0.0";
6462
6866
  } catch {
6463
6867
  return "0.0.0";
@@ -6496,6 +6900,11 @@ function buildProgram(cliVersion) {
6496
6900
  ).action(() => {
6497
6901
  runDoctor(process.cwd());
6498
6902
  });
6903
+ program.command("ci").addArgument(new import_commander.Argument("<phase>", "which phase of the pipeline to run").choices(CI_PHASES)).description(
6904
+ "Run a phase of the CI pipeline here, the same way CI runs it: `verify` is the sync check and then every project (or, in a pull request, the affected ones) through lint, typecheck, test and build. Exits non-zero when it fails"
6905
+ ).action((phase) => {
6906
+ process.exitCode = runCiPhase(phase, process.cwd());
6907
+ });
6499
6908
  program.command("sync").description(
6500
6909
  "Make every project agree: converge external dependency ranges declared at more than one version, then run 'nx sync' for TypeScript project references. Go is a no-op \u2014 one root go.mod means one version of every module"
6501
6910
  ).option("--check", "report drift and exit non-zero without writing anything").option("--ecosystem <name>", "restrict to one ecosystem: npm | pip | pub | go").action((options) => {
@@ -6521,6 +6930,9 @@ function buildProgram(cliVersion) {
6521
6930
  ).option(
6522
6931
  "--release",
6523
6932
  "go-app only: release the app. Versioned from its git tag, its six-platform zips attached to its GitHub Release"
6933
+ ).option(
6934
+ "--cgo",
6935
+ "go-app only: the app needs a C toolchain (a tray icon, a native GUI, a cgo driver), so CI builds it on a runner of each OS instead of cross-compiling"
6524
6936
  ).action(
6525
6937
  async (kind, name, options) => {
6526
6938
  await runAdd(kind, name, options);