@mnci/cli 4.1.5 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -10
- package/dist/cli.js +631 -171
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -38,8 +38,8 @@ module.exports = __toCommonJS(cli_exports);
|
|
|
38
38
|
var import_commander = require("commander");
|
|
39
39
|
|
|
40
40
|
// src/commands/add.ts
|
|
41
|
-
var
|
|
42
|
-
var
|
|
41
|
+
var import_node_path14 = require("path");
|
|
42
|
+
var import_prompts6 = require("@inquirer/prompts");
|
|
43
43
|
|
|
44
44
|
// src/nx.ts
|
|
45
45
|
var import_cross_spawn = __toESM(require("cross-spawn"));
|
|
@@ -291,13 +291,10 @@ function assertValidProjectName(name, label) {
|
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
-
// src/commands/add/
|
|
294
|
+
// src/commands/add/csharp.ts
|
|
295
|
+
var import_node_fs4 = require("fs");
|
|
295
296
|
var import_node_path4 = require("path");
|
|
296
297
|
|
|
297
|
-
// src/commands/add/shared.ts
|
|
298
|
-
var import_node_fs3 = require("fs");
|
|
299
|
-
var import_node_path3 = require("path");
|
|
300
|
-
|
|
301
298
|
// src/overlay.ts
|
|
302
299
|
var import_node_fs2 = require("fs");
|
|
303
300
|
var import_node_path2 = require("path");
|
|
@@ -436,7 +433,8 @@ function devcontainerJson(workspaceName) {
|
|
|
436
433
|
image: `mcr.microsoft.com/devcontainers/typescript-node:${NODE_VERSION}-bookworm`,
|
|
437
434
|
features: {
|
|
438
435
|
"ghcr.io/devcontainers/features/python:1": { version: "3.12" },
|
|
439
|
-
"ghcr.io/devcontainers/features/go:1": { version: "latest" }
|
|
436
|
+
"ghcr.io/devcontainers/features/go:1": { version: "latest" },
|
|
437
|
+
"ghcr.io/devcontainers/features/dotnet:2": { version: DOTNET_SDK_VERSION.replace(/\.x$/, "") }
|
|
440
438
|
},
|
|
441
439
|
// `npm ci` first: every guard after it runs through the workspace's own
|
|
442
440
|
// scripts and Nx, which do not exist until the install completes.
|
|
@@ -501,7 +499,7 @@ var ESLINT_PEER_OVERRIDES = {
|
|
|
501
499
|
// both — and forcing those to v5 breaks them. So the blast radius is one
|
|
502
500
|
// dependency edge per named parent, and a test asserts there is no top-level
|
|
503
501
|
// entry.
|
|
504
|
-
"nx": { "brace-expansion": "^5.0.9" },
|
|
502
|
+
"nx": { "brace-expansion": "^5.0.9", "smol-toml": "^1.7.1" },
|
|
505
503
|
"@nx/js": { "brace-expansion": "^5.0.9" },
|
|
506
504
|
"@nx/eslint": { "brace-expansion": "^5.0.9" },
|
|
507
505
|
"@nx/eslint-plugin": { "brace-expansion": "^5.0.9" },
|
|
@@ -779,6 +777,65 @@ function pythonPublishUrl(registry) {
|
|
|
779
777
|
}
|
|
780
778
|
return void 0;
|
|
781
779
|
}
|
|
780
|
+
function nugetFeedUrl(registry) {
|
|
781
|
+
if (registry.kind === "azure-artifacts") {
|
|
782
|
+
return `https://pkgs.dev.azure.com/${registry.organization}/${registry.project}/_packaging/${registry.artifactsFeed}/nuget/v3/index.json`;
|
|
783
|
+
}
|
|
784
|
+
return void 0;
|
|
785
|
+
}
|
|
786
|
+
var NUGET_AZURE_SOURCE = "AzureArtifacts";
|
|
787
|
+
function nugetConfigContent(registry, scope) {
|
|
788
|
+
if (registry.kind === "npm") {
|
|
789
|
+
return `<?xml version="1.0" encoding="utf-8"?>
|
|
790
|
+
<!-- Publish authentication for NuGet is deliberately UNCONFIGURED for the
|
|
791
|
+
public npm registry choice: publishing to public nuget.org needs a
|
|
792
|
+
nuget.org-issued API key, a credential mnci collects nowhere (the same
|
|
793
|
+
gap Python's PyPI publish has for this same registry choice). A
|
|
794
|
+
csharp-lib is still versioned and tagged; run "dotnet nuget push"
|
|
795
|
+
yourself with your own key, or regenerate choosing the azure-artifacts
|
|
796
|
+
registry instead. -->
|
|
797
|
+
<configuration>
|
|
798
|
+
<packageSources>
|
|
799
|
+
<clear />
|
|
800
|
+
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
|
801
|
+
</packageSources>
|
|
802
|
+
</configuration>
|
|
803
|
+
`;
|
|
804
|
+
}
|
|
805
|
+
const pascalScope2 = scope.replace(/^@/, "").split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
806
|
+
const feedUrl = nugetFeedUrl(registry);
|
|
807
|
+
return `<?xml version="1.0" encoding="utf-8"?>
|
|
808
|
+
<!-- NuGet's own environment-variable syntax is '%VAR%' on every platform \u2014
|
|
809
|
+
never '\${VAR}'/'$VAR', which resolve on none of them. NUGET_PAT is the
|
|
810
|
+
RAW PAT (not base64 \u2014 unlike .npmrc's _password, NuGet's HTTP client
|
|
811
|
+
handles Basic auth itself from Username + ClearTextPassword), exported
|
|
812
|
+
only by the CI release step (see nugetPublishEnvFragment in mnci); an
|
|
813
|
+
ordinary build/test/lint step never needs it, since packageSourceMapping
|
|
814
|
+
below scopes this feed to ${pascalScope2}.* packages only. -->
|
|
815
|
+
<configuration>
|
|
816
|
+
<packageSources>
|
|
817
|
+
<clear />
|
|
818
|
+
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
|
819
|
+
<add key="${NUGET_AZURE_SOURCE}" value="${feedUrl}" />
|
|
820
|
+
</packageSources>
|
|
821
|
+
<packageSourceCredentials>
|
|
822
|
+
<${NUGET_AZURE_SOURCE}>
|
|
823
|
+
<add key="Username" value="AzureArtifacts" />
|
|
824
|
+
<add key="ClearTextPassword" value="%NUGET_PAT%" />
|
|
825
|
+
</${NUGET_AZURE_SOURCE}>
|
|
826
|
+
</packageSourceCredentials>
|
|
827
|
+
<packageSourceMapping>
|
|
828
|
+
<clear />
|
|
829
|
+
<packageSource key="${NUGET_AZURE_SOURCE}">
|
|
830
|
+
<package pattern="${pascalScope2}.*" />
|
|
831
|
+
</packageSource>
|
|
832
|
+
<packageSource key="nuget.org">
|
|
833
|
+
<package pattern="*" />
|
|
834
|
+
</packageSource>
|
|
835
|
+
</packageSourceMapping>
|
|
836
|
+
</configuration>
|
|
837
|
+
`;
|
|
838
|
+
}
|
|
782
839
|
var PYTHON_INSTALL_GUARD = `node -e "if(!require('node:fs').existsSync('requirements-dev.txt')){console.log('No Python projects - skipping.');process.exit(0)}const py=process.platform==='win32'?'python':'python3';process.exit(require('node:child_process').spawnSync(py+' -m pip install -r requirements-dev.txt',{stdio:'inherit',shell:true}).status ?? 1)"`;
|
|
783
840
|
var PYTHON_WORKSPACE_INSTALL_GUARD = `node -e "const fs=require('node:fs'),path=require('node:path');const editableDirs=[...fs.globSync('apps/*/pyproject.toml'),...fs.globSync('python-packages/*/pyproject.toml'),...fs.globSync('libs/*/pyproject.toml')].map((p)=>path.dirname(p));const requirementsFiles=fs.globSync('apps/*/requirements.txt');if(editableDirs.length===0&&requirementsFiles.length===0){console.log('No Python projects - skipping.');process.exit(0)}const args=['-m','pip','install','--quiet',...editableDirs.flatMap((d)=>['-e',d]),...requirementsFiles.flatMap((f)=>['-r',f])];const py=process.platform==='win32'?'python':'python3';process.exit(require('node:child_process').spawnSync(py,args,{stdio:'inherit'}).status ?? 1)"`;
|
|
784
841
|
var PIP_AUDIT_GUARD = `node -e "if(!require('node:fs').existsSync('requirements-dev.txt')){console.log('No Python projects - skipping.');process.exit(0)}const py=process.platform==='win32'?'python':'python3';require('node:child_process').spawnSync(py,['-m','pip_audit'],{stdio:'inherit'});process.exit(0)"`;
|
|
@@ -790,6 +847,8 @@ var GO_TOOL_PATH_GITHUB = `node -e "${GO_TOOL_PATH_PRELUDE}if(!process.env.GITHU
|
|
|
790
847
|
var FLUTTER_SDK_VERSION = "3.44.8";
|
|
791
848
|
var NODE_VERSION = "24";
|
|
792
849
|
var NPM_VERSION = "11";
|
|
850
|
+
var DOTNET_SDK_VERSION = "10.0.x";
|
|
851
|
+
var DOTNET_DETECT_AZURE = `node -e "const fs=require('node:fs');const has=[...fs.globSync('apps/*/*.csproj'),...fs.globSync('packages/*/*.csproj'),...fs.globSync('libs/*/*.csproj')].length>0;console.log('##vso[task.setvariable variable=hasDotnetProjects]'+has)"`;
|
|
793
852
|
var FLUTTER_SDK_DIRECTORY_EXPRESSION = `require('node:path').join(require('node:os').homedir(),'.mnci-flutter-${FLUTTER_SDK_VERSION}')`;
|
|
794
853
|
var FLUTTER_SDK_INSTALL_GUARD = `node -e "const fs=require('node:fs'),cp=require('node:child_process');if(!fs.existsSync('pubspec.yaml')){console.log('No Flutter projects - skipping.');process.exit(0)}if(cp.spawnSync('flutter',['--version'],{stdio:'ignore',shell:process.platform==='win32'}).status===0){console.log('Flutter SDK already on PATH - skipping.');process.exit(0)}const sdk=${FLUTTER_SDK_DIRECTORY_EXPRESSION};if(fs.existsSync(sdk)){console.log('Flutter SDK already installed at '+sdk+' - skipping.');process.exit(0)}process.exit(cp.spawnSync('git',['clone','--depth','1','--branch','${FLUTTER_SDK_VERSION}','https://github.com/flutter/flutter.git',sdk],{stdio:'inherit'}).status ?? 1)"`;
|
|
795
854
|
var FLUTTER_TOOL_PATH_PRELUDE = `const fs=require('node:fs'),path=require('node:path');if(!fs.existsSync('pubspec.yaml')){console.log('No Flutter projects - skipping.');process.exit(0)}const sdk=${FLUTTER_SDK_DIRECTORY_EXPRESSION};if(!fs.existsSync(sdk)){console.log('Flutter SDK was not installed by mnci (already on PATH) - skipping.');process.exit(0)}const bin=path.join(sdk,'bin');`;
|
|
@@ -799,20 +858,23 @@ var FLUTTER_PUB_GET_GUARD = `node -e "const fs=require('node:fs');if(!fs.existsS
|
|
|
799
858
|
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 act=all.filter(v=>v.fixAvailable&&BLOCK.includes(v.severity));const rest=all.filter(v=>!act.includes(v));for(const v of rest)console.log(' note ['+v.severity+'] '+v.name+(v.fixAvailable?' - fix available, below the blocking threshold':' - NO fix available upstream, nothing to do here'));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'+(v.fixAvailable&&v.fixAvailable.isSemVerMajor?' (semver-major)':''));console.log('Each has a published fix. Add a targeted overrides entry in package.json rather than npm audit fix --force.');process.exit(1)"`;
|
|
800
859
|
var VERIFY_TARGETS = "lint,typecheck,test,build";
|
|
801
860
|
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)"`;
|
|
802
|
-
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}});if(!hasProjectJson&&!hasInlineNx){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)"`;
|
|
803
|
-
function releaseGuard(pythonPublishEnv) {
|
|
804
|
-
return `node -e "const fs=require('node:fs'),cp=require('node:child_process');const hasNpm=fs.globSync('packages/*/package.json').length>0;const hasPython=fs.globSync('python-packages/*/pyproject.toml').length>0;if(!hasNpm&&!hasPython){console.log('Nothing to release - skipping.');process.exit(0)}const env={...process.env};${pythonPublishEnv}process.exit(cp.spawnSync('npx nx release --yes',{stdio:'inherit',shell:true,env}).status ?? 1)"`;
|
|
861
|
+
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)"`;
|
|
862
|
+
function releaseGuard(pythonPublishEnv, nugetPublishEnv) {
|
|
863
|
+
return `node -e "const fs=require('node:fs'),cp=require('node:child_process');const hasNpm=fs.globSync('packages/*/package.json').length>0;const hasPython=fs.globSync('python-packages/*/pyproject.toml').length>0;const hasCsharp=fs.globSync('packages/*/*.csproj').length>0;if(!hasNpm&&!hasPython&&!hasCsharp){console.log('Nothing to release - skipping.');process.exit(0)}const env={...process.env};${pythonPublishEnv}${nugetPublishEnv}process.exit(cp.spawnSync('npx nx release --yes',{stdio:'inherit',shell:true,env}).status ?? 1)"`;
|
|
805
864
|
}
|
|
806
865
|
function pythonPublishEnvFragment(pythonPublishUrl2) {
|
|
807
866
|
return pythonPublishUrl2 ? `if(hasPython){env.TWINE_REPOSITORY_URL='${pythonPublishUrl2}';env.TWINE_USERNAME='AzureArtifacts';env.TWINE_PASSWORD=Buffer.from(process.env.PAT,'base64').toString()}` : "";
|
|
808
867
|
}
|
|
868
|
+
function nugetPublishEnvFragment(nugetFeedUrl2) {
|
|
869
|
+
return nugetFeedUrl2 ? "if(hasCsharp){env.NUGET_PAT=Buffer.from(process.env.PAT,'base64').toString()}" : "";
|
|
870
|
+
}
|
|
809
871
|
function npmAuthEnvVariable(registryKind, variableReference) {
|
|
810
872
|
return registryKind === "npm" ? ["NODE_AUTH_TOKEN", variableReference("NPM_TOKEN")] : ["PAT", variableReference("PAT")];
|
|
811
873
|
}
|
|
812
874
|
function poolBlock(agent) {
|
|
813
875
|
return /^(?:ubuntu|windows|macos)-/i.test(agent) ? ` vmImage: ${agent}` : ` name: ${agent}`;
|
|
814
876
|
}
|
|
815
|
-
function azurePipelinesYaml(agent, variableGroup, pythonPublishUrl2, registryKind = "azure-artifacts") {
|
|
877
|
+
function azurePipelinesYaml(agent, variableGroup, pythonPublishUrl2, registryKind = "azure-artifacts", nugetFeedUrl2) {
|
|
816
878
|
const onMain = "and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'), eq(variables['Build.SourceBranchName'], 'main'))";
|
|
817
879
|
const [npmAuthName, npmAuthValue] = npmAuthEnvVariable(registryKind, (name) => `$(${name})`);
|
|
818
880
|
return `name: monorepo-ci-$(Date:yyyyMMdd)$(Rev:.r)
|
|
@@ -984,6 +1046,20 @@ steps:
|
|
|
984
1046
|
- script: ${FLUTTER_PUB_GET_GUARD}
|
|
985
1047
|
displayName: Resolve Dart dependencies (one pub get for the whole workspace)
|
|
986
1048
|
|
|
1049
|
+
# .NET, if the workspace has any. Azure's 'condition:' expression language
|
|
1050
|
+
# has no glob function, so this script step detects C# projects first and
|
|
1051
|
+
# hands the answer to the install task below through a pipeline variable \u2014
|
|
1052
|
+
# see DOTNET_DETECT_AZURE's remarks for why this differs from every other
|
|
1053
|
+
# toolchain's self-gating 'node -e' guard.
|
|
1054
|
+
- script: ${DOTNET_DETECT_AZURE}
|
|
1055
|
+
displayName: Detect .NET projects
|
|
1056
|
+
|
|
1057
|
+
- task: UseDotNet@2
|
|
1058
|
+
displayName: Install the .NET SDK (${DOTNET_SDK_VERSION})
|
|
1059
|
+
condition: eq(variables['hasDotnetProjects'], 'true')
|
|
1060
|
+
inputs:
|
|
1061
|
+
version: ${DOTNET_SDK_VERSION}
|
|
1062
|
+
|
|
987
1063
|
# Fails fast, with an unambiguous message, when a stale TypeScript project
|
|
988
1064
|
# reference (or another sync generator's drift) was never synced+committed
|
|
989
1065
|
# locally \u2014 sync.applyChanges (nx.json) only auto-applies interactively, so
|
|
@@ -1024,13 +1100,14 @@ steps:
|
|
|
1024
1100
|
displayName: Tag the run per app (type-name)
|
|
1025
1101
|
condition: ${onMain}
|
|
1026
1102
|
|
|
1027
|
-
# Version + tag + publish, in one release, for npm (packages/*)
|
|
1028
|
-
# (python-packages/*) \u2014 conventional commits,
|
|
1029
|
-
# nx release errors on an empty scope, so
|
|
1030
|
-
# to release. When there are Python
|
|
1031
|
-
#
|
|
1032
|
-
|
|
1033
|
-
|
|
1103
|
+
# Version + tag + publish, in one release, for npm (packages/*), Python
|
|
1104
|
+
# (python-packages/*) AND C# (packages/*/*.csproj) \u2014 conventional commits,
|
|
1105
|
+
# tag-only push. Portable guard: nx release errors on an empty scope, so
|
|
1106
|
+
# skip cleanly when there is nothing to release. When there are Python or
|
|
1107
|
+
# C# packages and an Azure feed, twine/NuGet publish credentials are
|
|
1108
|
+
# exported (raw PAT, decoded from the base64 variable).
|
|
1109
|
+
- script: ${releaseGuard(pythonPublishEnvFragment(pythonPublishUrl2), nugetPublishEnvFragment(nugetFeedUrl2))}
|
|
1110
|
+
displayName: Release \u2014 version, tag and publish (npm + Python + C#)
|
|
1034
1111
|
condition: ${onMain}
|
|
1035
1112
|
env:
|
|
1036
1113
|
${npmAuthName}: ${npmAuthValue}
|
|
@@ -1045,7 +1122,7 @@ steps:
|
|
|
1045
1122
|
condition: ${onMain}
|
|
1046
1123
|
`;
|
|
1047
1124
|
}
|
|
1048
|
-
function githubActionsYaml(agent, pythonPublishUrl2, registryKind = "azure-artifacts", ci = "github") {
|
|
1125
|
+
function githubActionsYaml(agent, pythonPublishUrl2, registryKind = "azure-artifacts", ci = "github", nugetFeedUrl2) {
|
|
1049
1126
|
const onMain = "github.event_name == 'push' && github.ref_name == 'main'";
|
|
1050
1127
|
const [npmAuthName, npmAuthValue] = npmAuthEnvVariable(
|
|
1051
1128
|
registryKind,
|
|
@@ -1180,6 +1257,16 @@ jobs:
|
|
|
1180
1257
|
- run: ${FLUTTER_PUB_GET_GUARD}
|
|
1181
1258
|
name: Resolve Dart dependencies (one pub get for the whole workspace)
|
|
1182
1259
|
|
|
1260
|
+
# .NET, if the workspace has any. actions/setup-dotnet is the
|
|
1261
|
+
# maintained, cached installer GitHub itself ships, so this uses it
|
|
1262
|
+
# directly rather than a hand-rolled 'node -e' guard \u2014 see
|
|
1263
|
+
# DOTNET_DETECT_AZURE's remarks for the full reasoning. hashFiles()
|
|
1264
|
+
# gates it inline, so a JS-only workspace pays nothing.
|
|
1265
|
+
- uses: actions/setup-dotnet@v4
|
|
1266
|
+
if: \${{ hashFiles('apps/*/*.csproj', 'packages/*/*.csproj', 'libs/*/*.csproj') != '' }}
|
|
1267
|
+
with:
|
|
1268
|
+
dotnet-version: ${DOTNET_SDK_VERSION}
|
|
1269
|
+
|
|
1183
1270
|
# Fails fast, with an unambiguous message, when a stale TypeScript project
|
|
1184
1271
|
# reference (or another sync generator's drift) was never synced+committed
|
|
1185
1272
|
# locally \u2014 sync.applyChanges (nx.json) only auto-applies interactively, so
|
|
@@ -1214,18 +1301,19 @@ jobs:
|
|
|
1214
1301
|
path: dist/drop
|
|
1215
1302
|
if-no-files-found: ignore
|
|
1216
1303
|
|
|
1217
|
-
# Version + tag + publish, in one release, for npm (packages/*)
|
|
1218
|
-
# (python-packages/*) \u2014 conventional
|
|
1219
|
-
# nx release errors on an empty
|
|
1220
|
-
#
|
|
1221
|
-
#
|
|
1304
|
+
# Version + tag + publish, in one release, for npm (packages/*), Python
|
|
1305
|
+
# (python-packages/*) AND C# (packages/*/*.csproj) \u2014 conventional
|
|
1306
|
+
# commits, tag-only push. Portable guard: nx release errors on an empty
|
|
1307
|
+
# scope, so skip cleanly when there is nothing to release. When there
|
|
1308
|
+
# are Python or C# packages and an Azure feed, twine/NuGet publish
|
|
1309
|
+
# credentials are exported (raw PAT, decoded from the base64 secret).${githubReleases ? `
|
|
1222
1310
|
# This provider also creates a per-project GitHub Release (changelog
|
|
1223
1311
|
# generated from conventional commits since that project's last tag),
|
|
1224
1312
|
# which is why 'nx release' pushes the tag itself here \u2014 see
|
|
1225
1313
|
# releaseConfig's remarks for why that is safe on this Nx version and
|
|
1226
1314
|
# why every other provider combination keeps the explicit push step below.` : ""}
|
|
1227
|
-
- run: ${releaseGuard(pythonPublishEnvFragment(pythonPublishUrl2))}
|
|
1228
|
-
name: Release \u2014 version, tag${githubReleases ? ", publish and GitHub Release" : " and publish"} (npm + Python)
|
|
1315
|
+
- run: ${releaseGuard(pythonPublishEnvFragment(pythonPublishUrl2), nugetPublishEnvFragment(nugetFeedUrl2))}
|
|
1316
|
+
name: Release \u2014 version, tag${githubReleases ? ", publish and GitHub Release" : " and publish"} (npm + Python + C#)
|
|
1229
1317
|
if: \${{ ${onMain} }}
|
|
1230
1318
|
env:
|
|
1231
1319
|
${npmAuthName}: ${npmAuthValue}${githubReleases ? `
|
|
@@ -1407,24 +1495,27 @@ function applyOverlay(workspaceRoot, options, onProgress = () => {
|
|
|
1407
1495
|
(0, import_node_fs2.rmSync)((0, import_node_path2.join)(workspaceRoot, "undefined.code-workspace"), { force: true });
|
|
1408
1496
|
}
|
|
1409
1497
|
const publishUrl = pythonPublishUrl(options.registry);
|
|
1498
|
+
const nugetUrl = nugetFeedUrl(options.registry);
|
|
1410
1499
|
if (options.ci === "azure" || options.ci === "both") {
|
|
1411
1500
|
onProgress("azure-pipelines.yml \u2014 build, verify, pack and release");
|
|
1412
1501
|
writeFileEnsured(
|
|
1413
1502
|
(0, import_node_path2.join)(workspaceRoot, "azure-pipelines.yml"),
|
|
1414
|
-
azurePipelinesYaml(options.agent, options.variableGroup, publishUrl, options.registry.kind)
|
|
1503
|
+
azurePipelinesYaml(options.agent, options.variableGroup, publishUrl, options.registry.kind, nugetUrl)
|
|
1415
1504
|
);
|
|
1416
1505
|
}
|
|
1417
1506
|
if (options.ci === "github" || options.ci === "both") {
|
|
1418
1507
|
onProgress(".github/workflows/ci.yml and dependabot.yml");
|
|
1419
1508
|
writeFileEnsured(
|
|
1420
1509
|
(0, import_node_path2.join)(workspaceRoot, ".github/workflows/ci.yml"),
|
|
1421
|
-
githubActionsYaml(options.agent, publishUrl, options.registry.kind, options.ci)
|
|
1510
|
+
githubActionsYaml(options.agent, publishUrl, options.registry.kind, options.ci, nugetUrl)
|
|
1422
1511
|
);
|
|
1423
1512
|
writeFileEnsured((0, import_node_path2.join)(workspaceRoot, ".github/dependabot.yml"), dependabotConfig(workspaceRoot));
|
|
1424
1513
|
}
|
|
1425
1514
|
}
|
|
1426
1515
|
|
|
1427
1516
|
// src/commands/add/shared.ts
|
|
1517
|
+
var import_node_fs3 = require("fs");
|
|
1518
|
+
var import_node_path3 = require("path");
|
|
1428
1519
|
function hasPlugin(workspaceRoot, packageName) {
|
|
1429
1520
|
const manifest = readJson((0, import_node_path3.join)(workspaceRoot, "package.json"));
|
|
1430
1521
|
const installed = { ...manifest.dependencies, ...manifest.devDependencies };
|
|
@@ -1671,6 +1762,11 @@ function addNxTargets(manifestPath, newTargets) {
|
|
|
1671
1762
|
toJson({ ...manifest, nx: { ...nx, targets: { ...targets, ...newTargets } } })
|
|
1672
1763
|
);
|
|
1673
1764
|
}
|
|
1765
|
+
function addProjectJsonTargets(projectJsonPath, newTargets) {
|
|
1766
|
+
const project = fileExists(projectJsonPath) ? readJson(projectJsonPath) : {};
|
|
1767
|
+
const targets = project.targets ?? {};
|
|
1768
|
+
writeFileEnsured(projectJsonPath, toJson({ ...project, targets: { ...targets, ...newTargets } }));
|
|
1769
|
+
}
|
|
1674
1770
|
var ESLINT_CONFIG_FILENAMES = [
|
|
1675
1771
|
"eslint.config.js",
|
|
1676
1772
|
"eslint.config.mjs",
|
|
@@ -1798,12 +1894,261 @@ function relocateRootRuntimeDependencies(workspaceRoot, projectName, before) {
|
|
|
1798
1894
|
}
|
|
1799
1895
|
}
|
|
1800
1896
|
|
|
1801
|
-
// src/commands/add/
|
|
1802
|
-
function
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1897
|
+
// src/commands/add/csharp.ts
|
|
1898
|
+
function ensureDotnet(workspaceRoot) {
|
|
1899
|
+
if (runShell("dotnet", ["--version"], workspaceRoot) !== 0) {
|
|
1900
|
+
throw new Error(".NET SDK not found. Install .NET 8+ first: https://dotnet.microsoft.com/download");
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
function targetFramework() {
|
|
1904
|
+
const [major, minor] = DOTNET_SDK_VERSION.split(".", 2);
|
|
1905
|
+
return `net${major}.${minor}`;
|
|
1906
|
+
}
|
|
1907
|
+
function pascalCase(name) {
|
|
1908
|
+
return name.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
1909
|
+
}
|
|
1910
|
+
function scaffoldDotnetProject(workspaceRoot, projectRoot, identity, template) {
|
|
1911
|
+
if (runShell(
|
|
1912
|
+
"dotnet",
|
|
1913
|
+
["new", template, "-n", identity, "-o", projectRoot, "--framework", targetFramework()],
|
|
1914
|
+
workspaceRoot
|
|
1915
|
+
) !== 0) {
|
|
1916
|
+
throw new Error(`dotnet new ${template} failed for ${projectRoot}`);
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
function csharpAppPackageTarget(tag, projectRoot, name) {
|
|
1920
|
+
const outDir = `dist/apps/${name}`;
|
|
1921
|
+
const zip = `dist/drop/${tag}-${name}.zip`;
|
|
1922
|
+
const command = `node -e "const cp=require('node:child_process');const r=cp.spawnSync('dotnet',['publish','${projectRoot}','-c','Release','-o','${outDir}'],{stdio:'inherit',shell:true});if(r.status!==0)process.exit(r.status??1);const fs=require('node:fs');fs.mkdirSync('dist/drop',{recursive:true});const A=require('adm-zip');const z=new A();z.addLocalFolder('${outDir}');z.writeZip('${zip}')"`;
|
|
1923
|
+
return {
|
|
1924
|
+
executor: "nx:run-commands",
|
|
1925
|
+
outputs: [`{workspaceRoot}/${zip}`],
|
|
1926
|
+
options: { command }
|
|
1927
|
+
};
|
|
1928
|
+
}
|
|
1929
|
+
function csharpAppStartTarget(projectRoot) {
|
|
1930
|
+
return {
|
|
1931
|
+
executor: "nx:run-commands",
|
|
1932
|
+
continuous: true,
|
|
1933
|
+
options: { command: "dotnet run", cwd: projectRoot }
|
|
1934
|
+
};
|
|
1935
|
+
}
|
|
1936
|
+
function addCsharpApp(workspaceRoot, name, template = "console") {
|
|
1937
|
+
ensureDotnet(workspaceRoot);
|
|
1938
|
+
ensurePlugin(workspaceRoot, "@nx/dotnet");
|
|
1939
|
+
ensureAdmZip(workspaceRoot);
|
|
1940
|
+
const projectRoot = `apps/${name}`;
|
|
1941
|
+
scaffoldDotnetProject(workspaceRoot, projectRoot, pascalCase(name), template);
|
|
1942
|
+
addProjectJsonTargets((0, import_node_path4.join)(workspaceRoot, projectRoot, "project.json"), {
|
|
1943
|
+
package: csharpAppPackageTarget("csharp-app", projectRoot, name),
|
|
1944
|
+
start: csharpAppStartTarget(projectRoot)
|
|
1945
|
+
});
|
|
1946
|
+
registerProjectCommands(workspaceRoot, name, { build: true, start: `nx run ${name}:start` });
|
|
1947
|
+
}
|
|
1948
|
+
function pascalScope(scope) {
|
|
1949
|
+
return pascalCase(scope.replace(/^@/, ""));
|
|
1950
|
+
}
|
|
1951
|
+
var CSHARP_VERSION_ACTIONS_PATH = "tools/csharp-version-actions.cjs";
|
|
1952
|
+
var CSHARP_VERSION_ACTIONS = `'use strict'
|
|
1953
|
+
|
|
1954
|
+
const { join } = require('node:path')
|
|
1955
|
+
const { VersionActions } = require('nx/release')
|
|
1956
|
+
|
|
1957
|
+
const VERSION_TAG = /<Version>([^<]*)<\\/Version>/
|
|
1958
|
+
|
|
1959
|
+
function findCsproj (tree, root) {
|
|
1960
|
+
const name = tree.children(root).find((entry) => entry.endsWith('.csproj'))
|
|
1961
|
+
return name ? join(root, name) : null
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
/**
|
|
1965
|
+
* Hand-written Nx release VersionActions for a publishable C# library: reads
|
|
1966
|
+
* and writes the <Version> element of the project's own .csproj. Written by
|
|
1967
|
+
* \`mnci add csharp-lib\` \u2014 see that command's source for why this is a
|
|
1968
|
+
* workspace file rather than an npm package.
|
|
1969
|
+
*/
|
|
1970
|
+
class CsharpVersionActions extends VersionActions {
|
|
1971
|
+
validManifestFilenames = ['*.csproj']
|
|
1972
|
+
|
|
1973
|
+
async readCurrentVersionFromSourceManifest (tree) {
|
|
1974
|
+
const manifestPath = findCsproj(tree, this.projectGraphNode.data.root)
|
|
1975
|
+
if (!manifestPath) {
|
|
1976
|
+
return null
|
|
1977
|
+
}
|
|
1978
|
+
const contents = tree.read(manifestPath, 'utf8') ?? ''
|
|
1979
|
+
const match = VERSION_TAG.exec(contents)
|
|
1980
|
+
if (!match || !match[1]) {
|
|
1981
|
+
throw new Error(\`Could not find a <Version> element in \${manifestPath}\`)
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
return { currentVersion: match[1], manifestPath }
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1987
|
+
async readCurrentVersionFromRegistry (_tree, _currentVersionResolverMetadata) {
|
|
1988
|
+
return {
|
|
1989
|
+
currentVersion: null,
|
|
1990
|
+
logText: 'C# libraries resolve their current version from git tags, not a registry lookup',
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
async readCurrentVersionOfDependency (_tree, _projectGraph, _dependencyProjectName) {
|
|
1995
|
+
return { currentVersion: null, dependencyCollection: null }
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
async updateProjectVersion (tree, newVersion) {
|
|
1999
|
+
const manifestPath = findCsproj(tree, this.projectGraphNode.data.root)
|
|
2000
|
+
if (!manifestPath) {
|
|
2001
|
+
throw new Error(\`No .csproj found in \${this.projectGraphNode.data.root}\`)
|
|
2002
|
+
}
|
|
2003
|
+
const contents = tree.read(manifestPath, 'utf8') ?? ''
|
|
2004
|
+
if (!VERSION_TAG.test(contents)) {
|
|
2005
|
+
throw new Error(\`Could not find a <Version> element in \${manifestPath}\`)
|
|
2006
|
+
}
|
|
2007
|
+
tree.write(manifestPath, contents.replace(VERSION_TAG, () => \`<Version>\${newVersion}</Version>\`))
|
|
2008
|
+
|
|
2009
|
+
return [\`Updated \${manifestPath} to version \${newVersion}\`]
|
|
2010
|
+
}
|
|
2011
|
+
|
|
2012
|
+
async updateProjectDependencies (_tree, _projectGraph, _dependenciesToUpdate) {
|
|
2013
|
+
return []
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
async validate (tree) {
|
|
2017
|
+
if (!findCsproj(tree, this.projectGraphNode.data.root)) {
|
|
2018
|
+
throw new Error(\`The project "\${this.projectGraphNode.name}" does not have a .csproj file available in \${this.projectGraphNode.data.root}\`)
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
1806
2021
|
}
|
|
2022
|
+
|
|
2023
|
+
module.exports = CsharpVersionActions
|
|
2024
|
+
`;
|
|
2025
|
+
function writeCsharpVersionActions(workspaceRoot) {
|
|
2026
|
+
writeFileEnsured((0, import_node_path4.join)(workspaceRoot, CSHARP_VERSION_ACTIONS_PATH), CSHARP_VERSION_ACTIONS);
|
|
2027
|
+
}
|
|
2028
|
+
function addProjectJsonReleaseVersionActions(projectJsonPath) {
|
|
2029
|
+
const project = fileExists(projectJsonPath) ? readJson(projectJsonPath) : {};
|
|
2030
|
+
const release = project.release ?? {};
|
|
2031
|
+
const version = release.version ?? {};
|
|
2032
|
+
writeFileEnsured(
|
|
2033
|
+
projectJsonPath,
|
|
2034
|
+
toJson({
|
|
2035
|
+
...project,
|
|
2036
|
+
release: { ...release, version: { ...version, versionActions: CSHARP_VERSION_ACTIONS_PATH } }
|
|
2037
|
+
})
|
|
2038
|
+
);
|
|
2039
|
+
}
|
|
2040
|
+
function addInitialVersion(csprojPath) {
|
|
2041
|
+
const contents = (0, import_node_fs4.readFileSync)(csprojPath, "utf8");
|
|
2042
|
+
writeFileEnsured(csprojPath, contents.replace("<PropertyGroup>", "<PropertyGroup>\n <Version>0.1.0</Version>"));
|
|
2043
|
+
}
|
|
2044
|
+
function csharpLibPublishTarget(projectRoot) {
|
|
2045
|
+
const outDir = `${projectRoot}/dist`;
|
|
2046
|
+
const command = `node -e "if(!process.env.NUGET_PAT){console.log('NuGet publish is not configured for this registry choice (no NUGET_PAT) - skipping. Regenerate with --registry azure-artifacts, or run dotnet nuget push manually.');process.exit(0)}const cp=require('node:child_process');const pack=cp.spawnSync('dotnet',['pack','${projectRoot}','-c','Release','-o','${outDir}'],{stdio:'inherit',shell:true});if(pack.status!==0)process.exit(pack.status??1);const fs=require('node:fs');for(const pkg of fs.globSync('${outDir}/*.nupkg')){const push=cp.spawnSync('dotnet',['nuget','push',pkg,'--source','${NUGET_AZURE_SOURCE}','--api-key','AZ'],{stdio:'inherit',shell:true});if(push.status!==0)process.exit(push.status??1)}"`;
|
|
2047
|
+
return { executor: "nx:run-commands", options: { command } };
|
|
2048
|
+
}
|
|
2049
|
+
async function addCsharpLib(workspaceRoot, name, options, kindProvided) {
|
|
2050
|
+
ensureDotnet(workspaceRoot);
|
|
2051
|
+
ensurePlugin(workspaceRoot, "@nx/dotnet");
|
|
2052
|
+
const scope = options.scope ?? (kindProvided ? defaultScope(workspaceRoot) : await promptText("NuGet package scope for the published library", defaultScope(workspaceRoot)));
|
|
2053
|
+
const projectRoot = `packages/${name}`;
|
|
2054
|
+
const identity = `${pascalScope(scope)}.${pascalCase(name)}`;
|
|
2055
|
+
scaffoldDotnetProject(workspaceRoot, projectRoot, identity, "classlib");
|
|
2056
|
+
addInitialVersion((0, import_node_path4.join)(workspaceRoot, projectRoot, `${identity}.csproj`));
|
|
2057
|
+
writeCsharpVersionActions(workspaceRoot);
|
|
2058
|
+
addProjectJsonReleaseVersionActions((0, import_node_path4.join)(workspaceRoot, projectRoot, "project.json"));
|
|
2059
|
+
addProjectJsonTargets((0, import_node_path4.join)(workspaceRoot, projectRoot, "project.json"), {
|
|
2060
|
+
"nx-release-publish": csharpLibPublishTarget(projectRoot)
|
|
2061
|
+
});
|
|
2062
|
+
const registry = readMnciConfig(workspaceRoot).registry ?? { kind: "npm" };
|
|
2063
|
+
writeFileEnsured((0, import_node_path4.join)(workspaceRoot, "nuget.config"), nugetConfigContent(registry, scope));
|
|
2064
|
+
registerProjectCommands(workspaceRoot, name, { build: true });
|
|
2065
|
+
}
|
|
2066
|
+
function addCsharpInternalLib(workspaceRoot, name) {
|
|
2067
|
+
ensureDotnet(workspaceRoot);
|
|
2068
|
+
ensurePlugin(workspaceRoot, "@nx/dotnet");
|
|
2069
|
+
const projectRoot = `libs/${name}`;
|
|
2070
|
+
const identity = pascalCase(name);
|
|
2071
|
+
scaffoldDotnetProject(workspaceRoot, projectRoot, identity, "classlib");
|
|
2072
|
+
registerProjectCommands(workspaceRoot, name, { build: false });
|
|
2073
|
+
logger.step(
|
|
2074
|
+
`Reference it from a consumer with: dotnet add <consumer>.csproj reference ${projectRoot}/${identity}.csproj`
|
|
2075
|
+
);
|
|
2076
|
+
}
|
|
2077
|
+
var CSHARP_FUNCTION_APP_HOST_JSON = `{
|
|
2078
|
+
"version": "2.0",
|
|
2079
|
+
"extensionBundle": {
|
|
2080
|
+
"id": "Microsoft.Azure.Functions.ExtensionBundle",
|
|
2081
|
+
"version": "[4.*, 5.0.0)"
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
`;
|
|
2085
|
+
function csharpFunctionAppCsproj() {
|
|
2086
|
+
return `<Project Sdk="Azure.Functions.Sdk/1.0.0">
|
|
2087
|
+
<PropertyGroup>
|
|
2088
|
+
<TargetFramework>${targetFramework()}</TargetFramework>
|
|
2089
|
+
</PropertyGroup>
|
|
2090
|
+
|
|
2091
|
+
<ItemGroup>
|
|
2092
|
+
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.52.0" />
|
|
2093
|
+
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.1.0" />
|
|
2094
|
+
</ItemGroup>
|
|
2095
|
+
</Project>
|
|
2096
|
+
`;
|
|
2097
|
+
}
|
|
2098
|
+
var CSHARP_FUNCTION_APP_PROGRAM = `using Microsoft.Azure.Functions.Worker.Builder;
|
|
2099
|
+
using Microsoft.Extensions.Hosting;
|
|
2100
|
+
|
|
2101
|
+
var builder = FunctionsApplication.CreateBuilder(args);
|
|
2102
|
+
|
|
2103
|
+
builder.ConfigureFunctionsWebApplication();
|
|
2104
|
+
|
|
2105
|
+
builder.Build().Run();
|
|
2106
|
+
`;
|
|
2107
|
+
function csharpFunctionAppHello(identity) {
|
|
2108
|
+
return `using Microsoft.AspNetCore.Http;
|
|
2109
|
+
using Microsoft.AspNetCore.Mvc;
|
|
2110
|
+
using Microsoft.Azure.Functions.Worker;
|
|
2111
|
+
|
|
2112
|
+
namespace ${identity};
|
|
2113
|
+
|
|
2114
|
+
public class Hello
|
|
2115
|
+
{
|
|
2116
|
+
[Function("Hello")]
|
|
2117
|
+
public IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req)
|
|
2118
|
+
{
|
|
2119
|
+
return new OkObjectResult("Hello from mnci.");
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
`;
|
|
2123
|
+
}
|
|
2124
|
+
function csharpFunctionAppStartTarget(projectRoot) {
|
|
2125
|
+
return {
|
|
2126
|
+
executor: "nx:run-commands",
|
|
2127
|
+
continuous: true,
|
|
2128
|
+
options: { command: "dotnet run", cwd: projectRoot }
|
|
2129
|
+
};
|
|
2130
|
+
}
|
|
2131
|
+
function addCsharpFunctionApp(workspaceRoot, name) {
|
|
2132
|
+
ensureDotnet(workspaceRoot);
|
|
2133
|
+
ensurePlugin(workspaceRoot, "@nx/dotnet");
|
|
2134
|
+
ensureAdmZip(workspaceRoot);
|
|
2135
|
+
const projectRoot = `apps/${name}`;
|
|
2136
|
+
const identity = pascalCase(name);
|
|
2137
|
+
scaffoldDotnetProject(workspaceRoot, projectRoot, identity, "console");
|
|
2138
|
+
const absoluteRoot = (0, import_node_path4.join)(workspaceRoot, projectRoot);
|
|
2139
|
+
writeFileEnsured((0, import_node_path4.join)(absoluteRoot, `${identity}.csproj`), csharpFunctionAppCsproj());
|
|
2140
|
+
writeFileEnsured((0, import_node_path4.join)(absoluteRoot, "Program.cs"), CSHARP_FUNCTION_APP_PROGRAM);
|
|
2141
|
+
writeFileEnsured((0, import_node_path4.join)(absoluteRoot, "Hello.cs"), csharpFunctionAppHello(identity));
|
|
2142
|
+
writeFileEnsured((0, import_node_path4.join)(absoluteRoot, "host.json"), CSHARP_FUNCTION_APP_HOST_JSON);
|
|
2143
|
+
addProjectJsonTargets((0, import_node_path4.join)(absoluteRoot, "project.json"), {
|
|
2144
|
+
package: csharpAppPackageTarget("csharp-function-app", projectRoot, name),
|
|
2145
|
+
start: csharpFunctionAppStartTarget(projectRoot)
|
|
2146
|
+
});
|
|
2147
|
+
registerProjectCommands(workspaceRoot, name, { build: true, start: `nx run ${name}:start` });
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2150
|
+
// src/commands/add/flutter.ts
|
|
2151
|
+
var import_node_path5 = require("path");
|
|
1807
2152
|
function flutterAppStartTarget(name) {
|
|
1808
2153
|
return {
|
|
1809
2154
|
executor: "nx:run-commands",
|
|
@@ -1839,7 +2184,7 @@ function addFlutterApp(workspaceRoot, name) {
|
|
|
1839
2184
|
prepareFlutter(workspaceRoot);
|
|
1840
2185
|
ensureAdmZip(workspaceRoot);
|
|
1841
2186
|
runNx(["g", "@mnci/nx-flutter:application", name, "--no-interactive"], workspaceRoot);
|
|
1842
|
-
addProjectJsonTargets((0,
|
|
2187
|
+
addProjectJsonTargets((0, import_node_path5.join)(workspaceRoot, "apps", name, "project.json"), {
|
|
1843
2188
|
start: flutterAppStartTarget(name)
|
|
1844
2189
|
});
|
|
1845
2190
|
registerProjectCommands(workspaceRoot, name, { build: true, start: `nx run ${name}:start` });
|
|
@@ -1856,8 +2201,8 @@ function addFlutterInternalLib(workspaceRoot, name) {
|
|
|
1856
2201
|
}
|
|
1857
2202
|
|
|
1858
2203
|
// src/commands/add/go.ts
|
|
1859
|
-
var
|
|
1860
|
-
var
|
|
2204
|
+
var import_node_fs5 = require("fs");
|
|
2205
|
+
var import_node_path6 = require("path");
|
|
1861
2206
|
function ensureGo(workspaceRoot) {
|
|
1862
2207
|
if (runShell("go", ["version"], workspaceRoot) !== 0) {
|
|
1863
2208
|
throw new Error("Go not found. Install Go 1.21+ first: https://go.dev/dl/");
|
|
@@ -1884,7 +2229,7 @@ function ensureNxGoPlugin(workspaceRoot) {
|
|
|
1884
2229
|
}
|
|
1885
2230
|
}
|
|
1886
2231
|
function ensureGoModule(workspaceRoot) {
|
|
1887
|
-
if (fileExists((0,
|
|
2232
|
+
if (fileExists((0, import_node_path6.join)(workspaceRoot, "go.mod"))) {
|
|
1888
2233
|
return;
|
|
1889
2234
|
}
|
|
1890
2235
|
logger.step("Bootstrapping the workspace Go module (single root go.mod)");
|
|
@@ -1893,17 +2238,12 @@ function ensureGoModule(workspaceRoot) {
|
|
|
1893
2238
|
}
|
|
1894
2239
|
function goModulePath(workspaceRoot) {
|
|
1895
2240
|
try {
|
|
1896
|
-
const contents = (0,
|
|
2241
|
+
const contents = (0, import_node_fs5.readFileSync)((0, import_node_path6.join)(workspaceRoot, "go.mod"), "utf8");
|
|
1897
2242
|
return /^module\s+(\S+)/m.exec(contents)?.[1];
|
|
1898
2243
|
} catch {
|
|
1899
2244
|
return void 0;
|
|
1900
2245
|
}
|
|
1901
2246
|
}
|
|
1902
|
-
function addProjectJsonTargets2(projectJsonPath, newTargets) {
|
|
1903
|
-
const project = readJson(projectJsonPath);
|
|
1904
|
-
const targets = project.targets ?? {};
|
|
1905
|
-
writeFileEnsured(projectJsonPath, toJson({ ...project, targets: { ...targets, ...newTargets } }));
|
|
1906
|
-
}
|
|
1907
2247
|
function goTestTarget() {
|
|
1908
2248
|
return { executor: "@nx-go/nx-go:test" };
|
|
1909
2249
|
}
|
|
@@ -1958,7 +2298,7 @@ function addGoApp(workspaceRoot, name) {
|
|
|
1958
2298
|
],
|
|
1959
2299
|
workspaceRoot
|
|
1960
2300
|
);
|
|
1961
|
-
|
|
2301
|
+
addProjectJsonTargets((0, import_node_path6.join)(workspaceRoot, "apps", name, "project.json"), {
|
|
1962
2302
|
build: goBuildTarget(name),
|
|
1963
2303
|
test: goTestTarget(),
|
|
1964
2304
|
lint: goLintTarget(),
|
|
@@ -1981,7 +2321,7 @@ function addGoFunctionApp(workspaceRoot, name) {
|
|
|
1981
2321
|
],
|
|
1982
2322
|
workspaceRoot
|
|
1983
2323
|
);
|
|
1984
|
-
|
|
2324
|
+
addProjectJsonTargets((0, import_node_path6.join)(workspaceRoot, "apps", name, "project.json"), {
|
|
1985
2325
|
build: goBuildTarget(name),
|
|
1986
2326
|
test: goTestTarget(),
|
|
1987
2327
|
lint: goLintTarget(),
|
|
@@ -2002,7 +2342,7 @@ function addGoLib(workspaceRoot, name) {
|
|
|
2002
2342
|
],
|
|
2003
2343
|
workspaceRoot
|
|
2004
2344
|
);
|
|
2005
|
-
|
|
2345
|
+
addProjectJsonTargets((0, import_node_path6.join)(workspaceRoot, "packages", name, "project.json"), {
|
|
2006
2346
|
test: goTestTarget(),
|
|
2007
2347
|
lint: goLintTarget()
|
|
2008
2348
|
});
|
|
@@ -2025,7 +2365,7 @@ function addGoInternalLib(workspaceRoot, name) {
|
|
|
2025
2365
|
],
|
|
2026
2366
|
workspaceRoot
|
|
2027
2367
|
);
|
|
2028
|
-
|
|
2368
|
+
addProjectJsonTargets((0, import_node_path6.join)(workspaceRoot, "libs", name, "project.json"), {
|
|
2029
2369
|
test: goTestTarget(),
|
|
2030
2370
|
lint: goLintTarget()
|
|
2031
2371
|
});
|
|
@@ -2037,7 +2377,7 @@ function addGoInternalLib(workspaceRoot, name) {
|
|
|
2037
2377
|
}
|
|
2038
2378
|
|
|
2039
2379
|
// src/commands/add/node.ts
|
|
2040
|
-
var
|
|
2380
|
+
var import_node_path7 = require("path");
|
|
2041
2381
|
function ensurePlugin2(workspaceRoot, packageName) {
|
|
2042
2382
|
if (hasPlugin(workspaceRoot, packageName)) {
|
|
2043
2383
|
return;
|
|
@@ -2075,7 +2415,7 @@ function nodeAppPackageTarget(name) {
|
|
|
2075
2415
|
function addNodeApp(workspaceRoot, name, stack, framework = "none") {
|
|
2076
2416
|
runNodeApp(workspaceRoot, name, stack, framework);
|
|
2077
2417
|
ensureAdmZip(workspaceRoot);
|
|
2078
|
-
addNxTargets((0,
|
|
2418
|
+
addNxTargets((0, import_node_path7.join)(workspaceRoot, "apps", name, "package.json"), {
|
|
2079
2419
|
package: nodeAppPackageTarget(name)
|
|
2080
2420
|
});
|
|
2081
2421
|
removeGeneratedEslintConfig(workspaceRoot, `apps/${name}`);
|
|
@@ -2131,10 +2471,10 @@ describe('buildGreeting', () => {
|
|
|
2131
2471
|
})
|
|
2132
2472
|
`;
|
|
2133
2473
|
function repairNodeFunctionAppManifest(nodeFunctionAppRoot, workspaceRoot) {
|
|
2134
|
-
const manifestPath = (0,
|
|
2474
|
+
const manifestPath = (0, import_node_path7.join)(nodeFunctionAppRoot, "package.json");
|
|
2135
2475
|
const manifest = readJson(manifestPath);
|
|
2136
2476
|
const azureFunctionsVersion = readJson(
|
|
2137
|
-
(0,
|
|
2477
|
+
(0, import_node_path7.join)(workspaceRoot, "node_modules/@azure/functions/package.json")
|
|
2138
2478
|
).version;
|
|
2139
2479
|
const dependencies = manifest.dependencies ?? {};
|
|
2140
2480
|
writeFileEnsured(
|
|
@@ -2168,21 +2508,21 @@ function nodeFunctionAppStartTarget(name) {
|
|
|
2168
2508
|
function addNodeFunctionApp(workspaceRoot, name, stack) {
|
|
2169
2509
|
runNodeApp(workspaceRoot, name, stack, "none");
|
|
2170
2510
|
ensureAzureFunctionsPackage(workspaceRoot);
|
|
2171
|
-
const nodeFunctionAppRoot = (0,
|
|
2172
|
-
writeFileEnsured((0,
|
|
2173
|
-
writeFileEnsured((0,
|
|
2511
|
+
const nodeFunctionAppRoot = (0, import_node_path7.join)(workspaceRoot, "apps", name);
|
|
2512
|
+
writeFileEnsured((0, import_node_path7.join)(nodeFunctionAppRoot, "src/main.ts"), NODE_FUNCTION_APP_MAIN);
|
|
2513
|
+
writeFileEnsured((0, import_node_path7.join)(nodeFunctionAppRoot, "src/functions/hello.ts"), NODE_FUNCTION_APP_HELLO);
|
|
2174
2514
|
writeFileEnsured(
|
|
2175
|
-
(0,
|
|
2515
|
+
(0, import_node_path7.join)(nodeFunctionAppRoot, "src/functions/greeting.ts"),
|
|
2176
2516
|
NODE_FUNCTION_APP_GREETING
|
|
2177
2517
|
);
|
|
2178
2518
|
writeFileEnsured(
|
|
2179
|
-
(0,
|
|
2519
|
+
(0, import_node_path7.join)(nodeFunctionAppRoot, "src/functions/greeting.spec.ts"),
|
|
2180
2520
|
NODE_FUNCTION_APP_GREETING_SPEC
|
|
2181
2521
|
);
|
|
2182
|
-
writeFileEnsured((0,
|
|
2522
|
+
writeFileEnsured((0, import_node_path7.join)(nodeFunctionAppRoot, "host.json"), NODE_FUNCTION_APP_HOST_JSON);
|
|
2183
2523
|
repairNodeFunctionAppManifest(nodeFunctionAppRoot, workspaceRoot);
|
|
2184
2524
|
ensureAdmZip(workspaceRoot);
|
|
2185
|
-
addNxTargets((0,
|
|
2525
|
+
addNxTargets((0, import_node_path7.join)(nodeFunctionAppRoot, "package.json"), {
|
|
2186
2526
|
package: nodeFunctionAppPackageTarget(name),
|
|
2187
2527
|
start: nodeFunctionAppStartTarget(name)
|
|
2188
2528
|
});
|
|
@@ -2191,7 +2531,7 @@ function addNodeFunctionApp(workspaceRoot, name, stack) {
|
|
|
2191
2531
|
}
|
|
2192
2532
|
|
|
2193
2533
|
// src/commands/add/npmLib.ts
|
|
2194
|
-
var
|
|
2534
|
+
var import_node_path8 = require("path");
|
|
2195
2535
|
async function addNpmLib(workspaceRoot, name, options, kindProvided, stack) {
|
|
2196
2536
|
const scope = options.scope ?? (kindProvided ? defaultScope(workspaceRoot) : await promptText("npm scope for the published package", defaultScope(workspaceRoot)));
|
|
2197
2537
|
runNx(
|
|
@@ -2208,18 +2548,18 @@ async function addNpmLib(workspaceRoot, name, options, kindProvided, stack) {
|
|
|
2208
2548
|
],
|
|
2209
2549
|
workspaceRoot
|
|
2210
2550
|
);
|
|
2211
|
-
const manifestPath = (0,
|
|
2551
|
+
const manifestPath = (0, import_node_path8.join)(workspaceRoot, "packages", name, "package.json");
|
|
2212
2552
|
markPublic(manifestPath);
|
|
2213
2553
|
repairPublishableManifest(manifestPath);
|
|
2214
|
-
repairDeclarationSpecifiers((0,
|
|
2215
|
-
writeProjectReadme((0,
|
|
2554
|
+
repairDeclarationSpecifiers((0, import_node_path8.join)(workspaceRoot, `packages/${name}`));
|
|
2555
|
+
writeProjectReadme((0, import_node_path8.join)(workspaceRoot, `packages/${name}`), `${scope}/${name}`, stack.testRunner);
|
|
2216
2556
|
removeGeneratedEslintConfig(workspaceRoot, `packages/${name}`);
|
|
2217
2557
|
registerProjectCommands(workspaceRoot, name, { build: true });
|
|
2218
2558
|
}
|
|
2219
2559
|
|
|
2220
2560
|
// src/commands/add/python.ts
|
|
2221
|
-
var
|
|
2222
|
-
var
|
|
2561
|
+
var import_node_fs6 = require("fs");
|
|
2562
|
+
var import_node_path9 = require("path");
|
|
2223
2563
|
function ensurePython(workspaceRoot) {
|
|
2224
2564
|
const hasPython = runShell("python3", ["--version"], workspaceRoot) === 0 || runShell("python", ["--version"], workspaceRoot) === 0;
|
|
2225
2565
|
if (!hasPython) {
|
|
@@ -2248,7 +2588,7 @@ pytest
|
|
|
2248
2588
|
pip-audit
|
|
2249
2589
|
`;
|
|
2250
2590
|
function ensureRequirementsDev(workspaceRoot) {
|
|
2251
|
-
const requirementsDevPath = (0,
|
|
2591
|
+
const requirementsDevPath = (0, import_node_path9.join)(workspaceRoot, "requirements-dev.txt");
|
|
2252
2592
|
if (!fileExists(requirementsDevPath)) {
|
|
2253
2593
|
writeFileEnsured(requirementsDevPath, PYTHON_REQUIREMENTS_DEV);
|
|
2254
2594
|
}
|
|
@@ -2256,11 +2596,6 @@ function ensureRequirementsDev(workspaceRoot) {
|
|
|
2256
2596
|
function pythonModuleDirectory(name) {
|
|
2257
2597
|
return name.replaceAll("-", "_");
|
|
2258
2598
|
}
|
|
2259
|
-
function addProjectJsonTargets3(projectJsonPath, newTargets) {
|
|
2260
|
-
const project = readJson(projectJsonPath);
|
|
2261
|
-
const targets = project.targets ?? {};
|
|
2262
|
-
writeFileEnsured(projectJsonPath, toJson({ ...project, targets: { ...targets, ...newTargets } }));
|
|
2263
|
-
}
|
|
2264
2599
|
function pythonAppMain(name) {
|
|
2265
2600
|
return `def main() -> None:
|
|
2266
2601
|
print('${name} is running')
|
|
@@ -2313,8 +2648,8 @@ function addPythonApp(workspaceRoot, name) {
|
|
|
2313
2648
|
["g", "@mnci/nx-python-pip:application", name, `--directory=apps/${name}`, "--no-interactive"],
|
|
2314
2649
|
workspaceRoot
|
|
2315
2650
|
);
|
|
2316
|
-
writeFileEnsured((0,
|
|
2317
|
-
|
|
2651
|
+
writeFileEnsured((0, import_node_path9.join)(workspaceRoot, "apps", name, "main.py"), pythonAppMain(name));
|
|
2652
|
+
addProjectJsonTargets((0, import_node_path9.join)(workspaceRoot, "apps", name, "project.json"), {
|
|
2318
2653
|
package: pythonAppPackageTarget(name),
|
|
2319
2654
|
start: pythonAppStartTarget(name)
|
|
2320
2655
|
});
|
|
@@ -2336,7 +2671,7 @@ function addPythonFunctionApp(workspaceRoot, name) {
|
|
|
2336
2671
|
workspaceRoot
|
|
2337
2672
|
);
|
|
2338
2673
|
const moduleDirectory = pythonModuleDirectory(name);
|
|
2339
|
-
|
|
2674
|
+
addProjectJsonTargets((0, import_node_path9.join)(workspaceRoot, "apps", name, "project.json"), {
|
|
2340
2675
|
package: pythonFunctionAppPackageTarget(name, moduleDirectory),
|
|
2341
2676
|
start: pythonFunctionAppStartTarget(name)
|
|
2342
2677
|
});
|
|
@@ -2377,7 +2712,7 @@ function addPythonInternalLib(workspaceRoot, name) {
|
|
|
2377
2712
|
var PYTHON_PROJECT_DIRS = ["apps", "python-packages", "libs"];
|
|
2378
2713
|
function findPythonProjectDirectory(workspaceRoot, name) {
|
|
2379
2714
|
return PYTHON_PROJECT_DIRS.find(
|
|
2380
|
-
(directory) => fileExists((0,
|
|
2715
|
+
(directory) => fileExists((0, import_node_path9.join)(workspaceRoot, directory, name, "pyproject.toml"))
|
|
2381
2716
|
);
|
|
2382
2717
|
}
|
|
2383
2718
|
function parseVendorEntries(pyprojectToml) {
|
|
@@ -2416,7 +2751,7 @@ async function addPythonVendor(workspaceRoot, consumer, options, kindProvided) {
|
|
|
2416
2751
|
`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.`
|
|
2417
2752
|
);
|
|
2418
2753
|
}
|
|
2419
|
-
if (!fileExists((0,
|
|
2754
|
+
if (!fileExists((0, import_node_path9.join)(workspaceRoot, "libs", lib, "pyproject.toml"))) {
|
|
2420
2755
|
throw new Error(
|
|
2421
2756
|
`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.`
|
|
2422
2757
|
);
|
|
@@ -2424,8 +2759,8 @@ async function addPythonVendor(workspaceRoot, consumer, options, kindProvided) {
|
|
|
2424
2759
|
if (consumerDirectory === "libs" && consumer === lib) {
|
|
2425
2760
|
throw new Error(`'${consumer}' cannot vendor itself.`);
|
|
2426
2761
|
}
|
|
2427
|
-
const pyprojectPath = (0,
|
|
2428
|
-
const pyprojectToml = (0,
|
|
2762
|
+
const pyprojectPath = (0, import_node_path9.join)(workspaceRoot, consumerDirectory, consumer, "pyproject.toml");
|
|
2763
|
+
const pyprojectToml = (0, import_node_fs6.readFileSync)(pyprojectPath, "utf8");
|
|
2429
2764
|
if (parseVendorEntries(pyprojectToml).includes(lib)) {
|
|
2430
2765
|
logger.info(`'${consumer}' already vendors '${lib}' \u2014 nothing to do.`);
|
|
2431
2766
|
return;
|
|
@@ -2437,8 +2772,8 @@ async function addPythonVendor(workspaceRoot, consumer, options, kindProvided) {
|
|
|
2437
2772
|
}
|
|
2438
2773
|
|
|
2439
2774
|
// src/commands/add/reactApp.ts
|
|
2440
|
-
var
|
|
2441
|
-
var
|
|
2775
|
+
var import_node_fs7 = require("fs");
|
|
2776
|
+
var import_node_path10 = require("path");
|
|
2442
2777
|
var REACT_ENVIRONMENTS = ["dev", "uat", "prod"];
|
|
2443
2778
|
function reactEnvironmentFile(environment) {
|
|
2444
2779
|
return `# Vite compiles VITE_-prefixed vars into the '${environment}' bundle at build time.
|
|
@@ -2475,12 +2810,12 @@ function reactAppTargets(name) {
|
|
|
2475
2810
|
return targets;
|
|
2476
2811
|
}
|
|
2477
2812
|
function allowEnvFiles(workspaceRoot) {
|
|
2478
|
-
const gitignorePath = (0,
|
|
2813
|
+
const gitignorePath = (0, import_node_path10.join)(workspaceRoot, ".gitignore");
|
|
2479
2814
|
if (!fileExists(gitignorePath)) {
|
|
2480
2815
|
return;
|
|
2481
2816
|
}
|
|
2482
2817
|
const marker = "# MoNecromanCI: keep the committed per-environment Vite config (public VITE_ values)";
|
|
2483
|
-
const current = (0,
|
|
2818
|
+
const current = (0, import_node_fs7.readFileSync)(gitignorePath, "utf8");
|
|
2484
2819
|
if (current.includes(marker)) {
|
|
2485
2820
|
return;
|
|
2486
2821
|
}
|
|
@@ -2507,18 +2842,18 @@ function addReactApp(workspaceRoot, name, stack) {
|
|
|
2507
2842
|
workspaceRoot
|
|
2508
2843
|
);
|
|
2509
2844
|
ensureAdmZip(workspaceRoot);
|
|
2510
|
-
const reactAppRoot = (0,
|
|
2845
|
+
const reactAppRoot = (0, import_node_path10.join)(workspaceRoot, "apps", name);
|
|
2511
2846
|
for (const environment of REACT_ENVIRONMENTS) {
|
|
2512
|
-
writeFileEnsured((0,
|
|
2847
|
+
writeFileEnsured((0, import_node_path10.join)(reactAppRoot, `.env.${environment}`), reactEnvironmentFile(environment));
|
|
2513
2848
|
}
|
|
2514
2849
|
allowEnvFiles(workspaceRoot);
|
|
2515
|
-
addNxTargets((0,
|
|
2850
|
+
addNxTargets((0, import_node_path10.join)(reactAppRoot, "package.json"), reactAppTargets(name));
|
|
2516
2851
|
removeGeneratedEslintConfig(workspaceRoot, `apps/${name}`);
|
|
2517
2852
|
registerProjectCommands(workspaceRoot, name, { build: true, start: `nx run ${name}:serve` });
|
|
2518
2853
|
}
|
|
2519
2854
|
|
|
2520
2855
|
// src/commands/add/reactLib.ts
|
|
2521
|
-
var
|
|
2856
|
+
var import_node_path11 = require("path");
|
|
2522
2857
|
var REACT_LIB_BUNDLER = "rollup";
|
|
2523
2858
|
async function addReactLib(workspaceRoot, name, options, kindProvided, stack) {
|
|
2524
2859
|
ensurePlugin(workspaceRoot, "@nx/react");
|
|
@@ -2538,11 +2873,11 @@ async function addReactLib(workspaceRoot, name, options, kindProvided, stack) {
|
|
|
2538
2873
|
],
|
|
2539
2874
|
workspaceRoot
|
|
2540
2875
|
);
|
|
2541
|
-
const publishableManifest = (0,
|
|
2876
|
+
const publishableManifest = (0, import_node_path11.join)(workspaceRoot, "packages", name, "package.json");
|
|
2542
2877
|
markPublic(publishableManifest);
|
|
2543
2878
|
repairPublishableManifest(publishableManifest);
|
|
2544
|
-
repairDeclarationSpecifiers((0,
|
|
2545
|
-
writeProjectReadme((0,
|
|
2879
|
+
repairDeclarationSpecifiers((0, import_node_path11.join)(workspaceRoot, "packages", name));
|
|
2880
|
+
writeProjectReadme((0, import_node_path11.join)(workspaceRoot, "packages", name), `${scope}/${name}`, stack.testRunner);
|
|
2546
2881
|
removeGeneratedEslintConfig(workspaceRoot, `packages/${name}`);
|
|
2547
2882
|
registerProjectCommands(workspaceRoot, name, { build: true });
|
|
2548
2883
|
}
|
|
@@ -2561,22 +2896,22 @@ function addReactInternalLib(workspaceRoot, name, stack) {
|
|
|
2561
2896
|
],
|
|
2562
2897
|
workspaceRoot
|
|
2563
2898
|
);
|
|
2564
|
-
const privateManifest = (0,
|
|
2899
|
+
const privateManifest = (0, import_node_path11.join)(workspaceRoot, "libs", name, "package.json");
|
|
2565
2900
|
markPrivate(privateManifest);
|
|
2566
2901
|
repairPublishableManifest(privateManifest);
|
|
2567
|
-
repairDeclarationSpecifiers((0,
|
|
2568
|
-
writeProjectReadme((0,
|
|
2902
|
+
repairDeclarationSpecifiers((0, import_node_path11.join)(workspaceRoot, "libs", name));
|
|
2903
|
+
writeProjectReadme((0, import_node_path11.join)(workspaceRoot, "libs", name), name, stack.testRunner);
|
|
2569
2904
|
removeGeneratedEslintConfig(workspaceRoot, `libs/${name}`);
|
|
2570
2905
|
registerProjectCommands(workspaceRoot, name, { build: true });
|
|
2571
2906
|
}
|
|
2572
2907
|
|
|
2573
2908
|
// src/commands/sync.ts
|
|
2574
|
-
var
|
|
2909
|
+
var import_node_path13 = require("path");
|
|
2575
2910
|
|
|
2576
2911
|
// src/deps/inventory.ts
|
|
2577
|
-
var
|
|
2578
|
-
var
|
|
2579
|
-
var ECOSYSTEMS = ["npm", "pip", "pub", "go"];
|
|
2912
|
+
var import_node_fs8 = require("fs");
|
|
2913
|
+
var import_node_path12 = require("path");
|
|
2914
|
+
var ECOSYSTEMS = ["npm", "pip", "pub", "nuget", "go"];
|
|
2580
2915
|
var ROOT_LABEL = "(root)";
|
|
2581
2916
|
var MANIFEST_GLOBS = {
|
|
2582
2917
|
// `libs/*` carries private internal libs; `packages/*` the publishable ones.
|
|
@@ -2584,6 +2919,10 @@ var MANIFEST_GLOBS = {
|
|
|
2584
2919
|
// Matches PYTHON_PROJECT_DIRS in commands/add/python.ts.
|
|
2585
2920
|
pip: ["apps/*/pyproject.toml", "python-packages/*/pyproject.toml", "libs/*/pyproject.toml"],
|
|
2586
2921
|
pub: ["apps/*/pubspec.yaml", "packages/*/pubspec.yaml", "libs/*/pubspec.yaml"],
|
|
2922
|
+
// Unlike every other ecosystem, the filename itself varies (the project's own
|
|
2923
|
+
// PascalCase identity, not a fixed name) — the same three roots
|
|
2924
|
+
// PACK_APPS_GUARD and add/csharp.ts already scan.
|
|
2925
|
+
nuget: ["apps/*/*.csproj", "packages/*/*.csproj", "libs/*/*.csproj"],
|
|
2587
2926
|
// Single root module by design — there are no per-project Go manifests.
|
|
2588
2927
|
go: []
|
|
2589
2928
|
};
|
|
@@ -2604,20 +2943,23 @@ function projectOf(manifestRelativePath) {
|
|
|
2604
2943
|
}
|
|
2605
2944
|
function hasEcosystem(workspaceRoot, ecosystem) {
|
|
2606
2945
|
if (ecosystem === "go") {
|
|
2607
|
-
return fileExists((0,
|
|
2946
|
+
return fileExists((0, import_node_path12.join)(workspaceRoot, "go.mod"));
|
|
2947
|
+
}
|
|
2948
|
+
if (ecosystem === "nuget") {
|
|
2949
|
+
return (0, import_node_fs8.globSync)(MANIFEST_GLOBS.nuget, { cwd: workspaceRoot }).length > 0;
|
|
2608
2950
|
}
|
|
2609
2951
|
const rootMarker = {
|
|
2610
2952
|
npm: "package.json",
|
|
2611
2953
|
pip: "requirements-dev.txt",
|
|
2612
2954
|
pub: "pubspec.yaml"
|
|
2613
2955
|
};
|
|
2614
|
-
return fileExists((0,
|
|
2956
|
+
return fileExists((0, import_node_path12.join)(workspaceRoot, rootMarker[ecosystem])) || (0, import_node_fs8.globSync)(MANIFEST_GLOBS[ecosystem], { cwd: workspaceRoot }).length > 0;
|
|
2615
2957
|
}
|
|
2616
2958
|
function collectNpm(workspaceRoot) {
|
|
2617
2959
|
const sites = [];
|
|
2618
|
-
const relativePaths = ["package.json", ...(0,
|
|
2960
|
+
const relativePaths = ["package.json", ...(0, import_node_fs8.globSync)(MANIFEST_GLOBS.npm, { cwd: workspaceRoot })];
|
|
2619
2961
|
for (const relativePath of relativePaths) {
|
|
2620
|
-
const manifestPath = (0,
|
|
2962
|
+
const manifestPath = (0, import_node_path12.join)(workspaceRoot, relativePath);
|
|
2621
2963
|
try {
|
|
2622
2964
|
const manifest = readJson(manifestPath);
|
|
2623
2965
|
sites.push(...npmManifestSites(manifest, relativePath, manifestPath));
|
|
@@ -2678,17 +3020,17 @@ function collectPip(workspaceRoot) {
|
|
|
2678
3020
|
name: parsed.name,
|
|
2679
3021
|
ecosystem: "pip",
|
|
2680
3022
|
project: projectOf(relativePath),
|
|
2681
|
-
manifestPath: (0,
|
|
3023
|
+
manifestPath: (0, import_node_path12.join)(workspaceRoot, relativePath),
|
|
2682
3024
|
section,
|
|
2683
3025
|
spec: parsed.spec,
|
|
2684
3026
|
rewritable: parsed.rewritable && parsed.spec !== ""
|
|
2685
3027
|
});
|
|
2686
3028
|
};
|
|
2687
|
-
const pyprojectPaths = (0,
|
|
3029
|
+
const pyprojectPaths = (0, import_node_fs8.globSync)(MANIFEST_GLOBS.pip, { cwd: workspaceRoot });
|
|
2688
3030
|
for (const relativePath of pyprojectPaths) {
|
|
2689
3031
|
let content;
|
|
2690
3032
|
try {
|
|
2691
|
-
content = (0,
|
|
3033
|
+
content = (0, import_node_fs8.readFileSync)((0, import_node_path12.join)(workspaceRoot, relativePath), "utf8");
|
|
2692
3034
|
} catch {
|
|
2693
3035
|
continue;
|
|
2694
3036
|
}
|
|
@@ -2699,14 +3041,14 @@ function collectPip(workspaceRoot) {
|
|
|
2699
3041
|
}
|
|
2700
3042
|
const requirementsPaths = [
|
|
2701
3043
|
"requirements-dev.txt",
|
|
2702
|
-
...(0,
|
|
3044
|
+
...(0, import_node_fs8.globSync)("apps/*/requirements.txt", { cwd: workspaceRoot })
|
|
2703
3045
|
];
|
|
2704
3046
|
for (const relativePath of requirementsPaths) {
|
|
2705
|
-
if (!fileExists((0,
|
|
3047
|
+
if (!fileExists((0, import_node_path12.join)(workspaceRoot, relativePath))) {
|
|
2706
3048
|
continue;
|
|
2707
3049
|
}
|
|
2708
3050
|
const section = relativePath === "requirements-dev.txt" ? "devDep" : "dep";
|
|
2709
|
-
const lines = (0,
|
|
3051
|
+
const lines = (0, import_node_fs8.readFileSync)((0, import_node_path12.join)(workspaceRoot, relativePath), "utf8").split(/\r?\n/);
|
|
2710
3052
|
for (const line of lines) {
|
|
2711
3053
|
push(relativePath, section, line);
|
|
2712
3054
|
}
|
|
@@ -2744,11 +3086,11 @@ function pyprojectDependencies(content) {
|
|
|
2744
3086
|
}
|
|
2745
3087
|
function collectPub(workspaceRoot) {
|
|
2746
3088
|
const sites = [];
|
|
2747
|
-
const pubspecPaths = (0,
|
|
3089
|
+
const pubspecPaths = (0, import_node_fs8.globSync)(MANIFEST_GLOBS.pub, { cwd: workspaceRoot });
|
|
2748
3090
|
for (const relativePath of pubspecPaths) {
|
|
2749
3091
|
let content;
|
|
2750
3092
|
try {
|
|
2751
|
-
content = (0,
|
|
3093
|
+
content = (0, import_node_fs8.readFileSync)((0, import_node_path12.join)(workspaceRoot, relativePath), "utf8");
|
|
2752
3094
|
} catch {
|
|
2753
3095
|
continue;
|
|
2754
3096
|
}
|
|
@@ -2758,7 +3100,7 @@ function collectPub(workspaceRoot) {
|
|
|
2758
3100
|
name: entry.name,
|
|
2759
3101
|
ecosystem: "pub",
|
|
2760
3102
|
project: projectOf(relativePath),
|
|
2761
|
-
manifestPath: (0,
|
|
3103
|
+
manifestPath: (0, import_node_path12.join)(workspaceRoot, relativePath),
|
|
2762
3104
|
section: block === "dependencies" ? "dep" : "devDep",
|
|
2763
3105
|
spec: entry.spec,
|
|
2764
3106
|
rewritable: entry.spec !== ""
|
|
@@ -2806,14 +3148,53 @@ function pubspecBlockEntries(content, block) {
|
|
|
2806
3148
|
function stripQuotes(value) {
|
|
2807
3149
|
return /^(['"]).*\1$/.test(value) ? value.slice(1, -1) : value;
|
|
2808
3150
|
}
|
|
3151
|
+
function collectNuget(workspaceRoot) {
|
|
3152
|
+
const sites = [];
|
|
3153
|
+
const csprojPaths = (0, import_node_fs8.globSync)(MANIFEST_GLOBS.nuget, { cwd: workspaceRoot });
|
|
3154
|
+
for (const relativePath of csprojPaths) {
|
|
3155
|
+
let content;
|
|
3156
|
+
try {
|
|
3157
|
+
content = (0, import_node_fs8.readFileSync)((0, import_node_path12.join)(workspaceRoot, relativePath), "utf8");
|
|
3158
|
+
} catch {
|
|
3159
|
+
continue;
|
|
3160
|
+
}
|
|
3161
|
+
for (const entry of csprojPackageReferences(content)) {
|
|
3162
|
+
sites.push({
|
|
3163
|
+
name: entry.name,
|
|
3164
|
+
ecosystem: "nuget",
|
|
3165
|
+
project: projectOf(relativePath),
|
|
3166
|
+
manifestPath: (0, import_node_path12.join)(workspaceRoot, relativePath),
|
|
3167
|
+
section: "dep",
|
|
3168
|
+
spec: entry.spec,
|
|
3169
|
+
// A plain SemVer string is rewritable; an MSBuild property reference
|
|
3170
|
+
// ($(SharedVersion)) or an interval-notation range ([1.0,2.0)) is
|
|
3171
|
+
// reported only — neither is a version this can safely overwrite.
|
|
3172
|
+
rewritable: /^\d/.test(entry.spec)
|
|
3173
|
+
});
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
3176
|
+
return sites;
|
|
3177
|
+
}
|
|
3178
|
+
function csprojPackageReferences(content) {
|
|
3179
|
+
const entries = [];
|
|
3180
|
+
for (const tag of content.matchAll(/<PackageReference([^>]*)\/>/g)) {
|
|
3181
|
+
const attributes = tag[1];
|
|
3182
|
+
const name = /\bInclude\s*=\s*"([^"]*)"/.exec(attributes)?.[1];
|
|
3183
|
+
const spec = /\bVersion\s*=\s*"([^"]*)"/.exec(attributes)?.[1];
|
|
3184
|
+
if (name && spec) {
|
|
3185
|
+
entries.push({ name, spec });
|
|
3186
|
+
}
|
|
3187
|
+
}
|
|
3188
|
+
return entries;
|
|
3189
|
+
}
|
|
2809
3190
|
function collectGo(workspaceRoot) {
|
|
2810
|
-
const manifestPath = (0,
|
|
3191
|
+
const manifestPath = (0, import_node_path12.join)(workspaceRoot, "go.mod");
|
|
2811
3192
|
if (!fileExists(manifestPath)) {
|
|
2812
3193
|
return [];
|
|
2813
3194
|
}
|
|
2814
3195
|
let content;
|
|
2815
3196
|
try {
|
|
2816
|
-
content = (0,
|
|
3197
|
+
content = (0, import_node_fs8.readFileSync)(manifestPath, "utf8");
|
|
2817
3198
|
} catch {
|
|
2818
3199
|
return [];
|
|
2819
3200
|
}
|
|
@@ -2835,6 +3216,7 @@ function collectInventory(workspaceRoot, ecosystems = ECOSYSTEMS) {
|
|
|
2835
3216
|
npm: collectNpm,
|
|
2836
3217
|
pip: collectPip,
|
|
2837
3218
|
pub: collectPub,
|
|
3219
|
+
nuget: collectNuget,
|
|
2838
3220
|
go: collectGo
|
|
2839
3221
|
};
|
|
2840
3222
|
const inventory = /* @__PURE__ */ new Map();
|
|
@@ -2869,8 +3251,27 @@ function rewriteSpec(site, spec) {
|
|
|
2869
3251
|
writeFileEnsured(site.manifestPath, toJson(manifest));
|
|
2870
3252
|
return true;
|
|
2871
3253
|
}
|
|
2872
|
-
const before = (0,
|
|
2873
|
-
const after =
|
|
3254
|
+
const before = (0, import_node_fs8.readFileSync)(site.manifestPath, "utf8");
|
|
3255
|
+
const after = (() => {
|
|
3256
|
+
switch (site.ecosystem) {
|
|
3257
|
+
case "pip": {
|
|
3258
|
+
return replacePipSpec(before, name, spec);
|
|
3259
|
+
}
|
|
3260
|
+
case "pub": {
|
|
3261
|
+
return replacePubSpec(before, name, spec);
|
|
3262
|
+
}
|
|
3263
|
+
case "nuget": {
|
|
3264
|
+
return replaceNugetSpec(before, name, spec);
|
|
3265
|
+
}
|
|
3266
|
+
// 'go' entries are never rewritable (see collectGo), so this is
|
|
3267
|
+
// unreachable in practice — returning the text unchanged is the safe
|
|
3268
|
+
// no-op if that invariant is ever broken, rather than guessing at a
|
|
3269
|
+
// rewrite for a format this branch was never meant to handle.
|
|
3270
|
+
default: {
|
|
3271
|
+
return before;
|
|
3272
|
+
}
|
|
3273
|
+
}
|
|
3274
|
+
})();
|
|
2874
3275
|
if (after === before) {
|
|
2875
3276
|
return false;
|
|
2876
3277
|
}
|
|
@@ -2890,19 +3291,29 @@ function replacePubSpec(content, name, spec) {
|
|
|
2890
3291
|
(match, lead) => `${lead}${spec}`
|
|
2891
3292
|
);
|
|
2892
3293
|
}
|
|
3294
|
+
function replaceNugetSpec(content, name, spec) {
|
|
3295
|
+
const escaped = escapeForRegex(name);
|
|
3296
|
+
const includePattern = new RegExp(String.raw`\bInclude\s*=\s*"${escaped}"`);
|
|
3297
|
+
return content.replaceAll(/<PackageReference([^>]*)\/>/g, (tag, attributes) => {
|
|
3298
|
+
if (!includePattern.test(attributes)) {
|
|
3299
|
+
return tag;
|
|
3300
|
+
}
|
|
3301
|
+
return tag.replace(/\bVersion\s*=\s*"[^"]*"/, () => `Version="${spec}"`);
|
|
3302
|
+
});
|
|
3303
|
+
}
|
|
2893
3304
|
function escapeForRegex(value) {
|
|
2894
3305
|
return value.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
|
|
2895
3306
|
}
|
|
2896
3307
|
function isWorkspaceProject(workspaceRoot, name) {
|
|
2897
3308
|
const short = name.includes("/") ? name.split("/").at(-1) : name;
|
|
2898
3309
|
return ["apps", "libs", "packages"].some(
|
|
2899
|
-
(directory) => fileExists((0,
|
|
3310
|
+
(directory) => fileExists((0, import_node_path12.join)(workspaceRoot, directory, short ?? name, "package.json"))
|
|
2900
3311
|
);
|
|
2901
3312
|
}
|
|
2902
3313
|
function isAliasedInstall(workspaceRoot, name) {
|
|
2903
3314
|
try {
|
|
2904
3315
|
const installed = readJson(
|
|
2905
|
-
(0,
|
|
3316
|
+
(0, import_node_path12.join)(workspaceRoot, "node_modules", name, "package.json")
|
|
2906
3317
|
);
|
|
2907
3318
|
return installed.name !== void 0 && installed.name !== name;
|
|
2908
3319
|
} catch {
|
|
@@ -2913,14 +3324,14 @@ function resolvedVersion(workspaceRoot, ecosystem, name) {
|
|
|
2913
3324
|
if (ecosystem === "npm") {
|
|
2914
3325
|
try {
|
|
2915
3326
|
return readJson(
|
|
2916
|
-
(0,
|
|
3327
|
+
(0, import_node_path12.join)(workspaceRoot, "node_modules", name, "package.json")
|
|
2917
3328
|
).version;
|
|
2918
3329
|
} catch {
|
|
2919
3330
|
return void 0;
|
|
2920
3331
|
}
|
|
2921
3332
|
}
|
|
2922
3333
|
if (ecosystem === "pub") {
|
|
2923
|
-
const lockPath = (0,
|
|
3334
|
+
const lockPath = (0, import_node_path12.join)(workspaceRoot, "pubspec.lock");
|
|
2924
3335
|
if (!fileExists(lockPath)) {
|
|
2925
3336
|
return void 0;
|
|
2926
3337
|
}
|
|
@@ -2928,7 +3339,7 @@ function resolvedVersion(workspaceRoot, ecosystem, name) {
|
|
|
2928
3339
|
const match = new RegExp(
|
|
2929
3340
|
String.raw`^\s{2}${escapeForRegex(name)}:[^]*?^\s+version:\s*["']?([^"'\s]+)`,
|
|
2930
3341
|
"m"
|
|
2931
|
-
).exec((0,
|
|
3342
|
+
).exec((0, import_node_fs8.readFileSync)(lockPath, "utf8"));
|
|
2932
3343
|
return match?.[1];
|
|
2933
3344
|
} catch {
|
|
2934
3345
|
return void 0;
|
|
@@ -3120,7 +3531,7 @@ function describe(finding) {
|
|
|
3120
3531
|
return `${finding.name} \u2192 ${finding.target} (${finding.reason}); disagreeing: ${sites}`;
|
|
3121
3532
|
}
|
|
3122
3533
|
function runSync(workspaceRoot, options) {
|
|
3123
|
-
if (!fileExists((0,
|
|
3534
|
+
if (!fileExists((0, import_node_path13.join)(workspaceRoot, "nx.json"))) {
|
|
3124
3535
|
throw new Error(
|
|
3125
3536
|
`No nx.json found in ${workspaceRoot} \u2014 run 'mnci sync' from the workspace root.`
|
|
3126
3537
|
);
|
|
@@ -3189,16 +3600,20 @@ var PROJECT_KINDS = [
|
|
|
3189
3600
|
"go-internal-lib",
|
|
3190
3601
|
"flutter-app",
|
|
3191
3602
|
"flutter-lib",
|
|
3192
|
-
"flutter-internal-lib"
|
|
3603
|
+
"flutter-internal-lib",
|
|
3604
|
+
"csharp-app",
|
|
3605
|
+
"csharp-function-app",
|
|
3606
|
+
"csharp-lib",
|
|
3607
|
+
"csharp-internal-lib"
|
|
3193
3608
|
];
|
|
3194
3609
|
async function runAdd(kind, name, options) {
|
|
3195
3610
|
const workspaceRoot = process.cwd();
|
|
3196
|
-
if (!fileExists((0,
|
|
3611
|
+
if (!fileExists((0, import_node_path14.join)(workspaceRoot, "nx.json"))) {
|
|
3197
3612
|
throw new Error("No nx.json found here. Run `add` from the workspace root.");
|
|
3198
3613
|
}
|
|
3199
3614
|
const stack = readWorkspaceStack(workspaceRoot);
|
|
3200
3615
|
const kindProvided = kind !== void 0;
|
|
3201
|
-
const resolvedKind = kind ?? await (0,
|
|
3616
|
+
const resolvedKind = kind ?? await (0, import_prompts6.select)({
|
|
3202
3617
|
message: "What kind of project?",
|
|
3203
3618
|
choices: PROJECT_KINDS.map((value) => ({ name: value, value }))
|
|
3204
3619
|
});
|
|
@@ -3243,7 +3658,7 @@ async function runAdd(kind, name, options) {
|
|
|
3243
3658
|
],
|
|
3244
3659
|
workspaceRoot
|
|
3245
3660
|
);
|
|
3246
|
-
markPrivate((0,
|
|
3661
|
+
markPrivate((0, import_node_path14.join)(workspaceRoot, "libs", resolvedName, "package.json"));
|
|
3247
3662
|
removeGeneratedEslintConfig(workspaceRoot, `libs/${resolvedName}`);
|
|
3248
3663
|
registerProjectCommands(workspaceRoot, resolvedName, { build: true });
|
|
3249
3664
|
break;
|
|
@@ -3292,6 +3707,22 @@ async function runAdd(kind, name, options) {
|
|
|
3292
3707
|
addFlutterInternalLib(workspaceRoot, resolvedName);
|
|
3293
3708
|
break;
|
|
3294
3709
|
}
|
|
3710
|
+
case "csharp-app": {
|
|
3711
|
+
addCsharpApp(workspaceRoot, resolvedName);
|
|
3712
|
+
break;
|
|
3713
|
+
}
|
|
3714
|
+
case "csharp-function-app": {
|
|
3715
|
+
addCsharpFunctionApp(workspaceRoot, resolvedName);
|
|
3716
|
+
break;
|
|
3717
|
+
}
|
|
3718
|
+
case "csharp-lib": {
|
|
3719
|
+
await addCsharpLib(workspaceRoot, resolvedName, options, kindProvided);
|
|
3720
|
+
break;
|
|
3721
|
+
}
|
|
3722
|
+
case "csharp-internal-lib": {
|
|
3723
|
+
addCsharpInternalLib(workspaceRoot, resolvedName);
|
|
3724
|
+
break;
|
|
3725
|
+
}
|
|
3295
3726
|
case "python-vendor": {
|
|
3296
3727
|
await addPythonVendor(workspaceRoot, resolvedName, options, kindProvided);
|
|
3297
3728
|
syncProjectReferences(workspaceRoot);
|
|
@@ -3312,7 +3743,7 @@ async function runAdd(kind, name, options) {
|
|
|
3312
3743
|
}
|
|
3313
3744
|
function readWorkspaceStack(workspaceRoot) {
|
|
3314
3745
|
const nxJson = readJson(
|
|
3315
|
-
(0,
|
|
3746
|
+
(0, import_node_path14.join)(workspaceRoot, "nx.json")
|
|
3316
3747
|
);
|
|
3317
3748
|
const stack = nxJson.mnci?.stack;
|
|
3318
3749
|
return {
|
|
@@ -3321,15 +3752,15 @@ function readWorkspaceStack(workspaceRoot) {
|
|
|
3321
3752
|
}
|
|
3322
3753
|
|
|
3323
3754
|
// src/commands/doctor.ts
|
|
3324
|
-
var
|
|
3325
|
-
var
|
|
3755
|
+
var import_node_fs9 = require("fs");
|
|
3756
|
+
var import_node_path15 = require("path");
|
|
3326
3757
|
var SUPPORTED_ESLINT_MAJOR = ESLINT_VERSION.replace(/^\D*/, "").split(".", 1)[0];
|
|
3327
3758
|
function toPosix2(path) {
|
|
3328
3759
|
return path.replaceAll("\\", "/");
|
|
3329
3760
|
}
|
|
3330
3761
|
function checkEslintConfigs(workspaceRoot) {
|
|
3331
|
-
const rootConfigs = (0,
|
|
3332
|
-
const projectConfigs = (0,
|
|
3762
|
+
const rootConfigs = (0, import_node_fs9.globSync)("eslint.config.{js,mjs,cjs,ts,mts,cts}", { cwd: workspaceRoot });
|
|
3763
|
+
const projectConfigs = (0, import_node_fs9.globSync)("{apps,libs,packages}/*/eslint.config.{js,mjs,cjs,ts,mts,cts}", {
|
|
3333
3764
|
cwd: workspaceRoot
|
|
3334
3765
|
}).map((config) => toPosix2(config));
|
|
3335
3766
|
return [
|
|
@@ -3350,7 +3781,7 @@ function checkEslintConfigs(workspaceRoot) {
|
|
|
3350
3781
|
function declaredDevDependencies(workspaceRoot) {
|
|
3351
3782
|
try {
|
|
3352
3783
|
const manifest = readJson(
|
|
3353
|
-
(0,
|
|
3784
|
+
(0, import_node_path15.join)(workspaceRoot, "package.json")
|
|
3354
3785
|
);
|
|
3355
3786
|
return manifest.devDependencies ?? {};
|
|
3356
3787
|
} catch {
|
|
@@ -3358,7 +3789,7 @@ function declaredDevDependencies(workspaceRoot) {
|
|
|
3358
3789
|
}
|
|
3359
3790
|
}
|
|
3360
3791
|
function checkNoRetiredFormatter(workspaceRoot) {
|
|
3361
|
-
const files = RETIRED_FORMATTER_FILES.filter((file) => fileExists((0,
|
|
3792
|
+
const files = RETIRED_FORMATTER_FILES.filter((file) => fileExists((0, import_node_path15.join)(workspaceRoot, file)));
|
|
3362
3793
|
const declared = ["prettier", "eslint-config-prettier", "oxlint", "oxfmt", "@mnci/oxlint-config"].filter((name) => declaredDevDependencies(workspaceRoot)[name] !== void 0);
|
|
3363
3794
|
const stale = [...files, ...declared];
|
|
3364
3795
|
if (stale.length === 0) {
|
|
@@ -3384,7 +3815,7 @@ function checkEslintPlugin(nxJson) {
|
|
|
3384
3815
|
};
|
|
3385
3816
|
}
|
|
3386
3817
|
function checkResolvedEslint(workspaceRoot) {
|
|
3387
|
-
const manifestPath = (0,
|
|
3818
|
+
const manifestPath = (0, import_node_path15.join)(workspaceRoot, "node_modules/eslint/package.json");
|
|
3388
3819
|
if (!fileExists(manifestPath)) {
|
|
3389
3820
|
return void 0;
|
|
3390
3821
|
}
|
|
@@ -3402,11 +3833,11 @@ function checkResolvedEslint(workspaceRoot) {
|
|
|
3402
3833
|
}
|
|
3403
3834
|
}
|
|
3404
3835
|
function checkNpmrc(workspaceRoot, registry, scope) {
|
|
3405
|
-
const npmrcPath = (0,
|
|
3836
|
+
const npmrcPath = (0, import_node_path15.join)(workspaceRoot, ".npmrc");
|
|
3406
3837
|
if (!registry || !fileExists(npmrcPath)) {
|
|
3407
3838
|
return void 0;
|
|
3408
3839
|
}
|
|
3409
|
-
const npmrc = (0,
|
|
3840
|
+
const npmrc = (0, import_node_fs9.readFileSync)(npmrcPath, "utf8");
|
|
3410
3841
|
if (registry.kind === "npm") {
|
|
3411
3842
|
return {
|
|
3412
3843
|
check: ".npmrc authenticates the public registry",
|
|
@@ -3424,12 +3855,12 @@ function checkNpmrc(workspaceRoot, registry, scope) {
|
|
|
3424
3855
|
}
|
|
3425
3856
|
function checkVersionActions(workspaceRoot) {
|
|
3426
3857
|
const candidates = [
|
|
3427
|
-
...(0,
|
|
3428
|
-
...(0,
|
|
3858
|
+
...(0, import_node_fs9.globSync)("packages/*/pubspec.yaml", { cwd: workspaceRoot }),
|
|
3859
|
+
...(0, import_node_fs9.globSync)("python-packages/*/pyproject.toml", { cwd: workspaceRoot })
|
|
3429
3860
|
].map((manifest) => toPosix2(manifest));
|
|
3430
3861
|
return candidates.flatMap((manifest) => {
|
|
3431
3862
|
const projectRoot = manifest.slice(0, manifest.lastIndexOf("/"));
|
|
3432
|
-
const projectJsonPath = (0,
|
|
3863
|
+
const projectJsonPath = (0, import_node_path15.join)(workspaceRoot, projectRoot, "project.json");
|
|
3433
3864
|
let hasOverride = false;
|
|
3434
3865
|
try {
|
|
3435
3866
|
const projectJson = readJson(projectJsonPath);
|
|
@@ -3458,7 +3889,7 @@ function declaredTargets(workspaceRoot, projectRoot) {
|
|
|
3458
3889
|
]) {
|
|
3459
3890
|
try {
|
|
3460
3891
|
const targets = extract(
|
|
3461
|
-
readJson((0,
|
|
3892
|
+
readJson((0, import_node_path15.join)(workspaceRoot, projectRoot, file))
|
|
3462
3893
|
);
|
|
3463
3894
|
if (targets && typeof targets === "object") {
|
|
3464
3895
|
sources.push({
|
|
@@ -3474,8 +3905,8 @@ function declaredTargets(workspaceRoot, projectRoot) {
|
|
|
3474
3905
|
function checkTargetFilesExist(workspaceRoot) {
|
|
3475
3906
|
const projectRoots = new Set(
|
|
3476
3907
|
[
|
|
3477
|
-
...(0,
|
|
3478
|
-
...(0,
|
|
3908
|
+
...(0, import_node_fs9.globSync)("{apps,libs,packages}/*/project.json", { cwd: workspaceRoot }),
|
|
3909
|
+
...(0, import_node_fs9.globSync)("{apps,libs,packages}/*/package.json", { cwd: workspaceRoot })
|
|
3479
3910
|
].map((manifest) => toPosix2(manifest).split("/").slice(0, 2).join("/"))
|
|
3480
3911
|
);
|
|
3481
3912
|
return [...projectRoots].flatMap(
|
|
@@ -3490,7 +3921,7 @@ function checkOneTargetsFiles(workspaceRoot, source, targetName, target) {
|
|
|
3490
3921
|
return TARGET_FILE_OPTIONS.flatMap((option) => {
|
|
3491
3922
|
const value = target?.options?.[option];
|
|
3492
3923
|
const checkable = typeof value === "string" && !value.includes("{");
|
|
3493
|
-
if (!checkable || fileExists((0,
|
|
3924
|
+
if (!checkable || fileExists((0, import_node_path15.join)(workspaceRoot, value))) {
|
|
3494
3925
|
return [];
|
|
3495
3926
|
}
|
|
3496
3927
|
return [
|
|
@@ -3512,7 +3943,7 @@ function checkSync(workspaceRoot) {
|
|
|
3512
3943
|
};
|
|
3513
3944
|
}
|
|
3514
3945
|
function checkNoRootRuntimeDependencies(workspaceRoot) {
|
|
3515
|
-
const manifestPath = (0,
|
|
3946
|
+
const manifestPath = (0, import_node_path15.join)(workspaceRoot, "package.json");
|
|
3516
3947
|
if (!fileExists(manifestPath)) {
|
|
3517
3948
|
return void 0;
|
|
3518
3949
|
}
|
|
@@ -3532,14 +3963,14 @@ function checkNoRootRuntimeDependencies(workspaceRoot) {
|
|
|
3532
3963
|
};
|
|
3533
3964
|
}
|
|
3534
3965
|
function checkRollupSourceMaps(workspaceRoot) {
|
|
3535
|
-
const configs = (0,
|
|
3966
|
+
const configs = (0, import_node_fs9.globSync)(["packages/*/rollup.config.cjs", "libs/*/rollup.config.cjs"], {
|
|
3536
3967
|
cwd: workspaceRoot
|
|
3537
3968
|
}).map((config) => toPosix2(config));
|
|
3538
3969
|
return configs.flatMap((relativePath) => {
|
|
3539
|
-
const configPath = (0,
|
|
3970
|
+
const configPath = (0, import_node_path15.join)(workspaceRoot, relativePath);
|
|
3540
3971
|
let config;
|
|
3541
3972
|
try {
|
|
3542
|
-
config = (0,
|
|
3973
|
+
config = (0, import_node_fs9.readFileSync)(configPath, "utf8");
|
|
3543
3974
|
} catch {
|
|
3544
3975
|
return [];
|
|
3545
3976
|
}
|
|
@@ -3554,7 +3985,7 @@ function checkRollupSourceMaps(workspaceRoot) {
|
|
|
3554
3985
|
});
|
|
3555
3986
|
}
|
|
3556
3987
|
function collectFindings(workspaceRoot) {
|
|
3557
|
-
const nxJsonPath = (0,
|
|
3988
|
+
const nxJsonPath = (0, import_node_path15.join)(workspaceRoot, "nx.json");
|
|
3558
3989
|
if (!fileExists(nxJsonPath)) {
|
|
3559
3990
|
throw new Error(
|
|
3560
3991
|
`No nx.json found in ${workspaceRoot} \u2014 run 'mnci doctor' from the workspace root.`
|
|
@@ -3596,12 +4027,12 @@ function runDoctor(workspaceRoot) {
|
|
|
3596
4027
|
}
|
|
3597
4028
|
|
|
3598
4029
|
// src/commands/interactive.ts
|
|
3599
|
-
var
|
|
3600
|
-
var
|
|
4030
|
+
var import_node_path18 = require("path");
|
|
4031
|
+
var import_prompts9 = require("@inquirer/prompts");
|
|
3601
4032
|
|
|
3602
4033
|
// src/commands/new.ts
|
|
3603
|
-
var
|
|
3604
|
-
var
|
|
4034
|
+
var import_node_fs10 = require("fs");
|
|
4035
|
+
var import_node_path16 = require("path");
|
|
3605
4036
|
function nxCloudProviderValue(ci) {
|
|
3606
4037
|
return ci === "azure" ? "azure" : "github";
|
|
3607
4038
|
}
|
|
@@ -3662,7 +4093,7 @@ async function runNew(name, options) {
|
|
|
3662
4093
|
],
|
|
3663
4094
|
process.cwd()
|
|
3664
4095
|
);
|
|
3665
|
-
const workspaceRoot = (0,
|
|
4096
|
+
const workspaceRoot = (0, import_node_path16.join)(process.cwd(), workspaceName);
|
|
3666
4097
|
logger.step(
|
|
3667
4098
|
"Applying MoNecromanCI overlay (VS Code workspace, release config, .npmrc, commitlint, pipeline, stack)"
|
|
3668
4099
|
);
|
|
@@ -3671,8 +4102,8 @@ async function runNew(name, options) {
|
|
|
3671
4102
|
{ workspaceName, scope, registry, agent, variableGroup, ci, stack },
|
|
3672
4103
|
logger.detail
|
|
3673
4104
|
);
|
|
3674
|
-
(0,
|
|
3675
|
-
(0,
|
|
4105
|
+
(0, import_node_fs10.rmSync)((0, import_node_path16.join)(workspaceRoot, "node_modules"), { recursive: true, force: true });
|
|
4106
|
+
(0, import_node_fs10.rmSync)((0, import_node_path16.join)(workspaceRoot, "package-lock.json"), { force: true });
|
|
3676
4107
|
logger.step("Installing the toolchain (commitlint + husky + linting/formatting)");
|
|
3677
4108
|
const installStatus = runShell(
|
|
3678
4109
|
"npm",
|
|
@@ -3702,8 +4133,8 @@ async function runNew(name, options) {
|
|
|
3702
4133
|
}
|
|
3703
4134
|
|
|
3704
4135
|
// src/commands/upgrade.ts
|
|
3705
|
-
var
|
|
3706
|
-
var
|
|
4136
|
+
var import_node_fs11 = require("fs");
|
|
4137
|
+
var import_node_path17 = require("path");
|
|
3707
4138
|
function resolveRegistry2(options, persisted) {
|
|
3708
4139
|
if (options.registry === "azure-artifacts" || options.organization && options.artifactsFeed) {
|
|
3709
4140
|
const persistedAzure = persisted?.kind === "azure-artifacts" ? persisted : void 0;
|
|
@@ -3732,7 +4163,7 @@ function resolveWorkspaceName(workspaceRoot, persisted) {
|
|
|
3732
4163
|
return persisted.workspaceName;
|
|
3733
4164
|
}
|
|
3734
4165
|
try {
|
|
3735
|
-
const existing = (0,
|
|
4166
|
+
const existing = (0, import_node_fs11.readdirSync)(workspaceRoot).find(
|
|
3736
4167
|
(file) => file.endsWith(".code-workspace") && file !== "undefined.code-workspace"
|
|
3737
4168
|
);
|
|
3738
4169
|
if (existing) {
|
|
@@ -3740,7 +4171,7 @@ function resolveWorkspaceName(workspaceRoot, persisted) {
|
|
|
3740
4171
|
}
|
|
3741
4172
|
} catch {
|
|
3742
4173
|
}
|
|
3743
|
-
return (0,
|
|
4174
|
+
return (0, import_node_path17.basename)(workspaceRoot);
|
|
3744
4175
|
}
|
|
3745
4176
|
function resolveOverlayOptions(workspaceRoot, options, persisted) {
|
|
3746
4177
|
const scope = options.scope ?? persisted.scope;
|
|
@@ -3778,7 +4209,7 @@ function resolveOverlayOptions(workspaceRoot, options, persisted) {
|
|
|
3778
4209
|
};
|
|
3779
4210
|
}
|
|
3780
4211
|
function runUpgrade(workspaceRoot, options) {
|
|
3781
|
-
if (!fileExists((0,
|
|
4212
|
+
if (!fileExists((0, import_node_path17.join)(workspaceRoot, "nx.json"))) {
|
|
3782
4213
|
throw new Error(
|
|
3783
4214
|
`No nx.json found in ${workspaceRoot} \u2014 this does not look like an Nx workspace. Run 'mnci upgrade' from the workspace root.`
|
|
3784
4215
|
);
|
|
@@ -3803,14 +4234,14 @@ function runUpgrade(workspaceRoot, options) {
|
|
|
3803
4234
|
|
|
3804
4235
|
// src/commands/interactive.ts
|
|
3805
4236
|
async function runInteractive() {
|
|
3806
|
-
const inWorkspace = fileExists((0,
|
|
4237
|
+
const inWorkspace = fileExists((0, import_node_path18.join)(process.cwd(), "nx.json"));
|
|
3807
4238
|
const choiceNew = { name: "Create a new monorepo", value: "new" };
|
|
3808
4239
|
const choiceAdd = { name: "Add a project to this workspace", value: "add" };
|
|
3809
4240
|
const choiceUpgrade = {
|
|
3810
4241
|
name: "Upgrade this workspace (re-apply the latest overlay)",
|
|
3811
4242
|
value: "upgrade"
|
|
3812
4243
|
};
|
|
3813
|
-
const action = await (0,
|
|
4244
|
+
const action = await (0, import_prompts9.select)({
|
|
3814
4245
|
message: "What would you like to do?",
|
|
3815
4246
|
choices: inWorkspace ? [choiceAdd, choiceUpgrade, choiceNew] : [choiceNew, choiceAdd, choiceUpgrade]
|
|
3816
4247
|
});
|
|
@@ -3824,8 +4255,8 @@ async function runInteractive() {
|
|
|
3824
4255
|
}
|
|
3825
4256
|
|
|
3826
4257
|
// src/commands/up.ts
|
|
3827
|
-
var
|
|
3828
|
-
var
|
|
4258
|
+
var import_node_path19 = require("path");
|
|
4259
|
+
var import_prompts10 = require("@inquirer/prompts");
|
|
3829
4260
|
|
|
3830
4261
|
// src/deps/registry.ts
|
|
3831
4262
|
var LOOKUP_CONCURRENCY = 8;
|
|
@@ -3897,6 +4328,27 @@ async function latestPubVersions(cwd) {
|
|
|
3897
4328
|
return /* @__PURE__ */ new Map();
|
|
3898
4329
|
}
|
|
3899
4330
|
}
|
|
4331
|
+
async function latestNugetVersions(names, cwd) {
|
|
4332
|
+
const results = await pool(names, LOOKUP_CONCURRENCY, async (name) => {
|
|
4333
|
+
const result = await runCaptureAsync(
|
|
4334
|
+
"dotnet",
|
|
4335
|
+
["package", "search", name, "--exact-match", "--format", "json"],
|
|
4336
|
+
cwd
|
|
4337
|
+
);
|
|
4338
|
+
if (result.status !== 0) {
|
|
4339
|
+
return;
|
|
4340
|
+
}
|
|
4341
|
+
try {
|
|
4342
|
+
const parsed = JSON.parse(result.stdout);
|
|
4343
|
+
const packages = parsed.searchResult?.flatMap((source) => source.packages ?? []) ?? [];
|
|
4344
|
+
const match = packages.find((entry) => entry.id?.toLowerCase() === name.toLowerCase()) ?? packages[0];
|
|
4345
|
+
return match?.latestVersion ? [name, match.latestVersion] : void 0;
|
|
4346
|
+
} catch {
|
|
4347
|
+
return;
|
|
4348
|
+
}
|
|
4349
|
+
});
|
|
4350
|
+
return new Map(results.filter((entry) => entry !== void 0));
|
|
4351
|
+
}
|
|
3900
4352
|
async function latestVersions(ecosystem, names, cwd) {
|
|
3901
4353
|
switch (ecosystem) {
|
|
3902
4354
|
case "npm": {
|
|
@@ -3905,10 +4357,17 @@ async function latestVersions(ecosystem, names, cwd) {
|
|
|
3905
4357
|
case "pip": {
|
|
3906
4358
|
return await latestPipVersions(names, cwd);
|
|
3907
4359
|
}
|
|
4360
|
+
case "nuget": {
|
|
4361
|
+
return await latestNugetVersions(names, cwd);
|
|
4362
|
+
}
|
|
3908
4363
|
case "go": {
|
|
3909
4364
|
return await latestGoVersions(cwd);
|
|
3910
4365
|
}
|
|
3911
|
-
default:
|
|
4366
|
+
// 'pub' explicitly, not a default: a future ecosystem added to the union
|
|
4367
|
+
// without a case here should fail to compile, not silently resolve as
|
|
4368
|
+
// Dart/Flutter's whole-graph query — exactly the trap this switch would
|
|
4369
|
+
// otherwise have laid for 'nuget' itself.
|
|
4370
|
+
case "pub": {
|
|
3912
4371
|
return await latestPubVersions(cwd);
|
|
3913
4372
|
}
|
|
3914
4373
|
}
|
|
@@ -4025,13 +4484,13 @@ async function promptForUpdates(outdated) {
|
|
|
4025
4484
|
continue;
|
|
4026
4485
|
}
|
|
4027
4486
|
const { title, blurb } = UPDATE_KIND_LABELS[kind];
|
|
4028
|
-
choices.push(new
|
|
4487
|
+
choices.push(new import_prompts10.Separator(`
|
|
4029
4488
|
${title} ${blurb}`));
|
|
4030
4489
|
for (const entry of section) {
|
|
4031
4490
|
choices.push({ name: row(entry, widths), value: entry });
|
|
4032
4491
|
}
|
|
4033
4492
|
}
|
|
4034
|
-
return await (0,
|
|
4493
|
+
return await (0, import_prompts10.checkbox)({
|
|
4035
4494
|
message: "Choose which packages to update.",
|
|
4036
4495
|
choices,
|
|
4037
4496
|
pageSize: 20
|
|
@@ -4055,6 +4514,7 @@ function reinstall(workspaceRoot, ecosystems) {
|
|
|
4055
4514
|
["npm", "npm", ["install"]],
|
|
4056
4515
|
["pip", "npm", ["run", "python:install"]],
|
|
4057
4516
|
["pub", "flutter", ["pub", "get"]],
|
|
4517
|
+
["nuget", "npx", ["nx", "run-many", "-t", "restore"]],
|
|
4058
4518
|
["go", "go", ["mod", "tidy"]]
|
|
4059
4519
|
];
|
|
4060
4520
|
for (const [ecosystem, command, arguments_] of commands) {
|
|
@@ -4078,7 +4538,7 @@ function reinstall(workspaceRoot, ecosystems) {
|
|
|
4078
4538
|
function hasPythonInstallScript(workspaceRoot) {
|
|
4079
4539
|
try {
|
|
4080
4540
|
const manifest = readJson(
|
|
4081
|
-
(0,
|
|
4541
|
+
(0, import_node_path19.join)(workspaceRoot, "package.json")
|
|
4082
4542
|
);
|
|
4083
4543
|
return manifest.scripts?.["python:install"] !== void 0;
|
|
4084
4544
|
} catch {
|
|
@@ -4094,7 +4554,7 @@ function applyGoUpdates(workspaceRoot, entries) {
|
|
|
4094
4554
|
}
|
|
4095
4555
|
}
|
|
4096
4556
|
async function runUp(workspaceRoot, options) {
|
|
4097
|
-
if (!fileExists((0,
|
|
4557
|
+
if (!fileExists((0, import_node_path19.join)(workspaceRoot, "nx.json"))) {
|
|
4098
4558
|
throw new Error(`No nx.json found in ${workspaceRoot} \u2014 run 'mnci up' from the workspace root.`);
|
|
4099
4559
|
}
|
|
4100
4560
|
const ecosystems = resolveEcosystems(options.ecosystem);
|
|
@@ -4142,8 +4602,8 @@ async function runUp(workspaceRoot, options) {
|
|
|
4142
4602
|
}
|
|
4143
4603
|
|
|
4144
4604
|
// src/util/versionChecker.ts
|
|
4145
|
-
var
|
|
4146
|
-
var
|
|
4605
|
+
var import_node_fs12 = require("fs");
|
|
4606
|
+
var import_node_path20 = require("path");
|
|
4147
4607
|
var import_cross_spawn2 = __toESM(require("cross-spawn"));
|
|
4148
4608
|
var PACKAGE_NAME = "@mnci/cli";
|
|
4149
4609
|
var REGISTRY_TIMEOUT_MS = 2e3;
|
|
@@ -4199,8 +4659,8 @@ function releaseTriple(version) {
|
|
|
4199
4659
|
}
|
|
4200
4660
|
function readCliVersion(packageDirectory) {
|
|
4201
4661
|
try {
|
|
4202
|
-
const manifestPath = (0,
|
|
4203
|
-
const manifest = JSON.parse((0,
|
|
4662
|
+
const manifestPath = (0, import_node_path20.join)(packageDirectory, "..", "package.json");
|
|
4663
|
+
const manifest = JSON.parse((0, import_node_fs12.readFileSync)(manifestPath, "utf8"));
|
|
4204
4664
|
return manifest.version ?? "0.0.0";
|
|
4205
4665
|
} catch {
|
|
4206
4666
|
return "0.0.0";
|