@zcatalyst/transport 0.0.1 → 0.0.3
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/LICENCE +55 -1
- package/README.md +266 -0
- package/dist-cjs/fetch-handler.js +269 -0
- package/dist-cjs/http-handler.js +404 -0
- package/dist-cjs/index.browser.js +23 -0
- package/dist-cjs/index.js +34 -0
- package/dist-cjs/utils/clonable-stream.js +107 -0
- package/dist-cjs/utils/constants.js +55 -0
- package/dist-cjs/utils/enums.js +22 -0
- package/dist-cjs/utils/errors.js +10 -0
- package/dist-cjs/utils/form-data.js +223 -0
- package/dist-cjs/utils/helpers.js +10 -0
- package/dist-cjs/utils/interfaces.js +2 -0
- package/dist-cjs/utils/request-agent.js +22 -0
- package/dist-cjs/utils/request-timeout.js +14 -0
- package/dist-es/fetch-handler.js +261 -0
- package/dist-es/http-handler.js +362 -0
- package/dist-es/index.browser.js +13 -0
- package/dist-es/index.js +21 -0
- package/dist-es/utils/clonable-stream.js +104 -0
- package/dist-es/utils/constants.js +52 -0
- package/dist-es/utils/enums.js +19 -0
- package/dist-es/utils/errors.js +6 -0
- package/dist-es/utils/form-data.js +218 -0
- package/dist-es/utils/helpers.js +7 -0
- package/dist-es/utils/interfaces.js +1 -0
- package/dist-es/utils/request-agent.js +19 -0
- package/dist-es/utils/request-timeout.js +11 -0
- package/dist-types/fetch-handler.d.ts +149 -0
- package/dist-types/http-handler.d.ts +79 -0
- package/dist-types/index.browser.d.ts +29 -0
- package/dist-types/index.d.ts +36 -0
- package/dist-types/ts3.4/fetch-handler.d.ts +149 -0
- package/dist-types/ts3.4/http-handler.d.ts +79 -0
- package/dist-types/ts3.4/index.browser.d.ts +29 -0
- package/dist-types/ts3.4/index.d.ts +36 -0
- package/dist-types/ts3.4/utils/clonable-stream.d.ts +75 -0
- package/dist-types/ts3.4/utils/constants.d.ts +11 -0
- package/dist-types/ts3.4/utils/enums.d.ts +16 -0
- package/dist-types/ts3.4/utils/errors.d.ts +11 -0
- package/dist-types/ts3.4/utils/form-data.d.ts +285 -0
- package/dist-types/ts3.4/utils/helpers.d.ts +13 -0
- package/dist-types/ts3.4/utils/interfaces.d.ts +68 -0
- package/dist-types/ts3.4/utils/request-agent.d.ts +12 -0
- package/dist-types/ts3.4/utils/request-timeout.d.ts +13 -0
- package/dist-types/utils/clonable-stream.d.ts +75 -0
- package/dist-types/utils/constants.d.ts +11 -0
- package/dist-types/utils/enums.d.ts +16 -0
- package/dist-types/utils/errors.d.ts +11 -0
- package/dist-types/utils/form-data.d.ts +285 -0
- package/dist-types/utils/helpers.d.ts +13 -0
- package/dist-types/utils/interfaces.d.ts +68 -0
- package/dist-types/utils/request-agent.d.ts +12 -0
- package/dist-types/utils/request-timeout.d.ts +13 -0
- package/package.json +37 -7
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
const stream_1 = require("stream");
|
|
8
|
+
const util_1 = require("util");
|
|
9
|
+
const clonable_stream_1 = __importDefault(require("./clonable-stream"));
|
|
10
|
+
class FormData extends stream_1.Stream {
|
|
11
|
+
constructor(streams) {
|
|
12
|
+
super();
|
|
13
|
+
this.writable = false;
|
|
14
|
+
this.readable = true;
|
|
15
|
+
this.released = false;
|
|
16
|
+
this.streams = streams || [];
|
|
17
|
+
this.insideLoop = false;
|
|
18
|
+
this.pendingNext = false;
|
|
19
|
+
}
|
|
20
|
+
isStream(value) {
|
|
21
|
+
return (value !== undefined &&
|
|
22
|
+
value !== null &&
|
|
23
|
+
((typeof value.on === 'function' &&
|
|
24
|
+
typeof value.pipe === 'function') ||
|
|
25
|
+
value instanceof stream_1.Readable));
|
|
26
|
+
}
|
|
27
|
+
_multiPartHeader(field, value) {
|
|
28
|
+
const contentDisposition = this._getContentDisposition(value);
|
|
29
|
+
const contentType = this._getContentType(value);
|
|
30
|
+
let contents = '';
|
|
31
|
+
const headers = {
|
|
32
|
+
'Content-Disposition': ['form-data', 'name="' + field + '"'].concat(contentDisposition || []),
|
|
33
|
+
'Content-Type': [contentType]
|
|
34
|
+
};
|
|
35
|
+
for (const prop in headers) {
|
|
36
|
+
if (headers[prop]) {
|
|
37
|
+
const header = headers[prop];
|
|
38
|
+
if (header.length > 0) {
|
|
39
|
+
contents += prop + ': ' + header.join('; ') + FormData.LINE_BREAK;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return '--' + this.getBoundary() + FormData.LINE_BREAK + contents + FormData.LINE_BREAK;
|
|
44
|
+
}
|
|
45
|
+
_getContentDisposition(value) {
|
|
46
|
+
let filename = '';
|
|
47
|
+
let contentDisposition = '';
|
|
48
|
+
if (typeof value === 'object' && value !== null && ('name' in value || 'path' in value)) {
|
|
49
|
+
const val = value;
|
|
50
|
+
filename = (0, path_1.basename)(val.name || val.path || '');
|
|
51
|
+
}
|
|
52
|
+
else if (typeof value === 'object' &&
|
|
53
|
+
value !== null &&
|
|
54
|
+
'readable' in value &&
|
|
55
|
+
'httpVersion' in value &&
|
|
56
|
+
'client' in value) {
|
|
57
|
+
const httpValue = value;
|
|
58
|
+
filename = (0, path_1.basename)(httpValue.client._httpMessage.path || '');
|
|
59
|
+
}
|
|
60
|
+
if (filename) {
|
|
61
|
+
contentDisposition = 'filename="' + filename + '"';
|
|
62
|
+
}
|
|
63
|
+
return contentDisposition;
|
|
64
|
+
}
|
|
65
|
+
_getContentType(value) {
|
|
66
|
+
let contentType = '';
|
|
67
|
+
if (value.readable && value.hasOwnProperty('httpVersion')) {
|
|
68
|
+
contentType = value.headers['content-type'];
|
|
69
|
+
}
|
|
70
|
+
if (!contentType) {
|
|
71
|
+
contentType = FormData.CONTENT_TYPE;
|
|
72
|
+
}
|
|
73
|
+
return contentType;
|
|
74
|
+
}
|
|
75
|
+
_lastBoundary() {
|
|
76
|
+
return '--' + this.getBoundary() + '--' + FormData.LINE_BREAK;
|
|
77
|
+
}
|
|
78
|
+
_generateBoundary() {
|
|
79
|
+
let boundary = '--------------------------';
|
|
80
|
+
for (let i = 0; i < 24; i++) {
|
|
81
|
+
boundary += Math.floor(Math.random() * 10).toString(16);
|
|
82
|
+
}
|
|
83
|
+
this.boundary = boundary;
|
|
84
|
+
return boundary;
|
|
85
|
+
}
|
|
86
|
+
_error(err) {
|
|
87
|
+
this._reset();
|
|
88
|
+
this.emit('error', err);
|
|
89
|
+
}
|
|
90
|
+
_handleStreamErrors(stream) {
|
|
91
|
+
stream.on('error', (err) => {
|
|
92
|
+
this._error(err);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
_pipeNext(stream) {
|
|
96
|
+
this.currentStream = stream;
|
|
97
|
+
if (this.isStream(stream)) {
|
|
98
|
+
stream.on('end', this._getNext.bind(this));
|
|
99
|
+
stream.pipe(this, {
|
|
100
|
+
end: false
|
|
101
|
+
});
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const value = stream;
|
|
105
|
+
this.write(value);
|
|
106
|
+
this._getNext();
|
|
107
|
+
}
|
|
108
|
+
_getNext() {
|
|
109
|
+
this.currentStream = undefined;
|
|
110
|
+
if (this.insideLoop) {
|
|
111
|
+
this.pendingNext = true;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
this.insideLoop = true;
|
|
115
|
+
try {
|
|
116
|
+
do {
|
|
117
|
+
this.pendingNext = false;
|
|
118
|
+
const stream = this.streams.shift();
|
|
119
|
+
if (typeof stream === 'undefined') {
|
|
120
|
+
this.end();
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
this._pipeNext(stream);
|
|
124
|
+
}
|
|
125
|
+
} while (this.pendingNext);
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
this.insideLoop = false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
_reset() {
|
|
132
|
+
this.writable = false;
|
|
133
|
+
this.streams = [];
|
|
134
|
+
this.currentStream = undefined;
|
|
135
|
+
}
|
|
136
|
+
createClone() {
|
|
137
|
+
const newStreams = [];
|
|
138
|
+
this.streams.forEach((stream) => {
|
|
139
|
+
const clone = this.isStream(stream)
|
|
140
|
+
? new clonable_stream_1.default(stream).clone()
|
|
141
|
+
: stream;
|
|
142
|
+
newStreams.push(clone);
|
|
143
|
+
});
|
|
144
|
+
return new FormData(newStreams);
|
|
145
|
+
}
|
|
146
|
+
append(field, value) {
|
|
147
|
+
if (Array.isArray(value)) {
|
|
148
|
+
this._error(new Error('Arrays are not supported.'));
|
|
149
|
+
return this;
|
|
150
|
+
}
|
|
151
|
+
if (typeof value !== 'string' && !Buffer.isBuffer(value) && !this.isStream(value)) {
|
|
152
|
+
value = (0, util_1.inspect)(value);
|
|
153
|
+
}
|
|
154
|
+
if (this.isStream(value)) {
|
|
155
|
+
this._handleStreamErrors(value);
|
|
156
|
+
}
|
|
157
|
+
this.streams.push(this._multiPartHeader(field, value));
|
|
158
|
+
this.streams.push(value);
|
|
159
|
+
this.streams.push(FormData.LINE_BREAK);
|
|
160
|
+
return this;
|
|
161
|
+
}
|
|
162
|
+
getHeaders(userHeaders) {
|
|
163
|
+
const formHeaders = {};
|
|
164
|
+
for (const header in userHeaders) {
|
|
165
|
+
if (userHeaders[header]) {
|
|
166
|
+
formHeaders[header.toLowerCase()] = userHeaders[header];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
formHeaders['content-type'] = 'multipart/form-data; boundary=' + this.getBoundary();
|
|
170
|
+
return formHeaders;
|
|
171
|
+
}
|
|
172
|
+
getBoundary() {
|
|
173
|
+
if (this.boundary === undefined) {
|
|
174
|
+
return this._generateBoundary();
|
|
175
|
+
}
|
|
176
|
+
return this.boundary;
|
|
177
|
+
}
|
|
178
|
+
pipe(dest, options) {
|
|
179
|
+
stream_1.Stream.prototype.pipe.call(this, dest, options);
|
|
180
|
+
this.resume();
|
|
181
|
+
return dest;
|
|
182
|
+
}
|
|
183
|
+
write(data) {
|
|
184
|
+
const lastPart = this.streams.length === 0;
|
|
185
|
+
this.emit('data', data);
|
|
186
|
+
if (lastPart) {
|
|
187
|
+
this.emit('data', this._lastBoundary());
|
|
188
|
+
}
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
pause() {
|
|
192
|
+
if (this.currentStream !== undefined &&
|
|
193
|
+
typeof this.currentStream.pause === 'function') {
|
|
194
|
+
this.currentStream.pause();
|
|
195
|
+
}
|
|
196
|
+
this.emit('pause');
|
|
197
|
+
}
|
|
198
|
+
resume() {
|
|
199
|
+
if (!this.released) {
|
|
200
|
+
this.released = true;
|
|
201
|
+
this.writable = true;
|
|
202
|
+
this._getNext();
|
|
203
|
+
}
|
|
204
|
+
if (this.currentStream && typeof this.currentStream.resume === 'function') {
|
|
205
|
+
this.currentStream.resume();
|
|
206
|
+
}
|
|
207
|
+
this.emit('resume');
|
|
208
|
+
}
|
|
209
|
+
end() {
|
|
210
|
+
this._reset();
|
|
211
|
+
this.emit('end');
|
|
212
|
+
}
|
|
213
|
+
destroy() {
|
|
214
|
+
this._reset();
|
|
215
|
+
this.emit('close');
|
|
216
|
+
}
|
|
217
|
+
toString() {
|
|
218
|
+
return '[object FormData]';
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
FormData.LINE_BREAK = '\r\n';
|
|
222
|
+
FormData.CONTENT_TYPE = 'application/octet-stream';
|
|
223
|
+
exports.default = FormData;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isHttps = isHttps;
|
|
4
|
+
function isHttps(url) {
|
|
5
|
+
if (url === undefined) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
const parsedUrl = url instanceof URL ? url : new URL(url);
|
|
9
|
+
return parsedUrl.protocol === 'https:';
|
|
10
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("@zcatalyst/utils");
|
|
4
|
+
const http_1 = require("http");
|
|
5
|
+
const https_1 = require("https");
|
|
6
|
+
const agentMap = {};
|
|
7
|
+
class RequestAgent {
|
|
8
|
+
constructor(isHttps, host, replaceAgent) {
|
|
9
|
+
const protocol = isHttps ? utils_1.CONSTANTS.PROTOCOL.HTTPS : utils_1.CONSTANTS.PROTOCOL.HTTP;
|
|
10
|
+
if (agentMap[protocol] === undefined) {
|
|
11
|
+
agentMap[protocol] = {};
|
|
12
|
+
}
|
|
13
|
+
const protocolMap = agentMap[protocol];
|
|
14
|
+
if (protocolMap[host] === undefined || replaceAgent) {
|
|
15
|
+
protocolMap[host] = isHttps
|
|
16
|
+
? new https_1.Agent({ keepAlive: true })
|
|
17
|
+
: new http_1.Agent({ keepAlive: true });
|
|
18
|
+
}
|
|
19
|
+
this.agent = protocolMap[host];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.default = RequestAgent;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requestTimeout = requestTimeout;
|
|
4
|
+
function requestTimeout(timeoutInMs = 0) {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
if (timeoutInMs) {
|
|
7
|
+
setTimeout(() => {
|
|
8
|
+
const timeoutError = new Error(`Request did not complete within ${timeoutInMs} ms`);
|
|
9
|
+
timeoutError.name = 'TimeoutError';
|
|
10
|
+
reject(timeoutError);
|
|
11
|
+
}, timeoutInMs);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
6
|
+
var _a, _ResponseHandler_attachAppSpecificHeaders, _ResponseHandler_followZcrfTokenProtocol, _ResponseHandler_followJwtZCAuthProtocol, _ResponseHandler_sendRequest;
|
|
7
|
+
import { addDefaultAppHeaders, Auth_Protocol, collectZCRFToken, ConfigStore, getToken, JWT_COOKIE_PREFIX, PROJECT_ID } from '@zcatalyst/auth-client';
|
|
8
|
+
import { CONSTANTS, getServicePath } from '@zcatalyst/utils';
|
|
9
|
+
import pkg from '../package.json';
|
|
10
|
+
const { version } = pkg;
|
|
11
|
+
import { HTTP_HEADER_MAP as HEADER_MAP, HTTP_HEADER_MAP, X_ZCSRF_TOKEN, ZD_CSRPARAM } from './utils/constants';
|
|
12
|
+
import { CatalystAPIError } from './utils/errors';
|
|
13
|
+
import { requestTimeout } from './utils/request-timeout';
|
|
14
|
+
const { REQ_METHOD } = CONSTANTS;
|
|
15
|
+
export class DefaultHttpResponse {
|
|
16
|
+
constructor(resp) {
|
|
17
|
+
this.statusCode = resp.statusCode;
|
|
18
|
+
this.headers = resp.headers;
|
|
19
|
+
this.config = resp.config;
|
|
20
|
+
this.resp = resp;
|
|
21
|
+
}
|
|
22
|
+
get data() {
|
|
23
|
+
if (this.resp.data === undefined) {
|
|
24
|
+
throw new CatalystAPIError('UNPARSABLE_RESPONSE', `Error while processing response data. Raw server ` +
|
|
25
|
+
`response: "${this.resp.data}". `, '', this.statusCode);
|
|
26
|
+
}
|
|
27
|
+
return this.resp.data;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export class ResponseHandler {
|
|
31
|
+
constructor() { }
|
|
32
|
+
static async fireGeneralRequest({ requestCore, url }, requestOptions = {}) {
|
|
33
|
+
try {
|
|
34
|
+
const headers = requestCore.headers || {};
|
|
35
|
+
const method = requestCore.method;
|
|
36
|
+
const methodAllowsBody = method !== REQ_METHOD.get && method !== REQ_METHOD.head;
|
|
37
|
+
const options = {
|
|
38
|
+
method,
|
|
39
|
+
headers,
|
|
40
|
+
credentials: requestOptions.auth ? 'include' : 'omit',
|
|
41
|
+
body: methodAllowsBody ? requestCore.body : undefined
|
|
42
|
+
};
|
|
43
|
+
const isExternal = requestOptions.service === "external";
|
|
44
|
+
if (requestOptions.auth && !isExternal) {
|
|
45
|
+
options.headers = await _a.attachZCAuthHeaders(headers);
|
|
46
|
+
options.headers = __classPrivateFieldGet(this, _a, "m", _ResponseHandler_attachAppSpecificHeaders).call(this, headers);
|
|
47
|
+
}
|
|
48
|
+
const controller = new AbortController();
|
|
49
|
+
if (requestOptions.abortSignal) {
|
|
50
|
+
requestOptions.abortSignal.addEventListener('abort', () => controller.abort());
|
|
51
|
+
}
|
|
52
|
+
options.signal = controller.signal;
|
|
53
|
+
const response = await Promise.race([
|
|
54
|
+
fetch(url, options),
|
|
55
|
+
requestTimeout(requestOptions?.requestTimeout)
|
|
56
|
+
]);
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
const errorData = await response.json().catch(() => null);
|
|
59
|
+
throw new CatalystAPIError(`HTTP_ERROR_${response.status}`, errorData?.message || response.statusText, errorData, response.status);
|
|
60
|
+
}
|
|
61
|
+
if (requestOptions.retry && requestOptions.retry > 0) {
|
|
62
|
+
try {
|
|
63
|
+
return await _a.wrapResponse(response, {
|
|
64
|
+
...requestOptions,
|
|
65
|
+
request: requestCore
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
requestOptions.retry--;
|
|
70
|
+
return this.fireGeneralRequest({ requestCore, url }, requestOptions);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return await _a.wrapResponse(response, {
|
|
74
|
+
...requestOptions,
|
|
75
|
+
request: requestCore
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
if (error instanceof CatalystAPIError) {
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
if (error.name === 'AbortError') {
|
|
83
|
+
throw new CatalystAPIError('REQUEST_ABORTED', 'The request was aborted', error);
|
|
84
|
+
}
|
|
85
|
+
if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {
|
|
86
|
+
throw new CatalystAPIError('NETWORK_ERROR', 'Network error occurred while making the request', error);
|
|
87
|
+
}
|
|
88
|
+
throw new CatalystAPIError('REQUEST_FAILED', error.message || 'Request failed', error, error.statusCode);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
static async wrapResponse(response, options) {
|
|
92
|
+
try {
|
|
93
|
+
const method = options?.request?.method?.toUpperCase();
|
|
94
|
+
const hasNoBody = method === REQ_METHOD.head || response.status === 204 || response.status === 304;
|
|
95
|
+
let data;
|
|
96
|
+
if (hasNoBody) {
|
|
97
|
+
data = '';
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
switch (options?.expecting || "json") {
|
|
101
|
+
case "buffer":
|
|
102
|
+
data = await response.arrayBuffer();
|
|
103
|
+
break;
|
|
104
|
+
case "raw":
|
|
105
|
+
data = await response.blob();
|
|
106
|
+
break;
|
|
107
|
+
case "json":
|
|
108
|
+
data = await response.json();
|
|
109
|
+
break;
|
|
110
|
+
case "string":
|
|
111
|
+
data = await response.text();
|
|
112
|
+
break;
|
|
113
|
+
default:
|
|
114
|
+
throw new CatalystAPIError('UNSUPPORTED_RESPONSE_TYPE', `Unsupported response type: ${options?.expecting}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return new DefaultHttpResponse({
|
|
118
|
+
headers: response.headers,
|
|
119
|
+
statusCode: response.status,
|
|
120
|
+
data,
|
|
121
|
+
request: options?.request || {},
|
|
122
|
+
config: options || {}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
throw new CatalystAPIError('RESPONSE_PARSE_ERROR', 'Failed to parse response data', error);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
static async fireRawRequest(requestCore, reqOptions) {
|
|
130
|
+
let headers = requestCore.headers;
|
|
131
|
+
if (reqOptions.auth) {
|
|
132
|
+
headers = await _a.attachZCAuthHeaders(headers);
|
|
133
|
+
headers = __classPrivateFieldGet(this, _a, "m", _ResponseHandler_attachAppSpecificHeaders).call(this, headers);
|
|
134
|
+
headers = { ...headers, credentials: 'include' };
|
|
135
|
+
}
|
|
136
|
+
const options = {
|
|
137
|
+
method: requestCore.method,
|
|
138
|
+
headers
|
|
139
|
+
};
|
|
140
|
+
if (requestCore.method !== REQ_METHOD.get && requestCore.body !== null)
|
|
141
|
+
options.body = requestCore.body;
|
|
142
|
+
const url = this.apiDomain ? `${this.apiDomain}${requestCore.url}` : requestCore.url;
|
|
143
|
+
return await this.wrapResponse(await fetch(url, options));
|
|
144
|
+
}
|
|
145
|
+
static async attachZCAuthHeaders(headers) {
|
|
146
|
+
const authProtocol = ConfigStore.get('AUTH_PROTOCOL');
|
|
147
|
+
switch (authProtocol) {
|
|
148
|
+
case Auth_Protocol.ZcrfTokenProtocol:
|
|
149
|
+
return await __classPrivateFieldGet(_a, _a, "m", _ResponseHandler_followZcrfTokenProtocol).call(_a, headers);
|
|
150
|
+
case Auth_Protocol.JwtTokenProtocol:
|
|
151
|
+
return await __classPrivateFieldGet(_a, _a, "m", _ResponseHandler_followJwtZCAuthProtocol).call(_a, headers);
|
|
152
|
+
default:
|
|
153
|
+
return Promise.resolve(headers);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
static getJWTZCAuthToken() {
|
|
157
|
+
const jwtPrefix = ConfigStore.get(JWT_COOKIE_PREFIX);
|
|
158
|
+
return new Promise((resolve, reject) => {
|
|
159
|
+
const jwtZCAuthToken = getToken();
|
|
160
|
+
if (jwtZCAuthToken === '') {
|
|
161
|
+
reject('Unable to get the JWT Access Token.');
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
resolve({
|
|
165
|
+
access_token: `${jwtPrefix} ${jwtZCAuthToken}`
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
static appendQueryString(url, qs) {
|
|
171
|
+
if (!qs || Object.keys(qs).length === 0) {
|
|
172
|
+
return url;
|
|
173
|
+
}
|
|
174
|
+
const searchParams = new URLSearchParams();
|
|
175
|
+
Object.entries(qs)
|
|
176
|
+
.filter(([_, value]) => value != null)
|
|
177
|
+
.forEach(([key, value]) => searchParams.append(key, String(value)));
|
|
178
|
+
const baseUrl = url.split('?')[0];
|
|
179
|
+
const existingParams = url.split('?')[1] || '';
|
|
180
|
+
return `${baseUrl}?${existingParams ? `${existingParams}&` : ''}${searchParams.toString()}`;
|
|
181
|
+
}
|
|
182
|
+
static async send(options, componentName, componentVersion) {
|
|
183
|
+
const headers = options.headers || {};
|
|
184
|
+
const isExternal = options.service === "external";
|
|
185
|
+
if (!isExternal) {
|
|
186
|
+
let userAgent = CONSTANTS.USER_AGENT.PREFIX + version;
|
|
187
|
+
if (componentName) {
|
|
188
|
+
userAgent += ` ${componentName}/${componentVersion || 'unknown'}`;
|
|
189
|
+
}
|
|
190
|
+
headers['X-Catalyst-User-Agent'] = userAgent;
|
|
191
|
+
}
|
|
192
|
+
let data = options.data;
|
|
193
|
+
if (data !== undefined) {
|
|
194
|
+
switch (options.type) {
|
|
195
|
+
case "json":
|
|
196
|
+
data = JSON.stringify(data);
|
|
197
|
+
headers['Content-Type'] = HEADER_MAP.CONTENT_JSON;
|
|
198
|
+
break;
|
|
199
|
+
case "file":
|
|
200
|
+
const formData = new FormData();
|
|
201
|
+
const keyData = Object.keys(data);
|
|
202
|
+
keyData.forEach((key) => {
|
|
203
|
+
formData.append(key, data[key]);
|
|
204
|
+
});
|
|
205
|
+
data = formData;
|
|
206
|
+
break;
|
|
207
|
+
case "raw":
|
|
208
|
+
if (headers['Content-Type'] === undefined) {
|
|
209
|
+
headers['Content-Type'] = 'application/octet-stream';
|
|
210
|
+
}
|
|
211
|
+
data = new Blob([data], { type: headers['Content-Type'] });
|
|
212
|
+
break;
|
|
213
|
+
default:
|
|
214
|
+
data = JSON.stringify(data);
|
|
215
|
+
headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (this.apiDomain === null && !options.origin) {
|
|
219
|
+
throw new CatalystAPIError('API_REQUEST_ERROR', 'Unable to get the base url');
|
|
220
|
+
}
|
|
221
|
+
if (!isExternal && options.path) {
|
|
222
|
+
options.path = `${getServicePath(options.service)}/project/${ConfigStore.get(PROJECT_ID)}${options.path}`;
|
|
223
|
+
}
|
|
224
|
+
const request = {
|
|
225
|
+
url: options.url ?? `${options.origin ?? this.apiDomain}${options.path}`,
|
|
226
|
+
method: options.method,
|
|
227
|
+
...(data ? { body: data } : {}),
|
|
228
|
+
headers
|
|
229
|
+
};
|
|
230
|
+
request.url = this.appendQueryString(request.url, options.qs);
|
|
231
|
+
return await __classPrivateFieldGet(this, _a, "m", _ResponseHandler_sendRequest).call(this, request, {
|
|
232
|
+
expecting: options.expecting,
|
|
233
|
+
auth: options.auth ?? true,
|
|
234
|
+
service: options.service
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
_a = ResponseHandler, _ResponseHandler_attachAppSpecificHeaders = function _ResponseHandler_attachAppSpecificHeaders(headers) {
|
|
239
|
+
let normalizedHeaders = headers;
|
|
240
|
+
normalizedHeaders = addDefaultAppHeaders(normalizedHeaders);
|
|
241
|
+
return normalizedHeaders;
|
|
242
|
+
}, _ResponseHandler_followZcrfTokenProtocol = async function _ResponseHandler_followZcrfTokenProtocol(headers) {
|
|
243
|
+
await collectZCRFToken();
|
|
244
|
+
const csrfToken = ConfigStore.get('CSRF_TOKEN');
|
|
245
|
+
headers[X_ZCSRF_TOKEN] = `${ZD_CSRPARAM}=${csrfToken}`;
|
|
246
|
+
return headers;
|
|
247
|
+
}, _ResponseHandler_followJwtZCAuthProtocol = async function _ResponseHandler_followJwtZCAuthProtocol(headers) {
|
|
248
|
+
return this.getJWTZCAuthToken()
|
|
249
|
+
.then((resp) => {
|
|
250
|
+
headers[HTTP_HEADER_MAP.AUTHORIZATION_KEY] =
|
|
251
|
+
resp.access_token;
|
|
252
|
+
return headers;
|
|
253
|
+
})
|
|
254
|
+
.catch((err) => {
|
|
255
|
+
throw new CatalystAPIError('API_ERROR', err.message, err.status);
|
|
256
|
+
});
|
|
257
|
+
}, _ResponseHandler_sendRequest = async function _ResponseHandler_sendRequest(request, options) {
|
|
258
|
+
const { url, ...requestCore } = request;
|
|
259
|
+
return _a.fireGeneralRequest({ url, requestCore }, options);
|
|
260
|
+
};
|
|
261
|
+
ResponseHandler.apiDomain = typeof document !== 'undefined' ? document.location.origin : '';
|