@gadmin2n/schematics 0.0.136 → 0.0.137

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 (94) hide show
  1. package/dist/lib/application/files/gadmin2-game-angle-demo/Dockerfile.server +2 -2
  2. package/dist/lib/application/files/gadmin2-game-angle-demo/compose-ctl.sh +1 -1
  3. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/canvas.prisma +1 -0
  4. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +14 -3
  5. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/User.ts +4 -4
  6. package/dist/lib/application/files/gadmin2-game-angle-demo/docker-compose.md +2 -2
  7. package/dist/lib/application/files/gadmin2-game-angle-demo/docker-compose.yml +13 -92
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/readme.md +105 -7
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/server/ensure-database.js +1 -1
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +5 -5
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/server/prisma.config.ts +9 -1
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/notify-dev-servers.js +9 -8
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/server/scripts/wait-for-nest-ready.js +5 -5
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-node-types.ts +43 -2
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow.seed.ts +9 -1
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflows.ts +24 -0
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas-export.dto.ts +27 -0
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas-export.service.spec.ts +430 -0
  19. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas-export.service.ts +203 -0
  20. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.controller.ts +36 -3
  21. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.module.ts +2 -1
  22. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.controller.spec.ts +54 -0
  23. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.controller.ts +245 -0
  24. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.module.ts +10 -0
  25. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.service.spec.ts +366 -0
  26. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/temporalTenantConfig/temporalTenantConfig.service.ts +110 -0
  27. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-execution.dto.ts +19 -1
  28. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +15 -0
  29. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.spec.ts +79 -0
  30. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +41 -19
  31. package/dist/lib/application/files/gadmin2-game-angle-demo/server/start-prod.sh +5 -5
  32. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/README.md +37 -573
  33. package/dist/lib/application/files/gadmin2-game-angle-demo/web/ecosystem.dev.config.cjs +12 -1
  34. package/dist/lib/application/files/gadmin2-game-angle-demo/web/package.json +1 -0
  35. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/header.tsx +3 -2
  36. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +39 -26
  37. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/i18n.ts +3 -1
  38. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +3 -0
  39. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +3 -0
  40. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasEditPage.tsx +23 -5
  41. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasListPage.tsx +66 -10
  42. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasPage.tsx +16 -7
  43. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasToolbar.tsx +21 -0
  44. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasApi.ts +30 -0
  45. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/ExportModal.tsx +84 -0
  46. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/ImportModal.tsx +166 -0
  47. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/hooks/useCanvasHistory.ts +52 -13
  48. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/DslView.tsx +6 -0
  49. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.tsx +6 -1
  50. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/editor.tsx +17 -0
  51. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.tsx +18 -6
  52. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/temporal-tenant/index.tsx +225 -0
  53. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/utilities/lazy-with-reload.ts +31 -0
  54. package/package.json +1 -1
  55. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-dsl-validate.spec.ts +0 -220
  56. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-dsl-validate.ts +0 -132
  57. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/TODO.md +0 -152
  58. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/config/development-sql.yaml +0 -5
  59. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/docker-compose.yml +0 -25
  60. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/package.json +0 -13
  61. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/.dockerignore +0 -12
  62. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/.env +0 -7
  63. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/Dockerfile +0 -79
  64. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/GRACEFUL-DEPLOYMENT.md +0 -270
  65. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/SANDBOX.md +0 -122
  66. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/package-lock.json +0 -4285
  67. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/package.json +0 -28
  68. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/code-execute.ts +0 -51
  69. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/db-execute.ts +0 -85
  70. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/db-query.ts +0 -35
  71. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/http-request.ts +0 -54
  72. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/index.ts +0 -6
  73. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/reporting.ts +0 -85
  74. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/send-notification.ts +0 -47
  75. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/config.ts +0 -13
  76. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/condition.ts +0 -101
  77. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/context.ts +0 -58
  78. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/graph.ts +0 -184
  79. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/helpers.ts +0 -133
  80. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/node-types.ts +0 -96
  81. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/types.ts +0 -77
  82. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/validate.ts +0 -109
  83. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/index.ts +0 -101
  84. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/outbox-poller.ts +0 -382
  85. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/tests/activities/code-execute.test.ts +0 -44
  86. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/tests/activities/http-request.test.ts +0 -87
  87. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/tests/cron-trigger-workflow.test.ts +0 -20
  88. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/tests/helpers.test.ts +0 -225
  89. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/tests/node-type-consistency.test.ts +0 -101
  90. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/tests/validate.test.ts +0 -205
  91. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/workflows/dsl-workflow.ts +0 -499
  92. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/tsconfig.json +0 -19
  93. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/vitest.config.ts +0 -8
  94. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/yarn.lock +0 -1905
@@ -1,28 +0,0 @@
1
- {
2
- "name": "gadmin-workflow-worker",
3
- "version": "1.0.0",
4
- "private": true,
5
- "scripts": {
6
- "build": "tsc",
7
- "dev": "ts-node src/index.ts",
8
- "start": "node dist/index.js",
9
- "test": "vitest run",
10
- "test:watch": "vitest"
11
- },
12
- "dependencies": {
13
- "@temporalio/activity": "^1.11.6",
14
- "@temporalio/client": "^1.11.6",
15
- "@temporalio/worker": "^1.11.6",
16
- "@temporalio/workflow": "^1.11.6",
17
- "axios": "^1.7.9",
18
- "dotenv": "^16.4.7",
19
- "pg": "^8.16.3"
20
- },
21
- "devDependencies": {
22
- "@types/node": "^22.0.0",
23
- "@types/pg": "^8.11.0",
24
- "ts-node": "^10.9.2",
25
- "typescript": "^5.7.0",
26
- "vitest": "^3.1.0"
27
- }
28
- }
@@ -1,51 +0,0 @@
1
- export interface CodeExecuteInput {
2
- script: string;
3
- mode?: 'runOnceForAll' | 'runOnceForEach';
4
- timeout?: number;
5
- data?: any;
6
- items?: any[];
7
- }
8
-
9
- export interface CodeExecuteOutput {
10
- result: any;
11
- }
12
-
13
- /**
14
- * Execute custom JavaScript code in a sandboxed environment.
15
- * Uses Node.js vm module for basic isolation.
16
- * For production, consider isolated-vm for stronger sandboxing.
17
- */
18
- export async function codeExecute(input: CodeExecuteInput): Promise<CodeExecuteOutput> {
19
- const { script, mode = 'runOnceForAll', timeout = 5000, data, items } = input;
20
- const vm = await import('vm');
21
-
22
- if (mode === 'runOnceForEach' && Array.isArray(items)) {
23
- const results: any[] = [];
24
- for (const item of items) {
25
- const sandbox = {
26
- item,
27
- data,
28
- console: { log: () => {} },
29
- result: undefined as any,
30
- };
31
- const context = vm.createContext(sandbox);
32
- const wrappedScript = new vm.Script(`result = (function() { ${script} })()`);
33
- wrappedScript.runInContext(context, { timeout });
34
- results.push(sandbox.result);
35
- }
36
- return { result: results };
37
- }
38
-
39
- // runOnceForAll
40
- const sandbox = {
41
- data,
42
- items: items || [],
43
- console: { log: () => {} },
44
- result: undefined as any,
45
- };
46
- const context = vm.createContext(sandbox);
47
- const wrappedScript = new vm.Script(`result = (function() { ${script} })()`);
48
- wrappedScript.runInContext(context, { timeout });
49
-
50
- return { result: sandbox.result };
51
- }
@@ -1,85 +0,0 @@
1
- import { Pool } from 'pg';
2
- import { config } from '../config';
3
-
4
- const pool = new Pool({ connectionString: config.database.url });
5
-
6
- export interface DbExecuteInput {
7
- operation: 'insert' | 'update' | 'delete' | 'raw';
8
- table?: string;
9
- data?: Record<string, any>;
10
- where?: string;
11
- rawSql?: string;
12
- params?: any[];
13
- datasource?: string;
14
- timeout?: number;
15
- }
16
-
17
- export interface DbExecuteOutput {
18
- affectedRows: number;
19
- insertedId?: string;
20
- }
21
-
22
- /**
23
- * Execute a database write operation (INSERT/UPDATE/DELETE).
24
- */
25
- export async function dbExecute(input: DbExecuteInput): Promise<DbExecuteOutput> {
26
- const client = await pool.connect();
27
- try {
28
- if (input.timeout) {
29
- await client.query(`SET statement_timeout = ${input.timeout}`);
30
- }
31
-
32
- let query: string;
33
- let params: any[] = [];
34
-
35
- switch (input.operation) {
36
- case 'raw':
37
- query = input.rawSql || '';
38
- params = input.params || [];
39
- break;
40
-
41
- case 'insert': {
42
- if (!input.table || !input.data) throw new Error('table and data required for insert');
43
- const keys = Object.keys(input.data);
44
- const values = Object.values(input.data);
45
- const placeholders = keys.map((_, i) => `$${i + 1}`);
46
- query = `INSERT INTO ${input.table} (${keys.join(', ')}) VALUES (${placeholders.join(', ')}) RETURNING id`;
47
- params = values;
48
- break;
49
- }
50
-
51
- case 'update': {
52
- if (!input.table || !input.data) throw new Error('table and data required for update');
53
- const entries = Object.entries(input.data);
54
- const sets = entries.map(([k], i) => `${k} = $${i + 1}`);
55
- params = entries.map(([, v]) => v);
56
- query = `UPDATE ${input.table} SET ${sets.join(', ')}`;
57
- if (input.where) {
58
- query += ` WHERE ${input.where}`;
59
- }
60
- break;
61
- }
62
-
63
- case 'delete': {
64
- if (!input.table) throw new Error('table required for delete');
65
- query = `DELETE FROM ${input.table}`;
66
- if (input.where) {
67
- query += ` WHERE ${input.where}`;
68
- }
69
- params = input.params || [];
70
- break;
71
- }
72
-
73
- default:
74
- throw new Error(`Unknown operation: ${input.operation}`);
75
- }
76
-
77
- const result = await client.query(query, params);
78
- return {
79
- affectedRows: result.rowCount || 0,
80
- insertedId: result.rows?.[0]?.id?.toString(),
81
- };
82
- } finally {
83
- client.release();
84
- }
85
- }
@@ -1,35 +0,0 @@
1
- import { Pool } from 'pg';
2
- import { config } from '../config';
3
-
4
- const pool = new Pool({ connectionString: config.database.url });
5
-
6
- export interface DbQueryInput {
7
- query: string;
8
- params?: any[];
9
- datasource?: string;
10
- timeout?: number;
11
- }
12
-
13
- export interface DbQueryOutput {
14
- rows: any[];
15
- rowCount: number;
16
- }
17
-
18
- /**
19
- * Execute a database SELECT query.
20
- */
21
- export async function dbQuery(input: DbQueryInput): Promise<DbQueryOutput> {
22
- const client = await pool.connect();
23
- try {
24
- if (input.timeout) {
25
- await client.query(`SET statement_timeout = ${input.timeout}`);
26
- }
27
- const result = await client.query(input.query, input.params || []);
28
- return {
29
- rows: result.rows,
30
- rowCount: result.rowCount || 0,
31
- };
32
- } finally {
33
- client.release();
34
- }
35
- }
@@ -1,54 +0,0 @@
1
- import axios, { AxiosRequestConfig } from 'axios';
2
-
3
- export interface HttpRequestInput {
4
- url: string;
5
- method: string;
6
- headers?: Record<string, string>;
7
- body?: any;
8
- timeout?: number;
9
- authentication?: string;
10
- followRedirects?: boolean;
11
- responseFormat?: 'json' | 'text' | 'binary';
12
- ignoreSslErrors?: boolean;
13
- }
14
-
15
- export interface HttpRequestOutput {
16
- status: number;
17
- data: any;
18
- headers: Record<string, string>;
19
- }
20
-
21
- /**
22
- * Execute an HTTP request activity.
23
- */
24
- export async function httpRequest(input: HttpRequestInput): Promise<HttpRequestOutput> {
25
- const axiosConfig: AxiosRequestConfig = {
26
- url: input.url,
27
- method: input.method.toLowerCase() as any,
28
- headers: input.headers || {},
29
- timeout: input.timeout || 30000,
30
- maxRedirects: input.followRedirects === false ? 0 : 5,
31
- validateStatus: () => true, // Don't throw on non-2xx
32
- };
33
-
34
- if (input.body && ['post', 'put', 'patch'].includes(axiosConfig.method as string)) {
35
- axiosConfig.data = input.body;
36
- }
37
-
38
- if (input.ignoreSslErrors) {
39
- const https = await import('https');
40
- axiosConfig.httpsAgent = new https.Agent({ rejectUnauthorized: false });
41
- }
42
-
43
- if (input.responseFormat === 'binary') {
44
- axiosConfig.responseType = 'arraybuffer';
45
- }
46
-
47
- const response = await axios(axiosConfig);
48
-
49
- return {
50
- status: response.status,
51
- data: response.data,
52
- headers: response.headers as Record<string, string>,
53
- };
54
- }
@@ -1,6 +0,0 @@
1
- export { httpRequest } from './http-request';
2
- export { dbQuery } from './db-query';
3
- export { dbExecute } from './db-execute';
4
- export { sendNotification } from './send-notification';
5
- export { codeExecute } from './code-execute';
6
- export { reportNodeStatus, reportWorkflowStatus, createCronInstance } from './reporting';
@@ -1,85 +0,0 @@
1
- import { Pool } from 'pg';
2
- import { config } from '../config';
3
- import { ReportNodeStatusInput, ReportWorkflowStatusInput } from '../dsl/types';
4
-
5
- const pool = new Pool({ connectionString: config.database.url });
6
-
7
- /**
8
- * Report a node's execution status to the database.
9
- */
10
- export async function reportNodeStatus(input: ReportNodeStatusInput): Promise<void> {
11
- const { instanceId, nodeId, nodeType, nodeLabel, status, input: nodeInput, output, error } = input;
12
-
13
- if (status === 'RUNNING') {
14
- // Create or update node execution record with RUNNING status
15
- await pool.query(
16
- `INSERT INTO t_workflow_node_execution (instance_id, node_id, node_type, node_label, status, input, started_at, created_at, updated_at)
17
- VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW(), NOW())
18
- ON CONFLICT (instance_id, node_id) DO UPDATE SET
19
- status = $5, input = $6, started_at = NOW(), updated_at = NOW()`,
20
- [instanceId, nodeId, nodeType, nodeLabel || null, status, nodeInput ? JSON.stringify(nodeInput) : null],
21
- );
22
- } else {
23
- // Update with final status
24
- await pool.query(
25
- `UPDATE t_workflow_node_execution
26
- SET status = $1, output = $2, error = $3, finished_at = NOW(), updated_at = NOW()
27
- WHERE instance_id = $4 AND node_id = $5`,
28
- [status, output ? JSON.stringify(output) : null, error ? JSON.stringify(error) : null, instanceId, nodeId],
29
- );
30
- }
31
- }
32
-
33
- /**
34
- * Create a workflow instance for a cron-triggered run.
35
- * Used by cronTriggerWorkflow before delegating to dslWorkflow.
36
- */
37
- export async function createCronInstance(input: {
38
- workflowId: number;
39
- versionId: number;
40
- scheduleId: string;
41
- }): Promise<{ instanceId: number }> {
42
- const { rows } = await pool.query(
43
- `INSERT INTO t_workflow_instance
44
- (workflow_id, version_id, status, context, creator, created_at, updated_at)
45
- VALUES ($1, $2, 'PENDING', $3, 'cron', NOW(), NOW())
46
- RETURNING id`,
47
- [
48
- input.workflowId,
49
- input.versionId,
50
- JSON.stringify({ scheduleId: input.scheduleId, scheduledAt: new Date().toISOString() }),
51
- ],
52
- );
53
- return { instanceId: Number(rows[0].id) };
54
- }
55
-
56
- /**
57
- * Report overall workflow execution status.
58
- */
59
- export async function reportWorkflowStatus(input: ReportWorkflowStatusInput): Promise<void> {
60
- const { instanceId, status, result } = input;
61
-
62
- const updates: string[] = ['status = $1', 'updated_at = NOW()'];
63
- const values: any[] = [status];
64
- let paramIdx = 2;
65
-
66
- if (status === 'RUNNING') {
67
- updates.push(`started_at = NOW()`);
68
- }
69
-
70
- if (status === 'COMPLETED' || status === 'FAILED' || status === 'CANCELLED') {
71
- updates.push(`finished_at = NOW()`);
72
- }
73
-
74
- if (result !== undefined) {
75
- updates.push(`result = $${paramIdx}`);
76
- values.push(JSON.stringify(result));
77
- paramIdx++;
78
- }
79
-
80
- values.push(instanceId);
81
- await pool.query(
82
- `UPDATE t_workflow_instance SET ${updates.join(', ')} WHERE id = $${paramIdx}`,
83
- values,
84
- );
85
- }
@@ -1,47 +0,0 @@
1
- export interface SendNotificationInput {
2
- channel: 'email' | 'slack' | 'webhook' | 'dingtalk' | 'wecom';
3
- recipients: string[];
4
- subject?: string;
5
- message: string;
6
- templateId?: string;
7
- }
8
-
9
- export interface SendNotificationOutput {
10
- sent: boolean;
11
- messageId: string;
12
- }
13
-
14
- /**
15
- * Send a notification via the configured channel.
16
- * Currently stubs — implement actual integrations as needed.
17
- */
18
- export async function sendNotification(input: SendNotificationInput): Promise<SendNotificationOutput> {
19
- const { channel, recipients, subject, message } = input;
20
-
21
- console.log(`[Notification] channel=${channel} recipients=${recipients.join(',')} subject=${subject || ''}`);
22
- console.log(`[Notification] message: ${message}`);
23
-
24
- // TODO: Implement actual notification channels
25
- // For now, log and return success
26
- switch (channel) {
27
- case 'webhook': {
28
- // For webhook channel, POST to each recipient URL
29
- const axios = (await import('axios')).default;
30
- for (const url of recipients) {
31
- await axios.post(url, { subject, message });
32
- }
33
- break;
34
- }
35
- case 'email':
36
- case 'slack':
37
- case 'dingtalk':
38
- case 'wecom':
39
- // Stub: log only
40
- break;
41
- }
42
-
43
- return {
44
- sent: true,
45
- messageId: `notif_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
46
- };
47
- }
@@ -1,13 +0,0 @@
1
- import * as dotenv from 'dotenv';
2
- dotenv.config();
3
-
4
- export const config = {
5
- temporal: {
6
- address: process.env.TEMPORAL_ADDRESS || 'localhost:7233',
7
- namespace: process.env.TEMPORAL_NAMESPACE || 'default',
8
- taskQueue: process.env.TEMPORAL_TASK_QUEUE || 'workflow-execution',
9
- },
10
- database: {
11
- url: process.env.DATABASE_URL || 'postgresql://kavenma:kavenma@127.0.0.1:5432/gadmin_demo?schema=public',
12
- },
13
- };
@@ -1,101 +0,0 @@
1
- /**
2
- * Condition evaluation for if_else and switch nodes.
3
- */
4
-
5
- export interface ConditionRule {
6
- field: string;
7
- operator: string;
8
- value: string;
9
- }
10
-
11
- /**
12
- * Evaluate a single condition rule against a context value.
13
- */
14
- export function evaluateRule(fieldValue: any, operator: string, compareValue: string): boolean {
15
- switch (operator) {
16
- case 'equals':
17
- case '==':
18
- return String(fieldValue) === compareValue;
19
- case 'notEquals':
20
- case '!=':
21
- return String(fieldValue) !== compareValue;
22
- case 'contains':
23
- return String(fieldValue).includes(compareValue);
24
- case 'notContains':
25
- return !String(fieldValue).includes(compareValue);
26
- case 'startsWith':
27
- return String(fieldValue).startsWith(compareValue);
28
- case 'endsWith':
29
- return String(fieldValue).endsWith(compareValue);
30
- case 'greaterThan':
31
- case '>':
32
- return Number(fieldValue) > Number(compareValue);
33
- case 'lessThan':
34
- case '<':
35
- return Number(fieldValue) < Number(compareValue);
36
- case 'greaterThanOrEqual':
37
- case '>=':
38
- return Number(fieldValue) >= Number(compareValue);
39
- case 'lessThanOrEqual':
40
- case '<=':
41
- return Number(fieldValue) <= Number(compareValue);
42
- case 'isEmpty':
43
- return fieldValue == null || fieldValue === '' || (Array.isArray(fieldValue) && fieldValue.length === 0);
44
- case 'isNotEmpty':
45
- return fieldValue != null && fieldValue !== '' && !(Array.isArray(fieldValue) && fieldValue.length === 0);
46
- case 'regex':
47
- try {
48
- return new RegExp(compareValue).test(String(fieldValue));
49
- } catch {
50
- return false;
51
- }
52
- default:
53
- return false;
54
- }
55
- }
56
-
57
- /**
58
- * Evaluate multiple condition rules with AND/OR combinator.
59
- */
60
- export function evaluateConditions(
61
- conditions: ConditionRule[],
62
- contextData: Record<string, any>,
63
- combineOperation: 'AND' | 'OR' = 'AND',
64
- ): boolean {
65
- if (conditions.length === 0) return true;
66
-
67
- const results = conditions.map((rule) => {
68
- const fieldValue = getNestedValue(contextData, rule.field);
69
- return evaluateRule(fieldValue, rule.operator, rule.value);
70
- });
71
-
72
- return combineOperation === 'AND'
73
- ? results.every(Boolean)
74
- : results.some(Boolean);
75
- }
76
-
77
- /**
78
- * Evaluate a switch node — returns the matched case value or "default".
79
- */
80
- export function evaluateSwitch(
81
- field: string,
82
- cases: Array<{ value: string; label: string }>,
83
- contextData: Record<string, any>,
84
- ): string {
85
- const fieldValue = String(getNestedValue(contextData, field) ?? '');
86
- const matched = cases.find((c) => c.value === fieldValue);
87
- return matched ? matched.value : 'default';
88
- }
89
-
90
- /**
91
- * Get a nested value from an object using dot-notation path.
92
- */
93
- function getNestedValue(obj: Record<string, any>, path: string): any {
94
- const parts = path.split('.');
95
- let current: any = obj;
96
- for (const part of parts) {
97
- if (current == null) return undefined;
98
- current = current[part];
99
- }
100
- return current;
101
- }
@@ -1,58 +0,0 @@
1
- /**
2
- * Workflow execution context — a shared data store that flows between nodes.
3
- * Each node can read from context and write its output back.
4
- */
5
- export class ExecutionContext {
6
- private data: Record<string, any>;
7
-
8
- constructor(initialData: Record<string, any> = {}) {
9
- this.data = { ...initialData };
10
- }
11
-
12
- /** Get a value by dot-notation path (e.g. "node1.data.email") */
13
- get(path: string): any {
14
- const parts = path.split('.');
15
- let current: any = this.data;
16
- for (const part of parts) {
17
- if (current == null) return undefined;
18
- current = current[part];
19
- }
20
- return current;
21
- }
22
-
23
- /** Set a value by key */
24
- set(key: string, value: any): void {
25
- this.data[key] = value;
26
- }
27
-
28
- /** Merge node output into context under the node's ID */
29
- mergeNodeOutput(nodeId: string, output: Record<string, any>): void {
30
- this.data[nodeId] = output;
31
- }
32
-
33
- /** Get the full context object */
34
- toJSON(): Record<string, any> {
35
- return { ...this.data };
36
- }
37
-
38
- /** Resolve template strings like "{{node1.data.email}}" within a value */
39
- resolveTemplates(value: any): any {
40
- if (typeof value === 'string') {
41
- return value.replace(/\{\{(.+?)\}\}/g, (_, path) => {
42
- const resolved = this.get(path.trim());
43
- return resolved !== undefined ? String(resolved) : '';
44
- });
45
- }
46
- if (Array.isArray(value)) {
47
- return value.map((v) => this.resolveTemplates(v));
48
- }
49
- if (value && typeof value === 'object') {
50
- const result: Record<string, any> = {};
51
- for (const [k, v] of Object.entries(value)) {
52
- result[k] = this.resolveTemplates(v);
53
- }
54
- return result;
55
- }
56
- return value;
57
- }
58
- }