@mnci/cli 1.12.0 → 1.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -12
- package/dist/cli.js +74 -25
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,14 +15,14 @@ config package, a custom CI engine, a dependency-injection step for published
|
|
|
15
15
|
packages, a doctor/drift-sync system to keep it all consistent — already has a
|
|
16
16
|
first-party (or established community) Nx equivalent:
|
|
17
17
|
|
|
18
|
-
| Hand-rolled elsewhere | This CLI uses instead
|
|
19
|
-
| ------------------------------------------ |
|
|
20
|
-
| Template engine + per-project config files | `create-nx-workspace --preset=ts` + `nx g` plugin generators
|
|
21
|
-
| A shared toolchain package for configs | The configs the Nx generators emit (one root ESLint/tsconfig)
|
|
22
|
-
| A custom multi-step CI engine | `nx affected -t lint,test,build` + `nx release` (~60-line pipeline)
|
|
23
|
-
| A dist-package dependency injector | `nx release` updates dependent versions natively
|
|
24
|
-
| Hand-written Azure Function templates | `@nx/node:application` (plain Node app) + a thin Azure Functions v4 overlay
|
|
25
|
-
| doctor/drift sync of tool-owned files | Nothing to drift: this CLI owns 5 small files, Nx owns the rest
|
|
18
|
+
| Hand-rolled elsewhere | This CLI uses instead |
|
|
19
|
+
| ------------------------------------------ | ----------------------------------------------------------------------------- |
|
|
20
|
+
| Template engine + per-project config files | `create-nx-workspace --preset=ts` + `nx g` plugin generators |
|
|
21
|
+
| A shared toolchain package for configs | The configs the Nx generators emit (one root ESLint/tsconfig) |
|
|
22
|
+
| A custom multi-step CI engine | `nx affected -t lint,typecheck,test,build` + `nx release` (~60-line pipeline) |
|
|
23
|
+
| A dist-package dependency injector | `nx release` updates dependent versions natively |
|
|
24
|
+
| Hand-written Azure Function templates | `@nx/node:application` (plain Node app) + a thin Azure Functions v4 overlay |
|
|
25
|
+
| doctor/drift sync of tool-owned files | Nothing to drift: this CLI owns 5 small files, Nx owns the rest |
|
|
26
26
|
|
|
27
27
|
## Commands (deliberately just three)
|
|
28
28
|
|
|
@@ -69,7 +69,8 @@ each a single cross-platform command:
|
|
|
69
69
|
| `npm run build` | `nx run-many -t build` |
|
|
70
70
|
| `npm run lint` | `nx run-many -t lint` |
|
|
71
71
|
| `npm run test` | `nx run-many -t test` |
|
|
72
|
-
| `npm run
|
|
72
|
+
| `npm run typecheck` | `nx run-many -t typecheck` — its own script because a bundler-built project's `build` strips types without reading them |
|
|
73
|
+
| `npm run affected` | `nx affected -t lint,typecheck,test,build` (vs `main`) |
|
|
73
74
|
| `npm run graph` | `nx graph` |
|
|
74
75
|
| `npm run release:preview` | `nx release --dry-run` |
|
|
75
76
|
| `npm run python:install` | fixed Python toolchain (ruff/pytest/build/twine) + editable-install every Python project — the same two guards CI runs, for local dev |
|
|
@@ -146,9 +147,17 @@ same options `new` would have and calls the exact same `applyOverlay` `new`
|
|
|
146
147
|
itself calls — the one function that does every bit of `mnci`-owned file
|
|
147
148
|
writing (`nx.json`'s `release`/`sync`/`generators`/`mnci` blocks, `.npmrc`,
|
|
148
149
|
`eslint.config.mjs`, `.prettierrc.json`, `commitlint.config.mjs`,
|
|
149
|
-
`.husky/commit-msg`, the CI pipeline file(s),
|
|
150
|
-
`
|
|
151
|
-
|
|
150
|
+
`.husky/commit-msg`, the CI pipeline file(s), the
|
|
151
|
+
`<workspace-name>.code-workspace` file, and the curated root `package.json`
|
|
152
|
+
scripts). Nothing else in the workspace — app/lib source, `project.json` targets
|
|
153
|
+
from `mnci add` — is ever touched, and it finishes by running Prettier over the
|
|
154
|
+
result, the same way `new` and every `add` do.
|
|
155
|
+
|
|
156
|
+
The `.code-workspace` file is the one partial case, and deliberately so: its
|
|
157
|
+
folders, settings and extensions are regenerated, but the **`tasks` array is read
|
|
158
|
+
back and carried through unchanged**. Those tasks are per-project state written by
|
|
159
|
+
`mnci add`, not overlay-owned, so regenerating them wholesale would wipe every
|
|
160
|
+
project's build/qa/start entry on upgrade.
|
|
152
161
|
|
|
153
162
|
`upgrade` also **deletes** things, which is stronger than the overwriting it
|
|
154
163
|
has always done — one more reason to run `git diff` first, as the command's own
|
package/dist/cli.js
CHANGED
|
@@ -150,6 +150,13 @@ var import_node_path = require("path");
|
|
|
150
150
|
function readJson(path) {
|
|
151
151
|
return JSON.parse((0, import_node_fs.readFileSync)(path, "utf8"));
|
|
152
152
|
}
|
|
153
|
+
function readCodeWorkspace(path) {
|
|
154
|
+
try {
|
|
155
|
+
return JSON.parse((0, import_node_fs.readFileSync)(path, "utf8").replaceAll(/,(\s*[}\]])/g, "$1"));
|
|
156
|
+
} catch {
|
|
157
|
+
return void 0;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
153
160
|
function toJson(value) {
|
|
154
161
|
return `${JSON.stringify(value, void 0, 2)}
|
|
155
162
|
`;
|
|
@@ -234,10 +241,6 @@ function findCodeWorkspaceFile(workspaceRoot) {
|
|
|
234
241
|
return void 0;
|
|
235
242
|
}
|
|
236
243
|
}
|
|
237
|
-
function readCodeWorkspaceFile(path) {
|
|
238
|
-
const contents = (0, import_node_fs2.readFileSync)(path, "utf8").replaceAll(/,(\s*[}\]])/g, "$1");
|
|
239
|
-
return JSON.parse(contents);
|
|
240
|
-
}
|
|
241
244
|
function projectTask(name, kind) {
|
|
242
245
|
const script = `${name}:${kind}`;
|
|
243
246
|
const base = { label: `${name}: ${kind}`, type: "npm", script, problemMatcher: [] };
|
|
@@ -264,7 +267,7 @@ function registerProjectCommands(workspaceRoot, name, commands) {
|
|
|
264
267
|
if (!codeWorkspacePath) {
|
|
265
268
|
return;
|
|
266
269
|
}
|
|
267
|
-
const workspaceFile =
|
|
270
|
+
const workspaceFile = readCodeWorkspace(codeWorkspacePath) ?? {};
|
|
268
271
|
const label = (task) => task.label ?? "";
|
|
269
272
|
const existingTasks = (workspaceFile.tasks?.tasks ?? []).filter(
|
|
270
273
|
(task) => !label(task).startsWith(`${name}: `)
|
|
@@ -1276,7 +1279,7 @@ __pycache__
|
|
|
1276
1279
|
.ruff_cache
|
|
1277
1280
|
.dart_tool
|
|
1278
1281
|
`;
|
|
1279
|
-
function vscodeWorkspace(workspaceName) {
|
|
1282
|
+
function vscodeWorkspace(workspaceName, existingTasks) {
|
|
1280
1283
|
return JSON.stringify(
|
|
1281
1284
|
{
|
|
1282
1285
|
folders: [{ path: ".", name: workspaceName }],
|
|
@@ -1314,7 +1317,10 @@ function vscodeWorkspace(workspaceName) {
|
|
|
1314
1317
|
"firsttris.vscode-jest-runner"
|
|
1315
1318
|
]
|
|
1316
1319
|
},
|
|
1317
|
-
tasks: {
|
|
1320
|
+
tasks: {
|
|
1321
|
+
version: existingTasks?.version ?? "2.0.0",
|
|
1322
|
+
tasks: existingTasks?.tasks ?? []
|
|
1323
|
+
}
|
|
1318
1324
|
},
|
|
1319
1325
|
null,
|
|
1320
1326
|
2
|
|
@@ -1324,7 +1330,8 @@ var ROOT_SCRIPTS = {
|
|
|
1324
1330
|
build: "nx run-many -t build",
|
|
1325
1331
|
lint: "nx run-many -t lint",
|
|
1326
1332
|
test: "nx run-many -t test",
|
|
1327
|
-
|
|
1333
|
+
typecheck: "nx run-many -t typecheck",
|
|
1334
|
+
affected: "nx affected -t lint,typecheck,test,build",
|
|
1328
1335
|
graph: "nx graph",
|
|
1329
1336
|
"release:preview": "nx release --dry-run",
|
|
1330
1337
|
prepare: "husky"
|
|
@@ -1356,6 +1363,12 @@ function generatorDefaults(stack) {
|
|
|
1356
1363
|
}
|
|
1357
1364
|
function mnciConfig(options) {
|
|
1358
1365
|
return {
|
|
1366
|
+
// Persisted so `mnci upgrade` can name the `<name>.code-workspace` file it
|
|
1367
|
+
// rewrites. Its absence is why upgrade used to write a file literally called
|
|
1368
|
+
// `undefined.code-workspace` and therefore never refreshed the real one —
|
|
1369
|
+
// see `resolveWorkspaceName` in `commands/upgrade.ts`, which still needs a
|
|
1370
|
+
// fallback chain for workspaces generated before this field existed.
|
|
1371
|
+
workspaceName: options.workspaceName,
|
|
1359
1372
|
scope: options.scope,
|
|
1360
1373
|
registry: options.registry,
|
|
1361
1374
|
agent: options.agent,
|
|
@@ -1542,10 +1555,14 @@ steps:
|
|
|
1542
1555
|
displayName: Check formatting (run 'npm run format' locally to fix)
|
|
1543
1556
|
# \`lint\` here also runs any Nx lint targets \`npm run lint\` does not cover \u2014
|
|
1544
1557
|
# notably Python's ruff (every Python project owns a hand-authored \`lint\`
|
|
1545
|
-
# target).
|
|
1546
|
-
#
|
|
1547
|
-
-
|
|
1548
|
-
|
|
1558
|
+
# target). The JS lint runs twice, but Nx caches the repeat instantly.
|
|
1559
|
+
#
|
|
1560
|
+
# \`typecheck\` is load-bearing and not covered by \`build\`: a bundler-built
|
|
1561
|
+
# project (esbuild, swc) strips types without reading them, so a workspace can
|
|
1562
|
+
# build, test and lint green while carrying real type errors. --preset=ts
|
|
1563
|
+
# infers a typecheck target for every project, so this costs one target name.
|
|
1564
|
+
- script: npx nx run-many -t lint,typecheck,test,build
|
|
1565
|
+
displayName: Lint, typecheck, test and build everything
|
|
1549
1566
|
|
|
1550
1567
|
# Pack every app into dist/drop/<type>-<name>.zip via each app's 'package'
|
|
1551
1568
|
# target. Portable guard: skip cleanly when the workspace has no apps yet.
|
|
@@ -1720,10 +1737,15 @@ jobs:
|
|
|
1720
1737
|
name: Check formatting (run 'npm run format' locally to fix)
|
|
1721
1738
|
# \`lint\` here also runs any Nx lint targets \`npm run lint\` does not cover \u2014
|
|
1722
1739
|
# notably Python's ruff (every Python project owns a hand-authored \`lint\`
|
|
1723
|
-
# target).
|
|
1724
|
-
#
|
|
1725
|
-
-
|
|
1726
|
-
|
|
1740
|
+
# target). The JS lint runs twice, but Nx caches the repeat instantly.
|
|
1741
|
+
#
|
|
1742
|
+
# \`typecheck\` is load-bearing and not covered by \`build\`: a bundler-built
|
|
1743
|
+
# project (esbuild, swc) strips types without reading them, so a workspace
|
|
1744
|
+
# can build, test and lint green while carrying real type errors.
|
|
1745
|
+
# --preset=ts infers a typecheck target for every project, so this costs
|
|
1746
|
+
# one target name.
|
|
1747
|
+
- run: npx nx run-many -t lint,typecheck,test,build
|
|
1748
|
+
name: Lint, typecheck, test and build everything
|
|
1727
1749
|
|
|
1728
1750
|
# Pack every app into dist/drop/<type>-<name>.zip via each app's 'package'
|
|
1729
1751
|
# target. Portable guard: skip cleanly when the workspace has no apps yet.
|
|
@@ -1856,10 +1878,12 @@ function applyOverlay(workspaceRoot, options) {
|
|
|
1856
1878
|
writeFileEnsured((0, import_node_path10.join)(workspaceRoot, ".prettierrc.json"), PRETTIER_CONFIG);
|
|
1857
1879
|
writeFileEnsured((0, import_node_path10.join)(workspaceRoot, ".prettierignore"), PRETTIER_IGNORE);
|
|
1858
1880
|
removeNxScaffolding(workspaceRoot);
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
)
|
|
1881
|
+
const codeWorkspacePath = (0, import_node_path10.join)(workspaceRoot, `${options.workspaceName}.code-workspace`);
|
|
1882
|
+
const existing = readCodeWorkspace(codeWorkspacePath);
|
|
1883
|
+
writeFileEnsured(codeWorkspacePath, vscodeWorkspace(options.workspaceName, existing?.tasks));
|
|
1884
|
+
if (options.workspaceName !== "undefined") {
|
|
1885
|
+
(0, import_node_fs6.rmSync)((0, import_node_path10.join)(workspaceRoot, "undefined.code-workspace"), { force: true });
|
|
1886
|
+
}
|
|
1863
1887
|
const publishUrl = pythonPublishUrl(options.registry);
|
|
1864
1888
|
if (options.ci === "azure" || options.ci === "both") {
|
|
1865
1889
|
writeFileEnsured(
|
|
@@ -1976,6 +2000,7 @@ async function runNew(name, options) {
|
|
|
1976
2000
|
}
|
|
1977
2001
|
|
|
1978
2002
|
// src/commands/upgrade.ts
|
|
2003
|
+
var import_node_fs7 = require("fs");
|
|
1979
2004
|
var import_node_path12 = require("path");
|
|
1980
2005
|
function resolveRegistry2(options, persisted) {
|
|
1981
2006
|
if (options.registry === "azure-artifacts" || options.organization && options.artifactsFeed) {
|
|
@@ -2000,7 +2025,22 @@ function resolveRegistry2(options, persisted) {
|
|
|
2000
2025
|
"No registry found in nx.json's persisted config. Pass --registry npm or --registry azure-artifacts (with --organization/--project/--artifacts-feed)."
|
|
2001
2026
|
);
|
|
2002
2027
|
}
|
|
2003
|
-
function
|
|
2028
|
+
function resolveWorkspaceName(workspaceRoot, persisted) {
|
|
2029
|
+
if (persisted.workspaceName) {
|
|
2030
|
+
return persisted.workspaceName;
|
|
2031
|
+
}
|
|
2032
|
+
try {
|
|
2033
|
+
const existing = (0, import_node_fs7.readdirSync)(workspaceRoot).find(
|
|
2034
|
+
(file) => file.endsWith(".code-workspace") && file !== "undefined.code-workspace"
|
|
2035
|
+
);
|
|
2036
|
+
if (existing) {
|
|
2037
|
+
return existing.replace(/\.code-workspace$/, "");
|
|
2038
|
+
}
|
|
2039
|
+
} catch {
|
|
2040
|
+
}
|
|
2041
|
+
return (0, import_node_path12.basename)(workspaceRoot);
|
|
2042
|
+
}
|
|
2043
|
+
function resolveOverlayOptions(workspaceRoot, options, persisted) {
|
|
2004
2044
|
const scope = options.scope ?? persisted.scope;
|
|
2005
2045
|
if (!scope) {
|
|
2006
2046
|
throw new Error("No npm scope found in nx.json's persisted config. Pass --scope explicitly.");
|
|
@@ -2025,7 +2065,15 @@ function resolveOverlayOptions(options, persisted) {
|
|
|
2025
2065
|
"No testRunner found in nx.json's persisted config. Pass --test-runner explicitly."
|
|
2026
2066
|
);
|
|
2027
2067
|
}
|
|
2028
|
-
return {
|
|
2068
|
+
return {
|
|
2069
|
+
workspaceName: resolveWorkspaceName(workspaceRoot, persisted),
|
|
2070
|
+
scope,
|
|
2071
|
+
registry,
|
|
2072
|
+
agent,
|
|
2073
|
+
variableGroup,
|
|
2074
|
+
ci,
|
|
2075
|
+
stack: { testRunner }
|
|
2076
|
+
};
|
|
2029
2077
|
}
|
|
2030
2078
|
function runUpgrade(workspaceRoot, options) {
|
|
2031
2079
|
if (!fileExists((0, import_node_path12.join)(workspaceRoot, "nx.json"))) {
|
|
@@ -2034,11 +2082,12 @@ function runUpgrade(workspaceRoot, options) {
|
|
|
2034
2082
|
);
|
|
2035
2083
|
}
|
|
2036
2084
|
const persisted = readMnciConfig(workspaceRoot);
|
|
2037
|
-
const resolved = resolveOverlayOptions(options, persisted);
|
|
2085
|
+
const resolved = resolveOverlayOptions(workspaceRoot, options, persisted);
|
|
2038
2086
|
logger.step(
|
|
2039
2087
|
"Re-applying the MoNecromanCI overlay (release config, .npmrc, commitlint, pipeline, stack)"
|
|
2040
2088
|
);
|
|
2041
2089
|
applyOverlay(workspaceRoot, resolved);
|
|
2090
|
+
runPrettier(workspaceRoot);
|
|
2042
2091
|
logger.success("Done. Review the changes with `git diff` before committing.");
|
|
2043
2092
|
}
|
|
2044
2093
|
|
|
@@ -2065,7 +2114,7 @@ async function runInteractive() {
|
|
|
2065
2114
|
}
|
|
2066
2115
|
|
|
2067
2116
|
// src/util/versionChecker.ts
|
|
2068
|
-
var
|
|
2117
|
+
var import_node_fs8 = require("fs");
|
|
2069
2118
|
var import_node_path14 = require("path");
|
|
2070
2119
|
var import_cross_spawn2 = __toESM(require("cross-spawn"));
|
|
2071
2120
|
var PACKAGE_NAME = "@mnci/cli";
|
|
@@ -2123,7 +2172,7 @@ function releaseTriple(version) {
|
|
|
2123
2172
|
function readCliVersion(packageDirectory) {
|
|
2124
2173
|
try {
|
|
2125
2174
|
const manifestPath = (0, import_node_path14.join)(packageDirectory, "..", "package.json");
|
|
2126
|
-
const manifest = JSON.parse((0,
|
|
2175
|
+
const manifest = JSON.parse((0, import_node_fs8.readFileSync)(manifestPath, "utf8"));
|
|
2127
2176
|
return manifest.version ?? "0.0.0";
|
|
2128
2177
|
} catch {
|
|
2129
2178
|
return "0.0.0";
|