@tduniec/plugin-template-designer-foundation 0.1.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +13 -0
  3. package/dist/api/useScaffolderActions.esm.js +59 -0
  4. package/dist/api/useScaffolderActions.esm.js.map +1 -0
  5. package/dist/components/FieldEditorDialog.esm.js +55 -0
  6. package/dist/components/FieldEditorDialog.esm.js.map +1 -0
  7. package/dist/components/Nodes/ActionNode.esm.js +613 -0
  8. package/dist/components/Nodes/ActionNode.esm.js.map +1 -0
  9. package/dist/components/Nodes/OutputNode.esm.js +373 -0
  10. package/dist/components/Nodes/OutputNode.esm.js.map +1 -0
  11. package/dist/components/Nodes/ParameterInputNode.esm.js +320 -0
  12. package/dist/components/Nodes/ParameterInputNode.esm.js.map +1 -0
  13. package/dist/components/Nodes/ParameterTitlesNode.esm.js +251 -0
  14. package/dist/components/Nodes/ParameterTitlesNode.esm.js.map +1 -0
  15. package/dist/components/Nodes/ParametersNode.esm.js +147 -0
  16. package/dist/components/Nodes/ParametersNode.esm.js.map +1 -0
  17. package/dist/components/Nodes/action/schema.esm.js +68 -0
  18. package/dist/components/Nodes/action/schema.esm.js.map +1 -0
  19. package/dist/components/Nodes/action/useActionInputs.esm.js +71 -0
  20. package/dist/components/Nodes/action/useActionInputs.esm.js.map +1 -0
  21. package/dist/components/Nodes/common/AutoWidthPopper.esm.js +11 -0
  22. package/dist/components/Nodes/common/AutoWidthPopper.esm.js.map +1 -0
  23. package/dist/components/Nodes/common/nodeInteraction.esm.js +20 -0
  24. package/dist/components/Nodes/common/nodeInteraction.esm.js.map +1 -0
  25. package/dist/components/Nodes/output/useOutputController.esm.js +125 -0
  26. package/dist/components/Nodes/output/useOutputController.esm.js.map +1 -0
  27. package/dist/components/TemplateDesigner/TemplateLanding.esm.js +157 -0
  28. package/dist/components/TemplateDesigner/TemplateLanding.esm.js.map +1 -0
  29. package/dist/components/TemplateDesigner/TemplateWorkspace.esm.js +416 -0
  30. package/dist/components/TemplateDesigner/TemplateWorkspace.esm.js.map +1 -0
  31. package/dist/components/TemplateDesigner/codemirrorTheme.esm.js +30 -0
  32. package/dist/components/TemplateDesigner/codemirrorTheme.esm.js.map +1 -0
  33. package/dist/components/TemplateDesigner/useFieldEditor.esm.js +95 -0
  34. package/dist/components/TemplateDesigner/useFieldEditor.esm.js.map +1 -0
  35. package/dist/components/TemplateDesignerIcon.esm.js +33 -0
  36. package/dist/components/TemplateDesignerIcon.esm.js.map +1 -0
  37. package/dist/components/designerFlowConfig.esm.js +13 -0
  38. package/dist/components/designerFlowConfig.esm.js.map +1 -0
  39. package/dist/designerFlow/DesignerFlow.esm.js +828 -0
  40. package/dist/designerFlow/DesignerFlow.esm.js.map +1 -0
  41. package/dist/designerFlow/handlers.esm.js +317 -0
  42. package/dist/designerFlow/handlers.esm.js.map +1 -0
  43. package/dist/designerFlow/model.esm.js +166 -0
  44. package/dist/designerFlow/model.esm.js.map +1 -0
  45. package/dist/designerFlow/nodeLayout.esm.js +108 -0
  46. package/dist/designerFlow/nodeLayout.esm.js.map +1 -0
  47. package/dist/designerFlow/parameterTransforms.esm.js +124 -0
  48. package/dist/designerFlow/parameterTransforms.esm.js.map +1 -0
  49. package/dist/designerFlow/utils/stableComparators.esm.js +69 -0
  50. package/dist/designerFlow/utils/stableComparators.esm.js.map +1 -0
  51. package/dist/foundation/actionNodeCustomization.esm.js +20 -0
  52. package/dist/foundation/actionNodeCustomization.esm.js.map +1 -0
  53. package/dist/foundation/actionNodeRegistry.esm.js +30 -0
  54. package/dist/foundation/actionNodeRegistry.esm.js.map +1 -0
  55. package/dist/foundation/featureFlags.esm.js +6 -0
  56. package/dist/foundation/featureFlags.esm.js.map +1 -0
  57. package/dist/foundation/templateSources.esm.js +16 -0
  58. package/dist/foundation/templateSources.esm.js.map +1 -0
  59. package/dist/index.d.ts +382 -0
  60. package/dist/index.esm.js +25 -0
  61. package/dist/index.esm.js.map +1 -0
  62. package/dist/state/templateUtils.esm.js +46 -0
  63. package/dist/state/templateUtils.esm.js.map +1 -0
  64. package/dist/state/useParameterSections.esm.js +162 -0
  65. package/dist/state/useParameterSections.esm.js.map +1 -0
  66. package/dist/state/useTemplateState.esm.js +627 -0
  67. package/dist/state/useTemplateState.esm.js.map +1 -0
  68. package/dist/types/flowNodes.esm.js +8 -0
  69. package/dist/types/flowNodes.esm.js.map +1 -0
  70. package/dist/utils/createSequentialEdges.esm.js +15 -0
  71. package/dist/utils/createSequentialEdges.esm.js.map +1 -0
  72. package/dist/utils/mocks/mocks.esm.js +120 -0
  73. package/dist/utils/mocks/mocks.esm.js.map +1 -0
  74. package/dist/utils/sampleTemplate.esm.js +40 -0
  75. package/dist/utils/sampleTemplate.esm.js.map +1 -0
  76. package/dist/utils/yamlJsonConversion.esm.js +47 -0
  77. package/dist/utils/yamlJsonConversion.esm.js.map +1 -0
  78. package/package.json +103 -0
@@ -0,0 +1,382 @@
1
+ import * as react from 'react';
2
+ import { ComponentType, RefObject, ChangeEvent, ReactNode } from 'react';
3
+ import { NodeProps, Node, Edge, Position } from '@xyflow/react';
4
+ import * as _backstage_plugin_scaffolder_common from '@backstage/plugin-scaffolder-common';
5
+ import { TemplateEntityV1beta3, TaskStep, TemplateParametersV1beta3, TemplateParameterSchema, ScaffolderTaskOutput, ListActionsResponse } from '@backstage/plugin-scaffolder-common';
6
+ import * as react_jsx_runtime from 'react/jsx-runtime';
7
+ import { SvgIconProps } from '@material-ui/core/SvgIcon';
8
+ import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
9
+ import * as _backstage_catalog_client from '@backstage/catalog-client';
10
+
11
+ type RegisteredActionNode = {
12
+ id: string;
13
+ component: ComponentType<NodeProps>;
14
+ locked: boolean;
15
+ };
16
+ type FeatureFlagClient = {
17
+ isEnabled: (flag: string) => boolean;
18
+ };
19
+ type TemplateSourceProvider = {
20
+ id: string;
21
+ label: string;
22
+ selectTemplate: () => Promise<TemplateEntityV1beta3 | null>;
23
+ };
24
+
25
+ declare class ActionNodeRegistry {
26
+ private readonly nodes;
27
+ /**
28
+ * Register a new action node renderer. Locked nodes cannot be overridden.
29
+ */
30
+ register(id: string, component: ComponentType<NodeProps>, options?: {
31
+ locked?: boolean;
32
+ }): void;
33
+ get(id: string): ComponentType<NodeProps> | undefined;
34
+ list(): RegisteredActionNode[];
35
+ }
36
+ /**
37
+ * Shared registry instance to keep the common action nodes "final".
38
+ * PRO can append new nodes by registering under a different id.
39
+ */
40
+ declare const actionNodeRegistry: ActionNodeRegistry;
41
+
42
+ declare class TemplateSourceRegistry {
43
+ private readonly providers;
44
+ register(provider: TemplateSourceProvider): void;
45
+ list(): TemplateSourceProvider[];
46
+ }
47
+ /**
48
+ * Registry that lets OSS and PRO expose additional template pickers
49
+ * (catalog, git, SaaS, etc.) without changing the core UI.
50
+ */
51
+ declare const templateSourceRegistry: TemplateSourceRegistry;
52
+
53
+ /**
54
+ * Default flag client used by OSS; PRO can swap for a richer provider.
55
+ */
56
+ declare const noopFeatureFlags: FeatureFlagClient;
57
+
58
+ type JsonSchemaProperty = Record<string, unknown>;
59
+ type ActionSchemaDecorator = (options: {
60
+ actionId: string;
61
+ step: TaskStep;
62
+ schema: Record<string, JsonSchemaProperty>;
63
+ }) => Record<string, JsonSchemaProperty>;
64
+ type ActionFieldsRendererProps = {
65
+ actionId: string;
66
+ step: TaskStep;
67
+ input?: Record<string, unknown>;
68
+ schema: Record<string, JsonSchemaProperty>;
69
+ onUpdateInput: (key: string, value: unknown) => void;
70
+ };
71
+ type ActionFieldsRenderer = ComponentType<ActionFieldsRendererProps>;
72
+ /**
73
+ * Simple singleton registry used by the Action node to apply schema tweaks
74
+ * and render optional custom UI from downstream packages (e.g. PRO).
75
+ */
76
+ declare class ActionNodeCustomizationRegistry {
77
+ private schemaDecorators;
78
+ private fieldsRenderer;
79
+ registerSchemaDecorator(decorator: ActionSchemaDecorator): void;
80
+ registerFieldsRenderer(renderer: ActionFieldsRenderer): void;
81
+ getSchemaDecorators(): ActionSchemaDecorator[];
82
+ getFieldsRenderer(): ActionFieldsRenderer | undefined;
83
+ }
84
+ declare const actionNodeCustomizationRegistry: ActionNodeCustomizationRegistry;
85
+
86
+ declare const FILE_PICKER_ACCEPT: {
87
+ "application/yaml": string[];
88
+ "application/json": string[];
89
+ };
90
+ declare const FILE_PICKER_TYPES: {
91
+ description: string;
92
+ accept: {
93
+ "application/yaml": string[];
94
+ "application/json": string[];
95
+ };
96
+ }[];
97
+ declare const DEFAULT_FILE_NAME = "template.yaml";
98
+ declare const isTaskStep: (candidate: unknown) => candidate is TaskStep;
99
+ declare const cloneDeep: <T>(value: T) => T;
100
+ declare const cloneSteps: (steps: TaskStep[]) => TaskStep[];
101
+ declare const asRecord: (candidate: unknown) => Record<string, unknown> | undefined;
102
+ declare const downloadString: (value: string, fileName: string) => void;
103
+ type FileSystemFileHandleLike = {
104
+ name?: string;
105
+ getFile: () => Promise<File>;
106
+ createWritable?: () => Promise<{
107
+ write: (data: Blob | string) => Promise<void>;
108
+ close: () => Promise<void>;
109
+ }>;
110
+ queryPermission?: (options?: {
111
+ mode?: "read" | "readwrite";
112
+ }) => Promise<PermissionState>;
113
+ requestPermission?: (options?: {
114
+ mode?: "read" | "readwrite";
115
+ }) => Promise<PermissionState>;
116
+ };
117
+ type TemplateSource = {
118
+ type: "sample";
119
+ label: string;
120
+ } | {
121
+ type: "file";
122
+ label: string;
123
+ handle?: FileSystemFileHandleLike;
124
+ } | {
125
+ type: "catalog";
126
+ label: string;
127
+ };
128
+ type FileSystemWindow = Window & Partial<{
129
+ showOpenFilePicker: (options?: unknown) => Promise<FileSystemFileHandleLike[]>;
130
+ showSaveFilePicker: (options?: unknown) => Promise<FileSystemFileHandleLike>;
131
+ }>;
132
+
133
+ type TemplateParametersValue = TemplateParametersV1beta3 | TemplateParametersV1beta3[] | TemplateParameterSchema | TemplateParameterSchema[] | undefined;
134
+
135
+ type TemplateState = {
136
+ templateObject: Record<string, unknown> | null;
137
+ templateYaml: string;
138
+ yamlError?: string;
139
+ loadError?: string;
140
+ isDirty: boolean;
141
+ templateSource?: TemplateSource;
142
+ isReloading: boolean;
143
+ isSaving: boolean;
144
+ isSyncing: boolean;
145
+ templateSteps: TaskStep[];
146
+ templateParameters: TemplateParametersValue;
147
+ templateOutput?: ScaffolderTaskOutput;
148
+ fileInputRef: RefObject<HTMLInputElement>;
149
+ handleStartSampleTemplate: () => void;
150
+ handleTemplateFileSelected: (event: ChangeEvent<HTMLInputElement>) => void;
151
+ handleOpenTemplatePicker: () => void;
152
+ handleYamlChange: (value: string) => void;
153
+ handleStepsChange: (steps: TaskStep[]) => void;
154
+ handleParametersChange: (parameters: TemplateParametersValue) => void;
155
+ handleOutputChange: (output?: ScaffolderTaskOutput) => void;
156
+ handleReloadFromFile: () => void;
157
+ handleSaveTemplate: () => void;
158
+ availableTemplates: TemplateEntityV1beta3[];
159
+ selectCatalogTemplate: (selected: TemplateEntityV1beta3) => void;
160
+ };
161
+ /**
162
+ * Encapsulates the template designer data model including YAML parsing,
163
+ * scaffolder spec updates, and file-system interactions.
164
+ */
165
+ declare const useTemplateState: () => TemplateState;
166
+
167
+ type DesignerNodeType = "parametersNode" | "actionNode" | "outputNode";
168
+ type AddNodeConfig = {
169
+ afterRfId: string;
170
+ type?: DesignerNodeType;
171
+ stepTemplate?: Partial<TaskStep>;
172
+ outputTemplate?: ScaffolderTaskOutput;
173
+ parametersTemplate?: TemplateParametersValue;
174
+ };
175
+ type BaseNodeData = {
176
+ /** Stable ReactFlow node id */
177
+ rfId: string;
178
+ /** Cached scaffolder action ids for dropdown options */
179
+ scaffolderActionIds?: string[];
180
+ /** Cached action input schemas keyed by action id */
181
+ scaffolderActionInputsById?: Record<string, Record<string, unknown>>;
182
+ /** Cached action required input keys keyed by action id */
183
+ scaffolderActionInputRequiredById?: Record<string, string[]>;
184
+ /** Cached action output schemas keyed by action id */
185
+ scaffolderActionOutputsById?: Record<string, Record<string, unknown>>;
186
+ /** Suggestions for referencing previous step outputs */
187
+ stepOutputReferences?: string[];
188
+ onAddNode?: (config: AddNodeConfig) => void;
189
+ onRemoveNode?: (rfId: string) => void;
190
+ };
191
+ type ActionNodeData = BaseNodeData & {
192
+ /** User payload; id is editable string (reserved by your template) */
193
+ step: TaskStep & {
194
+ input?: Record<string, unknown>;
195
+ };
196
+ onUpdateField?: (rfId: string, field: keyof TaskStep, value: string) => void;
197
+ onUpdateInput?: (rfId: string, key: string, value: unknown) => void;
198
+ onRemoveInputKey?: (rfId: string, key: string) => void;
199
+ };
200
+ type OutputNodeData = BaseNodeData & {
201
+ output: ScaffolderTaskOutput;
202
+ onUpdateOutput?: (rfId: string, updater: (prev: ScaffolderTaskOutput) => ScaffolderTaskOutput) => void;
203
+ };
204
+ type ParameterFieldDisplay = {
205
+ id: string;
206
+ fieldName: string;
207
+ sectionId: string;
208
+ sectionTitle?: string;
209
+ required: boolean;
210
+ schema?: Record<string, unknown>;
211
+ };
212
+ type ParameterSectionDisplay = {
213
+ id: string;
214
+ title?: string;
215
+ description?: string;
216
+ required?: string[];
217
+ properties?: Record<string, Record<string, unknown>>;
218
+ fields: ParameterFieldDisplay[];
219
+ };
220
+ type ParametersNodeData = BaseNodeData & {
221
+ parameters: TemplateParametersValue;
222
+ sections?: ParameterSectionDisplay[];
223
+ onUpdateSections?: (rfId: string, updater: (prev: ParameterSectionDisplay[]) => ParameterSectionDisplay[]) => void;
224
+ };
225
+ declare const NODE_VERTICAL_SPACING: Record<DesignerNodeType, number>;
226
+
227
+ declare const useParameterSectionsController: (data: ParametersNodeData) => {
228
+ sections: ParameterSectionDisplay[];
229
+ handleSectionUpdate: (sectionId: string, updater: (section: ParameterSectionDisplay) => ParameterSectionDisplay) => void;
230
+ handleFieldUpdate: (sectionId: string, fieldId: string, updater: (field: ParameterFieldDisplay) => ParameterFieldDisplay) => void;
231
+ handleAddSection: (afterSectionId?: string) => void;
232
+ handleMoveSection: (sectionId: string, direction: "up" | "down") => void;
233
+ handleAddField: (sectionId: string, afterFieldId?: string) => void;
234
+ handleMoveField: (sectionId: string, fieldId: string, direction: "up" | "down") => void;
235
+ };
236
+
237
+ declare const convertJsonToYaml: (value: unknown) => string;
238
+ declare const convertYamlToJson: (value: unknown) => string;
239
+
240
+ declare const SAMPLE_TEMPLATE_BLUEPRINT: Record<string, unknown>;
241
+
242
+ declare function createSequentialEdges(nodes: Node[]): Edge[];
243
+
244
+ type ScaffolderActionsCache = {
245
+ ids: string[];
246
+ inputsById: Record<string, Record<string, unknown>>;
247
+ outputsById: Record<string, Record<string, unknown>>;
248
+ inputRequiredById: Record<string, string[]>;
249
+ };
250
+ declare const useScaffolderActions: () => ScaffolderActionsCache;
251
+
252
+ type FieldEditorDialogProps = {
253
+ open: boolean;
254
+ label?: string;
255
+ value: string;
256
+ onClose: () => void;
257
+ onApply: (value: string) => void;
258
+ };
259
+ declare const FieldEditorDialog: ({ open, label, value, onClose, onApply, }: FieldEditorDialogProps) => react_jsx_runtime.JSX.Element;
260
+
261
+ declare const TemplateDesignerIcon: (props: SvgIconProps) => react_jsx_runtime.JSX.Element;
262
+
263
+ type TemplateLandingProps = {
264
+ loadError?: string;
265
+ onStartSampleTemplate: () => void;
266
+ onOpenTemplatePicker: () => void;
267
+ availableTemplates: TemplateEntityV1beta3[];
268
+ selectCatalogTemplate: (selected: TemplateEntityV1beta3) => void;
269
+ };
270
+ declare const TemplateLanding: ({ loadError, onStartSampleTemplate, onOpenTemplatePicker, availableTemplates, selectCatalogTemplate, }: TemplateLandingProps) => react_jsx_runtime.JSX.Element;
271
+
272
+ type DesignerFlowProps = {
273
+ steps?: TaskStep[];
274
+ parameters?: TemplateParametersValue;
275
+ output?: ScaffolderTaskOutput | null;
276
+ onStepsChange?: (steps: TaskStep[]) => void;
277
+ onParametersChange?: (parameters: TemplateParametersValue) => void;
278
+ onOutputChange?: (output: ScaffolderTaskOutput | undefined) => void;
279
+ actionNodeComponent: ComponentType<{
280
+ data: ActionNodeData;
281
+ }>;
282
+ parametersNodeComponent: ComponentType<{
283
+ data: ParametersNodeData;
284
+ }>;
285
+ outputNodeComponent: ComponentType<{
286
+ data: OutputNodeData;
287
+ }>;
288
+ decorateNodes?: (nodes: Node[]) => Node[];
289
+ decorateEdges?: (edges: Edge[], nodes: Node[]) => Edge[];
290
+ nodeDefaults?: Partial<Node>;
291
+ };
292
+ declare function DesignerFlow({ steps, parameters, output, onStepsChange, onParametersChange, onOutputChange, actionNodeComponent, parametersNodeComponent, outputNodeComponent, decorateNodes, decorateEdges, nodeDefaults, }: DesignerFlowProps): react_jsx_runtime.JSX.Element;
293
+
294
+ type TemplateWorkspaceProps = {
295
+ templateSteps: TaskStep[];
296
+ templateParameters: TemplateParametersValue;
297
+ templateOutput?: ScaffolderTaskOutput;
298
+ templateYaml: string;
299
+ yamlError?: string;
300
+ loadError?: string;
301
+ showYaml: boolean;
302
+ onToggleYaml: () => void;
303
+ onYamlChange: (value: string) => void;
304
+ onStepsChange: (steps: TaskStep[]) => void;
305
+ onParametersChange: (parameters: TemplateParametersValue) => void;
306
+ onOutputChange: (output?: ScaffolderTaskOutput) => void;
307
+ onReload: () => void;
308
+ onSave: () => void;
309
+ onOpenTemplatePicker: () => void;
310
+ activeTemplateLabel?: string;
311
+ reloadButtonLabel: string;
312
+ saveButtonLabel: string;
313
+ isReloading: boolean;
314
+ isSaving: boolean;
315
+ isSyncing?: boolean;
316
+ parametersNodeComponent: DesignerFlowProps["parametersNodeComponent"];
317
+ actionNodeComponent?: DesignerFlowProps["actionNodeComponent"];
318
+ outputNodeComponent?: DesignerFlowProps["outputNodeComponent"];
319
+ headerActionsSlot?: ReactNode;
320
+ flowTopSlot?: ReactNode;
321
+ rightPanelSlot?: ReactNode;
322
+ };
323
+ declare const TemplateWorkspace: ({ templateSteps, templateParameters, templateOutput, templateYaml, yamlError, loadError, showYaml, onToggleYaml, onYamlChange, onStepsChange, onParametersChange, onOutputChange, onReload, onSave, onOpenTemplatePicker, activeTemplateLabel, reloadButtonLabel, saveButtonLabel, isReloading, isSaving, isSyncing, parametersNodeComponent, actionNodeComponent, outputNodeComponent, headerActionsSlot, flowTopSlot, rightPanelSlot, }: TemplateWorkspaceProps) => react_jsx_runtime.JSX.Element;
324
+
325
+ type EditorState = null | {
326
+ target: HTMLInputElement | HTMLTextAreaElement;
327
+ label: string;
328
+ initialValue: string;
329
+ };
330
+ /**
331
+ * Provides a modal-friendly editing experience for readonly-looking inputs
332
+ * by letting users double-click any text field and edit its value centrally.
333
+ */
334
+ declare const useFieldEditor: () => {
335
+ editorState: EditorState;
336
+ interactionRootRef: react.MutableRefObject<HTMLDivElement | null>;
337
+ closeEditor: () => void;
338
+ applyEditorValue: (value: string) => void;
339
+ };
340
+
341
+ declare const FLOW_LAYOUT: {
342
+ readonly verticalSpacing: 200;
343
+ readonly fixedXPosition: 100;
344
+ };
345
+ declare const nodeDefaults: {
346
+ sourcePosition: Position;
347
+ targetPosition: Position;
348
+ };
349
+
350
+ declare const ActionNode: react.NamedExoticComponent<{
351
+ data: ActionNodeData;
352
+ }>;
353
+
354
+ declare const OutputNode: react.NamedExoticComponent<{
355
+ data: OutputNodeData;
356
+ }>;
357
+
358
+ declare const ParametersNode: react.NamedExoticComponent<{
359
+ data: ParametersNodeData;
360
+ }>;
361
+
362
+ declare const createStopNodeInteraction: () => {
363
+ onPointerDown: (e: React.PointerEvent<HTMLElement>) => void;
364
+ onKeyDown: (e: React.KeyboardEvent<HTMLElement>) => void;
365
+ className: string;
366
+ inputProps: {
367
+ onPointerDown: (e: React.PointerEvent<HTMLElement>) => void;
368
+ onKeyDown: (e: React.KeyboardEvent<HTMLElement>) => void;
369
+ };
370
+ };
371
+
372
+ declare const MOCK_CATALOG_TEMPLATES: TemplateEntityV1beta3[];
373
+ declare const MOCK_SCAFFOLDER_ACTIONS: ListActionsResponse;
374
+ declare const mockCatalogApiFactory: _backstage_core_plugin_api.ApiFactory<_backstage_catalog_client.CatalogApi, any, {
375
+ [x: string]: unknown;
376
+ }>;
377
+ declare const mockScaffolderApiFactory: _backstage_core_plugin_api.ApiFactory<_backstage_plugin_scaffolder_common.ScaffolderApi, any, {
378
+ [x: string]: unknown;
379
+ }>;
380
+
381
+ export { ActionNode, ActionNodeRegistry, DEFAULT_FILE_NAME, DesignerFlow, FILE_PICKER_ACCEPT, FILE_PICKER_TYPES, FLOW_LAYOUT, FieldEditorDialog, MOCK_CATALOG_TEMPLATES, MOCK_SCAFFOLDER_ACTIONS, NODE_VERTICAL_SPACING, OutputNode, ParametersNode, SAMPLE_TEMPLATE_BLUEPRINT, TemplateDesignerIcon, TemplateLanding, TemplateWorkspace, actionNodeCustomizationRegistry, actionNodeRegistry, asRecord, cloneDeep, cloneSteps, convertJsonToYaml, convertYamlToJson, createSequentialEdges, createStopNodeInteraction, downloadString, isTaskStep, mockCatalogApiFactory, mockScaffolderApiFactory, nodeDefaults, noopFeatureFlags, templateSourceRegistry, useFieldEditor, useParameterSectionsController, useScaffolderActions, useTemplateState };
382
+ export type { ActionFieldsRenderer, ActionFieldsRendererProps, ActionNodeData, ActionSchemaDecorator, AddNodeConfig, DesignerFlowProps, DesignerNodeType, FeatureFlagClient, FieldEditorDialogProps, FileSystemFileHandleLike, FileSystemWindow, OutputNodeData, ParameterFieldDisplay, ParameterSectionDisplay, ParametersNodeData, RegisteredActionNode, ScaffolderActionsCache, TemplateParametersValue, TemplateSource, TemplateSourceProvider, TemplateState };
@@ -0,0 +1,25 @@
1
+ export { ActionNodeRegistry, actionNodeRegistry } from './foundation/actionNodeRegistry.esm.js';
2
+ export { templateSourceRegistry } from './foundation/templateSources.esm.js';
3
+ export { noopFeatureFlags } from './foundation/featureFlags.esm.js';
4
+ export { actionNodeCustomizationRegistry } from './foundation/actionNodeCustomization.esm.js';
5
+ export { DEFAULT_FILE_NAME, FILE_PICKER_ACCEPT, FILE_PICKER_TYPES, asRecord, cloneDeep, cloneSteps, downloadString, isTaskStep } from './state/templateUtils.esm.js';
6
+ export { useTemplateState } from './state/useTemplateState.esm.js';
7
+ export { useParameterSectionsController } from './state/useParameterSections.esm.js';
8
+ export { convertJsonToYaml, convertYamlToJson } from './utils/yamlJsonConversion.esm.js';
9
+ export { SAMPLE_TEMPLATE_BLUEPRINT } from './utils/sampleTemplate.esm.js';
10
+ export { createSequentialEdges } from './utils/createSequentialEdges.esm.js';
11
+ export { NODE_VERTICAL_SPACING } from './types/flowNodes.esm.js';
12
+ export { useScaffolderActions } from './api/useScaffolderActions.esm.js';
13
+ export { FieldEditorDialog } from './components/FieldEditorDialog.esm.js';
14
+ export { TemplateDesignerIcon } from './components/TemplateDesignerIcon.esm.js';
15
+ export { TemplateLanding } from './components/TemplateDesigner/TemplateLanding.esm.js';
16
+ export { TemplateWorkspace } from './components/TemplateDesigner/TemplateWorkspace.esm.js';
17
+ export { useFieldEditor } from './components/TemplateDesigner/useFieldEditor.esm.js';
18
+ export { FLOW_LAYOUT, nodeDefaults } from './components/designerFlowConfig.esm.js';
19
+ export { default as DesignerFlow } from './designerFlow/DesignerFlow.esm.js';
20
+ export { ActionNode } from './components/Nodes/ActionNode.esm.js';
21
+ export { OutputNode } from './components/Nodes/OutputNode.esm.js';
22
+ export { ParametersNode } from './components/Nodes/ParametersNode.esm.js';
23
+ export { createStopNodeInteraction } from './components/Nodes/common/nodeInteraction.esm.js';
24
+ export { MOCK_CATALOG_TEMPLATES, MOCK_SCAFFOLDER_ACTIONS, mockCatalogApiFactory, mockScaffolderApiFactory } from './utils/mocks/mocks.esm.js';
25
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,46 @@
1
+ const FILE_PICKER_ACCEPT = {
2
+ "application/yaml": [".yaml", ".yml"],
3
+ "application/json": [".json"]
4
+ };
5
+ const FILE_PICKER_TYPES = [
6
+ {
7
+ description: "Scaffolder template",
8
+ accept: FILE_PICKER_ACCEPT
9
+ }
10
+ ];
11
+ const DEFAULT_FILE_NAME = "template.yaml";
12
+ const isTaskStep = (candidate) => {
13
+ if (!candidate || typeof candidate !== "object") {
14
+ return false;
15
+ }
16
+ const step = candidate;
17
+ return typeof step.id === "string" && typeof step.name === "string" && typeof step.action === "string";
18
+ };
19
+ const cloneDeep = (value) => {
20
+ if (value === void 0 || value === null) {
21
+ return value;
22
+ }
23
+ return JSON.parse(JSON.stringify(value));
24
+ };
25
+ const cloneSteps = (steps) => steps.map((step) => cloneDeep(step));
26
+ const asRecord = (candidate) => {
27
+ if (!candidate || typeof candidate !== "object") {
28
+ return void 0;
29
+ }
30
+ return candidate;
31
+ };
32
+ const downloadString = (value, fileName) => {
33
+ const blob = new Blob([value], { type: "text/yaml" });
34
+ const url = URL.createObjectURL(blob);
35
+ const anchor = document.createElement("a");
36
+ anchor.href = url;
37
+ anchor.download = fileName;
38
+ anchor.style.display = "none";
39
+ document.body.appendChild(anchor);
40
+ anchor.click();
41
+ document.body.removeChild(anchor);
42
+ URL.revokeObjectURL(url);
43
+ };
44
+
45
+ export { DEFAULT_FILE_NAME, FILE_PICKER_ACCEPT, FILE_PICKER_TYPES, asRecord, cloneDeep, cloneSteps, downloadString, isTaskStep };
46
+ //# sourceMappingURL=templateUtils.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templateUtils.esm.js","sources":["../../src/state/templateUtils.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;;;;"}
@@ -0,0 +1,162 @@
1
+ import { useCallback } from 'react';
2
+
3
+ const buildUniqueId = () => `${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
4
+ const createSectionTemplate = () => {
5
+ const unique = buildUniqueId();
6
+ return {
7
+ id: `section-${unique}`,
8
+ title: "New Section",
9
+ description: "",
10
+ fields: [],
11
+ properties: {},
12
+ required: []
13
+ };
14
+ };
15
+ const createFieldTemplate = (section) => {
16
+ const unique = buildUniqueId();
17
+ const nextIndex = (section.fields?.length ?? 0) + 1;
18
+ const fallbackName = `field_${nextIndex}`;
19
+ return {
20
+ id: `${section.id}-field-${unique}`,
21
+ fieldName: fallbackName,
22
+ sectionId: section.id,
23
+ sectionTitle: section.title,
24
+ required: false,
25
+ schema: {
26
+ title: `Field ${nextIndex}`,
27
+ type: "string"
28
+ }
29
+ };
30
+ };
31
+ const useParameterSectionsController = (data) => {
32
+ const applySectionsUpdate = useCallback(
33
+ (updater) => {
34
+ if (!data.onUpdateSections) {
35
+ return;
36
+ }
37
+ data.onUpdateSections(data.rfId, (prev) => updater(prev ?? []));
38
+ },
39
+ [data]
40
+ );
41
+ const handleSectionUpdate = useCallback(
42
+ (sectionId, updater) => {
43
+ applySectionsUpdate(
44
+ (prev) => (prev ?? []).map(
45
+ (section) => section.id === sectionId ? updater(section) : section
46
+ )
47
+ );
48
+ },
49
+ [applySectionsUpdate]
50
+ );
51
+ const handleFieldUpdate = useCallback(
52
+ (sectionId, fieldId, updater) => {
53
+ handleSectionUpdate(sectionId, (section) => ({
54
+ ...section,
55
+ fields: section.fields?.map(
56
+ (field) => field.id === fieldId ? updater(field) : field
57
+ ) ?? []
58
+ }));
59
+ },
60
+ [handleSectionUpdate]
61
+ );
62
+ const handleAddSection = useCallback(
63
+ (afterSectionId) => {
64
+ applySectionsUpdate((prev) => {
65
+ const list = [...prev ?? []];
66
+ const insertIndex = afterSectionId ? Math.max(
67
+ list.findIndex((section) => section.id === afterSectionId) + 1,
68
+ 0
69
+ ) : list.length;
70
+ const nextSection = createSectionTemplate();
71
+ list.splice(insertIndex, 0, nextSection);
72
+ return list;
73
+ });
74
+ },
75
+ [applySectionsUpdate]
76
+ );
77
+ const handleMoveSection = useCallback(
78
+ (sectionId, direction) => {
79
+ applySectionsUpdate((prev) => {
80
+ const list = [...prev ?? []];
81
+ const currentIndex = list.findIndex(
82
+ (section) => section.id === sectionId
83
+ );
84
+ if (currentIndex < 0) {
85
+ return list;
86
+ }
87
+ const targetIndex = direction === "up" ? currentIndex - 1 : currentIndex + 1;
88
+ if (targetIndex < 0 || targetIndex >= list.length) {
89
+ return list;
90
+ }
91
+ const [item] = list.splice(currentIndex, 1);
92
+ list.splice(targetIndex, 0, item);
93
+ return list;
94
+ });
95
+ },
96
+ [applySectionsUpdate]
97
+ );
98
+ const handleAddField = useCallback(
99
+ (sectionId, afterFieldId) => {
100
+ applySectionsUpdate(
101
+ (prev) => (prev ?? []).map((section) => {
102
+ if (section.id !== sectionId) {
103
+ return section;
104
+ }
105
+ const fields = [...section.fields ?? []];
106
+ const insertIndex = afterFieldId && fields.length ? Math.max(
107
+ fields.findIndex((field) => field.id === afterFieldId) + 1,
108
+ 0
109
+ ) : fields.length;
110
+ const newField = createFieldTemplate(section);
111
+ fields.splice(insertIndex, 0, newField);
112
+ return {
113
+ ...section,
114
+ fields
115
+ };
116
+ })
117
+ );
118
+ },
119
+ [applySectionsUpdate]
120
+ );
121
+ const handleMoveField = useCallback(
122
+ (sectionId, fieldId, direction) => {
123
+ applySectionsUpdate(
124
+ (prev) => (prev ?? []).map((section) => {
125
+ if (section.id !== sectionId) {
126
+ return section;
127
+ }
128
+ const fields = [...section.fields ?? []];
129
+ const currentIndex = fields.findIndex(
130
+ (field) => field.id === fieldId
131
+ );
132
+ if (currentIndex < 0) {
133
+ return section;
134
+ }
135
+ const targetIndex = direction === "up" ? currentIndex - 1 : currentIndex + 1;
136
+ if (targetIndex < 0 || targetIndex >= fields.length) {
137
+ return section;
138
+ }
139
+ const [item] = fields.splice(currentIndex, 1);
140
+ fields.splice(targetIndex, 0, item);
141
+ return {
142
+ ...section,
143
+ fields
144
+ };
145
+ })
146
+ );
147
+ },
148
+ [applySectionsUpdate]
149
+ );
150
+ return {
151
+ sections: data.sections ?? [],
152
+ handleSectionUpdate,
153
+ handleFieldUpdate,
154
+ handleAddSection,
155
+ handleMoveSection,
156
+ handleAddField,
157
+ handleMoveField
158
+ };
159
+ };
160
+
161
+ export { useParameterSectionsController };
162
+ //# sourceMappingURL=useParameterSections.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useParameterSections.esm.js","sources":["../../src/state/useParameterSections.ts"],"sourcesContent":["import { useCallback } from \"react\";\nimport type {\n ParameterFieldDisplay,\n ParameterSectionDisplay,\n ParametersNodeData,\n} from \"../types/flowNodes\";\n\nconst buildUniqueId = () =>\n `${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n\nconst createSectionTemplate = (): ParameterSectionDisplay => {\n const unique = buildUniqueId();\n return {\n id: `section-${unique}`,\n title: \"New Section\",\n description: \"\",\n fields: [],\n properties: {},\n required: [],\n };\n};\n\nconst createFieldTemplate = (\n section: ParameterSectionDisplay\n): ParameterFieldDisplay => {\n const unique = buildUniqueId();\n const nextIndex = (section.fields?.length ?? 0) + 1;\n const fallbackName = `field_${nextIndex}`;\n return {\n id: `${section.id}-field-${unique}`,\n fieldName: fallbackName,\n sectionId: section.id,\n sectionTitle: section.title,\n required: false,\n schema: {\n title: `Field ${nextIndex}`,\n type: \"string\",\n },\n };\n};\n\nexport const useParameterSectionsController = (data: ParametersNodeData) => {\n const applySectionsUpdate = useCallback(\n (\n updater: (\n prevSections: ParameterSectionDisplay[]\n ) => ParameterSectionDisplay[]\n ) => {\n if (!data.onUpdateSections) {\n return;\n }\n data.onUpdateSections(data.rfId, (prev) => updater(prev ?? []));\n },\n [data]\n );\n\n const handleSectionUpdate = useCallback(\n (\n sectionId: string,\n updater: (section: ParameterSectionDisplay) => ParameterSectionDisplay\n ) => {\n applySectionsUpdate((prev) =>\n (prev ?? []).map((section) =>\n section.id === sectionId ? updater(section) : section\n )\n );\n },\n [applySectionsUpdate]\n );\n\n const handleFieldUpdate = useCallback(\n (\n sectionId: string,\n fieldId: string,\n updater: (field: ParameterFieldDisplay) => ParameterFieldDisplay\n ) => {\n handleSectionUpdate(sectionId, (section) => ({\n ...section,\n fields:\n section.fields?.map((field) =>\n field.id === fieldId ? updater(field) : field\n ) ?? [],\n }));\n },\n [handleSectionUpdate]\n );\n\n const handleAddSection = useCallback(\n (afterSectionId?: string) => {\n applySectionsUpdate((prev) => {\n const list = [...(prev ?? [])];\n const insertIndex = afterSectionId\n ? Math.max(\n list.findIndex((section) => section.id === afterSectionId) + 1,\n 0\n )\n : list.length;\n const nextSection = createSectionTemplate();\n list.splice(insertIndex, 0, nextSection);\n return list;\n });\n },\n [applySectionsUpdate]\n );\n\n const handleMoveSection = useCallback(\n (sectionId: string, direction: \"up\" | \"down\") => {\n applySectionsUpdate((prev) => {\n const list = [...(prev ?? [])];\n const currentIndex = list.findIndex(\n (section) => section.id === sectionId\n );\n if (currentIndex < 0) {\n return list;\n }\n const targetIndex =\n direction === \"up\" ? currentIndex - 1 : currentIndex + 1;\n if (targetIndex < 0 || targetIndex >= list.length) {\n return list;\n }\n const [item] = list.splice(currentIndex, 1);\n list.splice(targetIndex, 0, item);\n return list;\n });\n },\n [applySectionsUpdate]\n );\n\n const handleAddField = useCallback(\n (sectionId: string, afterFieldId?: string) => {\n applySectionsUpdate((prev) =>\n (prev ?? []).map((section) => {\n if (section.id !== sectionId) {\n return section;\n }\n const fields = [...(section.fields ?? [])];\n const insertIndex =\n afterFieldId && fields.length\n ? Math.max(\n fields.findIndex((field) => field.id === afterFieldId) + 1,\n 0\n )\n : fields.length;\n const newField = createFieldTemplate(section);\n fields.splice(insertIndex, 0, newField);\n return {\n ...section,\n fields,\n };\n })\n );\n },\n [applySectionsUpdate]\n );\n\n const handleMoveField = useCallback(\n (sectionId: string, fieldId: string, direction: \"up\" | \"down\") => {\n applySectionsUpdate((prev) =>\n (prev ?? []).map((section) => {\n if (section.id !== sectionId) {\n return section;\n }\n const fields = [...(section.fields ?? [])];\n const currentIndex = fields.findIndex(\n (field) => field.id === fieldId\n );\n if (currentIndex < 0) {\n return section;\n }\n const targetIndex =\n direction === \"up\" ? currentIndex - 1 : currentIndex + 1;\n if (targetIndex < 0 || targetIndex >= fields.length) {\n return section;\n }\n const [item] = fields.splice(currentIndex, 1);\n fields.splice(targetIndex, 0, item);\n return {\n ...section,\n fields,\n };\n })\n );\n },\n [applySectionsUpdate]\n );\n\n return {\n sections: data.sections ?? [],\n handleSectionUpdate,\n handleFieldUpdate,\n handleAddSection,\n handleMoveSection,\n handleAddField,\n handleMoveField,\n };\n};\n"],"names":[],"mappings":"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"}