@mnci/cli 4.41.0 → 4.42.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 +107 -93
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -7896,6 +7896,10 @@ function runKinds(options) {
|
|
|
7896
7896
|
|
|
7897
7897
|
// src/workspace-diagnostics/check-invariants.use-case.ts
|
|
7898
7898
|
var import_node_child_process = require("child_process");
|
|
7899
|
+
var import_node_fs30 = require("fs");
|
|
7900
|
+
var import_node_path35 = require("path");
|
|
7901
|
+
|
|
7902
|
+
// src/workspace-diagnostics/locate-stranded-release-tags.use-case.ts
|
|
7899
7903
|
var import_node_fs29 = require("fs");
|
|
7900
7904
|
var import_node_path34 = require("path");
|
|
7901
7905
|
|
|
@@ -7924,14 +7928,28 @@ function findStrandedReleaseTags(projects, tags) {
|
|
|
7924
7928
|
return stranded;
|
|
7925
7929
|
}
|
|
7926
7930
|
|
|
7931
|
+
// src/workspace-diagnostics/locate-stranded-release-tags.use-case.ts
|
|
7932
|
+
var MNCI_TAG_PATTERN = "{projectName}@{version}";
|
|
7933
|
+
function locateStrandedReleaseTags(workspaceRoot, tagPattern) {
|
|
7934
|
+
if (tagPattern !== void 0 && tagPattern !== MNCI_TAG_PATTERN) {
|
|
7935
|
+
return [];
|
|
7936
|
+
}
|
|
7937
|
+
const listed = runCapture("git", ["tag", "--list"], workspaceRoot);
|
|
7938
|
+
if (listed.status !== 0) {
|
|
7939
|
+
return [];
|
|
7940
|
+
}
|
|
7941
|
+
const projects = (0, import_node_fs29.globSync)("{apps,libs,packages}/*/package.json", { cwd: workspaceRoot }).map((path) => readJson((0, import_node_path34.join)(workspaceRoot, path))).filter((manifest) => manifest.private !== true && manifest.name !== void 0).map((manifest) => manifest.name);
|
|
7942
|
+
return findStrandedReleaseTags(projects, listed.stdout.split(/\r?\n/).filter(Boolean));
|
|
7943
|
+
}
|
|
7944
|
+
|
|
7927
7945
|
// src/workspace-diagnostics/check-invariants.use-case.ts
|
|
7928
7946
|
var SUPPORTED_ESLINT_MAJOR = ESLINT_VERSION.replace(/^\D*/, "").split(".", 1)[0];
|
|
7929
7947
|
function toPosix2(path) {
|
|
7930
7948
|
return path.replaceAll("\\", "/");
|
|
7931
7949
|
}
|
|
7932
7950
|
function checkEslintConfigs(workspaceRoot) {
|
|
7933
|
-
const rootConfigs = (0,
|
|
7934
|
-
const projectConfigs = (0,
|
|
7951
|
+
const rootConfigs = (0, import_node_fs30.globSync)("eslint.config.{js,mjs,cjs,ts,mts,cts}", { cwd: workspaceRoot });
|
|
7952
|
+
const projectConfigs = (0, import_node_fs30.globSync)("{apps,libs,packages}/*/eslint.config.{js,mjs,cjs,ts,mts,cts}", {
|
|
7935
7953
|
cwd: workspaceRoot
|
|
7936
7954
|
}).map((config) => toPosix2(config));
|
|
7937
7955
|
return [
|
|
@@ -7951,10 +7969,10 @@ function checkEslintConfigs(workspaceRoot) {
|
|
|
7951
7969
|
];
|
|
7952
7970
|
}
|
|
7953
7971
|
function checkEslintEntryPointReachesTheRules(workspaceRoot) {
|
|
7954
|
-
const rules = (0,
|
|
7955
|
-
if (!(0,
|
|
7956
|
-
const entryPoint = (0,
|
|
7957
|
-
const source = (0,
|
|
7972
|
+
const rules = (0, import_node_path35.join)(workspaceRoot, ESLINT_MNCI_FILENAME);
|
|
7973
|
+
if (!(0, import_node_fs30.existsSync)(rules)) return [];
|
|
7974
|
+
const entryPoint = (0, import_node_path35.join)(workspaceRoot, ESLINT_USER_FILENAME);
|
|
7975
|
+
const source = (0, import_node_fs30.existsSync)(entryPoint) ? (0, import_node_fs30.readFileSync)(entryPoint, "utf8") : "";
|
|
7958
7976
|
return [
|
|
7959
7977
|
{
|
|
7960
7978
|
check: `${ESLINT_USER_FILENAME} imports the mnci rules`,
|
|
@@ -7967,7 +7985,7 @@ function checkEslintEntryPointReachesTheRules(workspaceRoot) {
|
|
|
7967
7985
|
function declaredDevDependencies(workspaceRoot) {
|
|
7968
7986
|
try {
|
|
7969
7987
|
const manifest = readJson(
|
|
7970
|
-
(0,
|
|
7988
|
+
(0, import_node_path35.join)(workspaceRoot, "package.json")
|
|
7971
7989
|
);
|
|
7972
7990
|
return manifest.devDependencies ?? {};
|
|
7973
7991
|
} catch {
|
|
@@ -7975,7 +7993,7 @@ function declaredDevDependencies(workspaceRoot) {
|
|
|
7975
7993
|
}
|
|
7976
7994
|
}
|
|
7977
7995
|
function checkNoRetiredFormatter(workspaceRoot) {
|
|
7978
|
-
const files = RETIRED_FORMATTER_FILES.filter((file) => fileExists((0,
|
|
7996
|
+
const files = RETIRED_FORMATTER_FILES.filter((file) => fileExists((0, import_node_path35.join)(workspaceRoot, file)));
|
|
7979
7997
|
const declared = ["prettier", "eslint-config-prettier", "oxlint", "oxfmt", "@mnci/oxlint-config"].filter((name) => declaredDevDependencies(workspaceRoot)[name] !== void 0);
|
|
7980
7998
|
const stale = [...files, ...declared];
|
|
7981
7999
|
if (stale.length === 0) {
|
|
@@ -8001,7 +8019,7 @@ function checkEslintPlugin(nxJson) {
|
|
|
8001
8019
|
};
|
|
8002
8020
|
}
|
|
8003
8021
|
function checkResolvedEslint(workspaceRoot) {
|
|
8004
|
-
const manifestPath = (0,
|
|
8022
|
+
const manifestPath = (0, import_node_path35.join)(workspaceRoot, "node_modules/eslint/package.json");
|
|
8005
8023
|
if (!fileExists(manifestPath)) {
|
|
8006
8024
|
return void 0;
|
|
8007
8025
|
}
|
|
@@ -8019,11 +8037,11 @@ function checkResolvedEslint(workspaceRoot) {
|
|
|
8019
8037
|
}
|
|
8020
8038
|
}
|
|
8021
8039
|
function checkNpmrc(workspaceRoot, registry, scope) {
|
|
8022
|
-
const npmrcPath = (0,
|
|
8040
|
+
const npmrcPath = (0, import_node_path35.join)(workspaceRoot, ".npmrc");
|
|
8023
8041
|
if (!registry || !fileExists(npmrcPath)) {
|
|
8024
8042
|
return void 0;
|
|
8025
8043
|
}
|
|
8026
|
-
const npmrc = (0,
|
|
8044
|
+
const npmrc = (0, import_node_fs30.readFileSync)(npmrcPath, "utf8");
|
|
8027
8045
|
if (registry.kind === "npm") {
|
|
8028
8046
|
return {
|
|
8029
8047
|
check: ".npmrc authenticates the public registry",
|
|
@@ -8040,11 +8058,11 @@ function checkNpmrc(workspaceRoot, registry, scope) {
|
|
|
8040
8058
|
};
|
|
8041
8059
|
}
|
|
8042
8060
|
function checkNpmrcCredentialResolves(workspaceRoot, environment = process.env) {
|
|
8043
|
-
const npmrcPath = (0,
|
|
8061
|
+
const npmrcPath = (0, import_node_path35.join)(workspaceRoot, ".npmrc");
|
|
8044
8062
|
if (!fileExists(npmrcPath)) {
|
|
8045
8063
|
return void 0;
|
|
8046
8064
|
}
|
|
8047
|
-
const npmrc = (0,
|
|
8065
|
+
const npmrc = (0, import_node_fs30.readFileSync)(npmrcPath, "utf8");
|
|
8048
8066
|
const credentials = npmrc.split("\n").filter((line) => !line.trimStart().startsWith(";") && !line.trimStart().startsWith("#")).filter((line) => /(?:_authToken|_password|_auth)\s*=/u.test(line));
|
|
8049
8067
|
const referenced = [
|
|
8050
8068
|
...new Set(
|
|
@@ -8068,13 +8086,13 @@ function checkNpmrcCredentialResolves(workspaceRoot, environment = process.env)
|
|
|
8068
8086
|
};
|
|
8069
8087
|
}
|
|
8070
8088
|
function checkNpmAuthMatchesPipeline(workspaceRoot, registry) {
|
|
8071
|
-
const npmrcPath = (0,
|
|
8072
|
-
const pipelinePath = (0,
|
|
8089
|
+
const npmrcPath = (0, import_node_path35.join)(workspaceRoot, ".npmrc");
|
|
8090
|
+
const pipelinePath = (0, import_node_path35.join)(workspaceRoot, "azure-pipelines.yml");
|
|
8073
8091
|
if (registry?.kind !== "azure-artifacts" || !fileExists(npmrcPath) || !fileExists(pipelinePath)) {
|
|
8074
8092
|
return void 0;
|
|
8075
8093
|
}
|
|
8076
|
-
const holdsCredentials = (0,
|
|
8077
|
-
const runsTask = (0,
|
|
8094
|
+
const holdsCredentials = (0, import_node_fs30.readFileSync)(npmrcPath, "utf8").split("\n").filter((line) => !line.trimStart().startsWith(";") && !line.trimStart().startsWith("#")).some((line) => /(?:_authToken|_password|_auth)\s*=/u.test(line));
|
|
8095
|
+
const runsTask = (0, import_node_fs30.readFileSync)(pipelinePath, "utf8").includes("npmAuthenticate@0");
|
|
8078
8096
|
if (!holdsCredentials && !runsTask) {
|
|
8079
8097
|
return {
|
|
8080
8098
|
check: "npm auth: .npmrc and azure-pipelines.yml agree",
|
|
@@ -8119,13 +8137,13 @@ function npmjsCredentialShape(credentials, environment) {
|
|
|
8119
8137
|
}
|
|
8120
8138
|
function checkVersionActions(workspaceRoot) {
|
|
8121
8139
|
const candidates = [
|
|
8122
|
-
...(0,
|
|
8123
|
-
...(0,
|
|
8124
|
-
...(0,
|
|
8140
|
+
...(0, import_node_fs30.globSync)("packages/*/pubspec.yaml", { cwd: workspaceRoot }),
|
|
8141
|
+
...(0, import_node_fs30.globSync)("packages/*/*.csproj", { cwd: workspaceRoot }),
|
|
8142
|
+
...(0, import_node_fs30.globSync)("python-packages/*/pyproject.toml", { cwd: workspaceRoot })
|
|
8125
8143
|
].map((manifest) => toPosix2(manifest));
|
|
8126
8144
|
return candidates.flatMap((manifest) => {
|
|
8127
8145
|
const projectRoot = manifest.slice(0, manifest.lastIndexOf("/"));
|
|
8128
|
-
const projectJsonPath = (0,
|
|
8146
|
+
const projectJsonPath = (0, import_node_path35.join)(workspaceRoot, projectRoot, "project.json");
|
|
8129
8147
|
let hasOverride = false;
|
|
8130
8148
|
try {
|
|
8131
8149
|
const projectJson = readJson(projectJsonPath);
|
|
@@ -8154,7 +8172,7 @@ function declaredTargets(workspaceRoot, projectRoot) {
|
|
|
8154
8172
|
]) {
|
|
8155
8173
|
try {
|
|
8156
8174
|
const targets = extract(
|
|
8157
|
-
readJson((0,
|
|
8175
|
+
readJson((0, import_node_path35.join)(workspaceRoot, projectRoot, file))
|
|
8158
8176
|
);
|
|
8159
8177
|
if (targets && typeof targets === "object") {
|
|
8160
8178
|
sources.push({
|
|
@@ -8170,8 +8188,8 @@ function declaredTargets(workspaceRoot, projectRoot) {
|
|
|
8170
8188
|
function checkTargetFilesExist(workspaceRoot) {
|
|
8171
8189
|
const projectRoots = new Set(
|
|
8172
8190
|
[
|
|
8173
|
-
...(0,
|
|
8174
|
-
...(0,
|
|
8191
|
+
...(0, import_node_fs30.globSync)("{apps,libs,packages}/*/project.json", { cwd: workspaceRoot }),
|
|
8192
|
+
...(0, import_node_fs30.globSync)("{apps,libs,packages}/*/package.json", { cwd: workspaceRoot })
|
|
8175
8193
|
].map((manifest) => toPosix2(manifest).split("/").slice(0, 2).join("/"))
|
|
8176
8194
|
);
|
|
8177
8195
|
return [...projectRoots].flatMap(
|
|
@@ -8186,7 +8204,7 @@ function checkOneTargetsFiles(workspaceRoot, source, targetName, target) {
|
|
|
8186
8204
|
return TARGET_FILE_OPTIONS.flatMap((option) => {
|
|
8187
8205
|
const value = target?.options?.[option];
|
|
8188
8206
|
const checkable = typeof value === "string" && !value.includes("{");
|
|
8189
|
-
if (!checkable || fileExists((0,
|
|
8207
|
+
if (!checkable || fileExists((0, import_node_path35.join)(workspaceRoot, value))) {
|
|
8190
8208
|
return [];
|
|
8191
8209
|
}
|
|
8192
8210
|
return [
|
|
@@ -8225,15 +8243,15 @@ function checkGoPluginRegistered(workspaceRoot) {
|
|
|
8225
8243
|
};
|
|
8226
8244
|
}
|
|
8227
8245
|
function checkGoWorkInSync(workspaceRoot) {
|
|
8228
|
-
const goWorkPath = (0,
|
|
8246
|
+
const goWorkPath = (0, import_node_path35.join)(workspaceRoot, "go.work");
|
|
8229
8247
|
if (!fileExists(goWorkPath)) {
|
|
8230
8248
|
return void 0;
|
|
8231
8249
|
}
|
|
8232
|
-
const contents = (0,
|
|
8250
|
+
const contents = (0, import_node_fs30.existsSync)(goWorkPath) ? (0, import_node_fs30.readFileSync)(goWorkPath, "utf8") : "";
|
|
8233
8251
|
const blockEntries = Array.from(contents.matchAll(/(?:^|\n)\s*use\s+\(([^)]*)\)/g), (match) => match[1].split("\n")).flat();
|
|
8234
8252
|
const singleEntries = Array.from(contents.matchAll(/(?:^|\n)\s*use\s+(\.\S+)/g), (match) => match[1]);
|
|
8235
8253
|
const uses = [...blockEntries, ...singleEntries].map((entry) => entry.trim()).filter(Boolean);
|
|
8236
|
-
const stale = uses.filter((entry) => !(0,
|
|
8254
|
+
const stale = uses.filter((entry) => !(0, import_node_fs30.existsSync)((0, import_node_path35.join)(workspaceRoot, entry, "go.mod")));
|
|
8237
8255
|
return {
|
|
8238
8256
|
check: "every go.work `use` entry points to a module that still exists",
|
|
8239
8257
|
ok: stale.length === 0,
|
|
@@ -8249,9 +8267,9 @@ function checkNativeApps(workspaceRoot) {
|
|
|
8249
8267
|
{ file: ".github/workflows/ci.yml", marker: "native (${{ matrix.os }})" },
|
|
8250
8268
|
{ file: "azure-pipelines.yml", marker: "- job: native" }
|
|
8251
8269
|
];
|
|
8252
|
-
const findings = pipelines.filter(({ file }) => fileExists((0,
|
|
8270
|
+
const findings = pipelines.filter(({ file }) => fileExists((0, import_node_path35.join)(workspaceRoot, file))).map(({ file, marker }) => ({
|
|
8253
8271
|
check: `${file} builds the native apps on every OS`,
|
|
8254
|
-
ok: (0,
|
|
8272
|
+
ok: (0, import_node_fs30.readFileSync)((0, import_node_path35.join)(workspaceRoot, file), "utf8").includes(marker),
|
|
8255
8273
|
detail: `${file} has no native job: CI would verify a cgo app on the one agent that cannot build it`,
|
|
8256
8274
|
remedy: "run `mnci upgrade`"
|
|
8257
8275
|
}));
|
|
@@ -8264,7 +8282,7 @@ function checkNativeApps(workspaceRoot) {
|
|
|
8264
8282
|
return findings;
|
|
8265
8283
|
}
|
|
8266
8284
|
function checkNoRootRuntimeDependencies(workspaceRoot) {
|
|
8267
|
-
const manifestPath = (0,
|
|
8285
|
+
const manifestPath = (0, import_node_path35.join)(workspaceRoot, "package.json");
|
|
8268
8286
|
if (!fileExists(manifestPath)) {
|
|
8269
8287
|
return void 0;
|
|
8270
8288
|
}
|
|
@@ -8284,14 +8302,14 @@ function checkNoRootRuntimeDependencies(workspaceRoot) {
|
|
|
8284
8302
|
};
|
|
8285
8303
|
}
|
|
8286
8304
|
function checkRollupSourceMaps(workspaceRoot) {
|
|
8287
|
-
const configs = (0,
|
|
8305
|
+
const configs = (0, import_node_fs30.globSync)(["packages/*/rollup.config.cjs", "libs/*/rollup.config.cjs"], {
|
|
8288
8306
|
cwd: workspaceRoot
|
|
8289
8307
|
}).map((config) => toPosix2(config));
|
|
8290
8308
|
return configs.flatMap((relativePath) => {
|
|
8291
|
-
const configPath = (0,
|
|
8309
|
+
const configPath = (0, import_node_path35.join)(workspaceRoot, relativePath);
|
|
8292
8310
|
let config;
|
|
8293
8311
|
try {
|
|
8294
|
-
config = (0,
|
|
8312
|
+
config = (0, import_node_fs30.readFileSync)(configPath, "utf8");
|
|
8295
8313
|
} catch {
|
|
8296
8314
|
return [];
|
|
8297
8315
|
}
|
|
@@ -8306,11 +8324,11 @@ function checkRollupSourceMaps(workspaceRoot) {
|
|
|
8306
8324
|
});
|
|
8307
8325
|
}
|
|
8308
8326
|
function checkDeclarationSpecifiers(workspaceRoot) {
|
|
8309
|
-
const configs = (0,
|
|
8327
|
+
const configs = (0, import_node_fs30.globSync)(["packages/*/rollup.config.cjs", "libs/*/rollup.config.cjs"], {
|
|
8310
8328
|
cwd: workspaceRoot
|
|
8311
8329
|
}).map((config) => toPosix2(config));
|
|
8312
8330
|
return configs.flatMap((relativePath) => {
|
|
8313
|
-
const configPath = (0,
|
|
8331
|
+
const configPath = (0, import_node_path35.join)(workspaceRoot, relativePath);
|
|
8314
8332
|
if (!fileExists(configPath)) {
|
|
8315
8333
|
return [];
|
|
8316
8334
|
}
|
|
@@ -8325,7 +8343,7 @@ function checkDeclarationSpecifiers(workspaceRoot) {
|
|
|
8325
8343
|
// `plugins` array (what @nx/react:library writes). For any other shape it would no-op, and
|
|
8326
8344
|
// naming a command that silently does nothing is the failure mode the source-map check
|
|
8327
8345
|
// above goes out of its way to avoid, so the remedy depends on the shape.
|
|
8328
|
-
remedy: canAddDeclarationSpecifierPlugin((0,
|
|
8346
|
+
remedy: canAddDeclarationSpecifierPlugin((0, import_node_fs30.readFileSync)(configPath, "utf8")) ? "run `mnci upgrade`, which adds the plugin to the plugins array of withNx's second argument" : "add the plugin to withNx's second argument by hand (copy it from a freshly `mnci add npm-lib`'d project) \u2014 mnci does not recognise the shape of this config, so `mnci upgrade` cannot add it"
|
|
8329
8347
|
}
|
|
8330
8348
|
];
|
|
8331
8349
|
}
|
|
@@ -8341,8 +8359,8 @@ function checkDeclarationSpecifiers(workspaceRoot) {
|
|
|
8341
8359
|
}
|
|
8342
8360
|
function checkPipelinePhases(workspaceRoot) {
|
|
8343
8361
|
const files = ["azure-pipelines.yml", ".github/workflows/ci.yml"];
|
|
8344
|
-
return files.filter((file) => fileExists((0,
|
|
8345
|
-
const { verifyActive, switchedOff } = inspectPipeline((0,
|
|
8362
|
+
return files.filter((file) => fileExists((0, import_node_path35.join)(workspaceRoot, file))).flatMap((file) => {
|
|
8363
|
+
const { verifyActive, switchedOff } = inspectPipeline((0, import_node_fs30.readFileSync)((0, import_node_path35.join)(workspaceRoot, file), "utf8"));
|
|
8346
8364
|
const verify = {
|
|
8347
8365
|
check: `${file} runs the enforced verify phase`,
|
|
8348
8366
|
ok: verifyActive,
|
|
@@ -8383,7 +8401,7 @@ function checkDependencyRangesNotPreserved(nxJson) {
|
|
|
8383
8401
|
};
|
|
8384
8402
|
}
|
|
8385
8403
|
function checkLockfileHasNoLocalRegistry(workspaceRoot) {
|
|
8386
|
-
if (!fileExists((0,
|
|
8404
|
+
if (!fileExists((0, import_node_path35.join)(workspaceRoot, "package-lock.json"))) {
|
|
8387
8405
|
return void 0;
|
|
8388
8406
|
}
|
|
8389
8407
|
return {
|
|
@@ -8394,16 +8412,7 @@ function checkLockfileHasNoLocalRegistry(workspaceRoot) {
|
|
|
8394
8412
|
};
|
|
8395
8413
|
}
|
|
8396
8414
|
function checkReleaseTagsResolve(workspaceRoot, nxJson) {
|
|
8397
|
-
const
|
|
8398
|
-
if (pattern !== void 0 && pattern !== "{projectName}@{version}") {
|
|
8399
|
-
return void 0;
|
|
8400
|
-
}
|
|
8401
|
-
const listed = runCapture("git", ["tag", "--list"], workspaceRoot);
|
|
8402
|
-
if (listed.status !== 0) {
|
|
8403
|
-
return void 0;
|
|
8404
|
-
}
|
|
8405
|
-
const projects = (0, import_node_fs29.globSync)("{apps,libs,packages}/*/package.json", { cwd: workspaceRoot }).map((path) => readJson((0, import_node_path34.join)(workspaceRoot, path))).filter((manifest) => manifest.private !== true && manifest.name !== void 0).map((manifest) => manifest.name);
|
|
8406
|
-
const stranded = findStrandedReleaseTags(projects, listed.stdout.split(/\r?\n/).filter(Boolean));
|
|
8415
|
+
const stranded = locateStrandedReleaseTags(workspaceRoot, nxJson.release?.releaseTag?.pattern);
|
|
8407
8416
|
return {
|
|
8408
8417
|
check: "release tags resolve under each project's current name",
|
|
8409
8418
|
ok: stranded.length === 0,
|
|
@@ -8412,7 +8421,7 @@ function checkReleaseTagsResolve(workspaceRoot, nxJson) {
|
|
|
8412
8421
|
};
|
|
8413
8422
|
}
|
|
8414
8423
|
function collectFindings(workspaceRoot) {
|
|
8415
|
-
const nxJsonPath = (0,
|
|
8424
|
+
const nxJsonPath = (0, import_node_path35.join)(workspaceRoot, "nx.json");
|
|
8416
8425
|
if (!fileExists(nxJsonPath)) {
|
|
8417
8426
|
throw new Error(
|
|
8418
8427
|
`No nx.json found in ${workspaceRoot} \u2014 run 'mnci doctor' from the workspace root.`
|
|
@@ -8546,11 +8555,11 @@ function runCommands(program, options) {
|
|
|
8546
8555
|
}
|
|
8547
8556
|
|
|
8548
8557
|
// src/workspace-info/list-projects.use-case.ts
|
|
8549
|
-
var
|
|
8558
|
+
var import_node_path36 = require("path");
|
|
8550
8559
|
var TYPE_TAG_PREFIX = "type:";
|
|
8551
8560
|
function listProjects(workspaceRoot) {
|
|
8552
8561
|
return locateProjects(workspaceRoot).map((location) => {
|
|
8553
|
-
const projectJsonPath = (0,
|
|
8562
|
+
const projectJsonPath = (0, import_node_path36.join)(workspaceRoot, location.dir, "project.json");
|
|
8554
8563
|
const project = fileExists(projectJsonPath) ? readJson(projectJsonPath) : {};
|
|
8555
8564
|
const typeTag = (project.tags ?? []).find((tag) => tag.startsWith(TYPE_TAG_PREFIX));
|
|
8556
8565
|
return {
|
|
@@ -8563,7 +8572,7 @@ function listProjects(workspaceRoot) {
|
|
|
8563
8572
|
}).toSorted((a, b) => a.dir.localeCompare(b.dir));
|
|
8564
8573
|
}
|
|
8565
8574
|
function runProjects(workspaceRoot, options) {
|
|
8566
|
-
if (!fileExists((0,
|
|
8575
|
+
if (!fileExists((0, import_node_path36.join)(workspaceRoot, "nx.json"))) {
|
|
8567
8576
|
throw new Error("No nx.json found here. Run `projects` from the workspace root.");
|
|
8568
8577
|
}
|
|
8569
8578
|
const projects = listProjects(workspaceRoot);
|
|
@@ -8577,11 +8586,11 @@ function runProjects(workspaceRoot, options) {
|
|
|
8577
8586
|
}
|
|
8578
8587
|
|
|
8579
8588
|
// src/workspace-info/read-workspace-info.use-case.ts
|
|
8580
|
-
var
|
|
8589
|
+
var import_node_path38 = require("path");
|
|
8581
8590
|
|
|
8582
8591
|
// src/cli-version/check-for-update.use-case.ts
|
|
8583
|
-
var
|
|
8584
|
-
var
|
|
8592
|
+
var import_node_fs31 = require("fs");
|
|
8593
|
+
var import_node_path37 = require("path");
|
|
8585
8594
|
var import_cross_spawn3 = __toESM(require("cross-spawn"));
|
|
8586
8595
|
var PACKAGE_NAME2 = "@mnci/cli";
|
|
8587
8596
|
var REGISTRY_TIMEOUT_MS = 2e3;
|
|
@@ -8640,8 +8649,8 @@ function releaseTriple(version) {
|
|
|
8640
8649
|
}
|
|
8641
8650
|
function readCliVersion(packageDirectory) {
|
|
8642
8651
|
try {
|
|
8643
|
-
const manifestPath = (0,
|
|
8644
|
-
const manifest = JSON.parse((0,
|
|
8652
|
+
const manifestPath = (0, import_node_path37.join)(packageDirectory, "..", "package.json");
|
|
8653
|
+
const manifest = JSON.parse((0, import_node_fs31.readFileSync)(manifestPath, "utf8"));
|
|
8645
8654
|
return manifest.version ?? "0.0.0";
|
|
8646
8655
|
} catch {
|
|
8647
8656
|
return "0.0.0";
|
|
@@ -8651,7 +8660,7 @@ function readCliVersion(packageDirectory) {
|
|
|
8651
8660
|
// src/workspace-info/read-workspace-info.use-case.ts
|
|
8652
8661
|
function readWorkspaceInfo(workspaceRoot, cliVersion) {
|
|
8653
8662
|
const latest = fetchLatestVersion() ?? null;
|
|
8654
|
-
const isWorkspace = fileExists((0,
|
|
8663
|
+
const isWorkspace = fileExists((0, import_node_path38.join)(workspaceRoot, "nx.json"));
|
|
8655
8664
|
return {
|
|
8656
8665
|
cli: {
|
|
8657
8666
|
version: cliVersion,
|
|
@@ -8672,8 +8681,8 @@ function runInfo(workspaceRoot, cliVersion, options) {
|
|
|
8672
8681
|
}
|
|
8673
8682
|
|
|
8674
8683
|
// src/workspace-creation/adopt-directory.use-case.ts
|
|
8675
|
-
var
|
|
8676
|
-
var
|
|
8684
|
+
var import_node_fs32 = require("fs");
|
|
8685
|
+
var import_node_path39 = require("path");
|
|
8677
8686
|
var NEVER_COPIED = /* @__PURE__ */ new Set([".git", "node_modules"]);
|
|
8678
8687
|
var AGENT_AND_CI_ENTRIES = [
|
|
8679
8688
|
"AGENTS.md",
|
|
@@ -8704,13 +8713,13 @@ var PREFLIGHT_BLOCKERS = [
|
|
|
8704
8713
|
"packages"
|
|
8705
8714
|
];
|
|
8706
8715
|
function assertAdoptableDirectory(target) {
|
|
8707
|
-
if (!(0,
|
|
8716
|
+
if (!(0, import_node_fs32.existsSync)(target)) {
|
|
8708
8717
|
throw new Error(`--into '${target}' does not exist. Create or clone it first.`);
|
|
8709
8718
|
}
|
|
8710
|
-
if (!(0,
|
|
8719
|
+
if (!(0, import_node_fs32.statSync)(target).isDirectory()) {
|
|
8711
8720
|
throw new Error(`--into '${target}' is not a directory.`);
|
|
8712
8721
|
}
|
|
8713
|
-
const blockers = PREFLIGHT_BLOCKERS.filter((entry) => (0,
|
|
8722
|
+
const blockers = PREFLIGHT_BLOCKERS.filter((entry) => (0, import_node_fs32.existsSync)((0, import_node_path39.join)(target, entry)));
|
|
8714
8723
|
if (blockers.length > 0) {
|
|
8715
8724
|
throw new Error(
|
|
8716
8725
|
`--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.`
|
|
@@ -8718,15 +8727,15 @@ function assertAdoptableDirectory(target) {
|
|
|
8718
8727
|
}
|
|
8719
8728
|
}
|
|
8720
8729
|
function mergeGitignore(generatedFile, targetFile) {
|
|
8721
|
-
const existing = (0,
|
|
8730
|
+
const existing = (0, import_node_fs32.readFileSync)(targetFile, "utf8");
|
|
8722
8731
|
const present = new Set(existing.split("\n").map((line) => line.trim()));
|
|
8723
|
-
const additions = (0,
|
|
8732
|
+
const additions = (0, import_node_fs32.readFileSync)(generatedFile, "utf8").split("\n").map((line) => line.trimEnd()).filter((line) => {
|
|
8724
8733
|
const trimmed = line.trim();
|
|
8725
8734
|
return trimmed !== "" && !trimmed.startsWith("#") && !present.has(trimmed);
|
|
8726
8735
|
});
|
|
8727
8736
|
if (additions.length === 0) return false;
|
|
8728
8737
|
const separator = existing.endsWith("\n") ? "" : "\n";
|
|
8729
|
-
(0,
|
|
8738
|
+
(0, import_node_fs32.writeFileSync)(
|
|
8730
8739
|
targetFile,
|
|
8731
8740
|
`${existing}${separator}
|
|
8732
8741
|
# Added by mnci (Nx workspace)
|
|
@@ -8736,9 +8745,9 @@ ${additions.join("\n")}
|
|
|
8736
8745
|
return true;
|
|
8737
8746
|
}
|
|
8738
8747
|
function adoptGeneratedWorkspace(generatedRoot, target) {
|
|
8739
|
-
const entries = (0,
|
|
8748
|
+
const entries = (0, import_node_fs32.readdirSync)(generatedRoot).filter((entry) => !NEVER_COPIED.has(entry));
|
|
8740
8749
|
const collisions = entries.filter(
|
|
8741
|
-
(entry) => (0,
|
|
8750
|
+
(entry) => (0, import_node_fs32.existsSync)((0, import_node_path39.join)(target, entry)) && !EXISTING_WINS.has(entry) && entry !== ".gitignore"
|
|
8742
8751
|
);
|
|
8743
8752
|
if (collisions.length > 0) {
|
|
8744
8753
|
throw new Error(
|
|
@@ -8747,28 +8756,28 @@ function adoptGeneratedWorkspace(generatedRoot, target) {
|
|
|
8747
8756
|
}
|
|
8748
8757
|
const result = { copied: [], kept: [], mergedGitignore: false };
|
|
8749
8758
|
for (const entry of entries) {
|
|
8750
|
-
const from = (0,
|
|
8751
|
-
const to = (0,
|
|
8752
|
-
if (entry === ".gitignore" && (0,
|
|
8759
|
+
const from = (0, import_node_path39.join)(generatedRoot, entry);
|
|
8760
|
+
const to = (0, import_node_path39.join)(target, entry);
|
|
8761
|
+
if (entry === ".gitignore" && (0, import_node_fs32.existsSync)(to)) {
|
|
8753
8762
|
result.mergedGitignore = mergeGitignore(from, to);
|
|
8754
8763
|
result.kept.push(entry);
|
|
8755
8764
|
continue;
|
|
8756
8765
|
}
|
|
8757
|
-
if ((0,
|
|
8766
|
+
if ((0, import_node_fs32.existsSync)(to)) {
|
|
8758
8767
|
result.kept.push(entry);
|
|
8759
8768
|
continue;
|
|
8760
8769
|
}
|
|
8761
|
-
(0,
|
|
8770
|
+
(0, import_node_fs32.cpSync)(from, to, { recursive: true });
|
|
8762
8771
|
result.copied.push(entry);
|
|
8763
8772
|
}
|
|
8764
|
-
(0,
|
|
8773
|
+
(0, import_node_fs32.rmSync)(generatedRoot, { recursive: true, force: true });
|
|
8765
8774
|
return result;
|
|
8766
8775
|
}
|
|
8767
8776
|
|
|
8768
8777
|
// src/workspace-creation/create-workspace.use-case.ts
|
|
8769
|
-
var
|
|
8778
|
+
var import_node_fs33 = require("fs");
|
|
8770
8779
|
var import_node_os2 = require("os");
|
|
8771
|
-
var
|
|
8780
|
+
var import_node_path40 = require("path");
|
|
8772
8781
|
function nxCloudProviderValue(ci) {
|
|
8773
8782
|
return ci === "azure" ? "azure" : "github";
|
|
8774
8783
|
}
|
|
@@ -8811,9 +8820,9 @@ async function resolveRegistry(options) {
|
|
|
8811
8820
|
return await promptRegistry();
|
|
8812
8821
|
}
|
|
8813
8822
|
async function runNew(name, options) {
|
|
8814
|
-
const adoptTarget = options.into === void 0 ? void 0 : (0,
|
|
8823
|
+
const adoptTarget = options.into === void 0 ? void 0 : (0, import_node_path40.resolve)(process.cwd(), options.into);
|
|
8815
8824
|
if (adoptTarget !== void 0) assertAdoptableDirectory(adoptTarget);
|
|
8816
|
-
const workspaceName = name ?? (adoptTarget === void 0 ? await promptText("Workspace name") : (0,
|
|
8825
|
+
const workspaceName = name ?? (adoptTarget === void 0 ? await promptText("Workspace name") : (0, import_node_path40.basename)(adoptTarget));
|
|
8817
8826
|
assertValidProjectName(workspaceName, "Workspace name");
|
|
8818
8827
|
const scope = options.scope ?? (options.yes ? `@${workspaceName}` : await promptText("npm scope for publishable packages", `@${workspaceName}`));
|
|
8819
8828
|
const registry = await resolveRegistry(options);
|
|
@@ -8826,8 +8835,8 @@ async function runNew(name, options) {
|
|
|
8826
8835
|
const npmAuth = resolveNpmAuth(options.npmAuth, registry, ci);
|
|
8827
8836
|
const stack = await resolveStack(options);
|
|
8828
8837
|
const nxCloud = options.nxCloud ?? (options.yes ? false : await promptNxCloud());
|
|
8829
|
-
const stagingParent = adoptTarget === void 0 ? process.cwd() : (0,
|
|
8830
|
-
let workspaceRoot = (0,
|
|
8838
|
+
const stagingParent = adoptTarget === void 0 ? process.cwd() : (0, import_node_fs33.mkdtempSync)((0, import_node_path40.join)((0, import_node_os2.tmpdir)(), "mnci-new-"));
|
|
8839
|
+
let workspaceRoot = (0, import_node_path40.join)(stagingParent, workspaceName);
|
|
8831
8840
|
try {
|
|
8832
8841
|
logger.step(`Creating Nx workspace '${workspaceName}' (preset: ts)`);
|
|
8833
8842
|
runNpx(
|
|
@@ -8850,7 +8859,7 @@ async function runNew(name, options) {
|
|
|
8850
8859
|
workspaceRoot = adoptTarget;
|
|
8851
8860
|
}
|
|
8852
8861
|
} finally {
|
|
8853
|
-
if (adoptTarget !== void 0) (0,
|
|
8862
|
+
if (adoptTarget !== void 0) (0, import_node_fs33.rmSync)(stagingParent, { recursive: true, force: true });
|
|
8854
8863
|
}
|
|
8855
8864
|
logger.step(
|
|
8856
8865
|
"Applying MoNecromanCI overlay (VS Code workspace, release config, .npmrc, commitlint, pipeline, stack)"
|
|
@@ -8860,8 +8869,8 @@ async function runNew(name, options) {
|
|
|
8860
8869
|
{ workspaceName, scope, registry, agent, variableGroup, ci, stack, ...npmAuth && { npmAuth } },
|
|
8861
8870
|
logger.detail
|
|
8862
8871
|
);
|
|
8863
|
-
(0,
|
|
8864
|
-
(0,
|
|
8872
|
+
(0, import_node_fs33.rmSync)((0, import_node_path40.join)(workspaceRoot, "node_modules"), { recursive: true, force: true });
|
|
8873
|
+
(0, import_node_fs33.rmSync)((0, import_node_path40.join)(workspaceRoot, "package-lock.json"), { force: true });
|
|
8865
8874
|
logger.step("Installing the toolchain (commitlint + husky + linting/formatting)");
|
|
8866
8875
|
const installStatus = runShell(
|
|
8867
8876
|
"npm",
|
|
@@ -8899,12 +8908,12 @@ function projectKindHintLines(kinds = PROJECT_KINDS) {
|
|
|
8899
8908
|
}
|
|
8900
8909
|
|
|
8901
8910
|
// src/workspace-creation/interactive-wizard.use-case.ts
|
|
8902
|
-
var
|
|
8911
|
+
var import_node_path42 = require("path");
|
|
8903
8912
|
var import_prompts4 = require("@inquirer/prompts");
|
|
8904
8913
|
|
|
8905
8914
|
// src/workspace-upgrade/upgrade-workspace.use-case.ts
|
|
8906
|
-
var
|
|
8907
|
-
var
|
|
8915
|
+
var import_node_fs34 = require("fs");
|
|
8916
|
+
var import_node_path41 = require("path");
|
|
8908
8917
|
function resolveRegistry2(options, persisted) {
|
|
8909
8918
|
if (options.registry === "azure-artifacts" || options.organization && options.artifactsFeed) {
|
|
8910
8919
|
const persistedAzure = persisted?.kind === "azure-artifacts" ? persisted : void 0;
|
|
@@ -8933,7 +8942,7 @@ function resolveWorkspaceName(workspaceRoot, persisted) {
|
|
|
8933
8942
|
return persisted.workspaceName;
|
|
8934
8943
|
}
|
|
8935
8944
|
try {
|
|
8936
|
-
const existing = (0,
|
|
8945
|
+
const existing = (0, import_node_fs34.readdirSync)(workspaceRoot).find(
|
|
8937
8946
|
(file) => file.endsWith(".code-workspace") && file !== "undefined.code-workspace"
|
|
8938
8947
|
);
|
|
8939
8948
|
if (existing) {
|
|
@@ -8941,11 +8950,11 @@ function resolveWorkspaceName(workspaceRoot, persisted) {
|
|
|
8941
8950
|
}
|
|
8942
8951
|
} catch {
|
|
8943
8952
|
}
|
|
8944
|
-
return (0,
|
|
8953
|
+
return (0, import_node_path41.basename)(workspaceRoot);
|
|
8945
8954
|
}
|
|
8946
8955
|
function detectNpmAuth(workspaceRoot) {
|
|
8947
8956
|
try {
|
|
8948
|
-
return (0,
|
|
8957
|
+
return (0, import_node_fs34.readFileSync)((0, import_node_path41.join)(workspaceRoot, "azure-pipelines.yml"), "utf8").includes("npmAuthenticate@0") ? "build-identity" : void 0;
|
|
8949
8958
|
} catch {
|
|
8950
8959
|
return void 0;
|
|
8951
8960
|
}
|
|
@@ -8992,7 +9001,7 @@ function resolveOverlayOptions(workspaceRoot, options, persisted) {
|
|
|
8992
9001
|
};
|
|
8993
9002
|
}
|
|
8994
9003
|
function runUpgrade(workspaceRoot, options) {
|
|
8995
|
-
if (!fileExists((0,
|
|
9004
|
+
if (!fileExists((0, import_node_path41.join)(workspaceRoot, "nx.json"))) {
|
|
8996
9005
|
throw new Error(
|
|
8997
9006
|
`No nx.json found in ${workspaceRoot} \u2014 this does not look like an Nx workspace. Run 'mnci upgrade' from the workspace root.`
|
|
8998
9007
|
);
|
|
@@ -9066,13 +9075,18 @@ function runUpgrade(workspaceRoot, options) {
|
|
|
9066
9075
|
"Formatting the workspace (eslint --fix) \u2014 the slowest step, minutes on a large workspace"
|
|
9067
9076
|
);
|
|
9068
9077
|
runFormatter(workspaceRoot);
|
|
9078
|
+
const nxJson = readJson((0, import_node_path41.join)(workspaceRoot, "nx.json"));
|
|
9079
|
+
const stranded = locateStrandedReleaseTags(workspaceRoot, nxJson.release?.releaseTag?.pattern);
|
|
9080
|
+
for (const entry of stranded) {
|
|
9081
|
+
logger.warn(`${entry.project} has release tags only under ${entry.oldTag}: nx release would restart it from its disk version. Run \`git tag ${entry.newTag} ${entry.oldTag}^{commit}\` before the next release (\`mnci doctor\` lists them all).`);
|
|
9082
|
+
}
|
|
9069
9083
|
logger.success("Done. Review the changes with `git diff` before committing.");
|
|
9070
9084
|
logger.info("Run `npm install` and commit package-lock.json too: the overlay may have added or moved a dependency, and CI installs with `npm ci`, which refuses a stale lockfile.");
|
|
9071
9085
|
}
|
|
9072
9086
|
|
|
9073
9087
|
// src/workspace-creation/interactive-wizard.use-case.ts
|
|
9074
9088
|
async function runInteractive() {
|
|
9075
|
-
const inWorkspace = fileExists((0,
|
|
9089
|
+
const inWorkspace = fileExists((0, import_node_path42.join)(process.cwd(), "nx.json"));
|
|
9076
9090
|
const choiceNew = { name: "Create a new monorepo", value: "new" };
|
|
9077
9091
|
const choiceAdd = { name: "Add a project to this workspace", value: "add" };
|
|
9078
9092
|
const choiceUpgrade = {
|