@mnci/cli 1.17.0 → 1.17.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/README.md CHANGED
@@ -78,7 +78,7 @@ ever needed is noise that trains people to ignore the output.
78
78
  | Check | The failure it catches |
79
79
  | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
80
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 |
81
- | No stray `.prettierrc` | It outranks `.prettierrc.json`, so the whole formatting opinion is silently discarded while both files look fine |
81
+ | No stray `.prettierrc` | It outranks `.prettierrc.mjs`, so the whole formatting opinion is silently discarded while both files look fine |
82
82
  | `@nx/eslint/plugin` registered in `nx.json` | Without it `npm run lint` exits 0 while linting nothing |
83
83
  | The **resolved** `eslint` major | A declared range and an installed version are different things — manifests once said `^10` while the pin said 9 |
84
84
  | `.npmrc` matches the recorded registry | The two registry kinds get different files; an Azure workspace also needs its scope routed |
@@ -152,9 +152,11 @@ that would just fail felt worse than being upfront that it doesn't exist yet.
152
152
  changing one marked only the root pseudo-project — which has no
153
153
  lint/typecheck/test/build target — and the affected-scoped verify step ran
154
154
  nothing at all while reporting green.
155
- 3. Writes `eslint.config.mjs` (three lines importing `@mnci/eslint-config` —
156
- the whole linting opinion, in one root config), `.prettierrc.json` +
157
- `.prettierignore`, `.npmrc` (publish auth — see **Publish auth** below),
155
+ 3. Writes `eslint.config.mjs` (one import from `@mnci/eslint-config` — the whole
156
+ linting opinion, in one root config — plus a commented inventory naming every
157
+ config block and how to override it), `.prettierrc.mjs` (which re-exports
158
+ `@mnci/eslint-config/prettier`, so lint and format ship as one package and
159
+ upgrade together) + `.prettierignore`, `.npmrc` (publish auth — see **Publish auth** below),
158
160
  `commitlint.config.mjs`, a husky `commit-msg` hook, the chosen CI provider's
159
161
  pipeline file(s)
160
162
  (`azure-pipelines.yml` and/or `.github/workflows/ci.yml`, `--ci`, default
@@ -177,7 +179,7 @@ same options `new` would have and calls the exact same `applyOverlay` `new`
177
179
  itself calls — the one function that does every bit of `mnci`-owned file
178
180
  writing (`nx.json`'s `release`/`sync`/`generators`/`namedInputs.sharedGlobals`/
179
181
  `mnci` blocks, `.npmrc`,
180
- `eslint.config.mjs`, `.prettierrc.json`, `commitlint.config.mjs`,
182
+ `eslint.config.mjs`, `.prettierrc.mjs`, `commitlint.config.mjs`,
181
183
  `.husky/commit-msg`, the CI pipeline file(s), `.devcontainer/devcontainer.json`, the
182
184
  `<workspace-name>.code-workspace` file, and the curated root `package.json`
183
185
  scripts). Nothing else in the workspace — app/lib source, `project.json` targets
@@ -194,9 +196,10 @@ project's build/qa/start entry on upgrade.
194
196
  has always done — one more reason to run `git diff` first, as the command's own
195
197
  output tells you to:
196
198
 
197
- - `create-nx-workspace`'s `.prettierrc` and `.vscode/`, both superseded (by
198
- `.prettierrc.json`, which Prettier would otherwise never reach, and by the
199
- `.code-workspace` file).
199
+ - `create-nx-workspace`'s `.prettierrc` and `.vscode/`, plus mnci's own former
200
+ `.prettierrc.json`. The two Prettier files are deleted for the same reason:
201
+ both outrank `.prettierrc.mjs`, which Prettier would otherwise never reach.
202
+ `.vscode/` is superseded by the `.code-workspace` file.
200
203
  - **every per-project `eslint.config.*` under `apps/`, `libs/` and
201
204
  `packages/`.** This is the migration path for a workspace generated before
202
205
  mnci owned linting: without it an upgrade would install the root config while
@@ -251,11 +254,26 @@ switch linting off workspace-wide.)
251
254
 
252
255
  ESLint handles code quality only; **Prettier owns all formatting**, configured
253
256
  for JavaScript Standard Style (no semicolons, single quotes, 2-space indents, no
254
- trailing commas). `mnci` runs Prettier itself at the end of `new` and every
257
+ trailing commas). Both opinions come from the same package: `.prettierrc.mjs`
258
+ re-exports `@mnci/eslint-config/prettier`, so a formatting fix arrives through
259
+ `npm update` exactly as a rule fix does, and the two cannot drift into
260
+ contradicting each other. `mnci` runs Prettier itself at the end of `new` and every
255
261
  `add`, so a generated workspace passes its own `format:check` immediately — Nx's
256
262
  generators emit semicolons and double quotes, and without that pass the first
257
263
  commit buries every real change under generator noise.
258
264
 
265
+ **Finding and overriding a rule.** One root config importing a package is easy to
266
+ own and hard to read: nothing in three lines says which of ~20 plugins reported
267
+ the thing you disagree with. Every block in `@mnci/eslint-config` therefore
268
+ carries a `name` — `mnci/base`, `mnci/react`, `mnci/type-aware`,
269
+ `mnci/prettier-compat` — and the generated `eslint.config.mjs` ships the full list
270
+ as a comment, next to the recipe for overriding one. `npx eslint --inspect-config`
271
+ lists them as ESLint actually resolves them, `npx eslint --print-config <file>`
272
+ shows the merged result for a single file, and an override is a named block
273
+ appended after the spread, since later blocks win. Don't edit the package inside
274
+ `node_modules`: it is a dependency, and `npm update` will replace it.
275
+ `packages/eslint-config/README.md` has the block-by-block table.
276
+
259
277
  One caveat worth knowing: `space-before-function-paren`, Standard's signature
260
278
  rule, is **not** enforced. Prettier rewrites `function f (a)` to `function f(a)`
261
279
  on every run and has closed the corresponding option permanently, so enabling it
package/dist/cli.js CHANGED
@@ -1350,15 +1350,25 @@ var COMMITLINT_CONFIG = `export default { extends: ['@commitlint/config-conventi
1350
1350
  `;
1351
1351
  var COMMIT_MSG_HOOK = `npx --no -- commitlint --edit "$1"
1352
1352
  `;
1353
- var PRETTIER_CONFIG = `{
1354
- "semi": false,
1355
- "singleQuote": true,
1356
- "trailingComma": "none",
1357
- "arrowParens": "avoid",
1358
- "printWidth": 100,
1359
- "tabWidth": 2,
1360
- "useTabs": false
1361
- }
1353
+ var PRETTIER_CONFIG = `// The formatting half of @mnci/eslint-config.
1354
+ //
1355
+ // Prettier's options live in the same package as the ESLint rules on purpose:
1356
+ // linting and formatting are one decision. \`eslint-config-prettier\` is composed
1357
+ // last inside that package so every formatting rule defers to these settings, and
1358
+ // splitting the two across packages means a version pair that can drift until
1359
+ // \`npm run lint\` and \`npm run format:check\` disagree with each other.
1360
+ //
1361
+ // Consuming it as a shareable config also means a formatting fix reaches this
1362
+ // workspace through \`npm update\`, the same way a rule change does, instead of
1363
+ // waiting for \`mnci upgrade\` to rewrite a file.
1364
+ //
1365
+ // TO OVERRIDE an option, spread it rather than re-exporting:
1366
+ //
1367
+ // import mnci from '@mnci/eslint-config/prettier'
1368
+ // export default { ...mnci, printWidth: 120 }
1369
+ //
1370
+ // TO SEE the resolved options for a file: npx prettier --find-config-path <file>
1371
+ export { default } from '@mnci/eslint-config/prettier'
1362
1372
  `;
1363
1373
  var ESLINT_CONFIG_VERSION = "^0.1.0";
1364
1374
  function eslintConfigSpec() {
@@ -1415,8 +1425,61 @@ function eslintToolchainDependencies(nxVersion) {
1415
1425
  "@mnci/eslint-config": eslintConfigSpec()
1416
1426
  };
1417
1427
  }
1428
+ var ESLINT_BLOCK_INVENTORY = `// WHAT IS IN HERE. Each line is one config block, by the \`name\` it carries.
1429
+ //
1430
+ // mnci/ignores paths never linted (dist, coverage, .venv, \u2026)
1431
+ // mnci/base JS/TS correctness \u2014 @eslint/js, eslint-plugin-unicorn,
1432
+ // -promise, -n, -unused-imports
1433
+ // typescript-eslint/* typescript-eslint's own recommended blocks
1434
+ // mnci/typescript* TS rules on top of them, no type information needed
1435
+ // mnci/type-aware* the rules that DO read types (no-floating-promises and
1436
+ // friends), scoped to {apps,libs,packages}/*/src
1437
+ // mnci/import-graph import cycles \u2014 eslint-plugin-import-x
1438
+ // mnci/react JSX/TSX \u2014 @eslint-react/eslint-plugin,
1439
+ // eslint-plugin-react-hooks, -react-refresh, -jsx-a11y
1440
+ // mnci/regexp* regex correctness \u2014 eslint-plugin-regexp
1441
+ // mnci/json mnci/jsonc mnci/json5
1442
+ // eslint-plugin-jsonc \u2014 comments are allowed in .jsonc
1443
+ // and tsconfig.json, forbidden in plain .json
1444
+ // mnci/yaml* eslint-plugin-yml \u2014 your CI pipeline files
1445
+ // mnci/toml/base* eslint-plugin-toml, PARSER ONLY: a malformed
1446
+ // pyproject.toml is a syntax error, nothing is styled
1447
+ // mnci/markdown @eslint/markdown
1448
+ // mnci/css @eslint/css
1449
+ // mnci/html @html-eslint/eslint-plugin
1450
+ // mnci/tests *.spec/*.test relaxations \u2014 eslint-plugin-jest
1451
+ // (Vitest's globals too; the two stacks share them)
1452
+ // mnci/nx-dependency-checks @nx/eslint-plugin, on publishable packages' manifests
1453
+ // mnci/prettier-compat eslint-config-prettier \u2014 switches off every rule
1454
+ // Prettier owns. Composed LAST, on purpose.
1455
+ // mnci/stylistic the 3 Standard rules Prettier does not touch
1456
+ //
1457
+ // To list them as ESLint actually resolves them: npx eslint --inspect-config
1458
+ `;
1418
1459
  var ESLINT_CONFIG = `import mnci from '@mnci/eslint-config'
1419
1460
 
1461
+ ${ESLINT_BLOCK_INVENTORY}//
1462
+ // TO OVERRIDE a rule, append a block AFTER the spread \u2014 later blocks win, so one
1463
+ // of your own beats anything above it. Give it a name, so the inspector shows
1464
+ // where the change came from:
1465
+ //
1466
+ // export default [
1467
+ // ...mnci({ workspaceRoot: import.meta.dirname }),
1468
+ // {
1469
+ // name: 'local/legacy-app-allows-any',
1470
+ // files: ['apps/legacy/**/*.ts'],
1471
+ // rules: { '@typescript-eslint/no-explicit-any': 'off' }
1472
+ // }
1473
+ // ]
1474
+ //
1475
+ // Do NOT edit @mnci/eslint-config inside node_modules, and do not fork it: it is
1476
+ // a dependency, so \`npm update\` brings rule fixes in the way it brings any
1477
+ // other. An override here survives that; an edit to the package does not.
1478
+ //
1479
+ // One override cannot work, and it is the one people reach for first:
1480
+ // \`space-before-function-paren\`. Prettier rewrites \`f (a)\` to \`f(a)\` on every
1481
+ // run, so switching that rule on makes \`npm run lint\` and \`npm run format:check\`
1482
+ // impossible to satisfy at the same time. Formatting lives in .prettierrc.mjs.
1420
1483
  export default mnci({ workspaceRoot: import.meta.dirname })
1421
1484
  `;
1422
1485
  var PRETTIER_IGNORE = `node_modules
@@ -2036,7 +2099,7 @@ updates:
2036
2099
  schedule:
2037
2100
  interval: weekly
2038
2101
  `;
2039
- var NX_SCAFFOLDING_TO_REMOVE = [".prettierrc", ".vscode"];
2102
+ var NX_SCAFFOLDING_TO_REMOVE = [".prettierrc", ".prettierrc.json", ".vscode"];
2040
2103
  function removeNxScaffolding(workspaceRoot) {
2041
2104
  for (const entry of NX_SCAFFOLDING_TO_REMOVE) {
2042
2105
  (0, import_node_fs6.rmSync)((0, import_node_path11.join)(workspaceRoot, entry), { recursive: true, force: true });
@@ -2106,7 +2169,7 @@ function applyOverlay(workspaceRoot, options) {
2106
2169
  writeFileEnsured(hookPath, COMMIT_MSG_HOOK);
2107
2170
  markExecutable(hookPath);
2108
2171
  writeFileEnsured((0, import_node_path11.join)(workspaceRoot, "eslint.config.mjs"), ESLINT_CONFIG);
2109
- writeFileEnsured((0, import_node_path11.join)(workspaceRoot, ".prettierrc.json"), PRETTIER_CONFIG);
2172
+ writeFileEnsured((0, import_node_path11.join)(workspaceRoot, ".prettierrc.mjs"), PRETTIER_CONFIG);
2110
2173
  writeFileEnsured(
2111
2174
  (0, import_node_path11.join)(workspaceRoot, ".devcontainer/devcontainer.json"),
2112
2175
  devcontainerJson(options.workspaceName)