@mnci/cli 4.31.0 → 4.32.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/dist/cli.js +307 -108
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -44,6 +44,12 @@ var import_node_path = require("path");
|
|
|
44
44
|
// src/nx-workspace/nx.client.ts
|
|
45
45
|
var import_cross_spawn = __toESM(require("cross-spawn"));
|
|
46
46
|
|
|
47
|
+
// src/terminal/json-output.client.ts
|
|
48
|
+
function printJson(value) {
|
|
49
|
+
process.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
50
|
+
`);
|
|
51
|
+
}
|
|
52
|
+
|
|
47
53
|
// src/terminal/logger.client.ts
|
|
48
54
|
var logger = {
|
|
49
55
|
info(message) {
|
|
@@ -7055,6 +7061,45 @@ function readWorkspaceStack(workspaceRoot) {
|
|
|
7055
7061
|
};
|
|
7056
7062
|
}
|
|
7057
7063
|
|
|
7064
|
+
// src/project-scaffolding/project-kind-catalog.config.ts
|
|
7065
|
+
var PROJECT_KIND_CATALOG = [
|
|
7066
|
+
{ kind: "react-app", language: "typescript", label: "React app", description: "A Vite React app, built per environment", flags: [], requiredFlags: [] },
|
|
7067
|
+
{ kind: "react-lib", language: "typescript", label: "React library", description: "A publishable React component library", flags: ["scope", "empty"], requiredFlags: [] },
|
|
7068
|
+
{ kind: "react-internal-lib", language: "typescript", label: "React internal library", description: "A private React library for apps in this workspace", flags: ["empty"], requiredFlags: [] },
|
|
7069
|
+
{ kind: "node-app", language: "typescript", label: "Node app", description: "A Node service, with Express, Fastify, Koa or Nest if you choose one", flags: ["framework"], requiredFlags: [] },
|
|
7070
|
+
{ kind: "node-function-app", language: "typescript", label: "Node function app", description: "An Azure Functions (v4) app in TypeScript", flags: ["empty"], requiredFlags: [] },
|
|
7071
|
+
{ kind: "npm-lib", language: "typescript", label: "npm library", description: "A library published to npm, bundled with Rollup", flags: ["scope", "empty"], requiredFlags: [] },
|
|
7072
|
+
{ kind: "internal-lib", language: "typescript", label: "Internal library", description: "A private TypeScript library for apps in this workspace", flags: ["empty"], requiredFlags: [] },
|
|
7073
|
+
{ kind: "vscode-extension", language: "typescript", label: "VS Code extension", description: "A bundled Marketplace extension, optionally shipping a Go sidecar", flags: ["publisher", "sidecar"], requiredFlags: [] },
|
|
7074
|
+
{ kind: "python-app", language: "python", label: "Python app", description: "A pip-native Python application (Ruff, pytest)", flags: [], requiredFlags: [] },
|
|
7075
|
+
{ kind: "python-function-app", language: "python", label: "Python function app", description: "An Azure Functions (v2 model) app in Python", flags: [], requiredFlags: [] },
|
|
7076
|
+
{ kind: "python-lib", language: "python", label: "Python library", description: "A Python package published with twine", flags: [], requiredFlags: [] },
|
|
7077
|
+
{ kind: "python-internal-lib", language: "python", label: "Python internal library", description: "A private Python library, vendored into the apps that use it", flags: [], requiredFlags: [] },
|
|
7078
|
+
{ kind: "python-vendor", language: "python", label: "Vendor a Python library", description: "Copy an internal Python library into a consumer so it can be packaged", flags: ["lib"], requiredFlags: ["lib"] },
|
|
7079
|
+
{ kind: "go-app", language: "go", label: "Go app", description: "A Go executable with one static binary per platform", flags: ["release", "cgo", "web"], requiredFlags: [] },
|
|
7080
|
+
{ kind: "go-function-app", language: "go", label: "Go function app", description: "A Go Azure Functions custom handler", flags: [], requiredFlags: [] },
|
|
7081
|
+
{ kind: "go-lib", language: "go", label: "Go library", description: "A Go module other repositories can go get", flags: [], requiredFlags: [] },
|
|
7082
|
+
{ kind: "go-internal-lib", language: "go", label: "Go internal library", description: "A private Go module for apps in this workspace", flags: [], requiredFlags: [] },
|
|
7083
|
+
{ kind: "flutter-app", language: "flutter", label: "Flutter app", description: "A Flutter app built for the web", flags: [], requiredFlags: [] },
|
|
7084
|
+
{ kind: "flutter-lib", language: "flutter", label: "Flutter library", description: "A Dart package released by git tag", flags: [], requiredFlags: [] },
|
|
7085
|
+
{ kind: "flutter-internal-lib", language: "flutter", label: "Flutter internal library", description: "A private Dart package for apps in this workspace", flags: [], requiredFlags: [] },
|
|
7086
|
+
{ kind: "csharp-app", language: "csharp", label: "C# app", description: "A .NET console, web API or worker app", flags: [], requiredFlags: [] },
|
|
7087
|
+
{ kind: "csharp-function-app", language: "csharp", label: "C# function app", description: "An Azure Functions isolated-worker app", flags: [], requiredFlags: [] },
|
|
7088
|
+
{ kind: "csharp-lib", language: "csharp", label: "C# library", description: "A NuGet package", flags: ["scope"], requiredFlags: [] },
|
|
7089
|
+
{ kind: "csharp-internal-lib", language: "csharp", label: "C# internal library", description: "A private .NET library for apps in this workspace", flags: [], requiredFlags: [] }
|
|
7090
|
+
];
|
|
7091
|
+
|
|
7092
|
+
// src/project-scaffolding/list-project-kinds.use-case.ts
|
|
7093
|
+
function runKinds(options) {
|
|
7094
|
+
if (options.json === true) {
|
|
7095
|
+
printJson(PROJECT_KIND_CATALOG);
|
|
7096
|
+
return;
|
|
7097
|
+
}
|
|
7098
|
+
for (const entry of PROJECT_KIND_CATALOG) {
|
|
7099
|
+
logger.info(`${entry.kind.padEnd(22)} ${entry.description}`);
|
|
7100
|
+
}
|
|
7101
|
+
}
|
|
7102
|
+
|
|
7058
7103
|
// src/workspace-diagnostics/check-invariants.use-case.ts
|
|
7059
7104
|
var import_node_child_process = require("child_process");
|
|
7060
7105
|
var import_node_fs19 = require("fs");
|
|
@@ -7334,10 +7379,12 @@ function checkOneTargetsFiles(workspaceRoot, source, targetName, target) {
|
|
|
7334
7379
|
});
|
|
7335
7380
|
}
|
|
7336
7381
|
function checkSync(workspaceRoot) {
|
|
7382
|
+
const result = runCapture("npx", ["nx", "sync:check"], workspaceRoot);
|
|
7337
7383
|
return {
|
|
7338
7384
|
check: "TypeScript project references synced",
|
|
7339
|
-
ok:
|
|
7340
|
-
detail:
|
|
7385
|
+
ok: result.status === 0,
|
|
7386
|
+
detail: `nx sync:check failed \u2014 a stale project reference was never committed${result.stdout.trim() ? `
|
|
7387
|
+
${result.stdout.trim()}` : ""}`,
|
|
7341
7388
|
remedy: "run `npx nx sync` and commit the result"
|
|
7342
7389
|
};
|
|
7343
7390
|
}
|
|
@@ -7502,9 +7549,16 @@ function collectFindings(workspaceRoot) {
|
|
|
7502
7549
|
...checkNativeApps(workspaceRoot)
|
|
7503
7550
|
].filter((finding) => finding !== void 0);
|
|
7504
7551
|
}
|
|
7505
|
-
function runDoctor(workspaceRoot) {
|
|
7552
|
+
function runDoctor(workspaceRoot, options = {}) {
|
|
7506
7553
|
const findings = collectFindings(workspaceRoot);
|
|
7507
7554
|
const failed = findings.filter((finding) => !finding.ok);
|
|
7555
|
+
if (options.json === true) {
|
|
7556
|
+
printJson({ findings, passed: findings.length - failed.length, failed: failed.length });
|
|
7557
|
+
if (failed.length > 0) {
|
|
7558
|
+
process.exitCode = 1;
|
|
7559
|
+
}
|
|
7560
|
+
return;
|
|
7561
|
+
}
|
|
7508
7562
|
for (const finding of findings) {
|
|
7509
7563
|
if (finding.ok) {
|
|
7510
7564
|
logger.success(finding.check);
|
|
@@ -7523,9 +7577,204 @@ function runDoctor(workspaceRoot) {
|
|
|
7523
7577
|
process.exitCode = 1;
|
|
7524
7578
|
}
|
|
7525
7579
|
|
|
7526
|
-
// src/
|
|
7527
|
-
var
|
|
7580
|
+
// src/command-catalog/command-groups.config.ts
|
|
7581
|
+
var COMMAND_GROUPS = {
|
|
7582
|
+
new: "workspace",
|
|
7583
|
+
upgrade: "workspace",
|
|
7584
|
+
doctor: "workspace",
|
|
7585
|
+
add: "projects",
|
|
7586
|
+
install: "dependencies",
|
|
7587
|
+
sync: "dependencies",
|
|
7588
|
+
up: "dependencies",
|
|
7589
|
+
ci: "pipeline",
|
|
7590
|
+
commands: "inspect",
|
|
7591
|
+
kinds: "inspect",
|
|
7592
|
+
projects: "inspect",
|
|
7593
|
+
info: "inspect"
|
|
7594
|
+
};
|
|
7595
|
+
|
|
7596
|
+
// src/command-catalog/describe-commands.algorithm.ts
|
|
7597
|
+
function describeOption(option) {
|
|
7598
|
+
const isScalar = ["string", "number", "boolean"].includes(typeof option.defaultValue);
|
|
7599
|
+
return {
|
|
7600
|
+
name: option.name(),
|
|
7601
|
+
flags: option.flags,
|
|
7602
|
+
short: option.short,
|
|
7603
|
+
description: option.description,
|
|
7604
|
+
takesValue: option.required ? "required" : option.optional ? "optional" : "none",
|
|
7605
|
+
variadic: option.variadic,
|
|
7606
|
+
// A repeatable flag is declared with a list as its default, which its collector appends to.
|
|
7607
|
+
repeatable: Array.isArray(option.defaultValue),
|
|
7608
|
+
negated: option.negate,
|
|
7609
|
+
choices: option.argChoices,
|
|
7610
|
+
defaultValue: isScalar ? option.defaultValue : void 0
|
|
7611
|
+
};
|
|
7612
|
+
}
|
|
7613
|
+
function describeCommands(program) {
|
|
7614
|
+
return program.commands.filter((command) => command.name() !== "help").map((command) => {
|
|
7615
|
+
const group = COMMAND_GROUPS[command.name()];
|
|
7616
|
+
if (group === void 0) {
|
|
7617
|
+
throw new Error(`Command '${command.name()}' has no group in COMMAND_GROUPS (command-catalog/command-groups.config.ts).`);
|
|
7618
|
+
}
|
|
7619
|
+
const args = command.registeredArguments.map((argument) => ({
|
|
7620
|
+
name: argument.name(),
|
|
7621
|
+
description: argument.description,
|
|
7622
|
+
required: argument.required,
|
|
7623
|
+
variadic: argument.variadic,
|
|
7624
|
+
choices: argument.argChoices
|
|
7625
|
+
}));
|
|
7626
|
+
return {
|
|
7627
|
+
name: command.name(),
|
|
7628
|
+
aliases: command.aliases(),
|
|
7629
|
+
group,
|
|
7630
|
+
description: command.description(),
|
|
7631
|
+
arguments: args,
|
|
7632
|
+
options: command.options.map((option) => describeOption(option))
|
|
7633
|
+
};
|
|
7634
|
+
});
|
|
7635
|
+
}
|
|
7636
|
+
|
|
7637
|
+
// src/command-catalog/list-commands.use-case.ts
|
|
7638
|
+
function runCommands(program, options) {
|
|
7639
|
+
const commands = describeCommands(program);
|
|
7640
|
+
if (options.json === true) {
|
|
7641
|
+
printJson(commands);
|
|
7642
|
+
return;
|
|
7643
|
+
}
|
|
7644
|
+
for (const command of commands) {
|
|
7645
|
+
logger.info(`${command.name.padEnd(10)} ${command.description}`);
|
|
7646
|
+
}
|
|
7647
|
+
}
|
|
7648
|
+
|
|
7649
|
+
// src/workspace-info/list-projects.use-case.ts
|
|
7528
7650
|
var import_node_path27 = require("path");
|
|
7651
|
+
var TYPE_TAG_PREFIX = "type:";
|
|
7652
|
+
function listProjects(workspaceRoot) {
|
|
7653
|
+
return locateProjects(workspaceRoot).map((location) => {
|
|
7654
|
+
const projectJsonPath = (0, import_node_path27.join)(workspaceRoot, location.dir, "project.json");
|
|
7655
|
+
const project = fileExists(projectJsonPath) ? readJson(projectJsonPath) : {};
|
|
7656
|
+
const typeTag = (project.tags ?? []).find((tag) => tag.startsWith(TYPE_TAG_PREFIX));
|
|
7657
|
+
return {
|
|
7658
|
+
name: location.name,
|
|
7659
|
+
dir: location.dir,
|
|
7660
|
+
ecosystem: location.ecosystem,
|
|
7661
|
+
kind: typeTag?.slice(TYPE_TAG_PREFIX.length),
|
|
7662
|
+
targets: Object.keys(project.targets ?? {})
|
|
7663
|
+
};
|
|
7664
|
+
}).toSorted((a, b) => a.dir.localeCompare(b.dir));
|
|
7665
|
+
}
|
|
7666
|
+
function runProjects(workspaceRoot, options) {
|
|
7667
|
+
if (!fileExists((0, import_node_path27.join)(workspaceRoot, "nx.json"))) {
|
|
7668
|
+
throw new Error("No nx.json found here. Run `projects` from the workspace root.");
|
|
7669
|
+
}
|
|
7670
|
+
const projects = listProjects(workspaceRoot);
|
|
7671
|
+
if (options.json === true) {
|
|
7672
|
+
printJson(projects);
|
|
7673
|
+
return;
|
|
7674
|
+
}
|
|
7675
|
+
for (const project of projects) {
|
|
7676
|
+
logger.info(`${project.dir.padEnd(32)} ${project.ecosystem}${project.kind ? ` ${project.kind}` : ""}`);
|
|
7677
|
+
}
|
|
7678
|
+
}
|
|
7679
|
+
|
|
7680
|
+
// src/workspace-info/read-workspace-info.use-case.ts
|
|
7681
|
+
var import_node_path29 = require("path");
|
|
7682
|
+
|
|
7683
|
+
// src/cli-version/check-for-update.use-case.ts
|
|
7684
|
+
var import_node_fs20 = require("fs");
|
|
7685
|
+
var import_node_path28 = require("path");
|
|
7686
|
+
var import_cross_spawn2 = __toESM(require("cross-spawn"));
|
|
7687
|
+
var PACKAGE_NAME = "@mnci/cli";
|
|
7688
|
+
var REGISTRY_TIMEOUT_MS = 2e3;
|
|
7689
|
+
function checkForUpdate(currentVersion2) {
|
|
7690
|
+
try {
|
|
7691
|
+
if (!process.stdout.isTTY) {
|
|
7692
|
+
return;
|
|
7693
|
+
}
|
|
7694
|
+
setImmediate(() => {
|
|
7695
|
+
try {
|
|
7696
|
+
reportIfOutdated(currentVersion2);
|
|
7697
|
+
} catch {
|
|
7698
|
+
}
|
|
7699
|
+
});
|
|
7700
|
+
} catch {
|
|
7701
|
+
}
|
|
7702
|
+
}
|
|
7703
|
+
function fetchLatestVersion() {
|
|
7704
|
+
const result = import_cross_spawn2.default.sync("npm", ["view", PACKAGE_NAME, "version"], {
|
|
7705
|
+
encoding: "utf8",
|
|
7706
|
+
timeout: REGISTRY_TIMEOUT_MS,
|
|
7707
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
7708
|
+
});
|
|
7709
|
+
if (result.error || result.status !== 0) {
|
|
7710
|
+
return void 0;
|
|
7711
|
+
}
|
|
7712
|
+
return (result.stdout ?? "").trim() || void 0;
|
|
7713
|
+
}
|
|
7714
|
+
function reportIfOutdated(currentVersion2) {
|
|
7715
|
+
const latestVersion = fetchLatestVersion();
|
|
7716
|
+
if (!latestVersion || !isNewerVersion(latestVersion, currentVersion2)) {
|
|
7717
|
+
return;
|
|
7718
|
+
}
|
|
7719
|
+
logger.info("");
|
|
7720
|
+
logger.info(`A new version of ${PACKAGE_NAME} is available: ${latestVersion}`);
|
|
7721
|
+
logger.info(` Current version: ${currentVersion2}`);
|
|
7722
|
+
logger.info(` Update with: npm install -g ${PACKAGE_NAME}@latest`);
|
|
7723
|
+
logger.info("");
|
|
7724
|
+
}
|
|
7725
|
+
function isNewerVersion(candidate, current) {
|
|
7726
|
+
const candidateParts = releaseTriple(candidate);
|
|
7727
|
+
const currentParts = releaseTriple(current);
|
|
7728
|
+
if (!candidateParts || !currentParts) {
|
|
7729
|
+
return false;
|
|
7730
|
+
}
|
|
7731
|
+
for (const [index, candidatePart] of candidateParts.entries()) {
|
|
7732
|
+
if (candidatePart !== currentParts[index]) {
|
|
7733
|
+
return candidatePart > currentParts[index];
|
|
7734
|
+
}
|
|
7735
|
+
}
|
|
7736
|
+
return false;
|
|
7737
|
+
}
|
|
7738
|
+
function releaseTriple(version) {
|
|
7739
|
+
const match = /^(\d+)\.(\d+)\.(\d+)/.exec(version.trim());
|
|
7740
|
+
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : void 0;
|
|
7741
|
+
}
|
|
7742
|
+
function readCliVersion(packageDirectory) {
|
|
7743
|
+
try {
|
|
7744
|
+
const manifestPath = (0, import_node_path28.join)(packageDirectory, "..", "package.json");
|
|
7745
|
+
const manifest = JSON.parse((0, import_node_fs20.readFileSync)(manifestPath, "utf8"));
|
|
7746
|
+
return manifest.version ?? "0.0.0";
|
|
7747
|
+
} catch {
|
|
7748
|
+
return "0.0.0";
|
|
7749
|
+
}
|
|
7750
|
+
}
|
|
7751
|
+
|
|
7752
|
+
// src/workspace-info/read-workspace-info.use-case.ts
|
|
7753
|
+
function readWorkspaceInfo(workspaceRoot, cliVersion) {
|
|
7754
|
+
const latest = fetchLatestVersion() ?? null;
|
|
7755
|
+
const isWorkspace = fileExists((0, import_node_path29.join)(workspaceRoot, "nx.json"));
|
|
7756
|
+
return {
|
|
7757
|
+
cli: {
|
|
7758
|
+
version: cliVersion,
|
|
7759
|
+
latest,
|
|
7760
|
+
updateAvailable: latest !== null && isNewerVersion(latest, cliVersion)
|
|
7761
|
+
},
|
|
7762
|
+
workspace: isWorkspace ? { root: workspaceRoot, config: { ...readMnciConfig(workspaceRoot) } } : null
|
|
7763
|
+
};
|
|
7764
|
+
}
|
|
7765
|
+
function runInfo(workspaceRoot, cliVersion, options) {
|
|
7766
|
+
const info = readWorkspaceInfo(workspaceRoot, cliVersion);
|
|
7767
|
+
if (options.json === true) {
|
|
7768
|
+
printJson(info);
|
|
7769
|
+
return;
|
|
7770
|
+
}
|
|
7771
|
+
logger.info(`mnci ${info.cli.version}${info.cli.updateAvailable ? ` (${info.cli.latest} is available)` : ""}`);
|
|
7772
|
+
logger.info(info.workspace ? `workspace: ${info.workspace.root}` : "not inside a workspace");
|
|
7773
|
+
}
|
|
7774
|
+
|
|
7775
|
+
// src/workspace-creation/adopt-directory.use-case.ts
|
|
7776
|
+
var import_node_fs21 = require("fs");
|
|
7777
|
+
var import_node_path30 = require("path");
|
|
7529
7778
|
var NEVER_COPIED = /* @__PURE__ */ new Set([".git", "node_modules"]);
|
|
7530
7779
|
var AGENT_AND_CI_ENTRIES = [
|
|
7531
7780
|
"AGENTS.md",
|
|
@@ -7556,13 +7805,13 @@ var PREFLIGHT_BLOCKERS = [
|
|
|
7556
7805
|
"packages"
|
|
7557
7806
|
];
|
|
7558
7807
|
function assertAdoptableDirectory(target) {
|
|
7559
|
-
if (!(0,
|
|
7808
|
+
if (!(0, import_node_fs21.existsSync)(target)) {
|
|
7560
7809
|
throw new Error(`--into '${target}' does not exist. Create or clone it first.`);
|
|
7561
7810
|
}
|
|
7562
|
-
if (!(0,
|
|
7811
|
+
if (!(0, import_node_fs21.statSync)(target).isDirectory()) {
|
|
7563
7812
|
throw new Error(`--into '${target}' is not a directory.`);
|
|
7564
7813
|
}
|
|
7565
|
-
const blockers = PREFLIGHT_BLOCKERS.filter((entry) => (0,
|
|
7814
|
+
const blockers = PREFLIGHT_BLOCKERS.filter((entry) => (0, import_node_fs21.existsSync)((0, import_node_path30.join)(target, entry)));
|
|
7566
7815
|
if (blockers.length > 0) {
|
|
7567
7816
|
throw new Error(
|
|
7568
7817
|
`--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.`
|
|
@@ -7570,15 +7819,15 @@ function assertAdoptableDirectory(target) {
|
|
|
7570
7819
|
}
|
|
7571
7820
|
}
|
|
7572
7821
|
function mergeGitignore(generatedFile, targetFile) {
|
|
7573
|
-
const existing = (0,
|
|
7822
|
+
const existing = (0, import_node_fs21.readFileSync)(targetFile, "utf8");
|
|
7574
7823
|
const present = new Set(existing.split("\n").map((line) => line.trim()));
|
|
7575
|
-
const additions = (0,
|
|
7824
|
+
const additions = (0, import_node_fs21.readFileSync)(generatedFile, "utf8").split("\n").map((line) => line.trimEnd()).filter((line) => {
|
|
7576
7825
|
const trimmed = line.trim();
|
|
7577
7826
|
return trimmed !== "" && !trimmed.startsWith("#") && !present.has(trimmed);
|
|
7578
7827
|
});
|
|
7579
7828
|
if (additions.length === 0) return false;
|
|
7580
7829
|
const separator = existing.endsWith("\n") ? "" : "\n";
|
|
7581
|
-
(0,
|
|
7830
|
+
(0, import_node_fs21.writeFileSync)(
|
|
7582
7831
|
targetFile,
|
|
7583
7832
|
`${existing}${separator}
|
|
7584
7833
|
# Added by mnci (Nx workspace)
|
|
@@ -7588,9 +7837,9 @@ ${additions.join("\n")}
|
|
|
7588
7837
|
return true;
|
|
7589
7838
|
}
|
|
7590
7839
|
function adoptGeneratedWorkspace(generatedRoot, target) {
|
|
7591
|
-
const entries = (0,
|
|
7840
|
+
const entries = (0, import_node_fs21.readdirSync)(generatedRoot).filter((entry) => !NEVER_COPIED.has(entry));
|
|
7592
7841
|
const collisions = entries.filter(
|
|
7593
|
-
(entry) => (0,
|
|
7842
|
+
(entry) => (0, import_node_fs21.existsSync)((0, import_node_path30.join)(target, entry)) && !EXISTING_WINS.has(entry) && entry !== ".gitignore"
|
|
7594
7843
|
);
|
|
7595
7844
|
if (collisions.length > 0) {
|
|
7596
7845
|
throw new Error(
|
|
@@ -7599,28 +7848,28 @@ function adoptGeneratedWorkspace(generatedRoot, target) {
|
|
|
7599
7848
|
}
|
|
7600
7849
|
const result = { copied: [], kept: [], mergedGitignore: false };
|
|
7601
7850
|
for (const entry of entries) {
|
|
7602
|
-
const from = (0,
|
|
7603
|
-
const to = (0,
|
|
7604
|
-
if (entry === ".gitignore" && (0,
|
|
7851
|
+
const from = (0, import_node_path30.join)(generatedRoot, entry);
|
|
7852
|
+
const to = (0, import_node_path30.join)(target, entry);
|
|
7853
|
+
if (entry === ".gitignore" && (0, import_node_fs21.existsSync)(to)) {
|
|
7605
7854
|
result.mergedGitignore = mergeGitignore(from, to);
|
|
7606
7855
|
result.kept.push(entry);
|
|
7607
7856
|
continue;
|
|
7608
7857
|
}
|
|
7609
|
-
if ((0,
|
|
7858
|
+
if ((0, import_node_fs21.existsSync)(to)) {
|
|
7610
7859
|
result.kept.push(entry);
|
|
7611
7860
|
continue;
|
|
7612
7861
|
}
|
|
7613
|
-
(0,
|
|
7862
|
+
(0, import_node_fs21.cpSync)(from, to, { recursive: true });
|
|
7614
7863
|
result.copied.push(entry);
|
|
7615
7864
|
}
|
|
7616
|
-
(0,
|
|
7865
|
+
(0, import_node_fs21.rmSync)(generatedRoot, { recursive: true, force: true });
|
|
7617
7866
|
return result;
|
|
7618
7867
|
}
|
|
7619
7868
|
|
|
7620
7869
|
// src/workspace-creation/create-workspace.use-case.ts
|
|
7621
|
-
var
|
|
7870
|
+
var import_node_fs22 = require("fs");
|
|
7622
7871
|
var import_node_os = require("os");
|
|
7623
|
-
var
|
|
7872
|
+
var import_node_path31 = require("path");
|
|
7624
7873
|
function nxCloudProviderValue(ci) {
|
|
7625
7874
|
return ci === "azure" ? "azure" : "github";
|
|
7626
7875
|
}
|
|
@@ -7663,9 +7912,9 @@ async function resolveRegistry(options) {
|
|
|
7663
7912
|
return await promptRegistry();
|
|
7664
7913
|
}
|
|
7665
7914
|
async function runNew(name, options) {
|
|
7666
|
-
const adoptTarget = options.into === void 0 ? void 0 : (0,
|
|
7915
|
+
const adoptTarget = options.into === void 0 ? void 0 : (0, import_node_path31.resolve)(process.cwd(), options.into);
|
|
7667
7916
|
if (adoptTarget !== void 0) assertAdoptableDirectory(adoptTarget);
|
|
7668
|
-
const workspaceName = name ?? (adoptTarget === void 0 ? await promptText("Workspace name") : (0,
|
|
7917
|
+
const workspaceName = name ?? (adoptTarget === void 0 ? await promptText("Workspace name") : (0, import_node_path31.basename)(adoptTarget));
|
|
7669
7918
|
assertValidProjectName(workspaceName, "Workspace name");
|
|
7670
7919
|
const scope = options.scope ?? (options.yes ? `@${workspaceName}` : await promptText("npm scope for publishable packages", `@${workspaceName}`));
|
|
7671
7920
|
const registry = await resolveRegistry(options);
|
|
@@ -7678,8 +7927,8 @@ async function runNew(name, options) {
|
|
|
7678
7927
|
const npmAuth = resolveNpmAuth(options.npmAuth, registry, ci);
|
|
7679
7928
|
const stack = await resolveStack(options);
|
|
7680
7929
|
const nxCloud = options.nxCloud ?? (options.yes ? false : await promptNxCloud());
|
|
7681
|
-
const stagingParent = adoptTarget === void 0 ? process.cwd() : (0,
|
|
7682
|
-
let workspaceRoot = (0,
|
|
7930
|
+
const stagingParent = adoptTarget === void 0 ? process.cwd() : (0, import_node_fs22.mkdtempSync)((0, import_node_path31.join)((0, import_node_os.tmpdir)(), "mnci-new-"));
|
|
7931
|
+
let workspaceRoot = (0, import_node_path31.join)(stagingParent, workspaceName);
|
|
7683
7932
|
try {
|
|
7684
7933
|
logger.step(`Creating Nx workspace '${workspaceName}' (preset: ts)`);
|
|
7685
7934
|
runNpx(
|
|
@@ -7702,7 +7951,7 @@ async function runNew(name, options) {
|
|
|
7702
7951
|
workspaceRoot = adoptTarget;
|
|
7703
7952
|
}
|
|
7704
7953
|
} finally {
|
|
7705
|
-
if (adoptTarget !== void 0) (0,
|
|
7954
|
+
if (adoptTarget !== void 0) (0, import_node_fs22.rmSync)(stagingParent, { recursive: true, force: true });
|
|
7706
7955
|
}
|
|
7707
7956
|
logger.step(
|
|
7708
7957
|
"Applying MoNecromanCI overlay (VS Code workspace, release config, .npmrc, commitlint, pipeline, stack)"
|
|
@@ -7712,8 +7961,8 @@ async function runNew(name, options) {
|
|
|
7712
7961
|
{ workspaceName, scope, registry, agent, variableGroup, ci, stack, ...npmAuth && { npmAuth } },
|
|
7713
7962
|
logger.detail
|
|
7714
7963
|
);
|
|
7715
|
-
(0,
|
|
7716
|
-
(0,
|
|
7964
|
+
(0, import_node_fs22.rmSync)((0, import_node_path31.join)(workspaceRoot, "node_modules"), { recursive: true, force: true });
|
|
7965
|
+
(0, import_node_fs22.rmSync)((0, import_node_path31.join)(workspaceRoot, "package-lock.json"), { force: true });
|
|
7717
7966
|
logger.step("Installing the toolchain (commitlint + husky + linting/formatting)");
|
|
7718
7967
|
const installStatus = runShell(
|
|
7719
7968
|
"npm",
|
|
@@ -7751,12 +8000,12 @@ function projectKindHintLines(kinds = PROJECT_KINDS) {
|
|
|
7751
8000
|
}
|
|
7752
8001
|
|
|
7753
8002
|
// src/workspace-creation/interactive-wizard.use-case.ts
|
|
7754
|
-
var
|
|
8003
|
+
var import_node_path33 = require("path");
|
|
7755
8004
|
var import_prompts4 = require("@inquirer/prompts");
|
|
7756
8005
|
|
|
7757
8006
|
// src/workspace-upgrade/upgrade-workspace.use-case.ts
|
|
7758
|
-
var
|
|
7759
|
-
var
|
|
8007
|
+
var import_node_fs23 = require("fs");
|
|
8008
|
+
var import_node_path32 = require("path");
|
|
7760
8009
|
function resolveRegistry2(options, persisted) {
|
|
7761
8010
|
if (options.registry === "azure-artifacts" || options.organization && options.artifactsFeed) {
|
|
7762
8011
|
const persistedAzure = persisted?.kind === "azure-artifacts" ? persisted : void 0;
|
|
@@ -7785,7 +8034,7 @@ function resolveWorkspaceName(workspaceRoot, persisted) {
|
|
|
7785
8034
|
return persisted.workspaceName;
|
|
7786
8035
|
}
|
|
7787
8036
|
try {
|
|
7788
|
-
const existing = (0,
|
|
8037
|
+
const existing = (0, import_node_fs23.readdirSync)(workspaceRoot).find(
|
|
7789
8038
|
(file) => file.endsWith(".code-workspace") && file !== "undefined.code-workspace"
|
|
7790
8039
|
);
|
|
7791
8040
|
if (existing) {
|
|
@@ -7793,11 +8042,11 @@ function resolveWorkspaceName(workspaceRoot, persisted) {
|
|
|
7793
8042
|
}
|
|
7794
8043
|
} catch {
|
|
7795
8044
|
}
|
|
7796
|
-
return (0,
|
|
8045
|
+
return (0, import_node_path32.basename)(workspaceRoot);
|
|
7797
8046
|
}
|
|
7798
8047
|
function detectNpmAuth(workspaceRoot) {
|
|
7799
8048
|
try {
|
|
7800
|
-
return (0,
|
|
8049
|
+
return (0, import_node_fs23.readFileSync)((0, import_node_path32.join)(workspaceRoot, "azure-pipelines.yml"), "utf8").includes("npmAuthenticate@0") ? "build-identity" : void 0;
|
|
7801
8050
|
} catch {
|
|
7802
8051
|
return void 0;
|
|
7803
8052
|
}
|
|
@@ -7844,7 +8093,7 @@ function resolveOverlayOptions(workspaceRoot, options, persisted) {
|
|
|
7844
8093
|
};
|
|
7845
8094
|
}
|
|
7846
8095
|
function runUpgrade(workspaceRoot, options) {
|
|
7847
|
-
if (!fileExists((0,
|
|
8096
|
+
if (!fileExists((0, import_node_path32.join)(workspaceRoot, "nx.json"))) {
|
|
7848
8097
|
throw new Error(
|
|
7849
8098
|
`No nx.json found in ${workspaceRoot} \u2014 this does not look like an Nx workspace. Run 'mnci upgrade' from the workspace root.`
|
|
7850
8099
|
);
|
|
@@ -7909,7 +8158,7 @@ function runUpgrade(workspaceRoot, options) {
|
|
|
7909
8158
|
|
|
7910
8159
|
// src/workspace-creation/interactive-wizard.use-case.ts
|
|
7911
8160
|
async function runInteractive() {
|
|
7912
|
-
const inWorkspace = fileExists((0,
|
|
8161
|
+
const inWorkspace = fileExists((0, import_node_path33.join)(process.cwd(), "nx.json"));
|
|
7913
8162
|
const choiceNew = { name: "Create a new monorepo", value: "new" };
|
|
7914
8163
|
const choiceAdd = { name: "Add a project to this workspace", value: "add" };
|
|
7915
8164
|
const choiceUpgrade = {
|
|
@@ -7929,72 +8178,6 @@ async function runInteractive() {
|
|
|
7929
8178
|
}
|
|
7930
8179
|
}
|
|
7931
8180
|
|
|
7932
|
-
// src/cli-version/check-for-update.use-case.ts
|
|
7933
|
-
var import_node_fs23 = require("fs");
|
|
7934
|
-
var import_node_path31 = require("path");
|
|
7935
|
-
var import_cross_spawn2 = __toESM(require("cross-spawn"));
|
|
7936
|
-
var PACKAGE_NAME = "@mnci/cli";
|
|
7937
|
-
var REGISTRY_TIMEOUT_MS = 2e3;
|
|
7938
|
-
function checkForUpdate(currentVersion2) {
|
|
7939
|
-
try {
|
|
7940
|
-
if (!process.stdout.isTTY) {
|
|
7941
|
-
return;
|
|
7942
|
-
}
|
|
7943
|
-
setImmediate(() => {
|
|
7944
|
-
try {
|
|
7945
|
-
reportIfOutdated(currentVersion2);
|
|
7946
|
-
} catch {
|
|
7947
|
-
}
|
|
7948
|
-
});
|
|
7949
|
-
} catch {
|
|
7950
|
-
}
|
|
7951
|
-
}
|
|
7952
|
-
function reportIfOutdated(currentVersion2) {
|
|
7953
|
-
const result = import_cross_spawn2.default.sync("npm", ["view", PACKAGE_NAME, "version"], {
|
|
7954
|
-
encoding: "utf8",
|
|
7955
|
-
timeout: REGISTRY_TIMEOUT_MS,
|
|
7956
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
7957
|
-
});
|
|
7958
|
-
if (result.error || result.status !== 0) {
|
|
7959
|
-
return;
|
|
7960
|
-
}
|
|
7961
|
-
const latestVersion = (result.stdout ?? "").trim();
|
|
7962
|
-
if (!latestVersion || !isNewerVersion(latestVersion, currentVersion2)) {
|
|
7963
|
-
return;
|
|
7964
|
-
}
|
|
7965
|
-
logger.info("");
|
|
7966
|
-
logger.info(`A new version of ${PACKAGE_NAME} is available: ${latestVersion}`);
|
|
7967
|
-
logger.info(` Current version: ${currentVersion2}`);
|
|
7968
|
-
logger.info(` Update with: npm install -g ${PACKAGE_NAME}@latest`);
|
|
7969
|
-
logger.info("");
|
|
7970
|
-
}
|
|
7971
|
-
function isNewerVersion(candidate, current) {
|
|
7972
|
-
const candidateParts = releaseTriple(candidate);
|
|
7973
|
-
const currentParts = releaseTriple(current);
|
|
7974
|
-
if (!candidateParts || !currentParts) {
|
|
7975
|
-
return false;
|
|
7976
|
-
}
|
|
7977
|
-
for (const [index, candidatePart] of candidateParts.entries()) {
|
|
7978
|
-
if (candidatePart !== currentParts[index]) {
|
|
7979
|
-
return candidatePart > currentParts[index];
|
|
7980
|
-
}
|
|
7981
|
-
}
|
|
7982
|
-
return false;
|
|
7983
|
-
}
|
|
7984
|
-
function releaseTriple(version) {
|
|
7985
|
-
const match = /^(\d+)\.(\d+)\.(\d+)/.exec(version.trim());
|
|
7986
|
-
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : void 0;
|
|
7987
|
-
}
|
|
7988
|
-
function readCliVersion(packageDirectory) {
|
|
7989
|
-
try {
|
|
7990
|
-
const manifestPath = (0, import_node_path31.join)(packageDirectory, "..", "package.json");
|
|
7991
|
-
const manifest = JSON.parse((0, import_node_fs23.readFileSync)(manifestPath, "utf8"));
|
|
7992
|
-
return manifest.version ?? "0.0.0";
|
|
7993
|
-
} catch {
|
|
7994
|
-
return "0.0.0";
|
|
7995
|
-
}
|
|
7996
|
-
}
|
|
7997
|
-
|
|
7998
8181
|
// src/main.ts
|
|
7999
8182
|
function buildProgram(cliVersion) {
|
|
8000
8183
|
const program = new import_commander.Command();
|
|
@@ -8024,8 +8207,8 @@ function buildProgram(cliVersion) {
|
|
|
8024
8207
|
});
|
|
8025
8208
|
program.command("doctor").description(
|
|
8026
8209
|
"Check this workspace against the invariants mnci maintains (one ESLint config, no stray .prettierrc, the eslint plugin registered, the resolved eslint major, .npmrc vs the recorded registry, versionActions overrides, nx sync) \u2014 read-only; exits non-zero if anything failed"
|
|
8027
|
-
).action(() => {
|
|
8028
|
-
runDoctor(process.cwd());
|
|
8210
|
+
).option("--json", "print the findings as one JSON document, each with its remedy").action((options) => {
|
|
8211
|
+
runDoctor(process.cwd(), options);
|
|
8029
8212
|
});
|
|
8030
8213
|
program.command("ci").addArgument(new import_commander.Argument("<phase>", "which phase of the pipeline to run").choices(CI_PHASES)).description(
|
|
8031
8214
|
"Run a phase of the CI pipeline here, the same way CI runs it: `verify` is the sync check and then every project (or, in a pull request, the affected ones) through lint, typecheck, test and build. Exits non-zero when it fails"
|
|
@@ -8044,12 +8227,16 @@ function buildProgram(cliVersion) {
|
|
|
8044
8227
|
});
|
|
8045
8228
|
program.command("install").alias("i").argument("[packages...]", "packages to add (a bare name or a pinned spec); omit to install only").description(
|
|
8046
8229
|
"Add a dependency to a specific project using its own toolchain (npm/pip/pub/nuget/go), or \u2014 with no package \u2014 install everything. Each project owns its dependencies, so a package needs a target: 'mnci i -w <project> <package>'"
|
|
8047
|
-
).option(
|
|
8230
|
+
).option(
|
|
8231
|
+
"-w, --workspace <project>",
|
|
8232
|
+
"target project, by directory (apps/foo) or basename (foo); give the flag again for each project",
|
|
8233
|
+
(project, projects) => [...projects, project],
|
|
8234
|
+
[]
|
|
8235
|
+
).option("-D, --save-dev", "add as a development dependency, where the ecosystem distinguishes one").action((packages, options) => {
|
|
8048
8236
|
runInstall(process.cwd(), packages, options);
|
|
8049
8237
|
});
|
|
8050
|
-
program.command("add").addArgument(new import_commander.Argument("[kind]", "project kind").choices(PROJECT_KINDS)).argument("[name]", "project name").description("Add a project by delegating to the matching Nx plugin generator").option("--scope <scope>", "npm scope for a publishable lib (defaults to @<workspace name>)").
|
|
8051
|
-
"--framework <framework>",
|
|
8052
|
-
"node-app only: express | fastify | koa | nest | none (default: none)"
|
|
8238
|
+
program.command("add").addArgument(new import_commander.Argument("[kind]", "project kind").choices(PROJECT_KINDS)).argument("[name]", "project name").description("Add a project by delegating to the matching Nx plugin generator").option("--scope <scope>", "npm scope for a publishable lib (defaults to @<workspace name>)").addOption(
|
|
8239
|
+
new import_commander.Option("--framework <framework>", "node-app only: the web framework (default: none)").choices(["express", "fastify", "koa", "nest", "none"])
|
|
8053
8240
|
).option(
|
|
8054
8241
|
"--empty",
|
|
8055
8242
|
"npm-lib, internal-lib, react-lib, react-internal-lib, node-function-app: scaffold the slice skeleton only, with no sample code or spec"
|
|
@@ -8076,6 +8263,18 @@ function buildProgram(cliVersion) {
|
|
|
8076
8263
|
await runAdd(kind, name, options);
|
|
8077
8264
|
}
|
|
8078
8265
|
);
|
|
8266
|
+
program.command("commands").description("List every command with what it does and how to call it (--json is what an editor builds its menu from)").option("--json", "print the catalog as one JSON document").action((options) => {
|
|
8267
|
+
runCommands(program, options);
|
|
8268
|
+
});
|
|
8269
|
+
program.command("kinds").description("List every project kind that `add` accepts, with its language, a description and the flags that apply").option("--json", "print the kinds as one JSON document").action((options) => {
|
|
8270
|
+
runKinds(options);
|
|
8271
|
+
});
|
|
8272
|
+
program.command("projects").description("List this workspace's projects: directory, ecosystem, the kind mnci recorded and its explicit targets").option("--json", "print the projects as one JSON document").action((options) => {
|
|
8273
|
+
runProjects(process.cwd(), options);
|
|
8274
|
+
});
|
|
8275
|
+
program.command("info").description("Show the installed mnci version, the newest published one, and this workspace's recorded settings").option("--json", "print the report as one JSON document").action((options) => {
|
|
8276
|
+
runInfo(process.cwd(), cliVersion, options);
|
|
8277
|
+
});
|
|
8079
8278
|
program.action(async () => {
|
|
8080
8279
|
await runInteractive();
|
|
8081
8280
|
});
|