@mnci/cli 1.19.8 → 3.0.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/README.md +50 -114
- package/dist/cli.js +110 -332
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -30,7 +30,6 @@ first-party (or established community) Nx equivalent:
|
|
|
30
30
|
mnci new my-repo # create a monorepo (prompts scope + registry)
|
|
31
31
|
mnci new my-repo --yes --registry npm --scope @my
|
|
32
32
|
mnci new my-repo --yes --registry npm --scope @my --nx-cloud # opt in to Nx Cloud
|
|
33
|
-
mnci new my-repo --yes --registry npm --scope @my --linter oxlint # Rust toolchain
|
|
34
33
|
|
|
35
34
|
cd my-repo
|
|
36
35
|
mnci add react-app web # @nx/react (Vite + Jest)
|
|
@@ -79,14 +78,12 @@ ever needed is noise that trains people to ignore the output.
|
|
|
79
78
|
| Check | The failure it catches |
|
|
80
79
|
| ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
81
80
|
| Exactly one root ESLint config, and no per-project ones | The config fragmenting — every `@nx/*` generator writes one, so each project ends up linting against whichever config sits nearest |
|
|
82
|
-
| No stray `.prettierrc` | It outranks `.prettierrc.mjs`, so the whole formatting opinion is silently discarded while both files look fine |
|
|
83
81
|
| `@nx/eslint/plugin` registered in `nx.json` | Without it `npm run lint` exits 0 while linting nothing |
|
|
84
82
|
| The **resolved** `eslint` major | A declared range and an installed version are different things — manifests once said `^10` while the pin said 9 |
|
|
85
83
|
| `.npmrc` matches the recorded registry | The two registry kinds get different files; an Azure workspace also needs its scope routed |
|
|
86
84
|
| `versionActions` on publishable Dart/Python packages | Its absence aborts `nx release` for the **whole** workspace, not just that project |
|
|
87
85
|
| `nx sync:check` | A stale TypeScript project reference that was never committed |
|
|
88
|
-
|
|
|
89
|
-
| oxlint toolchain declared | `@mnci/oxlint-config` peers on `oxlint`, so a missing declaration turns `npm run lint` into "command not found" at the worst moment |
|
|
86
|
+
| No retired formatter is still configured | A leftover `.prettierrc*`, `.oxfmtrc.json` or `oxlint.config.ts`, or a `prettier`/`oxlint`/`oxfmt` devDependency, runs from no command line — which is what makes it dangerous, since an editor extension still resolves it and reformats on save, undoing Standard after every gate has passed |
|
|
90
87
|
|
|
91
88
|
Everything else is plain Nx, surfaced as a small curated set of root scripts —
|
|
92
89
|
each a single cross-platform command:
|
|
@@ -157,15 +154,14 @@ that would just fail felt worse than being upfront that it doesn't exist yet.
|
|
|
157
154
|
nothing at all while reporting green.
|
|
158
155
|
3. Writes `eslint.config.mjs` (one import from `@mnci/eslint-config` — the whole
|
|
159
156
|
linting opinion, in one root config — plus a commented inventory naming every
|
|
160
|
-
config block and how to override it
|
|
161
|
-
|
|
162
|
-
upgrade together) + `.prettierignore`, `.npmrc` (publish auth — see **Publish auth** below),
|
|
157
|
+
config block and how to override it — there is no formatter config, because
|
|
158
|
+
ESLint is the formatter), `.npmrc` (publish auth — see **Publish auth** below),
|
|
163
159
|
`commitlint.config.mjs`, a husky `commit-msg` hook, the chosen CI provider's
|
|
164
160
|
pipeline file(s)
|
|
165
161
|
(`azure-pipelines.yml` and/or `.github/workflows/ci.yml`, `--ci`, default
|
|
166
162
|
`azure`; `github`/`both` also gets `.github/dependabot.yml` — weekly
|
|
167
163
|
dependency-update PRs), a `<workspace-name>.code-workspace` file (VS Code
|
|
168
|
-
workspace configuration with folder structure, ESLint
|
|
164
|
+
workspace configuration with folder structure, ESLint settings,
|
|
169
165
|
recommended extensions, and an empty `tasks` array that `mnci add` fills in
|
|
170
166
|
per project — see below — open it in VS Code via `File > Open Workspace
|
|
171
167
|
from File`), and the curated root scripts.
|
|
@@ -182,12 +178,12 @@ same options `new` would have and calls the exact same `applyOverlay` `new`
|
|
|
182
178
|
itself calls — the one function that does every bit of `mnci`-owned file
|
|
183
179
|
writing (`nx.json`'s `release`/`sync`/`generators`/`namedInputs.sharedGlobals`/
|
|
184
180
|
`mnci` blocks, `.npmrc`,
|
|
185
|
-
`eslint.config.mjs`,
|
|
181
|
+
`eslint.config.mjs`, `commitlint.config.mjs`,
|
|
186
182
|
`.husky/commit-msg`, the CI pipeline file(s), `.devcontainer/devcontainer.json`, the
|
|
187
183
|
`<workspace-name>.code-workspace` file, and the curated root `package.json`
|
|
188
184
|
scripts). Nothing else in the workspace — app/lib source, `project.json` targets
|
|
189
|
-
from `mnci add` — is ever touched, and it finishes by running
|
|
190
|
-
result, the same way `new` and every `add` do.
|
|
185
|
+
from `mnci add` — is ever touched, and it finishes by running `eslint --fix`
|
|
186
|
+
over the result, the same way `new` and every `add` do.
|
|
191
187
|
|
|
192
188
|
The `.code-workspace` file is the one partial case, and deliberately so: its
|
|
193
189
|
folders, settings and extensions are regenerated, but the **`tasks` array is read
|
|
@@ -199,10 +195,14 @@ project's build/qa/start entry on upgrade.
|
|
|
199
195
|
has always done — one more reason to run `git diff` first, as the command's own
|
|
200
196
|
output tells you to:
|
|
201
197
|
|
|
202
|
-
- `create-nx-workspace`'s `.prettierrc` and `.vscode/`, plus
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
198
|
+
- `create-nx-workspace`'s `.prettierrc` and `.vscode/`, plus every formatter
|
|
199
|
+
config a past mnci version wrote — `.prettierrc.json`, `.prettierrc.mjs`,
|
|
200
|
+
`.prettierignore`, `.oxfmtrc.json`, `oxlint.config.ts`. None of them runs from
|
|
201
|
+
a command line any more, and that is exactly what makes them dangerous: a
|
|
202
|
+
globally installed `esbenp.prettier-vscode` or `oxc.oxc-vscode` still resolves
|
|
203
|
+
one and still reformats on save, undoing Standard while `lint` stays green
|
|
204
|
+
because the damage lands after the check. `.vscode/` is superseded by the
|
|
205
|
+
`.code-workspace` file.
|
|
206
206
|
- **every per-project `eslint.config.*` under `apps/`, `libs/` and
|
|
207
207
|
`packages/`.** This is the migration path for a workspace generated before
|
|
208
208
|
mnci owned linting: without it an upgrade would install the root config while
|
|
@@ -255,100 +255,35 @@ a `lint` target" and "the root config genuinely reports violations in a project
|
|
|
255
255
|
with no config of its own", because a future Nx change there would silently
|
|
256
256
|
switch linting off workspace-wide.)
|
|
257
257
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
A pure swap was considered and rejected: it would leave a duplicate key in a CI
|
|
289
|
-
pipeline, a malformed `pyproject.toml`, and a publishable package's wrong manifest
|
|
290
|
-
all reported by nothing. Switching modes with `mnci upgrade --linter=<other>`
|
|
291
|
-
rewrites the config files **and deletes the mode you left**, so a workspace never
|
|
292
|
-
carries two formatter configs.
|
|
293
|
-
|
|
294
|
-
**Exactly one formatter is declared, and that is a fix rather than tidiness.**
|
|
295
|
-
`prettier` under `eslint`, `oxfmt` under `oxlint`, and switching modes drops the
|
|
296
|
-
other from `devDependencies`. prettier stays in `node_modules` either way, since
|
|
297
|
-
`@mnci/eslint-config` depends on it — so what matters is the _declaration_:
|
|
298
|
-
`esbenp.prettier-vscode` resolves the formatter from the **project's**
|
|
299
|
-
dependencies, so an oxlint workspace that still declared prettier is one where a
|
|
300
|
-
globally installed Prettier extension reformats on save against the opinion oxfmt
|
|
301
|
-
is not applying, while `npm run format:check` (oxfmt) reports the result as
|
|
302
|
-
unformatted. Both configs valid, both binaries resolvable, neither one wrong on
|
|
303
|
-
its own — the `.prettierrc` precedence bug in another costume. `mnci doctor`
|
|
304
|
-
checks it.
|
|
305
|
-
|
|
306
|
-
**oxfmt formats `.toml`; Prettier cannot.** `prettier` on a `.toml` exits with
|
|
307
|
-
`No parser could be inferred for file`, so an oxlint workspace gets a formatted
|
|
308
|
-
`pyproject.toml` and the default cannot — the one gap
|
|
309
|
-
`@mnci/eslint-config`'s parser-only TOML block has always documented as
|
|
310
|
-
unenforceable. It is the only file type where the two formatters differ in what
|
|
311
|
-
they can parse, which is why `[toml]` is pinned for format-on-save under `oxlint`
|
|
312
|
-
only: pinning it under `eslint` would route the file to a formatter that errors
|
|
313
|
-
on it.
|
|
314
|
-
|
|
315
|
-
**Finding and overriding a rule.** One root config importing a package is easy to
|
|
316
|
-
own and hard to read: nothing in three lines says which of ~20 plugins reported
|
|
317
|
-
the thing you disagree with. Every block in `@mnci/eslint-config` therefore
|
|
318
|
-
carries a `name` — `mnci/base`, `mnci/react`, `mnci/type-aware`,
|
|
319
|
-
`mnci/prettier-compat` — and the generated `eslint.config.mjs` ships the full list
|
|
320
|
-
as a comment, next to the recipe for overriding one. `npx eslint --inspect-config`
|
|
321
|
-
lists them as ESLint actually resolves them, `npx eslint --print-config <file>`
|
|
322
|
-
shows the merged result for a single file, and an override is a named block
|
|
323
|
-
appended after the spread, since later blocks win. Don't edit the package inside
|
|
324
|
-
`node_modules`: it is a dependency, and `npm update` will replace it.
|
|
325
|
-
`packages/eslint-config/README.md` has the block-by-block table.
|
|
326
|
-
|
|
327
|
-
One caveat worth knowing: `space-before-function-paren`, Standard's signature
|
|
328
|
-
rule, is **not** enforced. Prettier rewrites `function f (a)` to `function f(a)`
|
|
329
|
-
on every run and has closed the corresponding option permanently, so enabling it
|
|
330
|
-
would make `npm run lint` and `npm run format:check` mutually unsatisfiable.
|
|
331
|
-
Choosing Prettier means accepting its call there.
|
|
332
|
-
|
|
333
|
-
`npm run lint` checks code quality; `npm run format` (write) and
|
|
334
|
-
`npm run format:check` (CI-safe) handle formatting. **Both run in CI**, as
|
|
335
|
-
separate steps: ESLint is configured for correctness only and deliberately
|
|
336
|
-
reports nothing about formatting, so Prettier needs a gate of its own or the
|
|
337
|
-
whole formatting opinion is advisory and a workspace drifts out of compliance
|
|
338
|
-
with no signal anywhere.
|
|
339
|
-
|
|
340
|
-
TypeScript is not a question — every workspace runs the **dual compiler** from
|
|
341
|
-
[Nx's TS 7 guide](https://nx.dev/docs/technologies/typescript/guides/typescript-7):
|
|
342
|
-
`typescript` resolves to a TS 6 package (keeping the programmatic API that Nx's
|
|
343
|
-
graph/plugins, Vite, typescript-eslint and the editor need) while
|
|
344
|
-
`@typescript/native` provides TS 7's native `tsc`. The inferred
|
|
345
|
-
`typecheck`/`build` tasks then run on the **fast TS 7 compiler**, and Nx keeps
|
|
346
|
-
analysing config through the TS 6 API — no target rewiring, frozen per repo by
|
|
347
|
-
the lockfile. (A plain `typescript@7` install would break Nx, since TS 7 ships
|
|
348
|
-
no programmatic API yet; the two aliases are what make it work.)
|
|
349
|
-
|
|
350
|
-
- **Test runner**: passed straight to the `@nx/*` generators; the function app
|
|
351
|
-
gets a matching `jest.config.mjs` (+ ts-jest) or `vitest.config.ts`.
|
|
258
|
+
`mnci` runs `eslint --fix` itself at the end of `new` and every `add`, so a
|
|
259
|
+
generated workspace passes its own `lint` immediately — Nx's generators emit
|
|
260
|
+
semicolons and double quotes, and without that pass the first commit buries every
|
|
261
|
+
real change under generator noise.
|
|
262
|
+
|
|
263
|
+
**One linter, which is also the formatter.** There is no `--linter` flag and no
|
|
264
|
+
choice to make: `@mnci/eslint-config` carries code quality, type-aware rules and
|
|
265
|
+
JavaScript Standard Style formatting in a single ESLint config at the root.
|
|
266
|
+
`npm run format` is `eslint . --fix --cache`; there is no `format:check`,
|
|
267
|
+
because `lint` already reports formatting as ordinary errors with a rule name,
|
|
268
|
+
a line and a column.
|
|
269
|
+
|
|
270
|
+
That is the point of the arrangement rather than a side effect. A formatter and
|
|
271
|
+
a linter that both hold style opinions have to be kept in agreement, and the
|
|
272
|
+
older setup dodged that only by having ESLint hold *no* style opinion at all —
|
|
273
|
+
which is exactly why a formatting mistake produced no squiggle and no message in
|
|
274
|
+
the editor. It also makes `space-before-function-paren` enforceable for the
|
|
275
|
+
first time: every Prettier-compatible formatter, oxfmt included, rewrites
|
|
276
|
+
`function f (a)` back to `function f(a)`.
|
|
277
|
+
|
|
278
|
+
**Upgrading an older workspace.** `mnci upgrade` deletes every config a previous
|
|
279
|
+
version could have written for a second tool — `.prettierrc`, `.prettierrc.json`,
|
|
280
|
+
`.prettierrc.mjs`, `.prettierignore`, `.oxfmtrc.json`, `oxlint.config.ts` — and
|
|
281
|
+
drops `prettier`, `oxlint`, `oxfmt` and `@mnci/oxlint-config` from
|
|
282
|
+
`devDependencies`. Both halves matter: the files are inert from the command line,
|
|
283
|
+
but an editor extension still resolves them, and the VS Code extension resolves a
|
|
284
|
+
formatter from the **project's** dependencies, so a stale declaration is enough
|
|
285
|
+
to reformat on save against an opinion nothing checks. `mnci doctor` reports a
|
|
286
|
+
workspace that has not been upgraded yet.
|
|
352
287
|
|
|
353
288
|
## Layout convention = release scoping
|
|
354
289
|
|
|
@@ -473,8 +408,8 @@ vulnerable transitive package) is exactly what this monorepo's own
|
|
|
473
408
|
attempts automatically.
|
|
474
409
|
|
|
475
410
|
Then `nx sync:check` (fails fast and clearly if the workspace wasn't
|
|
476
|
-
synced+committed locally — see above), then
|
|
477
|
-
|
|
411
|
+
synced+committed locally — see above), then **one verify step** running
|
|
412
|
+
`lint,typecheck,test,build`. `typecheck` is in that list
|
|
478
413
|
because a bundler-built project strips types without reading them, so `build`
|
|
479
414
|
passing proves nothing about type correctness.
|
|
480
415
|
|
|
@@ -483,9 +418,10 @@ project on anything else — including a push to `main`, so a release is always
|
|
|
483
418
|
verified in full. There is deliberately no separate `npm run lint` step: that is
|
|
484
419
|
`nx run-many -t lint`, a strict subset of the list above, and on an
|
|
485
420
|
affected-scoped PR it would re-lint every project and throw the benefit away.
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
421
|
+
|
|
422
|
+
There is no `format:check` step either, and its removal is not a saving but a
|
|
423
|
+
consequence: `lint` reports formatting itself now, so a second step would run
|
|
424
|
+
the same binary twice over the same tree.
|
|
489
425
|
|
|
490
426
|
Every fallback in that step verifies **everything**: no PR target branch, an
|
|
491
427
|
unresolvable merge-base (shallow clone, absent remote branch), any non-PR run.
|