@uipath/insights-tool 1.203.0-preview.205 → 1.204.0-preview.206

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.
@@ -0,0 +1,331 @@
1
+ import {
2
+ FROM_PROCESS_KEY_FLAG,
3
+ TO_PROCESS_KEY_FLAG
4
+ } from "./tool-fqh66108.js";
5
+ import {
6
+ RENDER_CAVEAT,
7
+ caseFlag,
8
+ defaultedFilterValuesSentence,
9
+ findUnknownTables,
10
+ isSavedDashboardId,
11
+ modelFieldIds,
12
+ modelTableIds,
13
+ nothingWritten,
14
+ postDashboardCreate,
15
+ prepareDefinition,
16
+ projectWriteOutcome,
17
+ readAoDashboard,
18
+ serializeJsonFile,
19
+ slotReadCommand,
20
+ writeDashboardGetError,
21
+ writeSlotOccupied
22
+ } from "./tool-sb0hkbsq.js";
23
+ import {
24
+ InsightsHttpError,
25
+ MAESTRO_DASHBOARD_SOURCE_TYPE,
26
+ OutputFormatter,
27
+ RESULTS,
28
+ catchError,
29
+ describePermissionError,
30
+ getFileSystem,
31
+ resolveInsightsConfig,
32
+ writeInsightsFailure
33
+ } from "./tool-bm77ha1d.js";
34
+ import"./tool-1de529jm.js";
35
+
36
+ // src/utils/dashboard-copy.ts
37
+ var COPY_VERB = "copy";
38
+ var COPY_PAST_VERB = "copied";
39
+ function sourceReadCommand(from, source) {
40
+ return source.state === "Saved" ? `uip insights dashboards get ${source.id}` : slotReadCommand(from);
41
+ }
42
+ function buildCopyWording(options, source) {
43
+ return {
44
+ verb: COPY_VERB,
45
+ pastVerb: COPY_PAST_VERB,
46
+ landedAdvice: "The copy succeeded and the row exists, so do not copy again: a second copy into the same slot fails as a duplicate.",
47
+ requestRecovery: `The definition came from the source process, so nothing here is yours to edit. Check ${FROM_PROCESS_KEY_FLAG} names the process you meant, and read it with '${slotReadCommand(options.from)}'.`,
48
+ definitionAdvice: "pick a destination whose slot is free, or free this one by deleting the dashboard that read reports, with 'uip insights dashboards delete <id> --yes'",
49
+ comparisonSource: `the source definition, which '${sourceReadCommand(options.from, source)}' reads`
50
+ };
51
+ }
52
+ var MAX_SOURCE_MESSAGE_LENGTH = 240;
53
+ var CONTROL_CHARACTERS = /[\p{Cc}\p{Cf}]/gu;
54
+ function echoSourceText(text) {
55
+ const flat = text.replace(CONTROL_CHARACTERS, " ");
56
+ return flat.length > MAX_SOURCE_MESSAGE_LENGTH ? `${flat.slice(0, MAX_SOURCE_MESSAGE_LENGTH)}…` : flat;
57
+ }
58
+ function writeCopyReadFailed(error, options, target, subject, flag, readCommand) {
59
+ if (!(error instanceof InsightsHttpError) || error.status !== 404) {
60
+ writeDashboardGetError(error, target);
61
+ return;
62
+ }
63
+ writeInsightsFailure({
64
+ errorCode: "not_found",
65
+ retry: "RetryWillNotFix",
66
+ message: `Insights could not read ${subject}: ${error.message}`,
67
+ instructions: `${nothingWritten(COPY_PAST_VERB)} into process ${options.to.processKey}. Check ${flag} names a Maestro process of the active tenant, and read it on its own with '${readCommand}'.`
68
+ }, error);
69
+ }
70
+ function copySides(options) {
71
+ return [
72
+ {
73
+ slot: options.from,
74
+ flag: FROM_PROCESS_KEY_FLAG,
75
+ subject: `the dashboard of source process ${options.from.processKey}`
76
+ },
77
+ {
78
+ slot: options.to,
79
+ flag: TO_PROCESS_KEY_FLAG,
80
+ subject: `the dashboard slot of destination process ${options.to.processKey}`
81
+ }
82
+ ];
83
+ }
84
+ async function readCopySlot(config, options, side) {
85
+ const [error, definition] = await readAoDashboard(config, side.slot.slotId);
86
+ if (error) {
87
+ writeCopyReadFailed(error, options, side.slot, side.subject, side.flag, slotReadCommand(side.slot));
88
+ return;
89
+ }
90
+ return definition;
91
+ }
92
+ async function readSavedSource(config, options, dashboardId) {
93
+ const [error, definition] = await readAoDashboard(config, dashboardId);
94
+ if (error) {
95
+ writeCopyReadFailed(error, options, {
96
+ kind: "id",
97
+ dashboardId,
98
+ sourceType: MAESTRO_DASHBOARD_SOURCE_TYPE
99
+ }, `dashboard ${dashboardId}, saved for source process ${options.from.processKey}`, FROM_PROCESS_KEY_FLAG, `uip insights dashboards get ${dashboardId}`);
100
+ return;
101
+ }
102
+ return definition;
103
+ }
104
+ var TEMPLATE_COPY_NAMES = {
105
+ process: "Maestro process monitoring",
106
+ case: "Maestro case monitoring"
107
+ };
108
+ function isBlank(name) {
109
+ return name == null || name.trim() === "";
110
+ }
111
+ function buildCopyInput(source, to) {
112
+ const nameDerived = isBlank(source.name);
113
+ const { version: _version, ...input } = source;
114
+ if (!nameDerived) {
115
+ return { input, nameDerived };
116
+ }
117
+ return {
118
+ input: { ...input, name: TEMPLATE_COPY_NAMES[to.slotKind] },
119
+ nameDerived
120
+ };
121
+ }
122
+ function writeDestinationOccupied(to, destination) {
123
+ writeSlotOccupied(to.processKey, destination.id, " and copy never overwrites", `Remove it with 'uip insights dashboards delete ${destination.id} --yes' and copy again, or pick a destination whose slot is free.`);
124
+ }
125
+ function createDirectlyCommand(to) {
126
+ return `uip insights dashboards create --process-key ${to.processKey}${caseFlag(to)} --file <path>`;
127
+ }
128
+ function fixSourceAdvice(source) {
129
+ if (!isSavedDashboardId(source.id)) {
130
+ return;
131
+ }
132
+ return `fix dashboard ${source.id} with 'uip insights dashboards get ${source.id} --output-file <path>', edit it, and 'uip insights dashboards update ${source.id} --file <path> --expected-version ${source.version ?? "<version>"}'`;
133
+ }
134
+ function writeSourceFault(fault, source, options) {
135
+ const { from, to } = options;
136
+ const fixAdvice = fixSourceAdvice(source);
137
+ const choices = fixAdvice === undefined ? `create the correct definition directly with '${createDirectlyCommand(to)}'` : `${fixAdvice} before copying again, or create it into the destination directly with '${createDirectlyCommand(to)}'`;
138
+ writeInsightsFailure({
139
+ errorCode: "invalid_argument",
140
+ retry: "RetryWillNotFix",
141
+ message: `The dashboard of process ${from.processKey} cannot be copied to process ${to.processKey}: ${echoSourceText(fault.message)}`,
142
+ instructions: `${nothingWritten(COPY_PAST_VERB)} into process ${to.processKey}. Either ${choices}.`
143
+ });
144
+ }
145
+ function writeDestinationModelEmpty(options) {
146
+ const { from, to } = options;
147
+ writeInsightsFailure({
148
+ errorCode: "invalid_argument",
149
+ retry: "RetryWillNotFix",
150
+ message: `The dashboard of process ${from.processKey} cannot be copied to process ${to.processKey}: the destination's deployment carries no AO data model, so it has no tables a dashboard can name and every table in the copy would fail to resolve (resolveTableReferences.ts:11-13).`,
151
+ instructions: `${nothingWritten(COPY_PAST_VERB)} into process ${to.processKey}. The source dashboard is not the cause, and a direct create into the destination meets the same empty model. Check '${slotReadCommand(to)}' returns tables for process ${to.processKey}, then copy again.`
152
+ });
153
+ }
154
+ async function writeCopyArtifact(options, path, request) {
155
+ const fs = getFileSystem();
156
+ const [writeError] = await catchError(fs.writeFile(fs.path.resolve(path), serializeJsonFile(request)));
157
+ if (writeError === undefined) {
158
+ return true;
159
+ }
160
+ writeInsightsFailure({
161
+ errorCode: describePermissionError(writeError) ? "local_permission_denied" : "invalid_argument",
162
+ retry: "RetryWillNotFix",
163
+ message: `Failed to write '${path}': ${writeError.message}`,
164
+ instructions: `${nothingWritten(COPY_PAST_VERB)} into process ${options.to.processKey}: the copy stops before the create when its artifact cannot be written. Pass --output-file a writable file path (the parent directories are created for you), or drop the flag and copy again.`
165
+ });
166
+ return false;
167
+ }
168
+ function sourceSentence(outcome) {
169
+ const { from } = outcome.options;
170
+ if (outcome.source.state === "Saved") {
171
+ return `Dashboard ${outcome.source.id}, saved for process ${from.processKey}, was copied.`;
172
+ }
173
+ return `The ${from.slotKind} slot of ${from.processKey} holds no saved dashboard, so what was copied is the built-in ${from.slotKind} monitoring template, with whatever custom variable field definitions that key resolved to. A key that names no Maestro process reads back the same template with none, so confirm ${FROM_PROCESS_KEY_FLAG} with '${slotReadCommand(from)}' before trusting the copy; author on top of the copy if the destination needs different variables.`;
174
+ }
175
+ function updateCopyCommand(outcome) {
176
+ return `uip insights dashboards update ${outcome.createdId} --file <path> --expected-version ${outcome.readBack.version ?? "<version>"}`;
177
+ }
178
+ function nameSentence(outcome) {
179
+ if (!outcome.source.nameDerived) {
180
+ return;
181
+ }
182
+ if (outcome.source.state === "Saved") {
183
+ return `Dashboard ${outcome.source.id} is stored with a blank name, which the create route refuses, so the copy was given a placeholder name; rename it with '${updateCopyCommand(outcome)}'.`;
184
+ }
185
+ return `The source carried no name, so the copy was named after the template it is; rename it with '${updateCopyCommand(outcome)}'.`;
186
+ }
187
+ function sourceOnlyFieldsSentence(outcome) {
188
+ const ids = outcome.source.sourceOnlyFieldIds;
189
+ if (ids.length === 0) {
190
+ return;
191
+ }
192
+ const { from, to } = outcome.options;
193
+ const sample = ids.slice(0, 3).map(echoSourceText).join(", ");
194
+ const more = ids.length > 3 ? ", and more" : "";
195
+ return `${ids.length} field id${ids.length === 1 ? "" : "s"} in the copy ${ids.length === 1 ? "is" : "are"} not in the destination's slot template (${sample}${more}). They come from custom variables process ${from.processKey} declares and process ${to.processKey} does not; whether a chart over such a field draws in the destination is unverified. Declare those variables on process ${to.processKey} in Maestro, or edit the charts that name them with '${updateCopyCommand(outcome)}'.`;
196
+ }
197
+ function slotSentence(outcome) {
198
+ const { to } = outcome.options;
199
+ if (outcome.slotState === "Served") {
200
+ return `The Maestro Monitoring tab of process ${to.processKey} now reads dashboard ${outcome.createdId}.`;
201
+ }
202
+ return `The destination slot could not be re-read after the copy; run '${slotReadCommand(to)}' to confirm it now serves dashboard ${outcome.createdId}.`;
203
+ }
204
+ function buildCopyInstructions(outcome) {
205
+ const parts = [sourceSentence(outcome)];
206
+ for (const sentence of [
207
+ nameSentence(outcome),
208
+ sourceOnlyFieldsSentence(outcome)
209
+ ]) {
210
+ if (sentence !== undefined) {
211
+ parts.push(sentence);
212
+ }
213
+ }
214
+ if (outcome.create.defaultedFilterValues > 0) {
215
+ parts.push(defaultedFilterValuesSentence(outcome.create.defaultedFilterValues));
216
+ }
217
+ parts.push(slotSentence(outcome), "The two dashboards are independent from here: an edit to one does not reach the other, because the copy is a separate row with its own id.");
218
+ if (outcome.options.outputFile !== undefined) {
219
+ parts.push(`The definition as sent was written to ${outcome.options.outputFile} in camelCase with no CLI envelope, before the create.`);
220
+ }
221
+ parts.push(`Read the full definition with 'uip insights dashboards get ${outcome.createdId}'. ${RENDER_CAVEAT}`);
222
+ return parts.join(" ");
223
+ }
224
+ function buildCopyData(outcome) {
225
+ const { options, readBack, source } = outcome;
226
+ const data = {
227
+ dashboardId: outcome.createdId,
228
+ fromProcessKey: options.from.processKey,
229
+ toProcessKey: options.to.processKey,
230
+ slotId: options.to.slotId,
231
+ sourceState: source.state,
232
+ sourceDashboardId: source.id,
233
+ nameDerived: source.nameDerived,
234
+ sourceOnlyFieldIds: source.sourceOnlyFieldIds,
235
+ ...projectWriteOutcome(readBack),
236
+ filterValuesDefaulted: outcome.create.defaultedFilterValues,
237
+ copyState: "Succeeded",
238
+ verificationState: "ReadBackSucceeded",
239
+ slotState: outcome.slotState
240
+ };
241
+ if (options.outputFile !== undefined) {
242
+ data.outputFile = options.outputFile;
243
+ }
244
+ return data;
245
+ }
246
+ async function executeDashboardCopy(options) {
247
+ const config = await resolveInsightsConfig();
248
+ if (config === null) {
249
+ return;
250
+ }
251
+ const [from, to] = copySides(options);
252
+ const sourceSlot = await readCopySlot(config, options, from);
253
+ if (sourceSlot === undefined) {
254
+ return;
255
+ }
256
+ const destinationTemplate = await readCopySlot(config, options, to);
257
+ if (destinationTemplate === undefined) {
258
+ return;
259
+ }
260
+ if (isSavedDashboardId(destinationTemplate.id)) {
261
+ writeDestinationOccupied(options.to, destinationTemplate);
262
+ return;
263
+ }
264
+ const state = isSavedDashboardId(sourceSlot.id) ? "Saved" : "Template";
265
+ const sourceDocument = state === "Saved" ? await readSavedSource(config, options, sourceSlot.id) : sourceSlot;
266
+ if (sourceDocument === undefined) {
267
+ return;
268
+ }
269
+ const prepared = prepareCopy({ document: sourceDocument, state }, destinationTemplate, options);
270
+ if (prepared === undefined) {
271
+ return;
272
+ }
273
+ if (options.outputFile !== undefined && !await writeCopyArtifact(options, options.outputFile, prepared.create.request)) {
274
+ return;
275
+ }
276
+ await sendCopy(config, options, prepared);
277
+ }
278
+ function findSourceOnlyFieldIds(sourceDocument, destinationTemplate) {
279
+ const destinationFields = modelFieldIds(destinationTemplate);
280
+ return [...modelFieldIds(sourceDocument)].filter((id) => !destinationFields.has(id));
281
+ }
282
+ function prepareCopy(source, destinationTemplate, options) {
283
+ const modelTables = modelTableIds(destinationTemplate);
284
+ if (modelTables.size === 0) {
285
+ writeDestinationModelEmpty(options);
286
+ return;
287
+ }
288
+ const { input, nameDerived } = buildCopyInput(source.document, options.to);
289
+ const result = prepareDefinition(input, options.to.slotId);
290
+ if (result.kind === "invalid") {
291
+ writeSourceFault(result.fault, source.document, options);
292
+ return;
293
+ }
294
+ const tableFault = findUnknownTables(result.prepared.request, modelTables);
295
+ if (tableFault !== null) {
296
+ writeSourceFault(tableFault, source.document, options);
297
+ return;
298
+ }
299
+ return {
300
+ create: result.prepared,
301
+ source: {
302
+ state: source.state,
303
+ id: source.document.id,
304
+ nameDerived,
305
+ sourceOnlyFieldIds: findSourceOnlyFieldIds(source.document, destinationTemplate)
306
+ }
307
+ };
308
+ }
309
+ async function sendCopy(config, options, prepared) {
310
+ const created = await postDashboardCreate(config, prepared.create.request, options.to, buildCopyWording(options, prepared.source));
311
+ if (created === undefined) {
312
+ return;
313
+ }
314
+ const outcome = {
315
+ ...created,
316
+ options,
317
+ source: prepared.source,
318
+ create: prepared.create
319
+ };
320
+ OutputFormatter.success({
321
+ Result: RESULTS.Success,
322
+ Code: "InsightsDashboardCopy",
323
+ Data: buildCopyData(outcome),
324
+ Instructions: buildCopyInstructions(outcome)
325
+ });
326
+ }
327
+ export {
328
+ executeDashboardCopy
329
+ };
330
+
331
+ //# debugId=59EDCED18B854BE264756E2164756E21