@ethisyscore/eslint-plugin-coreconnect 1.77.0 → 1.79.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.
|
|
3
|
+
"version": "1.79.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",
|
package/src/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import noHardcodedColors from "./rules/no-hardcoded-colors.js";
|
|
2
2
|
import noInlineObjectType from "./rules/no-inline-object-type.js";
|
|
3
3
|
import noInlineStringUnion from "./rules/no-inline-string-union.js";
|
|
4
|
+
import noLocalCompletenessBanner from "./rules/no-local-completeness-banner.js";
|
|
4
5
|
import noLocalDataGrid from "./rules/no-local-data-grid.js";
|
|
5
6
|
import noLocalDateInput from "./rules/no-local-date-input.js";
|
|
6
7
|
import noLocalEmptyState from "./rules/no-local-empty-state.js";
|
|
@@ -12,6 +13,7 @@ const rules = {
|
|
|
12
13
|
"no-hardcoded-colors": noHardcodedColors,
|
|
13
14
|
"no-inline-object-type": noInlineObjectType,
|
|
14
15
|
"no-inline-string-union": noInlineStringUnion,
|
|
16
|
+
"no-local-completeness-banner": noLocalCompletenessBanner,
|
|
15
17
|
"no-local-data-grid": noLocalDataGrid,
|
|
16
18
|
"no-local-date-input": noLocalDateInput,
|
|
17
19
|
"no-local-empty-state": noLocalEmptyState,
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disallow a plugin declaring its own connector mapping-completeness banner.
|
|
3
|
+
*
|
|
4
|
+
* The second backstop to the Tool Mappings promotion, and the one that shows why these rules report
|
|
5
|
+
* rather than warn. `MappingCompletenessBanner` moved into
|
|
6
|
+
* `@ethisyscore/plugin-ui/components/connectors` in 1.71.6, and `timesheets` adopted it. Measured on
|
|
7
|
+
* origin/develop months later, `self-healing` and `tech` still carried their own - 126 and 155 lines
|
|
8
|
+
* - and one of them had drifted on the string that matters most:
|
|
9
|
+
*
|
|
10
|
+
* - `self-healing`'s optional-gap alert is titled "Optional operations not mapped". The SDK's, and
|
|
11
|
+
* `tech`'s, read "Optional operations aren't fully mapped".
|
|
12
|
+
*
|
|
13
|
+
* That reads like a wording nit and is not. BOTH alerts select on
|
|
14
|
+
* `unmappedRequiredCanonicalFields`, i.e. on FIELD mapping, but "not mapped" describes TOOL mapping,
|
|
15
|
+
* which is a binary an operator can close with one button. So operators pressed auto-match - which
|
|
16
|
+
* picks the tool and cannot touch its fields - watched the count refuse to move, and raised the
|
|
17
|
+
* banner as broken. It was right; the sentence describing it was wrong, and the cost was paid in
|
|
18
|
+
* support round-trips rather than in a stack trace. Nothing was ever going to catch that in review,
|
|
19
|
+
* because reviewing a copy tells you nothing about the copy next door.
|
|
20
|
+
*
|
|
21
|
+
* Fires on a DECLARATION, never a use, so importing `MappingCompletenessBanner` from
|
|
22
|
+
* `@ethisyscore/plugin-ui/components/connectors` and rendering it is exactly what the rule wants -
|
|
23
|
+
* as is a local wrapper that composes it, which the shared helper exempts.
|
|
24
|
+
*
|
|
25
|
+
* ## Why there is no companion rule for the selectors
|
|
26
|
+
*
|
|
27
|
+
* `mappingCompleteness.ts` - `selectRequiredIncompleteOperations`,
|
|
28
|
+
* `selectOptionalIncompleteOperations`, `selectMappingReadiness` - is duplicated in the same two
|
|
29
|
+
* plugins, and it is where the field-vs-tool predicate actually lives, so it looks like the more
|
|
30
|
+
* dangerous copy. Measured, it is not:
|
|
31
|
+
*
|
|
32
|
+
* - Both plugin copies are BEHAVIOURALLY IDENTICAL to the promoted ones. Diffed against the SDK,
|
|
33
|
+
* they differ only by the type import's source and by selectors they never used being absent.
|
|
34
|
+
* Three copies, months, zero logic drift. What drifted was the prose explaining the predicate to
|
|
35
|
+
* an operator - which lives in the banner, and is what this rule guards.
|
|
36
|
+
* - The local selectors have exactly ONE consumer each, the local banner beside them. No page,
|
|
37
|
+
* hook or service imports them, and `tech`'s `selectIncompleteOperations` is referenced by
|
|
38
|
+
* nothing but its own docstring. So this rule already closes the duplication: `timesheets`,
|
|
39
|
+
* the one plugin that adopted the shared banner, deleted its whole `components/connectors`
|
|
40
|
+
* directory in the same move.
|
|
41
|
+
* - `createNoLocalComponentRule` could not express it anyway. It gates on `isComponentName`
|
|
42
|
+
* (`^[A-Z]`) and on a component-shaped initializer, and a selector is neither. A selectors rule
|
|
43
|
+
* would be new machinery for no coverage any measured file lacks.
|
|
44
|
+
*
|
|
45
|
+
* If a plugin ever imports those selectors somewhere other than its own banner, that reasoning stops
|
|
46
|
+
* holding and the rule becomes worth adding. Nothing in the estate does today.
|
|
47
|
+
*
|
|
48
|
+
* @type {import("eslint").Rule.RuleModule}
|
|
49
|
+
*/
|
|
50
|
+
import { createNoLocalComponentRule } from "./componentDeclarations.js";
|
|
51
|
+
|
|
52
|
+
export default createNoLocalComponentRule({
|
|
53
|
+
// Both a MAPPING context AND the literal `Completeness` AND a banner-shaped suffix. All three are
|
|
54
|
+
// load-bearing, and each was chosen against a count rather than a guess.
|
|
55
|
+
//
|
|
56
|
+
// A bare `Banner$` is unusable: the estate declares 25 other banners, among them
|
|
57
|
+
// `ConnectorWarningBanner`, `AiPlatformStatusBanner`, `PluginRuntimeBanner`, `ErrorBanner`,
|
|
58
|
+
// `SuspiciousActivityBanner`, `PinnedMessagesBanner` and `InvoiceWarningsBanner` - the first of
|
|
59
|
+
// which sits on the very same Tool Mappings page. Requiring `Completeness` spares all of them.
|
|
60
|
+
//
|
|
61
|
+
// A bare `Completeness(Banner|Alert)$` is no better, because `Completeness` is NOT this feature's
|
|
62
|
+
// private word. `repo-monitoring` ships a `DataCompleteness` union ("Complete" |
|
|
63
|
+
// "PartialFallbackApplied" | "Degraded") in both the host contracts and `tech`, and a
|
|
64
|
+
// `DataCompletenessBanner` warning that commit data is degraded is exactly the component that
|
|
65
|
+
// would appear next. So the qualifier alternation is required, and it is the same shape
|
|
66
|
+
// `no-local-mapping-editor` uses: `Mapping` normally, `Connector` or `Tool` for a rename that
|
|
67
|
+
// drops it. A prefixed spelling needs no branch of its own - `ToolMappingCompletenessBanner` ends
|
|
68
|
+
// in the branch-one form already.
|
|
69
|
+
//
|
|
70
|
+
// The suffix set is likewise measured. `Alert` is the MUI component the banner literally renders,
|
|
71
|
+
// so it is the likeliest rename; `Notice` and `Callout` are estate vocabulary (`DeveloperCallout`).
|
|
72
|
+
// `(View|Panel)` is optional so the adapter-view spelling matches. What is deliberately EXCLUDED
|
|
73
|
+
// is the rest of the `MappingCompleteness*` family, which is legitimately duplicated everywhere as
|
|
74
|
+
// wire contracts: `MappingCompletenessItem` (112 references), `MappingCompletenessResult` (34),
|
|
75
|
+
// `ConnectorMappingCompletenessResult`, `GetToolMappingCompletenessResponse` and
|
|
76
|
+
// `MappingCompletenessBannerProps`. Anchoring on a banner-shaped suffix is what keeps them out.
|
|
77
|
+
//
|
|
78
|
+
// Hooks are excluded by the shared helper, which matters here: `useConnectorMappingCompleteness`
|
|
79
|
+
// is a real hook in three repos. Lowercase names are excluded too, which covers
|
|
80
|
+
// `getMappingCompleteness`, `mappingCompleteness`, `dataCompleteness` and
|
|
81
|
+
// `invalidateMappingsAndCompleteness`.
|
|
82
|
+
pattern: /(Mappings?|Connector|Tool)Completeness(Banner|Alert|Notice|Callout)(View|Panel)?$/,
|
|
83
|
+
canonical: {
|
|
84
|
+
source: "@ethisyscore/plugin-ui/components/connectors",
|
|
85
|
+
name: "MappingCompletenessBanner",
|
|
86
|
+
},
|
|
87
|
+
messageId: "noLocalCompletenessBanner",
|
|
88
|
+
description:
|
|
89
|
+
"Disallow a locally-declared mapping completeness banner - import MappingCompletenessBanner from @ethisyscore/plugin-ui/components/connectors",
|
|
90
|
+
message:
|
|
91
|
+
"'{{name}}' re-declares the mapping completeness banner. Import { MappingCompletenessBanner } from '@ethisyscore/plugin-ui/components/connectors' instead: a local copy had already drifted to \"Optional operations not mapped\", which describes TOOL mapping when the alert selects on unmapped FIELDS - so operators pressed auto-match, saw the count refuse to move, and reported the banner as broken. If this reports completeness for something other than connector mappings, rename it so it does not read as one.",
|
|
92
|
+
});
|