Enhance Workflow API Call Handling and Authorization Logic
- Introduced a new proxy endpoint for API calls during workflow execution to handle CORS issues and streamline API interactions. - Updated the authorization logic to support Basic Auth with both token and username/password options, improving flexibility in API authentication. - Enhanced the API request building process to accommodate new node data structures, including dynamic handling of headers, parameters, and body content. - Improved error handling and response management in the workflow execution process, ensuring better feedback and control over API call outcomes. - Refactored the workflow page to utilize the new API call structure, enhancing overall workflow execution reliability and user experience.
This commit is contained in:
parent
dfea8e7f47
commit
bae98c2b17
@ -655,11 +655,18 @@ function buildApiRequest(nodeData, variables) {
|
|||||||
// 4. Authorization
|
// 4. Authorization
|
||||||
if (nodeData.authorization && nodeData.authorization.type && nodeData.authorization.type !== 'none') {
|
if (nodeData.authorization && nodeData.authorization.type && nodeData.authorization.type !== 'none') {
|
||||||
const auth = nodeData.authorization;
|
const auth = nodeData.authorization;
|
||||||
|
|
||||||
if (auth.type === 'bearer' && auth.token) {
|
if (auth.type === 'bearer' && auth.token) {
|
||||||
headers['Authorization'] = `Bearer ${substituteVariables(auth.token, variables)}`;
|
headers['Authorization'] = `Bearer ${substituteVariables(auth.token, variables)}`;
|
||||||
} else if (auth.type === 'basic' && auth.username && auth.password) {
|
} else if (auth.type === 'basic') {
|
||||||
const token = btoa(`${substituteVariables(auth.username, variables)}:${substituteVariables(auth.password, variables)}`);
|
if (auth.token) {
|
||||||
headers['Authorization'] = `Basic ${token}`;
|
// Basic Auth with token (JWT or other token)
|
||||||
|
headers['Authorization'] = `Basic ${substituteVariables(auth.token, variables)}`;
|
||||||
|
} else if (auth.username && auth.password) {
|
||||||
|
// Basic Auth with username/password
|
||||||
|
const token = btoa(`${substituteVariables(auth.username, variables)}:${substituteVariables(auth.password, variables)}`);
|
||||||
|
headers['Authorization'] = `Basic ${token}`;
|
||||||
|
}
|
||||||
} else if (auth.type === 'apiKey' && auth.key && auth.value) {
|
} else if (auth.type === 'apiKey' && auth.key && auth.value) {
|
||||||
if (auth.in === 'header') {
|
if (auth.in === 'header') {
|
||||||
headers[substituteVariables(auth.key, variables)] = substituteVariables(auth.value, variables);
|
headers[substituteVariables(auth.key, variables)] = substituteVariables(auth.value, variables);
|
||||||
@ -712,26 +719,45 @@ const executeCurrentStep = async () => {
|
|||||||
if (currentNode.value?.type === 'api') {
|
if (currentNode.value?.type === 'api') {
|
||||||
console.log(`[Workflow] Executing API node: ${currentNode.value.data?.label || currentNode.value.label}`);
|
console.log(`[Workflow] Executing API node: ${currentNode.value.data?.label || currentNode.value.label}`);
|
||||||
const nodeData = currentNode.value.data || {};
|
const nodeData = currentNode.value.data || {};
|
||||||
// Use new structure if present
|
|
||||||
if (nodeData.body || nodeData.headers || nodeData.params || nodeData.authorization) {
|
// Use new structure if present (check for any new structure properties)
|
||||||
const { url, headers, body } = buildApiRequest(nodeData, processVariables.value);
|
if (nodeData.body !== undefined || nodeData.headers !== undefined || nodeData.params !== undefined || nodeData.authorization !== undefined) {
|
||||||
const apiMethod = nodeData.apiMethod || 'GET';
|
|
||||||
const outputVariable = nodeData.outputVariable || 'apiResponse';
|
const outputVariable = nodeData.outputVariable || 'apiResponse';
|
||||||
const errorVariable = nodeData.errorVariable || 'apiError';
|
const errorVariable = nodeData.errorVariable || 'apiError';
|
||||||
const continueOnError = nodeData.continueOnError || false;
|
const continueOnError = nodeData.continueOnError || false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await $fetch(url, {
|
// Use proxy endpoint to avoid CORS issues
|
||||||
method: apiMethod,
|
const response = await $fetch('/api/process/workflow-api-call', {
|
||||||
headers,
|
method: 'POST',
|
||||||
body: ['GET', 'HEAD'].includes(apiMethod) ? undefined : body,
|
body: {
|
||||||
|
nodeData,
|
||||||
|
processVariables: processVariables.value
|
||||||
|
}
|
||||||
});
|
});
|
||||||
processVariables.value[outputVariable] = response;
|
|
||||||
processVariables.value[errorVariable] = null;
|
if (response.success) {
|
||||||
console.log('[Workflow] API call success. Output variable set:', outputVariable, response);
|
processVariables.value[outputVariable] = response.data;
|
||||||
if (canAutoProgress(currentNode.value)) {
|
processVariables.value[errorVariable] = null;
|
||||||
moveToNextStep();
|
console.log('[Workflow] API call success. Output variable set:', outputVariable, response.data);
|
||||||
|
if (canAutoProgress(currentNode.value)) {
|
||||||
|
moveToNextStep();
|
||||||
|
} else {
|
||||||
|
console.log('[Workflow] API completed, multiple paths available - waiting for user choice');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('[Workflow] API completed, multiple paths available - waiting for user choice');
|
processVariables.value[errorVariable] = response.error;
|
||||||
|
console.error('[Workflow] API call failed:', response.error);
|
||||||
|
if (continueOnError) {
|
||||||
|
if (canAutoProgress(currentNode.value)) {
|
||||||
|
moveToNextStep();
|
||||||
|
} else {
|
||||||
|
console.log('[Workflow] API failed but continuing, multiple paths available - waiting for user choice');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error.value = 'API call failed: ' + (response.error.message || response.error);
|
||||||
|
notifyParentOfError(error.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
processVariables.value[errorVariable] = err;
|
processVariables.value[errorVariable] = err;
|
||||||
@ -749,6 +775,7 @@ const executeCurrentStep = async () => {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Fallback: old structure
|
// Fallback: old structure
|
||||||
|
|
||||||
const {
|
const {
|
||||||
apiUrl,
|
apiUrl,
|
||||||
apiMethod = 'GET',
|
apiMethod = 'GET',
|
||||||
|
@ -1,73 +1,82 @@
|
|||||||
{
|
{
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"user": {
|
"caseInstance": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"userID": {
|
"caseID": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"userSecretKey": {
|
"caseUUID": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"caseName": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"caseStatus": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "active"
|
||||||
|
},
|
||||||
|
"caseVariables": {
|
||||||
"type": [
|
"type": [
|
||||||
|
"number",
|
||||||
"string",
|
"string",
|
||||||
|
"boolean",
|
||||||
|
"object",
|
||||||
|
"array",
|
||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"userUsername": {
|
"caseSettings": {
|
||||||
"type": [
|
"type": [
|
||||||
|
"number",
|
||||||
"string",
|
"string",
|
||||||
|
"boolean",
|
||||||
|
"object",
|
||||||
|
"array",
|
||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"userPassword": {
|
"caseDefinition": {
|
||||||
"type": [
|
"type": [
|
||||||
|
"number",
|
||||||
"string",
|
"string",
|
||||||
|
"boolean",
|
||||||
|
"object",
|
||||||
|
"array",
|
||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"userFullName": {
|
"caseCreatedDate": {
|
||||||
"type": [
|
"type": "string",
|
||||||
"string",
|
"format": "date-time"
|
||||||
"null"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"userEmail": {
|
"caseModifiedDate": {
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"null"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"userPhone": {
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"null"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"userStatus": {
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"null"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"userCreatedDate": {
|
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
"null"
|
"null"
|
||||||
],
|
],
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
},
|
},
|
||||||
"userModifiedDate": {
|
"caseCompletedDate": {
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
"null"
|
"null"
|
||||||
],
|
],
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
},
|
},
|
||||||
"caseInstance": {
|
"startedBy": {
|
||||||
"type": "array",
|
"anyOf": [
|
||||||
"items": {
|
{
|
||||||
"$ref": "#/definitions/caseInstance"
|
"$ref": "#/definitions/user"
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"process": {
|
||||||
|
"$ref": "#/definitions/process"
|
||||||
},
|
},
|
||||||
"caseTimeline": {
|
"caseTimeline": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
@ -75,123 +84,45 @@
|
|||||||
"$ref": "#/definitions/caseTimeline"
|
"$ref": "#/definitions/caseTimeline"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"forms": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/form"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"formHistoryEntries": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/formHistory"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"processes": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/process"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"processHistoryEntries": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/processHistory"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"task": {
|
"task": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/task"
|
"$ref": "#/definitions/task"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"userrole": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/userrole"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"startedCases": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/caseInstance"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"assignedTasks": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/task"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"caseTimelineEntries": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/caseTimeline"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"role": {
|
"caseTimeline": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"roleID": {
|
"timelineID": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"roleName": {
|
"timelineType": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"timelineDescription": {
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"roleDescription": {
|
"timelineDate": {
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"null"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"roleStatus": {
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"null"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"roleCreatedDate": {
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"format": "date-time"
|
|
||||||
},
|
|
||||||
"roleModifiedDate": {
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"format": "date-time"
|
|
||||||
},
|
|
||||||
"userrole": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/userrole"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"userrole": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"userRoleID": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"userRoleCreatedDate": {
|
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
},
|
},
|
||||||
"role": {
|
"caseInstance": {
|
||||||
"$ref": "#/definitions/role"
|
"$ref": "#/definitions/caseInstance"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"$ref": "#/definitions/user"
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/user"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -277,13 +208,13 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"history": {
|
"formHistory": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/formHistory"
|
"$ref": "#/definitions/formHistory"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tasks": {
|
"task": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/task"
|
"$ref": "#/definitions/task"
|
||||||
@ -366,7 +297,7 @@
|
|||||||
"form": {
|
"form": {
|
||||||
"$ref": "#/definitions/form"
|
"$ref": "#/definitions/form"
|
||||||
},
|
},
|
||||||
"savedByUser": {
|
"user": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/user"
|
"$ref": "#/definitions/user"
|
||||||
@ -507,17 +438,11 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"history": {
|
"processHistory": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/processHistory"
|
"$ref": "#/definitions/processHistory"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"cases": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/caseInstance"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -625,7 +550,7 @@
|
|||||||
"process": {
|
"process": {
|
||||||
"$ref": "#/definitions/process"
|
"$ref": "#/definitions/process"
|
||||||
},
|
},
|
||||||
"savedByUser": {
|
"user": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/user"
|
"$ref": "#/definitions/user"
|
||||||
@ -637,93 +562,48 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"caseInstance": {
|
"role": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"caseID": {
|
"roleID": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"caseUUID": {
|
"roleName": {
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"caseName": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"caseStatus": {
|
|
||||||
"type": "string",
|
|
||||||
"default": "active"
|
|
||||||
},
|
|
||||||
"caseVariables": {
|
|
||||||
"type": [
|
"type": [
|
||||||
"number",
|
|
||||||
"string",
|
"string",
|
||||||
"boolean",
|
|
||||||
"object",
|
|
||||||
"array",
|
|
||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"caseSettings": {
|
"roleDescription": {
|
||||||
"type": [
|
"type": [
|
||||||
"number",
|
|
||||||
"string",
|
"string",
|
||||||
"boolean",
|
|
||||||
"object",
|
|
||||||
"array",
|
|
||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"caseDefinition": {
|
"roleStatus": {
|
||||||
"type": [
|
"type": [
|
||||||
"number",
|
|
||||||
"string",
|
"string",
|
||||||
"boolean",
|
|
||||||
"object",
|
|
||||||
"array",
|
|
||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"caseCreatedDate": {
|
"roleCreatedDate": {
|
||||||
"type": "string",
|
|
||||||
"format": "date-time"
|
|
||||||
},
|
|
||||||
"caseModifiedDate": {
|
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
"null"
|
"null"
|
||||||
],
|
],
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
},
|
},
|
||||||
"caseCompletedDate": {
|
"roleModifiedDate": {
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
"null"
|
"null"
|
||||||
],
|
],
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
},
|
},
|
||||||
"process": {
|
"userrole": {
|
||||||
"$ref": "#/definitions/process"
|
|
||||||
},
|
|
||||||
"startedBy": {
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/definitions/user"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "null"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"tasks": {
|
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/task"
|
"$ref": "#/definitions/userrole"
|
||||||
}
|
|
||||||
},
|
|
||||||
"timeline": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/caseTimeline"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -775,10 +655,10 @@
|
|||||||
],
|
],
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
},
|
},
|
||||||
"case": {
|
"caseInstance": {
|
||||||
"$ref": "#/definitions/caseInstance"
|
"$ref": "#/definitions/caseInstance"
|
||||||
},
|
},
|
||||||
"assignedTo": {
|
"user": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/user"
|
"$ref": "#/definitions/user"
|
||||||
@ -800,51 +680,144 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"caseTimeline": {
|
"user": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"timelineID": {
|
"userID": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"timelineType": {
|
"userSecretKey": {
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"timelineDescription": {
|
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"timelineDate": {
|
"userUsername": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"userPassword": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"userFullName": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"userEmail": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"userPhone": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"userStatus": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"userCreatedDate": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"userModifiedDate": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"caseInstance": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/caseInstance"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"caseTimeline": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/caseTimeline"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"form": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/form"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"formHistory": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/formHistory"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"process": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/process"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"processHistory": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/processHistory"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"task": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/task"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"userrole": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/userrole"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"userrole": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"userRoleID": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"userRoleCreatedDate": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
},
|
},
|
||||||
"case": {
|
"role": {
|
||||||
"$ref": "#/definitions/caseInstance"
|
"$ref": "#/definitions/role"
|
||||||
},
|
},
|
||||||
"createdBy": {
|
"user": {
|
||||||
"anyOf": [
|
"$ref": "#/definitions/user"
|
||||||
{
|
|
||||||
"$ref": "#/definitions/user"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "null"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"user": {
|
"caseInstance": {
|
||||||
"$ref": "#/definitions/user"
|
"$ref": "#/definitions/caseInstance"
|
||||||
},
|
},
|
||||||
"role": {
|
"caseTimeline": {
|
||||||
"$ref": "#/definitions/role"
|
"$ref": "#/definitions/caseTimeline"
|
||||||
},
|
|
||||||
"userrole": {
|
|
||||||
"$ref": "#/definitions/userrole"
|
|
||||||
},
|
},
|
||||||
"form": {
|
"form": {
|
||||||
"$ref": "#/definitions/form"
|
"$ref": "#/definitions/form"
|
||||||
@ -858,14 +831,17 @@
|
|||||||
"processHistory": {
|
"processHistory": {
|
||||||
"$ref": "#/definitions/processHistory"
|
"$ref": "#/definitions/processHistory"
|
||||||
},
|
},
|
||||||
"caseInstance": {
|
"role": {
|
||||||
"$ref": "#/definitions/caseInstance"
|
"$ref": "#/definitions/role"
|
||||||
},
|
},
|
||||||
"task": {
|
"task": {
|
||||||
"$ref": "#/definitions/task"
|
"$ref": "#/definitions/task"
|
||||||
},
|
},
|
||||||
"caseTimeline": {
|
"user": {
|
||||||
"$ref": "#/definitions/caseTimeline"
|
"$ref": "#/definitions/user"
|
||||||
|
},
|
||||||
|
"userrole": {
|
||||||
|
"$ref": "#/definitions/userrole"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,50 +12,42 @@ datasource db {
|
|||||||
url = env("DATABASE_URL")
|
url = env("DATABASE_URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
model user {
|
model caseInstance {
|
||||||
userID Int @id @default(autoincrement())
|
caseID Int @id @default(autoincrement())
|
||||||
userSecretKey String? @db.VarChar(255)
|
caseUUID String @unique @db.VarChar(36)
|
||||||
userUsername String? @db.VarChar(255)
|
processID Int
|
||||||
userPassword String? @db.VarChar(255)
|
caseName String @db.VarChar(255)
|
||||||
userFullName String? @db.VarChar(255)
|
caseStatus String @default("active") @db.VarChar(50)
|
||||||
userEmail String? @db.VarChar(255)
|
caseStartedBy Int?
|
||||||
userPhone String? @db.VarChar(255)
|
caseVariables Json?
|
||||||
userStatus String? @db.VarChar(255)
|
caseSettings Json?
|
||||||
userCreatedDate DateTime? @db.DateTime(0)
|
caseDefinition Json?
|
||||||
userModifiedDate DateTime? @db.DateTime(0)
|
caseCreatedDate DateTime @default(now()) @db.DateTime(0)
|
||||||
caseInstance caseInstance[]
|
caseModifiedDate DateTime? @db.DateTime(0)
|
||||||
caseTimeline caseTimeline[]
|
caseCompletedDate DateTime? @db.DateTime(0)
|
||||||
forms form[] @relation("FormCreator")
|
startedBy user? @relation(fields: [caseStartedBy], references: [userID])
|
||||||
formHistoryEntries formHistory[]
|
process process @relation(fields: [processID], references: [processID])
|
||||||
processes process[] @relation("ProcessCreator")
|
caseTimeline caseTimeline[]
|
||||||
processHistoryEntries processHistory[]
|
task task[]
|
||||||
task task[]
|
|
||||||
userrole userrole[]
|
@@index([processID], map: "FK_case_process")
|
||||||
startedCases caseInstance[] @relation("CaseStartedBy")
|
@@index([caseStartedBy], map: "FK_case_startedBy")
|
||||||
assignedTasks task[] @relation("TaskAssignedTo")
|
@@index([caseStatus], map: "IDX_case_status")
|
||||||
caseTimelineEntries caseTimeline[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model role {
|
model caseTimeline {
|
||||||
roleID Int @id @default(autoincrement())
|
timelineID Int @id @default(autoincrement())
|
||||||
roleName String? @db.VarChar(255)
|
caseID Int
|
||||||
roleDescription String? @db.VarChar(255)
|
timelineType String @db.VarChar(50)
|
||||||
roleStatus String? @db.VarChar(255)
|
timelineDescription String? @db.Text
|
||||||
roleCreatedDate DateTime? @db.DateTime(0)
|
timelineDate DateTime @default(now()) @db.DateTime(0)
|
||||||
roleModifiedDate DateTime? @db.DateTime(0)
|
timelineCreatedBy Int?
|
||||||
userrole userrole[]
|
caseInstance caseInstance @relation(fields: [caseID], references: [caseID])
|
||||||
}
|
user user? @relation(fields: [timelineCreatedBy], references: [userID])
|
||||||
|
|
||||||
model userrole {
|
@@index([caseID], map: "FK_caseTimeline_case")
|
||||||
userRoleID Int @id @default(autoincrement())
|
@@index([timelineCreatedBy], map: "FK_caseTimeline_createdBy")
|
||||||
userRoleUserID Int @default(0)
|
@@index([timelineDate], map: "IDX_caseTimeline_date")
|
||||||
userRoleRoleID Int @default(0)
|
|
||||||
userRoleCreatedDate DateTime @db.DateTime(0)
|
|
||||||
role role @relation(fields: [userRoleRoleID], references: [roleID], onDelete: NoAction, onUpdate: NoAction, map: "FK_userrole_role")
|
|
||||||
user user @relation(fields: [userRoleUserID], references: [userID], onDelete: NoAction, onUpdate: NoAction, map: "FK_userrole_user")
|
|
||||||
|
|
||||||
@@index([userRoleRoleID], map: "FK_userrole_role")
|
|
||||||
@@index([userRoleUserID], map: "FK_userrole_user")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model form {
|
model form {
|
||||||
@ -67,14 +59,14 @@ model form {
|
|||||||
formStatus String @default("active") @db.VarChar(50)
|
formStatus String @default("active") @db.VarChar(50)
|
||||||
formCreatedBy Int?
|
formCreatedBy Int?
|
||||||
formCreatedDate DateTime @default(now()) @db.DateTime(0)
|
formCreatedDate DateTime @default(now()) @db.DateTime(0)
|
||||||
formModifiedDate DateTime? @updatedAt @db.DateTime(0)
|
formModifiedDate DateTime? @db.DateTime(0)
|
||||||
customCSS String? @db.Text
|
customCSS String? @db.Text
|
||||||
customScript String? @db.LongText
|
customScript String? @db.LongText
|
||||||
formEvents Json?
|
formEvents Json?
|
||||||
scriptMode String? @default("safe") @db.VarChar(20)
|
scriptMode String? @default("safe") @db.VarChar(20)
|
||||||
creator user? @relation("FormCreator", fields: [formCreatedBy], references: [userID])
|
creator user? @relation(fields: [formCreatedBy], references: [userID])
|
||||||
history formHistory[] @relation("FormHistoryEntries")
|
formHistory formHistory[]
|
||||||
tasks task[]
|
task task[]
|
||||||
|
|
||||||
@@index([formCreatedBy], map: "FK_form_creator")
|
@@index([formCreatedBy], map: "FK_form_creator")
|
||||||
}
|
}
|
||||||
@ -95,13 +87,13 @@ model formHistory {
|
|||||||
changeDescription String? @db.Text
|
changeDescription String? @db.Text
|
||||||
savedBy Int?
|
savedBy Int?
|
||||||
savedDate DateTime @default(now()) @db.DateTime(0)
|
savedDate DateTime @default(now()) @db.DateTime(0)
|
||||||
form form @relation("FormHistoryEntries", fields: [formID], references: [formID], onDelete: Cascade)
|
form form @relation(fields: [formID], references: [formID], onDelete: Cascade)
|
||||||
savedByUser user? @relation(fields: [savedBy], references: [userID])
|
user user? @relation(fields: [savedBy], references: [userID])
|
||||||
|
|
||||||
@@index([formID], map: "FK_formHistory_form")
|
@@index([formID], map: "FK_formHistory_form")
|
||||||
@@index([savedBy], map: "FK_formHistory_savedBy")
|
@@index([savedBy], map: "FK_formHistory_savedBy")
|
||||||
@@index([formUUID], map: "IDX_formHistory_uuid")
|
|
||||||
@@index([savedDate], map: "IDX_formHistory_date")
|
@@index([savedDate], map: "IDX_formHistory_date")
|
||||||
|
@@index([formUUID], map: "IDX_formHistory_uuid")
|
||||||
}
|
}
|
||||||
|
|
||||||
model process {
|
model process {
|
||||||
@ -114,7 +106,7 @@ model process {
|
|||||||
processStatus String @default("draft") @db.VarChar(50)
|
processStatus String @default("draft") @db.VarChar(50)
|
||||||
processCreatedBy Int?
|
processCreatedBy Int?
|
||||||
processCreatedDate DateTime @default(now()) @db.DateTime(0)
|
processCreatedDate DateTime @default(now()) @db.DateTime(0)
|
||||||
processModifiedDate DateTime? @updatedAt @db.DateTime(0)
|
processModifiedDate DateTime? @db.DateTime(0)
|
||||||
isTemplate Boolean @default(false)
|
isTemplate Boolean @default(false)
|
||||||
processCategory String? @db.VarChar(100)
|
processCategory String? @db.VarChar(100)
|
||||||
processOwner String? @db.VarChar(255)
|
processOwner String? @db.VarChar(255)
|
||||||
@ -125,13 +117,12 @@ model process {
|
|||||||
templateCategory String? @db.VarChar(100)
|
templateCategory String? @db.VarChar(100)
|
||||||
processDeletedDate DateTime? @db.DateTime(0)
|
processDeletedDate DateTime? @db.DateTime(0)
|
||||||
caseInstance caseInstance[]
|
caseInstance caseInstance[]
|
||||||
creator user? @relation("ProcessCreator", fields: [processCreatedBy], references: [userID])
|
creator user? @relation(fields: [processCreatedBy], references: [userID])
|
||||||
history processHistory[] @relation("ProcessHistoryEntries")
|
processHistory processHistory[]
|
||||||
cases caseInstance[]
|
|
||||||
|
|
||||||
@@index([processCreatedBy], map: "FK_process_creator")
|
@@index([processCreatedBy], map: "FK_process_creator")
|
||||||
@@index([processStatus], map: "IDX_process_status")
|
|
||||||
@@index([processCategory], map: "IDX_process_category")
|
@@index([processCategory], map: "IDX_process_category")
|
||||||
|
@@index([processStatus], map: "IDX_process_status")
|
||||||
@@index([isTemplate], map: "IDX_process_template")
|
@@index([isTemplate], map: "IDX_process_template")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,72 +146,77 @@ model processHistory {
|
|||||||
changeDescription String? @db.Text
|
changeDescription String? @db.Text
|
||||||
savedBy Int?
|
savedBy Int?
|
||||||
savedDate DateTime @default(now()) @db.DateTime(0)
|
savedDate DateTime @default(now()) @db.DateTime(0)
|
||||||
process process @relation("ProcessHistoryEntries", fields: [processID], references: [processID], onDelete: Cascade)
|
process process @relation(fields: [processID], references: [processID], onDelete: Cascade)
|
||||||
savedByUser user? @relation(fields: [savedBy], references: [userID])
|
user user? @relation(fields: [savedBy], references: [userID])
|
||||||
|
|
||||||
@@index([processID], map: "FK_processHistory_process")
|
@@index([processID], map: "FK_processHistory_process")
|
||||||
@@index([savedBy], map: "FK_processHistory_savedBy")
|
@@index([savedBy], map: "FK_processHistory_savedBy")
|
||||||
@@index([processUUID], map: "IDX_processHistory_uuid")
|
|
||||||
@@index([savedDate], map: "IDX_processHistory_date")
|
@@index([savedDate], map: "IDX_processHistory_date")
|
||||||
|
@@index([processUUID], map: "IDX_processHistory_uuid")
|
||||||
}
|
}
|
||||||
|
|
||||||
model caseInstance {
|
model role {
|
||||||
caseID Int @id @default(autoincrement())
|
roleID Int @id @default(autoincrement())
|
||||||
caseUUID String @unique @db.VarChar(36)
|
roleName String? @db.VarChar(255)
|
||||||
processID Int
|
roleDescription String? @db.VarChar(255)
|
||||||
caseName String @db.VarChar(255)
|
roleStatus String? @db.VarChar(255)
|
||||||
caseStatus String @default("active") @db.VarChar(50)
|
roleCreatedDate DateTime? @db.DateTime(0)
|
||||||
caseStartedBy Int?
|
roleModifiedDate DateTime? @db.DateTime(0)
|
||||||
caseVariables Json?
|
userrole userrole[]
|
||||||
caseSettings Json?
|
|
||||||
caseDefinition Json?
|
|
||||||
caseCreatedDate DateTime @default(now()) @db.DateTime(0)
|
|
||||||
caseModifiedDate DateTime? @updatedAt @db.DateTime(0)
|
|
||||||
caseCompletedDate DateTime? @db.DateTime(0)
|
|
||||||
process process @relation(fields: [processID], references: [processID])
|
|
||||||
startedBy user? @relation("CaseStartedBy", fields: [caseStartedBy], references: [userID])
|
|
||||||
tasks task[]
|
|
||||||
timeline caseTimeline[]
|
|
||||||
|
|
||||||
@@index([processID], map: "FK_case_process")
|
|
||||||
@@index([caseStartedBy], map: "FK_case_startedBy")
|
|
||||||
@@index([caseStatus], map: "IDX_case_status")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model task {
|
model task {
|
||||||
taskID Int @id @default(autoincrement())
|
taskID Int @id @default(autoincrement())
|
||||||
taskUUID String @unique @db.VarChar(36)
|
taskUUID String @unique @db.VarChar(36)
|
||||||
caseID Int
|
caseID Int
|
||||||
taskName String @db.VarChar(255)
|
taskName String @db.VarChar(255)
|
||||||
taskType String @db.VarChar(50)
|
taskType String @db.VarChar(50)
|
||||||
taskStatus String @default("pending") @db.VarChar(50)
|
taskStatus String @default("pending") @db.VarChar(50)
|
||||||
taskAssignedTo Int?
|
taskAssignedTo Int?
|
||||||
taskFormID Int?
|
taskFormID Int?
|
||||||
taskData Json?
|
taskData Json?
|
||||||
taskCreatedDate DateTime @default(now()) @db.DateTime(0)
|
taskCreatedDate DateTime @default(now()) @db.DateTime(0)
|
||||||
taskModifiedDate DateTime? @updatedAt @db.DateTime(0)
|
taskModifiedDate DateTime? @db.DateTime(0)
|
||||||
taskCompletedDate DateTime? @db.DateTime(0)
|
taskCompletedDate DateTime? @db.DateTime(0)
|
||||||
case caseInstance @relation(fields: [caseID], references: [caseID])
|
caseInstance caseInstance @relation(fields: [caseID], references: [caseID])
|
||||||
assignedTo user? @relation("TaskAssignedTo", fields: [taskAssignedTo], references: [userID])
|
user user? @relation(fields: [taskAssignedTo], references: [userID])
|
||||||
form form? @relation(fields: [taskFormID], references: [formID])
|
form form? @relation(fields: [taskFormID], references: [formID])
|
||||||
|
|
||||||
@@index([caseID], map: "FK_task_case")
|
|
||||||
@@index([taskAssignedTo], map: "FK_task_assignedTo")
|
@@index([taskAssignedTo], map: "FK_task_assignedTo")
|
||||||
|
@@index([caseID], map: "FK_task_case")
|
||||||
@@index([taskFormID], map: "FK_task_form")
|
@@index([taskFormID], map: "FK_task_form")
|
||||||
@@index([taskStatus], map: "IDX_task_status")
|
@@index([taskStatus], map: "IDX_task_status")
|
||||||
}
|
}
|
||||||
|
|
||||||
model caseTimeline {
|
model user {
|
||||||
timelineID Int @id @default(autoincrement())
|
userID Int @id @default(autoincrement())
|
||||||
caseID Int
|
userSecretKey String? @db.VarChar(255)
|
||||||
timelineType String @db.VarChar(50)
|
userUsername String? @db.VarChar(255)
|
||||||
timelineDescription String? @db.Text
|
userPassword String? @db.VarChar(255)
|
||||||
timelineDate DateTime @default(now()) @db.DateTime(0)
|
userFullName String? @db.VarChar(255)
|
||||||
timelineCreatedBy Int?
|
userEmail String? @db.VarChar(255)
|
||||||
case caseInstance @relation(fields: [caseID], references: [caseID])
|
userPhone String? @db.VarChar(255)
|
||||||
createdBy user? @relation(fields: [timelineCreatedBy], references: [userID])
|
userStatus String? @db.VarChar(255)
|
||||||
|
userCreatedDate DateTime? @db.DateTime(0)
|
||||||
@@index([caseID], map: "FK_caseTimeline_case")
|
userModifiedDate DateTime? @db.DateTime(0)
|
||||||
@@index([timelineCreatedBy], map: "FK_caseTimeline_createdBy")
|
caseInstance caseInstance[]
|
||||||
@@index([timelineDate], map: "IDX_caseTimeline_date")
|
caseTimeline caseTimeline[]
|
||||||
|
form form[]
|
||||||
|
formHistory formHistory[]
|
||||||
|
process process[]
|
||||||
|
processHistory processHistory[]
|
||||||
|
task task[]
|
||||||
|
userrole userrole[]
|
||||||
|
}
|
||||||
|
|
||||||
|
model userrole {
|
||||||
|
userRoleID Int @id @default(autoincrement())
|
||||||
|
userRoleUserID Int @default(0)
|
||||||
|
userRoleRoleID Int @default(0)
|
||||||
|
userRoleCreatedDate DateTime @db.DateTime(0)
|
||||||
|
role role @relation(fields: [userRoleRoleID], references: [roleID], onDelete: NoAction, onUpdate: NoAction, map: "FK_userrole_role")
|
||||||
|
user user @relation(fields: [userRoleUserID], references: [userID], onDelete: NoAction, onUpdate: NoAction, map: "FK_userrole_user")
|
||||||
|
|
||||||
|
@@index([userRoleRoleID], map: "FK_userrole_role")
|
||||||
|
@@index([userRoleUserID], map: "FK_userrole_user")
|
||||||
}
|
}
|
||||||
|
198
server/api/process/workflow-api-call.post.js
Normal file
198
server/api/process/workflow-api-call.post.js
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
/**
|
||||||
|
* Workflow API Call Proxy Endpoint
|
||||||
|
*
|
||||||
|
* This endpoint acts as a proxy for API calls made during workflow execution.
|
||||||
|
* It handles the new API node structure with proper authorization and avoids CORS issues.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Helper function to substitute variables in a string
|
||||||
|
function substituteVariables(str, variables) {
|
||||||
|
if (typeof str !== 'string') return str;
|
||||||
|
|
||||||
|
// Replace {{variable}} first
|
||||||
|
str = str.replace(/\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/g, (match, varName) => {
|
||||||
|
const value = variables[varName];
|
||||||
|
if (value === undefined || value === null) return '';
|
||||||
|
if (typeof value === 'object') {
|
||||||
|
return JSON.stringify(value);
|
||||||
|
}
|
||||||
|
return String(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Then replace {variable}
|
||||||
|
str = str.replace(/\{([a-zA-Z0-9_]+)\}/g, (match, varName) => {
|
||||||
|
const value = variables[varName];
|
||||||
|
if (value === undefined || value === null) return '';
|
||||||
|
if (typeof value === 'object') {
|
||||||
|
return JSON.stringify(value);
|
||||||
|
}
|
||||||
|
return String(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build API request from node data
|
||||||
|
function buildApiRequest(nodeData, variables) {
|
||||||
|
// 1. URL (with param substitution)
|
||||||
|
let url = substituteVariables(nodeData.apiUrl, variables);
|
||||||
|
|
||||||
|
// 2. Params (for GET, DELETE, etc.)
|
||||||
|
let params = Array.isArray(nodeData.params) ? nodeData.params : [];
|
||||||
|
if (params.length) {
|
||||||
|
const query = params
|
||||||
|
.filter(p => p.key)
|
||||||
|
.map(p => `${encodeURIComponent(substituteVariables(p.key, variables))}=${encodeURIComponent(substituteVariables(p.value, variables))}`)
|
||||||
|
.join('&');
|
||||||
|
if (query) {
|
||||||
|
url += (url.includes('?') ? '&' : '?') + query;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Headers
|
||||||
|
let headers = {};
|
||||||
|
if (Array.isArray(nodeData.headers)) {
|
||||||
|
nodeData.headers.forEach(h => {
|
||||||
|
if (h.key) headers[substituteVariables(h.key, variables)] = substituteVariables(h.value, variables);
|
||||||
|
});
|
||||||
|
} else if (typeof nodeData.headers === 'object') {
|
||||||
|
headers = { ...nodeData.headers };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Authorization
|
||||||
|
if (nodeData.authorization && nodeData.authorization.type && nodeData.authorization.type !== 'none') {
|
||||||
|
const auth = nodeData.authorization;
|
||||||
|
if (auth.type === 'bearer' && auth.token) {
|
||||||
|
headers['Authorization'] = `Bearer ${substituteVariables(auth.token, variables)}`;
|
||||||
|
} else if (auth.type === 'basic') {
|
||||||
|
if (auth.token) {
|
||||||
|
// Basic Auth with token (JWT or other token)
|
||||||
|
headers['Authorization'] = `Basic ${substituteVariables(auth.token, variables)}`;
|
||||||
|
} else if (auth.username && auth.password) {
|
||||||
|
// Basic Auth with username/password
|
||||||
|
const token = Buffer.from(`${substituteVariables(auth.username, variables)}:${substituteVariables(auth.password, variables)}`).toString('base64');
|
||||||
|
headers['Authorization'] = `Basic ${token}`;
|
||||||
|
}
|
||||||
|
} else if (auth.type === 'apiKey' && auth.key && auth.value) {
|
||||||
|
if (auth.in === 'header') {
|
||||||
|
headers[substituteVariables(auth.key, variables)] = substituteVariables(auth.value, variables);
|
||||||
|
} else if (auth.in === 'query') {
|
||||||
|
url += (url.includes('?') ? '&' : '?') + `${encodeURIComponent(substituteVariables(auth.key, variables))}=${encodeURIComponent(substituteVariables(auth.value, variables))}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Body
|
||||||
|
let body;
|
||||||
|
if (nodeData.body && nodeData.body.type && nodeData.body.type !== 'none') {
|
||||||
|
if (['form-data', 'x-www-form-urlencoded'].includes(nodeData.body.type)) {
|
||||||
|
const dataArr = Array.isArray(nodeData.body.data) ? nodeData.body.data : [];
|
||||||
|
if (nodeData.body.type === 'form-data') {
|
||||||
|
// For server-side, we'll use URLSearchParams for form-data
|
||||||
|
const formData = new URLSearchParams();
|
||||||
|
dataArr.forEach(item => {
|
||||||
|
if (item.key) formData.append(substituteVariables(item.key, variables), substituteVariables(item.value, variables));
|
||||||
|
});
|
||||||
|
body = formData.toString();
|
||||||
|
headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||||
|
} else {
|
||||||
|
// x-www-form-urlencoded
|
||||||
|
body = dataArr
|
||||||
|
.filter(item => item.key)
|
||||||
|
.map(item => `${encodeURIComponent(substituteVariables(item.key, variables))}=${encodeURIComponent(substituteVariables(item.value, variables))}`)
|
||||||
|
.join('&');
|
||||||
|
headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||||
|
}
|
||||||
|
} else if (nodeData.body.type === 'raw') {
|
||||||
|
body = substituteVariables(nodeData.body.data, variables);
|
||||||
|
// Try to detect JSON
|
||||||
|
if (body && body.trim().startsWith('{')) {
|
||||||
|
headers['Content-Type'] = 'application/json';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { url, headers, body };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
try {
|
||||||
|
// Get request body
|
||||||
|
const body = await readBody(event);
|
||||||
|
|
||||||
|
// Extract node configuration and process variables
|
||||||
|
const { nodeData, processVariables } = body;
|
||||||
|
|
||||||
|
// Validate input
|
||||||
|
if (!nodeData || !nodeData.apiUrl) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: {
|
||||||
|
message: 'Invalid API node configuration. Missing apiUrl.'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the API request
|
||||||
|
const { url, headers, body: requestBody } = buildApiRequest(nodeData, processVariables);
|
||||||
|
const apiMethod = nodeData.apiMethod || 'GET';
|
||||||
|
const outputVariable = nodeData.outputVariable || 'apiResponse';
|
||||||
|
const errorVariable = nodeData.errorVariable || 'apiError';
|
||||||
|
const continueOnError = nodeData.continueOnError || false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Prepare fetch options
|
||||||
|
const fetchOptions = {
|
||||||
|
method: apiMethod,
|
||||||
|
headers
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add body for non-GET requests
|
||||||
|
if (!['GET', 'HEAD'].includes(apiMethod) && requestBody) {
|
||||||
|
fetchOptions.body = requestBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the API call
|
||||||
|
const response = await fetch(url, fetchOptions);
|
||||||
|
|
||||||
|
// Get response data
|
||||||
|
let responseData;
|
||||||
|
const contentType = response.headers.get('content-type');
|
||||||
|
|
||||||
|
if (contentType && contentType.includes('application/json')) {
|
||||||
|
responseData = await response.json();
|
||||||
|
} else {
|
||||||
|
responseData = await response.text();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare result
|
||||||
|
const result = {
|
||||||
|
success: response.ok,
|
||||||
|
data: responseData,
|
||||||
|
status: response.status,
|
||||||
|
statusText: response.statusText,
|
||||||
|
headers: Object.fromEntries([...response.headers.entries()])
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
result.error = {
|
||||||
|
message: `API call failed with status ${response.status}`,
|
||||||
|
status: response.status,
|
||||||
|
statusText: response.statusText,
|
||||||
|
data: responseData
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: {
|
||||||
|
message: error.message || 'An error occurred while making the API call',
|
||||||
|
stack: process.env.NODE_ENV === 'development' ? error.stack : undefined
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user