@oronts/vendure-data-hub-plugin 0.1.1 → 0.1.3

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 (357) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +6 -2
  3. package/dashboard/gql/gql.ts +6 -6
  4. package/dashboard/gql/graphql.ts +9 -4
  5. package/dashboard/hooks/api/use-pipeline-runs.ts +1 -0
  6. package/dashboard/hooks/api/use-queues.ts +1 -0
  7. package/dist/dashboard/components/common/ConnectionConfigEditor.tsx +589 -0
  8. package/dist/dashboard/components/common/HeadersEditor.tsx +90 -0
  9. package/dist/dashboard/components/common/ValidationFeedback.tsx +17 -0
  10. package/dist/dashboard/components/common/index.ts +10 -0
  11. package/dist/dashboard/components/pipelines/PipelineEditor.tsx +504 -0
  12. package/dist/dashboard/components/pipelines/PipelineExport.tsx +63 -0
  13. package/dist/dashboard/components/pipelines/PipelineImport.tsx +87 -0
  14. package/dist/dashboard/components/pipelines/ReactFlowPipelineEditor.tsx +539 -0
  15. package/dist/dashboard/components/pipelines/shared/NodePropertiesPanel.tsx +146 -0
  16. package/dist/dashboard/components/pipelines/shared/PipelineNode.tsx +155 -0
  17. package/dist/dashboard/components/pipelines/shared/PipelineSettingsPanel.tsx +392 -0
  18. package/dist/dashboard/components/pipelines/shared/StepListItem.tsx +144 -0
  19. package/dist/dashboard/components/pipelines/shared/index.ts +33 -0
  20. package/dist/dashboard/components/pipelines/shared/visual-node-config.ts +169 -0
  21. package/dist/dashboard/components/shared/LoadMoreButton.tsx +18 -0
  22. package/dist/dashboard/components/shared/entity-selector/EntitySelector.tsx +59 -0
  23. package/dist/dashboard/components/shared/entity-selector/index.ts +1 -0
  24. package/dist/dashboard/components/shared/error-boundary/ErrorBoundary.tsx +90 -0
  25. package/dist/dashboard/components/shared/error-boundary/index.ts +1 -0
  26. package/dist/dashboard/components/shared/feedback/EmptyState.tsx +36 -0
  27. package/dist/dashboard/components/shared/feedback/ErrorState.tsx +69 -0
  28. package/dist/dashboard/components/shared/feedback/LoadingState.tsx +104 -0
  29. package/dist/dashboard/components/shared/feedback/ValidationErrorDisplay.tsx +29 -0
  30. package/dist/dashboard/components/shared/feedback/index.ts +4 -0
  31. package/dist/dashboard/components/shared/file-dropzone/FileDropzone.tsx +167 -0
  32. package/dist/dashboard/components/shared/file-dropzone/index.ts +1 -0
  33. package/dist/dashboard/components/shared/filter-conditions-editor/FilterConditionsEditor.tsx +226 -0
  34. package/dist/dashboard/components/shared/filter-conditions-editor/index.ts +1 -0
  35. package/dist/dashboard/components/shared/index.ts +45 -0
  36. package/dist/dashboard/components/shared/schema-form/SchemaFormRenderer.tsx +248 -0
  37. package/dist/dashboard/components/shared/schema-form/fields/BooleanField.tsx +26 -0
  38. package/dist/dashboard/components/shared/schema-form/fields/FieldWrapper.tsx +28 -0
  39. package/dist/dashboard/components/shared/schema-form/fields/FileUploadField.tsx +171 -0
  40. package/dist/dashboard/components/shared/schema-form/fields/JsonField.tsx +132 -0
  41. package/dist/dashboard/components/shared/schema-form/fields/NumberField.tsx +33 -0
  42. package/dist/dashboard/components/shared/schema-form/fields/SelectField.tsx +70 -0
  43. package/dist/dashboard/components/shared/schema-form/fields/StringField.tsx +36 -0
  44. package/dist/dashboard/components/shared/schema-form/fields/TextareaField.tsx +31 -0
  45. package/dist/dashboard/components/shared/schema-form/fields/index.ts +23 -0
  46. package/dist/dashboard/components/shared/schema-form/index.ts +2 -0
  47. package/dist/dashboard/components/shared/schema-form/utils.ts +3 -0
  48. package/dist/dashboard/components/shared/selectable-card/SelectableCard.tsx +65 -0
  49. package/dist/dashboard/components/shared/selectable-card/index.ts +1 -0
  50. package/dist/dashboard/components/shared/stat-card/StatCard.tsx +121 -0
  51. package/dist/dashboard/components/shared/stat-card/index.ts +1 -0
  52. package/dist/dashboard/components/shared/step-config/AdapterRequiredWarning.tsx +25 -0
  53. package/dist/dashboard/components/shared/step-config/AdapterSelector.tsx +109 -0
  54. package/dist/dashboard/components/shared/step-config/AdvancedEditors.tsx +634 -0
  55. package/dist/dashboard/components/shared/step-config/EnrichConfigComponent.tsx +295 -0
  56. package/dist/dashboard/components/shared/step-config/ExtractTestResults.tsx +143 -0
  57. package/dist/dashboard/components/shared/step-config/GateConfigComponent.tsx +127 -0
  58. package/dist/dashboard/components/shared/step-config/LoadTestResults.tsx +104 -0
  59. package/dist/dashboard/components/shared/step-config/OperatorCard.tsx +266 -0
  60. package/dist/dashboard/components/shared/step-config/OperatorCheatSheetButton.tsx +54 -0
  61. package/dist/dashboard/components/shared/step-config/OperatorFieldInput.tsx +209 -0
  62. package/dist/dashboard/components/shared/step-config/RetrySettingsComponent.tsx +111 -0
  63. package/dist/dashboard/components/shared/step-config/RouteConfigComponent.tsx +125 -0
  64. package/dist/dashboard/components/shared/step-config/StepConfigPanel.tsx +564 -0
  65. package/dist/dashboard/components/shared/step-config/StepTester.tsx +165 -0
  66. package/dist/dashboard/components/shared/step-config/TestResultContainer.tsx +57 -0
  67. package/dist/dashboard/components/shared/step-config/TransformTestResults.tsx +130 -0
  68. package/dist/dashboard/components/shared/step-config/ValidateConfigComponent.tsx +334 -0
  69. package/dist/dashboard/components/shared/step-config/index.ts +29 -0
  70. package/dist/dashboard/components/shared/step-config/step-test-handlers.ts +297 -0
  71. package/dist/dashboard/components/shared/trigger-config/TriggerForm.tsx +478 -0
  72. package/dist/dashboard/components/shared/trigger-config/index.ts +1 -0
  73. package/dist/dashboard/components/shared/triggers-panel/TriggersPanel.tsx +281 -0
  74. package/dist/dashboard/components/shared/triggers-panel/index.ts +1 -0
  75. package/dist/dashboard/components/shared/wizard/ConfigurationNameCard.tsx +59 -0
  76. package/dist/dashboard/components/shared/wizard/SummaryCard.tsx +53 -0
  77. package/dist/dashboard/components/shared/wizard/WizardFooter.tsx +47 -0
  78. package/dist/dashboard/components/shared/wizard/WizardProgressBar.tsx +78 -0
  79. package/dist/dashboard/components/shared/wizard/index.ts +4 -0
  80. package/dist/dashboard/components/shared/wizard-trigger/TriggerSchemaFields.tsx +128 -0
  81. package/dist/dashboard/components/shared/wizard-trigger/TriggerSelector.tsx +33 -0
  82. package/dist/dashboard/components/shared/wizard-trigger/index.ts +2 -0
  83. package/dist/dashboard/components/templates/TemplateGallery.tsx +210 -0
  84. package/dist/dashboard/components/templates/TemplatePreview.tsx +214 -0
  85. package/dist/dashboard/components/templates/index.ts +4 -0
  86. package/dist/dashboard/components/wizards/export-wizard/DestinationStep.tsx +207 -0
  87. package/dist/dashboard/components/wizards/export-wizard/ExportWizard.tsx +221 -0
  88. package/dist/dashboard/components/wizards/export-wizard/FieldsStep.tsx +159 -0
  89. package/dist/dashboard/components/wizards/export-wizard/FormatStep.tsx +246 -0
  90. package/dist/dashboard/components/wizards/export-wizard/ReviewStep.tsx +231 -0
  91. package/dist/dashboard/components/wizards/export-wizard/SourceStep.tsx +154 -0
  92. package/dist/dashboard/components/wizards/export-wizard/TriggerStep.tsx +234 -0
  93. package/dist/dashboard/components/wizards/export-wizard/constants.ts +73 -0
  94. package/dist/dashboard/components/wizards/export-wizard/index.ts +2 -0
  95. package/dist/dashboard/components/wizards/export-wizard/types.ts +39 -0
  96. package/dist/dashboard/components/wizards/import-wizard/ImportWizard.tsx +350 -0
  97. package/dist/dashboard/components/wizards/import-wizard/MappingStep.tsx +286 -0
  98. package/dist/dashboard/components/wizards/import-wizard/PreviewStep.tsx +79 -0
  99. package/dist/dashboard/components/wizards/import-wizard/ReviewStep.tsx +266 -0
  100. package/dist/dashboard/components/wizards/import-wizard/SourceStep.tsx +537 -0
  101. package/dist/dashboard/components/wizards/import-wizard/StrategyStep.tsx +328 -0
  102. package/dist/dashboard/components/wizards/import-wizard/TargetStep.tsx +76 -0
  103. package/dist/dashboard/components/wizards/import-wizard/TemplateStep.tsx +116 -0
  104. package/dist/dashboard/components/wizards/import-wizard/TransformStep.tsx +666 -0
  105. package/dist/dashboard/components/wizards/import-wizard/TriggerStep.tsx +51 -0
  106. package/dist/dashboard/components/wizards/import-wizard/constants.ts +104 -0
  107. package/dist/dashboard/components/wizards/import-wizard/index.ts +3 -0
  108. package/dist/dashboard/components/wizards/import-wizard/types.ts +35 -0
  109. package/dist/dashboard/components/wizards/index.ts +7 -0
  110. package/dist/dashboard/components/wizards/shared/WizardStepContainer.tsx +27 -0
  111. package/dist/dashboard/components/wizards/shared/constants.ts +16 -0
  112. package/dist/dashboard/components/wizards/shared/index.ts +10 -0
  113. package/dist/dashboard/constants/colors.ts +25 -0
  114. package/dist/dashboard/constants/connection-defaults.ts +7 -0
  115. package/dist/dashboard/constants/connection-types.ts +1 -0
  116. package/dist/dashboard/constants/defaults.ts +18 -0
  117. package/dist/dashboard/constants/editor.ts +69 -0
  118. package/dist/dashboard/constants/enum-maps.ts +18 -0
  119. package/dist/dashboard/constants/fallbacks.ts +44 -0
  120. package/dist/dashboard/constants/file-format-registry.ts +206 -0
  121. package/dist/dashboard/constants/index.ts +24 -0
  122. package/dist/dashboard/constants/navigation.ts +29 -0
  123. package/dist/dashboard/constants/permissions.ts +41 -0
  124. package/dist/dashboard/constants/placeholders.ts +77 -0
  125. package/dist/dashboard/constants/routes.ts +12 -0
  126. package/dist/dashboard/constants/run-status.ts +1 -0
  127. package/dist/dashboard/constants/sentinel-values.ts +12 -0
  128. package/dist/dashboard/constants/step-configs.ts +9 -0
  129. package/dist/dashboard/constants/step-mappings.ts +170 -0
  130. package/dist/dashboard/constants/steps.ts +37 -0
  131. package/dist/dashboard/constants/toast-messages.ts +149 -0
  132. package/dist/dashboard/constants/triggers.ts +5 -0
  133. package/dist/dashboard/constants/ui-config.ts +139 -0
  134. package/dist/dashboard/constants/ui-dimensions.ts +145 -0
  135. package/dist/dashboard/constants/ui-states.ts +28 -0
  136. package/dist/dashboard/constants/ui-types.ts +85 -0
  137. package/dist/dashboard/constants/validation-patterns.ts +26 -0
  138. package/dist/dashboard/gql/gql.ts +370 -0
  139. package/dist/dashboard/gql/graphql.ts +10383 -0
  140. package/dist/dashboard/gql/index.ts +1 -0
  141. package/dist/dashboard/hooks/api/index.ts +115 -0
  142. package/dist/dashboard/hooks/api/mutation-helpers.ts +34 -0
  143. package/dist/dashboard/hooks/api/use-adapters.ts +92 -0
  144. package/dist/dashboard/hooks/api/use-config-options.ts +513 -0
  145. package/dist/dashboard/hooks/api/use-connections.ts +84 -0
  146. package/dist/dashboard/hooks/api/use-entity-field-schemas.ts +99 -0
  147. package/dist/dashboard/hooks/api/use-entity-loaders.ts +45 -0
  148. package/dist/dashboard/hooks/api/use-hooks.ts +68 -0
  149. package/dist/dashboard/hooks/api/use-logs.ts +102 -0
  150. package/dist/dashboard/hooks/api/use-pipeline-runs.ts +222 -0
  151. package/dist/dashboard/hooks/api/use-pipelines.ts +279 -0
  152. package/dist/dashboard/hooks/api/use-queues.ts +142 -0
  153. package/dist/dashboard/hooks/api/use-secrets.ts +75 -0
  154. package/dist/dashboard/hooks/api/use-settings.ts +55 -0
  155. package/dist/dashboard/hooks/api/use-step-tester.ts +79 -0
  156. package/dist/dashboard/hooks/index.ts +13 -0
  157. package/dist/dashboard/hooks/use-adapter-catalog.ts +253 -0
  158. package/dist/dashboard/hooks/use-export-templates.ts +80 -0
  159. package/dist/dashboard/hooks/use-import-templates.ts +139 -0
  160. package/dist/dashboard/hooks/use-load-more.ts +29 -0
  161. package/dist/dashboard/hooks/use-stable-keys.ts +54 -0
  162. package/dist/dashboard/hooks/use-trigger-types.ts +100 -0
  163. package/dist/dashboard/hooks/use-wizard-navigation.ts +128 -0
  164. package/dist/dashboard/index.tsx +55 -0
  165. package/dist/dashboard/routes/adapters/AdapterCard.tsx +102 -0
  166. package/dist/dashboard/routes/adapters/AdapterConstants.tsx +20 -0
  167. package/dist/dashboard/routes/adapters/AdapterDetail.tsx +208 -0
  168. package/dist/dashboard/routes/adapters/AdapterTypeSection.tsx +105 -0
  169. package/dist/dashboard/routes/adapters/AdaptersPage.tsx +276 -0
  170. package/dist/dashboard/routes/adapters/AdaptersTable.tsx +107 -0
  171. package/dist/dashboard/routes/adapters/index.ts +1 -0
  172. package/dist/dashboard/routes/connections/ConnectionDetail.tsx +218 -0
  173. package/dist/dashboard/routes/connections/ConnectionsList.tsx +34 -0
  174. package/dist/dashboard/routes/connections/index.ts +2 -0
  175. package/dist/dashboard/routes/hooks/Hooks.tsx +425 -0
  176. package/dist/dashboard/routes/hooks/hook-stages.ts +52 -0
  177. package/dist/dashboard/routes/hooks/index.ts +1 -0
  178. package/dist/dashboard/routes/index.ts +8 -0
  179. package/dist/dashboard/routes/logs/Logs.tsx +93 -0
  180. package/dist/dashboard/routes/logs/components/LogDetailDrawer.tsx +118 -0
  181. package/dist/dashboard/routes/logs/components/LogExplorerTab.tsx +367 -0
  182. package/dist/dashboard/routes/logs/components/LogLevelBadge.tsx +34 -0
  183. package/dist/dashboard/routes/logs/components/LogTableRow.tsx +70 -0
  184. package/dist/dashboard/routes/logs/components/LogsOverviewTab.tsx +178 -0
  185. package/dist/dashboard/routes/logs/components/RealtimeLogTab.tsx +122 -0
  186. package/dist/dashboard/routes/logs/index.ts +1 -0
  187. package/dist/dashboard/routes/pipelines/ErrorAuditList.tsx +39 -0
  188. package/dist/dashboard/routes/pipelines/ExportWizardPage.tsx +96 -0
  189. package/dist/dashboard/routes/pipelines/ImportWizardPage.tsx +104 -0
  190. package/dist/dashboard/routes/pipelines/PipelineDetail.tsx +211 -0
  191. package/dist/dashboard/routes/pipelines/PipelineRunsBlock.tsx +377 -0
  192. package/dist/dashboard/routes/pipelines/PipelinesList.tsx +87 -0
  193. package/dist/dashboard/routes/pipelines/RetryPatchHelper.tsx +51 -0
  194. package/dist/dashboard/routes/pipelines/RunDetailsPanel.tsx +238 -0
  195. package/dist/dashboard/routes/pipelines/RunErrorsList.tsx +116 -0
  196. package/dist/dashboard/routes/pipelines/StepCounters.tsx +24 -0
  197. package/dist/dashboard/routes/pipelines/StepSummaryTable.tsx +36 -0
  198. package/dist/dashboard/routes/pipelines/components/DryRunDialog.tsx +341 -0
  199. package/dist/dashboard/routes/pipelines/components/PipelineActionButtons.tsx +201 -0
  200. package/dist/dashboard/routes/pipelines/components/PipelineEditorToggle.tsx +116 -0
  201. package/dist/dashboard/routes/pipelines/components/PipelineFormFields.tsx +156 -0
  202. package/dist/dashboard/routes/pipelines/components/PipelineWebhookInfo.tsx +111 -0
  203. package/dist/dashboard/routes/pipelines/components/ReviewActionsPanel.tsx +342 -0
  204. package/dist/dashboard/routes/pipelines/components/ValidationPanel.tsx +121 -0
  205. package/dist/dashboard/routes/pipelines/components/VersionHistoryDialog.tsx +131 -0
  206. package/dist/dashboard/routes/pipelines/components/index.ts +25 -0
  207. package/dist/dashboard/routes/pipelines/hooks/index.ts +1 -0
  208. package/dist/dashboard/routes/pipelines/hooks/use-pipeline-validation.ts +114 -0
  209. package/dist/dashboard/routes/pipelines/index.ts +4 -0
  210. package/dist/dashboard/routes/pipelines/utils/index.ts +1 -0
  211. package/dist/dashboard/routes/pipelines/utils/pipeline-conversion.ts +261 -0
  212. package/dist/dashboard/routes/queues/ConsumersTable.tsx +134 -0
  213. package/dist/dashboard/routes/queues/DeadLettersTable.tsx +118 -0
  214. package/dist/dashboard/routes/queues/FailedRunsTable.tsx +74 -0
  215. package/dist/dashboard/routes/queues/QueuesPage.tsx +290 -0
  216. package/dist/dashboard/routes/queues/index.ts +1 -0
  217. package/dist/dashboard/routes/queues/types.ts +22 -0
  218. package/dist/dashboard/routes/secrets/SecretDetail.tsx +278 -0
  219. package/dist/dashboard/routes/secrets/SecretsList.tsx +34 -0
  220. package/dist/dashboard/routes/secrets/index.ts +2 -0
  221. package/dist/dashboard/routes/settings/Settings.tsx +343 -0
  222. package/dist/dashboard/routes/settings/index.ts +1 -0
  223. package/dist/dashboard/types/index.ts +89 -0
  224. package/dist/dashboard/types/pipeline.ts +51 -0
  225. package/dist/dashboard/types/ui-types.ts +400 -0
  226. package/dist/dashboard/types/wizard.ts +235 -0
  227. package/dist/dashboard/utils/adapter-grouping.ts +43 -0
  228. package/dist/dashboard/utils/column-analysis.ts +11 -0
  229. package/dist/dashboard/utils/field-preparation.ts +31 -0
  230. package/dist/dashboard/utils/form-validation.ts +373 -0
  231. package/dist/dashboard/utils/formatters.ts +92 -0
  232. package/dist/dashboard/utils/icon-resolver.ts +35 -0
  233. package/dist/dashboard/utils/index.ts +60 -0
  234. package/dist/dashboard/utils/query-key-factory.ts +54 -0
  235. package/dist/dashboard/utils/step-helpers.ts +32 -0
  236. package/dist/dashboard/utils/string-helpers.ts +4 -0
  237. package/dist/dashboard/utils/template-helpers.ts +26 -0
  238. package/dist/dashboard/utils/trigger-sync.ts +138 -0
  239. package/dist/dashboard/utils/wizard-to-pipeline.ts +569 -0
  240. package/dist/shared/types/adapter-config.types.d.ts +254 -11
  241. package/dist/shared/types/adapter-config.types.d.ts.map +1 -1
  242. package/dist/shared/types/index.d.ts +1 -1
  243. package/dist/shared/types/index.d.ts.map +1 -1
  244. package/dist/shared/types/index.js.map +1 -1
  245. package/dist/shared/utils/error.d.ts +5 -0
  246. package/dist/shared/utils/error.d.ts.map +1 -1
  247. package/dist/shared/utils/error.js +11 -0
  248. package/dist/shared/utils/error.js.map +1 -1
  249. package/dist/src/api/schema/pipeline.schema.d.ts +1 -1
  250. package/dist/src/api/schema/pipeline.schema.d.ts.map +1 -1
  251. package/dist/src/api/schema/pipeline.schema.js +2 -0
  252. package/dist/src/api/schema/pipeline.schema.js.map +1 -1
  253. package/dist/src/bootstrap/initialization.d.ts.map +1 -1
  254. package/dist/src/bootstrap/initialization.js +6 -0
  255. package/dist/src/bootstrap/initialization.js.map +1 -1
  256. package/dist/src/entities/data/error-record.entity.d.ts +1 -0
  257. package/dist/src/entities/data/error-record.entity.d.ts.map +1 -1
  258. package/dist/src/entities/data/error-record.entity.js +4 -0
  259. package/dist/src/entities/data/error-record.entity.js.map +1 -1
  260. package/dist/src/gql/generated.d.ts +5 -0
  261. package/dist/src/gql/generated.d.ts.map +1 -1
  262. package/dist/src/gql/generated.js.map +1 -1
  263. package/dist/src/loaders/inventory/inventory.loader.d.ts.map +1 -1
  264. package/dist/src/loaders/inventory/inventory.loader.js +1 -2
  265. package/dist/src/loaders/inventory/inventory.loader.js.map +1 -1
  266. package/dist/src/runtime/executor-types.d.ts +3 -2
  267. package/dist/src/runtime/executor-types.d.ts.map +1 -1
  268. package/dist/src/runtime/executors/loaders/asset-handler.js +1 -1
  269. package/dist/src/runtime/executors/loaders/asset-handler.js.map +1 -1
  270. package/dist/src/runtime/executors/loaders/asset-import-handler.js +1 -1
  271. package/dist/src/runtime/executors/loaders/asset-import-handler.js.map +1 -1
  272. package/dist/src/runtime/executors/loaders/channel-handler.d.ts.map +1 -1
  273. package/dist/src/runtime/executors/loaders/channel-handler.js +14 -1
  274. package/dist/src/runtime/executors/loaders/channel-handler.js.map +1 -1
  275. package/dist/src/runtime/executors/loaders/collection-handler.d.ts.map +1 -1
  276. package/dist/src/runtime/executors/loaders/collection-handler.js +22 -3
  277. package/dist/src/runtime/executors/loaders/collection-handler.js.map +1 -1
  278. package/dist/src/runtime/executors/loaders/customer-group-handler.d.ts.map +1 -1
  279. package/dist/src/runtime/executors/loaders/customer-group-handler.js +8 -1
  280. package/dist/src/runtime/executors/loaders/customer-group-handler.js.map +1 -1
  281. package/dist/src/runtime/executors/loaders/customer-handler.d.ts.map +1 -1
  282. package/dist/src/runtime/executors/loaders/customer-handler.js +33 -2
  283. package/dist/src/runtime/executors/loaders/customer-handler.js.map +1 -1
  284. package/dist/src/runtime/executors/loaders/facet-handler.d.ts.map +1 -1
  285. package/dist/src/runtime/executors/loaders/facet-handler.js +34 -2
  286. package/dist/src/runtime/executors/loaders/facet-handler.js.map +1 -1
  287. package/dist/src/runtime/executors/loaders/graphql-mutation-handler.js +1 -1
  288. package/dist/src/runtime/executors/loaders/graphql-mutation-handler.js.map +1 -1
  289. package/dist/src/runtime/executors/loaders/inventory-adjust-handler.d.ts.map +1 -1
  290. package/dist/src/runtime/executors/loaders/inventory-adjust-handler.js +8 -1
  291. package/dist/src/runtime/executors/loaders/inventory-adjust-handler.js.map +1 -1
  292. package/dist/src/runtime/executors/loaders/inventory-handler.js +3 -3
  293. package/dist/src/runtime/executors/loaders/inventory-handler.js.map +1 -1
  294. package/dist/src/runtime/executors/loaders/loader-handler-registry.d.ts.map +1 -1
  295. package/dist/src/runtime/executors/loaders/loader-handler-registry.js +35 -10
  296. package/dist/src/runtime/executors/loaders/loader-handler-registry.js.map +1 -1
  297. package/dist/src/runtime/executors/loaders/order-handler.d.ts +1 -1
  298. package/dist/src/runtime/executors/loaders/order-handler.d.ts.map +1 -1
  299. package/dist/src/runtime/executors/loaders/order-handler.js +7 -4
  300. package/dist/src/runtime/executors/loaders/order-handler.js.map +1 -1
  301. package/dist/src/runtime/executors/loaders/payment-method-handler.d.ts.map +1 -1
  302. package/dist/src/runtime/executors/loaders/payment-method-handler.js +14 -1
  303. package/dist/src/runtime/executors/loaders/payment-method-handler.js.map +1 -1
  304. package/dist/src/runtime/executors/loaders/product-handler.d.ts +6 -0
  305. package/dist/src/runtime/executors/loaders/product-handler.d.ts.map +1 -1
  306. package/dist/src/runtime/executors/loaders/product-handler.js +31 -13
  307. package/dist/src/runtime/executors/loaders/product-handler.js.map +1 -1
  308. package/dist/src/runtime/executors/loaders/promotion-handler.d.ts.map +1 -1
  309. package/dist/src/runtime/executors/loaders/promotion-handler.js +21 -2
  310. package/dist/src/runtime/executors/loaders/promotion-handler.js.map +1 -1
  311. package/dist/src/runtime/executors/loaders/rest-handler.js +1 -1
  312. package/dist/src/runtime/executors/loaders/rest-handler.js.map +1 -1
  313. package/dist/src/runtime/executors/loaders/shared-lookups.d.ts +28 -1
  314. package/dist/src/runtime/executors/loaders/shared-lookups.d.ts.map +1 -1
  315. package/dist/src/runtime/executors/loaders/shared-lookups.js +136 -0
  316. package/dist/src/runtime/executors/loaders/shared-lookups.js.map +1 -1
  317. package/dist/src/runtime/executors/loaders/shipping-method-handler.d.ts.map +1 -1
  318. package/dist/src/runtime/executors/loaders/shipping-method-handler.js +8 -1
  319. package/dist/src/runtime/executors/loaders/shipping-method-handler.js.map +1 -1
  320. package/dist/src/runtime/executors/loaders/stock-location-handler.d.ts.map +1 -1
  321. package/dist/src/runtime/executors/loaders/stock-location-handler.js +8 -1
  322. package/dist/src/runtime/executors/loaders/stock-location-handler.js.map +1 -1
  323. package/dist/src/runtime/executors/loaders/tax-rate-handler.d.ts.map +1 -1
  324. package/dist/src/runtime/executors/loaders/tax-rate-handler.js +14 -1
  325. package/dist/src/runtime/executors/loaders/tax-rate-handler.js.map +1 -1
  326. package/dist/src/runtime/executors/loaders/types.d.ts +2 -0
  327. package/dist/src/runtime/executors/loaders/types.d.ts.map +1 -1
  328. package/dist/src/runtime/executors/loaders/variant-handler.d.ts +24 -2
  329. package/dist/src/runtime/executors/loaders/variant-handler.d.ts.map +1 -1
  330. package/dist/src/runtime/executors/loaders/variant-handler.js +190 -44
  331. package/dist/src/runtime/executors/loaders/variant-handler.js.map +1 -1
  332. package/dist/src/runtime/executors/sink-handler-registry.js +2 -2
  333. package/dist/src/runtime/executors/sink-handler-registry.js.map +1 -1
  334. package/dist/src/services/data/record-error.service.d.ts +1 -1
  335. package/dist/src/services/data/record-error.service.d.ts.map +1 -1
  336. package/dist/src/services/data/record-error.service.js +4 -1
  337. package/dist/src/services/data/record-error.service.js.map +1 -1
  338. package/dist/src/services/logger/execution-logger.d.ts +1 -1
  339. package/dist/src/services/logger/execution-logger.d.ts.map +1 -1
  340. package/dist/src/services/logger/execution-logger.js +8 -4
  341. package/dist/src/services/logger/execution-logger.js.map +1 -1
  342. package/dist/src/services/pipeline/pipeline-runner.service.d.ts.map +1 -1
  343. package/dist/src/services/pipeline/pipeline-runner.service.js +3 -3
  344. package/dist/src/services/pipeline/pipeline-runner.service.js.map +1 -1
  345. package/dist/src/utils/error.utils.d.ts +1 -1
  346. package/dist/src/utils/error.utils.d.ts.map +1 -1
  347. package/dist/src/utils/error.utils.js +2 -1
  348. package/dist/src/utils/error.utils.js.map +1 -1
  349. package/dist/src/utils/url-security.utils.d.ts +5 -3
  350. package/dist/src/utils/url-security.utils.d.ts.map +1 -1
  351. package/dist/src/utils/url-security.utils.js +20 -4
  352. package/dist/src/utils/url-security.utils.js.map +1 -1
  353. package/docs/reference/loaders.md +39 -2
  354. package/package.json +2 -2
  355. package/shared/types/adapter-config.types.ts +278 -9
  356. package/shared/types/index.ts +13 -0
  357. package/shared/utils/error.ts +11 -0
@@ -0,0 +1,276 @@
1
+ import * as React from 'react';
2
+ import {
3
+ Button,
4
+ Drawer,
5
+ DrawerContent,
6
+ DrawerDescription,
7
+ DrawerHeader,
8
+ DrawerTitle,
9
+ PageBlock,
10
+ PermissionGuard,
11
+ Page,
12
+ PageActionBar,
13
+ PageActionBarRight,
14
+ Card,
15
+ CardContent,
16
+ Badge,
17
+ Tabs,
18
+ TabsContent,
19
+ TabsList,
20
+ TabsTrigger,
21
+ } from '@vendure/dashboard';
22
+ import { DATAHUB_NAV_SECTION, ROUTES, DATAHUB_PERMISSIONS, FALLBACK_ADAPTER_TYPE_TABS } from '../../constants';
23
+ import { DashboardRouteDefinition } from '@vendure/dashboard';
24
+ import {
25
+ RefreshCw,
26
+ Puzzle,
27
+ Settings2,
28
+ Layers,
29
+ } from 'lucide-react';
30
+ import { ErrorState, LoadingState } from '../../components/shared';
31
+ import { cn } from '../../utils';
32
+ import { useAdapters } from '../../hooks';
33
+ import { useOptionValues } from '../../hooks/api/use-config-options';
34
+ import { resolveIconName } from '../../utils/icon-resolver';
35
+ import { AdapterTypeSection } from './AdapterTypeSection';
36
+ import { AdaptersTable } from './AdaptersTable';
37
+ import { AdapterDetail } from './AdapterDetail';
38
+ import { getErrorMessage } from '../../../shared';
39
+ import type { DataHubAdapter } from '../../types';
40
+
41
+ /** Accent colors per stat position for visual variety */
42
+ const STAT_ACCENTS = [
43
+ { bg: 'bg-blue-500/15 dark:bg-blue-500/20', text: 'text-blue-600 dark:text-blue-400', ring: 'ring-blue-500/20' },
44
+ { bg: 'bg-violet-500/15 dark:bg-violet-500/20', text: 'text-violet-600 dark:text-violet-400', ring: 'ring-violet-500/20' },
45
+ { bg: 'bg-emerald-500/15 dark:bg-emerald-500/20', text: 'text-emerald-600 dark:text-emerald-400', ring: 'ring-emerald-500/20' },
46
+ { bg: 'bg-amber-500/15 dark:bg-amber-500/20', text: 'text-amber-600 dark:text-amber-400', ring: 'ring-amber-500/20' },
47
+ { bg: 'bg-rose-500/15 dark:bg-rose-500/20', text: 'text-rose-600 dark:text-rose-400', ring: 'ring-rose-500/20' },
48
+ { bg: 'bg-cyan-500/15 dark:bg-cyan-500/20', text: 'text-cyan-600 dark:text-cyan-400', ring: 'ring-cyan-500/20' },
49
+ { bg: 'bg-orange-500/15 dark:bg-orange-500/20', text: 'text-orange-600 dark:text-orange-400', ring: 'ring-orange-500/20' },
50
+ ] as const;
51
+
52
+ export const adaptersList: DashboardRouteDefinition = {
53
+ navMenuItem: {
54
+ sectionId: DATAHUB_NAV_SECTION,
55
+ id: 'data-hub-adapters',
56
+ url: ROUTES.ADAPTERS,
57
+ title: 'Adapters',
58
+ },
59
+ path: ROUTES.ADAPTERS,
60
+ loader: () => ({ breadcrumb: 'Adapters' }),
61
+ component: () => (
62
+ <PermissionGuard requires={[DATAHUB_PERMISSIONS.MANAGE_ADAPTERS]}>
63
+ <AdaptersPage />
64
+ </PermissionGuard>
65
+ ),
66
+ };
67
+
68
+ function AdaptersPage() {
69
+ const { data: rows = [], isLoading, isError, error, refetch } = useAdapters();
70
+ const { options: adapterTypes } = useOptionValues('adapterTypes');
71
+ const [selected, setSelected] = React.useState<DataHubAdapter | null>(null);
72
+
73
+ const handleCloseDrawer = React.useCallback((open: boolean) => {
74
+ if (!open) setSelected(null);
75
+ }, []);
76
+
77
+ const tabs = adapterTypes.length > 0 ? adapterTypes : FALLBACK_ADAPTER_TYPE_TABS;
78
+
79
+ /** Group adapters by type, keyed by adapter type value */
80
+ const adaptersByType = React.useMemo(() => {
81
+ const map: Record<string, DataHubAdapter[]> = {};
82
+ for (const tab of tabs) {
83
+ map[tab.value] = rows.filter(r => r.type === tab.value);
84
+ }
85
+ return map;
86
+ }, [rows, tabs]);
87
+
88
+ /** Only show tabs that have at least one adapter registered */
89
+ const activeTabs = React.useMemo(
90
+ () => tabs.filter(tab => (adaptersByType[tab.value]?.length ?? 0) > 0),
91
+ [tabs, adaptersByType],
92
+ );
93
+
94
+ const builtInSet = React.useMemo(() => {
95
+ const set = new Set<string>();
96
+ for (const adapter of rows) {
97
+ if (adapter.builtIn !== false) {
98
+ set.add(adapter.code);
99
+ }
100
+ }
101
+ return set;
102
+ }, [rows]);
103
+
104
+ const isBuiltIn = React.useCallback((code: string) => {
105
+ return builtInSet.has(code);
106
+ }, [builtInSet]);
107
+
108
+ const customCount = React.useMemo(
109
+ () => rows.filter(r => !builtInSet.has(r.code)).length,
110
+ [rows, builtInSet],
111
+ );
112
+
113
+ if (isError) {
114
+ return (
115
+ <Page pageId="data-hub-adapters">
116
+ <PageBlock column="main" blockId="error">
117
+ <ErrorState
118
+ title="Failed to load adapters"
119
+ message={getErrorMessage(error)}
120
+ onRetry={() => refetch()}
121
+ />
122
+ </PageBlock>
123
+ </Page>
124
+ );
125
+ }
126
+
127
+ if (isLoading && rows.length === 0) {
128
+ return (
129
+ <Page pageId="data-hub-adapters">
130
+ <PageBlock column="main" blockId="loading">
131
+ <LoadingState type="card" rows={3} message="Loading adapters..." />
132
+ </PageBlock>
133
+ </Page>
134
+ );
135
+ }
136
+
137
+ const defaultTab = activeTabs.length > 0 ? activeTabs[0].value.toLowerCase() : 'all';
138
+
139
+ return (
140
+ <Page pageId="data-hub-adapters">
141
+ <PageActionBar>
142
+ <PageActionBarRight>
143
+ <Button variant="ghost" onClick={() => refetch()} disabled={isLoading} data-testid="datahub-adapters-refresh-button">
144
+ <RefreshCw className={cn('w-4 h-4 mr-2', isLoading && 'animate-spin')} />
145
+ Refresh
146
+ </Button>
147
+ </PageActionBarRight>
148
+ </PageActionBar>
149
+
150
+ <PageBlock column="main" blockId="intro">
151
+ <Card className="overflow-hidden">
152
+ <CardContent className="p-0">
153
+ {/* Hero header row */}
154
+ <div className="flex items-center justify-between px-6 py-5 border-b bg-muted/20">
155
+ <div className="flex items-center gap-3">
156
+ <div className="p-2.5 rounded-xl bg-primary/10 text-primary">
157
+ <Layers className="w-6 h-6" />
158
+ </div>
159
+ <div>
160
+ <h2 className="text-lg font-semibold tracking-tight">Pipeline Adapters</h2>
161
+ <p className="text-sm text-muted-foreground">
162
+ {rows.length} registered &middot; {rows.length - customCount} built-in &middot; {customCount} custom
163
+ </p>
164
+ </div>
165
+ </div>
166
+ </div>
167
+
168
+ {/* Stat chips grid - responsive, uses static grid classes */}
169
+ <div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6 gap-3 p-5">
170
+ {activeTabs.map((tab, idx) => {
171
+ const Icon = resolveIconName(tab.icon);
172
+ const accent = STAT_ACCENTS[idx % STAT_ACCENTS.length];
173
+ const count = adaptersByType[tab.value]?.length ?? 0;
174
+ return (
175
+ <div
176
+ key={tab.value}
177
+ className="group relative flex items-center gap-3 rounded-xl border bg-card p-3.5 transition-all hover:shadow-md hover:border-primary/30"
178
+ >
179
+ <div className={cn('flex-shrink-0 p-2 rounded-lg ring-1', accent.bg, accent.ring)}>
180
+ {Icon
181
+ ? <Icon className={cn('w-4 h-4', accent.text)} />
182
+ : <Puzzle className={cn('w-4 h-4', accent.text)} />
183
+ }
184
+ </div>
185
+ <div className="min-w-0">
186
+ <p className="text-xs text-muted-foreground truncate">{tab.label}</p>
187
+ <p className={cn('text-xl font-bold tabular-nums leading-tight', accent.text)}>
188
+ {count}
189
+ </p>
190
+ </div>
191
+ </div>
192
+ );
193
+ })}
194
+ </div>
195
+ </CardContent>
196
+ </Card>
197
+ </PageBlock>
198
+
199
+ <PageBlock column="main" blockId="adapters">
200
+ <Tabs defaultValue={defaultTab} className="w-full">
201
+ <TabsList className="mb-4" data-testid="datahub-adapters-tabs">
202
+ {activeTabs.map(tab => {
203
+ const Icon = resolveIconName(tab.icon);
204
+ const tabKey = tab.value.toLowerCase();
205
+ const count = adaptersByType[tab.value]?.length ?? 0;
206
+ return (
207
+ <TabsTrigger
208
+ key={tab.value}
209
+ value={tabKey}
210
+ className="gap-2"
211
+ data-testid={`datahub-adapters-tab-${tabKey}`}
212
+ >
213
+ {Icon && <Icon className="w-4 h-4" />}
214
+ {tab.label}
215
+ <Badge variant="secondary" className="ml-1 px-1.5 py-0 text-xs font-medium">
216
+ {count}
217
+ </Badge>
218
+ </TabsTrigger>
219
+ );
220
+ })}
221
+ <TabsTrigger value="all" className="gap-2" data-testid="datahub-adapters-tab-all">
222
+ <Settings2 className="w-4 h-4" />
223
+ All
224
+ <Badge variant="secondary" className="ml-1 px-1.5 py-0 text-xs font-medium">
225
+ {rows.length}
226
+ </Badge>
227
+ </TabsTrigger>
228
+ </TabsList>
229
+
230
+ {activeTabs.map(tab => {
231
+ const tabKey = tab.value.toLowerCase();
232
+ return (
233
+ <TabsContent key={tab.value} value={tabKey}>
234
+ <AdapterTypeSection
235
+ type={tab.value}
236
+ label={tab.label}
237
+ description={tab.description ?? undefined}
238
+ icon={tab.icon ?? undefined}
239
+ adapters={adaptersByType[tab.value] ?? []}
240
+ onSelect={setSelected}
241
+ isBuiltIn={isBuiltIn}
242
+ />
243
+ </TabsContent>
244
+ );
245
+ })}
246
+
247
+ <TabsContent value="all">
248
+ <AdaptersTable
249
+ adapters={rows}
250
+ onSelect={setSelected}
251
+ isBuiltIn={isBuiltIn}
252
+ isLoading={isLoading}
253
+ />
254
+ </TabsContent>
255
+ </Tabs>
256
+ </PageBlock>
257
+
258
+ <Drawer open={!!selected} onOpenChange={handleCloseDrawer}>
259
+ <DrawerContent data-testid="datahub-adapter-detail-drawer">
260
+ <DrawerHeader>
261
+ <div className="flex items-center gap-2">
262
+ <Badge variant="outline">
263
+ {selected?.type}
264
+ </Badge>
265
+ <DrawerTitle>{selected?.code}</DrawerTitle>
266
+ </div>
267
+ <DrawerDescription>
268
+ {selected?.description || 'No description available'}
269
+ </DrawerDescription>
270
+ </DrawerHeader>
271
+ {selected && <AdapterDetail adapter={selected} />}
272
+ </DrawerContent>
273
+ </Drawer>
274
+ </Page>
275
+ );
276
+ }
@@ -0,0 +1,107 @@
1
+ import * as React from 'react';
2
+ import {
3
+ DataTable,
4
+ Badge,
5
+ } from '@vendure/dashboard';
6
+ import { ColumnDef } from '@tanstack/react-table';
7
+ import { ADAPTERS_TABLE_PAGE_SIZE } from './AdapterConstants';
8
+ import type { DataHubAdapter } from '../../types';
9
+
10
+ export function AdaptersTable({
11
+ adapters,
12
+ onSelect,
13
+ isBuiltIn,
14
+ isLoading,
15
+ }: Readonly<{
16
+ adapters: DataHubAdapter[];
17
+ onSelect: (adapter: DataHubAdapter) => void;
18
+ isBuiltIn: (code: string) => boolean;
19
+ isLoading: boolean;
20
+ }>) {
21
+ const [page, setPage] = React.useState(1);
22
+
23
+ const handleSelectAdapter = React.useCallback((adapter: DataHubAdapter) => {
24
+ onSelect(adapter);
25
+ }, [onSelect]);
26
+
27
+ const handlePageChange = React.useCallback((_table: unknown, newPage: number) => {
28
+ setPage(newPage);
29
+ }, []);
30
+
31
+ const columns: ColumnDef<DataHubAdapter, unknown>[] = React.useMemo(() => [
32
+ {
33
+ id: 'type',
34
+ header: 'Type',
35
+ accessorFn: row => row.type,
36
+ cell: ({ row }) => (
37
+ <Badge variant="outline">
38
+ {row.original.type}
39
+ </Badge>
40
+ ),
41
+ },
42
+ {
43
+ id: 'code',
44
+ header: 'Code',
45
+ accessorFn: row => row.code,
46
+ cell: function CodeCell({ row }) {
47
+ const handleClick = React.useCallback(() => {
48
+ handleSelectAdapter(row.original);
49
+ }, [row.original]);
50
+ return (
51
+ <button
52
+ type="button"
53
+ className="font-mono text-sm underline-offset-2 hover:underline"
54
+ onClick={handleClick}
55
+ >
56
+ {row.original.code}
57
+ </button>
58
+ );
59
+ },
60
+ },
61
+ {
62
+ id: 'description',
63
+ header: 'Description',
64
+ accessorFn: row => row.description ?? '',
65
+ cell: ({ row }) => (
66
+ <span className="text-muted-foreground text-sm line-clamp-1">
67
+ {row.original.description || '—'}
68
+ </span>
69
+ ),
70
+ },
71
+ {
72
+ id: 'fields',
73
+ header: 'Fields',
74
+ accessorFn: row => row.schema.fields.length,
75
+ },
76
+ {
77
+ id: 'source',
78
+ header: 'Source',
79
+ accessorFn: row => (isBuiltIn(row.code) ? 'Built-in' : 'Custom'),
80
+ cell: ({ row }) => (
81
+ <Badge variant={isBuiltIn(row.original.code) ? 'outline' : 'secondary'}>
82
+ {isBuiltIn(row.original.code) ? 'Built-in' : 'Custom'}
83
+ </Badge>
84
+ ),
85
+ },
86
+ ], [handleSelectAdapter, isBuiltIn]);
87
+
88
+ // Client-side pagination for the adapters table
89
+ const paginatedAdapters = React.useMemo(() => {
90
+ const start = (page - 1) * ADAPTERS_TABLE_PAGE_SIZE;
91
+ return adapters.slice(start, start + ADAPTERS_TABLE_PAGE_SIZE);
92
+ }, [adapters, page]);
93
+
94
+ return (
95
+ <DataTable
96
+ columns={columns}
97
+ data={paginatedAdapters}
98
+ isLoading={isLoading}
99
+ totalItems={adapters.length}
100
+ itemsPerPage={ADAPTERS_TABLE_PAGE_SIZE}
101
+ page={page}
102
+ onPageChange={handlePageChange}
103
+ disableViewOptions
104
+ data-testid="datahub-adapters-table"
105
+ />
106
+ );
107
+ }
@@ -0,0 +1 @@
1
+ export { adaptersList } from './AdaptersPage';
@@ -0,0 +1,218 @@
1
+ import * as React from 'react';
2
+ import { Button, DashboardRouteDefinition, DetailFormGrid, FormFieldWrapper, Input, Page, PageActionBar, PageActionBarRight, PageBlock, PageLayout, PageTitle, detailPageRouteLoader, useDetailPage, Select, SelectTrigger, SelectContent, SelectItem, SelectValue, PermissionGuard } from '@vendure/dashboard';
3
+ import { AnyRoute, useNavigate } from '@tanstack/react-router';
4
+ import { useWatch } from 'react-hook-form';
5
+ import { toast } from 'sonner';
6
+ import {
7
+ ConnectionConfigEditor,
8
+ useConnectionTypeOptions,
9
+ createDefaultConnectionConfig,
10
+ normalizeConnectionConfig,
11
+ } from '../../components/common';
12
+ import type { UIConnectionType } from '../../types';
13
+ import { getErrorMessage } from '../../../shared';
14
+ import { CODE_PATTERN } from '../../utils';
15
+ import { FieldError } from '../../components/common';
16
+ import { QUERY_LIMITS, DATAHUB_PERMISSIONS, ROUTES, CONNECTION_DEFAULT_TYPE, SELECT_WIDTHS, TOAST_CONNECTION, ERROR_MESSAGES } from '../../constants';
17
+ import {
18
+ connectionDetailDocument,
19
+ createConnectionDocument,
20
+ updateConnectionDocument,
21
+ useSecrets,
22
+ } from '../../hooks';
23
+
24
+
25
+ export const connectionDetail: DashboardRouteDefinition = {
26
+ path: `${ROUTES.CONNECTIONS}/$id`,
27
+ loader: detailPageRouteLoader({ queryDocument: connectionDetailDocument, breadcrumb: (isNew, entity) => ['Data Hub', 'Connections', isNew ? 'New connection' : (entity?.code ?? '')] }),
28
+ component: route => (
29
+ <PermissionGuard requires={[DATAHUB_PERMISSIONS.MANAGE_CONNECTIONS]}>
30
+ <ConnectionDetailPage route={route} />
31
+ </PermissionGuard>
32
+ ),
33
+ };
34
+
35
+ function ConnectionDetailPage({ route }: { route: AnyRoute }) {
36
+ const params = route.useParams();
37
+ const navigate = useNavigate();
38
+ const creating = params.id === 'new';
39
+
40
+ const connectionTypeOptions = useConnectionTypeOptions();
41
+ const { data: secretsData, isError: secretsError } = useSecrets({ take: QUERY_LIMITS.SECRETS_LIST });
42
+
43
+ React.useEffect(() => {
44
+ if (secretsError) {
45
+ toast.error(TOAST_CONNECTION.SECRETS_LOAD_ERROR);
46
+ }
47
+ }, [secretsError]);
48
+
49
+ const secretOptions = (secretsData?.items ?? []).map(item => ({
50
+ code: item.code,
51
+ provider: item.provider ?? undefined,
52
+ }));
53
+
54
+ const { form, submitHandler, entity, isPending, resetForm } = useDetailPage({
55
+ queryDocument: connectionDetailDocument,
56
+ createDocument: createConnectionDocument,
57
+ updateDocument: updateConnectionDocument,
58
+ setValuesForCreate: () => ({
59
+ code: '',
60
+ type: CONNECTION_DEFAULT_TYPE,
61
+ config: createDefaultConnectionConfig(CONNECTION_DEFAULT_TYPE),
62
+ }),
63
+ setValuesForUpdate: s => {
64
+ const type = (s?.type ?? CONNECTION_DEFAULT_TYPE) as UIConnectionType;
65
+ return {
66
+ id: s?.id ?? '',
67
+ code: s?.code ?? '',
68
+ type,
69
+ config: normalizeConnectionConfig(type, s?.config ?? {}),
70
+ };
71
+ },
72
+ params: { id: params.id },
73
+ onSuccess: async data => {
74
+ toast.success(TOAST_CONNECTION.SAVE_SUCCESS);
75
+ resetForm();
76
+ if (creating) {
77
+ await navigate({ to: `../$id`, params: { id: data.id } });
78
+ }
79
+ },
80
+ onError: err => {
81
+ toast.error(TOAST_CONNECTION.SAVE_ERROR, {
82
+ description: getErrorMessage(err),
83
+ });
84
+ },
85
+ });
86
+
87
+ const configCacheRef = React.useRef<Record<string, Record<string, unknown>>>({});
88
+
89
+ React.useEffect(() => {
90
+ if (!entity) {
91
+ return;
92
+ }
93
+ const type = (entity.type ?? form.getValues('type') ?? CONNECTION_DEFAULT_TYPE) as UIConnectionType;
94
+ const normalized = normalizeConnectionConfig(type, entity.config ?? {});
95
+ configCacheRef.current[type] = normalized as Record<string, unknown>;
96
+ form.reset(
97
+ {
98
+ id: entity.id ?? '',
99
+ code: entity.code ?? '',
100
+ type,
101
+ config: normalized,
102
+ },
103
+ { keepDirty: false, keepTouched: false },
104
+ );
105
+ }, [entity?.id, form]);
106
+
107
+ const watchedType = useWatch({ control: form.control, name: 'type', defaultValue: entity?.type || CONNECTION_DEFAULT_TYPE });
108
+ const connectionType = (watchedType || entity?.type || CONNECTION_DEFAULT_TYPE) as UIConnectionType;
109
+
110
+ return (
111
+ <Page pageId="data-hub-connection-detail" form={form} submitHandler={submitHandler}>
112
+ <PageTitle>{creating ? 'New Connection' : (entity?.code ?? '')}</PageTitle>
113
+ <PageActionBar>
114
+ <PageActionBarRight>
115
+ <Button type="submit" disabled={!form.formState.isDirty || !form.formState.isValid || isPending}>
116
+ {creating ? 'Create' : 'Update'}
117
+ </Button>
118
+ </PageActionBarRight>
119
+ </PageActionBar>
120
+ <PageLayout>
121
+ <PageBlock column="main" blockId="connection-form">
122
+ <DetailFormGrid>
123
+ <FormFieldWrapper
124
+ name="code"
125
+ label="Code"
126
+ control={form.control}
127
+ rules={{
128
+ required: ERROR_MESSAGES.CODE_REQUIRED,
129
+ pattern: {
130
+ value: CODE_PATTERN,
131
+ message: ERROR_MESSAGES.CODE_PATTERN,
132
+ },
133
+ }}
134
+ render={({ field, fieldState }) => (
135
+ <div>
136
+ <Input
137
+ {...field}
138
+ placeholder="my-connection"
139
+ className={fieldState.error ? 'border-destructive focus-visible:ring-destructive' : ''}
140
+ />
141
+ <FieldError error={fieldState.error?.message} touched={fieldState.isTouched} />
142
+ {!fieldState.error && (
143
+ <p className="mt-1 text-xs text-muted-foreground">
144
+ Unique identifier for this connection
145
+ </p>
146
+ )}
147
+ </div>
148
+ )}
149
+ />
150
+ <FormFieldWrapper
151
+ name="type"
152
+ label="Connection Type"
153
+ control={form.control}
154
+ rules={{ required: ERROR_MESSAGES.CONNECTION_TYPE_REQUIRED }}
155
+ render={({ field, fieldState }) => (
156
+ <div>
157
+ <Select
158
+ value={
159
+ (typeof field.value === 'string' && field.value.length > 0)
160
+ ? field.value
161
+ : String(entity?.type ?? CONNECTION_DEFAULT_TYPE)
162
+ }
163
+ onValueChange={val => {
164
+ const prevType = (field.value as UIConnectionType | undefined) ?? (entity?.type as UIConnectionType | undefined);
165
+ const nextType = val as UIConnectionType;
166
+ const prevConfig = form.getValues('config') as Record<string, unknown> | undefined;
167
+ if (prevType && prevConfig && typeof prevConfig === 'object') {
168
+ configCacheRef.current[prevType] = prevConfig;
169
+ }
170
+ field.onChange(nextType);
171
+ const restored = configCacheRef.current[nextType] ?? createDefaultConnectionConfig(nextType);
172
+ form.setValue('config', restored, { shouldDirty: true });
173
+ }}
174
+ >
175
+ <SelectTrigger className={SELECT_WIDTHS.CONNECTION_TYPE}>
176
+ <SelectValue placeholder="Select type" />
177
+ </SelectTrigger>
178
+ <SelectContent>
179
+ {connectionTypeOptions.map(opt => (
180
+ <SelectItem key={opt.value} value={opt.value}>
181
+ {opt.label}
182
+ </SelectItem>
183
+ ))}
184
+ </SelectContent>
185
+ </Select>
186
+ <FieldError error={fieldState.error?.message} touched={fieldState.isTouched} />
187
+ </div>
188
+ )}
189
+ />
190
+ </DetailFormGrid>
191
+
192
+ <div className="mt-6">
193
+ <h3 className="text-sm font-medium mb-4">Connection Settings</h3>
194
+ <FormFieldWrapper
195
+ name="config"
196
+ label=""
197
+ control={form.control}
198
+ render={({ field }) => {
199
+ const serverConfig = normalizeConnectionConfig(connectionType, entity?.config ?? {});
200
+ const effectiveConfig = (field.value && typeof field.value === 'object')
201
+ ? (field.value as Record<string, unknown>)
202
+ : serverConfig;
203
+ return (
204
+ <ConnectionConfigEditor
205
+ type={connectionType}
206
+ config={effectiveConfig}
207
+ onChange={field.onChange}
208
+ secretOptions={secretOptions}
209
+ />
210
+ );
211
+ }}
212
+ />
213
+ </div>
214
+ </PageBlock>
215
+ </PageLayout>
216
+ </Page>
217
+ );
218
+ }
@@ -0,0 +1,34 @@
1
+ import { Button, DashboardRouteDefinition, DetailPageButton, ListPage, PageActionBarRight, PermissionGuard } from '@vendure/dashboard';
2
+ import { DATAHUB_NAV_SECTION, DATAHUB_PERMISSIONS, ROUTES } from '../../constants';
3
+ import { connectionsListDocument, deleteConnectionDocument } from '../../hooks';
4
+ import { Link } from '@tanstack/react-router';
5
+
6
+ export const connectionsList: DashboardRouteDefinition = {
7
+ navMenuItem: {
8
+ sectionId: DATAHUB_NAV_SECTION,
9
+ id: 'data-hub-connections',
10
+ url: ROUTES.CONNECTIONS,
11
+ title: 'Connections',
12
+ },
13
+ path: ROUTES.CONNECTIONS,
14
+ loader: () => ({ breadcrumb: 'Connections' }),
15
+ component: route => (
16
+ <PermissionGuard requires={[DATAHUB_PERMISSIONS.MANAGE_CONNECTIONS]}>
17
+ <ListPage
18
+ pageId="data-hub-connections-list"
19
+ title="Connections"
20
+ listQuery={connectionsListDocument}
21
+ deleteMutation={deleteConnectionDocument}
22
+ route={route}
23
+ customizeColumns={{
24
+ code: { header: 'Code', cell: ({ row }) => <DetailPageButton id={row.original.id} label={row.original.code} /> },
25
+ type: { header: 'Type' },
26
+ }}
27
+ >
28
+ <PageActionBarRight>
29
+ <Button asChild data-testid="datahub-connection-create-button"><Link to="./new">New connection</Link></Button>
30
+ </PageActionBarRight>
31
+ </ListPage>
32
+ </PermissionGuard>
33
+ ),
34
+ };
@@ -0,0 +1,2 @@
1
+ export { connectionsList } from './ConnectionsList';
2
+ export { connectionDetail } from './ConnectionDetail';