@fsai-flow/workflow 0.0.1
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/.eslintrc.json +33 -0
- package/README.md +11 -0
- package/dist/README.md +11 -0
- package/dist/package.json +42 -0
- package/dist/src/index.d.ts +21 -0
- package/dist/src/index.js +33 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lib/Constants.d.ts +68 -0
- package/dist/src/lib/Constants.js +106 -0
- package/dist/src/lib/Constants.js.map +1 -0
- package/dist/src/lib/DeferredPromise.d.ts +6 -0
- package/dist/src/lib/DeferredPromise.js +11 -0
- package/dist/src/lib/DeferredPromise.js.map +1 -0
- package/dist/src/lib/Expression.d.ts +65 -0
- package/dist/src/lib/Expression.js +215 -0
- package/dist/src/lib/Expression.js.map +1 -0
- package/dist/src/lib/Interfaces.d.ts +1569 -0
- package/dist/src/lib/Interfaces.js +44 -0
- package/dist/src/lib/Interfaces.js.map +1 -0
- package/dist/src/lib/LoggerProxy.d.ts +9 -0
- package/dist/src/lib/LoggerProxy.js +40 -0
- package/dist/src/lib/LoggerProxy.js.map +1 -0
- package/dist/src/lib/MetadataUtils.d.ts +4 -0
- package/dist/src/lib/MetadataUtils.js +27 -0
- package/dist/src/lib/MetadataUtils.js.map +1 -0
- package/dist/src/lib/NodeErrors.d.ts +82 -0
- package/dist/src/lib/NodeErrors.js +289 -0
- package/dist/src/lib/NodeErrors.js.map +1 -0
- package/dist/src/lib/NodeHelpers.d.ts +198 -0
- package/dist/src/lib/NodeHelpers.js +1348 -0
- package/dist/src/lib/NodeHelpers.js.map +1 -0
- package/dist/src/lib/ObservableObject.d.ts +5 -0
- package/dist/src/lib/ObservableObject.js +61 -0
- package/dist/src/lib/ObservableObject.js.map +1 -0
- package/dist/src/lib/RoutingNode.d.ts +18 -0
- package/dist/src/lib/RoutingNode.js +508 -0
- package/dist/src/lib/RoutingNode.js.map +1 -0
- package/dist/src/lib/TelemetryHelpers.d.ts +3 -0
- package/dist/src/lib/TelemetryHelpers.js +69 -0
- package/dist/src/lib/TelemetryHelpers.js.map +1 -0
- package/dist/src/lib/TypeValidation.d.ts +21 -0
- package/dist/src/lib/TypeValidation.js +385 -0
- package/dist/src/lib/TypeValidation.js.map +1 -0
- package/dist/src/lib/VersionedNodeType.d.ts +9 -0
- package/dist/src/lib/VersionedNodeType.js +26 -0
- package/dist/src/lib/VersionedNodeType.js.map +1 -0
- package/dist/src/lib/Workflow.d.ts +248 -0
- package/dist/src/lib/Workflow.js +901 -0
- package/dist/src/lib/Workflow.js.map +1 -0
- package/dist/src/lib/WorkflowDataProxy.d.ts +87 -0
- package/dist/src/lib/WorkflowDataProxy.js +556 -0
- package/dist/src/lib/WorkflowDataProxy.js.map +1 -0
- package/dist/src/lib/WorkflowErrors.d.ts +9 -0
- package/dist/src/lib/WorkflowErrors.js +18 -0
- package/dist/src/lib/WorkflowErrors.js.map +1 -0
- package/dist/src/lib/WorkflowHooks.d.ts +11 -0
- package/dist/src/lib/WorkflowHooks.js +34 -0
- package/dist/src/lib/WorkflowHooks.js.map +1 -0
- package/dist/src/lib/errors/base/base.error.d.ts +30 -0
- package/dist/src/lib/errors/base/base.error.js +45 -0
- package/dist/src/lib/errors/base/base.error.js.map +1 -0
- package/dist/src/lib/errors/base/operational.error.d.ts +15 -0
- package/dist/src/lib/errors/base/operational.error.js +19 -0
- package/dist/src/lib/errors/base/operational.error.js.map +1 -0
- package/dist/src/lib/errors/error.types.d.ts +11 -0
- package/dist/src/lib/errors/error.types.js +3 -0
- package/dist/src/lib/errors/error.types.js.map +1 -0
- package/dist/src/lib/errors/index.d.ts +1 -0
- package/dist/src/lib/errors/index.js +6 -0
- package/dist/src/lib/errors/index.js.map +1 -0
- package/dist/src/lib/result.d.ts +19 -0
- package/dist/src/lib/result.js +36 -0
- package/dist/src/lib/result.js.map +1 -0
- package/dist/src/lib/utils.d.ts +50 -0
- package/dist/src/lib/utils.js +110 -0
- package/dist/src/lib/utils.js.map +1 -0
- package/eslint.config.js +19 -0
- package/jest.config.ts +10 -0
- package/package.json +40 -0
- package/project.json +19 -0
- package/src/index.ts +33 -0
- package/src/lib/Constants.ts +124 -0
- package/src/lib/DeferredPromise.ts +14 -0
- package/src/lib/Expression.ts +375 -0
- package/src/lib/Interfaces.ts +2229 -0
- package/src/lib/LoggerProxy.ts +43 -0
- package/src/lib/MetadataUtils.ts +34 -0
- package/src/lib/NodeErrors.ts +332 -0
- package/src/lib/NodeHelpers.ts +1666 -0
- package/src/lib/ObservableObject.ts +77 -0
- package/src/lib/RoutingNode.ts +862 -0
- package/src/lib/TelemetryHelpers.ts +86 -0
- package/src/lib/TypeValidation.ts +431 -0
- package/src/lib/VersionedNodeType.ts +30 -0
- package/src/lib/Workflow.ts +1266 -0
- package/src/lib/WorkflowDataProxy.ts +708 -0
- package/src/lib/WorkflowErrors.ts +18 -0
- package/src/lib/WorkflowHooks.ts +51 -0
- package/src/lib/errors/base/base.error.ts +68 -0
- package/src/lib/errors/base/operational.error.ts +21 -0
- package/src/lib/errors/error.types.ts +14 -0
- package/src/lib/errors/index.ts +1 -0
- package/src/lib/result.ts +34 -0
- package/src/lib/utils.ts +132 -0
- package/tests/Helpers.ts +667 -0
- package/tests/NodeHelpers.test.ts +3053 -0
- package/tests/ObservableObject.test.ts +171 -0
- package/tests/RoutingNode.test.ts +1680 -0
- package/tests/Workflow.test.ts +1284 -0
- package/tests/WorkflowDataProxy.test.ts +199 -0
- package/tsconfig.json +27 -0
- package/tsconfig.lib.json +11 -0
- package/tsconfig.spec.json +14 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
2
|
+
// eslint-disable-next-line import/no-cycle
|
|
3
|
+
import { ILogger, LogTypes } from './Interfaces';
|
|
4
|
+
|
|
5
|
+
let logger: ILogger | undefined;
|
|
6
|
+
|
|
7
|
+
export function init(loggerInstance: ILogger) {
|
|
8
|
+
logger = loggerInstance;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function getInstance(): ILogger {
|
|
12
|
+
if (logger === undefined) {
|
|
13
|
+
throw new Error('LoggerProxy not initialized');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return logger;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function log(type: LogTypes, message: string, meta: object = {}) {
|
|
20
|
+
getInstance().log(type, message, meta);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Convenience methods below
|
|
24
|
+
|
|
25
|
+
export function debug(message: string, meta: object = {}) {
|
|
26
|
+
getInstance().log('debug', message, meta);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function info(message: string, meta: object = {}) {
|
|
30
|
+
getInstance().log('info', message, meta);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function error(message: string, meta: object = {}) {
|
|
34
|
+
getInstance().log('error', message, meta);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function verbose(message: string, meta: object = {}) {
|
|
38
|
+
getInstance().log('verbose', message, meta);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function warn(message: string, meta: object = {}) {
|
|
42
|
+
getInstance().log('warn', message, meta);
|
|
43
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ITaskMetadata } from './Interfaces';
|
|
2
|
+
import { hasKey } from './utils';
|
|
3
|
+
|
|
4
|
+
function responseHasSubworkflowData(
|
|
5
|
+
response: unknown,
|
|
6
|
+
): response is { executionId: string; workflowId: string } {
|
|
7
|
+
return ['executionId', 'workflowId'].every(
|
|
8
|
+
(x) => hasKey(response, x) && typeof response[x] === 'string',
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
type ISubWorkflowMetadata = Required<Pick<ITaskMetadata, 'subExecution' | 'subExecutionsCount'>>;
|
|
13
|
+
|
|
14
|
+
function parseErrorResponseWorkflowMetadata(response: unknown): ISubWorkflowMetadata | undefined {
|
|
15
|
+
if (!responseHasSubworkflowData(response)) return undefined;
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
subExecution: {
|
|
19
|
+
executionId: response.executionId,
|
|
20
|
+
workflowId: response.workflowId,
|
|
21
|
+
},
|
|
22
|
+
subExecutionsCount: 1,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function parseErrorMetadata(error: unknown): ISubWorkflowMetadata | undefined {
|
|
27
|
+
if (hasKey(error, 'errorResponse')) {
|
|
28
|
+
return parseErrorResponseWorkflowMetadata(error.errorResponse);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// This accounts for cases where the backend attaches the properties on plain errors
|
|
32
|
+
// e.g. from custom nodes throwing literal `Error` or `ApplicationError` objects directly
|
|
33
|
+
return parseErrorResponseWorkflowMetadata(error);
|
|
34
|
+
}
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-shadow */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
3
|
+
/* eslint-disable no-param-reassign */
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
6
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
7
|
+
// eslint-disable-next-line max-classes-per-file
|
|
8
|
+
import { parseString } from 'xml2js';
|
|
9
|
+
// eslint-disable-next-line import/no-cycle
|
|
10
|
+
import { INode, IStatusCodeMessages, JsonObject } from '..';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Top-level properties where an error message can be found in an API response.
|
|
14
|
+
*/
|
|
15
|
+
const ERROR_MESSAGE_PROPERTIES = [
|
|
16
|
+
'cause',
|
|
17
|
+
'error',
|
|
18
|
+
'message',
|
|
19
|
+
'Message',
|
|
20
|
+
'msg',
|
|
21
|
+
'messages',
|
|
22
|
+
'description',
|
|
23
|
+
'reason',
|
|
24
|
+
'detail',
|
|
25
|
+
'details',
|
|
26
|
+
'errors',
|
|
27
|
+
'errorMessage',
|
|
28
|
+
'errorMessages',
|
|
29
|
+
'ErrorMessage',
|
|
30
|
+
'error_message',
|
|
31
|
+
'_error_message',
|
|
32
|
+
'errorDescription',
|
|
33
|
+
'error_description',
|
|
34
|
+
'error_summary',
|
|
35
|
+
'title',
|
|
36
|
+
'text',
|
|
37
|
+
'field',
|
|
38
|
+
'err',
|
|
39
|
+
'type',
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Top-level properties where an HTTP error code can be found in an API response.
|
|
44
|
+
*/
|
|
45
|
+
const ERROR_STATUS_PROPERTIES = [
|
|
46
|
+
'statusCode',
|
|
47
|
+
'status',
|
|
48
|
+
'code',
|
|
49
|
+
'status_code',
|
|
50
|
+
'errorCode',
|
|
51
|
+
'error_code',
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Properties where a nested object can be found in an API response.
|
|
56
|
+
*/
|
|
57
|
+
const ERROR_NESTING_PROPERTIES = ['error', 'err', 'response', 'body', 'data'];
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Base class for specific NodeError-types, with functionality for finding
|
|
61
|
+
* a value recursively inside an error object.
|
|
62
|
+
*/
|
|
63
|
+
abstract class NodeError extends Error {
|
|
64
|
+
description: string | null | undefined;
|
|
65
|
+
|
|
66
|
+
cause: Error | JsonObject;
|
|
67
|
+
|
|
68
|
+
node: INode;
|
|
69
|
+
|
|
70
|
+
timestamp: number;
|
|
71
|
+
|
|
72
|
+
constructor(node: INode, error: Error | JsonObject) {
|
|
73
|
+
super();
|
|
74
|
+
this.name = this.constructor.name;
|
|
75
|
+
this.cause = error;
|
|
76
|
+
this.node = node;
|
|
77
|
+
this.timestamp = Date.now();
|
|
78
|
+
|
|
79
|
+
if (error.message) {
|
|
80
|
+
this.message = error.message as string;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Finds property through exploration based on potential keys and traversal keys.
|
|
86
|
+
* Depth-first approach.
|
|
87
|
+
*
|
|
88
|
+
* This method iterates over `potentialKeys` and, if the value at the key is a
|
|
89
|
+
* truthy value, the type of the value is checked:
|
|
90
|
+
* (1) if a string or number, the value is returned as a string; or
|
|
91
|
+
* (2) if an array,
|
|
92
|
+
* its string or number elements are collected as a long string,
|
|
93
|
+
* its object elements are traversed recursively (restart this function
|
|
94
|
+
* with each object as a starting point), or
|
|
95
|
+
* (3) if it is an object, it traverses the object and nested ones recursively
|
|
96
|
+
* based on the `potentialKeys` and returns a string if found.
|
|
97
|
+
*
|
|
98
|
+
* If nothing found via `potentialKeys` this method iterates over `traversalKeys` and
|
|
99
|
+
* if the value at the key is a traversable object, it restarts with the object as the
|
|
100
|
+
* new starting point (recursion).
|
|
101
|
+
* If nothing found for any of the `traversalKeys`, exploration continues with remaining
|
|
102
|
+
* `traversalKeys`.
|
|
103
|
+
*
|
|
104
|
+
* Otherwise, if all the paths have been exhausted and no value is eligible, `null` is
|
|
105
|
+
* returned.
|
|
106
|
+
*
|
|
107
|
+
* @param {JsonObject} error
|
|
108
|
+
* @param {string[]} potentialKeys
|
|
109
|
+
* @param {string[]} traversalKeys
|
|
110
|
+
* @returns {string | null}
|
|
111
|
+
*/
|
|
112
|
+
protected findProperty(
|
|
113
|
+
error: JsonObject,
|
|
114
|
+
potentialKeys: string[],
|
|
115
|
+
traversalKeys: string[] = [],
|
|
116
|
+
): string | null {
|
|
117
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
118
|
+
for (const key of potentialKeys) {
|
|
119
|
+
if (error[key]) {
|
|
120
|
+
if (typeof error[key] === 'string') return error[key] as string;
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
122
|
+
if (typeof error[key] === 'number') return error[key]!.toString();
|
|
123
|
+
if (Array.isArray(error[key])) {
|
|
124
|
+
// @ts-ignore
|
|
125
|
+
const resolvedErrors: string[] = error[key]
|
|
126
|
+
// @ts-ignore
|
|
127
|
+
.map((error) => {
|
|
128
|
+
if (typeof error === 'string') return error;
|
|
129
|
+
if (typeof error === 'number') return error.toString();
|
|
130
|
+
if (this.isTraversableObject(error)) {
|
|
131
|
+
return this.findProperty(error, potentialKeys);
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
})
|
|
135
|
+
.filter((errorValue: string | null) => errorValue !== null);
|
|
136
|
+
|
|
137
|
+
if (resolvedErrors.length === 0) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
return resolvedErrors.join(' | ');
|
|
141
|
+
}
|
|
142
|
+
if (this.isTraversableObject(error[key])) {
|
|
143
|
+
const property = this.findProperty(error[key] as JsonObject, potentialKeys);
|
|
144
|
+
if (property) {
|
|
145
|
+
return property;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
152
|
+
for (const key of traversalKeys) {
|
|
153
|
+
if (this.isTraversableObject(error[key])) {
|
|
154
|
+
const property = this.findProperty(error[key] as JsonObject, potentialKeys, traversalKeys);
|
|
155
|
+
if (property) {
|
|
156
|
+
return property;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Check if a value is an object with at least one key, i.e. it can be traversed.
|
|
166
|
+
*/
|
|
167
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
168
|
+
protected isTraversableObject(value: any): value is JsonObject {
|
|
169
|
+
return (
|
|
170
|
+
value && typeof value === 'object' && !Array.isArray(value) && !!Object.keys(value).length
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Remove circular references from objects.
|
|
176
|
+
*/
|
|
177
|
+
protected removeCircularRefs(obj: JsonObject, seen = new Set()) {
|
|
178
|
+
seen.add(obj);
|
|
179
|
+
Object.entries(obj).forEach(([key, value]) => {
|
|
180
|
+
if (this.isTraversableObject(value)) {
|
|
181
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
182
|
+
seen.has(value)
|
|
183
|
+
? (obj[key] = { circularReference: true })
|
|
184
|
+
: this.removeCircularRefs(value, seen);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (Array.isArray(value)) {
|
|
188
|
+
value.forEach((val, index) => {
|
|
189
|
+
if (seen.has(val)) {
|
|
190
|
+
value[index] = { circularReference: true };
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (this.isTraversableObject(val)) {
|
|
194
|
+
this.removeCircularRefs(val, seen);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Class for instantiating an operational error, e.g. an invalid credentials error.
|
|
204
|
+
*/
|
|
205
|
+
export class NodeOperationError extends NodeError {
|
|
206
|
+
itemIndex?: number;
|
|
207
|
+
functionality?: string;
|
|
208
|
+
constructor(
|
|
209
|
+
node: INode,
|
|
210
|
+
error: Error | string,
|
|
211
|
+
options?: { description?: string; itemIndex?: number, functionality?: string }
|
|
212
|
+
) {
|
|
213
|
+
if (typeof error === 'string') {
|
|
214
|
+
error = new Error(error);
|
|
215
|
+
}
|
|
216
|
+
super(node, error);
|
|
217
|
+
|
|
218
|
+
if (options?.description) {
|
|
219
|
+
this.description = options.description;
|
|
220
|
+
}
|
|
221
|
+
if (options?.itemIndex !== undefined) {
|
|
222
|
+
this.itemIndex = options.itemIndex;
|
|
223
|
+
}
|
|
224
|
+
if (options?.functionality) {
|
|
225
|
+
this.functionality = options.functionality;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const STATUS_CODE_MESSAGES: IStatusCodeMessages = {
|
|
231
|
+
'4XX': 'Your request is invalid or could not be processed by the service',
|
|
232
|
+
'400': 'Bad request - please check your parameters',
|
|
233
|
+
'401': 'Authorization failed - please check your credentials',
|
|
234
|
+
'402': 'Payment required - perhaps check your payment details?',
|
|
235
|
+
'403': 'Forbidden - perhaps check your credentials?',
|
|
236
|
+
'404': 'The resource you are requesting could not be found',
|
|
237
|
+
'405': 'Method not allowed - please check you are using the right HTTP method',
|
|
238
|
+
'429': 'The service is receiving too many requests from you! Perhaps take a break?',
|
|
239
|
+
|
|
240
|
+
'5XX': 'The service failed to process your request',
|
|
241
|
+
'500': 'The service was not able to process your request',
|
|
242
|
+
'502': 'Bad gateway - the service failed to handle your request',
|
|
243
|
+
'503': 'Service unavailable - perhaps try again later?',
|
|
244
|
+
'504': 'Gateway timed out - perhaps try again later?',
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
const UNKNOWN_ERROR_MESSAGE = 'UNKNOWN ERROR - check the detailed error for more information';
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Class for instantiating an error in an API response, e.g. a 404 Not Found response,
|
|
251
|
+
* with an HTTP error code, an error message and a description.
|
|
252
|
+
*/
|
|
253
|
+
export class NodeApiError extends NodeError {
|
|
254
|
+
httpCode: string | null;
|
|
255
|
+
|
|
256
|
+
constructor(
|
|
257
|
+
node: INode,
|
|
258
|
+
error: JsonObject,
|
|
259
|
+
{
|
|
260
|
+
message,
|
|
261
|
+
description,
|
|
262
|
+
httpCode,
|
|
263
|
+
parseXml,
|
|
264
|
+
}: { message?: string; description?: string; httpCode?: string; parseXml?: boolean } = {},
|
|
265
|
+
) {
|
|
266
|
+
super(node, error);
|
|
267
|
+
if (error['error']) {
|
|
268
|
+
// only for request library error
|
|
269
|
+
this.removeCircularRefs(error['error'] as JsonObject);
|
|
270
|
+
}
|
|
271
|
+
if (message) {
|
|
272
|
+
this.message = message;
|
|
273
|
+
this.description = description;
|
|
274
|
+
this.httpCode = httpCode ?? null;
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
this.httpCode = this.findProperty(error, ERROR_STATUS_PROPERTIES, ERROR_NESTING_PROPERTIES);
|
|
279
|
+
this.setMessage();
|
|
280
|
+
|
|
281
|
+
if (parseXml) {
|
|
282
|
+
this.setDescriptionFromXml(error['error'] as string);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
this.description = this.findProperty(error, ERROR_MESSAGE_PROPERTIES, ERROR_NESTING_PROPERTIES);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
private setDescriptionFromXml(xml: string) {
|
|
290
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
291
|
+
parseString(xml, { explicitArray: false }, (_, result) => {
|
|
292
|
+
if (!result) return;
|
|
293
|
+
|
|
294
|
+
const topLevelKey = Object.keys(result)[0];
|
|
295
|
+
this.description = this.findProperty(
|
|
296
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
297
|
+
result[topLevelKey],
|
|
298
|
+
ERROR_MESSAGE_PROPERTIES,
|
|
299
|
+
['Error'].concat(ERROR_NESTING_PROPERTIES),
|
|
300
|
+
);
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Set the error's message based on the HTTP status code.
|
|
306
|
+
*
|
|
307
|
+
* @returns {void}
|
|
308
|
+
*/
|
|
309
|
+
private setMessage() {
|
|
310
|
+
if (!this.httpCode) {
|
|
311
|
+
this.httpCode = null;
|
|
312
|
+
this.message = UNKNOWN_ERROR_MESSAGE;
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (STATUS_CODE_MESSAGES[this.httpCode]) {
|
|
317
|
+
this.message = STATUS_CODE_MESSAGES[this.httpCode];
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
switch (this.httpCode.charAt(0)) {
|
|
322
|
+
case '4':
|
|
323
|
+
this.message = STATUS_CODE_MESSAGES['4XX'];
|
|
324
|
+
break;
|
|
325
|
+
case '5':
|
|
326
|
+
this.message = STATUS_CODE_MESSAGES['5XX'];
|
|
327
|
+
break;
|
|
328
|
+
default:
|
|
329
|
+
this.message = UNKNOWN_ERROR_MESSAGE;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|