@tduniec/plugin-template-designer 0.2.4 → 0.3.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/dist/components/DesignerFlow/DesignerFlow.esm.js +97 -54
- package/dist/components/DesignerFlow/DesignerFlow.esm.js.map +1 -1
- package/dist/components/DesignerFlow/handlers.esm.js +14 -3
- package/dist/components/DesignerFlow/handlers.esm.js.map +1 -1
- package/dist/components/Nodes/ActionNode.esm.js +3 -2
- package/dist/components/Nodes/ActionNode.esm.js.map +1 -1
- package/dist/components/Nodes/OutputNode.esm.js +3 -1
- package/dist/components/Nodes/OutputNode.esm.js.map +1 -1
- package/dist/components/Nodes/ParametersNode.esm.js +3 -1
- package/dist/components/Nodes/ParametersNode.esm.js.map +1 -1
- package/dist/components/TemplateDesigner/TemplateDesigner.esm.js +75 -45
- package/dist/components/TemplateDesigner/TemplateDesigner.esm.js.map +1 -1
- package/dist/components/TemplateDesigner/components/FieldEditorDialog.esm.js +42 -19
- package/dist/components/TemplateDesigner/components/FieldEditorDialog.esm.js.map +1 -1
- package/dist/components/TemplateDesigner/components/TemplateLanding.esm.js +58 -4
- package/dist/components/TemplateDesigner/components/TemplateLanding.esm.js.map +1 -1
- package/dist/components/TemplateDesigner/components/TemplateWorkspace.esm.js +30 -3
- package/dist/components/TemplateDesigner/components/TemplateWorkspace.esm.js.map +1 -1
- package/dist/components/TemplateDesigner/useFieldEditor.esm.js +31 -32
- package/dist/components/TemplateDesigner/useFieldEditor.esm.js.map +1 -1
- package/dist/components/TemplateDesigner/useTemplateState.esm.js +290 -54
- package/dist/components/TemplateDesigner/useTemplateState.esm.js.map +1 -1
- package/dist/components/TemplateDesigner/utils.esm.js.map +1 -1
- package/dist/package.json.esm.js +5 -1
- package/dist/package.json.esm.js.map +1 -1
- package/package.json +5 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { useState, useRef, useCallback, useMemo } from 'react';
|
|
1
|
+
import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
|
|
2
2
|
import { convertJsonToYaml, convertYamlToJson } from '../../utils/yamlJsonConversion.esm.js';
|
|
3
3
|
import { SAMPLE_TEMPLATE_BLUEPRINT } from '../../utils/sampleTemplate.esm.js';
|
|
4
4
|
import { cloneDeep, FILE_PICKER_TYPES, asRecord, isTaskStep, cloneSteps, downloadString, DEFAULT_FILE_NAME } from './utils.esm.js';
|
|
5
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
6
|
+
import { catalogApiRef } from '@backstage/plugin-catalog-react';
|
|
5
7
|
|
|
6
8
|
const parseTemplateYaml = (value) => {
|
|
7
9
|
const parsed = JSON.parse(convertYamlToJson(value));
|
|
@@ -19,6 +21,22 @@ const useTemplateState = () => {
|
|
|
19
21
|
const [templateSource, setTemplateSource] = useState();
|
|
20
22
|
const [isReloading, setIsReloading] = useState(false);
|
|
21
23
|
const [isSaving, setIsSaving] = useState(false);
|
|
24
|
+
const [isSyncing, setIsSyncing] = useState(false);
|
|
25
|
+
const templateObjectRef = useRef(null);
|
|
26
|
+
const yamlParseTimeoutRef = useRef(
|
|
27
|
+
null
|
|
28
|
+
);
|
|
29
|
+
const yamlSerializeTimeoutRef = useRef(
|
|
30
|
+
null
|
|
31
|
+
);
|
|
32
|
+
const yamlParseIdleCancelRef = useRef(null);
|
|
33
|
+
const yamlSerializeIdleCancelRef = useRef(null);
|
|
34
|
+
const yamlParseCompletionRef = useRef(null);
|
|
35
|
+
const yamlSerializeCompletionRef = useRef(null);
|
|
36
|
+
const syncingCounterRef = useRef(0);
|
|
37
|
+
const catalogApi = useApi(catalogApiRef);
|
|
38
|
+
const [selectedTemplate, setSelectedTemplate] = useState(void 0);
|
|
39
|
+
const [availableTemplates, setAvailableTemplates] = useState([]);
|
|
22
40
|
const fileInputRef = useRef(null);
|
|
23
41
|
const ensureHandlePermission = useCallback(
|
|
24
42
|
async (handle, mode) => {
|
|
@@ -39,6 +57,7 @@ const useTemplateState = () => {
|
|
|
39
57
|
(template, source) => {
|
|
40
58
|
const nextTemplate = cloneDeep(template);
|
|
41
59
|
const nextYaml = convertJsonToYaml(nextTemplate);
|
|
60
|
+
templateObjectRef.current = nextTemplate;
|
|
42
61
|
setTemplateObject(nextTemplate);
|
|
43
62
|
setTemplateYaml(nextYaml);
|
|
44
63
|
setYamlError(void 0);
|
|
@@ -59,6 +78,180 @@ const useTemplateState = () => {
|
|
|
59
78
|
"This will discard the changes you have made. Continue?"
|
|
60
79
|
);
|
|
61
80
|
}, [isDirty, templateObject]);
|
|
81
|
+
const startSyncTask = useCallback(() => {
|
|
82
|
+
syncingCounterRef.current += 1;
|
|
83
|
+
if (syncingCounterRef.current === 1) {
|
|
84
|
+
setIsSyncing(true);
|
|
85
|
+
}
|
|
86
|
+
return () => {
|
|
87
|
+
syncingCounterRef.current = Math.max(syncingCounterRef.current - 1, 0);
|
|
88
|
+
if (syncingCounterRef.current === 0) {
|
|
89
|
+
setIsSyncing(false);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}, []);
|
|
93
|
+
const scheduleYamlParse = useCallback(
|
|
94
|
+
(nextYaml) => {
|
|
95
|
+
if (yamlParseTimeoutRef.current) {
|
|
96
|
+
clearTimeout(yamlParseTimeoutRef.current);
|
|
97
|
+
}
|
|
98
|
+
if (yamlParseIdleCancelRef.current) {
|
|
99
|
+
yamlParseIdleCancelRef.current();
|
|
100
|
+
yamlParseIdleCancelRef.current = null;
|
|
101
|
+
}
|
|
102
|
+
if (yamlParseCompletionRef.current) {
|
|
103
|
+
yamlParseCompletionRef.current();
|
|
104
|
+
yamlParseCompletionRef.current = null;
|
|
105
|
+
}
|
|
106
|
+
yamlParseCompletionRef.current = startSyncTask();
|
|
107
|
+
yamlParseTimeoutRef.current = setTimeout(() => {
|
|
108
|
+
yamlParseTimeoutRef.current = null;
|
|
109
|
+
const runParse = () => {
|
|
110
|
+
try {
|
|
111
|
+
const parsed = parseTemplateYaml(nextYaml);
|
|
112
|
+
templateObjectRef.current = parsed;
|
|
113
|
+
setTemplateObject(parsed);
|
|
114
|
+
setYamlError(void 0);
|
|
115
|
+
} catch (error) {
|
|
116
|
+
const message = error instanceof Error ? error.message : "Unknown error parsing YAML";
|
|
117
|
+
setYamlError(message);
|
|
118
|
+
}
|
|
119
|
+
if (yamlParseCompletionRef.current) {
|
|
120
|
+
yamlParseCompletionRef.current();
|
|
121
|
+
yamlParseCompletionRef.current = null;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
const idle = typeof window !== "undefined" && typeof window.requestIdleCallback === "function";
|
|
125
|
+
if (idle) {
|
|
126
|
+
const handle = window.requestIdleCallback(runParse, {
|
|
127
|
+
timeout: 800
|
|
128
|
+
});
|
|
129
|
+
yamlParseIdleCancelRef.current = () => {
|
|
130
|
+
window.cancelIdleCallback?.(handle);
|
|
131
|
+
if (yamlParseCompletionRef.current) {
|
|
132
|
+
yamlParseCompletionRef.current();
|
|
133
|
+
yamlParseCompletionRef.current = null;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
runParse();
|
|
139
|
+
}, 450);
|
|
140
|
+
},
|
|
141
|
+
[startSyncTask]
|
|
142
|
+
);
|
|
143
|
+
const scheduleYamlSerialization = useCallback(
|
|
144
|
+
(nextTemplate) => {
|
|
145
|
+
if (yamlSerializeTimeoutRef.current) {
|
|
146
|
+
clearTimeout(yamlSerializeTimeoutRef.current);
|
|
147
|
+
}
|
|
148
|
+
if (yamlSerializeIdleCancelRef.current) {
|
|
149
|
+
yamlSerializeIdleCancelRef.current();
|
|
150
|
+
yamlSerializeIdleCancelRef.current = null;
|
|
151
|
+
}
|
|
152
|
+
if (yamlSerializeCompletionRef.current) {
|
|
153
|
+
yamlSerializeCompletionRef.current();
|
|
154
|
+
yamlSerializeCompletionRef.current = null;
|
|
155
|
+
}
|
|
156
|
+
yamlSerializeCompletionRef.current = startSyncTask();
|
|
157
|
+
yamlSerializeTimeoutRef.current = setTimeout(() => {
|
|
158
|
+
yamlSerializeTimeoutRef.current = null;
|
|
159
|
+
if (!nextTemplate) {
|
|
160
|
+
setTemplateYaml("");
|
|
161
|
+
if (yamlSerializeCompletionRef.current) {
|
|
162
|
+
yamlSerializeCompletionRef.current();
|
|
163
|
+
yamlSerializeCompletionRef.current = null;
|
|
164
|
+
}
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const runSerialize = () => {
|
|
168
|
+
try {
|
|
169
|
+
setTemplateYaml(convertJsonToYaml(nextTemplate));
|
|
170
|
+
} catch (error) {
|
|
171
|
+
const message = error instanceof Error ? error.message : "Unknown error updating YAML";
|
|
172
|
+
setLoadError(message);
|
|
173
|
+
}
|
|
174
|
+
if (yamlSerializeCompletionRef.current) {
|
|
175
|
+
yamlSerializeCompletionRef.current();
|
|
176
|
+
yamlSerializeCompletionRef.current = null;
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
const idle = typeof window !== "undefined" && typeof window.requestIdleCallback === "function";
|
|
180
|
+
if (idle) {
|
|
181
|
+
const handle = window.requestIdleCallback(runSerialize, {
|
|
182
|
+
timeout: 800
|
|
183
|
+
});
|
|
184
|
+
yamlSerializeIdleCancelRef.current = () => {
|
|
185
|
+
window.cancelIdleCallback?.(handle);
|
|
186
|
+
if (yamlSerializeCompletionRef.current) {
|
|
187
|
+
yamlSerializeCompletionRef.current();
|
|
188
|
+
yamlSerializeCompletionRef.current = null;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
runSerialize();
|
|
194
|
+
}, 250);
|
|
195
|
+
},
|
|
196
|
+
[startSyncTask]
|
|
197
|
+
);
|
|
198
|
+
const flushPendingYamlSerialization = useCallback(() => {
|
|
199
|
+
if (yamlSerializeTimeoutRef.current) {
|
|
200
|
+
clearTimeout(yamlSerializeTimeoutRef.current);
|
|
201
|
+
yamlSerializeTimeoutRef.current = null;
|
|
202
|
+
}
|
|
203
|
+
if (yamlSerializeIdleCancelRef.current) {
|
|
204
|
+
yamlSerializeIdleCancelRef.current();
|
|
205
|
+
yamlSerializeIdleCancelRef.current = null;
|
|
206
|
+
}
|
|
207
|
+
if (yamlSerializeCompletionRef.current) {
|
|
208
|
+
yamlSerializeCompletionRef.current();
|
|
209
|
+
yamlSerializeCompletionRef.current = null;
|
|
210
|
+
}
|
|
211
|
+
const latest = templateObjectRef.current;
|
|
212
|
+
if (!latest) {
|
|
213
|
+
setTemplateYaml("");
|
|
214
|
+
return "";
|
|
215
|
+
}
|
|
216
|
+
try {
|
|
217
|
+
const serialized = convertJsonToYaml(latest);
|
|
218
|
+
setTemplateYaml(serialized);
|
|
219
|
+
return serialized;
|
|
220
|
+
} catch (error) {
|
|
221
|
+
const message = error instanceof Error ? error.message : "Unknown error updating YAML";
|
|
222
|
+
setLoadError(message);
|
|
223
|
+
return templateYaml;
|
|
224
|
+
}
|
|
225
|
+
}, [templateYaml]);
|
|
226
|
+
useEffect(() => {
|
|
227
|
+
return () => {
|
|
228
|
+
if (yamlParseTimeoutRef.current) {
|
|
229
|
+
clearTimeout(yamlParseTimeoutRef.current);
|
|
230
|
+
}
|
|
231
|
+
if (yamlParseIdleCancelRef.current) {
|
|
232
|
+
yamlParseIdleCancelRef.current();
|
|
233
|
+
}
|
|
234
|
+
if (yamlParseCompletionRef.current) {
|
|
235
|
+
yamlParseCompletionRef.current();
|
|
236
|
+
yamlParseCompletionRef.current = null;
|
|
237
|
+
}
|
|
238
|
+
if (yamlSerializeTimeoutRef.current) {
|
|
239
|
+
clearTimeout(yamlSerializeTimeoutRef.current);
|
|
240
|
+
}
|
|
241
|
+
if (yamlSerializeIdleCancelRef.current) {
|
|
242
|
+
yamlSerializeIdleCancelRef.current();
|
|
243
|
+
}
|
|
244
|
+
if (yamlSerializeCompletionRef.current) {
|
|
245
|
+
yamlSerializeCompletionRef.current();
|
|
246
|
+
yamlSerializeCompletionRef.current = null;
|
|
247
|
+
}
|
|
248
|
+
syncingCounterRef.current = 0;
|
|
249
|
+
setIsSyncing(false);
|
|
250
|
+
};
|
|
251
|
+
}, []);
|
|
252
|
+
useEffect(() => {
|
|
253
|
+
templateObjectRef.current = templateObject;
|
|
254
|
+
}, [templateObject]);
|
|
62
255
|
const handleStartSampleTemplate = useCallback(() => {
|
|
63
256
|
if (!confirmDiscardChanges()) {
|
|
64
257
|
return;
|
|
@@ -192,35 +385,35 @@ const useTemplateState = () => {
|
|
|
192
385
|
}
|
|
193
386
|
return cloneDeep(rawOutput);
|
|
194
387
|
}, [templateObject]);
|
|
195
|
-
const handleYamlChange = useCallback(
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
388
|
+
const handleYamlChange = useCallback(
|
|
389
|
+
(value) => {
|
|
390
|
+
setTemplateYaml(value);
|
|
391
|
+
setIsDirty(true);
|
|
392
|
+
scheduleYamlParse(value);
|
|
393
|
+
},
|
|
394
|
+
[scheduleYamlParse]
|
|
395
|
+
);
|
|
396
|
+
const handleStepsChange = useCallback(
|
|
397
|
+
(steps) => {
|
|
398
|
+
setIsDirty(true);
|
|
399
|
+
setTemplateObject((prevTemplate) => {
|
|
400
|
+
const base = prevTemplate && typeof prevTemplate === "object" ? cloneDeep(prevTemplate) : {};
|
|
401
|
+
const spec = asRecord(base.spec) ?? {};
|
|
402
|
+
const nextSteps = cloneSteps(steps);
|
|
403
|
+
const nextTemplate = {
|
|
404
|
+
...base,
|
|
405
|
+
spec: {
|
|
406
|
+
...spec,
|
|
407
|
+
steps: nextSteps
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
templateObjectRef.current = nextTemplate;
|
|
411
|
+
scheduleYamlSerialization(nextTemplate);
|
|
412
|
+
return nextTemplate;
|
|
413
|
+
});
|
|
414
|
+
},
|
|
415
|
+
[scheduleYamlSerialization]
|
|
416
|
+
);
|
|
224
417
|
const handleParametersChange = useCallback(
|
|
225
418
|
(parameters) => {
|
|
226
419
|
setIsDirty(true);
|
|
@@ -234,32 +427,46 @@ const useTemplateState = () => {
|
|
|
234
427
|
parameters: cloneDeep(parameters)
|
|
235
428
|
}
|
|
236
429
|
};
|
|
237
|
-
|
|
430
|
+
templateObjectRef.current = nextTemplate;
|
|
431
|
+
scheduleYamlSerialization(nextTemplate);
|
|
238
432
|
return nextTemplate;
|
|
239
433
|
});
|
|
240
434
|
},
|
|
241
|
-
[]
|
|
435
|
+
[scheduleYamlSerialization]
|
|
436
|
+
);
|
|
437
|
+
const handleOutputChange = useCallback(
|
|
438
|
+
(output) => {
|
|
439
|
+
setIsDirty(true);
|
|
440
|
+
setTemplateObject((prevTemplate) => {
|
|
441
|
+
const base = prevTemplate && typeof prevTemplate === "object" ? cloneDeep(prevTemplate) : {};
|
|
442
|
+
const spec = asRecord(base.spec) ?? {};
|
|
443
|
+
const nextTemplate = {
|
|
444
|
+
...base,
|
|
445
|
+
spec: {
|
|
446
|
+
...spec,
|
|
447
|
+
output: cloneDeep(output)
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
templateObjectRef.current = nextTemplate;
|
|
451
|
+
scheduleYamlSerialization(nextTemplate);
|
|
452
|
+
return nextTemplate;
|
|
453
|
+
});
|
|
454
|
+
},
|
|
455
|
+
[scheduleYamlSerialization]
|
|
242
456
|
);
|
|
243
|
-
const handleOutputChange = useCallback((output) => {
|
|
244
|
-
setIsDirty(true);
|
|
245
|
-
setTemplateObject((prevTemplate) => {
|
|
246
|
-
const base = prevTemplate && typeof prevTemplate === "object" ? cloneDeep(prevTemplate) : {};
|
|
247
|
-
const spec = asRecord(base.spec) ?? {};
|
|
248
|
-
const nextTemplate = {
|
|
249
|
-
...base,
|
|
250
|
-
spec: {
|
|
251
|
-
...spec,
|
|
252
|
-
output: cloneDeep(output)
|
|
253
|
-
}
|
|
254
|
-
};
|
|
255
|
-
setTemplateYaml(convertJsonToYaml(nextTemplate));
|
|
256
|
-
return nextTemplate;
|
|
257
|
-
});
|
|
258
|
-
}, []);
|
|
259
457
|
const handleReloadFromFile = useCallback(async () => {
|
|
260
458
|
if (!templateSource) {
|
|
261
459
|
return;
|
|
262
460
|
}
|
|
461
|
+
if (templateSource.type === "catalog") {
|
|
462
|
+
if (selectedTemplate) {
|
|
463
|
+
applyTemplate(selectedTemplate, {
|
|
464
|
+
type: "catalog",
|
|
465
|
+
label: selectedTemplate.metadata.title ?? selectedTemplate.metadata.name
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
263
470
|
if (templateSource.type !== "file") {
|
|
264
471
|
handleStartSampleTemplate();
|
|
265
472
|
return;
|
|
@@ -301,14 +508,16 @@ const useTemplateState = () => {
|
|
|
301
508
|
ensureHandlePermission,
|
|
302
509
|
handleOpenTemplatePicker,
|
|
303
510
|
handleStartSampleTemplate,
|
|
511
|
+
selectedTemplate,
|
|
304
512
|
templateSource
|
|
305
513
|
]);
|
|
306
514
|
const handleSaveTemplate = useCallback(async () => {
|
|
307
515
|
if (!templateObject) {
|
|
308
516
|
return;
|
|
309
517
|
}
|
|
518
|
+
const yamlToPersist = flushPendingYamlSerialization();
|
|
310
519
|
if (typeof window === "undefined") {
|
|
311
|
-
downloadString(
|
|
520
|
+
downloadString(yamlToPersist, DEFAULT_FILE_NAME);
|
|
312
521
|
setIsDirty(false);
|
|
313
522
|
return;
|
|
314
523
|
}
|
|
@@ -329,7 +538,7 @@ const useTemplateState = () => {
|
|
|
329
538
|
if (!writable) {
|
|
330
539
|
throw new Error("Unable to open file for writing.");
|
|
331
540
|
}
|
|
332
|
-
await writable.write(
|
|
541
|
+
await writable.write(yamlToPersist);
|
|
333
542
|
await writable.close();
|
|
334
543
|
setIsDirty(false);
|
|
335
544
|
return;
|
|
@@ -343,7 +552,7 @@ const useTemplateState = () => {
|
|
|
343
552
|
if (!writable) {
|
|
344
553
|
throw new Error("Unable to open file for writing.");
|
|
345
554
|
}
|
|
346
|
-
await writable.write(
|
|
555
|
+
await writable.write(yamlToPersist);
|
|
347
556
|
await writable.close();
|
|
348
557
|
setTemplateSource({
|
|
349
558
|
type: "file",
|
|
@@ -353,7 +562,7 @@ const useTemplateState = () => {
|
|
|
353
562
|
setIsDirty(false);
|
|
354
563
|
return;
|
|
355
564
|
}
|
|
356
|
-
downloadString(
|
|
565
|
+
downloadString(yamlToPersist, templateSource?.label ?? DEFAULT_FILE_NAME);
|
|
357
566
|
setIsDirty(false);
|
|
358
567
|
} catch (error) {
|
|
359
568
|
const message = error instanceof Error ? error.message : "Unknown error saving template";
|
|
@@ -361,7 +570,31 @@ const useTemplateState = () => {
|
|
|
361
570
|
} finally {
|
|
362
571
|
setIsSaving(false);
|
|
363
572
|
}
|
|
364
|
-
}, [
|
|
573
|
+
}, [
|
|
574
|
+
ensureHandlePermission,
|
|
575
|
+
flushPendingYamlSerialization,
|
|
576
|
+
templateObject,
|
|
577
|
+
templateSource
|
|
578
|
+
]);
|
|
579
|
+
useEffect(() => {
|
|
580
|
+
catalogApi.getEntities({
|
|
581
|
+
filter: {
|
|
582
|
+
kind: "Template"
|
|
583
|
+
}
|
|
584
|
+
}).then((data) => {
|
|
585
|
+
setAvailableTemplates(data.items);
|
|
586
|
+
}).catch(() => setAvailableTemplates([]));
|
|
587
|
+
}, [catalogApi]);
|
|
588
|
+
const selectCatalogTemplate = useCallback(
|
|
589
|
+
(selected) => {
|
|
590
|
+
setSelectedTemplate(selected);
|
|
591
|
+
applyTemplate(selected, {
|
|
592
|
+
type: "catalog",
|
|
593
|
+
label: selected.metadata.title ?? selected.metadata.name
|
|
594
|
+
});
|
|
595
|
+
},
|
|
596
|
+
[applyTemplate]
|
|
597
|
+
);
|
|
365
598
|
return {
|
|
366
599
|
templateObject,
|
|
367
600
|
templateYaml,
|
|
@@ -371,6 +604,7 @@ const useTemplateState = () => {
|
|
|
371
604
|
templateSource,
|
|
372
605
|
isReloading,
|
|
373
606
|
isSaving,
|
|
607
|
+
isSyncing,
|
|
374
608
|
templateSteps,
|
|
375
609
|
templateParameters,
|
|
376
610
|
templateOutput,
|
|
@@ -383,7 +617,9 @@ const useTemplateState = () => {
|
|
|
383
617
|
handleParametersChange,
|
|
384
618
|
handleOutputChange,
|
|
385
619
|
handleReloadFromFile,
|
|
386
|
-
handleSaveTemplate
|
|
620
|
+
handleSaveTemplate,
|
|
621
|
+
availableTemplates,
|
|
622
|
+
selectCatalogTemplate
|
|
387
623
|
};
|
|
388
624
|
};
|
|
389
625
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTemplateState.esm.js","sources":["../../../src/components/TemplateDesigner/useTemplateState.ts"],"sourcesContent":["import { useCallback, useMemo, useRef, useState } from \"react\";\nimport type { ChangeEvent, RefObject } from \"react\";\nimport type {\n ScaffolderTaskOutput,\n TaskStep,\n} from \"@backstage/plugin-scaffolder-common\";\nimport type { TemplateParametersValue } from \"../Nodes/types\";\nimport {\n convertJsonToYaml,\n convertYamlToJson,\n} from \"../../utils/yamlJsonConversion\";\nimport { SAMPLE_TEMPLATE_BLUEPRINT } from \"../../utils/sampleTemplate\";\nimport {\n DEFAULT_FILE_NAME,\n FILE_PICKER_TYPES,\n FileSystemFileHandleLike,\n FileSystemWindow,\n TemplateSource,\n asRecord,\n cloneDeep,\n cloneSteps,\n downloadString,\n isTaskStep,\n} from \"./utils\";\n\ntype TemplateState = {\n templateObject: Record<string, unknown> | null;\n templateYaml: string;\n yamlError?: string;\n loadError?: string;\n isDirty: boolean;\n templateSource?: TemplateSource;\n isReloading: boolean;\n isSaving: boolean;\n templateSteps: TaskStep[];\n templateParameters: TemplateParametersValue;\n templateOutput?: ScaffolderTaskOutput;\n fileInputRef: RefObject<HTMLInputElement>;\n handleStartSampleTemplate: () => void;\n handleTemplateFileSelected: (event: ChangeEvent<HTMLInputElement>) => void;\n handleOpenTemplatePicker: () => void;\n handleYamlChange: (value: string) => void;\n handleStepsChange: (steps: TaskStep[]) => void;\n handleParametersChange: (parameters: TemplateParametersValue) => void;\n handleOutputChange: (output?: ScaffolderTaskOutput) => void;\n handleReloadFromFile: () => void;\n handleSaveTemplate: () => void;\n};\n\nconst parseTemplateYaml = (value: string) => {\n const parsed = JSON.parse(convertYamlToJson(value));\n if (!parsed || typeof parsed !== \"object\") {\n throw new Error(\"Template YAML must describe an object\");\n }\n return parsed as Record<string, unknown>;\n};\n\n/**\n * Encapsulates the template designer data model including YAML parsing,\n * scaffolder spec updates, and file-system interactions.\n */\nexport const useTemplateState = (): TemplateState => {\n const [templateObject, setTemplateObject] = useState<Record<\n string,\n unknown\n > | null>(null);\n const [templateYaml, setTemplateYaml] = useState(\"\");\n const [yamlError, setYamlError] = useState<string | undefined>();\n const [loadError, setLoadError] = useState<string | undefined>();\n const [isDirty, setIsDirty] = useState(false);\n const [templateSource, setTemplateSource] = useState<\n TemplateSource | undefined\n >();\n const [isReloading, setIsReloading] = useState(false);\n const [isSaving, setIsSaving] = useState(false);\n\n const fileInputRef = useRef<HTMLInputElement | null>(null);\n\n const ensureHandlePermission = useCallback(\n async (\n handle: FileSystemFileHandleLike | undefined,\n mode: \"read\" | \"readwrite\"\n ) => {\n if (!handle || !handle.queryPermission || !handle.requestPermission) {\n return true;\n }\n const options = { mode };\n const current = await handle.queryPermission(options);\n if (current === \"granted\") {\n return true;\n }\n const request = await handle.requestPermission(options);\n return request === \"granted\";\n },\n []\n );\n\n const applyTemplate = useCallback(\n (template: Record<string, unknown>, source: TemplateSource) => {\n const nextTemplate = cloneDeep(template);\n const nextYaml = convertJsonToYaml(nextTemplate);\n setTemplateObject(nextTemplate);\n setTemplateYaml(nextYaml);\n setYamlError(undefined);\n setLoadError(undefined);\n setTemplateSource(source);\n setIsDirty(false);\n },\n []\n );\n\n const confirmDiscardChanges = useCallback(() => {\n if (!templateObject || !isDirty) {\n return true;\n }\n\n if (typeof window === \"undefined\") {\n return true;\n }\n\n // eslint-disable-next-line no-alert\n return window.confirm(\n \"This will discard the changes you have made. Continue?\"\n );\n }, [isDirty, templateObject]);\n\n const handleStartSampleTemplate = useCallback(() => {\n if (!confirmDiscardChanges()) {\n return;\n }\n applyTemplate(SAMPLE_TEMPLATE_BLUEPRINT, {\n type: \"sample\",\n label: \"Sample template\",\n });\n }, [applyTemplate, confirmDiscardChanges]);\n\n const handleTemplateFileSelected = useCallback(\n async (event: ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0];\n event.target.value = \"\";\n\n if (!file) {\n return;\n }\n\n if (!confirmDiscardChanges()) {\n return;\n }\n\n try {\n const fileContents = await file.text();\n const parsed = parseTemplateYaml(fileContents);\n applyTemplate(parsed, {\n type: \"file\",\n label: file.name,\n });\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : \"Unknown error loading template\";\n setLoadError(`Could not load template: ${message}`);\n }\n },\n [applyTemplate, confirmDiscardChanges]\n );\n\n const handleOpenTemplatePicker = useCallback(async () => {\n if (!confirmDiscardChanges()) {\n return;\n }\n\n if (typeof window === \"undefined\") {\n return;\n }\n\n const fsWindow = window as FileSystemWindow;\n\n if (fsWindow.showOpenFilePicker) {\n try {\n const handles = await fsWindow.showOpenFilePicker({\n multiple: false,\n types: FILE_PICKER_TYPES,\n });\n const [handle] = handles ?? [];\n if (!handle) {\n return;\n }\n\n const granted = await ensureHandlePermission(handle, \"read\");\n if (!granted) {\n setLoadError(\"Permission to read the selected file was denied.\");\n return;\n }\n\n const file = await handle.getFile();\n const text = await file.text();\n const parsed = parseTemplateYaml(text);\n applyTemplate(parsed, {\n type: \"file\",\n label: handle.name ?? file.name,\n handle,\n });\n } catch (error) {\n if (error instanceof DOMException && error.name === \"AbortError\") {\n return;\n }\n const message =\n error instanceof Error\n ? error.message\n : \"Unknown error loading template\";\n setLoadError(`Could not load template: ${message}`);\n }\n return;\n }\n\n fileInputRef.current?.click();\n }, [applyTemplate, confirmDiscardChanges, ensureHandlePermission]);\n\n const templateSteps = useMemo(() => {\n if (!templateObject) {\n return [];\n }\n\n const template = asRecord(templateObject);\n if (!template) {\n return [];\n }\n\n const spec = asRecord(template.spec);\n if (!spec) {\n return [];\n }\n\n const maybeSteps = spec.steps;\n if (!Array.isArray(maybeSteps)) {\n return [];\n }\n\n const validSteps = maybeSteps.filter(isTaskStep) as TaskStep[];\n return cloneSteps(validSteps);\n }, [templateObject]);\n\n const templateParameters = useMemo((): TemplateParametersValue => {\n if (!templateObject) {\n return undefined;\n }\n\n const template = asRecord(templateObject);\n if (!template) {\n return undefined;\n }\n\n const spec = asRecord(template.spec);\n if (!spec) {\n return undefined;\n }\n\n if (!Object.prototype.hasOwnProperty.call(spec, \"parameters\")) {\n return undefined;\n }\n\n const rawParameters = (spec as Record<string, unknown>).parameters;\n if (rawParameters === undefined) {\n return undefined;\n }\n\n return cloneDeep(rawParameters as TemplateParametersValue);\n }, [templateObject]);\n\n const templateOutput = useMemo(() => {\n if (!templateObject) {\n return undefined;\n }\n\n const template = asRecord(templateObject);\n if (!template) {\n return undefined;\n }\n\n const spec = asRecord(template.spec);\n if (!spec) {\n return undefined;\n }\n\n const rawOutput = spec.output;\n if (!rawOutput || typeof rawOutput !== \"object\") {\n return undefined;\n }\n\n return cloneDeep(rawOutput as ScaffolderTaskOutput);\n }, [templateObject]);\n\n const handleYamlChange = useCallback((value: string) => {\n setTemplateYaml(value);\n setIsDirty(true);\n try {\n const parsed = parseTemplateYaml(value);\n setTemplateObject(parsed);\n setYamlError(undefined);\n } catch (error) {\n const message =\n error instanceof Error ? error.message : \"Unknown error parsing YAML\";\n setYamlError(message);\n }\n }, []);\n\n const handleStepsChange = useCallback((steps: TaskStep[]) => {\n setIsDirty(true);\n setTemplateObject((prevTemplate) => {\n const base =\n prevTemplate && typeof prevTemplate === \"object\"\n ? (cloneDeep(prevTemplate) as Record<string, unknown>)\n : ({} as Record<string, unknown>);\n\n const spec = asRecord(base.spec) ?? {};\n const nextSteps = cloneSteps(steps);\n\n const nextTemplate: Record<string, unknown> = {\n ...base,\n spec: {\n ...spec,\n steps: nextSteps,\n },\n };\n\n setTemplateYaml(convertJsonToYaml(nextTemplate));\n return nextTemplate;\n });\n }, []);\n\n const handleParametersChange = useCallback(\n (parameters: TemplateParametersValue) => {\n setIsDirty(true);\n setTemplateObject((prevTemplate) => {\n const base =\n prevTemplate && typeof prevTemplate === \"object\"\n ? (cloneDeep(prevTemplate) as Record<string, unknown>)\n : ({} as Record<string, unknown>);\n\n const spec = asRecord(base.spec) ?? {};\n const nextTemplate: Record<string, unknown> = {\n ...base,\n spec: {\n ...spec,\n parameters: cloneDeep(parameters),\n },\n };\n\n setTemplateYaml(convertJsonToYaml(nextTemplate));\n return nextTemplate;\n });\n },\n []\n );\n\n const handleOutputChange = useCallback((output?: ScaffolderTaskOutput) => {\n setIsDirty(true);\n setTemplateObject((prevTemplate) => {\n const base =\n prevTemplate && typeof prevTemplate === \"object\"\n ? (cloneDeep(prevTemplate) as Record<string, unknown>)\n : ({} as Record<string, unknown>);\n\n const spec = asRecord(base.spec) ?? {};\n const nextTemplate: Record<string, unknown> = {\n ...base,\n spec: {\n ...spec,\n output: cloneDeep(output),\n },\n };\n\n setTemplateYaml(convertJsonToYaml(nextTemplate));\n return nextTemplate;\n });\n }, []);\n\n const handleReloadFromFile = useCallback(async () => {\n if (!templateSource) {\n return;\n }\n\n if (templateSource.type !== \"file\") {\n handleStartSampleTemplate();\n return;\n }\n\n if (!templateSource.handle) {\n handleOpenTemplatePicker();\n return;\n }\n\n if (!confirmDiscardChanges()) {\n return;\n }\n\n try {\n setIsReloading(true);\n const granted = await ensureHandlePermission(\n templateSource.handle,\n \"read\"\n );\n if (!granted) {\n setLoadError(\"Permission to read the selected file was denied.\");\n return;\n }\n\n const file = await templateSource.handle.getFile();\n const text = await file.text();\n const parsed = parseTemplateYaml(text);\n applyTemplate(parsed, {\n type: \"file\",\n label: templateSource.handle.name ?? file.name ?? templateSource.label,\n handle: templateSource.handle,\n });\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : \"Unknown error reloading template\";\n setLoadError(`Could not reload template: ${message}`);\n } finally {\n setIsReloading(false);\n }\n }, [\n applyTemplate,\n confirmDiscardChanges,\n ensureHandlePermission,\n handleOpenTemplatePicker,\n handleStartSampleTemplate,\n templateSource,\n ]);\n\n const handleSaveTemplate = useCallback(async () => {\n if (!templateObject) {\n return;\n }\n\n if (typeof window === \"undefined\") {\n downloadString(templateYaml, DEFAULT_FILE_NAME);\n setIsDirty(false);\n return;\n }\n\n try {\n setIsSaving(true);\n setLoadError(undefined);\n const fsWindow = window as FileSystemWindow;\n\n if (templateSource?.type === \"file\" && templateSource.handle) {\n const granted = await ensureHandlePermission(\n templateSource.handle,\n \"readwrite\"\n );\n if (!granted) {\n setLoadError(\"Permission to save to the selected file was denied.\");\n return;\n }\n const writable = await templateSource.handle.createWritable?.();\n if (!writable) {\n throw new Error(\"Unable to open file for writing.\");\n }\n await writable.write(templateYaml);\n await writable.close();\n setIsDirty(false);\n return;\n }\n\n if (fsWindow.showSaveFilePicker) {\n const handle = await fsWindow.showSaveFilePicker({\n suggestedName: templateSource?.label ?? DEFAULT_FILE_NAME,\n types: FILE_PICKER_TYPES,\n });\n const writable = await handle.createWritable?.();\n if (!writable) {\n throw new Error(\"Unable to open file for writing.\");\n }\n await writable.write(templateYaml);\n await writable.close();\n setTemplateSource({\n type: \"file\",\n label: handle.name ?? templateSource?.label ?? DEFAULT_FILE_NAME,\n handle,\n });\n setIsDirty(false);\n return;\n }\n\n downloadString(templateYaml, templateSource?.label ?? DEFAULT_FILE_NAME);\n setIsDirty(false);\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : \"Unknown error saving template\";\n setLoadError(`Failed to save template: ${message}`);\n } finally {\n setIsSaving(false);\n }\n }, [ensureHandlePermission, templateObject, templateSource, templateYaml]);\n\n return {\n templateObject,\n templateYaml,\n yamlError,\n loadError,\n isDirty,\n templateSource,\n isReloading,\n isSaving,\n templateSteps,\n templateParameters,\n templateOutput,\n fileInputRef,\n handleStartSampleTemplate,\n handleTemplateFileSelected,\n handleOpenTemplatePicker,\n handleYamlChange,\n handleStepsChange,\n handleParametersChange,\n handleOutputChange,\n handleReloadFromFile,\n handleSaveTemplate,\n };\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useTemplateState.esm.js","sources":["../../../src/components/TemplateDesigner/useTemplateState.ts"],"sourcesContent":["import {\n ChangeEvent,\n RefObject,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type {\n ScaffolderTaskOutput,\n TaskStep,\n} from \"@backstage/plugin-scaffolder-common\";\nimport { TemplateEntityV1beta3 } from \"@backstage/plugin-scaffolder-common\";\nimport type { TemplateParametersValue } from \"../Nodes/types\";\nimport {\n convertJsonToYaml,\n convertYamlToJson,\n} from \"../../utils/yamlJsonConversion\";\nimport { SAMPLE_TEMPLATE_BLUEPRINT } from \"../../utils/sampleTemplate\";\nimport {\n asRecord,\n cloneDeep,\n cloneSteps,\n DEFAULT_FILE_NAME,\n downloadString,\n FILE_PICKER_TYPES,\n FileSystemFileHandleLike,\n FileSystemWindow,\n isTaskStep,\n TemplateSource,\n} from \"./utils\";\nimport { useApi } from \"@backstage/core-plugin-api\";\nimport { catalogApiRef } from \"@backstage/plugin-catalog-react\";\n\ntype TemplateState = {\n templateObject: Record<string, unknown> | null;\n templateYaml: string;\n yamlError?: string;\n loadError?: string;\n isDirty: boolean;\n templateSource?: TemplateSource;\n isReloading: boolean;\n isSaving: boolean;\n isSyncing: boolean;\n templateSteps: TaskStep[];\n templateParameters: TemplateParametersValue;\n templateOutput?: ScaffolderTaskOutput;\n fileInputRef: RefObject<HTMLInputElement>;\n handleStartSampleTemplate: () => void;\n handleTemplateFileSelected: (event: ChangeEvent<HTMLInputElement>) => void;\n handleOpenTemplatePicker: () => void;\n handleYamlChange: (value: string) => void;\n handleStepsChange: (steps: TaskStep[]) => void;\n handleParametersChange: (parameters: TemplateParametersValue) => void;\n handleOutputChange: (output?: ScaffolderTaskOutput) => void;\n handleReloadFromFile: () => void;\n handleSaveTemplate: () => void;\n availableTemplates: TemplateEntityV1beta3[];\n selectCatalogTemplate: (selected: TemplateEntityV1beta3) => void;\n};\n\nconst parseTemplateYaml = (value: string) => {\n const parsed = JSON.parse(convertYamlToJson(value));\n if (!parsed || typeof parsed !== \"object\") {\n throw new Error(\"Template YAML must describe an object\");\n }\n return parsed as Record<string, unknown>;\n};\n\n/**\n * Encapsulates the template designer data model including YAML parsing,\n * scaffolder spec updates, and file-system interactions.\n */\nexport const useTemplateState = (): TemplateState => {\n const [templateObject, setTemplateObject] = useState<Record<\n string,\n unknown\n > | null>(null);\n const [templateYaml, setTemplateYaml] = useState(\"\");\n const [yamlError, setYamlError] = useState<string | undefined>();\n const [loadError, setLoadError] = useState<string | undefined>();\n const [isDirty, setIsDirty] = useState(false);\n const [templateSource, setTemplateSource] = useState<\n TemplateSource | undefined\n >();\n const [isReloading, setIsReloading] = useState(false);\n const [isSaving, setIsSaving] = useState(false);\n const [isSyncing, setIsSyncing] = useState(false);\n const templateObjectRef = useRef<Record<string, unknown> | null>(null);\n const yamlParseTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(\n null\n );\n const yamlSerializeTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(\n null\n );\n const yamlParseIdleCancelRef = useRef<(() => void) | null>(null);\n const yamlSerializeIdleCancelRef = useRef<(() => void) | null>(null);\n const yamlParseCompletionRef = useRef<(() => void) | null>(null);\n const yamlSerializeCompletionRef = useRef<(() => void) | null>(null);\n const syncingCounterRef = useRef(0);\n const catalogApi = useApi(catalogApiRef);\n const [selectedTemplate, setSelectedTemplate] = useState<\n TemplateEntityV1beta3 | undefined\n >(undefined);\n const [availableTemplates, setAvailableTemplates] = useState<\n TemplateEntityV1beta3[]\n >([]);\n\n const fileInputRef = useRef<HTMLInputElement | null>(null);\n\n const ensureHandlePermission = useCallback(\n async (\n handle: FileSystemFileHandleLike | undefined,\n mode: \"read\" | \"readwrite\"\n ) => {\n if (!handle || !handle.queryPermission || !handle.requestPermission) {\n return true;\n }\n const options = { mode };\n const current = await handle.queryPermission(options);\n if (current === \"granted\") {\n return true;\n }\n const request = await handle.requestPermission(options);\n return request === \"granted\";\n },\n []\n );\n\n const applyTemplate = useCallback(\n (template: Record<string, unknown>, source: TemplateSource) => {\n const nextTemplate = cloneDeep(template);\n const nextYaml = convertJsonToYaml(nextTemplate);\n templateObjectRef.current = nextTemplate;\n setTemplateObject(nextTemplate);\n setTemplateYaml(nextYaml);\n setYamlError(undefined);\n setLoadError(undefined);\n setTemplateSource(source);\n setIsDirty(false);\n },\n []\n );\n\n const confirmDiscardChanges = useCallback(() => {\n if (!templateObject || !isDirty) {\n return true;\n }\n\n if (typeof window === \"undefined\") {\n return true;\n }\n\n // eslint-disable-next-line no-alert\n return window.confirm(\n \"This will discard the changes you have made. Continue?\"\n );\n }, [isDirty, templateObject]);\n\n const startSyncTask = useCallback(() => {\n syncingCounterRef.current += 1;\n if (syncingCounterRef.current === 1) {\n setIsSyncing(true);\n }\n return () => {\n syncingCounterRef.current = Math.max(syncingCounterRef.current - 1, 0);\n if (syncingCounterRef.current === 0) {\n setIsSyncing(false);\n }\n };\n }, []);\n\n const scheduleYamlParse = useCallback(\n (nextYaml: string) => {\n if (yamlParseTimeoutRef.current) {\n clearTimeout(yamlParseTimeoutRef.current);\n }\n if (yamlParseIdleCancelRef.current) {\n yamlParseIdleCancelRef.current();\n yamlParseIdleCancelRef.current = null;\n }\n if (yamlParseCompletionRef.current) {\n yamlParseCompletionRef.current();\n yamlParseCompletionRef.current = null;\n }\n yamlParseCompletionRef.current = startSyncTask();\n yamlParseTimeoutRef.current = setTimeout(() => {\n yamlParseTimeoutRef.current = null;\n const runParse = () => {\n try {\n const parsed = parseTemplateYaml(nextYaml);\n templateObjectRef.current = parsed;\n setTemplateObject(parsed);\n setYamlError(undefined);\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : \"Unknown error parsing YAML\";\n setYamlError(message);\n }\n if (yamlParseCompletionRef.current) {\n yamlParseCompletionRef.current();\n yamlParseCompletionRef.current = null;\n }\n };\n const idle =\n typeof window !== \"undefined\" &&\n typeof (window as any).requestIdleCallback === \"function\";\n if (idle) {\n const handle = (window as any).requestIdleCallback(runParse, {\n timeout: 800,\n });\n yamlParseIdleCancelRef.current = () => {\n (window as any).cancelIdleCallback?.(handle);\n if (yamlParseCompletionRef.current) {\n yamlParseCompletionRef.current();\n yamlParseCompletionRef.current = null;\n }\n };\n return;\n }\n runParse();\n }, 450);\n },\n [startSyncTask]\n );\n\n const scheduleYamlSerialization = useCallback(\n (nextTemplate: Record<string, unknown> | null | undefined) => {\n if (yamlSerializeTimeoutRef.current) {\n clearTimeout(yamlSerializeTimeoutRef.current);\n }\n if (yamlSerializeIdleCancelRef.current) {\n yamlSerializeIdleCancelRef.current();\n yamlSerializeIdleCancelRef.current = null;\n }\n if (yamlSerializeCompletionRef.current) {\n yamlSerializeCompletionRef.current();\n yamlSerializeCompletionRef.current = null;\n }\n yamlSerializeCompletionRef.current = startSyncTask();\n yamlSerializeTimeoutRef.current = setTimeout(() => {\n yamlSerializeTimeoutRef.current = null;\n if (!nextTemplate) {\n setTemplateYaml(\"\");\n if (yamlSerializeCompletionRef.current) {\n yamlSerializeCompletionRef.current();\n yamlSerializeCompletionRef.current = null;\n }\n return;\n }\n const runSerialize = () => {\n try {\n setTemplateYaml(convertJsonToYaml(nextTemplate));\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : \"Unknown error updating YAML\";\n setLoadError(message);\n }\n if (yamlSerializeCompletionRef.current) {\n yamlSerializeCompletionRef.current();\n yamlSerializeCompletionRef.current = null;\n }\n };\n const idle =\n typeof window !== \"undefined\" &&\n typeof (window as any).requestIdleCallback === \"function\";\n if (idle) {\n const handle = (window as any).requestIdleCallback(runSerialize, {\n timeout: 800,\n });\n yamlSerializeIdleCancelRef.current = () => {\n (window as any).cancelIdleCallback?.(handle);\n if (yamlSerializeCompletionRef.current) {\n yamlSerializeCompletionRef.current();\n yamlSerializeCompletionRef.current = null;\n }\n };\n return;\n }\n runSerialize();\n }, 250);\n },\n [startSyncTask]\n );\n\n const flushPendingYamlSerialization = useCallback((): string => {\n if (yamlSerializeTimeoutRef.current) {\n clearTimeout(yamlSerializeTimeoutRef.current);\n yamlSerializeTimeoutRef.current = null;\n }\n if (yamlSerializeIdleCancelRef.current) {\n yamlSerializeIdleCancelRef.current();\n yamlSerializeIdleCancelRef.current = null;\n }\n if (yamlSerializeCompletionRef.current) {\n yamlSerializeCompletionRef.current();\n yamlSerializeCompletionRef.current = null;\n }\n const latest = templateObjectRef.current;\n if (!latest) {\n setTemplateYaml(\"\");\n return \"\";\n }\n try {\n const serialized = convertJsonToYaml(latest);\n setTemplateYaml(serialized);\n return serialized;\n } catch (error) {\n const message =\n error instanceof Error ? error.message : \"Unknown error updating YAML\";\n setLoadError(message);\n return templateYaml;\n }\n }, [templateYaml]);\n\n useEffect(() => {\n return () => {\n if (yamlParseTimeoutRef.current) {\n clearTimeout(yamlParseTimeoutRef.current);\n }\n if (yamlParseIdleCancelRef.current) {\n yamlParseIdleCancelRef.current();\n }\n if (yamlParseCompletionRef.current) {\n yamlParseCompletionRef.current();\n yamlParseCompletionRef.current = null;\n }\n if (yamlSerializeTimeoutRef.current) {\n clearTimeout(yamlSerializeTimeoutRef.current);\n }\n if (yamlSerializeIdleCancelRef.current) {\n yamlSerializeIdleCancelRef.current();\n }\n if (yamlSerializeCompletionRef.current) {\n yamlSerializeCompletionRef.current();\n yamlSerializeCompletionRef.current = null;\n }\n syncingCounterRef.current = 0;\n setIsSyncing(false);\n };\n }, []);\n\n useEffect(() => {\n templateObjectRef.current = templateObject;\n }, [templateObject]);\n\n const handleStartSampleTemplate = useCallback(() => {\n if (!confirmDiscardChanges()) {\n return;\n }\n applyTemplate(SAMPLE_TEMPLATE_BLUEPRINT, {\n type: \"sample\",\n label: \"Sample template\",\n });\n }, [applyTemplate, confirmDiscardChanges]);\n\n const handleTemplateFileSelected = useCallback(\n async (event: ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0];\n event.target.value = \"\";\n\n if (!file) {\n return;\n }\n\n if (!confirmDiscardChanges()) {\n return;\n }\n\n try {\n const fileContents = await file.text();\n const parsed = parseTemplateYaml(fileContents);\n applyTemplate(parsed, {\n type: \"file\",\n label: file.name,\n });\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : \"Unknown error loading template\";\n setLoadError(`Could not load template: ${message}`);\n }\n },\n [applyTemplate, confirmDiscardChanges]\n );\n\n const handleOpenTemplatePicker = useCallback(async () => {\n if (!confirmDiscardChanges()) {\n return;\n }\n\n if (typeof window === \"undefined\") {\n return;\n }\n\n const fsWindow = window as FileSystemWindow;\n\n if (fsWindow.showOpenFilePicker) {\n try {\n const handles = await fsWindow.showOpenFilePicker({\n multiple: false,\n types: FILE_PICKER_TYPES,\n });\n const [handle] = handles ?? [];\n if (!handle) {\n return;\n }\n\n const granted = await ensureHandlePermission(handle, \"read\");\n if (!granted) {\n setLoadError(\"Permission to read the selected file was denied.\");\n return;\n }\n\n const file = await handle.getFile();\n const text = await file.text();\n const parsed = parseTemplateYaml(text);\n applyTemplate(parsed, {\n type: \"file\",\n label: handle.name ?? file.name,\n handle,\n });\n } catch (error) {\n if (error instanceof DOMException && error.name === \"AbortError\") {\n return;\n }\n const message =\n error instanceof Error\n ? error.message\n : \"Unknown error loading template\";\n setLoadError(`Could not load template: ${message}`);\n }\n return;\n }\n\n fileInputRef.current?.click();\n }, [applyTemplate, confirmDiscardChanges, ensureHandlePermission]);\n\n const templateSteps = useMemo(() => {\n if (!templateObject) {\n return [];\n }\n\n const template = asRecord(templateObject);\n if (!template) {\n return [];\n }\n\n const spec = asRecord(template.spec);\n if (!spec) {\n return [];\n }\n\n const maybeSteps = spec.steps;\n if (!Array.isArray(maybeSteps)) {\n return [];\n }\n\n const validSteps = maybeSteps.filter(isTaskStep) as TaskStep[];\n return cloneSteps(validSteps);\n }, [templateObject]);\n\n const templateParameters = useMemo((): TemplateParametersValue => {\n if (!templateObject) {\n return undefined;\n }\n\n const template = asRecord(templateObject);\n if (!template) {\n return undefined;\n }\n\n const spec = asRecord(template.spec);\n if (!spec) {\n return undefined;\n }\n\n if (!Object.prototype.hasOwnProperty.call(spec, \"parameters\")) {\n return undefined;\n }\n\n const rawParameters = (spec as Record<string, unknown>).parameters;\n if (rawParameters === undefined) {\n return undefined;\n }\n\n return cloneDeep(rawParameters as TemplateParametersValue);\n }, [templateObject]);\n\n const templateOutput = useMemo(() => {\n if (!templateObject) {\n return undefined;\n }\n\n const template = asRecord(templateObject);\n if (!template) {\n return undefined;\n }\n\n const spec = asRecord(template.spec);\n if (!spec) {\n return undefined;\n }\n\n const rawOutput = spec.output;\n if (!rawOutput || typeof rawOutput !== \"object\") {\n return undefined;\n }\n\n return cloneDeep(rawOutput as ScaffolderTaskOutput);\n }, [templateObject]);\n\n const handleYamlChange = useCallback(\n (value: string) => {\n setTemplateYaml(value);\n setIsDirty(true);\n scheduleYamlParse(value);\n },\n [scheduleYamlParse]\n );\n\n const handleStepsChange = useCallback(\n (steps: TaskStep[]) => {\n setIsDirty(true);\n setTemplateObject((prevTemplate) => {\n const base =\n prevTemplate && typeof prevTemplate === \"object\"\n ? (cloneDeep(prevTemplate) as Record<string, unknown>)\n : ({} as Record<string, unknown>);\n\n const spec = asRecord(base.spec) ?? {};\n const nextSteps = cloneSteps(steps);\n\n const nextTemplate: Record<string, unknown> = {\n ...base,\n spec: {\n ...spec,\n steps: nextSteps,\n },\n };\n\n templateObjectRef.current = nextTemplate;\n scheduleYamlSerialization(nextTemplate);\n return nextTemplate;\n });\n },\n [scheduleYamlSerialization]\n );\n\n const handleParametersChange = useCallback(\n (parameters: TemplateParametersValue) => {\n setIsDirty(true);\n setTemplateObject((prevTemplate) => {\n const base =\n prevTemplate && typeof prevTemplate === \"object\"\n ? (cloneDeep(prevTemplate) as Record<string, unknown>)\n : ({} as Record<string, unknown>);\n\n const spec = asRecord(base.spec) ?? {};\n const nextTemplate: Record<string, unknown> = {\n ...base,\n spec: {\n ...spec,\n parameters: cloneDeep(parameters),\n },\n };\n\n templateObjectRef.current = nextTemplate;\n scheduleYamlSerialization(nextTemplate);\n return nextTemplate;\n });\n },\n [scheduleYamlSerialization]\n );\n\n const handleOutputChange = useCallback(\n (output?: ScaffolderTaskOutput) => {\n setIsDirty(true);\n setTemplateObject((prevTemplate) => {\n const base =\n prevTemplate && typeof prevTemplate === \"object\"\n ? (cloneDeep(prevTemplate) as Record<string, unknown>)\n : ({} as Record<string, unknown>);\n\n const spec = asRecord(base.spec) ?? {};\n const nextTemplate: Record<string, unknown> = {\n ...base,\n spec: {\n ...spec,\n output: cloneDeep(output),\n },\n };\n\n templateObjectRef.current = nextTemplate;\n scheduleYamlSerialization(nextTemplate);\n return nextTemplate;\n });\n },\n [scheduleYamlSerialization]\n );\n\n const handleReloadFromFile = useCallback(async () => {\n if (!templateSource) {\n return;\n }\n\n if (templateSource.type === \"catalog\") {\n if (selectedTemplate) {\n applyTemplate(selectedTemplate as unknown as Record<string, unknown>, {\n type: \"catalog\",\n label:\n selectedTemplate.metadata.title ?? selectedTemplate.metadata.name,\n });\n }\n return;\n }\n if (templateSource.type !== \"file\") {\n handleStartSampleTemplate();\n return;\n }\n\n if (!templateSource.handle) {\n handleOpenTemplatePicker();\n return;\n }\n\n if (!confirmDiscardChanges()) {\n return;\n }\n\n try {\n setIsReloading(true);\n const granted = await ensureHandlePermission(\n templateSource.handle,\n \"read\"\n );\n if (!granted) {\n setLoadError(\"Permission to read the selected file was denied.\");\n return;\n }\n\n const file = await templateSource.handle.getFile();\n const text = await file.text();\n const parsed = parseTemplateYaml(text);\n applyTemplate(parsed, {\n type: \"file\",\n label: templateSource.handle.name ?? file.name ?? templateSource.label,\n handle: templateSource.handle,\n });\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : \"Unknown error reloading template\";\n setLoadError(`Could not reload template: ${message}`);\n } finally {\n setIsReloading(false);\n }\n }, [\n applyTemplate,\n confirmDiscardChanges,\n ensureHandlePermission,\n handleOpenTemplatePicker,\n handleStartSampleTemplate,\n selectedTemplate,\n templateSource,\n ]);\n\n const handleSaveTemplate = useCallback(async () => {\n if (!templateObject) {\n return;\n }\n\n const yamlToPersist = flushPendingYamlSerialization();\n\n if (typeof window === \"undefined\") {\n downloadString(yamlToPersist, DEFAULT_FILE_NAME);\n setIsDirty(false);\n return;\n }\n\n try {\n setIsSaving(true);\n setLoadError(undefined);\n const fsWindow = window as FileSystemWindow;\n\n if (templateSource?.type === \"file\" && templateSource.handle) {\n const granted = await ensureHandlePermission(\n templateSource.handle,\n \"readwrite\"\n );\n if (!granted) {\n setLoadError(\"Permission to save to the selected file was denied.\");\n return;\n }\n const writable = await templateSource.handle.createWritable?.();\n if (!writable) {\n throw new Error(\"Unable to open file for writing.\");\n }\n await writable.write(yamlToPersist);\n await writable.close();\n setIsDirty(false);\n return;\n }\n\n if (fsWindow.showSaveFilePicker) {\n const handle = await fsWindow.showSaveFilePicker({\n suggestedName: templateSource?.label ?? DEFAULT_FILE_NAME,\n types: FILE_PICKER_TYPES,\n });\n const writable = await handle.createWritable?.();\n if (!writable) {\n throw new Error(\"Unable to open file for writing.\");\n }\n await writable.write(yamlToPersist);\n await writable.close();\n setTemplateSource({\n type: \"file\",\n label: handle.name ?? templateSource?.label ?? DEFAULT_FILE_NAME,\n handle,\n });\n setIsDirty(false);\n return;\n }\n\n downloadString(yamlToPersist, templateSource?.label ?? DEFAULT_FILE_NAME);\n setIsDirty(false);\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : \"Unknown error saving template\";\n setLoadError(`Failed to save template: ${message}`);\n } finally {\n setIsSaving(false);\n }\n }, [\n ensureHandlePermission,\n flushPendingYamlSerialization,\n templateObject,\n templateSource,\n ]);\n\n useEffect(() => {\n catalogApi\n .getEntities({\n filter: {\n kind: \"Template\",\n },\n })\n .then((data) => {\n setAvailableTemplates(data.items as TemplateEntityV1beta3[]);\n })\n .catch(() => setAvailableTemplates([]));\n }, [catalogApi]);\n\n const selectCatalogTemplate = useCallback(\n (selected: TemplateEntityV1beta3) => {\n setSelectedTemplate(selected);\n applyTemplate(selected as unknown as Record<string, unknown>, {\n type: \"catalog\",\n label: selected.metadata.title ?? selected.metadata.name,\n });\n },\n [applyTemplate]\n );\n\n return {\n templateObject,\n templateYaml,\n yamlError,\n loadError,\n isDirty,\n templateSource,\n isReloading,\n isSaving,\n isSyncing,\n templateSteps,\n templateParameters,\n templateOutput,\n fileInputRef,\n handleStartSampleTemplate,\n handleTemplateFileSelected,\n handleOpenTemplatePicker,\n handleYamlChange,\n handleStepsChange,\n handleParametersChange,\n handleOutputChange,\n handleReloadFromFile,\n handleSaveTemplate,\n availableTemplates,\n selectCatalogTemplate,\n };\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.esm.js","sources":["../../../src/components/TemplateDesigner/utils.ts"],"sourcesContent":["import type { TaskStep } from \"@backstage/plugin-scaffolder-common\";\n\nexport const FILE_PICKER_ACCEPT = {\n \"application/yaml\": [\".yaml\", \".yml\"],\n \"application/json\": [\".json\"],\n};\n\nexport const FILE_PICKER_TYPES = [\n {\n description: \"Scaffolder template\",\n accept: FILE_PICKER_ACCEPT,\n },\n];\n\nexport const DEFAULT_FILE_NAME = \"template.yaml\";\n\nexport const isTaskStep = (candidate: unknown): candidate is TaskStep => {\n if (!candidate || typeof candidate !== \"object\") {\n return false;\n }\n const step = candidate as Record<string, unknown>;\n return (\n typeof step.id === \"string\" &&\n typeof step.name === \"string\" &&\n typeof step.action === \"string\"\n );\n};\n\nexport const cloneDeep = <T>(value: T): T => {\n if (value === undefined || value === null) {\n return value;\n }\n return JSON.parse(JSON.stringify(value)) as T;\n};\n\nexport const cloneSteps = (steps: TaskStep[]): TaskStep[] =>\n steps.map((step) => cloneDeep(step));\n\nexport const asRecord = (\n candidate: unknown\n): Record<string, unknown> | undefined => {\n if (!candidate || typeof candidate !== \"object\") {\n return undefined;\n }\n return candidate as Record<string, unknown>;\n};\n\nexport const downloadString = (value: string, fileName: string) => {\n const blob = new Blob([value], { type: \"text/yaml\" });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = fileName;\n anchor.style.display = \"none\";\n document.body.appendChild(anchor);\n anchor.click();\n document.body.removeChild(anchor);\n URL.revokeObjectURL(url);\n};\n\nexport type FileSystemFileHandleLike = {\n name?: string;\n getFile: () => Promise<File>;\n createWritable?: () => Promise<{\n write: (data: Blob | string) => Promise<void>;\n close: () => Promise<void>;\n }>;\n queryPermission?: (options?: {\n mode?: \"read\" | \"readwrite\";\n }) => Promise<PermissionState>;\n requestPermission?: (options?: {\n mode?: \"read\" | \"readwrite\";\n }) => Promise<PermissionState>;\n};\n\nexport type TemplateSource =\n | { type: \"sample\"; label: string }\n | { type: \"file\"; label: string; handle?: FileSystemFileHandleLike };\n\nexport type FileSystemWindow = Window &\n Partial<{\n showOpenFilePicker: (\n options?: unknown\n ) => Promise<FileSystemFileHandleLike[]>;\n showSaveFilePicker: (\n options?: unknown\n ) => Promise<FileSystemFileHandleLike>;\n }>;\n"],"names":[],"mappings":"AAEO,MAAM,kBAAA,GAAqB;AAAA,EAChC,kBAAA,EAAoB,CAAC,OAAA,EAAS,MAAM,CAAA;AAAA,EACpC,kBAAA,EAAoB,CAAC,OAAO;AAC9B;AAEO,MAAM,iBAAA,GAAoB;AAAA,EAC/B;AAAA,IACE,WAAA,EAAa,qBAAA;AAAA,IACb,MAAA,EAAQ;AAAA;AAEZ;AAEO,MAAM,iBAAA,GAAoB;AAE1B,MAAM,UAAA,GAAa,CAAC,SAAA,KAA8C;AACvE,EAAA,IAAI,CAAC,SAAA,IAAa,OAAO,SAAA,KAAc,QAAA,EAAU;AAC/C,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,MAAM,IAAA,GAAO,SAAA;AACb,EAAA,OACE,OAAO,IAAA,CAAK,EAAA,KAAO,QAAA,IACnB,OAAO,KAAK,IAAA,KAAS,QAAA,IACrB,OAAO,IAAA,CAAK,MAAA,KAAW,QAAA;AAE3B;AAEO,MAAM,SAAA,GAAY,CAAI,KAAA,KAAgB;AAC3C,EAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AACzC,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AACzC;AAEO,MAAM,UAAA,GAAa,CAAC,KAAA,KACzB,KAAA,CAAM,IAAI,CAAC,IAAA,KAAS,SAAA,CAAU,IAAI,CAAC;AAE9B,MAAM,QAAA,GAAW,CACtB,SAAA,KACwC;AACxC,EAAA,IAAI,CAAC,SAAA,IAAa,OAAO,SAAA,KAAc,QAAA,EAAU;AAC/C,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,SAAA;AACT;AAEO,MAAM,cAAA,GAAiB,CAAC,KAAA,EAAe,QAAA,KAAqB;AACjE,EAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,CAAC,KAAK,CAAA,EAAG,EAAE,IAAA,EAAM,WAAA,EAAa,CAAA;AACpD,EAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,CAAgB,IAAI,CAAA;AACpC,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,GAAG,CAAA;AACzC,EAAA,MAAA,CAAO,IAAA,GAAO,GAAA;AACd,EAAA,MAAA,CAAO,QAAA,GAAW,QAAA;AAClB,EAAA,MAAA,CAAO,MAAM,OAAA,GAAU,MAAA;AACvB,EAAA,QAAA,CAAS,IAAA,CAAK,YAAY,MAAM,CAAA;AAChC,EAAA,MAAA,CAAO,KAAA,EAAM;AACb,EAAA,QAAA,CAAS,IAAA,CAAK,YAAY,MAAM,CAAA;AAChC,EAAA,GAAA,CAAI,gBAAgB,GAAG,CAAA;AACzB;;;;"}
|
|
1
|
+
{"version":3,"file":"utils.esm.js","sources":["../../../src/components/TemplateDesigner/utils.ts"],"sourcesContent":["import type { TaskStep } from \"@backstage/plugin-scaffolder-common\";\n\nexport const FILE_PICKER_ACCEPT = {\n \"application/yaml\": [\".yaml\", \".yml\"],\n \"application/json\": [\".json\"],\n};\n\nexport const FILE_PICKER_TYPES = [\n {\n description: \"Scaffolder template\",\n accept: FILE_PICKER_ACCEPT,\n },\n];\n\nexport const DEFAULT_FILE_NAME = \"template.yaml\";\n\nexport const isTaskStep = (candidate: unknown): candidate is TaskStep => {\n if (!candidate || typeof candidate !== \"object\") {\n return false;\n }\n const step = candidate as Record<string, unknown>;\n return (\n typeof step.id === \"string\" &&\n typeof step.name === \"string\" &&\n typeof step.action === \"string\"\n );\n};\n\nexport const cloneDeep = <T>(value: T): T => {\n if (value === undefined || value === null) {\n return value;\n }\n return JSON.parse(JSON.stringify(value)) as T;\n};\n\nexport const cloneSteps = (steps: TaskStep[]): TaskStep[] =>\n steps.map((step) => cloneDeep(step));\n\nexport const asRecord = (\n candidate: unknown\n): Record<string, unknown> | undefined => {\n if (!candidate || typeof candidate !== \"object\") {\n return undefined;\n }\n return candidate as Record<string, unknown>;\n};\n\nexport const downloadString = (value: string, fileName: string) => {\n const blob = new Blob([value], { type: \"text/yaml\" });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = fileName;\n anchor.style.display = \"none\";\n document.body.appendChild(anchor);\n anchor.click();\n document.body.removeChild(anchor);\n URL.revokeObjectURL(url);\n};\n\nexport type FileSystemFileHandleLike = {\n name?: string;\n getFile: () => Promise<File>;\n createWritable?: () => Promise<{\n write: (data: Blob | string) => Promise<void>;\n close: () => Promise<void>;\n }>;\n queryPermission?: (options?: {\n mode?: \"read\" | \"readwrite\";\n }) => Promise<PermissionState>;\n requestPermission?: (options?: {\n mode?: \"read\" | \"readwrite\";\n }) => Promise<PermissionState>;\n};\n\nexport type TemplateSource =\n | { type: \"sample\"; label: string }\n | { type: \"file\"; label: string; handle?: FileSystemFileHandleLike }\n | { type: \"catalog\"; label: string };\n\nexport type FileSystemWindow = Window &\n Partial<{\n showOpenFilePicker: (\n options?: unknown\n ) => Promise<FileSystemFileHandleLike[]>;\n showSaveFilePicker: (\n options?: unknown\n ) => Promise<FileSystemFileHandleLike>;\n }>;\n"],"names":[],"mappings":"AAEO,MAAM,kBAAA,GAAqB;AAAA,EAChC,kBAAA,EAAoB,CAAC,OAAA,EAAS,MAAM,CAAA;AAAA,EACpC,kBAAA,EAAoB,CAAC,OAAO;AAC9B;AAEO,MAAM,iBAAA,GAAoB;AAAA,EAC/B;AAAA,IACE,WAAA,EAAa,qBAAA;AAAA,IACb,MAAA,EAAQ;AAAA;AAEZ;AAEO,MAAM,iBAAA,GAAoB;AAE1B,MAAM,UAAA,GAAa,CAAC,SAAA,KAA8C;AACvE,EAAA,IAAI,CAAC,SAAA,IAAa,OAAO,SAAA,KAAc,QAAA,EAAU;AAC/C,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,MAAM,IAAA,GAAO,SAAA;AACb,EAAA,OACE,OAAO,IAAA,CAAK,EAAA,KAAO,QAAA,IACnB,OAAO,KAAK,IAAA,KAAS,QAAA,IACrB,OAAO,IAAA,CAAK,MAAA,KAAW,QAAA;AAE3B;AAEO,MAAM,SAAA,GAAY,CAAI,KAAA,KAAgB;AAC3C,EAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AACzC,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AACzC;AAEO,MAAM,UAAA,GAAa,CAAC,KAAA,KACzB,KAAA,CAAM,IAAI,CAAC,IAAA,KAAS,SAAA,CAAU,IAAI,CAAC;AAE9B,MAAM,QAAA,GAAW,CACtB,SAAA,KACwC;AACxC,EAAA,IAAI,CAAC,SAAA,IAAa,OAAO,SAAA,KAAc,QAAA,EAAU;AAC/C,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,SAAA;AACT;AAEO,MAAM,cAAA,GAAiB,CAAC,KAAA,EAAe,QAAA,KAAqB;AACjE,EAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,CAAC,KAAK,CAAA,EAAG,EAAE,IAAA,EAAM,WAAA,EAAa,CAAA;AACpD,EAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,CAAgB,IAAI,CAAA;AACpC,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,GAAG,CAAA;AACzC,EAAA,MAAA,CAAO,IAAA,GAAO,GAAA;AACd,EAAA,MAAA,CAAO,QAAA,GAAW,QAAA;AAClB,EAAA,MAAA,CAAO,MAAM,OAAA,GAAU,MAAA;AACvB,EAAA,QAAA,CAAS,IAAA,CAAK,YAAY,MAAM,CAAA;AAChC,EAAA,MAAA,CAAO,KAAA,EAAM;AACb,EAAA,QAAA,CAAS,IAAA,CAAK,YAAY,MAAM,CAAA;AAChC,EAAA,GAAA,CAAI,gBAAgB,GAAG,CAAA;AACzB;;;;"}
|
package/dist/package.json.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
var name = "@tduniec/plugin-template-designer";
|
|
2
2
|
var description = "Template Designer turns blank Backstage YAML into a storyboard-like canvas, guiding anyone through drag-and-drop scaffolder authoring before ever touching code. Rally non-experts, broadcast best practices, and accelerate template launches directly inside Backstage.";
|
|
3
|
-
var version = "0.
|
|
3
|
+
var version = "0.3.0";
|
|
4
4
|
var license = "Apache-2.0";
|
|
5
5
|
var keywords = [
|
|
6
6
|
"backstage",
|
|
@@ -60,6 +60,7 @@ var dependencies = {
|
|
|
60
60
|
"@backstage/core-components": "backstage:^",
|
|
61
61
|
"@backstage/core-plugin-api": "backstage:^",
|
|
62
62
|
"@backstage/frontend-plugin-api": "backstage:^",
|
|
63
|
+
"@backstage/plugin-catalog-react": "backstage:^",
|
|
63
64
|
"@backstage/plugin-scaffolder-common": "backstage:^",
|
|
64
65
|
"@backstage/plugin-scaffolder-react": "backstage:^",
|
|
65
66
|
"@backstage/theme": "backstage:^",
|
|
@@ -80,9 +81,12 @@ var peerDependencies = {
|
|
|
80
81
|
"react-use": "^17.2.4"
|
|
81
82
|
};
|
|
82
83
|
var devDependencies = {
|
|
84
|
+
"@backstage/catalog-client": "backstage:^",
|
|
85
|
+
"@backstage/catalog-model": "backstage:^",
|
|
83
86
|
"@backstage/cli": "backstage:^",
|
|
84
87
|
"@backstage/core-app-api": "backstage:^",
|
|
85
88
|
"@backstage/dev-utils": "backstage:^",
|
|
89
|
+
"@backstage/plugin-catalog-common": "backstage:^",
|
|
86
90
|
"@backstage/test-utils": "backstage:^",
|
|
87
91
|
"@codemirror/lang-yaml": "6.1.2",
|
|
88
92
|
"@codemirror/state": "6.5.2",
|