@quanticjs/workflow-quanticflow 3.3.0
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.
- package/README.md +193 -0
- package/dist/QuanticFlowCallbackController.d.ts +24 -0
- package/dist/QuanticFlowCallbackController.js +91 -0
- package/dist/QuanticFlowClient.d.ts +59 -0
- package/dist/QuanticFlowClient.js +79 -0
- package/dist/QuanticFlowWorkflowEngine.d.ts +13 -0
- package/dist/QuanticFlowWorkflowEngine.js +48 -0
- package/dist/QuanticFlowWorkflowModule.d.ts +22 -0
- package/dist/QuanticFlowWorkflowModule.js +82 -0
- package/dist/ServiceTaskEventConsumer.d.ts +20 -0
- package/dist/ServiceTaskEventConsumer.js +86 -0
- package/dist/ServiceTaskHandlerRegistry.d.ts +25 -0
- package/dist/ServiceTaskHandlerRegistry.js +49 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +17 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# @quanticjs/workflow-quanticflow
|
|
2
|
+
|
|
3
|
+
QuanticFlow workflow engine adapter for `@quanticjs/workflow`. Connects any QuanticJS application to a standalone [QuanticFlow](https://github.com/quanticjs/quanticflow) instance via REST API.
|
|
4
|
+
|
|
5
|
+
Supports two modes for service task execution:
|
|
6
|
+
|
|
7
|
+
| Mode | Transport | How it works |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| **Callback** | HTTP webhook | QuanticFlow POSTs to your app's `/workflow-callback/service-task` endpoint |
|
|
10
|
+
| **Event** | Redis Streams | Your app consumes `ServiceTaskStartedEvent` from Redis and signals back via REST |
|
|
11
|
+
|
|
12
|
+
Both modes can run simultaneously (`mode: 'both'`).
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @quanticjs/workflow-quanticflow
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { Module } from '@nestjs/common';
|
|
24
|
+
import { QuanticFlowWorkflowModule } from '@quanticjs/workflow-quanticflow';
|
|
25
|
+
import { QuanticWorkflowModule } from '@quanticjs/workflow';
|
|
26
|
+
|
|
27
|
+
@Module({
|
|
28
|
+
imports: [
|
|
29
|
+
// 1. Register the QuanticFlow engine adapter
|
|
30
|
+
QuanticFlowWorkflowModule.forRoot({
|
|
31
|
+
url: 'http://quanticflow:3000',
|
|
32
|
+
serviceTaskHandling: {
|
|
33
|
+
mode: 'both', // 'callback' | 'event' | 'both'
|
|
34
|
+
callbackSecret: process.env.CALLBACK_SECRET,
|
|
35
|
+
},
|
|
36
|
+
}),
|
|
37
|
+
|
|
38
|
+
// 2. Wire the @Workflow decorator into the CQRS pipeline
|
|
39
|
+
QuanticWorkflowModule.forRoot(),
|
|
40
|
+
],
|
|
41
|
+
})
|
|
42
|
+
export class AppModule {}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Now any command decorated with `@Workflow` will be routed to QuanticFlow:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { Workflow } from '@quanticjs/core';
|
|
49
|
+
|
|
50
|
+
@Workflow('expense-approval')
|
|
51
|
+
@Validate(CreateExpenseValidator)
|
|
52
|
+
export class CreateExpenseCommand {
|
|
53
|
+
constructor(
|
|
54
|
+
readonly amount: number,
|
|
55
|
+
readonly category: string,
|
|
56
|
+
) {}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Service Task Handlers
|
|
61
|
+
|
|
62
|
+
Register handlers that execute when QuanticFlow reaches a service task node:
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { Injectable } from '@nestjs/common';
|
|
66
|
+
import { ServiceTaskHandler, ServiceTaskContext, ServiceTaskResult } from '@quanticjs/workflow-quanticflow';
|
|
67
|
+
|
|
68
|
+
@Injectable()
|
|
69
|
+
export class SendEmailHandler implements ServiceTaskHandler {
|
|
70
|
+
constructor(private readonly mailer: MailerService) {}
|
|
71
|
+
|
|
72
|
+
async execute(context: ServiceTaskContext): Promise<ServiceTaskResult> {
|
|
73
|
+
await this.mailer.send({
|
|
74
|
+
to: context.variables.recipientEmail,
|
|
75
|
+
subject: `Process ${context.correlationId} update`,
|
|
76
|
+
});
|
|
77
|
+
return { signal: 'email-sent', data: { sentAt: new Date() } };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Register handlers in your module — the registry resolves them by name from the DI container:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
@Module({
|
|
86
|
+
providers: [SendEmailHandler],
|
|
87
|
+
})
|
|
88
|
+
export class NotificationsModule {}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The handler name in the BPMN definition must match the class name (e.g., `SendEmailHandler`).
|
|
92
|
+
|
|
93
|
+
## Configuration
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
QuanticFlowWorkflowModule.forRoot({
|
|
97
|
+
// Required
|
|
98
|
+
url: 'http://quanticflow:3000',
|
|
99
|
+
|
|
100
|
+
// Optional
|
|
101
|
+
requestTimeout: 10000, // HTTP timeout in ms (default: 10000)
|
|
102
|
+
|
|
103
|
+
serviceTaskHandling: {
|
|
104
|
+
mode: 'callback', // 'callback' | 'event' | 'both'
|
|
105
|
+
|
|
106
|
+
// Callback mode options
|
|
107
|
+
callbackSecret: 'hmac-secret', // HMAC-SHA256 signature verification
|
|
108
|
+
|
|
109
|
+
// Event mode options (requires ioredis + @quanticjs/redis)
|
|
110
|
+
streamKey: 'arex:events:services', // Redis stream (default)
|
|
111
|
+
consumerGroup: 'my-app-tasks', // Consumer group name
|
|
112
|
+
consumerName: 'worker-1', // Consumer name (default: consumer-{pid})
|
|
113
|
+
},
|
|
114
|
+
})
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Using the Client Directly
|
|
118
|
+
|
|
119
|
+
The `QuanticFlowClient` is exported for direct REST API access beyond the `WorkflowEngine` interface:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { QuanticFlowClient } from '@quanticjs/workflow-quanticflow';
|
|
123
|
+
|
|
124
|
+
@Injectable()
|
|
125
|
+
export class WorkflowDashboardService {
|
|
126
|
+
constructor(private readonly qf: QuanticFlowClient) {}
|
|
127
|
+
|
|
128
|
+
async getMyTasks(userId: string) {
|
|
129
|
+
return this.qf.listTasks({ userId, status: 'pending' });
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async approveTask(taskId: string) {
|
|
133
|
+
return this.qf.executeTaskAction(taskId, 'approve', { comment: 'Looks good' });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Client Methods
|
|
139
|
+
|
|
140
|
+
| Method | Endpoint | Description |
|
|
141
|
+
|---|---|---|
|
|
142
|
+
| `startInstance(definitionId, variables?, correlationId?)` | `POST /workflow/instances` | Start a workflow |
|
|
143
|
+
| `signalInstance(instanceId, signal, data?)` | `POST /workflow/instances/:id/signal` | Send signal |
|
|
144
|
+
| `abortInstance(instanceId)` | `POST /workflow/instances/:id/abort` | Abort workflow |
|
|
145
|
+
| `getInstance(instanceId)` | `GET /workflow/instances/:id` | Get instance detail |
|
|
146
|
+
| `updateVariables(instanceId, variables)` | `PUT /workflow/instances/:id/variables` | Update variables |
|
|
147
|
+
| `listTasks(filters?)` | `GET /workflow/tasks` | List tasks |
|
|
148
|
+
| `getTask(taskId)` | `GET /workflow/tasks/:id` | Get task detail |
|
|
149
|
+
| `claimTask(taskId)` | `POST /workflow/tasks/:id/claim` | Claim task |
|
|
150
|
+
| `executeTaskAction(taskId, action, data?)` | `POST /workflow/tasks/:id/action` | Execute action |
|
|
151
|
+
|
|
152
|
+
## Architecture
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
┌──────────────────────────────────────────────┐
|
|
156
|
+
│ Your NestJS App │
|
|
157
|
+
│ │
|
|
158
|
+
│ @Workflow('expense') │
|
|
159
|
+
│ CreateExpenseCommand ──▶ WorkflowBehavior │
|
|
160
|
+
│ │ │
|
|
161
|
+
│ ┌─────────▼──────────┐ │
|
|
162
|
+
│ │ QuanticFlowWorkflow │ │
|
|
163
|
+
│ │ Engine (HTTP) │ │
|
|
164
|
+
│ └─────────┬──────────┘ │
|
|
165
|
+
│ │ │
|
|
166
|
+
│ ┌───────────────────────────┼────────────┐ │
|
|
167
|
+
│ │ Service Task Handling │ │ │
|
|
168
|
+
│ │ │ │ │
|
|
169
|
+
│ │ ┌─────────────┐ ┌──────▼─────────┐ │ │
|
|
170
|
+
│ │ │ Callback │ │ Event │ │ │
|
|
171
|
+
│ │ │ Controller │ │ Consumer │ │ │
|
|
172
|
+
│ │ │ (webhook) │ │ (Redis Stream)│ │ │
|
|
173
|
+
│ │ └──────┬──────┘ └──────┬─────────┘ │ │
|
|
174
|
+
│ │ │ │ │ │
|
|
175
|
+
│ │ ▼ ▼ │ │
|
|
176
|
+
│ │ ServiceTaskHandlerRegistry │ │
|
|
177
|
+
│ │ │ │ │
|
|
178
|
+
│ │ ▼ │ │
|
|
179
|
+
│ │ SendEmailHandler (your code) │ │
|
|
180
|
+
│ └────────────────────────────────────────┘ │
|
|
181
|
+
└──────────────────────────────────────────────┘
|
|
182
|
+
│
|
|
183
|
+
│ HTTP / Redis
|
|
184
|
+
▼
|
|
185
|
+
┌──────────────────┐
|
|
186
|
+
│ QuanticFlow │
|
|
187
|
+
│ (standalone) │
|
|
188
|
+
└──────────────────┘
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## License
|
|
192
|
+
|
|
193
|
+
MIT
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { QuanticFlowClient } from './QuanticFlowClient';
|
|
2
|
+
import { ServiceTaskHandlerRegistry } from './ServiceTaskHandlerRegistry';
|
|
3
|
+
import { QuanticFlowWorkflowModuleOptions } from './QuanticFlowWorkflowModule';
|
|
4
|
+
export interface ServiceTaskCallbackPayload {
|
|
5
|
+
instanceId: string;
|
|
6
|
+
definitionId: string;
|
|
7
|
+
stateName: string;
|
|
8
|
+
handlerName: string;
|
|
9
|
+
correlationId?: string;
|
|
10
|
+
variables: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
export interface ServiceTaskCallbackResponse {
|
|
13
|
+
signal: string;
|
|
14
|
+
data?: unknown;
|
|
15
|
+
}
|
|
16
|
+
export declare class QuanticFlowCallbackController {
|
|
17
|
+
private readonly registry;
|
|
18
|
+
private readonly client;
|
|
19
|
+
private readonly logger;
|
|
20
|
+
private readonly callbackSecret?;
|
|
21
|
+
constructor(registry: ServiceTaskHandlerRegistry, client: QuanticFlowClient, options: QuanticFlowWorkflowModuleOptions);
|
|
22
|
+
handleServiceTask(payload: ServiceTaskCallbackPayload, signature?: string): Promise<ServiceTaskCallbackResponse>;
|
|
23
|
+
private verifySignature;
|
|
24
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var QuanticFlowCallbackController_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.QuanticFlowCallbackController = void 0;
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const QuanticFlowClient_1 = require("./QuanticFlowClient");
|
|
19
|
+
const ServiceTaskHandlerRegistry_1 = require("./ServiceTaskHandlerRegistry");
|
|
20
|
+
const QuanticFlowWorkflowModule_1 = require("./QuanticFlowWorkflowModule");
|
|
21
|
+
const crypto_1 = require("crypto");
|
|
22
|
+
let QuanticFlowCallbackController = QuanticFlowCallbackController_1 = class QuanticFlowCallbackController {
|
|
23
|
+
registry;
|
|
24
|
+
client;
|
|
25
|
+
logger = new common_1.Logger(QuanticFlowCallbackController_1.name);
|
|
26
|
+
callbackSecret;
|
|
27
|
+
constructor(registry, client, options) {
|
|
28
|
+
this.registry = registry;
|
|
29
|
+
this.client = client;
|
|
30
|
+
this.callbackSecret = options.serviceTaskHandling?.callbackSecret;
|
|
31
|
+
}
|
|
32
|
+
async handleServiceTask(payload, signature) {
|
|
33
|
+
this.verifySignature(payload, signature);
|
|
34
|
+
this.logger.log(`Service task callback: handler=${payload.handlerName}, instance=${payload.instanceId}`);
|
|
35
|
+
const handler = await this.registry.resolve(payload.handlerName);
|
|
36
|
+
if (!handler) {
|
|
37
|
+
this.logger.error(`No handler registered for "${payload.handlerName}"`);
|
|
38
|
+
await this.client.signalInstance(payload.instanceId, 'handler-not-found', {
|
|
39
|
+
error: `Handler "${payload.handlerName}" not registered`,
|
|
40
|
+
});
|
|
41
|
+
return { signal: 'handler-not-found' };
|
|
42
|
+
}
|
|
43
|
+
const context = {
|
|
44
|
+
instanceId: payload.instanceId,
|
|
45
|
+
definitionId: payload.definitionId,
|
|
46
|
+
stateName: payload.stateName,
|
|
47
|
+
handlerName: payload.handlerName,
|
|
48
|
+
correlationId: payload.correlationId,
|
|
49
|
+
variables: payload.variables,
|
|
50
|
+
};
|
|
51
|
+
try {
|
|
52
|
+
const result = await handler.execute(context);
|
|
53
|
+
this.logger.log(`Handler "${payload.handlerName}" completed with signal="${result.signal}"`);
|
|
54
|
+
return { signal: result.signal, data: result.data };
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
58
|
+
this.logger.error(`Handler "${payload.handlerName}" failed: ${message}`);
|
|
59
|
+
return { signal: 'handler-error', data: { error: message } };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
verifySignature(payload, signature) {
|
|
63
|
+
if (!this.callbackSecret)
|
|
64
|
+
return;
|
|
65
|
+
if (!signature) {
|
|
66
|
+
throw new common_1.ForbiddenException('Missing callback signature');
|
|
67
|
+
}
|
|
68
|
+
const expected = (0, crypto_1.createHmac)('sha256', this.callbackSecret)
|
|
69
|
+
.update(JSON.stringify(payload))
|
|
70
|
+
.digest('hex');
|
|
71
|
+
if (signature !== expected) {
|
|
72
|
+
throw new common_1.ForbiddenException('Invalid callback signature');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
exports.QuanticFlowCallbackController = QuanticFlowCallbackController;
|
|
77
|
+
__decorate([
|
|
78
|
+
(0, common_1.Post)('service-task'),
|
|
79
|
+
(0, common_1.HttpCode)(200),
|
|
80
|
+
__param(0, (0, common_1.Body)()),
|
|
81
|
+
__param(1, (0, common_1.Headers)('x-callback-signature')),
|
|
82
|
+
__metadata("design:type", Function),
|
|
83
|
+
__metadata("design:paramtypes", [Object, String]),
|
|
84
|
+
__metadata("design:returntype", Promise)
|
|
85
|
+
], QuanticFlowCallbackController.prototype, "handleServiceTask", null);
|
|
86
|
+
exports.QuanticFlowCallbackController = QuanticFlowCallbackController = QuanticFlowCallbackController_1 = __decorate([
|
|
87
|
+
(0, common_1.Controller)('workflow-callback'),
|
|
88
|
+
__param(2, (0, common_1.Inject)(QuanticFlowWorkflowModule_1.QUANTICFLOW_OPTIONS)),
|
|
89
|
+
__metadata("design:paramtypes", [ServiceTaskHandlerRegistry_1.ServiceTaskHandlerRegistry,
|
|
90
|
+
QuanticFlowClient_1.QuanticFlowClient, Object])
|
|
91
|
+
], QuanticFlowCallbackController);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { HttpService } from '@nestjs/axios';
|
|
2
|
+
export interface QuanticFlowInstance {
|
|
3
|
+
id: string;
|
|
4
|
+
definitionId: string;
|
|
5
|
+
definitionVersion: string;
|
|
6
|
+
status: string;
|
|
7
|
+
currentState: string;
|
|
8
|
+
variables: Record<string, unknown>;
|
|
9
|
+
correlationId: string | null;
|
|
10
|
+
startedBy: string;
|
|
11
|
+
completedAt: string | null;
|
|
12
|
+
createdAt: string;
|
|
13
|
+
updatedAt: string;
|
|
14
|
+
}
|
|
15
|
+
export interface QuanticFlowTask {
|
|
16
|
+
id: string;
|
|
17
|
+
processInstanceId: string;
|
|
18
|
+
stateName: string;
|
|
19
|
+
taskType: string;
|
|
20
|
+
taskName: string;
|
|
21
|
+
assignedRole: string;
|
|
22
|
+
assignedUserId: string | null;
|
|
23
|
+
status: string;
|
|
24
|
+
actions: Array<{
|
|
25
|
+
name: string;
|
|
26
|
+
label: string;
|
|
27
|
+
roles: string[];
|
|
28
|
+
}>;
|
|
29
|
+
outcome: string | null;
|
|
30
|
+
outputData: Record<string, unknown> | null;
|
|
31
|
+
formSchema: Record<string, unknown> | null;
|
|
32
|
+
formData: Record<string, unknown> | null;
|
|
33
|
+
dueAt: string | null;
|
|
34
|
+
completedBy: string | null;
|
|
35
|
+
completedAt: string | null;
|
|
36
|
+
createdAt: string;
|
|
37
|
+
updatedAt: string;
|
|
38
|
+
}
|
|
39
|
+
export interface PaginatedResult<T> {
|
|
40
|
+
items: T[];
|
|
41
|
+
total: number;
|
|
42
|
+
page: number;
|
|
43
|
+
limit: number;
|
|
44
|
+
totalPages: number;
|
|
45
|
+
}
|
|
46
|
+
export declare class QuanticFlowClient {
|
|
47
|
+
private readonly httpService;
|
|
48
|
+
private readonly logger;
|
|
49
|
+
constructor(httpService: HttpService);
|
|
50
|
+
startInstance(definitionId: string, variables?: Record<string, unknown>, correlationId?: string): Promise<QuanticFlowInstance>;
|
|
51
|
+
signalInstance(instanceId: string, signalName: string, signalData?: unknown): Promise<QuanticFlowInstance>;
|
|
52
|
+
abortInstance(instanceId: string): Promise<QuanticFlowInstance>;
|
|
53
|
+
getInstance(instanceId: string): Promise<QuanticFlowInstance>;
|
|
54
|
+
updateVariables(instanceId: string, variables: Record<string, unknown>): Promise<QuanticFlowInstance>;
|
|
55
|
+
listTasks(filters?: Record<string, string | number>): Promise<PaginatedResult<QuanticFlowTask>>;
|
|
56
|
+
getTask(taskId: string): Promise<QuanticFlowTask>;
|
|
57
|
+
claimTask(taskId: string): Promise<QuanticFlowTask>;
|
|
58
|
+
executeTaskAction(taskId: string, actionName: string, actionData?: Record<string, unknown>): Promise<QuanticFlowTask>;
|
|
59
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var QuanticFlowClient_1;
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.QuanticFlowClient = void 0;
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const axios_1 = require("@nestjs/axios");
|
|
16
|
+
const rxjs_1 = require("rxjs");
|
|
17
|
+
let QuanticFlowClient = QuanticFlowClient_1 = class QuanticFlowClient {
|
|
18
|
+
httpService;
|
|
19
|
+
logger = new common_1.Logger(QuanticFlowClient_1.name);
|
|
20
|
+
constructor(httpService) {
|
|
21
|
+
this.httpService = httpService;
|
|
22
|
+
}
|
|
23
|
+
async startInstance(definitionId, variables, correlationId) {
|
|
24
|
+
const { data } = await (0, rxjs_1.firstValueFrom)(this.httpService.post('/workflow/instances', {
|
|
25
|
+
definitionId,
|
|
26
|
+
variables,
|
|
27
|
+
correlationId,
|
|
28
|
+
}));
|
|
29
|
+
this.logger.log(`Started instance ${data.id} for definition ${definitionId}`);
|
|
30
|
+
return data;
|
|
31
|
+
}
|
|
32
|
+
async signalInstance(instanceId, signalName, signalData) {
|
|
33
|
+
const { data } = await (0, rxjs_1.firstValueFrom)(this.httpService.post(`/workflow/instances/${instanceId}/signal`, { signalName, data: signalData }));
|
|
34
|
+
this.logger.log(`Signaled instance ${instanceId} with "${signalName}"`);
|
|
35
|
+
return data;
|
|
36
|
+
}
|
|
37
|
+
async abortInstance(instanceId) {
|
|
38
|
+
const { data } = await (0, rxjs_1.firstValueFrom)(this.httpService.post(`/workflow/instances/${instanceId}/abort`));
|
|
39
|
+
this.logger.log(`Aborted instance ${instanceId}`);
|
|
40
|
+
return data;
|
|
41
|
+
}
|
|
42
|
+
async getInstance(instanceId) {
|
|
43
|
+
const { data } = await (0, rxjs_1.firstValueFrom)(this.httpService.get(`/workflow/instances/${instanceId}`));
|
|
44
|
+
return data;
|
|
45
|
+
}
|
|
46
|
+
async updateVariables(instanceId, variables) {
|
|
47
|
+
const { data } = await (0, rxjs_1.firstValueFrom)(this.httpService.put(`/workflow/instances/${instanceId}/variables`, { variables }));
|
|
48
|
+
this.logger.log(`Updated variables for instance ${instanceId}`);
|
|
49
|
+
return data;
|
|
50
|
+
}
|
|
51
|
+
async listTasks(filters) {
|
|
52
|
+
const { data } = await (0, rxjs_1.firstValueFrom)(this.httpService.get('/workflow/tasks', {
|
|
53
|
+
params: filters,
|
|
54
|
+
}));
|
|
55
|
+
return data;
|
|
56
|
+
}
|
|
57
|
+
async getTask(taskId) {
|
|
58
|
+
const { data } = await (0, rxjs_1.firstValueFrom)(this.httpService.get(`/workflow/tasks/${taskId}`));
|
|
59
|
+
return data;
|
|
60
|
+
}
|
|
61
|
+
async claimTask(taskId) {
|
|
62
|
+
const { data } = await (0, rxjs_1.firstValueFrom)(this.httpService.post(`/workflow/tasks/${taskId}/claim`));
|
|
63
|
+
this.logger.log(`Claimed task ${taskId}`);
|
|
64
|
+
return data;
|
|
65
|
+
}
|
|
66
|
+
async executeTaskAction(taskId, actionName, actionData) {
|
|
67
|
+
const { data } = await (0, rxjs_1.firstValueFrom)(this.httpService.post(`/workflow/tasks/${taskId}/action`, {
|
|
68
|
+
actionName,
|
|
69
|
+
data: actionData,
|
|
70
|
+
}));
|
|
71
|
+
this.logger.log(`Executed action "${actionName}" on task ${taskId}`);
|
|
72
|
+
return data;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
exports.QuanticFlowClient = QuanticFlowClient;
|
|
76
|
+
exports.QuanticFlowClient = QuanticFlowClient = QuanticFlowClient_1 = __decorate([
|
|
77
|
+
(0, common_1.Injectable)(),
|
|
78
|
+
__metadata("design:paramtypes", [axios_1.HttpService])
|
|
79
|
+
], QuanticFlowClient);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { WorkflowEngine, WorkflowStartResult } from '@quanticjs/core';
|
|
2
|
+
import { QuanticFlowClient } from './QuanticFlowClient';
|
|
3
|
+
export declare class QuanticFlowWorkflowEngine implements WorkflowEngine {
|
|
4
|
+
private readonly client;
|
|
5
|
+
private readonly logger;
|
|
6
|
+
constructor(client: QuanticFlowClient);
|
|
7
|
+
startProcess(processDefinitionId: string, command: object, metadata: {
|
|
8
|
+
commandType: string;
|
|
9
|
+
correlationId?: string;
|
|
10
|
+
}): Promise<WorkflowStartResult>;
|
|
11
|
+
signalProcess(processInstanceId: string, signal: string, data?: unknown): Promise<void>;
|
|
12
|
+
abortProcess(processInstanceId: string): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var QuanticFlowWorkflowEngine_1;
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.QuanticFlowWorkflowEngine = void 0;
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const QuanticFlowClient_1 = require("./QuanticFlowClient");
|
|
16
|
+
let QuanticFlowWorkflowEngine = QuanticFlowWorkflowEngine_1 = class QuanticFlowWorkflowEngine {
|
|
17
|
+
client;
|
|
18
|
+
logger = new common_1.Logger(QuanticFlowWorkflowEngine_1.name);
|
|
19
|
+
constructor(client) {
|
|
20
|
+
this.client = client;
|
|
21
|
+
}
|
|
22
|
+
async startProcess(processDefinitionId, command, metadata) {
|
|
23
|
+
const variables = {
|
|
24
|
+
...JSON.parse(JSON.stringify(command)),
|
|
25
|
+
__commandType: metadata.commandType,
|
|
26
|
+
};
|
|
27
|
+
const instance = await this.client.startInstance(processDefinitionId, variables, metadata.correlationId);
|
|
28
|
+
this.logger.log(`Workflow started: instance=${instance.id}, definition=${processDefinitionId}`);
|
|
29
|
+
return {
|
|
30
|
+
workflowInstanceId: instance.id,
|
|
31
|
+
processInstanceId: instance.id,
|
|
32
|
+
status: 'STARTED',
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
async signalProcess(processInstanceId, signal, data) {
|
|
36
|
+
await this.client.signalInstance(processInstanceId, signal, data);
|
|
37
|
+
this.logger.log(`Workflow signaled: instance=${processInstanceId}, signal=${signal}`);
|
|
38
|
+
}
|
|
39
|
+
async abortProcess(processInstanceId) {
|
|
40
|
+
await this.client.abortInstance(processInstanceId);
|
|
41
|
+
this.logger.log(`Workflow aborted: instance=${processInstanceId}`);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
exports.QuanticFlowWorkflowEngine = QuanticFlowWorkflowEngine;
|
|
45
|
+
exports.QuanticFlowWorkflowEngine = QuanticFlowWorkflowEngine = QuanticFlowWorkflowEngine_1 = __decorate([
|
|
46
|
+
(0, common_1.Injectable)(),
|
|
47
|
+
__metadata("design:paramtypes", [QuanticFlowClient_1.QuanticFlowClient])
|
|
48
|
+
], QuanticFlowWorkflowEngine);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { DynamicModule } from '@nestjs/common';
|
|
2
|
+
import { ServiceTaskHandler } from './ServiceTaskHandlerRegistry';
|
|
3
|
+
export declare const QUANTICFLOW_OPTIONS: unique symbol;
|
|
4
|
+
export interface ServiceTaskHandlingOptions {
|
|
5
|
+
mode: 'callback' | 'event' | 'both';
|
|
6
|
+
callbackSecret?: string;
|
|
7
|
+
streamKey?: string;
|
|
8
|
+
consumerGroup?: string;
|
|
9
|
+
consumerName?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface QuanticFlowWorkflowModuleOptions {
|
|
12
|
+
url: string;
|
|
13
|
+
requestTimeout?: number;
|
|
14
|
+
serviceTaskHandling?: ServiceTaskHandlingOptions;
|
|
15
|
+
handlers?: Array<{
|
|
16
|
+
name: string;
|
|
17
|
+
useClass: new (...args: unknown[]) => ServiceTaskHandler;
|
|
18
|
+
}>;
|
|
19
|
+
}
|
|
20
|
+
export declare class QuanticFlowWorkflowModule {
|
|
21
|
+
static forRoot(options: QuanticFlowWorkflowModuleOptions): DynamicModule;
|
|
22
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var QuanticFlowWorkflowModule_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.QuanticFlowWorkflowModule = exports.QUANTICFLOW_OPTIONS = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const axios_1 = require("@nestjs/axios");
|
|
13
|
+
const core_1 = require("@quanticjs/core");
|
|
14
|
+
const QuanticFlowClient_1 = require("./QuanticFlowClient");
|
|
15
|
+
const QuanticFlowWorkflowEngine_1 = require("./QuanticFlowWorkflowEngine");
|
|
16
|
+
const QuanticFlowCallbackController_1 = require("./QuanticFlowCallbackController");
|
|
17
|
+
const ServiceTaskEventConsumer_1 = require("./ServiceTaskEventConsumer");
|
|
18
|
+
const ServiceTaskHandlerRegistry_1 = require("./ServiceTaskHandlerRegistry");
|
|
19
|
+
exports.QUANTICFLOW_OPTIONS = Symbol('QUANTICFLOW_OPTIONS');
|
|
20
|
+
let QuanticFlowWorkflowModule = QuanticFlowWorkflowModule_1 = class QuanticFlowWorkflowModule {
|
|
21
|
+
static forRoot(options) {
|
|
22
|
+
const mode = options.serviceTaskHandling?.mode ?? 'callback';
|
|
23
|
+
const enableCallback = mode === 'callback' || mode === 'both';
|
|
24
|
+
const enableEvents = mode === 'event' || mode === 'both';
|
|
25
|
+
const providers = [
|
|
26
|
+
{
|
|
27
|
+
provide: exports.QUANTICFLOW_OPTIONS,
|
|
28
|
+
useValue: options,
|
|
29
|
+
},
|
|
30
|
+
QuanticFlowClient_1.QuanticFlowClient,
|
|
31
|
+
{
|
|
32
|
+
provide: core_1.WORKFLOW_ENGINE,
|
|
33
|
+
useClass: QuanticFlowWorkflowEngine_1.QuanticFlowWorkflowEngine,
|
|
34
|
+
},
|
|
35
|
+
ServiceTaskHandlerRegistry_1.ServiceTaskHandlerRegistry,
|
|
36
|
+
];
|
|
37
|
+
const controllers = [];
|
|
38
|
+
if (enableCallback) {
|
|
39
|
+
controllers.push(QuanticFlowCallbackController_1.QuanticFlowCallbackController);
|
|
40
|
+
}
|
|
41
|
+
if (enableEvents) {
|
|
42
|
+
providers.push({
|
|
43
|
+
provide: 'QUANTICFLOW_EVENT_OPTIONS',
|
|
44
|
+
useValue: {
|
|
45
|
+
streamKey: options.serviceTaskHandling?.streamKey,
|
|
46
|
+
consumerGroup: options.serviceTaskHandling?.consumerGroup,
|
|
47
|
+
consumerName: options.serviceTaskHandling?.consumerName,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
providers.push(ServiceTaskEventConsumer_1.ServiceTaskEventConsumer);
|
|
51
|
+
}
|
|
52
|
+
if (options.handlers) {
|
|
53
|
+
for (const { name, useClass } of options.handlers) {
|
|
54
|
+
providers.push({
|
|
55
|
+
provide: name,
|
|
56
|
+
useClass,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
module: QuanticFlowWorkflowModule_1,
|
|
62
|
+
imports: [
|
|
63
|
+
axios_1.HttpModule.register({
|
|
64
|
+
baseURL: options.url,
|
|
65
|
+
timeout: options.requestTimeout ?? 10000,
|
|
66
|
+
}),
|
|
67
|
+
],
|
|
68
|
+
controllers,
|
|
69
|
+
providers,
|
|
70
|
+
exports: [
|
|
71
|
+
core_1.WORKFLOW_ENGINE,
|
|
72
|
+
QuanticFlowClient_1.QuanticFlowClient,
|
|
73
|
+
ServiceTaskHandlerRegistry_1.ServiceTaskHandlerRegistry,
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
exports.QuanticFlowWorkflowModule = QuanticFlowWorkflowModule;
|
|
79
|
+
exports.QuanticFlowWorkflowModule = QuanticFlowWorkflowModule = QuanticFlowWorkflowModule_1 = __decorate([
|
|
80
|
+
(0, common_1.Global)(),
|
|
81
|
+
(0, common_1.Module)({})
|
|
82
|
+
], QuanticFlowWorkflowModule);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Logger } from '@nestjs/common';
|
|
2
|
+
import { RedisStreamConsumer } from '@quanticjs/events';
|
|
3
|
+
import { QuanticFlowClient } from './QuanticFlowClient';
|
|
4
|
+
import { ServiceTaskHandlerRegistry } from './ServiceTaskHandlerRegistry';
|
|
5
|
+
import type { Redis } from 'ioredis';
|
|
6
|
+
export declare class ServiceTaskEventConsumer extends RedisStreamConsumer {
|
|
7
|
+
private readonly registry;
|
|
8
|
+
private readonly client;
|
|
9
|
+
protected readonly logger: Logger;
|
|
10
|
+
readonly streamKey: string;
|
|
11
|
+
readonly consumerGroup: string;
|
|
12
|
+
readonly consumerName: string;
|
|
13
|
+
constructor(redis: Redis | undefined, registry: ServiceTaskHandlerRegistry, client: QuanticFlowClient, options: {
|
|
14
|
+
streamKey?: string;
|
|
15
|
+
consumerGroup?: string;
|
|
16
|
+
consumerName?: string;
|
|
17
|
+
});
|
|
18
|
+
protected shouldHandle(fields: Record<string, string>): boolean;
|
|
19
|
+
handleMessage(fields: Record<string, string>): Promise<void>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var ServiceTaskEventConsumer_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.ServiceTaskEventConsumer = void 0;
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const core_1 = require("@quanticjs/core");
|
|
19
|
+
const events_1 = require("@quanticjs/events");
|
|
20
|
+
const QuanticFlowClient_1 = require("./QuanticFlowClient");
|
|
21
|
+
const ServiceTaskHandlerRegistry_1 = require("./ServiceTaskHandlerRegistry");
|
|
22
|
+
const DEFAULT_STREAM_KEY = 'arex:events:services';
|
|
23
|
+
const DEFAULT_CONSUMER_GROUP = 'quanticflow-service-tasks';
|
|
24
|
+
let ServiceTaskEventConsumer = ServiceTaskEventConsumer_1 = class ServiceTaskEventConsumer extends events_1.RedisStreamConsumer {
|
|
25
|
+
registry;
|
|
26
|
+
client;
|
|
27
|
+
logger = new common_1.Logger(ServiceTaskEventConsumer_1.name);
|
|
28
|
+
streamKey;
|
|
29
|
+
consumerGroup;
|
|
30
|
+
consumerName;
|
|
31
|
+
constructor(redis, registry, client, options) {
|
|
32
|
+
super(redis);
|
|
33
|
+
this.registry = registry;
|
|
34
|
+
this.client = client;
|
|
35
|
+
this.streamKey = options.streamKey ?? DEFAULT_STREAM_KEY;
|
|
36
|
+
this.consumerGroup = options.consumerGroup ?? DEFAULT_CONSUMER_GROUP;
|
|
37
|
+
this.consumerName = options.consumerName ?? `consumer-${process.pid}`;
|
|
38
|
+
}
|
|
39
|
+
shouldHandle(fields) {
|
|
40
|
+
return fields['eventType'] === 'ServiceTaskStartedEvent';
|
|
41
|
+
}
|
|
42
|
+
async handleMessage(fields) {
|
|
43
|
+
const payload = JSON.parse(fields['payload'] ?? '{}');
|
|
44
|
+
const { instanceId, definitionId, stateName, handlerName, correlationId, variables, } = payload;
|
|
45
|
+
this.logger.log(`Service task event: handler=${handlerName}, instance=${instanceId}`);
|
|
46
|
+
const handler = await this.registry.resolve(handlerName);
|
|
47
|
+
if (!handler) {
|
|
48
|
+
this.logger.error(`No handler registered for "${handlerName}"`);
|
|
49
|
+
await this.client.signalInstance(instanceId, 'handler-not-found', {
|
|
50
|
+
error: `Handler "${handlerName}" not registered`,
|
|
51
|
+
});
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const context = {
|
|
55
|
+
instanceId,
|
|
56
|
+
definitionId,
|
|
57
|
+
stateName,
|
|
58
|
+
handlerName,
|
|
59
|
+
correlationId,
|
|
60
|
+
variables: variables ?? {},
|
|
61
|
+
};
|
|
62
|
+
try {
|
|
63
|
+
const result = await handler.execute(context);
|
|
64
|
+
await this.client.signalInstance(instanceId, result.signal, result.data);
|
|
65
|
+
this.logger.log(`Handler "${handlerName}" completed, signaled instance ${instanceId} with "${result.signal}"`);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
69
|
+
this.logger.error(`Handler "${handlerName}" failed: ${message}`);
|
|
70
|
+
await this.client.signalInstance(instanceId, 'handler-error', {
|
|
71
|
+
error: message,
|
|
72
|
+
handlerName,
|
|
73
|
+
stateName,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
exports.ServiceTaskEventConsumer = ServiceTaskEventConsumer;
|
|
79
|
+
exports.ServiceTaskEventConsumer = ServiceTaskEventConsumer = ServiceTaskEventConsumer_1 = __decorate([
|
|
80
|
+
(0, common_1.Injectable)(),
|
|
81
|
+
__param(0, (0, common_1.Optional)()),
|
|
82
|
+
__param(0, (0, common_1.Inject)(core_1.REDIS_CLIENT)),
|
|
83
|
+
__param(3, (0, common_1.Inject)('QUANTICFLOW_EVENT_OPTIONS')),
|
|
84
|
+
__metadata("design:paramtypes", [Object, ServiceTaskHandlerRegistry_1.ServiceTaskHandlerRegistry,
|
|
85
|
+
QuanticFlowClient_1.QuanticFlowClient, Object])
|
|
86
|
+
], ServiceTaskEventConsumer);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ModuleRef } from '@nestjs/core';
|
|
2
|
+
export interface ServiceTaskHandler {
|
|
3
|
+
execute(context: ServiceTaskContext): Promise<ServiceTaskResult>;
|
|
4
|
+
}
|
|
5
|
+
export interface ServiceTaskContext {
|
|
6
|
+
instanceId: string;
|
|
7
|
+
definitionId: string;
|
|
8
|
+
stateName: string;
|
|
9
|
+
handlerName: string;
|
|
10
|
+
correlationId?: string;
|
|
11
|
+
variables: Record<string, unknown>;
|
|
12
|
+
}
|
|
13
|
+
export interface ServiceTaskResult {
|
|
14
|
+
signal: string;
|
|
15
|
+
data?: unknown;
|
|
16
|
+
}
|
|
17
|
+
export declare const SERVICE_TASK_HANDLERS: unique symbol;
|
|
18
|
+
export declare class ServiceTaskHandlerRegistry {
|
|
19
|
+
private readonly moduleRef;
|
|
20
|
+
private readonly logger;
|
|
21
|
+
private readonly handlers;
|
|
22
|
+
constructor(moduleRef: ModuleRef);
|
|
23
|
+
register(name: string, handler: ServiceTaskHandler): void;
|
|
24
|
+
resolve(name: string): Promise<ServiceTaskHandler | undefined>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var ServiceTaskHandlerRegistry_1;
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.ServiceTaskHandlerRegistry = exports.SERVICE_TASK_HANDLERS = void 0;
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const core_1 = require("@nestjs/core");
|
|
16
|
+
exports.SERVICE_TASK_HANDLERS = Symbol('SERVICE_TASK_HANDLERS');
|
|
17
|
+
let ServiceTaskHandlerRegistry = ServiceTaskHandlerRegistry_1 = class ServiceTaskHandlerRegistry {
|
|
18
|
+
moduleRef;
|
|
19
|
+
logger = new common_1.Logger(ServiceTaskHandlerRegistry_1.name);
|
|
20
|
+
handlers = new Map();
|
|
21
|
+
constructor(moduleRef) {
|
|
22
|
+
this.moduleRef = moduleRef;
|
|
23
|
+
}
|
|
24
|
+
register(name, handler) {
|
|
25
|
+
this.handlers.set(name, handler);
|
|
26
|
+
this.logger.log(`Registered service task handler: ${name}`);
|
|
27
|
+
}
|
|
28
|
+
async resolve(name) {
|
|
29
|
+
const registered = this.handlers.get(name);
|
|
30
|
+
if (registered)
|
|
31
|
+
return registered;
|
|
32
|
+
try {
|
|
33
|
+
const handler = this.moduleRef.get(name, { strict: false });
|
|
34
|
+
if (handler && typeof handler.execute === 'function') {
|
|
35
|
+
this.handlers.set(name, handler);
|
|
36
|
+
return handler;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// Not found in DI container
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
exports.ServiceTaskHandlerRegistry = ServiceTaskHandlerRegistry;
|
|
46
|
+
exports.ServiceTaskHandlerRegistry = ServiceTaskHandlerRegistry = ServiceTaskHandlerRegistry_1 = __decorate([
|
|
47
|
+
(0, common_1.Injectable)(),
|
|
48
|
+
__metadata("design:paramtypes", [core_1.ModuleRef])
|
|
49
|
+
], ServiceTaskHandlerRegistry);
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { QuanticFlowWorkflowModule, QUANTICFLOW_OPTIONS } from './QuanticFlowWorkflowModule';
|
|
2
|
+
export type { QuanticFlowWorkflowModuleOptions, ServiceTaskHandlingOptions, } from './QuanticFlowWorkflowModule';
|
|
3
|
+
export { QuanticFlowClient } from './QuanticFlowClient';
|
|
4
|
+
export type { QuanticFlowInstance, QuanticFlowTask, PaginatedResult, } from './QuanticFlowClient';
|
|
5
|
+
export { QuanticFlowWorkflowEngine } from './QuanticFlowWorkflowEngine';
|
|
6
|
+
export { QuanticFlowCallbackController } from './QuanticFlowCallbackController';
|
|
7
|
+
export type { ServiceTaskCallbackPayload, ServiceTaskCallbackResponse, } from './QuanticFlowCallbackController';
|
|
8
|
+
export { ServiceTaskEventConsumer } from './ServiceTaskEventConsumer';
|
|
9
|
+
export { ServiceTaskHandlerRegistry, SERVICE_TASK_HANDLERS, } from './ServiceTaskHandlerRegistry';
|
|
10
|
+
export type { ServiceTaskHandler, ServiceTaskContext, ServiceTaskResult, } from './ServiceTaskHandlerRegistry';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SERVICE_TASK_HANDLERS = exports.ServiceTaskHandlerRegistry = exports.ServiceTaskEventConsumer = exports.QuanticFlowCallbackController = exports.QuanticFlowWorkflowEngine = exports.QuanticFlowClient = exports.QUANTICFLOW_OPTIONS = exports.QuanticFlowWorkflowModule = void 0;
|
|
4
|
+
var QuanticFlowWorkflowModule_1 = require("./QuanticFlowWorkflowModule");
|
|
5
|
+
Object.defineProperty(exports, "QuanticFlowWorkflowModule", { enumerable: true, get: function () { return QuanticFlowWorkflowModule_1.QuanticFlowWorkflowModule; } });
|
|
6
|
+
Object.defineProperty(exports, "QUANTICFLOW_OPTIONS", { enumerable: true, get: function () { return QuanticFlowWorkflowModule_1.QUANTICFLOW_OPTIONS; } });
|
|
7
|
+
var QuanticFlowClient_1 = require("./QuanticFlowClient");
|
|
8
|
+
Object.defineProperty(exports, "QuanticFlowClient", { enumerable: true, get: function () { return QuanticFlowClient_1.QuanticFlowClient; } });
|
|
9
|
+
var QuanticFlowWorkflowEngine_1 = require("./QuanticFlowWorkflowEngine");
|
|
10
|
+
Object.defineProperty(exports, "QuanticFlowWorkflowEngine", { enumerable: true, get: function () { return QuanticFlowWorkflowEngine_1.QuanticFlowWorkflowEngine; } });
|
|
11
|
+
var QuanticFlowCallbackController_1 = require("./QuanticFlowCallbackController");
|
|
12
|
+
Object.defineProperty(exports, "QuanticFlowCallbackController", { enumerable: true, get: function () { return QuanticFlowCallbackController_1.QuanticFlowCallbackController; } });
|
|
13
|
+
var ServiceTaskEventConsumer_1 = require("./ServiceTaskEventConsumer");
|
|
14
|
+
Object.defineProperty(exports, "ServiceTaskEventConsumer", { enumerable: true, get: function () { return ServiceTaskEventConsumer_1.ServiceTaskEventConsumer; } });
|
|
15
|
+
var ServiceTaskHandlerRegistry_1 = require("./ServiceTaskHandlerRegistry");
|
|
16
|
+
Object.defineProperty(exports, "ServiceTaskHandlerRegistry", { enumerable: true, get: function () { return ServiceTaskHandlerRegistry_1.ServiceTaskHandlerRegistry; } });
|
|
17
|
+
Object.defineProperty(exports, "SERVICE_TASK_HANDLERS", { enumerable: true, get: function () { return ServiceTaskHandlerRegistry_1.SERVICE_TASK_HANDLERS; } });
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@quanticjs/workflow-quanticflow",
|
|
3
|
+
"version": "3.3.0",
|
|
4
|
+
"description": "QuanticFlow workflow engine adapter for @quanticjs/workflow — supports callback and event-driven service task execution",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc -p tsconfig.json",
|
|
12
|
+
"test": "jest --passWithNoTests",
|
|
13
|
+
"clean": "rm -rf dist"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"nestjs",
|
|
17
|
+
"cqrs",
|
|
18
|
+
"quanticflow",
|
|
19
|
+
"workflow",
|
|
20
|
+
"bpmn"
|
|
21
|
+
],
|
|
22
|
+
"author": "turkelk",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@nestjs/axios": "^4.0.0",
|
|
26
|
+
"@quanticjs/core": "^3.3.0",
|
|
27
|
+
"@quanticjs/events": "^3.3.0",
|
|
28
|
+
"axios": "^1.6.0"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"@nestjs/common": "^10.0.0 || ^11.0.0",
|
|
32
|
+
"@nestjs/core": "^10.0.0 || ^11.0.0",
|
|
33
|
+
"@nestjs/cqrs": "^10.0.0 || ^11.0.0",
|
|
34
|
+
"ioredis": "^5.0.0",
|
|
35
|
+
"reflect-metadata": "^0.1.13 || ^0.2.0"
|
|
36
|
+
},
|
|
37
|
+
"peerDependenciesMeta": {
|
|
38
|
+
"ioredis": {
|
|
39
|
+
"optional": true
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"registry": "https://registry.npmjs.org",
|
|
44
|
+
"access": "public"
|
|
45
|
+
},
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "https://github.com/quanticjs/quanticjs-backend.git",
|
|
49
|
+
"directory": "packages/workflow-quanticflow"
|
|
50
|
+
}
|
|
51
|
+
}
|