@oronts/vendure-data-hub-plugin 0.1.0 → 0.1.2

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 (235) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/dashboard/components/common/ConnectionConfigEditor.tsx +589 -0
  3. package/dist/dashboard/components/common/HeadersEditor.tsx +90 -0
  4. package/dist/dashboard/components/common/ValidationFeedback.tsx +17 -0
  5. package/dist/dashboard/components/common/index.ts +10 -0
  6. package/dist/dashboard/components/pipelines/PipelineEditor.tsx +504 -0
  7. package/dist/dashboard/components/pipelines/PipelineExport.tsx +63 -0
  8. package/dist/dashboard/components/pipelines/PipelineImport.tsx +87 -0
  9. package/dist/dashboard/components/pipelines/ReactFlowPipelineEditor.tsx +539 -0
  10. package/dist/dashboard/components/pipelines/shared/NodePropertiesPanel.tsx +146 -0
  11. package/dist/dashboard/components/pipelines/shared/PipelineNode.tsx +155 -0
  12. package/dist/dashboard/components/pipelines/shared/PipelineSettingsPanel.tsx +392 -0
  13. package/dist/dashboard/components/pipelines/shared/StepListItem.tsx +144 -0
  14. package/dist/dashboard/components/pipelines/shared/index.ts +33 -0
  15. package/dist/dashboard/components/pipelines/shared/visual-node-config.ts +169 -0
  16. package/dist/dashboard/components/shared/LoadMoreButton.tsx +18 -0
  17. package/dist/dashboard/components/shared/entity-selector/EntitySelector.tsx +59 -0
  18. package/dist/dashboard/components/shared/entity-selector/index.ts +1 -0
  19. package/dist/dashboard/components/shared/error-boundary/ErrorBoundary.tsx +90 -0
  20. package/dist/dashboard/components/shared/error-boundary/index.ts +1 -0
  21. package/dist/dashboard/components/shared/feedback/EmptyState.tsx +36 -0
  22. package/dist/dashboard/components/shared/feedback/ErrorState.tsx +69 -0
  23. package/dist/dashboard/components/shared/feedback/LoadingState.tsx +104 -0
  24. package/dist/dashboard/components/shared/feedback/ValidationErrorDisplay.tsx +29 -0
  25. package/dist/dashboard/components/shared/feedback/index.ts +4 -0
  26. package/dist/dashboard/components/shared/file-dropzone/FileDropzone.tsx +167 -0
  27. package/dist/dashboard/components/shared/file-dropzone/index.ts +1 -0
  28. package/dist/dashboard/components/shared/filter-conditions-editor/FilterConditionsEditor.tsx +226 -0
  29. package/dist/dashboard/components/shared/filter-conditions-editor/index.ts +1 -0
  30. package/dist/dashboard/components/shared/index.ts +45 -0
  31. package/dist/dashboard/components/shared/schema-form/SchemaFormRenderer.tsx +248 -0
  32. package/dist/dashboard/components/shared/schema-form/fields/BooleanField.tsx +26 -0
  33. package/dist/dashboard/components/shared/schema-form/fields/FieldWrapper.tsx +28 -0
  34. package/dist/dashboard/components/shared/schema-form/fields/FileUploadField.tsx +171 -0
  35. package/dist/dashboard/components/shared/schema-form/fields/JsonField.tsx +132 -0
  36. package/dist/dashboard/components/shared/schema-form/fields/NumberField.tsx +33 -0
  37. package/dist/dashboard/components/shared/schema-form/fields/SelectField.tsx +70 -0
  38. package/dist/dashboard/components/shared/schema-form/fields/StringField.tsx +36 -0
  39. package/dist/dashboard/components/shared/schema-form/fields/TextareaField.tsx +31 -0
  40. package/dist/dashboard/components/shared/schema-form/fields/index.ts +23 -0
  41. package/dist/dashboard/components/shared/schema-form/index.ts +2 -0
  42. package/dist/dashboard/components/shared/schema-form/utils.ts +3 -0
  43. package/dist/dashboard/components/shared/selectable-card/SelectableCard.tsx +65 -0
  44. package/dist/dashboard/components/shared/selectable-card/index.ts +1 -0
  45. package/dist/dashboard/components/shared/stat-card/StatCard.tsx +121 -0
  46. package/dist/dashboard/components/shared/stat-card/index.ts +1 -0
  47. package/dist/dashboard/components/shared/step-config/AdapterRequiredWarning.tsx +25 -0
  48. package/dist/dashboard/components/shared/step-config/AdapterSelector.tsx +109 -0
  49. package/dist/dashboard/components/shared/step-config/AdvancedEditors.tsx +634 -0
  50. package/dist/dashboard/components/shared/step-config/EnrichConfigComponent.tsx +295 -0
  51. package/dist/dashboard/components/shared/step-config/ExtractTestResults.tsx +143 -0
  52. package/dist/dashboard/components/shared/step-config/GateConfigComponent.tsx +127 -0
  53. package/dist/dashboard/components/shared/step-config/LoadTestResults.tsx +104 -0
  54. package/dist/dashboard/components/shared/step-config/OperatorCard.tsx +266 -0
  55. package/dist/dashboard/components/shared/step-config/OperatorCheatSheetButton.tsx +54 -0
  56. package/dist/dashboard/components/shared/step-config/OperatorFieldInput.tsx +209 -0
  57. package/dist/dashboard/components/shared/step-config/RetrySettingsComponent.tsx +111 -0
  58. package/dist/dashboard/components/shared/step-config/RouteConfigComponent.tsx +125 -0
  59. package/dist/dashboard/components/shared/step-config/StepConfigPanel.tsx +564 -0
  60. package/dist/dashboard/components/shared/step-config/StepTester.tsx +165 -0
  61. package/dist/dashboard/components/shared/step-config/TestResultContainer.tsx +57 -0
  62. package/dist/dashboard/components/shared/step-config/TransformTestResults.tsx +130 -0
  63. package/dist/dashboard/components/shared/step-config/ValidateConfigComponent.tsx +334 -0
  64. package/dist/dashboard/components/shared/step-config/index.ts +29 -0
  65. package/dist/dashboard/components/shared/step-config/step-test-handlers.ts +297 -0
  66. package/dist/dashboard/components/shared/trigger-config/TriggerForm.tsx +478 -0
  67. package/dist/dashboard/components/shared/trigger-config/index.ts +1 -0
  68. package/dist/dashboard/components/shared/triggers-panel/TriggersPanel.tsx +281 -0
  69. package/dist/dashboard/components/shared/triggers-panel/index.ts +1 -0
  70. package/dist/dashboard/components/shared/wizard/ConfigurationNameCard.tsx +59 -0
  71. package/dist/dashboard/components/shared/wizard/SummaryCard.tsx +53 -0
  72. package/dist/dashboard/components/shared/wizard/WizardFooter.tsx +47 -0
  73. package/dist/dashboard/components/shared/wizard/WizardProgressBar.tsx +78 -0
  74. package/dist/dashboard/components/shared/wizard/index.ts +4 -0
  75. package/dist/dashboard/components/shared/wizard-trigger/TriggerSchemaFields.tsx +128 -0
  76. package/dist/dashboard/components/shared/wizard-trigger/TriggerSelector.tsx +33 -0
  77. package/dist/dashboard/components/shared/wizard-trigger/index.ts +2 -0
  78. package/dist/dashboard/components/templates/TemplateGallery.tsx +210 -0
  79. package/dist/dashboard/components/templates/TemplatePreview.tsx +214 -0
  80. package/dist/dashboard/components/templates/index.ts +4 -0
  81. package/dist/dashboard/components/wizards/export-wizard/DestinationStep.tsx +207 -0
  82. package/dist/dashboard/components/wizards/export-wizard/ExportWizard.tsx +221 -0
  83. package/dist/dashboard/components/wizards/export-wizard/FieldsStep.tsx +159 -0
  84. package/dist/dashboard/components/wizards/export-wizard/FormatStep.tsx +246 -0
  85. package/dist/dashboard/components/wizards/export-wizard/ReviewStep.tsx +231 -0
  86. package/dist/dashboard/components/wizards/export-wizard/SourceStep.tsx +154 -0
  87. package/dist/dashboard/components/wizards/export-wizard/TriggerStep.tsx +234 -0
  88. package/dist/dashboard/components/wizards/export-wizard/constants.ts +73 -0
  89. package/dist/dashboard/components/wizards/export-wizard/index.ts +2 -0
  90. package/dist/dashboard/components/wizards/export-wizard/types.ts +39 -0
  91. package/dist/dashboard/components/wizards/import-wizard/ImportWizard.tsx +350 -0
  92. package/dist/dashboard/components/wizards/import-wizard/MappingStep.tsx +286 -0
  93. package/dist/dashboard/components/wizards/import-wizard/PreviewStep.tsx +79 -0
  94. package/dist/dashboard/components/wizards/import-wizard/ReviewStep.tsx +266 -0
  95. package/dist/dashboard/components/wizards/import-wizard/SourceStep.tsx +537 -0
  96. package/dist/dashboard/components/wizards/import-wizard/StrategyStep.tsx +328 -0
  97. package/dist/dashboard/components/wizards/import-wizard/TargetStep.tsx +76 -0
  98. package/dist/dashboard/components/wizards/import-wizard/TemplateStep.tsx +116 -0
  99. package/dist/dashboard/components/wizards/import-wizard/TransformStep.tsx +666 -0
  100. package/dist/dashboard/components/wizards/import-wizard/TriggerStep.tsx +51 -0
  101. package/dist/dashboard/components/wizards/import-wizard/constants.ts +104 -0
  102. package/dist/dashboard/components/wizards/import-wizard/index.ts +3 -0
  103. package/dist/dashboard/components/wizards/import-wizard/types.ts +35 -0
  104. package/dist/dashboard/components/wizards/index.ts +7 -0
  105. package/dist/dashboard/components/wizards/shared/WizardStepContainer.tsx +27 -0
  106. package/dist/dashboard/components/wizards/shared/constants.ts +16 -0
  107. package/dist/dashboard/components/wizards/shared/index.ts +10 -0
  108. package/dist/dashboard/constants/colors.ts +25 -0
  109. package/dist/dashboard/constants/connection-defaults.ts +7 -0
  110. package/dist/dashboard/constants/connection-types.ts +1 -0
  111. package/dist/dashboard/constants/defaults.ts +18 -0
  112. package/dist/dashboard/constants/editor.ts +69 -0
  113. package/dist/dashboard/constants/enum-maps.ts +18 -0
  114. package/dist/dashboard/constants/fallbacks.ts +44 -0
  115. package/dist/dashboard/constants/file-format-registry.ts +206 -0
  116. package/dist/dashboard/constants/index.ts +24 -0
  117. package/dist/dashboard/constants/navigation.ts +29 -0
  118. package/dist/dashboard/constants/permissions.ts +41 -0
  119. package/dist/dashboard/constants/placeholders.ts +77 -0
  120. package/dist/dashboard/constants/routes.ts +12 -0
  121. package/dist/dashboard/constants/run-status.ts +1 -0
  122. package/dist/dashboard/constants/sentinel-values.ts +12 -0
  123. package/dist/dashboard/constants/step-configs.ts +9 -0
  124. package/dist/dashboard/constants/step-mappings.ts +170 -0
  125. package/dist/dashboard/constants/steps.ts +37 -0
  126. package/dist/dashboard/constants/toast-messages.ts +149 -0
  127. package/dist/dashboard/constants/triggers.ts +5 -0
  128. package/dist/dashboard/constants/ui-config.ts +139 -0
  129. package/dist/dashboard/constants/ui-dimensions.ts +145 -0
  130. package/dist/dashboard/constants/ui-states.ts +28 -0
  131. package/dist/dashboard/constants/ui-types.ts +85 -0
  132. package/dist/dashboard/constants/validation-patterns.ts +26 -0
  133. package/dist/dashboard/gql/gql.ts +370 -0
  134. package/dist/dashboard/gql/graphql.ts +10378 -0
  135. package/dist/dashboard/gql/index.ts +1 -0
  136. package/dist/dashboard/hooks/api/index.ts +115 -0
  137. package/dist/dashboard/hooks/api/mutation-helpers.ts +34 -0
  138. package/dist/dashboard/hooks/api/use-adapters.ts +92 -0
  139. package/dist/dashboard/hooks/api/use-config-options.ts +513 -0
  140. package/dist/dashboard/hooks/api/use-connections.ts +84 -0
  141. package/dist/dashboard/hooks/api/use-entity-field-schemas.ts +99 -0
  142. package/dist/dashboard/hooks/api/use-entity-loaders.ts +45 -0
  143. package/dist/dashboard/hooks/api/use-hooks.ts +68 -0
  144. package/dist/dashboard/hooks/api/use-logs.ts +102 -0
  145. package/dist/dashboard/hooks/api/use-pipeline-runs.ts +221 -0
  146. package/dist/dashboard/hooks/api/use-pipelines.ts +279 -0
  147. package/dist/dashboard/hooks/api/use-queues.ts +141 -0
  148. package/dist/dashboard/hooks/api/use-secrets.ts +75 -0
  149. package/dist/dashboard/hooks/api/use-settings.ts +55 -0
  150. package/dist/dashboard/hooks/api/use-step-tester.ts +79 -0
  151. package/dist/dashboard/hooks/index.ts +13 -0
  152. package/dist/dashboard/hooks/use-adapter-catalog.ts +253 -0
  153. package/dist/dashboard/hooks/use-export-templates.ts +80 -0
  154. package/dist/dashboard/hooks/use-import-templates.ts +139 -0
  155. package/dist/dashboard/hooks/use-load-more.ts +29 -0
  156. package/dist/dashboard/hooks/use-stable-keys.ts +54 -0
  157. package/dist/dashboard/hooks/use-trigger-types.ts +100 -0
  158. package/dist/dashboard/hooks/use-wizard-navigation.ts +128 -0
  159. package/dist/dashboard/index.tsx +55 -0
  160. package/dist/dashboard/routes/adapters/AdapterCard.tsx +102 -0
  161. package/dist/dashboard/routes/adapters/AdapterConstants.tsx +20 -0
  162. package/dist/dashboard/routes/adapters/AdapterDetail.tsx +208 -0
  163. package/dist/dashboard/routes/adapters/AdapterTypeSection.tsx +105 -0
  164. package/dist/dashboard/routes/adapters/AdaptersPage.tsx +276 -0
  165. package/dist/dashboard/routes/adapters/AdaptersTable.tsx +107 -0
  166. package/dist/dashboard/routes/adapters/index.ts +1 -0
  167. package/dist/dashboard/routes/connections/ConnectionDetail.tsx +218 -0
  168. package/dist/dashboard/routes/connections/ConnectionsList.tsx +34 -0
  169. package/dist/dashboard/routes/connections/index.ts +2 -0
  170. package/dist/dashboard/routes/hooks/Hooks.tsx +425 -0
  171. package/dist/dashboard/routes/hooks/hook-stages.ts +52 -0
  172. package/dist/dashboard/routes/hooks/index.ts +1 -0
  173. package/dist/dashboard/routes/index.ts +8 -0
  174. package/dist/dashboard/routes/logs/Logs.tsx +93 -0
  175. package/dist/dashboard/routes/logs/components/LogDetailDrawer.tsx +118 -0
  176. package/dist/dashboard/routes/logs/components/LogExplorerTab.tsx +367 -0
  177. package/dist/dashboard/routes/logs/components/LogLevelBadge.tsx +34 -0
  178. package/dist/dashboard/routes/logs/components/LogTableRow.tsx +70 -0
  179. package/dist/dashboard/routes/logs/components/LogsOverviewTab.tsx +178 -0
  180. package/dist/dashboard/routes/logs/components/RealtimeLogTab.tsx +122 -0
  181. package/dist/dashboard/routes/logs/index.ts +1 -0
  182. package/dist/dashboard/routes/pipelines/ErrorAuditList.tsx +39 -0
  183. package/dist/dashboard/routes/pipelines/ExportWizardPage.tsx +96 -0
  184. package/dist/dashboard/routes/pipelines/ImportWizardPage.tsx +104 -0
  185. package/dist/dashboard/routes/pipelines/PipelineDetail.tsx +211 -0
  186. package/dist/dashboard/routes/pipelines/PipelineRunsBlock.tsx +377 -0
  187. package/dist/dashboard/routes/pipelines/PipelinesList.tsx +87 -0
  188. package/dist/dashboard/routes/pipelines/RetryPatchHelper.tsx +51 -0
  189. package/dist/dashboard/routes/pipelines/RunDetailsPanel.tsx +238 -0
  190. package/dist/dashboard/routes/pipelines/RunErrorsList.tsx +116 -0
  191. package/dist/dashboard/routes/pipelines/StepCounters.tsx +24 -0
  192. package/dist/dashboard/routes/pipelines/StepSummaryTable.tsx +36 -0
  193. package/dist/dashboard/routes/pipelines/components/DryRunDialog.tsx +341 -0
  194. package/dist/dashboard/routes/pipelines/components/PipelineActionButtons.tsx +201 -0
  195. package/dist/dashboard/routes/pipelines/components/PipelineEditorToggle.tsx +116 -0
  196. package/dist/dashboard/routes/pipelines/components/PipelineFormFields.tsx +156 -0
  197. package/dist/dashboard/routes/pipelines/components/PipelineWebhookInfo.tsx +111 -0
  198. package/dist/dashboard/routes/pipelines/components/ReviewActionsPanel.tsx +342 -0
  199. package/dist/dashboard/routes/pipelines/components/ValidationPanel.tsx +121 -0
  200. package/dist/dashboard/routes/pipelines/components/VersionHistoryDialog.tsx +131 -0
  201. package/dist/dashboard/routes/pipelines/components/index.ts +25 -0
  202. package/dist/dashboard/routes/pipelines/hooks/index.ts +1 -0
  203. package/dist/dashboard/routes/pipelines/hooks/use-pipeline-validation.ts +114 -0
  204. package/dist/dashboard/routes/pipelines/index.ts +4 -0
  205. package/dist/dashboard/routes/pipelines/utils/index.ts +1 -0
  206. package/dist/dashboard/routes/pipelines/utils/pipeline-conversion.ts +261 -0
  207. package/dist/dashboard/routes/queues/ConsumersTable.tsx +134 -0
  208. package/dist/dashboard/routes/queues/DeadLettersTable.tsx +118 -0
  209. package/dist/dashboard/routes/queues/FailedRunsTable.tsx +74 -0
  210. package/dist/dashboard/routes/queues/QueuesPage.tsx +290 -0
  211. package/dist/dashboard/routes/queues/index.ts +1 -0
  212. package/dist/dashboard/routes/queues/types.ts +22 -0
  213. package/dist/dashboard/routes/secrets/SecretDetail.tsx +278 -0
  214. package/dist/dashboard/routes/secrets/SecretsList.tsx +34 -0
  215. package/dist/dashboard/routes/secrets/index.ts +2 -0
  216. package/dist/dashboard/routes/settings/Settings.tsx +343 -0
  217. package/dist/dashboard/routes/settings/index.ts +1 -0
  218. package/dist/dashboard/types/index.ts +89 -0
  219. package/dist/dashboard/types/pipeline.ts +51 -0
  220. package/dist/dashboard/types/ui-types.ts +400 -0
  221. package/dist/dashboard/types/wizard.ts +235 -0
  222. package/dist/dashboard/utils/adapter-grouping.ts +43 -0
  223. package/dist/dashboard/utils/column-analysis.ts +11 -0
  224. package/dist/dashboard/utils/field-preparation.ts +31 -0
  225. package/dist/dashboard/utils/form-validation.ts +373 -0
  226. package/dist/dashboard/utils/formatters.ts +92 -0
  227. package/dist/dashboard/utils/icon-resolver.ts +35 -0
  228. package/dist/dashboard/utils/index.ts +60 -0
  229. package/dist/dashboard/utils/query-key-factory.ts +54 -0
  230. package/dist/dashboard/utils/step-helpers.ts +32 -0
  231. package/dist/dashboard/utils/string-helpers.ts +4 -0
  232. package/dist/dashboard/utils/template-helpers.ts +26 -0
  233. package/dist/dashboard/utils/trigger-sync.ts +138 -0
  234. package/dist/dashboard/utils/wizard-to-pipeline.ts +569 -0
  235. package/package.json +4 -4
@@ -0,0 +1,155 @@
1
+ import * as React from 'react';
2
+ import { Handle, Position, NodeProps, Node } from '@xyflow/react';
3
+ import { Badge } from '@vendure/dashboard';
4
+ import type { PipelineNodeData, VisualNodeCategory } from '../../../types';
5
+ import { getVisualNodeConfig, VisualNodeConfig } from './visual-node-config';
6
+ import { FALLBACK_COLORS, BRANCH_COLORS, NODE_DIMENSIONS, ICON_SIZES, TEST_STATUS } from '../../../constants';
7
+
8
+ export function createPipelineNode(category: VisualNodeCategory) {
9
+ return function PipelineNodeComponent({ data, selected }: NodeProps<Node<PipelineNodeData>>) {
10
+ const config = getVisualNodeConfig(category);
11
+ const Icon = config.icon;
12
+
13
+ return (
14
+ <div
15
+ className={`${NODE_DIMENSIONS.MIN_WIDTH} rounded-lg border-2 bg-background shadow-md transition-all ${
16
+ selected ? 'shadow-lg' : ''
17
+ }`}
18
+ style={{ borderColor: selected ? config.color : FALLBACK_COLORS.BORDER }}
19
+ data-testid={`datahub-pipeline-node-${category}`}
20
+ >
21
+ {config.hasTargetHandle && (
22
+ <Handle
23
+ type="target"
24
+ position={Position.Left}
25
+ style={{ backgroundColor: config.color }}
26
+ className={NODE_DIMENSIONS.HANDLE_SIZE}
27
+ />
28
+ )}
29
+ <div
30
+ className="px-3 py-2 rounded-t-lg text-white flex items-center gap-2"
31
+ style={{ backgroundColor: config.color }}
32
+ >
33
+ <Icon className={ICON_SIZES.SM} />
34
+ <span className="font-medium text-sm truncate">{data.label}</span>
35
+ </div>
36
+ <div className="px-3 py-2 text-xs text-muted-foreground">{config.description}</div>
37
+ {data.status && <StatusBadge status={data.status} />}
38
+ {config.hasSourceHandle && (
39
+ <Handle
40
+ type="source"
41
+ position={Position.Right}
42
+ style={{ backgroundColor: config.color }}
43
+ className={NODE_DIMENSIONS.HANDLE_SIZE}
44
+ />
45
+ )}
46
+ </div>
47
+ );
48
+ };
49
+ }
50
+
51
+ function ConditionNodeComponent({ data, selected }: NodeProps<Node<PipelineNodeData>>) {
52
+ const config = getVisualNodeConfig('condition');
53
+ const Icon = config.icon;
54
+
55
+ return (
56
+ <div
57
+ className={`${NODE_DIMENSIONS.MIN_WIDTH} rounded-lg border-2 bg-background shadow-md transition-all ${
58
+ selected ? 'shadow-lg' : ''
59
+ }`}
60
+ style={{ borderColor: selected ? config.color : FALLBACK_COLORS.BORDER }}
61
+ data-testid="datahub-pipeline-node-condition"
62
+ >
63
+ <Handle
64
+ type="target"
65
+ position={Position.Left}
66
+ style={{ backgroundColor: config.color }}
67
+ className={NODE_DIMENSIONS.HANDLE_SIZE}
68
+ />
69
+ <div
70
+ className="px-3 py-2 rounded-t-lg text-white flex items-center gap-2"
71
+ style={{ backgroundColor: config.color }}
72
+ >
73
+ <Icon className={ICON_SIZES.SM} />
74
+ <span className="font-medium text-sm truncate">{data.label}</span>
75
+ </div>
76
+ <div className="px-3 py-2 text-xs text-muted-foreground">{config.description}</div>
77
+ <Handle
78
+ type="source"
79
+ position={Position.Right}
80
+ id="true"
81
+ className={NODE_DIMENSIONS.HANDLE_SIZE}
82
+ style={{ top: '40%', backgroundColor: BRANCH_COLORS.TRUE }}
83
+ />
84
+ <Handle
85
+ type="source"
86
+ position={Position.Right}
87
+ id="false"
88
+ className={NODE_DIMENSIONS.HANDLE_SIZE}
89
+ style={{ top: '60%', backgroundColor: BRANCH_COLORS.FALSE }}
90
+ />
91
+ </div>
92
+ );
93
+ }
94
+
95
+ function StatusBadge({ status }: { status: PipelineNodeData['status'] }) {
96
+ if (!status) return null;
97
+
98
+ switch (status) {
99
+ case TEST_STATUS.TESTING:
100
+ return (
101
+ <div className="px-3 pb-2" role="status" aria-live="polite">
102
+ <Badge variant="secondary" className="animate-pulse">Running...</Badge>
103
+ </div>
104
+ );
105
+ case TEST_STATUS.SUCCESS:
106
+ return (
107
+ <div className="px-3 pb-2" role="status" aria-live="polite">
108
+ <Badge className="bg-green-500">Complete</Badge>
109
+ </div>
110
+ );
111
+ case TEST_STATUS.ERROR:
112
+ return (
113
+ <div className="px-3 pb-2" role="status" aria-live="assertive">
114
+ <Badge variant="destructive">Error</Badge>
115
+ </div>
116
+ );
117
+ case TEST_STATUS.WARNING:
118
+ return (
119
+ <div className="px-3 pb-2" role="status" aria-live="polite">
120
+ <Badge variant="outline" className="border-amber-500 text-amber-500">Warning</Badge>
121
+ </div>
122
+ );
123
+ default:
124
+ return null;
125
+ }
126
+ }
127
+
128
+ export const TriggerNode = createPipelineNode('trigger');
129
+ export const SourceNode = createPipelineNode('source');
130
+ export const TransformNode = createPipelineNode('transform');
131
+ export const ValidateNode = createPipelineNode('validate');
132
+ export const EnrichNode = createPipelineNode('enrich');
133
+ export const LoadNode = createPipelineNode('load');
134
+ export const FeedNode = createPipelineNode('feed');
135
+ export const ExportNode = createPipelineNode('export');
136
+ export const SinkNode = createPipelineNode('sink');
137
+ export const FilterNode = createPipelineNode('filter');
138
+ export const GateNode = createPipelineNode('gate');
139
+
140
+ export const ConditionNode = ConditionNodeComponent;
141
+
142
+ export const pipelineNodeTypes = {
143
+ trigger: TriggerNode,
144
+ source: SourceNode,
145
+ transform: TransformNode,
146
+ validate: ValidateNode,
147
+ condition: ConditionNode,
148
+ filter: FilterNode,
149
+ load: LoadNode,
150
+ feed: FeedNode,
151
+ export: ExportNode,
152
+ sink: SinkNode,
153
+ enrich: EnrichNode,
154
+ gate: GateNode,
155
+ };
@@ -0,0 +1,392 @@
1
+ import * as React from 'react';
2
+ import { useCallback } from 'react';
3
+ import {
4
+ Input,
5
+ Select,
6
+ SelectContent,
7
+ SelectItem,
8
+ SelectTrigger,
9
+ SelectValue,
10
+ Card,
11
+ CardContent,
12
+ CardHeader,
13
+ CardTitle,
14
+ Switch,
15
+ Label,
16
+ } from '@vendure/dashboard';
17
+ import { Clock, AlertTriangle, Zap, GitBranch } from 'lucide-react';
18
+ import {
19
+ PIPELINE_RETRY_DEFAULTS,
20
+ PIPELINE_CHECKPOINT_DEFAULTS,
21
+ CHECKPOINT_STRATEGY,
22
+ } from '../../../constants';
23
+ import { useOptionValues } from '../../../hooks';
24
+ import type {
25
+ PipelineContext,
26
+ ErrorHandlingConfig,
27
+ CheckpointingConfig,
28
+ Throughput,
29
+ RunModeValue,
30
+ CheckpointStrategy,
31
+ ParallelExecutionConfig,
32
+ } from '../../../types';
33
+
34
+ export interface PipelineSettingsPanelProps {
35
+ readonly context: PipelineContext;
36
+ readonly onChange: (context: PipelineContext) => void;
37
+ readonly compact?: boolean;
38
+ }
39
+
40
+ export function PipelineSettingsPanel({ context, onChange, compact = false }: PipelineSettingsPanelProps) {
41
+ const { options: runModeOptions } = useOptionValues('runModes');
42
+ const { options: checkpointStrategyOptions } = useOptionValues('checkpointStrategies');
43
+ const { options: errorPolicyOptions } = useOptionValues('parallelErrorPolicies');
44
+
45
+ const updateErrorHandling = useCallback((errorHandling: ErrorHandlingConfig) => {
46
+ onChange({ ...context, errorHandling });
47
+ }, [context, onChange]);
48
+
49
+ const updateCheckpointing = useCallback((checkpointing: CheckpointingConfig) => {
50
+ onChange({ ...context, checkpointing });
51
+ }, [context, onChange]);
52
+
53
+ const updateThroughput = useCallback((throughput: Throughput) => {
54
+ onChange({ ...context, throughput });
55
+ }, [context, onChange]);
56
+
57
+ const updateParallelExecution = useCallback((parallelExecution: ParallelExecutionConfig) => {
58
+ onChange({ ...context, parallelExecution });
59
+ }, [context, onChange]);
60
+
61
+ const labelSize = compact ? 'text-[10px]' : 'text-xs';
62
+ const inputHeight = compact ? 'h-7' : 'h-8';
63
+ const spacing = compact ? 'space-y-3' : 'space-y-4';
64
+ const cardHeaderPadding = compact ? 'py-2 px-3' : 'py-3 px-4';
65
+ const cardContentPadding = compact ? 'px-3 pb-3' : 'px-4 pb-4';
66
+
67
+ return (
68
+ <div className="flex flex-col h-full overflow-auto">
69
+ <div className="p-3 border-b bg-muted/50">
70
+ <h3 className="font-semibold text-sm">Pipeline Settings</h3>
71
+ <p className="text-xs text-muted-foreground">Execution configuration</p>
72
+ </div>
73
+
74
+ <div className={`p-3 ${spacing}`}>
75
+ <div className="space-y-2">
76
+ <Label className={labelSize}>Run Mode</Label>
77
+ <Select
78
+ value={context.runMode ?? 'BATCH'}
79
+ onValueChange={(v) => onChange({ ...context, runMode: v as RunModeValue })}
80
+ >
81
+ <SelectTrigger className={`${labelSize} ${inputHeight}`}>
82
+ <SelectValue />
83
+ </SelectTrigger>
84
+ <SelectContent>
85
+ {runModeOptions.map(mode => (
86
+ <SelectItem key={mode.value} value={mode.value}>{mode.label}</SelectItem>
87
+ ))}
88
+ </SelectContent>
89
+ </Select>
90
+ </div>
91
+
92
+ <Card>
93
+ <CardHeader className={cardHeaderPadding}>
94
+ <CardTitle className="text-xs flex items-center gap-2">
95
+ <AlertTriangle className="h-3 w-3 text-amber-500" />
96
+ Error Handling
97
+ </CardTitle>
98
+ </CardHeader>
99
+ <CardContent className={`${cardContentPadding} space-y-3`}>
100
+ <div className="grid grid-cols-2 gap-2">
101
+ <div className="space-y-1">
102
+ <Label className={labelSize}>Max Retries</Label>
103
+ <Input
104
+ type="number"
105
+ min={0}
106
+ max={10}
107
+ value={context.errorHandling?.maxRetries ?? 3}
108
+ onChange={(e) => updateErrorHandling({
109
+ ...context.errorHandling,
110
+ maxRetries: parseInt(e.target.value) || 0,
111
+ })}
112
+ className={`${inputHeight} text-xs`}
113
+ />
114
+ </div>
115
+ <div className="space-y-1">
116
+ <Label className={labelSize}>Retry Delay (ms)</Label>
117
+ <Input
118
+ type="number"
119
+ min={100}
120
+ value={context.errorHandling?.retryDelayMs ?? PIPELINE_RETRY_DEFAULTS.DELAY_MS}
121
+ onChange={(e) => updateErrorHandling({
122
+ ...context.errorHandling,
123
+ retryDelayMs: parseInt(e.target.value) || PIPELINE_RETRY_DEFAULTS.DELAY_MS,
124
+ })}
125
+ className={`${inputHeight} text-xs`}
126
+ />
127
+ </div>
128
+ </div>
129
+ <div className="grid grid-cols-2 gap-2">
130
+ <div className="space-y-1">
131
+ <Label className={labelSize}>Max Delay (ms)</Label>
132
+ <Input
133
+ type="number"
134
+ min={PIPELINE_RETRY_DEFAULTS.MIN_DELAY_MS}
135
+ value={context.errorHandling?.maxRetryDelayMs ?? PIPELINE_RETRY_DEFAULTS.MAX_DELAY_MS}
136
+ onChange={(e) => updateErrorHandling({
137
+ ...context.errorHandling,
138
+ maxRetryDelayMs: parseInt(e.target.value) || PIPELINE_RETRY_DEFAULTS.MAX_DELAY_MS,
139
+ })}
140
+ className={`${inputHeight} text-xs`}
141
+ />
142
+ </div>
143
+ <div className="space-y-1">
144
+ <Label className={labelSize}>Backoff Multiplier</Label>
145
+ <Input
146
+ type="number"
147
+ min={1}
148
+ max={5}
149
+ step={0.5}
150
+ value={context.errorHandling?.backoffMultiplier ?? 2}
151
+ onChange={(e) => updateErrorHandling({
152
+ ...context.errorHandling,
153
+ backoffMultiplier: parseFloat(e.target.value) || 2,
154
+ })}
155
+ className={`${inputHeight} text-xs`}
156
+ />
157
+ </div>
158
+ </div>
159
+ <div className="flex items-center justify-between">
160
+ <Label className={labelSize}>Dead Letter Queue</Label>
161
+ <Switch
162
+ checked={context.errorHandling?.deadLetterQueue ?? false}
163
+ onCheckedChange={(v) => updateErrorHandling({
164
+ ...context.errorHandling,
165
+ deadLetterQueue: v,
166
+ })}
167
+ />
168
+ </div>
169
+ {context.errorHandling?.deadLetterQueue && (
170
+ <div className="flex items-center justify-between">
171
+ <Label className={labelSize}>Alert on Dead Letter</Label>
172
+ <Switch
173
+ checked={context.errorHandling?.alertOnDeadLetter ?? false}
174
+ onCheckedChange={(v) => updateErrorHandling({
175
+ ...context.errorHandling,
176
+ alertOnDeadLetter: v,
177
+ })}
178
+ />
179
+ </div>
180
+ )}
181
+ </CardContent>
182
+ </Card>
183
+
184
+ <Card>
185
+ <CardHeader className={cardHeaderPadding}>
186
+ <CardTitle className="text-xs flex items-center gap-2">
187
+ <Clock className="h-3 w-3 text-blue-500" />
188
+ Checkpointing
189
+ </CardTitle>
190
+ </CardHeader>
191
+ <CardContent className={`${cardContentPadding} space-y-3`}>
192
+ <div className="flex items-center justify-between">
193
+ <Label className={labelSize}>Enable Checkpointing</Label>
194
+ <Switch
195
+ checked={context.checkpointing?.enabled ?? false}
196
+ onCheckedChange={(v) => updateCheckpointing({
197
+ ...context.checkpointing,
198
+ enabled: v,
199
+ })}
200
+ />
201
+ </div>
202
+ {context.checkpointing?.enabled && (
203
+ <>
204
+ <div className="space-y-1">
205
+ <Label className={labelSize}>Strategy</Label>
206
+ <Select
207
+ value={context.checkpointing?.strategy ?? CHECKPOINT_STRATEGY.COUNT}
208
+ onValueChange={(v) => updateCheckpointing({
209
+ ...context.checkpointing,
210
+ strategy: v as CheckpointStrategy,
211
+ })}
212
+ >
213
+ <SelectTrigger className={`${inputHeight} text-xs`}>
214
+ <SelectValue />
215
+ </SelectTrigger>
216
+ <SelectContent>
217
+ {checkpointStrategyOptions.map(opt => (
218
+ <SelectItem key={opt.value} value={opt.value}>{opt.label}</SelectItem>
219
+ ))}
220
+ </SelectContent>
221
+ </Select>
222
+ </div>
223
+ {context.checkpointing?.strategy === CHECKPOINT_STRATEGY.COUNT && (
224
+ <div className="space-y-1">
225
+ <Label className={labelSize}>Checkpoint Every N Records</Label>
226
+ <Input
227
+ type="number"
228
+ min={100}
229
+ value={context.checkpointing?.intervalRecords ?? PIPELINE_CHECKPOINT_DEFAULTS.INTERVAL_RECORDS}
230
+ onChange={(e) => updateCheckpointing({
231
+ ...context.checkpointing,
232
+ intervalRecords: parseInt(e.target.value) || PIPELINE_CHECKPOINT_DEFAULTS.INTERVAL_RECORDS,
233
+ })}
234
+ className={`${inputHeight} text-xs`}
235
+ />
236
+ </div>
237
+ )}
238
+ {context.checkpointing?.strategy === CHECKPOINT_STRATEGY.INTERVAL && (
239
+ <div className="space-y-1">
240
+ <Label className={labelSize}>Checkpoint Interval (ms)</Label>
241
+ <Input
242
+ type="number"
243
+ min={PIPELINE_CHECKPOINT_DEFAULTS.MIN_INTERVAL_MS}
244
+ value={context.checkpointing?.intervalMs ?? PIPELINE_CHECKPOINT_DEFAULTS.INTERVAL_MS}
245
+ onChange={(e) => updateCheckpointing({
246
+ ...context.checkpointing,
247
+ intervalMs: parseInt(e.target.value) || PIPELINE_CHECKPOINT_DEFAULTS.INTERVAL_MS,
248
+ })}
249
+ className={`${inputHeight} text-xs`}
250
+ />
251
+ </div>
252
+ )}
253
+ {context.checkpointing?.strategy === CHECKPOINT_STRATEGY.TIMESTAMP && (
254
+ <div className="space-y-1">
255
+ <Label className={labelSize}>Timestamp Field</Label>
256
+ <Input
257
+ value={context.checkpointing?.field ?? 'updatedAt'}
258
+ onChange={(e) => updateCheckpointing({
259
+ ...context.checkpointing,
260
+ field: e.target.value,
261
+ })}
262
+ placeholder="updatedAt"
263
+ className={`${inputHeight} text-xs`}
264
+ />
265
+ </div>
266
+ )}
267
+ </>
268
+ )}
269
+ </CardContent>
270
+ </Card>
271
+
272
+ <Card>
273
+ <CardHeader className={cardHeaderPadding}>
274
+ <CardTitle className="text-xs flex items-center gap-2">
275
+ <Zap className="h-3 w-3 text-green-500" />
276
+ Throughput
277
+ </CardTitle>
278
+ </CardHeader>
279
+ <CardContent className={`${cardContentPadding} space-y-3`}>
280
+ <div className="grid grid-cols-2 gap-2">
281
+ <div className="space-y-1">
282
+ <Label className={labelSize}>Batch Size</Label>
283
+ <Input
284
+ type="number"
285
+ min={1}
286
+ value={context.throughput?.batchSize ?? 100}
287
+ onChange={(e) => updateThroughput({
288
+ ...context.throughput,
289
+ batchSize: parseInt(e.target.value) || 100,
290
+ })}
291
+ className={`${inputHeight} text-xs`}
292
+ />
293
+ </div>
294
+ <div className="space-y-1">
295
+ <Label className={labelSize}>Concurrency</Label>
296
+ <Input
297
+ type="number"
298
+ min={1}
299
+ max={32}
300
+ value={context.throughput?.concurrency ?? 4}
301
+ onChange={(e) => updateThroughput({
302
+ ...context.throughput,
303
+ concurrency: parseInt(e.target.value) || 4,
304
+ })}
305
+ className={`${inputHeight} text-xs`}
306
+ />
307
+ </div>
308
+ </div>
309
+ <div className="space-y-1">
310
+ <Label className={labelSize}>Rate Limit (requests/sec)</Label>
311
+ <Input
312
+ type="number"
313
+ min={0}
314
+ value={context.throughput?.rateLimitRps ?? 0}
315
+ onChange={(e) => updateThroughput({
316
+ ...context.throughput,
317
+ rateLimitRps: parseInt(e.target.value) || 0,
318
+ })}
319
+ placeholder="0 = unlimited"
320
+ className={`${inputHeight} text-xs`}
321
+ />
322
+ <p className={`${labelSize} text-muted-foreground`}>0 = no rate limiting</p>
323
+ </div>
324
+ </CardContent>
325
+ </Card>
326
+
327
+ <Card>
328
+ <CardHeader className={cardHeaderPadding}>
329
+ <CardTitle className="text-xs flex items-center gap-2">
330
+ <GitBranch className="h-3 w-3 text-purple-500" />
331
+ Parallel Execution
332
+ </CardTitle>
333
+ </CardHeader>
334
+ <CardContent className={`${cardContentPadding} space-y-3`}>
335
+ <div className="flex items-center justify-between">
336
+ <div className="space-y-0.5">
337
+ <Label className={labelSize}>Enable Parallel Steps</Label>
338
+ <p className={`${labelSize} text-muted-foreground`}>
339
+ Run independent steps concurrently
340
+ </p>
341
+ </div>
342
+ <Switch
343
+ checked={context.parallelExecution?.enabled ?? false}
344
+ onCheckedChange={(v) => updateParallelExecution({
345
+ ...context.parallelExecution,
346
+ enabled: v,
347
+ })}
348
+ />
349
+ </div>
350
+ {context.parallelExecution?.enabled && (
351
+ <>
352
+ <div className="space-y-1">
353
+ <Label className={labelSize}>Max Concurrent Steps</Label>
354
+ <Input
355
+ type="number"
356
+ min={2}
357
+ max={16}
358
+ value={context.parallelExecution?.maxConcurrentSteps ?? 4}
359
+ onChange={(e) => updateParallelExecution({
360
+ ...context.parallelExecution,
361
+ maxConcurrentSteps: parseInt(e.target.value) || 4,
362
+ })}
363
+ className={`${inputHeight} text-xs`}
364
+ />
365
+ </div>
366
+ <div className="space-y-1">
367
+ <Label className={labelSize}>Error Policy</Label>
368
+ <Select
369
+ value={context.parallelExecution?.errorPolicy ?? 'FAIL_FAST'}
370
+ onValueChange={(v) => updateParallelExecution({
371
+ ...context.parallelExecution,
372
+ errorPolicy: v as 'FAIL_FAST' | 'CONTINUE' | 'BEST_EFFORT',
373
+ })}
374
+ >
375
+ <SelectTrigger className={`${inputHeight} text-xs`}>
376
+ <SelectValue />
377
+ </SelectTrigger>
378
+ <SelectContent>
379
+ {errorPolicyOptions.map(policy => (
380
+ <SelectItem key={policy.value} value={policy.value}>{policy.label}</SelectItem>
381
+ ))}
382
+ </SelectContent>
383
+ </Select>
384
+ </div>
385
+ </>
386
+ )}
387
+ </CardContent>
388
+ </Card>
389
+ </div>
390
+ </div>
391
+ );
392
+ }