@gadmin2n/schematics 0.0.143 → 0.0.145

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 (279) hide show
  1. package/dist/lib/application/files/gadmin2-game-angle-demo/config/.types.d.ts +10 -0
  2. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/approval.prisma +2 -0
  3. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +140 -19
  4. package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +2 -2
  5. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/data-mngt.seed.ts +0 -2
  6. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-node-types.ts +694 -327
  7. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-outbox.ts +57 -0
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow.seed.ts +35 -5
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflows.ts +224 -59
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-executor.spec.ts +23 -0
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-executor.ts +16 -5
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-runtime.controller.spec.ts +98 -0
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-runtime.controller.ts +26 -6
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-runtime.dto.ts +17 -2
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-runtime.controller.spec.ts +1 -0
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-runtime.controller.ts +3 -0
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-runtime.dto.ts +0 -2
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-signal-outbox.service.spec.ts +30 -0
  19. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-signal-outbox.service.ts +28 -6
  20. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction.service.spec.ts +63 -0
  21. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction.service.ts +151 -38
  22. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-wait.handler.ts +4 -1
  23. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/human-approval.handler.spec.ts +16 -5
  24. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/human-approval.handler.ts +23 -6
  25. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.controller.spec.ts +130 -0
  26. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.controller.ts +62 -62
  27. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.dto.ts +15 -1
  28. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.util.spec.ts +70 -9
  29. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.util.ts +31 -7
  30. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-signal-outbox.service.spec.ts +30 -0
  31. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-signal-outbox.service.ts +28 -6
  32. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-subject-source.util.spec.ts +50 -3
  33. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-subject-source.util.ts +26 -3
  34. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.dto.ts +53 -47
  35. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.errors.ts +0 -1
  36. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.service.spec.ts +541 -0
  37. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.service.ts +442 -200
  38. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/outbox-retry.util.ts +1 -0
  39. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/human-approval-runtime.controller.spec.ts +150 -0
  40. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/human-approval-runtime.controller.ts +56 -40
  41. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/human-approval-runtime.dto.ts +16 -60
  42. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-connection.controller.ts +13 -0
  43. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-connection.service.spec.ts +44 -0
  44. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-connection.service.ts +6 -0
  45. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/dsl-validate.util.spec.ts +258 -12
  46. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/dsl-validate.util.ts +127 -14
  47. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/manual-workflow-execution.spec.ts +85 -0
  48. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/manual-workflow-execution.ts +108 -0
  49. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/parameter-binding.ts +5 -5
  50. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.service.spec.ts +96 -25
  51. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.service.ts +77 -34
  52. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-callable.spec.ts +23 -34
  53. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-callable.ts +0 -21
  54. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-cancellation.spec.ts +245 -0
  55. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.service.spec.ts +639 -188
  56. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.service.ts +408 -235
  57. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.types.ts +1 -3
  58. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-data-edge.util.spec.ts +279 -95
  59. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-data-edge.util.ts +360 -80
  60. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-event-catalog.spec.ts +323 -0
  61. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-execution-idempotency.spec.ts +773 -0
  62. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-execution.dto.ts +7 -13
  63. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.dto.ts +0 -16
  64. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.service.spec.ts +184 -0
  65. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.service.ts +69 -138
  66. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-handle-validator.spec.ts +113 -0
  67. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-handle-validator.ts +59 -13
  68. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-runtime.facade.ts +86 -0
  69. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-switch-config.spec.ts +25 -0
  70. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-switch-config.ts +45 -0
  71. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.spec.ts +78 -43
  72. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +103 -40
  73. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.dto.ts +57 -0
  74. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.module.ts +3 -1
  75. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.spec.ts +1000 -240
  76. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +2184 -317
  77. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/node-config-validator.service.spec.ts +279 -2
  78. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/node-config-validator.service.ts +5 -1
  79. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/subject-config-validator.service.spec.ts +4 -1
  80. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/subject-config-validator.service.ts +5 -1
  81. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/widget-catalog.service.spec.ts +12 -3
  82. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/widget-catalog.service.ts +10 -1
  83. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.spec.ts +2 -24
  84. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.ts +3 -70
  85. package/dist/lib/application/files/gadmin2-game-angle-demo/web/package.json +3 -1
  86. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/RowActions.tsx +25 -5
  87. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/WorkflowActionButton.test.tsx +71 -0
  88. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/WorkflowActionButton.tsx +89 -0
  89. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/index.ts +1 -0
  90. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/header.tsx +52 -12
  91. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +12 -0
  92. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/constants/layout.ts +2 -2
  93. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/AddDataModal.tsx +10 -33
  94. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/AddPageModal.tsx +13 -37
  95. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DevShell.tsx +55 -7
  96. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/style.css +14 -0
  97. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/http.ts +10 -0
  98. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/list.tsx +1 -0
  99. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/workflowAction.ts +19 -0
  100. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/index.ts +1 -0
  101. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/types.ts +3 -1
  102. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useDynamicResources.tsx +1 -6
  103. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useReferenceUpload.ts +95 -0
  104. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +2 -2
  105. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/workflow.json +672 -110
  106. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +2 -2
  107. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/workflow.json +676 -114
  108. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/plugins/devShellPlugin.ts +13 -1
  109. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/index.tsx +1 -0
  110. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasEditPage.tsx +38 -4
  111. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasListPage.tsx +276 -376
  112. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/CanvasAiModal.tsx +126 -6
  113. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/human-approval/DecisionModal.test.tsx +50 -0
  114. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/human-approval/DecisionModal.tsx +48 -11
  115. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/human-approval/inbox.tsx +32 -34
  116. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/RegisterBusinessEventModal.test.tsx +111 -0
  117. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/RegisterBusinessEventModal.tsx +167 -0
  118. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/business-events.css +99 -0
  119. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/detail.test.tsx +106 -0
  120. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/detail.tsx +324 -0
  121. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/index.test.tsx +73 -0
  122. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/business-events/index.tsx +359 -0
  123. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CanvasZoomControls.tsx +46 -0
  124. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CreateNodeInstanceDrawer.tsx +9 -1
  125. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CustomNode.test.tsx +105 -4
  126. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CustomNode.tsx +90 -48
  127. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/DeletableEdge.tsx +3 -2
  128. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/DslView.test.tsx +259 -0
  129. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/DslView.tsx +167 -103
  130. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/EnhancedFlowRenderer.tsx +142 -140
  131. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExecutionStatusNode.test.tsx +60 -15
  132. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExecutionStatusNode.tsx +25 -12
  133. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/FlowRenderer.tsx +364 -200
  134. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NewNodeDefaults.test.tsx +220 -52
  135. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeOutputSummary.test.tsx +260 -0
  136. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeOutputSummary.tsx +300 -130
  137. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.test.tsx +507 -33
  138. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.tsx +630 -592
  139. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ParameterBindingEditor.tsx +67 -70
  140. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ReadonlyNodePanel.test.tsx +90 -0
  141. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ReadonlyNodePanel.tsx +325 -0
  142. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/RunWorkflowModal.test.tsx +52 -0
  143. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/RunWorkflowModal.tsx +14 -9
  144. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/StatusCards.tsx +2 -1
  145. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/VersionPanel.tsx +2 -1
  146. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/WorkflowCodeEditor.test.tsx +42 -0
  147. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/WorkflowCodeEditor.tsx +76 -0
  148. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/WorkflowWorkspaceHeader.tsx +56 -0
  149. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/parameter-binding-editor.css +46 -0
  150. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/workflow-code-editor.css +34 -0
  151. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/ConnectionModal.test.tsx +53 -7
  152. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/ConnectionModal.tsx +123 -62
  153. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/connections.css +85 -0
  154. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/connectionsApi.ts +29 -0
  155. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/index.test.tsx +75 -0
  156. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/index.tsx +69 -36
  157. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/editor.test.tsx +494 -0
  158. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/editor.tsx +665 -194
  159. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useReferencedNodeInstanceConfigs.test.tsx +92 -0
  160. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useReferencedNodeInstanceConfigs.ts +96 -0
  161. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useWorkflowAgent.test.tsx +297 -0
  162. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useWorkflowAgent.ts +135 -65
  163. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/index.tsx +53 -42
  164. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.tsx +344 -155
  165. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instances.tsx +79 -58
  166. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/CreateNodeInstanceModal.tsx +123 -144
  167. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/NodeInstanceForm.tsx +169 -98
  168. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/node-instance-form.css +91 -0
  169. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/index.tsx +54 -31
  170. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/node-config.css +854 -0
  171. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/SchemaField.tsx +41 -14
  172. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/SchemaForm.test.tsx +75 -0
  173. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/SchemaForm.tsx +3 -0
  174. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/default-widgets.tsx +20 -2
  175. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/widget-registry.tsx +2 -1
  176. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/show.tsx +61 -66
  177. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApprovalRuleEditor.test.tsx +33 -1
  178. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApprovalRuleEditor.tsx +47 -15
  179. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/BranchConfigEditors.test.tsx +104 -0
  180. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/CallableInputParametersEditor.tsx +22 -52
  181. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/CodeConfigEditor.test.tsx +72 -0
  182. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/CodeConfigEditor.tsx +78 -70
  183. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/CronTriggerConfigEditor.tsx +569 -0
  184. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/DbExecuteConfigEditor.tsx +130 -0
  185. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/DelayConfigEditor.tsx +100 -0
  186. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/EventTriggerConfigEditor.tsx +620 -0
  187. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ExternalRequestConfigEditor.test.tsx +22 -45
  188. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ExternalRequestConfigEditor.tsx +25 -92
  189. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ExternalWaitConfigEditor.tsx +3 -11
  190. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ForEachConfigEditor.test.tsx +58 -0
  191. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ForEachConfigEditor.tsx +107 -0
  192. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HttpRequestConfigEditor.test.tsx +212 -31
  193. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HttpRequestConfigEditor.tsx +214 -304
  194. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HumanApprovalConfigEditor.test.tsx +175 -40
  195. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HumanApprovalConfigEditor.tsx +693 -293
  196. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/IfElseConfigEditor.tsx +190 -0
  197. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ManualTriggerConfigEditor.test.tsx +152 -0
  198. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ManualTriggerConfigEditor.tsx +286 -0
  199. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ParallelConfigEditor.tsx +101 -0
  200. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ParameterBindingListEditor.tsx +99 -0
  201. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SimplifiedNodeEditors.test.tsx +495 -0
  202. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubWorkflowConfigEditor.test.tsx +124 -0
  203. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubWorkflowConfigEditor.tsx +222 -0
  204. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubjectPicker.tsx +2 -4
  205. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SwitchConfigEditor.tsx +204 -0
  206. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/UserGroupCreateModal.tsx +3 -1
  207. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/UserGroupEditModal.tsx +9 -6
  208. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/callable-workflow.ts +4 -0
  209. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/code-config.css +96 -0
  210. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/event-catalog.api.ts +117 -0
  211. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/http-request-config.css +242 -0
  212. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/human-approval-config.css +194 -0
  213. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/show.tsx +264 -167
  214. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/temporal-tenant/index.tsx +6 -9
  215. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/types/parameter-binding.ts +19 -16
  216. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/types.ts +28 -4
  217. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/useWorkflowFormValidation.test.tsx +59 -0
  218. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/useWorkflowFormValidation.ts +24 -0
  219. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/forEachConnection.test.ts +311 -0
  220. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/forEachConnection.ts +198 -0
  221. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/mainFlowConnection.test.ts +143 -0
  222. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/mainFlowConnection.ts +19 -0
  223. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/newNodeConfig.ts +103 -5
  224. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/removeWorkflowEdges.test.ts +158 -3
  225. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/removeWorkflowEdges.ts +117 -9
  226. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveEffectiveOutput.test.ts +70 -0
  227. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveEffectiveOutput.ts +48 -0
  228. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveLookupPorts.test.ts +55 -0
  229. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveLookupPorts.ts +95 -22
  230. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveOutputs.test.ts +148 -1
  231. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveOutputs.ts +62 -11
  232. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveWorkflowDisplay.test.ts +19 -0
  233. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveWorkflowDisplay.ts +1 -1
  234. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/subWorkflowChange.test.ts +45 -0
  235. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/subWorkflowChange.ts +26 -0
  236. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/validateWorkflowDsl.test.ts +502 -0
  237. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/validateWorkflowDsl.ts +694 -0
  238. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowDateTime.test.ts +27 -0
  239. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowDateTime.ts +33 -0
  240. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowHistory.test.ts +34 -0
  241. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowHistory.ts +52 -0
  242. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowPublishError.test.ts +99 -0
  243. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowPublishError.ts +91 -0
  244. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowSkillPrompt.test.ts +74 -0
  245. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/workflowSkillPrompt.ts +120 -0
  246. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/workflow-ui.css +481 -0
  247. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/index.css +1 -1
  248. package/package.json +1 -1
  249. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowEventOutbox.ts +0 -62
  250. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/migrate-human-approval-configs.ts +0 -86
  251. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-event-trigger.ts +0 -60
  252. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.external-decision.spec.ts +0 -183
  253. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/legacy-approval-config-migration.ts +0 -227
  254. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-http-response.spec.ts +0 -82
  255. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-http-response.ts +0 -111
  256. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.controller.spec.ts +0 -54
  257. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.controller.ts +0 -147
  258. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.module.ts +0 -10
  259. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.service.spec.ts +0 -350
  260. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.service.ts +0 -110
  261. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/index.ts +0 -1
  262. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/InstanceRequiredDialog.tsx +0 -106
  263. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/LookupConnectionDialog.test.tsx +0 -45
  264. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/LookupConnectionDialog.tsx +0 -43
  265. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeTypeBadge.tsx +0 -36
  266. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useNodeInstanceLibrary.ts +0 -41
  267. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApproverSourceEditor.test.tsx +0 -47
  268. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApproverSourceEditor.tsx +0 -182
  269. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ReturnResultConfigEditor.test.tsx +0 -34
  270. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ReturnResultConfigEditor.tsx +0 -16
  271. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/approver-source.test.ts +0 -25
  272. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/approver-source.ts +0 -42
  273. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/lookupConnection.test.ts +0 -208
  274. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/lookupConnection.ts +0 -246
  275. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/create.tsx +0 -111
  276. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/edit.tsx +0 -127
  277. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/index.tsx +0 -4
  278. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/list.tsx +0 -282
  279. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/show.tsx +0 -74
@@ -2,6 +2,7 @@ import { BadRequestException, Injectable } from '@nestjs/common';
2
2
  import { Prisma } from '@prisma/client';
3
3
  import { PrismaService } from 'nestjs-prisma';
4
4
  import { ActorContext } from '../subjectProvider/subject-provider.types';
5
+ import type { NodeConfigValidationError } from '../workflowConfig/node-config-validator.service';
5
6
  import { NodeConfigValidatorService } from '../workflowConfig/node-config-validator.service';
6
7
  import { JsonSchema } from '../workflowConfig/schema.types';
7
8
  import { SubjectConfigValidatorService } from '../workflowConfig/subject-config-validator.service';
@@ -10,7 +11,6 @@ import { hashNodeInstanceConfig } from '../workflowNodeInstance/node-instance-co
10
11
  import { validateParameterBinding } from './parameter-binding';
11
12
  import {
12
13
  describeCallableWorkflow,
13
- describeReturningWorkflowInputs,
14
14
  validateCallableWorkflow,
15
15
  } from './workflow-callable';
16
16
  import {
@@ -20,7 +20,7 @@ import {
20
20
  DraftWorkflowNode,
21
21
  WorkflowCompilerErrorCode,
22
22
  } from './workflow-compiler.types';
23
- import { validateWebhookResponseWorkflow } from './workflow-http-response';
23
+ import { switchCaseValidationError } from './workflow-switch-config';
24
24
 
25
25
  @Injectable()
26
26
  export class WorkflowCompilerService {
@@ -34,6 +34,7 @@ export class WorkflowCompilerService {
34
34
  async compile(
35
35
  draftDsl: DraftWorkflowDsl,
36
36
  actor: ActorContext,
37
+ options?: { workflowId?: bigint },
37
38
  ): Promise<CompiledWorkflowDsl> {
38
39
  if (!draftDsl || !Array.isArray(draftDsl.nodes))
39
40
  throw new BadRequestException({
@@ -56,6 +57,7 @@ export class WorkflowCompilerService {
56
57
  select: {
57
58
  id: true,
58
59
  type: true,
60
+ label: true,
59
61
  runtimeKey: true,
60
62
  instancePolicy: true,
61
63
  schemaVersion: true,
@@ -92,19 +94,6 @@ export class WorkflowCompilerService {
92
94
  `Unknown node type: ${node.type}`,
93
95
  );
94
96
  const ref = node.instanceRef;
95
- if (nodeType.instancePolicy === 'REQUIRED' && !ref)
96
- this.fail(
97
- 'NODE_INSTANCE_REQUIRED',
98
- node,
99
- `Node type ${node.type} requires an instance`,
100
- );
101
- if (nodeType.instancePolicy === 'INLINE_ONLY' && ref)
102
- this.fail(
103
- 'INLINE_NODE_INSTANCE_FORBIDDEN',
104
- node,
105
- `Node type ${node.type} does not accept an instance reference`,
106
- );
107
-
108
97
  let config = clone(node.config ?? {});
109
98
  let source: CompiledWorkflowNode['source'];
110
99
  if (ref) {
@@ -146,225 +135,114 @@ export class WorkflowCompilerService {
146
135
 
147
136
  const schemaKey = `${nodeType.id}:${nodeType.schemaVersion}`;
148
137
  const schema = nodeType.configSchema as JsonSchema;
149
- this.configs.validateOrThrow(schemaKey, schema, config);
138
+ const approvalSubjects = (config as Record<string, unknown>).subjects;
139
+ if (
140
+ nodeType.runtimeKey === 'human_approval' &&
141
+ (!Array.isArray(approvalSubjects) || approvalSubjects.length === 0)
142
+ )
143
+ this.fail(
144
+ 'NODE_TYPE_MISMATCH',
145
+ node,
146
+ '必须至少设置一位固定审批人或动态审批人',
147
+ );
148
+ const manualParameterError =
149
+ nodeType.runtimeKey === 'manual_trigger'
150
+ ? validateManualInputParameters(config)
151
+ : null;
152
+ if (manualParameterError)
153
+ this.fail('NODE_TYPE_MISMATCH', node, manualParameterError);
154
+ const invalidBindingPath = findInvalidParameterBinding(config);
155
+ if (invalidBindingPath)
156
+ this.fail(
157
+ 'NODE_TYPE_MISMATCH',
158
+ node,
159
+ `参数来源或固定值无效:${invalidBindingPath}`,
160
+ );
161
+ try {
162
+ this.configs.validateOrThrow(schemaKey, schema, config);
163
+ } catch (error) {
164
+ const errors = nodeConfigValidationErrors(error);
165
+ if (!errors) throw error;
166
+ const nodeLabel = String(node.label ?? '').trim() || nodeType.label;
167
+ throw new BadRequestException({
168
+ code: 'NODE_CONFIG_INVALID',
169
+ message: `节点“${nodeLabel}”的配置不完整或有误`,
170
+ nodeLabel,
171
+ errors,
172
+ });
173
+ }
150
174
  this.widgets.assertUiSchemaSupported(nodeType.uiSchema);
151
- await this.subjects.validateSubjects(schema, config, actor);
152
- if (nodeType.runtimeKey === 'http_request') {
153
- const connectionRef = (config as Record<string, unknown>)
154
- ?.connectionRef;
155
- const connection =
156
- typeof connectionRef === 'string'
157
- ? await this.prisma.integrationConnection.findUnique({
158
- where: { code: connectionRef },
159
- select: { isEnabled: true },
160
- })
161
- : null;
162
- if (!connection?.isEnabled)
163
- this.fail(
164
- 'NODE_TYPE_MISMATCH',
165
- node,
166
- 'HTTP Request Connection was not found or is disabled',
167
- );
175
+ try {
176
+ await this.subjects.validateSubjects(schema, config, actor);
177
+ } catch (error) {
178
+ const errors = subjectValidationErrors(error);
179
+ if (!errors) throw error;
180
+ const nodeLabel = String(node.label ?? '').trim() || nodeType.label;
181
+ throw new BadRequestException({
182
+ code: 'SUBJECT_REF_INVALID',
183
+ message: `节点“${nodeLabel}”的审批人配置不完整或无效`,
184
+ nodeLabel,
185
+ errors,
186
+ });
168
187
  }
169
- if (nodeType.runtimeKey === 'sub_workflow') {
170
- const workflowId = String(
171
- (config as Record<string, unknown>)?.workflowId ?? '',
188
+ if (nodeType.runtimeKey === 'http_request') {
189
+ await this.validateIntegrationConnection(
190
+ node,
191
+ (config as Record<string, unknown>)?.connectionRef,
192
+ 'HTTP Request Connection',
172
193
  );
173
- if (!/^[1-9]\d*$/.test(workflowId))
174
- this.fail('NODE_TYPE_MISMATCH', node, '调用的 Workflow ID 无效');
175
- const workflow = await this.prisma.workflow.findUnique({
176
- where: { id: BigInt(workflowId) },
177
- select: {
178
- isEnabled: true,
179
- status: true,
180
- versions: {
181
- orderBy: { version: 'desc' },
182
- take: 1,
183
- select: { dsl: true },
184
- },
185
- },
186
- });
187
- if (!workflow?.isEnabled || workflow.status !== 'PUBLISHED')
188
- this.fail(
189
- 'NODE_TYPE_MISMATCH',
190
- node,
191
- '调用的 Workflow 未发布或已停用',
192
- );
193
- let descriptor;
194
- try {
195
- descriptor = describeCallableWorkflow(workflow.versions[0]?.dsl);
196
- } catch (error) {
197
- this.fail(
198
- 'NODE_TYPE_MISMATCH',
194
+ }
195
+ if (nodeType.runtimeKey === 'human_approval') {
196
+ const approvalConfig = asObject(config);
197
+ if (approvalConfig.external) {
198
+ await this.validateIntegrationConnection(
199
199
  node,
200
- error instanceof Error ? error.message : '调用的 Workflow 配置无效',
200
+ asObject(asObject(approvalConfig.external).request).connectionRef,
201
+ '外部审批连接',
201
202
  );
202
203
  }
203
- if (!descriptor)
204
- this.fail(
205
- 'NODE_TYPE_MISMATCH',
204
+ const approvalSubjects = Array.isArray(approvalConfig.subjects)
205
+ ? approvalConfig.subjects
206
+ : [];
207
+ for (const subjectValue of approvalSubjects) {
208
+ const subject = asObject(subjectValue);
209
+ if (subject.source !== 'DYNAMIC') continue;
210
+ await this.validateIntegrationConnection(
206
211
  node,
207
- '选择的 Workflow 不能被内部调用',
212
+ asObject(asObject(subject.lookup).request).connectionRef,
213
+ `动态审批人“${String(
214
+ subject.label ?? subject.inputKey ?? '',
215
+ )}”连接`,
208
216
  );
209
- const bindings =
210
- (config as Record<string, unknown>).inputBindings &&
211
- typeof (config as Record<string, unknown>).inputBindings ===
212
- 'object' &&
213
- !Array.isArray((config as Record<string, unknown>).inputBindings)
214
- ? ((config as Record<string, unknown>).inputBindings as Record<
215
- string,
216
- unknown
217
- >)
218
- : {};
219
- const invalidParameter = descriptor.inputParameters.find(
220
- (parameter) =>
221
- (parameter.required || bindings[parameter.key] !== undefined) &&
222
- !validateParameterBinding(bindings[parameter.key]),
217
+ }
218
+ }
219
+ if (nodeType.runtimeKey === 'switch') {
220
+ const error = switchCaseValidationError(
221
+ (config as Record<string, unknown>).cases,
223
222
  );
224
- if (invalidParameter)
223
+ if (error) this.fail('NODE_TYPE_MISMATCH', node, error);
224
+ }
225
+ if (nodeType.runtimeKey === 'db_execute') {
226
+ const databaseConfig = config as Record<string, unknown>;
227
+ const allowWrite = databaseConfig.allowWrite === true;
228
+ const sql = String(databaseConfig.sql ?? '');
229
+ if (!isDatabaseSqlAllowed(sql, allowWrite))
225
230
  this.fail(
226
231
  'NODE_TYPE_MISMATCH',
227
232
  node,
228
- `调用 Workflow 的参数来源无效:${
229
- invalidParameter.label ?? invalidParameter.key
230
- }`,
233
+ allowWrite
234
+ ? '数据库操作只允许单条查询、新增、更新或删除语句'
235
+ : '当前数据库操作节点只允许单条只读查询',
231
236
  );
232
237
  }
233
- if (nodeType.runtimeKey === 'human_approval') {
234
- const approvalWorkflowId = (config as Record<string, unknown>)
235
- ?.approvalWorkflowId;
236
- if (
237
- typeof approvalWorkflowId === 'string' &&
238
- /^[1-9]\d*$/.test(approvalWorkflowId)
239
- ) {
240
- const approvalWorkflow = await this.prisma.workflow.findUnique({
241
- where: { id: BigInt(approvalWorkflowId) },
242
- select: {
243
- isEnabled: true,
244
- status: true,
245
- versions: {
246
- orderBy: { version: 'desc' },
247
- take: 1,
248
- select: { dsl: true },
249
- },
250
- },
251
- });
252
- if (
253
- !approvalWorkflow?.isEnabled ||
254
- approvalWorkflow.status !== 'PUBLISHED'
255
- )
256
- this.fail(
257
- 'NODE_TYPE_MISMATCH',
258
- node,
259
- 'Approval Workflow was not found, published, or enabled',
260
- );
261
- const bindings =
262
- (config as Record<string, unknown>).approvalWorkflowInputBindings &&
263
- typeof (config as Record<string, unknown>)
264
- .approvalWorkflowInputBindings === 'object' &&
265
- !Array.isArray(
266
- (config as Record<string, unknown>).approvalWorkflowInputBindings,
267
- )
268
- ? ((config as Record<string, unknown>)
269
- .approvalWorkflowInputBindings as Record<string, unknown>)
270
- : {};
271
- const missing = describeReturningWorkflowInputs(
272
- approvalWorkflow.versions[0]?.dsl,
273
- ).find((parameter) => parameter.required && !bindings[parameter.key]);
274
- if (missing)
275
- this.fail(
276
- 'NODE_TYPE_MISMATCH',
277
- node,
278
- `审批 Workflow 缺少必填参数:${missing.label ?? missing.key}`,
279
- );
280
- } else if (approvalWorkflowId !== undefined) {
281
- this.fail('NODE_TYPE_MISMATCH', node, 'Approval Workflow ID 无效');
282
- }
283
- const approverSources = Array.isArray(
284
- (config as Record<string, unknown>)?.approverSources,
285
- )
286
- ? ((config as Record<string, unknown>).approverSources as Array<
287
- Record<string, unknown>
288
- >)
289
- : [];
290
- for (const source of approverSources) {
291
- const workflowId = String(source.workflowId ?? '');
292
- if (!/^[1-9]\d*$/.test(workflowId))
293
- this.fail(
294
- 'NODE_TYPE_MISMATCH',
295
- node,
296
- '自动找审批人的 Workflow ID 无效',
297
- );
298
- const workflow = await this.prisma.workflow.findUnique({
299
- where: { id: BigInt(workflowId) },
300
- include: {
301
- versions: {
302
- orderBy: { version: 'desc' },
303
- take: 1,
304
- },
305
- },
306
- });
307
- if (
308
- !workflow ||
309
- workflow.status !== 'PUBLISHED' ||
310
- !workflow.isEnabled
311
- )
312
- this.fail(
313
- 'NODE_TYPE_MISMATCH',
314
- node,
315
- '自动找审批人的 Workflow 未发布或已停用',
316
- );
317
- let descriptor;
318
- try {
319
- descriptor = describeCallableWorkflow(workflow.versions[0]?.dsl);
320
- } catch (error) {
321
- this.fail(
322
- 'NODE_TYPE_MISMATCH',
323
- node,
324
- error instanceof Error
325
- ? error.message
326
- : '自动找审批人的 Workflow 配置无效',
327
- );
328
- }
329
- if (descriptor?.mode !== 'RETURN')
330
- this.fail(
331
- 'NODE_TYPE_MISMATCH',
332
- node,
333
- '选择的 Workflow 没有返回结果',
334
- );
335
- const inputBindings =
336
- source.inputBindings &&
337
- typeof source.inputBindings === 'object' &&
338
- !Array.isArray(source.inputBindings)
339
- ? (source.inputBindings as Record<string, unknown>)
340
- : {};
341
- const missingInput = descriptor.inputParameters.find(
342
- (parameter) =>
343
- parameter.required &&
344
- !validateParameterBinding(inputBindings[parameter.key]),
345
- );
346
- if (missingInput)
347
- this.fail(
348
- 'NODE_TYPE_MISMATCH',
349
- node,
350
- `自动找审批人缺少参数映射:${
351
- missingInput.label ?? missingInput.key
352
- }`,
353
- );
354
- const invalidInput = descriptor.inputParameters.find(
355
- (parameter) =>
356
- inputBindings[parameter.key] !== undefined &&
357
- !validateParameterBinding(inputBindings[parameter.key]),
358
- );
359
- if (invalidInput)
360
- this.fail(
361
- 'NODE_TYPE_MISMATCH',
362
- node,
363
- `自动找审批人的参数来源无效:${
364
- invalidInput.label ?? invalidInput.key
365
- }`,
366
- );
367
- }
238
+ if (nodeType.runtimeKey === 'sub_workflow') {
239
+ await this.validateCallableTarget(
240
+ node,
241
+ (config as Record<string, unknown>).workflowId,
242
+ (config as Record<string, unknown>).workflowVersionId,
243
+ (config as Record<string, unknown>).inputBindings,
244
+ '调用 Workflow',
245
+ );
368
246
  }
369
247
  compiledNodes.push({
370
248
  ...clone(node),
@@ -381,7 +259,6 @@ export class WorkflowCompilerService {
381
259
  } catch (error) {
382
260
  const boundaryNode =
383
261
  draftDsl.nodes.find((node) => node.type === 'callable_trigger') ??
384
- draftDsl.nodes.find((node) => node.type === 'return_result') ??
385
262
  draftDsl.nodes[0];
386
263
  this.fail(
387
264
  'NODE_TYPE_MISMATCH',
@@ -390,25 +267,151 @@ export class WorkflowCompilerService {
390
267
  );
391
268
  }
392
269
  }
270
+ return compiledDsl;
271
+ }
272
+
273
+ private async validateCallableTarget(
274
+ node: DraftWorkflowNode,
275
+ workflowIdValue: unknown,
276
+ workflowVersionIdValue: unknown,
277
+ inputBindingsValue: unknown,
278
+ label: string,
279
+ ): Promise<void> {
280
+ const workflowId = String(workflowIdValue ?? '');
281
+ if (!/^[1-9]\d*$/.test(workflowId))
282
+ this.fail('NODE_TYPE_MISMATCH', node, `${label} ID 无效`);
283
+ const workflowVersionId = String(workflowVersionIdValue ?? '');
284
+ if (!/^[1-9]\d*$/.test(workflowVersionId))
285
+ this.fail('NODE_TYPE_MISMATCH', node, `${label}版本 ID 无效`);
286
+ const workflow = await this.prisma.workflow.findUnique({
287
+ where: { id: BigInt(workflowId) },
288
+ select: {
289
+ isEnabled: true,
290
+ versions: {
291
+ where: { id: BigInt(workflowVersionId) },
292
+ take: 1,
293
+ select: { dsl: true },
294
+ },
295
+ },
296
+ });
297
+ if (!workflow?.isEnabled)
298
+ this.fail('NODE_TYPE_MISMATCH', node, `${label} 不存在或已停用`);
299
+ if (!workflow.versions[0])
300
+ this.fail(
301
+ 'NODE_TYPE_MISMATCH',
302
+ node,
303
+ `${label}版本不存在、未发布或不属于所选 Workflow`,
304
+ );
305
+
306
+ let descriptor;
393
307
  try {
394
- validateWebhookResponseWorkflow(compiledDsl);
308
+ descriptor = describeCallableWorkflow(workflow.versions[0]?.dsl);
395
309
  } catch (error) {
396
- const boundaryNode =
397
- draftDsl.nodes.find(
398
- (node) =>
399
- node.type === 'webhook_trigger' &&
400
- (node.config as Record<string, unknown> | undefined)
401
- ?.responseMode === 'WAIT_FOR_RESULT',
402
- ) ??
403
- draftDsl.nodes.find((node) => node.type === 'return_result') ??
404
- draftDsl.nodes[0];
405
310
  this.fail(
406
311
  'NODE_TYPE_MISMATCH',
407
- boundaryNode,
408
- error instanceof Error ? error.message : 'HTTP 返回配置无效',
312
+ node,
313
+ error instanceof Error ? error.message : `${label} 配置无效`,
409
314
  );
410
315
  }
411
- return compiledDsl;
316
+ if (!descriptor)
317
+ this.fail('NODE_TYPE_MISMATCH', node, `${label} 不能被内部调用`);
318
+
319
+ await this.assertNoInvocationCycle(
320
+ BigInt(workflowId),
321
+ BigInt(workflowVersionId),
322
+ workflow.versions[0]?.dsl,
323
+ node,
324
+ label,
325
+ );
326
+
327
+ const bindings = asObject(inputBindingsValue);
328
+ const declaredKeys = new Set(
329
+ descriptor.inputParameters.map((parameter) => parameter.key),
330
+ );
331
+ const extraParameter = Object.keys(bindings).find(
332
+ (key) => !declaredKeys.has(key),
333
+ );
334
+ if (extraParameter)
335
+ this.fail(
336
+ 'NODE_TYPE_MISMATCH',
337
+ node,
338
+ `${label} 包含未声明的参数:${extraParameter}`,
339
+ );
340
+ const invalidParameter = descriptor.inputParameters.find(
341
+ (parameter) =>
342
+ (parameter.required || bindings[parameter.key] !== undefined) &&
343
+ !validateParameterBinding(bindings[parameter.key]),
344
+ );
345
+ if (invalidParameter)
346
+ this.fail(
347
+ 'NODE_TYPE_MISMATCH',
348
+ node,
349
+ `${label} 的参数来源无效:${
350
+ invalidParameter.label ?? invalidParameter.key
351
+ }`,
352
+ );
353
+ }
354
+
355
+ private async validateIntegrationConnection(
356
+ node: DraftWorkflowNode,
357
+ connectionRefValue: unknown,
358
+ label: string,
359
+ ): Promise<void> {
360
+ const connection =
361
+ typeof connectionRefValue === 'string'
362
+ ? await this.prisma.integrationConnection.findUnique({
363
+ where: { code: connectionRefValue },
364
+ select: { isEnabled: true },
365
+ })
366
+ : null;
367
+ if (!connection?.isEnabled)
368
+ this.fail('NODE_TYPE_MISMATCH', node, `${label}不存在或已停用`);
369
+ }
370
+
371
+ private async assertNoInvocationCycle(
372
+ targetWorkflowId: bigint,
373
+ targetWorkflowVersionId: bigint,
374
+ targetDsl: unknown,
375
+ node: DraftWorkflowNode,
376
+ label: string,
377
+ active = new Set<string>(),
378
+ visited = new Set<string>(),
379
+ ): Promise<void> {
380
+ const targetKey = `${targetWorkflowId}:${targetWorkflowVersionId}`;
381
+ if (active.has(targetKey))
382
+ this.fail(
383
+ 'NODE_TYPE_MISMATCH',
384
+ node,
385
+ `${label} 的固定版本调用链存在循环`,
386
+ );
387
+ if (visited.has(targetKey)) return;
388
+ active.add(targetKey);
389
+
390
+ for (const referenced of collectInvokedWorkflows(targetDsl)) {
391
+ const referencedKey = `${referenced.workflowId}:${referenced.workflowVersionId}`;
392
+ if (visited.has(referencedKey) && !active.has(referencedKey)) continue;
393
+ const referencedWorkflow = await this.prisma.workflow.findUnique({
394
+ where: { id: referenced.workflowId },
395
+ select: {
396
+ versions: {
397
+ where: { id: referenced.workflowVersionId },
398
+ take: 1,
399
+ select: { dsl: true },
400
+ },
401
+ },
402
+ });
403
+ await this.assertNoInvocationCycle(
404
+ referenced.workflowId,
405
+ referenced.workflowVersionId,
406
+ referencedWorkflow?.versions[0]?.dsl,
407
+ node,
408
+ label,
409
+ active,
410
+ visited,
411
+ );
412
+ }
413
+ active.delete(targetKey);
414
+ visited.add(targetKey);
412
415
  }
413
416
 
414
417
  private fail(
@@ -416,8 +419,39 @@ export class WorkflowCompilerService {
416
419
  node: DraftWorkflowNode,
417
420
  message: string,
418
421
  ): never {
419
- throw new BadRequestException({ code, message, nodeId: node.id });
422
+ const nodeLabel = String(node.label ?? '').trim();
423
+ throw new BadRequestException({
424
+ code,
425
+ message,
426
+ ...(nodeLabel && { nodeLabel }),
427
+ nodeId: node.id,
428
+ });
429
+ }
430
+ }
431
+
432
+ function collectInvokedWorkflows(
433
+ dsl: unknown,
434
+ ): Array<{ workflowId: bigint; workflowVersionId: bigint }> {
435
+ const value = asObject(dsl);
436
+ const nodes = Array.isArray(value.nodes) ? value.nodes : [];
437
+ const result = new Map<
438
+ string,
439
+ { workflowId: bigint; workflowVersionId: bigint }
440
+ >();
441
+ for (const item of nodes) {
442
+ const node = asObject(item);
443
+ const config = asObject(node.config);
444
+ if (node.type !== 'sub_workflow') continue;
445
+ const workflowId = String(config.workflowId ?? '');
446
+ const workflowVersionId = String(config.workflowVersionId ?? '');
447
+ if (!/^[1-9]\d*$/.test(workflowId) || !/^[1-9]\d*$/.test(workflowVersionId))
448
+ continue;
449
+ result.set(`${workflowId}:${workflowVersionId}`, {
450
+ workflowId: BigInt(workflowId),
451
+ workflowVersionId: BigInt(workflowVersionId),
452
+ });
420
453
  }
454
+ return [...result.values()];
421
455
  }
422
456
 
423
457
  function parseId(value: string, node: DraftWorkflowNode): bigint {
@@ -433,3 +467,142 @@ function parseId(value: string, node: DraftWorkflowNode): bigint {
433
467
  function clone<T>(value: T): T {
434
468
  return JSON.parse(JSON.stringify(value)) as T;
435
469
  }
470
+
471
+ function isSingleReadOnlySql(sql: string): boolean {
472
+ const normalized = normalizeSqlForPolicy(sql);
473
+ if (!/^(select|with)\b/i.test(normalized)) return false;
474
+ return !/\b(insert|update|delete|merge|call|copy|create|alter|drop|truncate|grant|revoke|vacuum|refresh)\b/i.test(
475
+ normalized,
476
+ );
477
+ }
478
+
479
+ function isDatabaseSqlAllowed(sql: string, allowWrite: boolean): boolean {
480
+ const normalized = normalizeSqlForPolicy(sql);
481
+ const writableCte =
482
+ /^with\b/i.test(normalized) &&
483
+ /\b(insert|update|delete)\b/i.test(normalized) &&
484
+ !/\b(merge|call|copy|create|alter|drop|truncate|grant|revoke|vacuum|refresh)\b/i.test(
485
+ normalized,
486
+ );
487
+ return (
488
+ isSingleReadOnlySql(sql) ||
489
+ (allowWrite &&
490
+ (/^(insert|update|delete)\b/i.test(normalized) || writableCte))
491
+ );
492
+ }
493
+
494
+ function normalizeSqlForPolicy(sql: string): string {
495
+ const withoutContent = sql
496
+ .replace(/\$(\w*)\$[\s\S]*?\$\1\$/g, ' ')
497
+ .replace(/'(?:''|[^'])*'/g, ' ')
498
+ .replace(/"(?:""|[^"])*"/g, ' ')
499
+ .replace(/\/\*[\s\S]*?\*\//g, ' ')
500
+ .replace(/--[^\r\n]*/g, ' ')
501
+ .trim();
502
+ const withoutTrailingSemicolon = withoutContent.replace(/;\s*$/, '').trim();
503
+ return withoutTrailingSemicolon.includes(';') ? '' : withoutTrailingSemicolon;
504
+ }
505
+
506
+ function asObject(value: unknown): Record<string, unknown> {
507
+ return value && typeof value === 'object' && !Array.isArray(value)
508
+ ? (value as Record<string, unknown>)
509
+ : {};
510
+ }
511
+
512
+ function nodeConfigValidationErrors(
513
+ error: unknown,
514
+ ): NodeConfigValidationError[] | null {
515
+ const getResponse = (error as { getResponse?: () => unknown })?.getResponse;
516
+ if (typeof getResponse !== 'function') return null;
517
+ const response = getResponse.call(error);
518
+ if (!response || typeof response !== 'object' || Array.isArray(response))
519
+ return null;
520
+ const value = response as Record<string, unknown>;
521
+ if (value.code !== 'NODE_CONFIG_INVALID' || !Array.isArray(value.errors))
522
+ return null;
523
+ return value.errors.filter(
524
+ (item): item is NodeConfigValidationError =>
525
+ Boolean(item) &&
526
+ typeof item === 'object' &&
527
+ typeof (item as NodeConfigValidationError).path === 'string' &&
528
+ typeof (item as NodeConfigValidationError).keyword === 'string' &&
529
+ typeof (item as NodeConfigValidationError).message === 'string',
530
+ );
531
+ }
532
+
533
+ function subjectValidationErrors(
534
+ error: unknown,
535
+ ): NodeConfigValidationError[] | null {
536
+ const getResponse = (error as { getResponse?: () => unknown })?.getResponse;
537
+ if (typeof getResponse !== 'function') return null;
538
+ const response = getResponse.call(error);
539
+ if (!response || typeof response !== 'object' || Array.isArray(response))
540
+ return null;
541
+ const value = response as Record<string, unknown>;
542
+ if (value.code !== 'SUBJECT_REF_INVALID' || !Array.isArray(value.issues))
543
+ return null;
544
+ return value.issues.flatMap((item) => {
545
+ if (!item || typeof item !== 'object' || Array.isArray(item)) return [];
546
+ const issue = item as Record<string, unknown>;
547
+ if (typeof issue.path !== 'string' || typeof issue.message !== 'string')
548
+ return [];
549
+ return [
550
+ {
551
+ path: issue.path,
552
+ keyword:
553
+ typeof issue.code === 'string' ? issue.code : 'INVALID_SUBJECT',
554
+ message: issue.message,
555
+ },
556
+ ];
557
+ });
558
+ }
559
+
560
+ function findInvalidParameterBinding(
561
+ value: unknown,
562
+ path = 'config',
563
+ ): string | null {
564
+ if (Array.isArray(value)) {
565
+ for (let index = 0; index < value.length; index++) {
566
+ const invalid = findInvalidParameterBinding(
567
+ value[index],
568
+ `${path}[${index}]`,
569
+ );
570
+ if (invalid) return invalid;
571
+ }
572
+ return null;
573
+ }
574
+ if (!value || typeof value !== 'object') return null;
575
+
576
+ const object = value as Record<string, unknown>;
577
+ const isBindingCandidate =
578
+ Object.prototype.hasOwnProperty.call(object, 'source') &&
579
+ (Object.prototype.hasOwnProperty.call(object, 'path') ||
580
+ Object.prototype.hasOwnProperty.call(object, 'valueType') ||
581
+ Object.prototype.hasOwnProperty.call(object, 'value'));
582
+ if (isBindingCandidate && !validateParameterBinding(object)) return path;
583
+
584
+ for (const [key, child] of Object.entries(object)) {
585
+ if (['body', 'inputSchema'].includes(key)) continue;
586
+ const invalid = findInvalidParameterBinding(child, `${path}.${key}`);
587
+ if (invalid) return invalid;
588
+ }
589
+ return null;
590
+ }
591
+
592
+ function validateManualInputParameters(
593
+ config: Record<string, unknown>,
594
+ ): string | null {
595
+ if (!Array.isArray(config.inputParameters)) return null;
596
+ const seen = new Set<string>();
597
+ for (const [index, item] of config.inputParameters.entries()) {
598
+ const parameter =
599
+ item && typeof item === 'object' && !Array.isArray(item)
600
+ ? (item as Record<string, unknown>)
601
+ : {};
602
+ const key = typeof parameter.key === 'string' ? parameter.key.trim() : '';
603
+ if (!key) return `启动参数 ${index + 1} 的参数名不能为空`;
604
+ if (seen.has(key)) return `启动参数名不能重复:${key}`;
605
+ seen.add(key);
606
+ }
607
+ return null;
608
+ }