@ethisyscore/plugin-ui 1.93.0 → 1.95.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 +2 -1
- package/dist/components/connectors/index.cjs +656 -2
- package/dist/components/connectors/index.cjs.map +1 -1
- package/dist/components/connectors/index.d.cts +135 -373
- package/dist/components/connectors/index.d.ts +135 -373
- package/dist/components/connectors/index.js +652 -5
- package/dist/components/connectors/index.js.map +1 -1
- package/dist/components/ui/index.cjs +4 -0
- package/dist/components/ui/index.d.cts +31 -1
- package/dist/components/ui/index.d.ts +31 -1
- package/dist/components/ui/index.js +1 -1
- package/dist/connector-mappings/index.cjs +1061 -0
- package/dist/connector-mappings/index.cjs.map +1 -0
- package/dist/connector-mappings/index.d.cts +1274 -0
- package/dist/connector-mappings/index.d.ts +1274 -0
- package/dist/connector-mappings/index.js +1020 -0
- package/dist/connector-mappings/index.js.map +1 -0
- package/dist/mappingQueryKeys-BcbA0TGy.d.cts +473 -0
- package/dist/mappingQueryKeys-BcbA0TGy.d.ts +473 -0
- package/dist/mcpService-4h3sKDpW.d.cts +35 -0
- package/dist/mcpService-4h3sKDpW.d.ts +35 -0
- package/dist/platform-react/index.cjs +52 -4
- package/dist/platform-react/index.cjs.map +1 -1
- package/dist/platform-react/index.d.cts +30 -35
- package/dist/platform-react/index.d.ts +30 -35
- package/dist/platform-react/index.js +53 -6
- package/dist/platform-react/index.js.map +1 -1
- package/package.json +6 -1
|
@@ -1,404 +1,166 @@
|
|
|
1
|
+
import { C as ConnectorCanonicalField } from '../../mappingQueryKeys-BcbA0TGy.js';
|
|
2
|
+
export { a as CONNECTOR_CONTROL_LABEL, b as ConnectorCanonicalFieldKind, c as ConnectorMappingSuggestionResult, d as ConnectorMappingTranslationEditorProps, e as ConnectorMappingTranslationEditorView, M as MappingCompletenessBanner, f as MappingCompletenessBannerProps, g as MappingCompletenessItem, h as MappingCompletenessResult, i as MappingReadiness, P as PLUGIN_PROVIDER_CONTROL_LABEL, j as PROVIDER_CONTROL_LABEL, k as PROVIDER_OPTION_LABEL, T as TestToolMappingExtractedField, l as TestToolMappingRequest, m as TestToolMappingResult, n as connectorMappingCompletenessQueryKey, o as connectorMappingsQueryKey, p as connectorMappingsRootQueryKey, q as pluginTargetMappingsQueryKey, s as selectIncompleteOperations, r as selectMappingReadiness, t as selectOptionalIncompleteOperations, u as selectRequiredIncompleteOperations } from '../../mappingQueryKeys-BcbA0TGy.js';
|
|
1
3
|
import * as react from 'react';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* mapped and still be incomplete, because the tool's schema does not accept a field the operation
|
|
15
|
-
* requires. Copy that says "not mapped" when it means "fields not mapped" sends the operator to
|
|
16
|
-
* auto-match, which maps tools and cannot close a field gap.
|
|
17
|
-
*/
|
|
18
|
-
interface MappingCompletenessItem {
|
|
19
|
-
/** Canonical operation key, e.g. `list-commits`. */
|
|
20
|
-
operationKey: string;
|
|
21
|
-
/** Human label for the operation, as declared by the module's catalogue. */
|
|
22
|
-
label: string;
|
|
23
|
-
/**
|
|
24
|
-
* Whether the module declares this operation as required. Required gaps block the module from
|
|
25
|
-
* working; optional ones only leave an extra capability switched off.
|
|
26
|
-
*/
|
|
27
|
-
isRequired: boolean;
|
|
28
|
-
/**
|
|
29
|
-
* Whether ANY tool is mapped to the operation. False means the operator has not chosen a tool
|
|
30
|
-
* yet; true says nothing about whether the mapping is complete.
|
|
31
|
-
*/
|
|
32
|
-
isToolMapped: boolean;
|
|
33
|
-
/**
|
|
34
|
-
* Canonical request fields the operation requires that do not map onto a property the live tool
|
|
35
|
-
* actually accepts. Non-empty means incomplete, whether or not a tool is mapped.
|
|
36
|
-
*/
|
|
37
|
-
unmappedRequiredCanonicalFields: string[];
|
|
38
|
-
}
|
|
39
|
-
/** Response envelope for the completeness read, post-unwrap. */
|
|
40
|
-
interface MappingCompletenessResult {
|
|
41
|
-
operations: MappingCompletenessItem[];
|
|
6
|
+
declare const SOURCE: {
|
|
7
|
+
readonly keyword: "keyword";
|
|
8
|
+
readonly ai: "ai";
|
|
9
|
+
readonly manual: "manual";
|
|
10
|
+
};
|
|
11
|
+
/** The vocabulary of `ToolMapping.Source` values the backend writes. Derived so the two cannot drift. */
|
|
12
|
+
type MappingSourceValue = (typeof SOURCE)[keyof typeof SOURCE];
|
|
13
|
+
/** A connector offered in the picker. */
|
|
14
|
+
interface ConnectorMappingViewConnector {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
42
17
|
}
|
|
43
18
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* value verbatim as the field-kind chip, so an unrecognised kind degrades to a label rather than
|
|
48
|
-
* a blank.
|
|
49
|
-
*/
|
|
50
|
-
type ConnectorCanonicalFieldKind = "String" | "Integer" | "Boolean" | "DateTime" | "Object" | "StringArray";
|
|
51
|
-
/**
|
|
52
|
-
* A single canonical field on an operation's request or response schema. Carried on the mapping row
|
|
53
|
-
* so the editor can render an input per field without a separate schema fetch.
|
|
19
|
+
* What serves the module, as this view spells it. Structurally identical to `MappingTargetKind` in
|
|
20
|
+
* the hooks module, declared here for the reason every shape in this file is: the two barrels share
|
|
21
|
+
* types across the boundary only as type-only imports, and this one is two literals.
|
|
54
22
|
*/
|
|
55
|
-
|
|
23
|
+
type ConnectorMappingViewProviderKind = "connector" | "plugin";
|
|
24
|
+
/** An installed application offered in the provider picker. */
|
|
25
|
+
interface ConnectorMappingViewPluginProvider {
|
|
26
|
+
extensionId: string;
|
|
56
27
|
name: string;
|
|
57
|
-
kind: ConnectorCanonicalFieldKind;
|
|
58
|
-
isRequired: boolean;
|
|
59
28
|
}
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
sampleArgs: Record<string, unknown>;
|
|
68
|
-
/** Current unsaved request-field map (empty inputs stripped; `null` if all blank). */
|
|
29
|
+
/** A tool offered in the per-row picker. */
|
|
30
|
+
interface ConnectorMappingViewTool {
|
|
31
|
+
name: string;
|
|
32
|
+
description: string;
|
|
33
|
+
}
|
|
34
|
+
/** The operator-editable translation on one row, as handed to `onEditTranslation`. */
|
|
35
|
+
interface ConnectorMappingViewTranslationState {
|
|
69
36
|
requestFieldMap: Record<string, string> | null;
|
|
70
|
-
/** Current unsaved response-field paths (empty inputs stripped; `null` if all blank). */
|
|
71
37
|
responseFieldPaths: Record<string, string> | null;
|
|
72
|
-
|
|
73
|
-
* Current unsaved static request parameters (blank-key rows dropped; `null` if none). Optional and
|
|
74
|
-
* backward-compatible: it lets the dry-run exercise the DRAFT static params — a consolidated
|
|
75
|
-
* tool's `method` discriminator, say — that the operator typed but has not saved yet. A consumer
|
|
76
|
-
* whose test endpoint does not accept static fields simply ignores it.
|
|
77
|
-
*/
|
|
78
|
-
staticRequestFields?: Record<string, string> | null;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Result of extracting one canonical response field from the tool's raw response. Mirrors the
|
|
82
|
-
* backend `ExtractedFieldResult` DTO.
|
|
83
|
-
*/
|
|
84
|
-
interface TestToolMappingExtractedField {
|
|
85
|
-
canonicalField: string;
|
|
86
|
-
/** Extracted value, or `null` when the path matched nothing. */
|
|
87
|
-
value: string | null;
|
|
88
|
-
/** `true` when the JSON path resolved to a node in the response. */
|
|
89
|
-
present: boolean;
|
|
90
|
-
/**
|
|
91
|
-
* `true` when the extracted value looks like Base64 content (long string, charset
|
|
92
|
-
* `[A-Za-z0-9+/=]`, no whitespace). The editor shows a "prefix with base64:" hint so the operator
|
|
93
|
-
* adjusts the JSON path rather than concluding the mapping is broken.
|
|
94
|
-
*/
|
|
95
|
-
looksBase64: boolean;
|
|
96
|
-
}
|
|
97
|
-
/** Result the consumer's `onTestMapping` callback resolves with, after the dry-run. */
|
|
98
|
-
interface TestToolMappingResult {
|
|
99
|
-
success: boolean;
|
|
100
|
-
/** Error message when `success` is false. */
|
|
101
|
-
error: string | null;
|
|
102
|
-
/**
|
|
103
|
-
* Raw JSON string of the tool's response, shown in a collapsible so the operator can find the
|
|
104
|
-
* right JSON path.
|
|
105
|
-
*/
|
|
106
|
-
rawResponseJson: string | null;
|
|
107
|
-
/** Per-field extraction result. */
|
|
108
|
-
extractedFields: TestToolMappingExtractedField[];
|
|
38
|
+
staticRequestFields: Record<string, string> | null;
|
|
109
39
|
}
|
|
110
|
-
/**
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
requestFieldMap
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
* Empty object `{}` when the model found no response-side rewrites.
|
|
127
|
-
*/
|
|
128
|
-
responseFieldPaths: Record<string, string>;
|
|
40
|
+
/** One row of the mapping table. */
|
|
41
|
+
interface ConnectorMappingViewRow {
|
|
42
|
+
operationKey: string;
|
|
43
|
+
label: string;
|
|
44
|
+
isRequired: boolean;
|
|
45
|
+
mappedToolName: string | null;
|
|
46
|
+
source: MappingSourceValue | null;
|
|
47
|
+
confidence: number | null;
|
|
48
|
+
/** `null` when no stored row exists yet; the view sends `""` up so the host upserts. */
|
|
49
|
+
rowVersion: string | null;
|
|
50
|
+
requiresReview?: boolean;
|
|
51
|
+
canonicalRequestFields?: ConnectorCanonicalField[] | null;
|
|
52
|
+
canonicalResponseFields?: ConnectorCanonicalField[] | null;
|
|
53
|
+
requestFieldMap?: Record<string, string> | null;
|
|
54
|
+
responseFieldPaths?: Record<string, string> | null;
|
|
55
|
+
staticRequestFields?: Record<string, string> | null;
|
|
129
56
|
}
|
|
130
|
-
|
|
131
|
-
interface
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
operations: MappingCompletenessItem[];
|
|
138
|
-
/**
|
|
139
|
-
* Opt-in AI assist. Invoked with the operation the operator chose to fix. The consumer wires this
|
|
140
|
-
* to the suggest-translation mutation and decides what to do with the result (open the editor
|
|
141
|
-
* seeded with the suggestion, apply it, and so on).
|
|
142
|
-
*/
|
|
143
|
-
onSuggestWithAi: (operation: MappingCompletenessItem) => void;
|
|
144
|
-
/**
|
|
145
|
-
* Opens the manual mapping editor for an operation. The consumer owns the editor surface and
|
|
146
|
-
* routing; the banner only raises intent.
|
|
147
|
-
*
|
|
148
|
-
* Every known consumer wires this to the request/response translation editor, which is why the
|
|
149
|
-
* row control is labelled for what it opens rather than for this prop's name. Kept required
|
|
150
|
-
* because it always was: making it optional would let a consumer render rows with no action.
|
|
151
|
-
*/
|
|
152
|
-
onOpenMappingEditor: (operation: MappingCompletenessItem) => void;
|
|
153
|
-
/**
|
|
154
|
-
* OPTIONAL, and the preferred wiring. Jumps straight to the operation's REQUEST-FIELD
|
|
155
|
-
* TRANSLATION editor — the "Configure field translation" surface — rather than to whatever general
|
|
156
|
-
* mapping surface `onOpenMappingEditor` happens to open.
|
|
157
|
-
*
|
|
158
|
-
* @remarks
|
|
159
|
-
* Optional on purpose. This package is pinned independently by every plugin, so a required prop
|
|
160
|
-
* would break every consumer that has not been updated. When it is absent the row falls back to
|
|
161
|
-
* `onOpenMappingEditor` with identical rendering, so an un-updated consumer keeps exactly the
|
|
162
|
-
* behaviour it had and still gains the corrected copy.
|
|
163
|
-
*/
|
|
164
|
-
onConfigureTranslation?: (operation: MappingCompletenessItem) => void;
|
|
165
|
-
/**
|
|
166
|
-
* Operation key currently awaiting an AI suggestion, or `null`. Drives the per-row spinner and
|
|
167
|
-
* disabled state so a slow suggestion does not lock the whole banner.
|
|
168
|
-
*/
|
|
169
|
-
suggestingOperationKey?: string | null;
|
|
170
|
-
/** Disables the AI assist affordance entirely, e.g. AI not configured for the organisation. */
|
|
171
|
-
disableSuggest?: boolean;
|
|
57
|
+
/** Outcome of the most recent auto-match run, as the banner reads it. */
|
|
58
|
+
interface ConnectorMappingViewBannerState {
|
|
59
|
+
aiAvailable: boolean;
|
|
60
|
+
unmatchedRequiredCount: number;
|
|
61
|
+
matchedByKeyword: number;
|
|
62
|
+
matchedByAi: number;
|
|
63
|
+
conflictReason: string | null;
|
|
172
64
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
* It separates two cases:
|
|
180
|
-
*
|
|
181
|
-
* - **Required** operations with unmapped required fields, a warning the operator must act on
|
|
182
|
-
* because the module cannot run them.
|
|
183
|
-
* - **Optional** operations with unmapped required fields, a calm note. These power extra
|
|
184
|
-
* capabilities that stay off until their fields are mapped, and the connector may legitimately
|
|
185
|
-
* expose no suitable tool, so they must never read as a blocking error.
|
|
186
|
-
*
|
|
187
|
-
* Renders nothing when neither group has gaps.
|
|
188
|
-
*
|
|
189
|
-
* @remarks
|
|
190
|
-
* **The wording is load-bearing, and was wrong in the copy this was promoted from.** Both groups are
|
|
191
|
-
* selected on `unmappedRequiredCanonicalFields`, which is about FIELD mapping. The original optional
|
|
192
|
-
* alert was titled "Optional operations not mapped" and said they "stay off until mapped", which
|
|
193
|
-
* describes TOOL mapping. Auto-match maps tools and cannot close a field gap, so an operator who
|
|
194
|
-
* pressed auto-match saw the count refuse to move and reported the banner as broken. It was
|
|
195
|
-
* accurate; the text was not. Every string here therefore says "fields", and both alerts say plainly
|
|
196
|
-
* that auto-match will not clear them.
|
|
197
|
-
*
|
|
198
|
-
* A row without the "No tool mapped" chip already HAS a tool and needs its fields mapped. That chip
|
|
199
|
-
* is the only thing distinguishing the two states, which is why the prose points at it.
|
|
200
|
-
*
|
|
201
|
-
* **The second wording fix, from a production report.** Saying "fields" was necessary but not
|
|
202
|
-
* sufficient. An operator read "fields that aren't mapped to this connector's tools", concluded the
|
|
203
|
-
* TOOL was unmapped (it was not), and had no idea which control closed the gap — the text named an
|
|
204
|
-
* abstraction, "the mapping editor", and never the affordance on screen. So the copy now names the
|
|
205
|
-
* thing that is missing (the REQUEST-FIELD TRANSLATION, canonical field name → the tool's own
|
|
206
|
-
* parameter name) and the control that supplies it ("Configure field translation"), and every
|
|
207
|
-
* listed operation carries that control inline. Their words: "it doesnt really suggest how to fix
|
|
208
|
-
* it".
|
|
209
|
-
*
|
|
210
|
-
* That label is not invented here: it is the verbatim tooltip and aria-label of the per-row gear in
|
|
211
|
-
* every consumer's `ConnectorMappingView` (host gogo-ui, self-healing, tech, timesheets, sales). The
|
|
212
|
-
* prose has to name a string the operator can actually find on the page, so a near-miss paraphrase
|
|
213
|
-
* would reintroduce the defect in a quieter form.
|
|
214
|
-
*/
|
|
215
|
-
declare function MappingCompletenessBanner({ operations, onSuggestWithAi, onOpenMappingEditor, onConfigureTranslation, suggestingOperationKey, disableSuggest, }: MappingCompletenessBannerProps): react.JSX.Element | null;
|
|
216
|
-
|
|
217
|
-
interface ConnectorMappingTranslationEditorProps {
|
|
218
|
-
open: boolean;
|
|
65
|
+
interface ConnectorMappingViewProps {
|
|
66
|
+
isLoading: boolean;
|
|
67
|
+
/** Wire key of the mapping module, e.g. `repo-monitoring`. Not rendered; kept for parity. */
|
|
68
|
+
moduleKey: string;
|
|
69
|
+
/** Human-readable module label, used in the header and the empty state. */
|
|
70
|
+
moduleLabel: string;
|
|
219
71
|
/**
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
* Optional because it is derived from a looked-up operation that may not be found: every caller
|
|
223
|
-
* passes `string | undefined`. The contract claimed required while reality was optional, so this
|
|
224
|
-
* states the truth rather than changing any runtime value.
|
|
72
|
+
* When `true` (the default), the view renders its own `<h1>` plus {@link breadcrumbs}. Set it to
|
|
73
|
+
* `false` on a page that already renders a `PageHeader`, or the title appears twice.
|
|
225
74
|
*/
|
|
226
|
-
|
|
75
|
+
withHeader?: boolean;
|
|
227
76
|
/**
|
|
228
|
-
*
|
|
77
|
+
* Breadcrumb trail rendered under the built-in `<h1>`, and only when {@link withHeader} is true.
|
|
229
78
|
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
79
|
+
* A node rather than an import. Breadcrumbs are plugin-specific — they need that plugin's route
|
|
80
|
+
* table and its menu context — and one of the three plugins this was promoted from had deleted
|
|
81
|
+
* the whole header block rather than lift `PageBreadcrumbs` plus its context and router shim for
|
|
82
|
+
* an import that could never execute. Injecting it means a consumer that wants the built-in
|
|
83
|
+
* header can have it without this package taking on a router dependency, and a consumer that
|
|
84
|
+
* does not simply omits both.
|
|
232
85
|
*/
|
|
233
|
-
|
|
86
|
+
breadcrumbs?: ReactNode;
|
|
234
87
|
/**
|
|
235
|
-
*
|
|
88
|
+
* What to render while {@link isLoading}. Defaults to a plain skeleton block.
|
|
236
89
|
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*/
|
|
240
|
-
canonicalRequestFields?: ConnectorCanonicalField[] | null;
|
|
241
|
-
/** Canonical response fields the editor renders one JSON-path input per. Same nullability. */
|
|
242
|
-
canonicalResponseFields?: ConnectorCanonicalField[] | null;
|
|
243
|
-
/** Currently-persisted request-field translation, or `null` if the operator hasn't supplied one. */
|
|
244
|
-
requestFieldMap: Record<string, string> | null;
|
|
245
|
-
/** Currently-persisted response-field translation, or `null` if the operator hasn't supplied one. */
|
|
246
|
-
responseFieldPaths: Record<string, string> | null;
|
|
247
|
-
/**
|
|
248
|
-
* Currently-persisted static request parameters (tool field name → constant literal value), or
|
|
249
|
-
* `null` if the operator hasn't supplied any. Seeds the "Static request parameters" rows.
|
|
90
|
+
* Injected for the same reason as {@link breadcrumbs}: each plugin has its own page skeleton, and
|
|
91
|
+
* a shared one that did not match would be a visible regression on adoption.
|
|
250
92
|
*/
|
|
251
|
-
|
|
93
|
+
loadingFallback?: ReactNode;
|
|
94
|
+
connectors: ConnectorMappingViewConnector[];
|
|
95
|
+
selectedConnectorId: string;
|
|
96
|
+
onConnectorChange: (connectorId: string) => void;
|
|
252
97
|
/**
|
|
253
|
-
*
|
|
254
|
-
* stripped before this fires; if every input on a side was blank, that side is delivered as `null`
|
|
255
|
-
* rather than `{}` so the consumer can pass it straight through and the BE writes a NULL column
|
|
256
|
-
* (which the resolver treats as "no operator override" and falls back to the connector's
|
|
257
|
-
* vendor-default translation). A populated dictionary means "rewrite these fields explicitly"; the
|
|
258
|
-
* BE persists it verbatim and the resolver applies it on top of vendor defaults.
|
|
98
|
+
* What currently serves the module, or `undefined` when the operator has made no choice.
|
|
259
99
|
*
|
|
260
|
-
* `
|
|
261
|
-
*
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
100
|
+
* `undefined` is a real state and is NOT rendered as "connector". An unconfigured module and a
|
|
101
|
+
* module pointed at a connector with nothing mapped yet look similar and need different actions,
|
|
102
|
+
* and defaulting here is how an operator ends up sent to the wrong control.
|
|
103
|
+
*/
|
|
104
|
+
providerKind?: ConnectorMappingViewProviderKind;
|
|
105
|
+
/** Supplying this is what turns the provider picker on. See the block comment above. */
|
|
106
|
+
onProviderKindChange?: (kind: ConnectorMappingViewProviderKind) => void;
|
|
107
|
+
/** The installed applications on offer. Only read while {@link providerKind} is `"plugin"`. */
|
|
108
|
+
pluginProviders?: ConnectorMappingViewPluginProvider[];
|
|
109
|
+
/** The chosen application, or `""`. */
|
|
110
|
+
selectedPluginExtensionId?: string;
|
|
111
|
+
onPluginProviderChange?: (extensionId: string) => void;
|
|
112
|
+
mappings: ConnectorMappingViewRow[];
|
|
113
|
+
availableTools: ConnectorMappingViewTool[];
|
|
114
|
+
/**
|
|
115
|
+
* Called with `toolName === ""` when the operator clears a row's picker. The consumer routes that
|
|
116
|
+
* to the host's delete tool — see `useConnectorMappingMutations`, which does it — because the
|
|
117
|
+
* set validator rejects an empty tool name.
|
|
118
|
+
*/
|
|
119
|
+
onUpdateMapping: (operationKey: string, toolName: string, rowVersion: string) => void;
|
|
120
|
+
onAutoMatch: () => void;
|
|
121
|
+
isUpdating: boolean;
|
|
122
|
+
isAutoMatching: boolean;
|
|
123
|
+
/** `null` when no outcome banner should render (nothing to say, or the operator dismissed it). */
|
|
124
|
+
bannerState: ConnectorMappingViewBannerState | null;
|
|
125
|
+
onDismissBanner: () => void;
|
|
126
|
+
/**
|
|
127
|
+
* Href of the host's AI-providers settings page. The view owns no routing; the consumer passes
|
|
128
|
+
* the href so the link stays correct across templates and route changes.
|
|
129
|
+
*/
|
|
130
|
+
aiProvidersHref: string;
|
|
131
|
+
/** Href of the selected connector's settings page. Same routing-ownership rule. */
|
|
132
|
+
connectorSettingsHref: string;
|
|
133
|
+
/**
|
|
134
|
+
* Raised by the per-row "Configure field translation" button. Rows with no mapped tool, or with
|
|
135
|
+
* no declared canonical schema, never raise it — the view hides the button for those, because
|
|
136
|
+
* there is nothing operator-meaningful to translate.
|
|
137
|
+
*/
|
|
138
|
+
onEditTranslation: (operationKey: string, current: ConnectorMappingViewTranslationState) => void;
|
|
282
139
|
}
|
|
283
140
|
/**
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
* (request / response): left column shows the canonical field's name + kind chip + required
|
|
287
|
-
* indicator; right column captures the operator-supplied tool field name (request side) or JSON
|
|
288
|
-
* path (response side).
|
|
289
|
-
*
|
|
290
|
-
* <p><b>Identity semantics.</b> An empty input on a field means "identity — pass the canonical name
|
|
291
|
-
* through unchanged". On Save the editor strips empty values; if every input on a side was blank,
|
|
292
|
-
* that side is delivered to `onSave` as <code>null</code> (not <code>{}</code>) so the BE writes a
|
|
293
|
-
* NULL column. The resolver then treats the NULL as "no operator override" and falls back to the
|
|
294
|
-
* connector's vendor-default translation; a populated dictionary means "rewrite these fields
|
|
295
|
-
* explicitly" and applies on top of the vendor default.</p>
|
|
296
|
-
*
|
|
297
|
-
* <p><b>State seeding.</b> The consumer page mounts/unmounts this dialog every time the editor opens
|
|
298
|
-
* (the `open` prop is always `true` in practice — the parent gates rendering via conditional mount),
|
|
299
|
-
* so local state initialises lazily from the props on each mount. This avoids the "setState in
|
|
300
|
-
* useEffect" pattern the eslint react-hooks ruleset blocks, AND keeps the operator's in-flight edits
|
|
301
|
-
* sovereign once the dialog is open — a concurrent refresh of the mapping row doesn't clobber what
|
|
302
|
-
* they're typing.</p>
|
|
141
|
+
* The Tool Mappings table: a connector picker, one row per canonical operation with a tool picker
|
|
142
|
+
* and a source chip, the auto-match control, and the per-row translation affordance.
|
|
303
143
|
*
|
|
304
|
-
*
|
|
305
|
-
* plus `self-healing`, `tech` and `timesheets` — and the copies had already drifted. Three
|
|
306
|
-
* differences were adjudicated on the way in, and each is a reason the duplication was expensive:</p>
|
|
144
|
+
* ## Promoted, not designed here
|
|
307
145
|
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
* `timesheets` had fixed it. Nothing noticed, because there was no single source to notice
|
|
314
|
-
* it against.</li>
|
|
315
|
-
* <li><b>Backgrounds come from the theme (`action.hover`), never a hardcoded
|
|
316
|
-
* <code>rgba()</code>.</b> A literal <code>rgba(0,0,0,0.03)</code> is invisible in dark mode
|
|
317
|
-
* and is what `coreconnect/no-hardcoded-colors` exists to stop.</li>
|
|
318
|
-
* <li><b>No emoji in chip labels.</b> The chips already carry an icon and a semantic colour, so
|
|
319
|
-
* the emoji was a third, untranslatable, screen-reader-hostile encoding of the same state.</li>
|
|
320
|
-
* </ol>
|
|
146
|
+
* This file existed three times — `sales`, `tech` and `timesheets` — and two of the three were
|
|
147
|
+
* BYTE-IDENTICAL at 329 lines. The third was the same file with the header block deleted and one
|
|
148
|
+
* behaviour difference that was a live defect (see {@link renderBanner}). Nothing about it was
|
|
149
|
+
* plugin-specific except two imports, which are now props: the breadcrumbs and the loading
|
|
150
|
+
* skeleton.
|
|
321
151
|
*
|
|
322
|
-
*
|
|
323
|
-
* `coreconnect/no-local-mapping-editor` stops a fifth being written.</p>
|
|
324
|
-
*/
|
|
325
|
-
declare function ConnectorMappingTranslationEditorView({ open, operationLabel, toolName, canonicalRequestFields: canonicalRequestFieldsProp, canonicalResponseFields: canonicalResponseFieldsProp, requestFieldMap, responseFieldPaths, staticRequestFields, onSave, onCancel, onTestMapping, onSuggestTranslation, }: ConnectorMappingTranslationEditorProps): react.JSX.Element;
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Every operation with a gap, required or optional. Use it to decide whether to mount a banner at
|
|
329
|
-
* all, without duplicating the predicate.
|
|
330
|
-
*/
|
|
331
|
-
declare function selectIncompleteOperations(operations: MappingCompletenessItem[]): MappingCompletenessItem[];
|
|
332
|
-
/**
|
|
333
|
-
* REQUIRED operations with a gap. These genuinely block the module: the connector cannot run them.
|
|
334
|
-
*/
|
|
335
|
-
declare function selectRequiredIncompleteOperations(operations: MappingCompletenessItem[]): MappingCompletenessItem[];
|
|
336
|
-
/**
|
|
337
|
-
* OPTIONAL operations with a gap. Informational only: the operation powers an extra capability that
|
|
338
|
-
* stays off until its fields are mapped, and the connector may legitimately expose no suitable tool.
|
|
152
|
+
* ## What it owns and what it does not
|
|
339
153
|
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
|
|
345
|
-
declare function selectOptionalIncompleteOperations(operations: MappingCompletenessItem[]): MappingCompletenessItem[];
|
|
346
|
-
/** A module's readiness, counted over REQUIRED operations only. */
|
|
347
|
-
interface MappingReadiness {
|
|
348
|
-
/** Required operations that are mapped AND have no field gaps. */
|
|
349
|
-
complete: number;
|
|
350
|
-
/** Total required operations declared by the module's catalogue. */
|
|
351
|
-
total: number;
|
|
352
|
-
/** True when every required operation is mapped and complete. */
|
|
353
|
-
isReady: boolean;
|
|
354
|
-
}
|
|
355
|
-
/**
|
|
356
|
-
* Readiness over REQUIRED operations only, for a progress indicator or a "ready" badge.
|
|
154
|
+
* Presentational and fully props-driven. It fetches nothing, writes nothing and routes nowhere —
|
|
155
|
+
* `aiProvidersHref` and `connectorSettingsHref` arrive as strings, and clearing a row's picker
|
|
156
|
+
* emits `onUpdateMapping(key, "", rowVersion)` for the consumer to route. Pair it with
|
|
157
|
+
* `useConnectorToolMappings` from `@ethisyscore/plugin-ui/connector-mappings`, whose `view` bundle
|
|
158
|
+
* spreads straight onto these props.
|
|
357
159
|
*
|
|
358
|
-
*
|
|
359
|
-
*
|
|
360
|
-
*
|
|
361
|
-
* rule came from `ethisyscore-plugin-timesheets`, which had it right while another plugin was
|
|
362
|
-
* reporting optional field gaps in a standing banner.
|
|
363
|
-
*/
|
|
364
|
-
declare function selectMappingReadiness(operations: MappingCompletenessItem[]): MappingReadiness;
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* React-query keys for a connector's tool mappings and the completeness read derived from them.
|
|
368
|
-
*
|
|
369
|
-
* @remarks
|
|
370
|
-
* The completeness key is built as a CHILD of the mappings key, and that nesting is the whole point
|
|
371
|
-
* of shipping these from the SDK rather than letting each plugin declare its own.
|
|
372
|
-
*
|
|
373
|
-
* Completeness is derived state: it is the mappings joined against the live tool schemas. Every write
|
|
374
|
-
* that changes a mapping can change it. When the two keys are siblings, a mutation has to remember to
|
|
375
|
-
* invalidate both, and one plugin duly invalidated only the mappings key — so its "operations aren't
|
|
376
|
-
* fully mapped" banner went stale after every save, clear and auto-match, and stayed stale until the
|
|
377
|
-
* operator navigated away. Nesting means a single `invalidateQueries({ queryKey: mappings })` takes
|
|
378
|
-
* the completeness read with it, and there is nothing left to forget.
|
|
379
|
-
*
|
|
380
|
-
* @example
|
|
381
|
-
* ```ts
|
|
382
|
-
* const mappings = connectorMappingsQueryKey(connectorId, moduleKey);
|
|
383
|
-
*
|
|
384
|
-
* useQuery({ queryKey: mappings, queryFn: ... });
|
|
385
|
-
* useQuery({ queryKey: connectorMappingCompletenessQueryKey(connectorId, moduleKey), queryFn: ... });
|
|
386
|
-
*
|
|
387
|
-
* // One call. Covers both, and any future query keyed beneath the mappings key.
|
|
388
|
-
* queryClient.invalidateQueries({ queryKey: mappings });
|
|
389
|
-
* ```
|
|
390
|
-
*/
|
|
391
|
-
/**
|
|
392
|
-
* Key for the mappings list of one connector + module.
|
|
393
|
-
*
|
|
394
|
-
* `connectorId` is accepted as possibly-undefined because the page renders before a connector is
|
|
395
|
-
* chosen; pair it with `enabled: !!connectorId` rather than branching on the key.
|
|
396
|
-
*/
|
|
397
|
-
declare function connectorMappingsQueryKey(connectorId: string | undefined, moduleKey: string): readonly ["connector-mappings", string | undefined, string];
|
|
398
|
-
/**
|
|
399
|
-
* Key for the completeness read, nested UNDER {@link connectorMappingsQueryKey} so invalidating the
|
|
400
|
-
* mappings prefix always covers it. Do not flatten this into a sibling key.
|
|
160
|
+
* The translation affordance appears only when a row HAS a mapped tool AND declares both canonical
|
|
161
|
+
* schemas. A row with no schema has nothing to translate, and offering the button anyway opens an
|
|
162
|
+
* editor with no fields in it.
|
|
401
163
|
*/
|
|
402
|
-
declare function
|
|
164
|
+
declare function ConnectorMappingView({ isLoading, moduleLabel, breadcrumbs, loadingFallback, connectors, selectedConnectorId, onConnectorChange, providerKind, onProviderKindChange, pluginProviders, selectedPluginExtensionId, onPluginProviderChange, mappings, availableTools, onUpdateMapping, onAutoMatch, isUpdating, isAutoMatching, bannerState, onDismissBanner, onEditTranslation, withHeader, }: ConnectorMappingViewProps): react.JSX.Element;
|
|
403
165
|
|
|
404
|
-
export {
|
|
166
|
+
export { ConnectorCanonicalField, ConnectorMappingView, type ConnectorMappingViewBannerState, type ConnectorMappingViewConnector, type ConnectorMappingViewPluginProvider, type ConnectorMappingViewProps, type ConnectorMappingViewProviderKind, type ConnectorMappingViewRow, type ConnectorMappingViewTool, type ConnectorMappingViewTranslationState };
|