@mnci/cli 4.30.0 → 4.32.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 +339 -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) {
|
|
@@ -2563,6 +2569,19 @@ function csharpConsoleProgram(identity) {
|
|
|
2563
2569
|
Console.WriteLine(GreetUseCase.Greet("world").Message);
|
|
2564
2570
|
`;
|
|
2565
2571
|
}
|
|
2572
|
+
function csharpExampleTest(identity) {
|
|
2573
|
+
return `using ${identity};
|
|
2574
|
+
|
|
2575
|
+
public class GreetUseCaseTests
|
|
2576
|
+
{
|
|
2577
|
+
[Fact]
|
|
2578
|
+
public void GreetsAName()
|
|
2579
|
+
{
|
|
2580
|
+
Assert.Equal("Hello, world!", GreetUseCase.Greet("world").Message);
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2583
|
+
`;
|
|
2584
|
+
}
|
|
2566
2585
|
|
|
2567
2586
|
// src/project-scaffolding/post-generation.use-case.ts
|
|
2568
2587
|
var import_node_fs5 = require("fs");
|
|
@@ -2970,6 +2989,21 @@ function writeCsharpExample(absoluteRoot, identity, kind) {
|
|
|
2970
2989
|
writeFileEnsured((0, import_node_path6.join)(absoluteRoot, "Program.cs"), csharpConsoleProgram(identity));
|
|
2971
2990
|
}
|
|
2972
2991
|
}
|
|
2992
|
+
function addCsharpTestProject(workspaceRoot, projectRoot, identity) {
|
|
2993
|
+
const name = (0, import_node_path6.basename)(projectRoot);
|
|
2994
|
+
const testRoot = `tests/${name}`;
|
|
2995
|
+
scaffoldDotnetProject(workspaceRoot, testRoot, `${identity}.Tests`, "xunit");
|
|
2996
|
+
(0, import_node_fs6.rmSync)((0, import_node_path6.join)(workspaceRoot, testRoot, "UnitTest1.cs"), { force: true });
|
|
2997
|
+
writeFileEnsured((0, import_node_path6.join)(workspaceRoot, testRoot, "GreetUseCaseTests.cs"), csharpExampleTest(identity));
|
|
2998
|
+
writeFileEnsured(
|
|
2999
|
+
(0, import_node_path6.join)(workspaceRoot, testRoot, "project.json"),
|
|
3000
|
+
toJson({ name: `${name}-tests`, tags: ["type:csharp-test"] })
|
|
3001
|
+
);
|
|
3002
|
+
const reference = (0, import_node_path6.join)(workspaceRoot, projectRoot, `${identity}.csproj`);
|
|
3003
|
+
if (runShell("dotnet", ["add", (0, import_node_path6.join)(workspaceRoot, testRoot), "reference", reference], workspaceRoot) !== 0) {
|
|
3004
|
+
throw new Error(`dotnet add reference failed for ${testRoot}`);
|
|
3005
|
+
}
|
|
3006
|
+
}
|
|
2973
3007
|
function csharpAppPackageTarget(tag, projectRoot, name) {
|
|
2974
3008
|
const outDir = `dist/apps/${name}`;
|
|
2975
3009
|
const zip = `dist/drop/${tag}-${name}.zip`;
|
|
@@ -2994,6 +3028,7 @@ function addCsharpApp(workspaceRoot, name, template = "console") {
|
|
|
2994
3028
|
const projectRoot = `apps/${name}`;
|
|
2995
3029
|
scaffoldDotnetProject(workspaceRoot, projectRoot, pascalCase(name), template);
|
|
2996
3030
|
writeCsharpExample((0, import_node_path6.join)(workspaceRoot, projectRoot), pascalCase(name), template);
|
|
3031
|
+
addCsharpTestProject(workspaceRoot, projectRoot, pascalCase(name));
|
|
2997
3032
|
addProjectJsonTargets((0, import_node_path6.join)(workspaceRoot, projectRoot, "project.json"), {
|
|
2998
3033
|
package: csharpAppPackageTarget("csharp-app", projectRoot, name),
|
|
2999
3034
|
start: csharpAppStartTarget(projectRoot)
|
|
@@ -3118,6 +3153,7 @@ async function addCsharpLib(workspaceRoot, name, options, kindProvided) {
|
|
|
3118
3153
|
const identity = `${pascalScope(scope)}.${pascalCase(name)}`;
|
|
3119
3154
|
scaffoldDotnetProject(workspaceRoot, projectRoot, identity, "classlib");
|
|
3120
3155
|
writeCsharpExample((0, import_node_path6.join)(workspaceRoot, projectRoot), identity, "classlib");
|
|
3156
|
+
addCsharpTestProject(workspaceRoot, projectRoot, identity);
|
|
3121
3157
|
addInitialVersion((0, import_node_path6.join)(workspaceRoot, projectRoot, `${identity}.csproj`));
|
|
3122
3158
|
writeCsharpVersionActions(workspaceRoot);
|
|
3123
3159
|
addProjectJsonReleaseVersionActions((0, import_node_path6.join)(workspaceRoot, projectRoot, "project.json"));
|
|
@@ -3135,6 +3171,7 @@ function addCsharpInternalLib(workspaceRoot, name) {
|
|
|
3135
3171
|
const identity = pascalCase(name);
|
|
3136
3172
|
scaffoldDotnetProject(workspaceRoot, projectRoot, identity, "classlib");
|
|
3137
3173
|
writeCsharpExample((0, import_node_path6.join)(workspaceRoot, projectRoot), identity, "classlib");
|
|
3174
|
+
addCsharpTestProject(workspaceRoot, projectRoot, identity);
|
|
3138
3175
|
registerProjectCommands(workspaceRoot, name, { build: false });
|
|
3139
3176
|
logger.step(
|
|
3140
3177
|
`Reference it from a consumer with: dotnet add <consumer>.csproj reference ${projectRoot}/${identity}.csproj`
|
|
@@ -3214,6 +3251,7 @@ function addCsharpFunctionApp(workspaceRoot, name) {
|
|
|
3214
3251
|
if (runShell("dotnet", ["restore", projectRoot], workspaceRoot) !== 0) {
|
|
3215
3252
|
throw new Error(`dotnet restore failed for ${projectRoot}`);
|
|
3216
3253
|
}
|
|
3254
|
+
addCsharpTestProject(workspaceRoot, projectRoot, identity);
|
|
3217
3255
|
addProjectJsonTargets((0, import_node_path6.join)(absoluteRoot, "project.json"), {
|
|
3218
3256
|
package: csharpAppPackageTarget("csharp-function-app", projectRoot, name),
|
|
3219
3257
|
start: csharpFunctionAppStartTarget(projectRoot)
|
|
@@ -7023,6 +7061,45 @@ function readWorkspaceStack(workspaceRoot) {
|
|
|
7023
7061
|
};
|
|
7024
7062
|
}
|
|
7025
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
|
+
|
|
7026
7103
|
// src/workspace-diagnostics/check-invariants.use-case.ts
|
|
7027
7104
|
var import_node_child_process = require("child_process");
|
|
7028
7105
|
var import_node_fs19 = require("fs");
|
|
@@ -7302,10 +7379,12 @@ function checkOneTargetsFiles(workspaceRoot, source, targetName, target) {
|
|
|
7302
7379
|
});
|
|
7303
7380
|
}
|
|
7304
7381
|
function checkSync(workspaceRoot) {
|
|
7382
|
+
const result = runCapture("npx", ["nx", "sync:check"], workspaceRoot);
|
|
7305
7383
|
return {
|
|
7306
7384
|
check: "TypeScript project references synced",
|
|
7307
|
-
ok:
|
|
7308
|
-
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()}` : ""}`,
|
|
7309
7388
|
remedy: "run `npx nx sync` and commit the result"
|
|
7310
7389
|
};
|
|
7311
7390
|
}
|
|
@@ -7470,9 +7549,16 @@ function collectFindings(workspaceRoot) {
|
|
|
7470
7549
|
...checkNativeApps(workspaceRoot)
|
|
7471
7550
|
].filter((finding) => finding !== void 0);
|
|
7472
7551
|
}
|
|
7473
|
-
function runDoctor(workspaceRoot) {
|
|
7552
|
+
function runDoctor(workspaceRoot, options = {}) {
|
|
7474
7553
|
const findings = collectFindings(workspaceRoot);
|
|
7475
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
|
+
}
|
|
7476
7562
|
for (const finding of findings) {
|
|
7477
7563
|
if (finding.ok) {
|
|
7478
7564
|
logger.success(finding.check);
|
|
@@ -7491,9 +7577,204 @@ function runDoctor(workspaceRoot) {
|
|
|
7491
7577
|
process.exitCode = 1;
|
|
7492
7578
|
}
|
|
7493
7579
|
|
|
7494
|
-
// src/
|
|
7495
|
-
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
|
|
7496
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");
|
|
7497
7778
|
var NEVER_COPIED = /* @__PURE__ */ new Set([".git", "node_modules"]);
|
|
7498
7779
|
var AGENT_AND_CI_ENTRIES = [
|
|
7499
7780
|
"AGENTS.md",
|
|
@@ -7524,13 +7805,13 @@ var PREFLIGHT_BLOCKERS = [
|
|
|
7524
7805
|
"packages"
|
|
7525
7806
|
];
|
|
7526
7807
|
function assertAdoptableDirectory(target) {
|
|
7527
|
-
if (!(0,
|
|
7808
|
+
if (!(0, import_node_fs21.existsSync)(target)) {
|
|
7528
7809
|
throw new Error(`--into '${target}' does not exist. Create or clone it first.`);
|
|
7529
7810
|
}
|
|
7530
|
-
if (!(0,
|
|
7811
|
+
if (!(0, import_node_fs21.statSync)(target).isDirectory()) {
|
|
7531
7812
|
throw new Error(`--into '${target}' is not a directory.`);
|
|
7532
7813
|
}
|
|
7533
|
-
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)));
|
|
7534
7815
|
if (blockers.length > 0) {
|
|
7535
7816
|
throw new Error(
|
|
7536
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.`
|
|
@@ -7538,15 +7819,15 @@ function assertAdoptableDirectory(target) {
|
|
|
7538
7819
|
}
|
|
7539
7820
|
}
|
|
7540
7821
|
function mergeGitignore(generatedFile, targetFile) {
|
|
7541
|
-
const existing = (0,
|
|
7822
|
+
const existing = (0, import_node_fs21.readFileSync)(targetFile, "utf8");
|
|
7542
7823
|
const present = new Set(existing.split("\n").map((line) => line.trim()));
|
|
7543
|
-
const additions = (0,
|
|
7824
|
+
const additions = (0, import_node_fs21.readFileSync)(generatedFile, "utf8").split("\n").map((line) => line.trimEnd()).filter((line) => {
|
|
7544
7825
|
const trimmed = line.trim();
|
|
7545
7826
|
return trimmed !== "" && !trimmed.startsWith("#") && !present.has(trimmed);
|
|
7546
7827
|
});
|
|
7547
7828
|
if (additions.length === 0) return false;
|
|
7548
7829
|
const separator = existing.endsWith("\n") ? "" : "\n";
|
|
7549
|
-
(0,
|
|
7830
|
+
(0, import_node_fs21.writeFileSync)(
|
|
7550
7831
|
targetFile,
|
|
7551
7832
|
`${existing}${separator}
|
|
7552
7833
|
# Added by mnci (Nx workspace)
|
|
@@ -7556,9 +7837,9 @@ ${additions.join("\n")}
|
|
|
7556
7837
|
return true;
|
|
7557
7838
|
}
|
|
7558
7839
|
function adoptGeneratedWorkspace(generatedRoot, target) {
|
|
7559
|
-
const entries = (0,
|
|
7840
|
+
const entries = (0, import_node_fs21.readdirSync)(generatedRoot).filter((entry) => !NEVER_COPIED.has(entry));
|
|
7560
7841
|
const collisions = entries.filter(
|
|
7561
|
-
(entry) => (0,
|
|
7842
|
+
(entry) => (0, import_node_fs21.existsSync)((0, import_node_path30.join)(target, entry)) && !EXISTING_WINS.has(entry) && entry !== ".gitignore"
|
|
7562
7843
|
);
|
|
7563
7844
|
if (collisions.length > 0) {
|
|
7564
7845
|
throw new Error(
|
|
@@ -7567,28 +7848,28 @@ function adoptGeneratedWorkspace(generatedRoot, target) {
|
|
|
7567
7848
|
}
|
|
7568
7849
|
const result = { copied: [], kept: [], mergedGitignore: false };
|
|
7569
7850
|
for (const entry of entries) {
|
|
7570
|
-
const from = (0,
|
|
7571
|
-
const to = (0,
|
|
7572
|
-
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)) {
|
|
7573
7854
|
result.mergedGitignore = mergeGitignore(from, to);
|
|
7574
7855
|
result.kept.push(entry);
|
|
7575
7856
|
continue;
|
|
7576
7857
|
}
|
|
7577
|
-
if ((0,
|
|
7858
|
+
if ((0, import_node_fs21.existsSync)(to)) {
|
|
7578
7859
|
result.kept.push(entry);
|
|
7579
7860
|
continue;
|
|
7580
7861
|
}
|
|
7581
|
-
(0,
|
|
7862
|
+
(0, import_node_fs21.cpSync)(from, to, { recursive: true });
|
|
7582
7863
|
result.copied.push(entry);
|
|
7583
7864
|
}
|
|
7584
|
-
(0,
|
|
7865
|
+
(0, import_node_fs21.rmSync)(generatedRoot, { recursive: true, force: true });
|
|
7585
7866
|
return result;
|
|
7586
7867
|
}
|
|
7587
7868
|
|
|
7588
7869
|
// src/workspace-creation/create-workspace.use-case.ts
|
|
7589
|
-
var
|
|
7870
|
+
var import_node_fs22 = require("fs");
|
|
7590
7871
|
var import_node_os = require("os");
|
|
7591
|
-
var
|
|
7872
|
+
var import_node_path31 = require("path");
|
|
7592
7873
|
function nxCloudProviderValue(ci) {
|
|
7593
7874
|
return ci === "azure" ? "azure" : "github";
|
|
7594
7875
|
}
|
|
@@ -7631,9 +7912,9 @@ async function resolveRegistry(options) {
|
|
|
7631
7912
|
return await promptRegistry();
|
|
7632
7913
|
}
|
|
7633
7914
|
async function runNew(name, options) {
|
|
7634
|
-
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);
|
|
7635
7916
|
if (adoptTarget !== void 0) assertAdoptableDirectory(adoptTarget);
|
|
7636
|
-
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));
|
|
7637
7918
|
assertValidProjectName(workspaceName, "Workspace name");
|
|
7638
7919
|
const scope = options.scope ?? (options.yes ? `@${workspaceName}` : await promptText("npm scope for publishable packages", `@${workspaceName}`));
|
|
7639
7920
|
const registry = await resolveRegistry(options);
|
|
@@ -7646,8 +7927,8 @@ async function runNew(name, options) {
|
|
|
7646
7927
|
const npmAuth = resolveNpmAuth(options.npmAuth, registry, ci);
|
|
7647
7928
|
const stack = await resolveStack(options);
|
|
7648
7929
|
const nxCloud = options.nxCloud ?? (options.yes ? false : await promptNxCloud());
|
|
7649
|
-
const stagingParent = adoptTarget === void 0 ? process.cwd() : (0,
|
|
7650
|
-
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);
|
|
7651
7932
|
try {
|
|
7652
7933
|
logger.step(`Creating Nx workspace '${workspaceName}' (preset: ts)`);
|
|
7653
7934
|
runNpx(
|
|
@@ -7670,7 +7951,7 @@ async function runNew(name, options) {
|
|
|
7670
7951
|
workspaceRoot = adoptTarget;
|
|
7671
7952
|
}
|
|
7672
7953
|
} finally {
|
|
7673
|
-
if (adoptTarget !== void 0) (0,
|
|
7954
|
+
if (adoptTarget !== void 0) (0, import_node_fs22.rmSync)(stagingParent, { recursive: true, force: true });
|
|
7674
7955
|
}
|
|
7675
7956
|
logger.step(
|
|
7676
7957
|
"Applying MoNecromanCI overlay (VS Code workspace, release config, .npmrc, commitlint, pipeline, stack)"
|
|
@@ -7680,8 +7961,8 @@ async function runNew(name, options) {
|
|
|
7680
7961
|
{ workspaceName, scope, registry, agent, variableGroup, ci, stack, ...npmAuth && { npmAuth } },
|
|
7681
7962
|
logger.detail
|
|
7682
7963
|
);
|
|
7683
|
-
(0,
|
|
7684
|
-
(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 });
|
|
7685
7966
|
logger.step("Installing the toolchain (commitlint + husky + linting/formatting)");
|
|
7686
7967
|
const installStatus = runShell(
|
|
7687
7968
|
"npm",
|
|
@@ -7719,12 +8000,12 @@ function projectKindHintLines(kinds = PROJECT_KINDS) {
|
|
|
7719
8000
|
}
|
|
7720
8001
|
|
|
7721
8002
|
// src/workspace-creation/interactive-wizard.use-case.ts
|
|
7722
|
-
var
|
|
8003
|
+
var import_node_path33 = require("path");
|
|
7723
8004
|
var import_prompts4 = require("@inquirer/prompts");
|
|
7724
8005
|
|
|
7725
8006
|
// src/workspace-upgrade/upgrade-workspace.use-case.ts
|
|
7726
|
-
var
|
|
7727
|
-
var
|
|
8007
|
+
var import_node_fs23 = require("fs");
|
|
8008
|
+
var import_node_path32 = require("path");
|
|
7728
8009
|
function resolveRegistry2(options, persisted) {
|
|
7729
8010
|
if (options.registry === "azure-artifacts" || options.organization && options.artifactsFeed) {
|
|
7730
8011
|
const persistedAzure = persisted?.kind === "azure-artifacts" ? persisted : void 0;
|
|
@@ -7753,7 +8034,7 @@ function resolveWorkspaceName(workspaceRoot, persisted) {
|
|
|
7753
8034
|
return persisted.workspaceName;
|
|
7754
8035
|
}
|
|
7755
8036
|
try {
|
|
7756
|
-
const existing = (0,
|
|
8037
|
+
const existing = (0, import_node_fs23.readdirSync)(workspaceRoot).find(
|
|
7757
8038
|
(file) => file.endsWith(".code-workspace") && file !== "undefined.code-workspace"
|
|
7758
8039
|
);
|
|
7759
8040
|
if (existing) {
|
|
@@ -7761,11 +8042,11 @@ function resolveWorkspaceName(workspaceRoot, persisted) {
|
|
|
7761
8042
|
}
|
|
7762
8043
|
} catch {
|
|
7763
8044
|
}
|
|
7764
|
-
return (0,
|
|
8045
|
+
return (0, import_node_path32.basename)(workspaceRoot);
|
|
7765
8046
|
}
|
|
7766
8047
|
function detectNpmAuth(workspaceRoot) {
|
|
7767
8048
|
try {
|
|
7768
|
-
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;
|
|
7769
8050
|
} catch {
|
|
7770
8051
|
return void 0;
|
|
7771
8052
|
}
|
|
@@ -7812,7 +8093,7 @@ function resolveOverlayOptions(workspaceRoot, options, persisted) {
|
|
|
7812
8093
|
};
|
|
7813
8094
|
}
|
|
7814
8095
|
function runUpgrade(workspaceRoot, options) {
|
|
7815
|
-
if (!fileExists((0,
|
|
8096
|
+
if (!fileExists((0, import_node_path32.join)(workspaceRoot, "nx.json"))) {
|
|
7816
8097
|
throw new Error(
|
|
7817
8098
|
`No nx.json found in ${workspaceRoot} \u2014 this does not look like an Nx workspace. Run 'mnci upgrade' from the workspace root.`
|
|
7818
8099
|
);
|
|
@@ -7877,7 +8158,7 @@ function runUpgrade(workspaceRoot, options) {
|
|
|
7877
8158
|
|
|
7878
8159
|
// src/workspace-creation/interactive-wizard.use-case.ts
|
|
7879
8160
|
async function runInteractive() {
|
|
7880
|
-
const inWorkspace = fileExists((0,
|
|
8161
|
+
const inWorkspace = fileExists((0, import_node_path33.join)(process.cwd(), "nx.json"));
|
|
7881
8162
|
const choiceNew = { name: "Create a new monorepo", value: "new" };
|
|
7882
8163
|
const choiceAdd = { name: "Add a project to this workspace", value: "add" };
|
|
7883
8164
|
const choiceUpgrade = {
|
|
@@ -7897,72 +8178,6 @@ async function runInteractive() {
|
|
|
7897
8178
|
}
|
|
7898
8179
|
}
|
|
7899
8180
|
|
|
7900
|
-
// src/cli-version/check-for-update.use-case.ts
|
|
7901
|
-
var import_node_fs23 = require("fs");
|
|
7902
|
-
var import_node_path31 = require("path");
|
|
7903
|
-
var import_cross_spawn2 = __toESM(require("cross-spawn"));
|
|
7904
|
-
var PACKAGE_NAME = "@mnci/cli";
|
|
7905
|
-
var REGISTRY_TIMEOUT_MS = 2e3;
|
|
7906
|
-
function checkForUpdate(currentVersion2) {
|
|
7907
|
-
try {
|
|
7908
|
-
if (!process.stdout.isTTY) {
|
|
7909
|
-
return;
|
|
7910
|
-
}
|
|
7911
|
-
setImmediate(() => {
|
|
7912
|
-
try {
|
|
7913
|
-
reportIfOutdated(currentVersion2);
|
|
7914
|
-
} catch {
|
|
7915
|
-
}
|
|
7916
|
-
});
|
|
7917
|
-
} catch {
|
|
7918
|
-
}
|
|
7919
|
-
}
|
|
7920
|
-
function reportIfOutdated(currentVersion2) {
|
|
7921
|
-
const result = import_cross_spawn2.default.sync("npm", ["view", PACKAGE_NAME, "version"], {
|
|
7922
|
-
encoding: "utf8",
|
|
7923
|
-
timeout: REGISTRY_TIMEOUT_MS,
|
|
7924
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
7925
|
-
});
|
|
7926
|
-
if (result.error || result.status !== 0) {
|
|
7927
|
-
return;
|
|
7928
|
-
}
|
|
7929
|
-
const latestVersion = (result.stdout ?? "").trim();
|
|
7930
|
-
if (!latestVersion || !isNewerVersion(latestVersion, currentVersion2)) {
|
|
7931
|
-
return;
|
|
7932
|
-
}
|
|
7933
|
-
logger.info("");
|
|
7934
|
-
logger.info(`A new version of ${PACKAGE_NAME} is available: ${latestVersion}`);
|
|
7935
|
-
logger.info(` Current version: ${currentVersion2}`);
|
|
7936
|
-
logger.info(` Update with: npm install -g ${PACKAGE_NAME}@latest`);
|
|
7937
|
-
logger.info("");
|
|
7938
|
-
}
|
|
7939
|
-
function isNewerVersion(candidate, current) {
|
|
7940
|
-
const candidateParts = releaseTriple(candidate);
|
|
7941
|
-
const currentParts = releaseTriple(current);
|
|
7942
|
-
if (!candidateParts || !currentParts) {
|
|
7943
|
-
return false;
|
|
7944
|
-
}
|
|
7945
|
-
for (const [index, candidatePart] of candidateParts.entries()) {
|
|
7946
|
-
if (candidatePart !== currentParts[index]) {
|
|
7947
|
-
return candidatePart > currentParts[index];
|
|
7948
|
-
}
|
|
7949
|
-
}
|
|
7950
|
-
return false;
|
|
7951
|
-
}
|
|
7952
|
-
function releaseTriple(version) {
|
|
7953
|
-
const match = /^(\d+)\.(\d+)\.(\d+)/.exec(version.trim());
|
|
7954
|
-
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : void 0;
|
|
7955
|
-
}
|
|
7956
|
-
function readCliVersion(packageDirectory) {
|
|
7957
|
-
try {
|
|
7958
|
-
const manifestPath = (0, import_node_path31.join)(packageDirectory, "..", "package.json");
|
|
7959
|
-
const manifest = JSON.parse((0, import_node_fs23.readFileSync)(manifestPath, "utf8"));
|
|
7960
|
-
return manifest.version ?? "0.0.0";
|
|
7961
|
-
} catch {
|
|
7962
|
-
return "0.0.0";
|
|
7963
|
-
}
|
|
7964
|
-
}
|
|
7965
|
-
|
|
7966
8181
|
// src/main.ts
|
|
7967
8182
|
function buildProgram(cliVersion) {
|
|
7968
8183
|
const program = new import_commander.Command();
|
|
@@ -7992,8 +8207,8 @@ function buildProgram(cliVersion) {
|
|
|
7992
8207
|
});
|
|
7993
8208
|
program.command("doctor").description(
|
|
7994
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"
|
|
7995
|
-
).action(() => {
|
|
7996
|
-
runDoctor(process.cwd());
|
|
8210
|
+
).option("--json", "print the findings as one JSON document, each with its remedy").action((options) => {
|
|
8211
|
+
runDoctor(process.cwd(), options);
|
|
7997
8212
|
});
|
|
7998
8213
|
program.command("ci").addArgument(new import_commander.Argument("<phase>", "which phase of the pipeline to run").choices(CI_PHASES)).description(
|
|
7999
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"
|
|
@@ -8012,12 +8227,16 @@ function buildProgram(cliVersion) {
|
|
|
8012
8227
|
});
|
|
8013
8228
|
program.command("install").alias("i").argument("[packages...]", "packages to add (a bare name or a pinned spec); omit to install only").description(
|
|
8014
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>'"
|
|
8015
|
-
).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) => {
|
|
8016
8236
|
runInstall(process.cwd(), packages, options);
|
|
8017
8237
|
});
|
|
8018
|
-
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>)").
|
|
8019
|
-
"--framework <framework>",
|
|
8020
|
-
"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"])
|
|
8021
8240
|
).option(
|
|
8022
8241
|
"--empty",
|
|
8023
8242
|
"npm-lib, internal-lib, react-lib, react-internal-lib, node-function-app: scaffold the slice skeleton only, with no sample code or spec"
|
|
@@ -8044,6 +8263,18 @@ function buildProgram(cliVersion) {
|
|
|
8044
8263
|
await runAdd(kind, name, options);
|
|
8045
8264
|
}
|
|
8046
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
|
+
});
|
|
8047
8278
|
program.action(async () => {
|
|
8048
8279
|
await runInteractive();
|
|
8049
8280
|
});
|