@mnci/cli 1.19.8 → 2.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 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)
@@ -86,7 +85,7 @@ ever needed is noise that trains people to ignore the output.
86
85
  | `versionActions` on publishable Dart/Python packages | Its absence aborts `nx release` for the **whole** workspace, not just that project |
87
86
  | `nx sync:check` | A stale TypeScript project reference that was never committed |
88
87
  | Only the chosen linter's config files present | Two formatter configs is not a visible error — each is valid, the CLI picks one, the editor may pick the other, and the two gates disagree silently |
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 |
88
+ | no retired formatter is still configured | a leftover `.prettierrc.mjs` or `.oxfmtrc.json` runs from no command line, but a globally installed editor extension still resolves it and reformats on save, silently undoing Standard |
90
89
 
91
90
  Everything else is plain Nx, surfaced as a small curated set of root scripts —
92
91
  each a single cross-platform command:
@@ -265,90 +264,30 @@ contradicting each other. `mnci` runs Prettier itself at the end of `new` and ev
265
264
  generators emit semicolons and double quotes, and without that pass the first
266
265
  commit buries every real change under generator noise.
267
266
 
268
- **Choosing the linter.** `--linter=eslint` (default) or `--linter=oxlint`, also a
269
- prompt at `mnci new` and overridable on `mnci upgrade`. The formatter rides along
270
- — ESLint pairs with Prettier, oxlint with oxfmt — because both are the same seven
271
- Standard options, so the choice is about speed and toolchain, never about how the
272
- code ends up looking.
273
-
274
- **`oxlint` is a hybrid, not a swap**, and that is deliberate. oxlint parses
275
- JS/TS/JSX/Vue and nothing else, so an oxlint workspace keeps a trimmed ESLint
276
- config (`@mnci/eslint-config`'s `nonJs()`) for the file types oxlint cannot read:
277
-
278
- | | `eslint` | `oxlint` |
279
- | ------------------------------- | -------------------------------------- | -------------------------------------------------------- |
280
- | JS/TS lint | ESLint, 452 rules | oxlint, 206 native + 225 bridged |
281
- | YAML/TOML/MD/CSS/HTML/JSON lint | ESLint | **ESLint** (unchanged) |
282
- | `@nx/dependency-checks` | yes | **yes** (unchanged) |
283
- | Formatter | Prettier | oxfmt (~6x faster on this repo) |
284
- | Formats `.toml` | no — Prettier has no TOML parser | **yes** |
285
- | Config files | `eslint.config.mjs`, `.prettierrc.mjs` | `oxlint.config.ts`, `.oxfmtrc.json`, `eslint.config.mjs` |
286
- | VS Code extension | ESLint + Prettier | Oxc (covers both) + ESLint |
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`.
267
+ **One linter, which is also the formatter.** There is no `--linter` flag and no
268
+ choice to make: `@mnci/eslint-config` carries code quality, type-aware rules and
269
+ JavaScript Standard Style formatting in a single ESLint config at the root.
270
+ `npm run format` is `eslint . --fix --cache`; there is no `format:check`,
271
+ because `lint` already reports formatting as ordinary errors with a rule name,
272
+ a line and a column.
273
+
274
+ That is the point of the arrangement rather than a side effect. A formatter and
275
+ a linter that both hold style opinions have to be kept in agreement, and the
276
+ older setup dodged that only by having ESLint hold *no* style opinion at all —
277
+ which is exactly why a formatting mistake produced no squiggle and no message in
278
+ the editor. It also makes `space-before-function-paren` enforceable for the
279
+ first time: every Prettier-compatible formatter, oxfmt included, rewrites
280
+ `function f (a)` back to `function f(a)`.
281
+
282
+ **Upgrading an older workspace.** `mnci upgrade` deletes every config a previous
283
+ version could have written for a second tool — `.prettierrc`, `.prettierrc.json`,
284
+ `.prettierrc.mjs`, `.prettierignore`, `.oxfmtrc.json`, `oxlint.config.ts` — and
285
+ drops `prettier`, `oxlint`, `oxfmt` and `@mnci/oxlint-config` from
286
+ `devDependencies`. Both halves matter: the files are inert from the command line,
287
+ but an editor extension still resolves them, and the VS Code extension resolves a
288
+ formatter from the **project's** dependencies, so a stale declaration is enough
289
+ to reformat on save against an opinion nothing checks. `mnci doctor` reports a
290
+ workspace that has not been upgraded yet.
352
291
 
353
292
  ## Layout convention = release scoping
354
293