@ethisyscore/eslint-plugin-coreconnect 1.71.6 → 1.73.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ethisyscore/eslint-plugin-coreconnect",
3
- "version": "1.71.6",
3
+ "version": "1.73.0",
4
4
  "description": "ESLint rules enforcing EthisysCore plugin frontend conventions. Published so a new rule reaches every plugin on a version bump, rather than being copied into each scaffold and drifting.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -6,16 +6,39 @@
6
6
  * next person who needs it, and that argument does not reach a test file: the shape belongs to one
7
7
  * mock in one file, nobody imports it, and it is deleted when the test is.
8
8
  *
9
- * Measured before adding this: 80 of the estate's convention findings sit in test and mock files,
10
- * 74 of them `no-inline-object-type`, and almost all are the prop type of a hand-rolled MUI stub -
9
+ * Measured before adding this: 80 of the estate's convention findings sit in test files, 74 of them
10
+ * `no-inline-object-type`, and almost all are the prop type of a hand-rolled MUI stub -
11
11
  * `Alert: ({ children, action }: { children?: ReactNode; action?: ReactNode }) => ...`. Naming those
12
12
  * 74 would add 74 aliases that exist only to satisfy a rule, in files where the rule's own rationale
13
13
  * does not apply. A rule that demands ceremony gets switched off, which costs the 679 findings in
14
14
  * shipped code that it is genuinely right about.
15
15
  *
16
- * Deliberately NOT applied to `no-hardcoded-colors` or to any of the `no-local-*` rules. A hardcoded
17
- * colour is trivially fixable anywhere and there is exactly one in a test file estate-wide; and a
18
- * test file that re-declares the shared data grid is exactly the drift those rules exist to catch.
16
+ * ## What counts, and why a basename never can
17
+ *
18
+ * Only the three markers below, all of which say "this file exists to test something":
19
+ * a `__tests__/` or `__mocks__/` directory, or a `.test.` / `.spec.` suffix. They are conventions a
20
+ * bundler, a test runner and a reader all already agree on.
21
+ *
22
+ * A fourth marker was tried and WITHDRAWN: a basename match on `Mock[A-Z]*`, meant to catch "a
23
+ * hand-rolled stub kept beside the code it doubles rather than under `__tests__`". It was wrong,
24
+ * and wrong in the direction that costs most - it exempted SHIPPED code.
25
+ *
26
+ * Every plugin in this estate has `src/services/implementations/mock/Mock<Domain>Service.ts`, and
27
+ * those are not scaffolding. `useProjectService.ts` imports `MockProjectService` statically and
28
+ * picks between it and the real service at runtime on `IS_MOCK_MODE`, so the class is in the
29
+ * production bundle and its shapes are read by the same hooks that read the real service's. The
30
+ * rule's rationale reaches them exactly as it reaches any other source file.
31
+ *
32
+ * Measured on 2026-08-29 across the eight lint-adopting plugins: the basename branch was the ONLY
33
+ * thing exempting 17 findings, and every one of them was in a shipped `Mock*Service.ts` under a
34
+ * `mock/` directory. Nothing legitimate depended on it - the hand-rolled MUI stubs the exemption
35
+ * was written for all sit under `__tests__/` or carry a `.test.` suffix, and stay exempt.
36
+ *
37
+ * Two lessons worth keeping: a heuristic on a NAME cannot tell a test double from a shipped
38
+ * implementation of the same interface, because both are named after what they double; and an
39
+ * exemption that silently widens is worse than a finding, because nothing reports it.
40
+ *
41
+ * ## Why the check lives here
19
42
  *
20
43
  * The glob-shaped alternative - a `files` override in `configs.recommended` - would require that
21
44
  * config to become an array, and every consumer spreads it as an object
@@ -23,6 +46,10 @@
23
46
  * repos at once, so the check lives in the rules, which is also how this package delivers everything
24
47
  * else: on a version bump, with no consumer edit.
25
48
  *
49
+ * Deliberately NOT applied to `no-hardcoded-colors` or to any of the `no-local-*` rules. A hardcoded
50
+ * colour is trivially fixable anywhere and there is exactly one in a test file estate-wide; and a
51
+ * test file that re-declares the shared data grid is exactly the drift those rules exist to catch.
52
+ *
26
53
  * @param {string} filename Absolute or relative path, as ESLint reports it.
27
54
  * @returns {boolean}
28
55
  */
@@ -37,9 +64,6 @@ export function isTestFile(filename) {
37
64
  return (
38
65
  /(^|\/)__tests__\//.test(path) ||
39
66
  /(^|\/)__mocks__\//.test(path) ||
40
- /\.(test|spec)\.[cm]?[jt]sx?$/.test(path) ||
41
- // A hand-rolled stub kept beside the code it doubles rather than under __tests__. Anchored to the
42
- // basename so a legitimate directory like `mockups/` cannot match.
43
- /(^|\/)Mock[A-Z][^/]*\.[cm]?[jt]sx?$/.test(path)
67
+ /\.(test|spec)\.[cm]?[jt]sx?$/.test(path)
44
68
  );
45
69
  }