@gadmin2n/schematics 0.0.139 → 0.0.141

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 (329) hide show
  1. package/dist/lib/application/files/gadmin2-game-angle-demo/Jenkinsfile +6 -34
  2. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/approval.prisma +199 -0
  3. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/system.prisma +9 -0
  4. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +191 -14
  5. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Event.ts +1 -1
  6. package/dist/lib/application/files/gadmin2-game-angle-demo/gitignore +6 -5
  7. package/dist/lib/application/files/gadmin2-game-angle-demo/readme.md +10 -3
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/server/migrate-between-pg-schemas.js +6 -4
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +5 -2
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/server/prisma.config.ts +12 -3
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/gen-jwt.ts +8 -1
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/migrate-human-approval-configs.ts +86 -0
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-node-types.ts +710 -121
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow.seed.ts +125 -10
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/config/index.ts +28 -0
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/json-body-parser.spec.ts +61 -0
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/json-body-parser.ts +7 -0
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/structured-all-exceptions.filter.spec.ts +54 -0
  19. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/structured-all-exceptions.filter.ts +86 -0
  20. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/main.ts +9 -3
  21. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/approvalChannel/approval-channel.controller.ts +89 -0
  22. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/approvalChannel/approval-channel.dto.ts +68 -0
  23. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/approvalChannel/approval-channel.service.spec.ts +177 -0
  24. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/approvalChannel/approval-channel.service.ts +283 -0
  25. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/approvalChannel/approvalChannel.module.ts +10 -0
  26. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-executor.spec.ts +42 -0
  27. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-executor.ts +108 -0
  28. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-runtime.controller.ts +101 -0
  29. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/code-runtime.dto.ts +29 -0
  30. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/codeRuntime/codeRuntime.module.ts +21 -0
  31. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-handler.registry.ts +30 -0
  32. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-handler.ts +15 -0
  33. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-runtime.controller.spec.ts +105 -0
  34. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-runtime.controller.ts +96 -0
  35. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-runtime.dto.ts +78 -0
  36. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-signal-outbox.service.spec.ts +56 -0
  37. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-signal-outbox.service.ts +111 -0
  38. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-token.spec.ts +23 -0
  39. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction-token.ts +18 -0
  40. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction.service.spec.ts +240 -0
  41. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction.service.ts +339 -0
  42. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-interaction.types.ts +74 -0
  43. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/external-wait.handler.ts +47 -0
  44. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/externalInteraction.module.ts +41 -0
  45. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/human-approval.handler.spec.ts +70 -0
  46. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/human-approval.handler.ts +76 -0
  47. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/workflow-callback-url.controller.ts +12 -0
  48. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/workflow-callback-url.service.spec.ts +227 -0
  49. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/externalInteraction/workflow-callback-url.service.ts +121 -0
  50. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.controller.ts +160 -0
  51. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.dto.ts +41 -0
  52. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.util.spec.ts +171 -0
  53. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/http-request-runtime.util.ts +245 -0
  54. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/httpRequest/httpRequest.module.ts +22 -0
  55. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-rule-evaluator.spec.ts +68 -0
  56. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-rule-evaluator.ts +126 -0
  57. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-rule.types.ts +34 -0
  58. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-signal-outbox.service.ts +115 -0
  59. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-subject-source.util.spec.ts +45 -0
  60. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/approval-subject-source.util.ts +59 -0
  61. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.controller.ts +72 -0
  62. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.dto.ts +144 -0
  63. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.errors.ts +19 -0
  64. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.external-decision.spec.ts +350 -0
  65. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/human-approval.service.ts +774 -0
  66. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/humanApproval.module.ts +46 -0
  67. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/legacy-approval-config-migration.ts +227 -0
  68. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/outbox-retry.util.ts +14 -0
  69. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/human-approval-runtime.controller.ts +151 -0
  70. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/human-approval-runtime.dto.ts +88 -0
  71. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/humanApproval/runtime/runtime-token.guard.ts +43 -0
  72. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/index.ts +21 -1
  73. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-connection.controller.ts +77 -0
  74. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-connection.dto.ts +98 -0
  75. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-connection.service.ts +277 -0
  76. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-secret-cipher.spec.ts +14 -0
  77. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integration-secret-cipher.ts +59 -0
  78. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/integrationConnection/integrationConnection.module.ts +10 -0
  79. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/subjectProvider/actor-context.util.ts +27 -0
  80. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/subjectProvider/providers/user-group.provider.ts +208 -0
  81. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/subjectProvider/providers/user.provider.ts +168 -0
  82. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/subjectProvider/subject-provider.controller.spec.ts +157 -0
  83. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/subjectProvider/subject-provider.controller.ts +176 -0
  84. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/subjectProvider/subject-provider.dto.ts +21 -0
  85. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/subjectProvider/subject-provider.errors.ts +78 -0
  86. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/subjectProvider/subject-provider.registry.spec.ts +100 -0
  87. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/subjectProvider/subject-provider.registry.ts +115 -0
  88. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/subjectProvider/subject-provider.types.ts +97 -0
  89. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/subjectProvider/subjectProvider.module.ts +34 -0
  90. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.controller.spec.ts +89 -1
  91. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.controller.ts +4 -0
  92. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/user-group.controller.ts +119 -0
  93. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/user-group.dto.ts +91 -0
  94. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/user-group.errors.ts +34 -0
  95. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/user-group.service.spec.ts +161 -0
  96. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/user-group.service.ts +390 -0
  97. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/userGroup/userGroup.module.ts +10 -0
  98. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/dsl-validate.util.spec.ts +17 -0
  99. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/dsl-validate.util.ts +8 -2
  100. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/parameter-binding.ts +93 -0
  101. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.service.spec.ts +34 -1
  102. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.service.ts +26 -0
  103. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-callable.spec.ts +158 -0
  104. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-callable.ts +155 -0
  105. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.service.spec.ts +512 -0
  106. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.service.ts +368 -0
  107. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-compiler.types.ts +43 -0
  108. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-data-edge.util.spec.ts +174 -0
  109. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-data-edge.util.ts +149 -0
  110. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-dsl-comparison.ts +43 -0
  111. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-execution.dto.ts +1 -1
  112. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.dto.ts +4 -0
  113. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.service.ts +70 -28
  114. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-handle-validator.ts +128 -0
  115. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-http-response.spec.ts +85 -0
  116. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-http-response.ts +157 -0
  117. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.spec.ts +59 -0
  118. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +27 -5
  119. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.module.ts +18 -3
  120. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.spec.ts +493 -21
  121. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +426 -90
  122. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/node-config-validator.service.spec.ts +79 -0
  123. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/node-config-validator.service.ts +62 -0
  124. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/schema.types.ts +10 -0
  125. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/subject-config-validator.service.spec.ts +124 -0
  126. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/subject-config-validator.service.ts +236 -0
  127. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/widget-catalog.service.spec.ts +49 -0
  128. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/widget-catalog.service.ts +69 -0
  129. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowConfig/workflowConfig.module.ts +20 -0
  130. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/node-instance-config.util.spec.ts +15 -0
  131. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/node-instance-config.util.ts +25 -0
  132. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.controller.ts +103 -11
  133. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.dto.ts +98 -0
  134. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.module.ts +3 -0
  135. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.spec.ts +72 -62
  136. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.ts +148 -11
  137. package/dist/lib/application/files/gadmin2-game-angle-demo/web/package.json +13 -9
  138. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/App.tsx +5 -2
  139. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/authProvider.ts +2 -2
  140. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/BulkActions.tsx +0 -5
  141. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/PageHeader.tsx +46 -0
  142. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/SearchBar.tsx +26 -18
  143. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/components/eventList/index.tsx +2 -2
  144. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/components/logButton/index.tsx +24 -17
  145. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/components/logList/index.tsx +7 -18
  146. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/components/modalDiffViewer/index.tsx +2 -2
  147. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/contexts/color-mode/index.tsx +288 -33
  148. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/contexts/color-mode/themeStyles.ts +97 -0
  149. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/index.ts +1 -0
  150. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/SettingDrawer.tsx +251 -0
  151. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/header.tsx +47 -19
  152. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/layout.tsx +18 -9
  153. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/menuRenderer.tsx +155 -0
  154. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/sider.tsx +123 -129
  155. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.test.ts +10 -0
  156. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +18 -0
  157. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/constants/layout.ts +32 -3
  158. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/AddDataModal.tsx +98 -3
  159. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/AddPageModal.tsx +101 -0
  160. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DevShell.tsx +8 -0
  161. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/style.css +51 -0
  162. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/form.tsx +1 -1
  163. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/list.tsx +1 -1
  164. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/login.ts +40 -1
  165. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/show.tsx +5 -5
  166. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useDynamicResources.tsx +16 -1
  167. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useListPageState.ts +10 -7
  168. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/i18n.ts +4 -2
  169. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +26 -2
  170. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/workflow.json +575 -0
  171. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +26 -2
  172. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/workflow.json +575 -0
  173. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/plugins/devShellPlugin.ts +152 -2
  174. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/index.tsx +9 -15
  175. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/show.tsx +41 -9
  176. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/edit.tsx +1 -1
  177. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/list.tsx +10 -8
  178. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/show.tsx +3 -3
  179. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/components/action-cell.css +1 -1
  180. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/edit.tsx +1 -1
  181. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/list.tsx +141 -138
  182. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/show.tsx +3 -6
  183. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasCell.css +3 -0
  184. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasCell.tsx +45 -13
  185. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasComponentLibrary.tsx +45 -22
  186. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasListPage.tsx +175 -119
  187. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasPage.tsx +248 -74
  188. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasToolbar.tsx +33 -18
  189. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CodeFloatWindow.tsx +16 -10
  190. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/PublishModal.tsx +1 -1
  191. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasContextMenuRegistry.tsx +31 -0
  192. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasDefaults.ts +15 -0
  193. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/BarChartDataSourceModal.tsx +16 -11
  194. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/CanvasAiModal.tsx +25 -21
  195. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/ExportModal.tsx +6 -1
  196. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/LineChartDataSourceModal.tsx +9 -10
  197. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/MultiChartConfigModal.tsx +4 -7
  198. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/MultiChartDataSourceModal.tsx +23 -9
  199. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/NumCardDataSourceModal.tsx +16 -11
  200. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/PromptModal.tsx +2 -5
  201. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/RadarChartDataSourceModal.tsx +16 -11
  202. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/TableConfigModal.tsx +2 -9
  203. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/TableDataSourceModal.tsx +23 -12
  204. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/canvasModalProps.ts +2 -17
  205. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/sectionCompactor.test.ts +149 -0
  206. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/sectionCompactor.ts +111 -17
  207. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/types.ts +1 -0
  208. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/whiteboardLayout.test.ts +83 -0
  209. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/whiteboardLayout.ts +118 -0
  210. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/whiteboardName.test.ts +26 -0
  211. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas-page/index.tsx +9 -1
  212. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/edit.tsx +1 -1
  213. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/list.tsx +10 -8
  214. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/show.tsx +3 -6
  215. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/human-approval/DecisionModal.tsx +71 -0
  216. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/human-approval/inbox.tsx +209 -0
  217. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/AssignRolesModal.tsx +6 -1
  218. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/list.tsx +47 -150
  219. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/permissionReadme/index.tsx +21 -20
  220. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/modal.tsx +1 -1
  221. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/list.tsx +115 -118
  222. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/modal.tsx +1 -1
  223. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/list.tsx +61 -64
  224. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/show-drawer.tsx +1 -1
  225. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/list.tsx +187 -200
  226. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/approval-channels/ApprovalChannelModal.test.tsx +84 -0
  227. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/approval-channels/ApprovalChannelModal.tsx +141 -0
  228. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/approval-channels/approval-channel.types.ts +16 -0
  229. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/approval-channels/index.tsx +210 -0
  230. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CreateNodeInstanceDrawer.tsx +154 -0
  231. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CustomNode.tsx +194 -5
  232. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/DeletableEdge.tsx +76 -0
  233. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/DslView.tsx +1 -1
  234. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/EnhancedFlowRenderer.tsx +176 -22
  235. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExecutionStatusNode.test.tsx +62 -0
  236. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExecutionStatusNode.tsx +94 -5
  237. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExportModal.tsx +15 -10
  238. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/FlowRenderer.tsx +251 -70
  239. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ImportModal.tsx +18 -24
  240. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/InstanceRequiredDialog.tsx +106 -0
  241. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/LookupConnectionDialog.test.tsx +45 -0
  242. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/LookupConnectionDialog.tsx +43 -0
  243. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NewNodeDefaults.test.tsx +283 -0
  244. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeEditModal.tsx +6 -7
  245. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.test.tsx +335 -0
  246. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.tsx +433 -237
  247. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ParameterBindingEditor.tsx +179 -0
  248. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/RunWorkflowModal.tsx +18 -16
  249. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/StatusCards.tsx +20 -16
  250. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/VersionPanel.tsx +6 -4
  251. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/ConnectionModal.test.tsx +68 -0
  252. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/ConnectionModal.tsx +367 -0
  253. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/connection.types.ts +21 -0
  254. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/connections/index.tsx +180 -0
  255. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/editor.tsx +38 -22
  256. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useNodeInstanceLibrary.ts +41 -0
  257. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useWorkflowAgent.ts +6 -0
  258. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/index.tsx +29 -35
  259. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.tsx +8 -11
  260. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instances.tsx +4 -3
  261. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/NodeInstanceForm.tsx +56 -23
  262. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/create.tsx +21 -6
  263. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/edit.tsx +17 -20
  264. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/index.tsx +9 -17
  265. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/SchemaField.tsx +311 -0
  266. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/SchemaForm.test.tsx +218 -0
  267. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/SchemaForm.tsx +83 -0
  268. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/default-widgets.tsx +135 -0
  269. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/schema-defaults.ts +36 -0
  270. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/schema.types.ts +32 -0
  271. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/widget-registry.test.tsx +23 -0
  272. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/schema-form/widget-registry.tsx +52 -0
  273. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/show.tsx +9 -13
  274. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApprovalRequestTriggerConfigEditor.tsx +39 -0
  275. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApprovalRuleEditor.test.tsx +20 -0
  276. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApprovalRuleEditor.tsx +72 -0
  277. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApproverSourceEditor.test.tsx +47 -0
  278. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ApproverSourceEditor.tsx +185 -0
  279. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/CallableInputParametersEditor.test.tsx +102 -0
  280. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/CallableInputParametersEditor.tsx +150 -0
  281. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/CodeConfigEditor.tsx +103 -0
  282. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ExternalRequestConfigEditor.test.tsx +135 -0
  283. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ExternalRequestConfigEditor.tsx +273 -0
  284. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ExternalWaitConfigEditor.tsx +303 -0
  285. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HttpRequestConfigEditor.test.tsx +189 -0
  286. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HttpRequestConfigEditor.tsx +706 -0
  287. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HumanApprovalConfigEditor.test.tsx +86 -0
  288. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/HumanApprovalConfigEditor.tsx +458 -0
  289. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ReturnResultConfigEditor.test.tsx +81 -0
  290. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/ReturnResultConfigEditor.tsx +281 -0
  291. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubjectPicker.test.tsx +61 -0
  292. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubjectPicker.tsx +266 -0
  293. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubmitApprovalResultConfigEditor.tsx +104 -0
  294. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/SubmitExternalResultConfigEditor.tsx +98 -0
  295. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/UserGroupCreateModal.tsx +70 -0
  296. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/UserGroupEditModal.tsx +138 -0
  297. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/approver-source.test.ts +25 -0
  298. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/approver-source.ts +42 -0
  299. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/widgets/subject-provider.api.ts +95 -0
  300. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/show.tsx +15 -11
  301. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/temporal-tenant/index.test.tsx +152 -0
  302. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/temporal-tenant/index.tsx +438 -141
  303. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/types/parameter-binding.ts +49 -0
  304. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/types.ts +31 -2
  305. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/lookupConnection.test.ts +208 -0
  306. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/lookupConnection.ts +246 -0
  307. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/newNodeConfig.ts +77 -0
  308. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/removeWorkflowEdges.test.ts +34 -0
  309. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/removeWorkflowEdges.ts +18 -0
  310. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveLookupPorts.ts +66 -0
  311. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveOutputs.test.ts +39 -0
  312. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveOutputs.ts +48 -0
  313. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveWorkflowDisplay.test.ts +51 -0
  314. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/utils/resolveWorkflowDisplay.ts +32 -0
  315. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/edit.tsx +1 -1
  316. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/list.tsx +10 -8
  317. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/show.tsx +3 -3
  318. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/antd-theme-vars.css +93 -0
  319. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/antd.css +8 -8
  320. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/fc.css +4 -4
  321. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/index.css +40 -5
  322. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/show-drawer.module.css +3 -3
  323. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/show-page.module.css +3 -3
  324. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/theme-styles.css +81 -0
  325. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/test/setup.ts +5 -0
  326. package/dist/lib/application/files/gadmin2-game-angle-demo/web/vite.config.ts +1 -7
  327. package/dist/lib/application/files/gadmin2-game-angle-demo/web/vitest.config.ts +12 -0
  328. package/package.json +1 -1
  329. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/DynamicConfigForm.tsx +0 -154
@@ -0,0 +1,68 @@
1
+ import {
2
+ evaluateRules,
3
+ evaluateRulesDetailed,
4
+ } from './approval-rule-evaluator';
5
+ import { ApprovalRuleEvaluationInput } from './approval-rule.types';
6
+
7
+ const base = (candidateCount = 4): ApprovalRuleEvaluationInput => ({
8
+ candidateCount,
9
+ decisions: [],
10
+ approvalRule: { mode: 'ANY' },
11
+ rejectionRule: { mode: 'ANY' },
12
+ });
13
+
14
+ describe('approval rule evaluator', () => {
15
+ it.each([
16
+ [{ mode: 'ANY' } as const, 1, 4],
17
+ [{ mode: 'ALL' } as const, 4, 4],
18
+ [{ mode: 'COUNT', count: 2 } as const, 2, 4],
19
+ [{ mode: 'PERCENTAGE', percentage: 75 } as const, 3, 4],
20
+ ])(
21
+ 'approves when the %s threshold is reached',
22
+ (approvalRule, count, total) => {
23
+ expect(
24
+ evaluateRules({
25
+ ...base(total),
26
+ approvalRule,
27
+ decisions: Array.from({ length: count }, (_, index) => ({
28
+ principalRef: `user-${index}`,
29
+ decision: 'APPROVE' as const,
30
+ })),
31
+ }),
32
+ ).toBe('APPROVED');
33
+ },
34
+ );
35
+
36
+ it('blocks without candidates and gives rejection precedence', () => {
37
+ expect(evaluateRules(base(0))).toBe('BLOCKED');
38
+ expect(
39
+ evaluateRules({
40
+ ...base(2),
41
+ decisions: [
42
+ { principalRef: 'alice', decision: 'APPROVE' },
43
+ { principalRef: 'bob', decision: 'REJECT' },
44
+ ],
45
+ }),
46
+ ).toBe('REJECTED');
47
+ });
48
+
49
+ it('ignores inactive decisions, deduplicates principals, and warns on an impossible COUNT', () => {
50
+ const result = evaluateRulesDetailed({
51
+ ...base(2),
52
+ approvalRule: { mode: 'COUNT', count: 3 },
53
+ rejectionRule: { mode: 'ALL' },
54
+ decisions: [
55
+ { principalRef: 'alice', decision: 'APPROVE' },
56
+ { principalRef: 'alice', decision: 'APPROVE' },
57
+ { principalRef: 'bob', decision: 'APPROVE', active: false },
58
+ ],
59
+ });
60
+
61
+ expect(result).toMatchObject({
62
+ status: 'PENDING',
63
+ approvalCount: 1,
64
+ rejectionCount: 0,
65
+ });
66
+ expect(result.warnings).toHaveLength(1);
67
+ });
68
+ });
@@ -0,0 +1,126 @@
1
+ import {
2
+ ApprovalRule,
3
+ ApprovalRuleEvaluation,
4
+ ApprovalRuleEvaluationInput,
5
+ ApprovalRuleStatus,
6
+ } from './approval-rule.types';
7
+
8
+ export function evaluateRules(
9
+ input: ApprovalRuleEvaluationInput,
10
+ ): ApprovalRuleStatus {
11
+ return evaluateRulesDetailed(input).status;
12
+ }
13
+
14
+ export function evaluateRulesDetailed(
15
+ input: ApprovalRuleEvaluationInput,
16
+ ): ApprovalRuleEvaluation {
17
+ const candidateCount = assertCandidateCount(input.candidateCount);
18
+ if (candidateCount === 0) {
19
+ return {
20
+ status: 'BLOCKED',
21
+ warnings: [],
22
+ approvalCount: 0,
23
+ rejectionCount: 0,
24
+ };
25
+ }
26
+
27
+ // A principal contributes at most once. If inconsistent duplicate records
28
+ // exist, REJECT wins so corrupted input cannot accidentally approve work.
29
+ const decisions = new Map<string, 'APPROVE' | 'REJECT'>();
30
+ for (const decision of input.decisions) {
31
+ if (decision.active === false || !decision.principalRef) continue;
32
+ const current = decisions.get(decision.principalRef);
33
+ if (!current || decision.decision === 'REJECT') {
34
+ decisions.set(decision.principalRef, decision.decision);
35
+ }
36
+ }
37
+
38
+ let approvalCount = 0;
39
+ let rejectionCount = 0;
40
+ for (const decision of decisions.values()) {
41
+ if (decision === 'APPROVE') approvalCount += 1;
42
+ else rejectionCount += 1;
43
+ }
44
+
45
+ const warnings: string[] = [];
46
+ const rejected = thresholdReached(
47
+ input.rejectionRule,
48
+ rejectionCount,
49
+ candidateCount,
50
+ warnings,
51
+ 'rejection',
52
+ );
53
+ const approved = thresholdReached(
54
+ input.approvalRule,
55
+ approvalCount,
56
+ candidateCount,
57
+ warnings,
58
+ 'approval',
59
+ );
60
+
61
+ return {
62
+ status: rejected ? 'REJECTED' : approved ? 'APPROVED' : 'PENDING',
63
+ warnings,
64
+ approvalCount,
65
+ rejectionCount,
66
+ };
67
+ }
68
+
69
+ function thresholdReached(
70
+ rule: ApprovalRule,
71
+ decisionCount: number,
72
+ candidateCount: number,
73
+ warnings: string[],
74
+ label: string,
75
+ ): boolean {
76
+ switch (rule.mode) {
77
+ case 'ANY':
78
+ return decisionCount >= 1;
79
+ case 'ALL':
80
+ return decisionCount >= candidateCount;
81
+ case 'COUNT': {
82
+ const count = assertPositiveInteger(rule.count, `${label} count`);
83
+ if (count > candidateCount) {
84
+ warnings.push(
85
+ `${label} COUNT threshold ${count} exceeds candidate count ${candidateCount}`,
86
+ );
87
+ }
88
+ return decisionCount >= count;
89
+ }
90
+ case 'PERCENTAGE': {
91
+ const percentage = assertPercentage(rule.percentage, label);
92
+ return decisionCount * 100 >= percentage * candidateCount;
93
+ }
94
+ }
95
+ }
96
+
97
+ function assertCandidateCount(value: number): number {
98
+ if (!Number.isSafeInteger(value) || value < 0) {
99
+ throw new Error('candidateCount must be a non-negative integer');
100
+ }
101
+ return value;
102
+ }
103
+
104
+ function assertPositiveInteger(
105
+ value: number | undefined,
106
+ label: string,
107
+ ): number {
108
+ if (!Number.isSafeInteger(value) || Number(value) < 1) {
109
+ throw new Error(`${label} must be a positive integer`);
110
+ }
111
+ return Number(value);
112
+ }
113
+
114
+ function assertPercentage(value: number | undefined, label: string): number {
115
+ if (
116
+ typeof value !== 'number' ||
117
+ !Number.isFinite(value) ||
118
+ value <= 0 ||
119
+ value > 100
120
+ ) {
121
+ throw new Error(
122
+ `${label} percentage must be greater than 0 and at most 100`,
123
+ );
124
+ }
125
+ return value;
126
+ }
@@ -0,0 +1,34 @@
1
+ export type ApprovalRuleMode = 'ANY' | 'ALL' | 'COUNT' | 'PERCENTAGE';
2
+
3
+ export interface ApprovalRule {
4
+ mode: ApprovalRuleMode;
5
+ count?: number;
6
+ percentage?: number;
7
+ }
8
+
9
+ export interface ApprovalRuleDecision {
10
+ principalRef: string;
11
+ decision: 'APPROVE' | 'REJECT';
12
+ /** False when the candidate eligibility revision is no longer active. */
13
+ active?: boolean;
14
+ }
15
+
16
+ export interface ApprovalRuleEvaluationInput {
17
+ candidateCount: number;
18
+ decisions: readonly ApprovalRuleDecision[];
19
+ approvalRule: ApprovalRule;
20
+ rejectionRule: ApprovalRule;
21
+ }
22
+
23
+ export type ApprovalRuleStatus =
24
+ | 'APPROVED'
25
+ | 'REJECTED'
26
+ | 'PENDING'
27
+ | 'BLOCKED';
28
+
29
+ export interface ApprovalRuleEvaluation {
30
+ status: ApprovalRuleStatus;
31
+ warnings: readonly string[];
32
+ approvalCount: number;
33
+ rejectionCount: number;
34
+ }
@@ -0,0 +1,115 @@
1
+ import { Injectable, Logger } from '@nestjs/common';
2
+ import { Interval } from '@nestjs/schedule';
3
+ import { randomUUID } from 'crypto';
4
+ import { PrismaService } from 'nestjs-prisma';
5
+ import { TemporalService } from '../workflow/temporal.service';
6
+ import { outboxError, outboxRetryAt } from './outbox-retry.util';
7
+
8
+ const BATCH_SIZE = 25;
9
+ const LOCK_TIMEOUT_MS = 60_000;
10
+
11
+ @Injectable()
12
+ export class ApprovalSignalOutboxService {
13
+ private readonly logger = new Logger(ApprovalSignalOutboxService.name);
14
+ private readonly workerId = `approval-signal-${process.pid}-${randomUUID()}`;
15
+
16
+ constructor(
17
+ private readonly prisma: PrismaService,
18
+ private readonly temporal: TemporalService,
19
+ ) {}
20
+
21
+ @Interval(5000)
22
+ async poll(): Promise<void> {
23
+ const rows = await this.claim();
24
+ for (const row of rows) await this.dispatch(row);
25
+ }
26
+
27
+ private claim() {
28
+ const now = new Date();
29
+ const staleAt = new Date(now.getTime() - LOCK_TIMEOUT_MS);
30
+ const claimId = `${this.workerId}:${randomUUID()}`.slice(0, 128);
31
+ return this.prisma.$transaction(async (tx) => {
32
+ const candidates = await tx.approvalSignalOutbox.findMany({
33
+ where: {
34
+ nextAttemptAt: { lte: now },
35
+ OR: [
36
+ { status: { in: ['PENDING', 'FAILED'] }, lockedAt: null },
37
+ { status: 'PROCESSING', lockedAt: { lt: staleAt } },
38
+ ],
39
+ },
40
+ orderBy: { id: 'asc' },
41
+ take: BATCH_SIZE,
42
+ });
43
+ if (!candidates.length) return [];
44
+ const ids = candidates.map(({ id }) => id);
45
+ await tx.approvalSignalOutbox.updateMany({
46
+ where: {
47
+ id: { in: ids },
48
+ OR: [
49
+ { status: { in: ['PENDING', 'FAILED'] }, lockedAt: null },
50
+ { status: 'PROCESSING', lockedAt: { lt: staleAt } },
51
+ ],
52
+ },
53
+ data: { status: 'PROCESSING', lockedAt: now, lockedBy: claimId },
54
+ });
55
+ return tx.approvalSignalOutbox.findMany({
56
+ where: { id: { in: ids }, lockedBy: claimId, status: 'PROCESSING' },
57
+ orderBy: { id: 'asc' },
58
+ });
59
+ });
60
+ }
61
+
62
+ private async dispatch(row: {
63
+ id: bigint;
64
+ requestId: bigint;
65
+ payload: unknown;
66
+ retryCount: number;
67
+ }): Promise<void> {
68
+ try {
69
+ const instance = await this.prisma.workflowInstance.findUnique({
70
+ where: {
71
+ id: (
72
+ await this.prisma.approvalRequest.findUniqueOrThrow({
73
+ where: { id: row.requestId },
74
+ select: { workflowInstanceId: true },
75
+ })
76
+ ).workflowInstanceId,
77
+ },
78
+ select: { temporalRunId: true },
79
+ });
80
+ if (!instance?.temporalRunId)
81
+ throw new Error('Approval workflow has no Temporal run ID');
82
+ await this.temporal.signalWorkflow(
83
+ instance.temporalRunId,
84
+ 'humanApprovalResolved',
85
+ row.payload,
86
+ );
87
+ await this.prisma.approvalSignalOutbox.updateMany({
88
+ where: { id: row.id, status: 'PROCESSING' },
89
+ data: {
90
+ status: 'PROCESSED',
91
+ processedAt: new Date(),
92
+ lockedAt: null,
93
+ lockedBy: null,
94
+ lastError: null,
95
+ },
96
+ });
97
+ } catch (error) {
98
+ const retryCount = row.retryCount + 1;
99
+ await this.prisma.approvalSignalOutbox.updateMany({
100
+ where: { id: row.id, status: 'PROCESSING' },
101
+ data: {
102
+ status: 'FAILED',
103
+ retryCount,
104
+ nextAttemptAt: outboxRetryAt(retryCount),
105
+ lockedAt: null,
106
+ lockedBy: null,
107
+ lastError: outboxError(error),
108
+ },
109
+ });
110
+ this.logger.warn(
111
+ `Approval signal ${row.id} failed: ${outboxError(error)}`,
112
+ );
113
+ }
114
+ }
115
+ }
@@ -0,0 +1,45 @@
1
+ import { materializeApprovalSubjects } from './approval-subject-source.util';
2
+
3
+ describe('materializeApprovalSubjects', () => {
4
+ it('combines static approvers with scalar and array dynamic inputs', () => {
5
+ expect(
6
+ materializeApprovalSubjects(
7
+ [
8
+ { source: 'STATIC', provider: 'USER', refs: ['alice'] },
9
+ {
10
+ source: 'DYNAMIC',
11
+ provider: 'USER',
12
+ inputKey: 'request_owner',
13
+ },
14
+ {
15
+ source: 'DYNAMIC',
16
+ provider: 'USER_GROUP',
17
+ inputKey: 'review_groups',
18
+ },
19
+ ],
20
+ {
21
+ request_owner: 'bob',
22
+ review_groups: ['finance', 'risk', 'finance'],
23
+ },
24
+ ),
25
+ ).toEqual([
26
+ { provider: 'USER', refs: ['alice', 'bob'] },
27
+ { provider: 'USER_GROUP', refs: ['finance', 'risk'] },
28
+ ]);
29
+ });
30
+
31
+ it('rejects a missing dynamic approver input', () => {
32
+ expect(() =>
33
+ materializeApprovalSubjects(
34
+ [
35
+ {
36
+ source: 'DYNAMIC',
37
+ provider: 'USER',
38
+ inputKey: 'request_owner',
39
+ },
40
+ ],
41
+ {},
42
+ ),
43
+ ).toThrow('Dynamic approver input "request_owner" is missing or empty');
44
+ });
45
+ });
@@ -0,0 +1,59 @@
1
+ export type ApprovalSubjectProvider = 'USER' | 'USER_GROUP';
2
+
3
+ export type ApprovalSubjectSource =
4
+ | {
5
+ source?: 'STATIC';
6
+ provider: ApprovalSubjectProvider;
7
+ refs: string[];
8
+ }
9
+ | {
10
+ source: 'DYNAMIC';
11
+ provider: ApprovalSubjectProvider;
12
+ inputKey: string;
13
+ };
14
+
15
+ export interface MaterializedApprovalSubject {
16
+ provider: ApprovalSubjectProvider;
17
+ refs: string[];
18
+ }
19
+
20
+ export function materializeApprovalSubjects(
21
+ sources: ApprovalSubjectSource[],
22
+ dynamicInputs: Record<string, unknown> = {},
23
+ ): MaterializedApprovalSubject[] {
24
+ const refsByProvider = new Map<ApprovalSubjectProvider, string[]>();
25
+
26
+ for (const source of sources) {
27
+ const refs =
28
+ source.source === 'DYNAMIC'
29
+ ? normalizeDynamicRefs(dynamicInputs[source.inputKey], source.inputKey)
30
+ : normalizeRefs(source.refs);
31
+ const current = refsByProvider.get(source.provider) ?? [];
32
+ refsByProvider.set(source.provider, [...new Set([...current, ...refs])]);
33
+ }
34
+
35
+ return [...refsByProvider].map(([provider, refs]) => ({ provider, refs }));
36
+ }
37
+
38
+ function normalizeDynamicRefs(value: unknown, inputKey: string): string[] {
39
+ const refs = normalizeRefs(Array.isArray(value) ? value : [value]);
40
+ if (refs.length === 0)
41
+ throw new Error(`Dynamic approver input "${inputKey}" is missing or empty`);
42
+ return refs;
43
+ }
44
+
45
+ function normalizeRefs(values: unknown[]): string[] {
46
+ return [
47
+ ...new Set(
48
+ values
49
+ .filter(
50
+ (value) =>
51
+ typeof value === 'string' ||
52
+ (typeof value === 'number' && Number.isSafeInteger(value)),
53
+ )
54
+ .map(String)
55
+ .map((value) => value.trim())
56
+ .filter(Boolean),
57
+ ),
58
+ ];
59
+ }
@@ -0,0 +1,72 @@
1
+ import { ACGuard } from '@gadmin2n/nest-common';
2
+ import {
3
+ Body,
4
+ Controller,
5
+ Get,
6
+ HttpStatus,
7
+ Param,
8
+ Post,
9
+ Req,
10
+ UseGuards,
11
+ } from '@nestjs/common';
12
+ import { ApiTags } from '@nestjs/swagger';
13
+ import { UseRoles } from 'nest-access-control';
14
+ import {
15
+ actorContextFromRequest,
16
+ AuthenticatedActorRequest,
17
+ } from '../subjectProvider/actor-context.util';
18
+ import { SubmitApprovalDecisionDto } from './human-approval.dto';
19
+ import { HumanApprovalDomainError } from './human-approval.errors';
20
+ import { HumanApprovalService } from './human-approval.service';
21
+
22
+ @ApiTags('human-approval')
23
+ @UseGuards(ACGuard)
24
+ @Controller('human-approval')
25
+ export class HumanApprovalController {
26
+ constructor(private readonly service: HumanApprovalService) {}
27
+
28
+ @Get('inbox')
29
+ @UseRoles({ resource: 'humanApproval', action: 'read', possession: 'any' })
30
+ inbox(@Req() request: AuthenticatedActorRequest) {
31
+ return this.service.inbox(actorContextFromRequest(request));
32
+ }
33
+
34
+ @Post(':requestId/decisions')
35
+ @UseRoles({
36
+ resource: 'humanApproval',
37
+ action: 'update',
38
+ possession: 'any',
39
+ })
40
+ decide(
41
+ @Param('requestId') requestId: string,
42
+ @Body() input: SubmitApprovalDecisionDto,
43
+ @Req() request: AuthenticatedActorRequest,
44
+ ) {
45
+ return this.service.submitDecision(
46
+ parseBigIntParam(requestId),
47
+ input,
48
+ actorContextFromRequest(request),
49
+ );
50
+ }
51
+
52
+ @Post(':requestId/retry-dispatch')
53
+ @UseRoles({
54
+ resource: 'humanApproval',
55
+ action: 'update',
56
+ possession: 'any',
57
+ })
58
+ retryDispatch(@Param('requestId') requestId: string) {
59
+ return this.service.retryDispatch(parseBigIntParam(requestId));
60
+ }
61
+ }
62
+
63
+ function parseBigIntParam(value: string): bigint {
64
+ if (!/^[0-9]+$/.test(value)) {
65
+ throw new HumanApprovalDomainError(
66
+ 'APPROVAL_REQUEST_NOT_FOUND',
67
+ 'Approval request ID must be an integer',
68
+ HttpStatus.BAD_REQUEST,
69
+ );
70
+ }
71
+ return BigInt(value);
72
+ }
@@ -0,0 +1,144 @@
1
+ import { Type } from 'class-transformer';
2
+ import {
3
+ IsArray,
4
+ IsIn,
5
+ IsInt,
6
+ IsNotEmpty,
7
+ IsObject,
8
+ IsOptional,
9
+ IsString,
10
+ Min,
11
+ ValidateIf,
12
+ ValidateNested,
13
+ } from 'class-validator';
14
+ import { ApprovalRule } from './approval-rule.types';
15
+
16
+ export class ApprovalSubjectConfigDto {
17
+ @IsIn(['STATIC', 'DYNAMIC'])
18
+ source: 'STATIC' | 'DYNAMIC';
19
+
20
+ @IsString()
21
+ @IsNotEmpty()
22
+ provider: string;
23
+
24
+ @ValidateIf((input) => input.source === 'STATIC')
25
+ @IsArray()
26
+ @IsString({ each: true })
27
+ refs?: string[];
28
+
29
+ @ValidateIf((input) => input.source === 'DYNAMIC')
30
+ @IsString()
31
+ @IsNotEmpty()
32
+ inputKey?: string;
33
+ }
34
+
35
+ export class ApprovalTimeoutConfigDto {
36
+ @IsInt()
37
+ @Min(0)
38
+ durationSeconds: number;
39
+
40
+ @IsIn(['APPROVED', 'REJECTED'])
41
+ action: 'APPROVED' | 'REJECTED';
42
+ }
43
+
44
+ export class ApprovalConfigSnapshotDto {
45
+ @IsOptional()
46
+ @IsString()
47
+ @IsNotEmpty()
48
+ channelRef?: string;
49
+
50
+ @IsOptional()
51
+ @IsObject()
52
+ channelInputBindings?: Record<string, unknown>;
53
+
54
+ @IsArray()
55
+ @ValidateNested({ each: true })
56
+ @Type(() => ApprovalSubjectConfigDto)
57
+ subjects: ApprovalSubjectConfigDto[];
58
+
59
+ @IsObject()
60
+ approvalRule: ApprovalRule;
61
+
62
+ @IsObject()
63
+ rejectionRule: ApprovalRule;
64
+
65
+ @ValidateNested()
66
+ @Type(() => ApprovalTimeoutConfigDto)
67
+ timeout: ApprovalTimeoutConfigDto;
68
+ }
69
+
70
+ export class StartApprovalRequestDto {
71
+ workflowInstanceId: string | number | bigint;
72
+
73
+ @IsString()
74
+ @IsNotEmpty()
75
+ nodeId: string;
76
+
77
+ workflowVersionId: string | number | bigint;
78
+
79
+ @IsOptional()
80
+ @IsString()
81
+ tenantNamespace?: string;
82
+
83
+ @IsOptional()
84
+ @IsString()
85
+ temporalRunId?: string;
86
+
87
+ @IsString()
88
+ @IsNotEmpty()
89
+ configHash: string;
90
+
91
+ @ValidateNested()
92
+ @Type(() => ApprovalConfigSnapshotDto)
93
+ configSnapshot: ApprovalConfigSnapshotDto;
94
+
95
+ @IsOptional()
96
+ @IsObject()
97
+ dynamicInputs?: Record<string, unknown>;
98
+
99
+ @IsOptional()
100
+ @IsObject()
101
+ channelInputs?: Record<string, unknown>;
102
+
103
+ @IsOptional()
104
+ @IsArray()
105
+ @ValidateNested({ each: true })
106
+ @Type(() => ResolvedApprovalSubjectDto)
107
+ resolvedSubjects?: ResolvedApprovalSubjectDto[];
108
+ }
109
+
110
+ export class ResolvedApprovalSubjectDto {
111
+ @IsIn(['USER', 'USER_GROUP'])
112
+ provider!: 'USER' | 'USER_GROUP';
113
+
114
+ @IsArray()
115
+ @IsString({ each: true })
116
+ refs!: string[];
117
+ }
118
+
119
+ export class SubmitApprovalDecisionDto {
120
+ @IsIn(['APPROVE', 'REJECT'])
121
+ decision: 'APPROVE' | 'REJECT';
122
+
123
+ @IsOptional()
124
+ @IsString()
125
+ comment?: string;
126
+
127
+ @IsOptional()
128
+ @IsObject()
129
+ payload?: Record<string, unknown>;
130
+ }
131
+
132
+ export class SubmitExternalApprovalDecisionDto extends SubmitApprovalDecisionDto {
133
+ @IsString()
134
+ @IsNotEmpty()
135
+ channelRef!: string;
136
+
137
+ @IsString()
138
+ @IsNotEmpty()
139
+ eventId!: string;
140
+
141
+ @IsString()
142
+ @IsNotEmpty()
143
+ approverId!: string;
144
+ }
@@ -0,0 +1,19 @@
1
+ import { HttpException, HttpStatus } from '@nestjs/common';
2
+
3
+ export type HumanApprovalErrorCode =
4
+ | 'APPROVAL_CONFIG_MISMATCH'
5
+ | 'APPROVAL_REQUEST_NOT_FOUND'
6
+ | 'APPROVAL_REQUEST_CLOSED'
7
+ | 'APPROVAL_NOT_CANDIDATE'
8
+ | 'APPROVAL_CHANNEL_MISMATCH'
9
+ | 'APPROVAL_DECISION_CONFLICT';
10
+
11
+ export class HumanApprovalDomainError extends HttpException {
12
+ constructor(
13
+ code: HumanApprovalErrorCode,
14
+ message: string,
15
+ status: HttpStatus,
16
+ ) {
17
+ super({ code, message }, status);
18
+ }
19
+ }