@gadmin2n/schematics 0.0.72 → 0.0.74

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 (173) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +2 -0
  3. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/job.prisma +62 -0
  4. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/system.prisma +0 -21
  5. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +171 -0
  6. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/AgendaJob.ts +60 -0
  7. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Event.ts +1 -1
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowEventOutbox.ts +62 -0
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowNodeInstance.ts +62 -0
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowNodeType.ts +62 -0
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/server/.env +5 -0
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +5 -4
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/server/prisma.config.ts +14 -7
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/index.ts +4 -0
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/permissions.ts +49 -3
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-node-types.ts +746 -0
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflows.ts +786 -0
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agenda/agenda.controller.ts +6 -0
  19. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agenda/agenda.service.ts +79 -0
  20. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.controller.spec.ts +20 -0
  21. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.controller.ts +145 -0
  22. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.module.ts +10 -0
  23. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/{canvas/canvas.service.spec.ts → agendaJob/agendaJob.service.spec.ts} +71 -65
  24. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.service.ts +83 -0
  25. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/index.ts +2 -1
  26. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.module.ts +9 -0
  27. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.service.ts +100 -0
  28. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-execution.dto.ts +19 -0
  29. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.dto.ts +43 -0
  30. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.service.ts +317 -0
  31. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-node-type.controller.ts +16 -0
  32. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-node-type.service.ts +13 -0
  33. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +220 -0
  34. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.dto.ts +82 -0
  35. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.module.ts +16 -0
  36. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +505 -0
  37. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.controller.spec.ts +22 -0
  38. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.controller.ts +147 -0
  39. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.module.ts +10 -0
  40. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.service.spec.ts +356 -0
  41. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.service.ts +110 -0
  42. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.controller.spec.ts +22 -0
  43. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.controller.ts +216 -0
  44. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.module.ts +10 -0
  45. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.spec.ts +356 -0
  46. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.ts +168 -0
  47. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.controller.spec.ts +22 -0
  48. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.controller.ts +199 -0
  49. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.module.ts +10 -0
  50. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.service.spec.ts +348 -0
  51. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.service.ts +106 -0
  52. package/dist/lib/application/files/gadmin2-game-angle-demo/server/yarn.lock +579 -1082
  53. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/README.md +278 -0
  54. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/config/development-sql.yaml +5 -0
  55. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/docker-compose.yml +25 -0
  56. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/package.json +13 -0
  57. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/sql/create-event-trigger.sql +87 -0
  58. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/.env +7 -0
  59. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/SANDBOX.md +122 -0
  60. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/package-lock.json +4285 -0
  61. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/package.json +28 -0
  62. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/activities/code-execute.test.ts +44 -0
  63. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/activities/http-request.test.ts +87 -0
  64. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/helpers.test.ts +225 -0
  65. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/node-type-consistency.test.ts +101 -0
  66. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/code-execute.ts +51 -0
  67. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/db-execute.ts +85 -0
  68. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/db-query.ts +35 -0
  69. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/http-request.ts +54 -0
  70. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/index.ts +6 -0
  71. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/reporting.ts +62 -0
  72. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/send-notification.ts +47 -0
  73. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/config.ts +13 -0
  74. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/condition.ts +101 -0
  75. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/context.ts +58 -0
  76. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/graph.ts +184 -0
  77. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/helpers.ts +133 -0
  78. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/node-types.ts +57 -0
  79. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/types.ts +77 -0
  80. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/index.ts +36 -0
  81. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/outbox-poller.ts +226 -0
  82. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/workflows/dsl-workflow.ts +411 -0
  83. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/tsconfig.json +19 -0
  84. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/vitest.config.ts +8 -0
  85. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/yarn.lock +1905 -0
  86. package/dist/lib/application/files/gadmin2-game-angle-demo/web/package-lock.json +17555 -0
  87. package/dist/lib/application/files/gadmin2-game-angle-demo/web/package.json +5 -2
  88. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/App.tsx +1 -0
  89. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/sider.tsx +5 -1
  90. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/title.tsx +1 -1
  91. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +63 -0
  92. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DevShell.tsx +91 -2
  93. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/list.tsx +48 -2
  94. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/show.tsx +43 -2
  95. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +14 -9
  96. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +14 -9
  97. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/index.tsx +309 -56
  98. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/show.tsx +1 -3
  99. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/create.tsx +108 -0
  100. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/edit.tsx +124 -0
  101. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/index.tsx +4 -0
  102. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/list.tsx +245 -0
  103. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/show.tsx +70 -0
  104. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasListPage.tsx +0 -1
  105. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasPage.tsx +160 -2
  106. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasToolbar.tsx +120 -148
  107. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CodeFloatWindow.tsx +74 -181
  108. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/LivePreview.tsx +15 -13
  109. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasConfigRegistry.tsx +2 -2
  110. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasContextMenuRegistry.tsx +338 -3
  111. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasDefaults.ts +18 -17
  112. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/BarChartDataSourceModal.tsx +10 -4
  113. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/LineChartDataSourceModal.tsx +10 -4
  114. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/{ChartViewerConfigModal.tsx → MultiChartConfigModal.tsx} +30 -18
  115. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/MultiChartDataSourceModal.tsx +427 -0
  116. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/NumCardDataSourceModal.tsx +10 -4
  117. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/PromptModal.tsx +6 -14
  118. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/RadarChartDataSourceModal.tsx +10 -4
  119. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/TableDataSourceModal.tsx +10 -4
  120. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/canvasModalProps.ts +24 -0
  121. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/demos.ts +45 -63
  122. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CustomNode.tsx +99 -0
  123. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExportModal.tsx +87 -0
  124. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/FlowRenderer.tsx +322 -0
  125. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ImportModal.tsx +175 -0
  126. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeEditModal.tsx +60 -0
  127. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.tsx +1150 -0
  128. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/RunWorkflowModal.tsx +101 -0
  129. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/StatusCards.tsx +198 -0
  130. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/VersionPanel.tsx +81 -0
  131. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/editor.tsx +566 -0
  132. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useWorkflowAgent.ts +224 -0
  133. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/index.tsx +524 -0
  134. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.tsx +343 -0
  135. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instances.tsx +243 -0
  136. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/CreateNodeInstanceModal.tsx +363 -0
  137. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/DynamicConfigForm.tsx +154 -0
  138. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/NodeInstanceForm.tsx +176 -0
  139. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/create.tsx +77 -0
  140. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/edit.tsx +112 -0
  141. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/index.tsx +305 -0
  142. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/show.tsx +282 -0
  143. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/show.tsx +469 -0
  144. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/types.ts +92 -0
  145. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/create.tsx +111 -0
  146. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/edit.tsx +127 -0
  147. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/index.tsx +4 -0
  148. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/list.tsx +254 -0
  149. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/show.tsx +74 -0
  150. package/dist/lib/application/files/gadmin2-game-angle-demo/web/yarn.lock +1501 -1199
  151. package/package.json +1 -1
  152. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/app.controller.spec.ts +0 -22
  153. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/BarChart/index.tsx +0 -896
  154. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/ChartSwitcher/index.tsx +0 -219
  155. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/ChartViewer/index.tsx +0 -159
  156. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Filter/index.tsx +0 -192
  157. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/LineChart/index.tsx +0 -1034
  158. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumCard/NumCard.module.css +0 -8
  159. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumCard/index.tsx +0 -509
  160. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumLineCard/index.tsx +0 -66
  161. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/PieChart/index.tsx +0 -552
  162. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/RadarChart/index.tsx +0 -263
  163. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Section/index.tsx +0 -35
  164. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Table/index.tsx +0 -207
  165. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/TreemapChart/index.tsx +0 -382
  166. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/WorldMap/index.tsx +0 -135
  167. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/chart-constants.ts +0 -53
  168. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/icon/InfoIcon.tsx +0 -8
  169. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/icon/index.ts +0 -1
  170. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/config.ts +0 -31
  171. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/nameMap.json +0 -9
  172. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/world.geo.json +0 -39349
  173. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/metric-info-tooltip/index.tsx +0 -19
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Canonical list of all workflow node types.
3
+ *
4
+ * This is the SINGLE SOURCE OF TRUTH for node type strings.
5
+ * When you add a new type here, TypeScript will force you to handle it
6
+ * in the executeNode() switch — otherwise the build fails.
7
+ */
8
+ export const ALL_NODE_TYPES = [
9
+ // TRIGGER
10
+ 'cron_trigger',
11
+ 'webhook_trigger',
12
+ 'event_trigger',
13
+ 'manual_trigger',
14
+ // ACTION (calls an activity)
15
+ 'http_request',
16
+ 'db_query',
17
+ 'db_execute',
18
+ 'send_notification',
19
+ 'code',
20
+ // DATA PROCESSING (inline logic)
21
+ 'set_variable',
22
+ // CONDITION (inline logic)
23
+ 'if_else',
24
+ 'switch',
25
+ // FLOW CONTROL
26
+ 'for_each',
27
+ 'delay',
28
+ 'parallel',
29
+ 'error_handler',
30
+ // APPROVAL (Temporal signal)
31
+ 'approval',
32
+ // SUB WORKFLOW
33
+ 'sub_workflow',
34
+ ] as const;
35
+
36
+ /** Union of all supported node type strings. */
37
+ export type NodeType = (typeof ALL_NODE_TYPES)[number];
38
+
39
+ /** Node types that require a Temporal activity call. */
40
+ export const ACTIVITY_NODE_TYPES = [
41
+ 'http_request',
42
+ 'db_query',
43
+ 'db_execute',
44
+ 'send_notification',
45
+ 'code',
46
+ ] as const satisfies readonly NodeType[];
47
+
48
+ export type ActivityNodeType = (typeof ACTIVITY_NODE_TYPES)[number];
49
+
50
+ /**
51
+ * Compile-time exhaustiveness check.
52
+ * Place in the `default` of a switch over NodeType — if a case is missing,
53
+ * TypeScript emits: "Argument of type 'X' is not assignable to parameter of type 'never'."
54
+ */
55
+ export function assertNever(x: never): never {
56
+ throw new Error(`Unhandled node type: ${x}`);
57
+ }
@@ -0,0 +1,77 @@
1
+ // ─── DSL Types (mirrors frontend WorkflowDSL) ─────────────────────────────────
2
+
3
+ import type { NodeType } from './node-types';
4
+
5
+ export interface DslNode {
6
+ id: string;
7
+ type: NodeType;
8
+ label: string;
9
+ position: { x: number; y: number };
10
+ config: Record<string, any>;
11
+ }
12
+
13
+ export interface DslEdge {
14
+ id: string;
15
+ source: string;
16
+ target: string;
17
+ sourceHandle?: string; // for condition branches: "true"/"false" or case labels
18
+ label?: string;
19
+ }
20
+
21
+ export interface WorkflowDSL {
22
+ nodes: DslNode[];
23
+ edges: DslEdge[];
24
+ }
25
+
26
+ // ─── Workflow Execution Types ──────────────────────────────────────────────────
27
+
28
+ export interface WorkflowInput {
29
+ instanceId: number;
30
+ workflowId: number;
31
+ versionId: number;
32
+ dsl: WorkflowDSL;
33
+ context: Record<string, any>;
34
+ }
35
+
36
+ export interface WorkflowResult {
37
+ status: 'COMPLETED' | 'FAILED' | 'CANCELLED';
38
+ context: Record<string, any>;
39
+ error?: string;
40
+ }
41
+
42
+ // ─── Node Execution Context ───────────────────────────────────────────────────
43
+
44
+ export interface NodeExecutionResult {
45
+ output: Record<string, any>;
46
+ branch?: string; // For condition nodes: which branch to take
47
+ }
48
+
49
+ export type NodeStatus = 'PENDING' | 'RUNNING' | 'COMPLETED' | 'FAILED' | 'CANCELLED';
50
+
51
+ // ─── Activity Input Types ─────────────────────────────────────────────────────
52
+
53
+ export interface ReportNodeStatusInput {
54
+ instanceId: number;
55
+ nodeId: string;
56
+ nodeType: string;
57
+ nodeLabel?: string;
58
+ status: NodeStatus;
59
+ input?: Record<string, any>;
60
+ output?: Record<string, any>;
61
+ error?: Record<string, any>;
62
+ }
63
+
64
+ export interface ReportWorkflowStatusInput {
65
+ instanceId: number;
66
+ status: 'RUNNING' | 'COMPLETED' | 'FAILED' | 'CANCELLED';
67
+ result?: Record<string, any>;
68
+ }
69
+
70
+ // ─── Signals ──────────────────────────────────────────────────────────────────
71
+
72
+ export interface ApprovalSignalPayload {
73
+ nodeId: string;
74
+ approved: boolean;
75
+ comment?: string;
76
+ approvedBy: string;
77
+ }
@@ -0,0 +1,36 @@
1
+ import { NativeConnection, Worker } from '@temporalio/worker';
2
+ import * as activities from './activities';
3
+ import { config } from './config';
4
+ import { startOutboxPoller } from './outbox-poller';
5
+
6
+ async function run() {
7
+ console.log(`[Worker] Connecting to Temporal at ${config.temporal.address}...`);
8
+
9
+ const connection = await NativeConnection.connect({
10
+ address: config.temporal.address,
11
+ });
12
+
13
+ const worker = await Worker.create({
14
+ connection,
15
+ namespace: config.temporal.namespace,
16
+ taskQueue: config.temporal.taskQueue,
17
+ workflowsPath: require.resolve('./workflows/dsl-workflow'),
18
+ activities,
19
+ });
20
+
21
+ console.log(`[Worker] Started. Polling task queue: ${config.temporal.taskQueue}`);
22
+ console.log(`[Worker] Namespace: ${config.temporal.namespace}`);
23
+
24
+ // Start outbox poller for event_trigger workflows
25
+ startOutboxPoller().catch((err) => {
26
+ console.error('[OutboxPoller] Failed to start:', err.message);
27
+ });
28
+
29
+ // Start polling for workflow tasks
30
+ await worker.run();
31
+ }
32
+
33
+ run().catch((err) => {
34
+ console.error('[Worker] Fatal error:', err);
35
+ process.exit(1);
36
+ });
@@ -0,0 +1,226 @@
1
+ import { Client as PgClient } from "pg";
2
+ import { Client, Connection } from "@temporalio/client";
3
+ import { config } from "./config";
4
+
5
+ const POLL_INTERVAL = Number(process.env.EVENT_POLL_INTERVAL_MS) || 10_000; // 默认 10 秒
6
+ const BATCH_SIZE = 50;
7
+ const MAX_RETRIES = Number(process.env.OUTBOX_MAX_RETRIES) || 5;
8
+
9
+ /**
10
+ * Outbox Poller — 定时扫描 t_workflow_event_outbox 未处理事件,匹配并触发 workflow。
11
+ *
12
+ * 工作原理:
13
+ * 1. 业务表的 AFTER 触发器写入 outbox 行(同一事务,保证不丢)
14
+ * 2. 本轮询器每 N 秒扫描未处理行
15
+ * 3. 匹配 event_trigger workflow → 启动 Temporal 执行
16
+ * 4. 标记行为已处理
17
+ */
18
+ export async function startOutboxPoller() {
19
+ const pg = new PgClient({ connectionString: config.database.url });
20
+ await pg.connect();
21
+
22
+ const temporalConn = await Connection.connect({
23
+ address: config.temporal.address,
24
+ });
25
+ const temporalClient = new Client({
26
+ connection: temporalConn,
27
+ namespace: config.temporal.namespace,
28
+ });
29
+
30
+ console.log(`[OutboxPoller] Started. Polling every ${POLL_INTERVAL}ms, max retries: ${MAX_RETRIES}`);
31
+
32
+ const poll = async () => {
33
+ try {
34
+ // 用 FOR UPDATE SKIP LOCKED 保证多实例不重复消费
35
+ const { rows } = await pg.query(
36
+ `UPDATE t_workflow_event_outbox
37
+ SET processed = TRUE, processed_at = NOW()
38
+ WHERE id IN (
39
+ SELECT id FROM t_workflow_event_outbox
40
+ WHERE processed = FALSE
41
+ ORDER BY created_at
42
+ LIMIT $1
43
+ FOR UPDATE SKIP LOCKED
44
+ )
45
+ RETURNING id, event_name, payload, retry_count`,
46
+ [BATCH_SIZE],
47
+ );
48
+
49
+ if (rows.length === 0) return;
50
+ console.log(`[OutboxPoller] Processing ${rows.length} events`);
51
+
52
+ for (const row of rows) {
53
+ try {
54
+ const matched = await matchAndTrigger(
55
+ pg,
56
+ temporalClient,
57
+ row.event_name,
58
+ row.payload,
59
+ );
60
+ if (matched === 0) {
61
+ console.warn(
62
+ `[OutboxPoller] No workflow matched event "${row.event_name}" (id=${row.id}). Event consumed without action.`,
63
+ );
64
+ }
65
+ } catch (err: any) {
66
+ const nextRetry = (row.retry_count ?? 0) + 1;
67
+ const errMsg = String(err?.message ?? err);
68
+ if (nextRetry >= MAX_RETRIES) {
69
+ // 终态失败:保持 processed=true,仅记录 retry_count + last_error,不再重试
70
+ console.error(
71
+ `[OutboxPoller] Event ${row.id} (${row.event_name}) failed ${nextRetry} times. Marking as terminal failure: ${errMsg}`,
72
+ );
73
+ await pg.query(
74
+ `UPDATE t_workflow_event_outbox
75
+ SET retry_count = $1, last_error = $2
76
+ WHERE id = $3`,
77
+ [nextRetry, errMsg, row.id],
78
+ );
79
+ } else {
80
+ console.error(
81
+ `[OutboxPoller] Event ${row.id} (${row.event_name}) failed (retry ${nextRetry}/${MAX_RETRIES}): ${errMsg}`,
82
+ );
83
+ // 标记回未处理,下次重试
84
+ await pg.query(
85
+ `UPDATE t_workflow_event_outbox
86
+ SET processed = FALSE, processed_at = NULL, retry_count = $1, last_error = $2
87
+ WHERE id = $3`,
88
+ [nextRetry, errMsg, row.id],
89
+ );
90
+ }
91
+ }
92
+ }
93
+ } catch (err: any) {
94
+ console.error("[OutboxPoller] Poll error:", err.message);
95
+ }
96
+ };
97
+
98
+ // 自调度循环:每次 poll 完成后再排下一次,避免 setInterval 在 poll 慢于 POLL_INTERVAL 时重叠调用
99
+ const loop = async () => {
100
+ try {
101
+ await poll();
102
+ } finally {
103
+ setTimeout(loop, POLL_INTERVAL);
104
+ }
105
+ };
106
+ loop();
107
+ }
108
+
109
+ /**
110
+ * 查找监听该 eventName 的 workflow 并启动执行。
111
+ *
112
+ * @returns 实际匹配并启动的 workflow 数量;0 表示无人订阅。
113
+ */
114
+ async function matchAndTrigger(
115
+ pg: PgClient,
116
+ temporalClient: Client,
117
+ eventName: string,
118
+ payload: Record<string, any>,
119
+ ): Promise<number> {
120
+ // 查询所有已发布且启用的 workflow 的最新版本 DSL
121
+ const result = await pg.query(`
122
+ SELECT w.id AS workflow_id, wv.id AS version_id, wv.dsl
123
+ FROM t_workflow w
124
+ JOIN t_workflow_version wv ON wv.workflow_id = w.id
125
+ WHERE w.status = 'PUBLISHED'
126
+ AND w.is_enabled = true
127
+ AND wv.version = (
128
+ SELECT MAX(wv2.version)
129
+ FROM t_workflow_version wv2
130
+ WHERE wv2.workflow_id = w.id
131
+ )
132
+ `);
133
+
134
+ let matchedCount = 0;
135
+
136
+ for (const row of result.rows) {
137
+ const dsl = row.dsl;
138
+ if (!dsl?.nodes) continue;
139
+
140
+ // 找 event_trigger 节点且 eventName 匹配
141
+ const trigger = dsl.nodes.find(
142
+ (n: any) =>
143
+ n.type === "event_trigger" &&
144
+ matchEventName(n.config?.eventName, eventName),
145
+ );
146
+ if (!trigger) continue;
147
+
148
+ // 可选: filterExpression 过滤
149
+ if (trigger.config?.filterExpression) {
150
+ if (!evaluateFilter(trigger.config.filterExpression, payload)) continue;
151
+ }
152
+
153
+ // 创建 WorkflowInstance
154
+ const instance = await pg.query(
155
+ `INSERT INTO t_workflow_instance (workflow_id, version_id, status, context, creator, created_at, updated_at)
156
+ VALUES ($1, $2, 'PENDING', $3, 'event_trigger', NOW(), NOW())
157
+ RETURNING id`,
158
+ [row.workflow_id, row.version_id, JSON.stringify(payload)],
159
+ );
160
+ const instanceId = Number(instance.rows[0].id);
161
+
162
+ // 启动 Temporal workflow
163
+ const workflowId = `wf-${row.workflow_id}-${instanceId}`;
164
+ const handle = await temporalClient.workflow.start("dslWorkflow", {
165
+ taskQueue: config.temporal.taskQueue,
166
+ workflowId,
167
+ args: [
168
+ {
169
+ instanceId,
170
+ workflowId: Number(row.workflow_id),
171
+ versionId: Number(row.version_id),
172
+ dsl,
173
+ context: payload,
174
+ },
175
+ ],
176
+ });
177
+
178
+ // 回写 temporal_run_id
179
+ await pg.query(
180
+ `UPDATE t_workflow_instance SET temporal_run_id = $1 WHERE id = $2`,
181
+ [handle.workflowId, instanceId],
182
+ );
183
+
184
+ console.log(
185
+ `[OutboxPoller] Triggered workflow ${row.workflow_id} for event "${eventName}", instance=${instanceId}`,
186
+ );
187
+ matchedCount++;
188
+ }
189
+
190
+ return matchedCount;
191
+ }
192
+
193
+ /**
194
+ * 匹配事件名,支持通配符:
195
+ * - "t_order.insert" 精确匹配
196
+ * - "t_order.*" 匹配该表所有操作
197
+ * - "*.insert" 匹配所有表的 insert
198
+ */
199
+ function matchEventName(pattern: string | undefined, actual: string): boolean {
200
+ if (!pattern) return false;
201
+ if (pattern === actual) return true;
202
+ if (pattern === "*") return true;
203
+
204
+ const [patTable, patOp] = pattern.split(".");
205
+ const [actTable, actOp] = actual.split(".");
206
+
207
+ const tableMatch = patTable === "*" || patTable === actTable;
208
+ const opMatch = !patOp || patOp === "*" || patOp === actOp;
209
+
210
+ return tableMatch && opMatch;
211
+ }
212
+
213
+ /**
214
+ * 简单的 filter 表达式求值。
215
+ */
216
+ function evaluateFilter(
217
+ expression: string,
218
+ payload: Record<string, any>,
219
+ ): boolean {
220
+ try {
221
+ const fn = new Function("data", `return ${expression}`);
222
+ return !!fn(payload);
223
+ } catch {
224
+ return true;
225
+ }
226
+ }