@geniehr/utilities 1.0.13 → 1.0.15
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/dist/conductor/ConductorClient.d.ts +11 -0
- package/dist/conductor/ConductorClient.js +120 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/secrets/aws.d.ts +1 -0
- package/dist/secrets/aws.js +34 -0
- package/package.json +2 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class ConductorClient {
|
|
2
|
+
private client;
|
|
3
|
+
private workers;
|
|
4
|
+
constructor(serviceName?: string);
|
|
5
|
+
startWorkflow(name: string, input: any, correlationId?: string, version?: number): Promise<any>;
|
|
6
|
+
registerWorker(taskType: string, execute: (input: any) => Promise<any>, pollInterval?: number, domain?: string): Promise<void>;
|
|
7
|
+
private poll;
|
|
8
|
+
updateTask(taskId: string, workflowInstanceId: string, status: string, outputData: any, reasonForIncompletion?: string): Promise<void>;
|
|
9
|
+
getTask(workflowInstanceId: string, taskReferenceName: string): Promise<any>;
|
|
10
|
+
getWorkflow(workflowInstanceId: string, includeTasks?: boolean): Promise<any>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
const WORKFLOW_API_URL = process.env.CONDUCTOR_SERVER_URL || 'http://localhost:8080/api';
|
|
3
|
+
export class ConductorClient {
|
|
4
|
+
client;
|
|
5
|
+
workers = {};
|
|
6
|
+
constructor(serviceName = 'claims-service') {
|
|
7
|
+
this.client = axios.create({
|
|
8
|
+
baseURL: WORKFLOW_API_URL,
|
|
9
|
+
headers: {
|
|
10
|
+
'Content-Type': 'application/json',
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
console.log(`ConductorClient initialized for ${serviceName}`);
|
|
14
|
+
}
|
|
15
|
+
async startWorkflow(name, input, correlationId, version) {
|
|
16
|
+
try {
|
|
17
|
+
const payload = {
|
|
18
|
+
name,
|
|
19
|
+
input,
|
|
20
|
+
correlationId
|
|
21
|
+
};
|
|
22
|
+
if (version) {
|
|
23
|
+
payload.version = version;
|
|
24
|
+
}
|
|
25
|
+
const response = await this.client.post('/workflow', payload);
|
|
26
|
+
console.log(`Started workflow ${name} v${version}: ${JSON.stringify(response.data)}`);
|
|
27
|
+
return response.data;
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
console.error(`Error starting workflow ${name}:`, error.message);
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async registerWorker(taskType, execute, pollInterval = 1000, domain) {
|
|
35
|
+
if (this.workers[taskType]) {
|
|
36
|
+
console.warn(`Worker for ${taskType} already registered.`);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
this.workers[taskType] = true;
|
|
40
|
+
console.log(`Registered worker for ${taskType}`);
|
|
41
|
+
this.poll(taskType, execute, pollInterval, domain);
|
|
42
|
+
}
|
|
43
|
+
async poll(taskType, execute, interval, domain) {
|
|
44
|
+
while (this.workers[taskType]) {
|
|
45
|
+
try {
|
|
46
|
+
// Poll for a task
|
|
47
|
+
// GET /tasks/poll/{taskType}?workerid=...&domain=...
|
|
48
|
+
const workerId = `worker-${process.pid}`;
|
|
49
|
+
const response = await this.client.get(`/tasks/poll/${taskType}`, {
|
|
50
|
+
params: {
|
|
51
|
+
workerid: workerId,
|
|
52
|
+
domain
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
const task = response.data;
|
|
56
|
+
if (task && task.taskId) {
|
|
57
|
+
console.log(`Received task ${taskType} (ID: ${task.taskId})`);
|
|
58
|
+
let status = 'COMPLETED';
|
|
59
|
+
let outputData = {};
|
|
60
|
+
let reasonForIncompletion = '';
|
|
61
|
+
try {
|
|
62
|
+
outputData = await execute(task.inputData);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
console.error(`Error executing task ${taskType}:`, err.message);
|
|
66
|
+
status = 'FAILED';
|
|
67
|
+
reasonForIncompletion = err.message || 'Unknown error';
|
|
68
|
+
}
|
|
69
|
+
// Update task status
|
|
70
|
+
await this.updateTask(task.taskId, task.workflowInstanceId, status, outputData, reasonForIncompletion);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
// If polling fails (e.g. 204 No Content or connection error), just log debug/warn and wait
|
|
75
|
+
// console.debug(`Polling error for ${taskType}: ${error}`);
|
|
76
|
+
}
|
|
77
|
+
// Wait before next poll
|
|
78
|
+
await new Promise(resolve => setTimeout(resolve, interval));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async updateTask(taskId, workflowInstanceId, status, outputData, reasonForIncompletion) {
|
|
82
|
+
try {
|
|
83
|
+
await this.client.post('/tasks', {
|
|
84
|
+
taskId,
|
|
85
|
+
workflowInstanceId,
|
|
86
|
+
status,
|
|
87
|
+
outputData,
|
|
88
|
+
reasonForIncompletion
|
|
89
|
+
});
|
|
90
|
+
console.log(`Updated task ${taskId} to ${status}`);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.error(`Failed to update task ${taskId}:`, error.message);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async getTask(workflowInstanceId, taskReferenceName) {
|
|
97
|
+
try {
|
|
98
|
+
const response = await this.client.get(`/workflow/${workflowInstanceId}`);
|
|
99
|
+
const workflow = response.data;
|
|
100
|
+
if (workflow && workflow.tasks) {
|
|
101
|
+
return workflow.tasks.find((t) => t.referenceTaskName === taskReferenceName && t.status === 'IN_PROGRESS');
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
console.error(`Error getting workflow tasks:`, error.message);
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async getWorkflow(workflowInstanceId, includeTasks = true) {
|
|
111
|
+
try {
|
|
112
|
+
const response = await this.client.get(`/workflow/${workflowInstanceId}?includeTasks=${includeTasks}`);
|
|
113
|
+
return response.data;
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.error(`Error getting workflow:`, error.message);
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,9 +4,10 @@ export { getContext, setExtras, setContext } from './shared/context/index.js';
|
|
|
4
4
|
export { LoggerService as Logger } from './logger/LoggerService.js';
|
|
5
5
|
export { HttpStatusCode } from './shared/enums/HttpStatusCodes.js';
|
|
6
6
|
export { InvalidRequestException, InvalidEnvironmentException, AppException } from './shared/exceptions/index.js';
|
|
7
|
-
export { getAWSParameters, matchFace, registerFace, generatePresignedUrl, getCustomAttribute, updateCustomAttribute, executeS3Action } from './secrets/aws.js';
|
|
7
|
+
export { getAWSParameters, matchFace, registerFace, generatePresignedUrl, getCustomAttribute, updateCustomAttribute, executeS3Action, sendEmail } from './secrets/aws.js';
|
|
8
8
|
export { CognitoUserService } from './secrets/CognitoUserService.js';
|
|
9
9
|
export { HttpClient, GraphQLClient } from './apiUtils/httpUtils.js';
|
|
10
10
|
export { sendResponse } from './apiUtils/api.js';
|
|
11
11
|
export { services } from './shared/services.js';
|
|
12
12
|
export { ImageCompressor } from './shared/helper/ImageCompressor.js';
|
|
13
|
+
export { ConductorClient } from './conductor/ConductorClient.js';
|
package/dist/index.js
CHANGED
|
@@ -4,9 +4,10 @@ export { getContext, setExtras, setContext } from './shared/context/index.js';
|
|
|
4
4
|
export { LoggerService as Logger } from './logger/LoggerService.js';
|
|
5
5
|
export { HttpStatusCode } from './shared/enums/HttpStatusCodes.js';
|
|
6
6
|
export { InvalidRequestException, InvalidEnvironmentException, AppException } from './shared/exceptions/index.js';
|
|
7
|
-
export { getAWSParameters, matchFace, registerFace, generatePresignedUrl, getCustomAttribute, updateCustomAttribute, executeS3Action } from './secrets/aws.js';
|
|
7
|
+
export { getAWSParameters, matchFace, registerFace, generatePresignedUrl, getCustomAttribute, updateCustomAttribute, executeS3Action, sendEmail } from './secrets/aws.js';
|
|
8
8
|
export { CognitoUserService } from './secrets/CognitoUserService.js';
|
|
9
9
|
export { HttpClient, GraphQLClient } from './apiUtils/httpUtils.js';
|
|
10
10
|
export { sendResponse } from './apiUtils/api.js';
|
|
11
11
|
export { services } from './shared/services.js';
|
|
12
12
|
export { ImageCompressor } from './shared/helper/ImageCompressor.js';
|
|
13
|
+
export { ConductorClient } from './conductor/ConductorClient.js';
|
package/dist/secrets/aws.d.ts
CHANGED
|
@@ -17,3 +17,4 @@ export declare function getCustomAttribute(username: string, userPoolId: string,
|
|
|
17
17
|
value?: string;
|
|
18
18
|
message: string;
|
|
19
19
|
}>;
|
|
20
|
+
export declare function sendEmail(fromAddress: string, to: string[], displayName: string, cc: string[] | undefined, bcc: string[] | undefined, subject: string, htmlBody: string, metaData?: Record<string, any>): Promise<import("@aws-sdk/client-ses").SendEmailCommandOutput>;
|
package/dist/secrets/aws.js
CHANGED
|
@@ -4,6 +4,7 @@ import { AppException } from '../shared/exceptions/index.js';
|
|
|
4
4
|
import { S3Client, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3';
|
|
5
5
|
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
|
6
6
|
import { CognitoIdentityProviderClient, AdminUpdateUserAttributesCommand, AdminGetUserCommand } from '@aws-sdk/client-cognito-identity-provider';
|
|
7
|
+
import { SESClient, SendEmailCommand } from "@aws-sdk/client-ses";
|
|
7
8
|
let ssm;
|
|
8
9
|
let rand = Math.random().toString();
|
|
9
10
|
const env = process.env.NODE_ENV || rand;
|
|
@@ -21,6 +22,10 @@ const client = new CognitoIdentityProviderClient({
|
|
|
21
22
|
region: 'ap-south-1',
|
|
22
23
|
credentials: env === 'local' ? fromIni({ profile: 'ghr-aws-dev-profile' }) : undefined
|
|
23
24
|
});
|
|
25
|
+
const ses = new SESClient({
|
|
26
|
+
region: 'ap-south-1',
|
|
27
|
+
credentials: env === 'local' ? fromIni({ profile: 'ghr-aws-dev-profile' }) : undefined
|
|
28
|
+
});
|
|
24
29
|
/**
|
|
25
30
|
* Fetch a single parameter or all parameters under a prefix.
|
|
26
31
|
* @param nameOrPrefix Full name (e.g. /dev/mysql/person) or prefix (e.g. /dev/mysql/)
|
|
@@ -219,3 +224,32 @@ export async function getCustomAttribute(username, userPoolId, attributeName) {
|
|
|
219
224
|
};
|
|
220
225
|
}
|
|
221
226
|
}
|
|
227
|
+
export async function sendEmail(fromAddress, to, displayName, cc = [], bcc = [], subject, htmlBody, metaData = {}) {
|
|
228
|
+
try {
|
|
229
|
+
const command = new SendEmailCommand({
|
|
230
|
+
Source: displayName ? `"${displayName}" <${fromAddress}>` : fromAddress,
|
|
231
|
+
Destination: {
|
|
232
|
+
ToAddresses: to,
|
|
233
|
+
CcAddresses: cc,
|
|
234
|
+
BccAddresses: bcc,
|
|
235
|
+
},
|
|
236
|
+
Message: {
|
|
237
|
+
Subject: {
|
|
238
|
+
Data: subject,
|
|
239
|
+
Charset: "UTF-8",
|
|
240
|
+
},
|
|
241
|
+
Body: {
|
|
242
|
+
Html: {
|
|
243
|
+
Data: htmlBody,
|
|
244
|
+
Charset: "UTF-8",
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
const result = await ses.send(command);
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
throw new AppException(`Failed to send email: ${error instanceof Error ? error.message : "Unknown error"}`, "E-Send-Email-Failed");
|
|
254
|
+
}
|
|
255
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geniehr/utilities",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"description": "",
|
|
5
5
|
"homepage": "https://github.com/Genie-HR/ghr-utilities#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"@aws-sdk/client-cognito-identity-provider": "^3.859.0",
|
|
32
32
|
"@aws-sdk/client-rekognition": "^3.846.0",
|
|
33
33
|
"@aws-sdk/client-s3": "^3.848.0",
|
|
34
|
+
"@aws-sdk/client-ses": "^3.986.0",
|
|
34
35
|
"@aws-sdk/client-ssm": "^3.839.0",
|
|
35
36
|
"@aws-sdk/credential-providers": "^3.839.0",
|
|
36
37
|
"@aws-sdk/s3-request-presigner": "^3.848.0",
|