swagger-client 3.27.1 → 3.27.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/dist/swagger-client.browser.js +10806 -11986
- package/dist/swagger-client.browser.min.js +1 -1
- package/dist/swagger-client.browser.min.js.map +1 -1
- package/es/execute/index.js +5 -8
- package/es/execute/oas3/build-request.js +22 -1
- package/es/http/index.js +6 -370
- package/es/http/serializers/request/file.js +46 -0
- package/es/http/serializers/request/format.js +143 -0
- package/es/http/serializers/request/index.js +111 -0
- package/es/http/serializers/response/index.js +55 -0
- package/es/index.js +2 -1
- package/es/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/errors/SchemaRefError.js +3 -0
- package/es/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/visitors/dereference.js +5 -4
- package/es/{specmap → resolver/specmap}/helpers.js +1 -1
- package/es/{specmap → resolver/specmap}/lib/refs.js +8 -8
- package/es/resolver/strategies/generic/index.js +1 -1
- package/es/resolver/strategies/generic/resolve.js +1 -1
- package/lib/execute/index.js +8 -11
- package/lib/execute/oas3/build-request.js +22 -1
- package/lib/http/index.js +6 -379
- package/lib/http/serializers/request/file.js +53 -0
- package/lib/http/serializers/request/format.js +147 -0
- package/lib/http/serializers/request/index.js +117 -0
- package/lib/http/serializers/response/index.js +63 -0
- package/lib/index.js +34 -33
- package/lib/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/errors/SchemaRefError.js +7 -0
- package/lib/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/visitors/dereference.js +6 -5
- package/lib/{specmap → resolver/specmap}/helpers.js +1 -1
- package/lib/{specmap → resolver/specmap}/lib/refs.js +8 -8
- package/lib/resolver/strategies/generic/index.js +1 -1
- package/lib/resolver/strategies/generic/resolve.js +1 -1
- package/package.json +1 -1
- package/es/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/errors/index.js +0 -7
- package/es/specmap/lib/create-error.js +0 -17
- package/lib/resolver/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/errors/index.js +0 -11
- package/lib/specmap/lib/create-error.js +0 -21
- /package/es/{specmap → resolver/specmap}/index.js +0 -0
- /package/es/{specmap → resolver/specmap}/lib/all-of.js +0 -0
- /package/es/{specmap → resolver/specmap}/lib/context-tree.js +0 -0
- /package/es/{specmap → resolver/specmap}/lib/index.js +0 -0
- /package/es/{specmap → resolver/specmap}/lib/parameters.js +0 -0
- /package/es/{specmap → resolver/specmap}/lib/properties.js +0 -0
- /package/lib/{specmap → resolver/specmap}/index.js +0 -0
- /package/lib/{specmap → resolver/specmap}/lib/all-of.js +0 -0
- /package/lib/{specmap → resolver/specmap}/lib/context-tree.js +0 -0
- /package/lib/{specmap → resolver/specmap}/lib/index.js +0 -0
- /package/lib/{specmap → resolver/specmap}/lib/parameters.js +0 -0
- /package/lib/{specmap → resolver/specmap}/lib/properties.js +0 -0
package/es/execute/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import cookie from 'cookie';
|
|
2
2
|
import { isPlainObject } from 'is-plain-object';
|
|
3
|
+
import { ApiDOMStructuredError } from '@swagger-api/apidom-error';
|
|
3
4
|
import { url } from '@swagger-api/apidom-reference/configuration/empty';
|
|
4
5
|
import { DEFAULT_BASE_URL, DEFAULT_OPENAPI_3_SERVER } from '../constants.js';
|
|
5
|
-
import stockHttp
|
|
6
|
-
import
|
|
6
|
+
import stockHttp from '../http/index.js';
|
|
7
|
+
import { serializeRequest } from '../http/serializers/request/index.js';
|
|
7
8
|
import SWAGGER2_PARAMETER_BUILDERS from './swagger2/parameter-builders.js';
|
|
8
9
|
import * as OAS3_PARAMETER_BUILDERS from './oas3/parameter-builders.js';
|
|
9
10
|
import oas3BuildRequest from './oas3/build-request.js';
|
|
@@ -38,10 +39,7 @@ const parseURIReference = uriReference => {
|
|
|
38
39
|
};
|
|
39
40
|
}
|
|
40
41
|
};
|
|
41
|
-
|
|
42
|
-
this.originalError = oriError;
|
|
43
|
-
Object.assign(this, extra || {});
|
|
44
|
-
});
|
|
42
|
+
class OperationNotFoundError extends ApiDOMStructuredError {}
|
|
45
43
|
const findParametersWithName = (name, parameters) => parameters.filter(p => p.name === name);
|
|
46
44
|
|
|
47
45
|
// removes parameters that have duplicate 'in' and 'name' properties
|
|
@@ -272,8 +270,7 @@ export function buildRequest(options) {
|
|
|
272
270
|
|
|
273
271
|
// Will add the query object into the URL, if it exists
|
|
274
272
|
// ... will also create a FormData instance, if multipart/form-data (eg: a file)
|
|
275
|
-
|
|
276
|
-
return req;
|
|
273
|
+
return serializeRequest(req);
|
|
277
274
|
}
|
|
278
275
|
const stripNonAlpha = str => str ? str.replace(/\W/g, '') : null;
|
|
279
276
|
|
|
@@ -61,11 +61,32 @@ export default function buildRequest(options, req) {
|
|
|
61
61
|
const encoding = (_requestBodyDef$conte = (_requestBodyDef$conte2 = requestBodyDef.content[requestContentType]) === null || _requestBodyDef$conte2 === void 0 ? void 0 : _requestBodyDef$conte2.encoding) !== null && _requestBodyDef$conte !== void 0 ? _requestBodyDef$conte : {};
|
|
62
62
|
req.form = {};
|
|
63
63
|
Object.keys(requestBody).forEach(k => {
|
|
64
|
+
let value;
|
|
65
|
+
try {
|
|
66
|
+
value = JSON.parse(requestBody[k]);
|
|
67
|
+
} catch {
|
|
68
|
+
value = requestBody[k];
|
|
69
|
+
}
|
|
64
70
|
req.form[k] = {
|
|
65
|
-
value
|
|
71
|
+
value,
|
|
66
72
|
encoding: encoding[k] || {}
|
|
67
73
|
};
|
|
68
74
|
});
|
|
75
|
+
} else if (typeof requestBody === 'string') {
|
|
76
|
+
var _requestBodyDef$conte3, _requestBodyDef$conte4;
|
|
77
|
+
const encoding = (_requestBodyDef$conte3 = (_requestBodyDef$conte4 = requestBodyDef.content[requestContentType]) === null || _requestBodyDef$conte4 === void 0 ? void 0 : _requestBodyDef$conte4.encoding) !== null && _requestBodyDef$conte3 !== void 0 ? _requestBodyDef$conte3 : {};
|
|
78
|
+
try {
|
|
79
|
+
req.form = {};
|
|
80
|
+
const form = JSON.parse(requestBody);
|
|
81
|
+
Object.entries(form).forEach(([key, value]) => {
|
|
82
|
+
req.form[key] = {
|
|
83
|
+
value,
|
|
84
|
+
encoding: encoding[key] || {}
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
} catch {
|
|
88
|
+
req.form = requestBody;
|
|
89
|
+
}
|
|
69
90
|
} else {
|
|
70
91
|
req.form = requestBody;
|
|
71
92
|
}
|
package/es/http/index.js
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
import qs from 'qs';
|
|
2
|
-
import jsYaml from 'js-yaml';
|
|
3
1
|
import '../helpers/fetch-polyfill.node.js';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export const self = {
|
|
8
|
-
serializeRes,
|
|
9
|
-
mergeInQueryOrForm
|
|
10
|
-
};
|
|
2
|
+
import { serializeRequest } from './serializers/request/index.js';
|
|
3
|
+
import { serializeResponse } from './serializers/response/index.js';
|
|
4
|
+
export { serializeResponse as serializeRes };
|
|
11
5
|
|
|
12
6
|
// Handles fetch-like syntax and the case where there is only one object passed-in
|
|
13
7
|
// (which will have the URL as a property). Also serializes the response.
|
|
@@ -21,7 +15,7 @@ export default async function http(url, request = {}) {
|
|
|
21
15
|
// Serializes query, for convenience
|
|
22
16
|
// Should be the last thing we do, as its hard to mutate the URL with
|
|
23
17
|
// the search string, but much easier to manipulate the req.query object
|
|
24
|
-
|
|
18
|
+
request = serializeRequest(request);
|
|
25
19
|
|
|
26
20
|
// Newlines in header values cause weird error messages from `window.fetch`,
|
|
27
21
|
// so let's message them out.
|
|
@@ -56,7 +50,7 @@ export default async function http(url, request = {}) {
|
|
|
56
50
|
let res;
|
|
57
51
|
try {
|
|
58
52
|
res = await (request.userFetch || fetch)(request.url, request);
|
|
59
|
-
res = await
|
|
53
|
+
res = await serializeResponse(res, url, request);
|
|
60
54
|
if (request.responseInterceptor) {
|
|
61
55
|
res = (await request.responseInterceptor(res)) || res;
|
|
62
56
|
}
|
|
@@ -82,364 +76,6 @@ export default async function http(url, request = {}) {
|
|
|
82
76
|
return res;
|
|
83
77
|
}
|
|
84
78
|
|
|
85
|
-
// exported for testing
|
|
86
|
-
export const shouldDownloadAsText = (contentType = '') => /(json|xml|yaml|text)\b/.test(contentType);
|
|
87
|
-
function parseBody(body, contentType) {
|
|
88
|
-
if (contentType && (contentType.indexOf('application/json') === 0 || contentType.indexOf('+json') > 0)) {
|
|
89
|
-
return JSON.parse(body);
|
|
90
|
-
}
|
|
91
|
-
return jsYaml.load(body);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Serialize the response, returns a promise with headers and the body part of the hash
|
|
95
|
-
export function serializeRes(oriRes, url, {
|
|
96
|
-
loadSpec = false
|
|
97
|
-
} = {}) {
|
|
98
|
-
const res = {
|
|
99
|
-
ok: oriRes.ok,
|
|
100
|
-
url: oriRes.url || url,
|
|
101
|
-
status: oriRes.status,
|
|
102
|
-
statusText: oriRes.statusText,
|
|
103
|
-
headers: serializeHeaders(oriRes.headers)
|
|
104
|
-
};
|
|
105
|
-
const contentType = res.headers['content-type'];
|
|
106
|
-
const useText = loadSpec || shouldDownloadAsText(contentType);
|
|
107
|
-
const getBody = useText ? oriRes.text : oriRes.blob || oriRes.buffer;
|
|
108
|
-
return getBody.call(oriRes).then(body => {
|
|
109
|
-
res.text = body;
|
|
110
|
-
res.data = body;
|
|
111
|
-
if (useText) {
|
|
112
|
-
try {
|
|
113
|
-
const obj = parseBody(body, contentType);
|
|
114
|
-
res.body = obj;
|
|
115
|
-
res.obj = obj;
|
|
116
|
-
} catch (e) {
|
|
117
|
-
res.parseError = e;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return res;
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
function serializeHeaderValue(value) {
|
|
124
|
-
const isMulti = value.includes(', ');
|
|
125
|
-
return isMulti ? value.split(', ') : value;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Serialize headers into a hash, where mutliple-headers result in an array.
|
|
129
|
-
//
|
|
130
|
-
// eg: Cookie: one
|
|
131
|
-
// Cookie: two
|
|
132
|
-
// = { Cookie: [ "one", "two" ]
|
|
133
|
-
export function serializeHeaders(headers = {}) {
|
|
134
|
-
if (typeof headers.entries !== 'function') return {};
|
|
135
|
-
return Array.from(headers.entries()).reduce((acc, [header, value]) => {
|
|
136
|
-
acc[header] = serializeHeaderValue(value);
|
|
137
|
-
return acc;
|
|
138
|
-
}, {});
|
|
139
|
-
}
|
|
140
|
-
export function isFile(obj, navigatorObj) {
|
|
141
|
-
if (!navigatorObj && typeof navigator !== 'undefined') {
|
|
142
|
-
// eslint-disable-next-line no-undef
|
|
143
|
-
navigatorObj = navigator;
|
|
144
|
-
}
|
|
145
|
-
if (navigatorObj && navigatorObj.product === 'ReactNative') {
|
|
146
|
-
if (obj && typeof obj === 'object' && typeof obj.uri === 'string') {
|
|
147
|
-
return true;
|
|
148
|
-
}
|
|
149
|
-
return false;
|
|
150
|
-
}
|
|
151
|
-
if (typeof File !== 'undefined' && obj instanceof File) {
|
|
152
|
-
return true;
|
|
153
|
-
}
|
|
154
|
-
if (typeof Blob !== 'undefined' && obj instanceof Blob) {
|
|
155
|
-
return true;
|
|
156
|
-
}
|
|
157
|
-
if (ArrayBuffer.isView(obj)) {
|
|
158
|
-
return true;
|
|
159
|
-
}
|
|
160
|
-
return obj !== null && typeof obj === 'object' && typeof obj.pipe === 'function';
|
|
161
|
-
}
|
|
162
|
-
function isArrayOfFile(obj, navigatorObj) {
|
|
163
|
-
return Array.isArray(obj) && obj.some(v => isFile(v, navigatorObj));
|
|
164
|
-
}
|
|
165
|
-
const STYLE_SEPARATORS = {
|
|
166
|
-
form: ',',
|
|
167
|
-
spaceDelimited: '%20',
|
|
168
|
-
pipeDelimited: '|'
|
|
169
|
-
};
|
|
170
|
-
const SEPARATORS = {
|
|
171
|
-
csv: ',',
|
|
172
|
-
ssv: '%20',
|
|
173
|
-
tsv: '%09',
|
|
174
|
-
pipes: '|'
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Specialized sub-class of File class, that only
|
|
179
|
-
* accepts string data and retain this data in `data`
|
|
180
|
-
* public property throughout the lifecycle of its instances.
|
|
181
|
-
*
|
|
182
|
-
* This sub-class is exclusively used only when Encoding Object
|
|
183
|
-
* is defined within the Media Type Object (OpenAPI 3.x.y).
|
|
184
|
-
*/
|
|
185
|
-
class FileWithData extends File {
|
|
186
|
-
constructor(data, name = '', options = {}) {
|
|
187
|
-
super([data], name, options);
|
|
188
|
-
this.data = data;
|
|
189
|
-
}
|
|
190
|
-
valueOf() {
|
|
191
|
-
return this.data;
|
|
192
|
-
}
|
|
193
|
-
toString() {
|
|
194
|
-
return this.valueOf();
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// Formats a key-value and returns an array of key-value pairs.
|
|
199
|
-
//
|
|
200
|
-
// Return value example 1: [['color', 'blue']]
|
|
201
|
-
// Return value example 2: [['color', 'blue,black,brown']]
|
|
202
|
-
// Return value example 3: [['color', ['blue', 'black', 'brown']]]
|
|
203
|
-
// Return value example 4: [['color', 'R,100,G,200,B,150']]
|
|
204
|
-
// Return value example 5: [['R', '100'], ['G', '200'], ['B', '150']]
|
|
205
|
-
// Return value example 6: [['color[R]', '100'], ['color[G]', '200'], ['color[B]', '150']]
|
|
206
|
-
function formatKeyValue(key, input, skipEncoding = false) {
|
|
207
|
-
const {
|
|
208
|
-
collectionFormat,
|
|
209
|
-
allowEmptyValue,
|
|
210
|
-
serializationOption,
|
|
211
|
-
encoding
|
|
212
|
-
} = input;
|
|
213
|
-
// `input` can be string
|
|
214
|
-
const value = typeof input === 'object' && !Array.isArray(input) ? input.value : input;
|
|
215
|
-
const encodeFn = skipEncoding ? k => k.toString() : k => encodeURIComponent(k);
|
|
216
|
-
const encodedKey = encodeFn(key);
|
|
217
|
-
if (typeof value === 'undefined' && allowEmptyValue) {
|
|
218
|
-
return [[encodedKey, '']];
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// file
|
|
222
|
-
if (isFile(value) || isArrayOfFile(value)) {
|
|
223
|
-
return [[encodedKey, value]];
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// for OAS 3 Parameter Object for serialization
|
|
227
|
-
if (serializationOption) {
|
|
228
|
-
return formatKeyValueBySerializationOption(key, value, skipEncoding, serializationOption);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// for OAS 3 Encoding Object
|
|
232
|
-
if (encoding) {
|
|
233
|
-
if ([typeof encoding.style, typeof encoding.explode, typeof encoding.allowReserved].some(type => type !== 'undefined')) {
|
|
234
|
-
const {
|
|
235
|
-
style,
|
|
236
|
-
explode,
|
|
237
|
-
allowReserved
|
|
238
|
-
} = encoding;
|
|
239
|
-
return formatKeyValueBySerializationOption(key, value, skipEncoding, {
|
|
240
|
-
style,
|
|
241
|
-
explode,
|
|
242
|
-
allowReserved
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
if (typeof encoding.contentType === 'string') {
|
|
246
|
-
if (encoding.contentType.startsWith('application/json')) {
|
|
247
|
-
// if value is a string, assume value is already a JSON string
|
|
248
|
-
const json = typeof value === 'string' ? value : JSON.stringify(value);
|
|
249
|
-
const encodedJson = encodeFn(json);
|
|
250
|
-
const file = new FileWithData(encodedJson, 'blob', {
|
|
251
|
-
type: encoding.contentType
|
|
252
|
-
});
|
|
253
|
-
return [[encodedKey, file]];
|
|
254
|
-
}
|
|
255
|
-
const encodedData = encodeFn(String(value));
|
|
256
|
-
const blob = new FileWithData(encodedData, 'blob', {
|
|
257
|
-
type: encoding.contentType
|
|
258
|
-
});
|
|
259
|
-
return [[encodedKey, blob]];
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Primitive
|
|
263
|
-
if (typeof value !== 'object') {
|
|
264
|
-
return [[encodedKey, encodeFn(value)]];
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// Array of primitives
|
|
268
|
-
if (Array.isArray(value) && value.every(v => typeof v !== 'object')) {
|
|
269
|
-
return [[encodedKey, value.map(encodeFn).join(',')]];
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Array or object
|
|
273
|
-
return [[encodedKey, encodeFn(JSON.stringify(value))]];
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// for OAS 2 Parameter Object
|
|
277
|
-
// Primitive
|
|
278
|
-
if (typeof value !== 'object') {
|
|
279
|
-
return [[encodedKey, encodeFn(value)]];
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// Array
|
|
283
|
-
if (Array.isArray(value)) {
|
|
284
|
-
if (collectionFormat === 'multi') {
|
|
285
|
-
// In case of multipart/formdata, it is used as array.
|
|
286
|
-
// Otherwise, the caller will convert it to a query by qs.stringify.
|
|
287
|
-
return [[encodedKey, value.map(encodeFn)]];
|
|
288
|
-
}
|
|
289
|
-
return [[encodedKey, value.map(encodeFn).join(SEPARATORS[collectionFormat || 'csv'])]];
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// Object
|
|
293
|
-
return [[encodedKey, '']];
|
|
294
|
-
}
|
|
295
|
-
function formatKeyValueBySerializationOption(key, value, skipEncoding, serializationOption) {
|
|
296
|
-
const style = serializationOption.style || 'form';
|
|
297
|
-
const explode = typeof serializationOption.explode === 'undefined' ? style === 'form' : serializationOption.explode;
|
|
298
|
-
// eslint-disable-next-line no-nested-ternary
|
|
299
|
-
const escape = skipEncoding ? false : serializationOption && serializationOption.allowReserved ? 'unsafe' : 'reserved';
|
|
300
|
-
const encodeFn = v => valueEncoder(v, escape);
|
|
301
|
-
const encodeKeyFn = skipEncoding ? k => k : k => encodeFn(k);
|
|
302
|
-
if (typeof value === 'string') {
|
|
303
|
-
try {
|
|
304
|
-
value = JSON.parse(value);
|
|
305
|
-
} catch {
|
|
306
|
-
// can't parse the value so treat it as as a simple string
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// Primitive
|
|
311
|
-
if (typeof value !== 'object') {
|
|
312
|
-
return [[encodeKeyFn(key), encodeFn(value)]];
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// Array
|
|
316
|
-
if (Array.isArray(value)) {
|
|
317
|
-
if (explode) {
|
|
318
|
-
// In case of multipart/formdata, it is used as array.
|
|
319
|
-
// Otherwise, the caller will convert it to a query by qs.stringify.
|
|
320
|
-
return [[encodeKeyFn(key), value.map(encodeFn)]];
|
|
321
|
-
}
|
|
322
|
-
return [[encodeKeyFn(key), value.map(encodeFn).join(STYLE_SEPARATORS[style])]];
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// Object
|
|
326
|
-
if (style === 'deepObject') {
|
|
327
|
-
return Object.keys(value).map(valueKey => [encodeKeyFn(`${key}[${valueKey}]`), encodeFn(value[valueKey])]);
|
|
328
|
-
}
|
|
329
|
-
if (explode) {
|
|
330
|
-
return Object.keys(value).map(valueKey => [encodeKeyFn(valueKey), encodeFn(value[valueKey])]);
|
|
331
|
-
}
|
|
332
|
-
return [[encodeKeyFn(key), Object.keys(value).map(valueKey => [`${encodeKeyFn(valueKey)},${encodeFn(value[valueKey])}`]).join(',')]];
|
|
333
|
-
}
|
|
334
|
-
function buildFormData(reqForm) {
|
|
335
|
-
/**
|
|
336
|
-
* Build a new FormData instance, support array as field value
|
|
337
|
-
* OAS2.0 - when collectionFormat is multi
|
|
338
|
-
* OAS3.0 - when explode of Encoding Object is true
|
|
339
|
-
*
|
|
340
|
-
* This function explicitly handles Buffers (for backward compatibility)
|
|
341
|
-
* if provided as a values to FormData. FormData can only handle USVString
|
|
342
|
-
* or Blob.
|
|
343
|
-
*
|
|
344
|
-
* @param {Object} reqForm - ori req.form
|
|
345
|
-
* @return {FormData} - new FormData instance
|
|
346
|
-
*/
|
|
347
|
-
return Object.entries(reqForm).reduce((formData, [name, input]) => {
|
|
348
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
349
|
-
for (const [key, value] of formatKeyValue(name, input, true)) {
|
|
350
|
-
if (Array.isArray(value)) {
|
|
351
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
352
|
-
for (const v of value) {
|
|
353
|
-
if (ArrayBuffer.isView(v)) {
|
|
354
|
-
const blob = new Blob([v]);
|
|
355
|
-
formData.append(key, blob);
|
|
356
|
-
} else {
|
|
357
|
-
formData.append(key, v);
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
} else if (ArrayBuffer.isView(value)) {
|
|
361
|
-
const blob = new Blob([value]);
|
|
362
|
-
formData.append(key, blob);
|
|
363
|
-
} else {
|
|
364
|
-
formData.append(key, value);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
return formData;
|
|
368
|
-
}, new FormData());
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// Encodes an object using appropriate serializer.
|
|
372
|
-
export function encodeFormOrQuery(data) {
|
|
373
|
-
/**
|
|
374
|
-
* Encode parameter names and values
|
|
375
|
-
* @param {Object} result - parameter names and values
|
|
376
|
-
* @param {string} parameterName - Parameter name
|
|
377
|
-
* @return {object} encoded parameter names and values
|
|
378
|
-
*/
|
|
379
|
-
const encodedQuery = Object.keys(data).reduce((result, parameterName) => {
|
|
380
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
381
|
-
for (const [key, value] of formatKeyValue(parameterName, data[parameterName])) {
|
|
382
|
-
if (value instanceof FileWithData) {
|
|
383
|
-
result[key] = value.valueOf();
|
|
384
|
-
} else {
|
|
385
|
-
result[key] = value;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
return result;
|
|
389
|
-
}, {});
|
|
390
|
-
return qs.stringify(encodedQuery, {
|
|
391
|
-
encode: false,
|
|
392
|
-
indices: false
|
|
393
|
-
}) || '';
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
// If the request has a `query` object, merge it into the request.url, and delete the object
|
|
397
|
-
// If file and/or multipart, also create FormData instance
|
|
398
|
-
export function mergeInQueryOrForm(req = {}) {
|
|
399
|
-
const {
|
|
400
|
-
url = '',
|
|
401
|
-
query,
|
|
402
|
-
form
|
|
403
|
-
} = req;
|
|
404
|
-
const joinSearch = (...strs) => {
|
|
405
|
-
const search = strs.filter(a => a).join('&'); // Only truthy value
|
|
406
|
-
return search ? `?${search}` : ''; // Only add '?' if there is a str
|
|
407
|
-
};
|
|
408
|
-
if (form) {
|
|
409
|
-
const hasFile = Object.keys(form).some(key => {
|
|
410
|
-
const {
|
|
411
|
-
value
|
|
412
|
-
} = form[key];
|
|
413
|
-
return isFile(value) || isArrayOfFile(value);
|
|
414
|
-
});
|
|
415
|
-
const contentType = req.headers['content-type'] || req.headers['Content-Type'];
|
|
416
|
-
if (hasFile || /multipart\/form-data/i.test(contentType)) {
|
|
417
|
-
const formdata = buildFormData(req.form);
|
|
418
|
-
req.formdata = formdata;
|
|
419
|
-
req.body = formdata;
|
|
420
|
-
} else {
|
|
421
|
-
req.body = encodeFormOrQuery(form);
|
|
422
|
-
}
|
|
423
|
-
delete req.form;
|
|
424
|
-
}
|
|
425
|
-
if (query) {
|
|
426
|
-
const [baseUrl, oriSearch] = url.split('?');
|
|
427
|
-
let newStr = '';
|
|
428
|
-
if (oriSearch) {
|
|
429
|
-
const oriQuery = qs.parse(oriSearch);
|
|
430
|
-
const keysToRemove = Object.keys(query);
|
|
431
|
-
keysToRemove.forEach(key => delete oriQuery[key]);
|
|
432
|
-
newStr = qs.stringify(oriQuery, {
|
|
433
|
-
encode: true
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
|
-
const finalStr = joinSearch(newStr, encodeFormOrQuery(query));
|
|
437
|
-
req.url = baseUrl + finalStr;
|
|
438
|
-
delete req.query;
|
|
439
|
-
}
|
|
440
|
-
return req;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
79
|
// Wrap a http function ( there are otherways to do this, consider this deprecated )
|
|
444
80
|
export function makeHttp(httpFn, preFetch, postFetch) {
|
|
445
81
|
postFetch = postFetch || (a => a);
|
|
@@ -450,7 +86,7 @@ export function makeHttp(httpFn, preFetch, postFetch) {
|
|
|
450
86
|
url: req
|
|
451
87
|
};
|
|
452
88
|
}
|
|
453
|
-
|
|
89
|
+
req = serializeRequest(req);
|
|
454
90
|
req = preFetch(req);
|
|
455
91
|
return postFetch(httpFn(req));
|
|
456
92
|
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export function isFile(obj, navigatorObj) {
|
|
2
|
+
if (!navigatorObj && typeof navigator !== 'undefined') {
|
|
3
|
+
// eslint-disable-next-line no-undef
|
|
4
|
+
navigatorObj = navigator;
|
|
5
|
+
}
|
|
6
|
+
if (navigatorObj && navigatorObj.product === 'ReactNative') {
|
|
7
|
+
if (obj && typeof obj === 'object' && typeof obj.uri === 'string') {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
if (typeof File !== 'undefined' && obj instanceof File) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
if (typeof Blob !== 'undefined' && obj instanceof Blob) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
if (ArrayBuffer.isView(obj)) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
return obj !== null && typeof obj === 'object' && typeof obj.pipe === 'function';
|
|
22
|
+
}
|
|
23
|
+
export function isArrayOfFile(obj, navigatorObj) {
|
|
24
|
+
return Array.isArray(obj) && obj.some(v => isFile(v, navigatorObj));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Specialized sub-class of File class, that only
|
|
29
|
+
* accepts string data and retain this data in `data`
|
|
30
|
+
* public property throughout the lifecycle of its instances.
|
|
31
|
+
*
|
|
32
|
+
* This sub-class is exclusively used only when Encoding Object
|
|
33
|
+
* is defined within the Media Type Object (OpenAPI 3.x.y).
|
|
34
|
+
*/
|
|
35
|
+
export class FileWithData extends File {
|
|
36
|
+
constructor(data, name = '', options = {}) {
|
|
37
|
+
super([data], name, options);
|
|
38
|
+
this.data = data;
|
|
39
|
+
}
|
|
40
|
+
valueOf() {
|
|
41
|
+
return this.data;
|
|
42
|
+
}
|
|
43
|
+
toString() {
|
|
44
|
+
return this.valueOf();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { isFile, isArrayOfFile, FileWithData } from './file.js';
|
|
2
|
+
import { valueEncoder } from '../../../execute/oas3/style-serializer.js';
|
|
3
|
+
const STYLE_SEPARATORS = {
|
|
4
|
+
form: ',',
|
|
5
|
+
spaceDelimited: '%20',
|
|
6
|
+
pipeDelimited: '|'
|
|
7
|
+
};
|
|
8
|
+
const SEPARATORS = {
|
|
9
|
+
csv: ',',
|
|
10
|
+
ssv: '%20',
|
|
11
|
+
tsv: '%09',
|
|
12
|
+
pipes: '|'
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// Formats a key-value and returns an array of key-value pairs.
|
|
16
|
+
//
|
|
17
|
+
// Return value example 1: [['color', 'blue']]
|
|
18
|
+
// Return value example 2: [['color', 'blue,black,brown']]
|
|
19
|
+
// Return value example 3: [['color', ['blue', 'black', 'brown']]]
|
|
20
|
+
// Return value example 4: [['color', 'R,100,G,200,B,150']]
|
|
21
|
+
// Return value example 5: [['R', '100'], ['G', '200'], ['B', '150']]
|
|
22
|
+
// Return value example 6: [['color[R]', '100'], ['color[G]', '200'], ['color[B]', '150']]
|
|
23
|
+
export default function formatKeyValue(key, input, skipEncoding = false) {
|
|
24
|
+
const {
|
|
25
|
+
collectionFormat,
|
|
26
|
+
allowEmptyValue,
|
|
27
|
+
serializationOption,
|
|
28
|
+
encoding
|
|
29
|
+
} = input;
|
|
30
|
+
// `input` can be string
|
|
31
|
+
const value = typeof input === 'object' && !Array.isArray(input) ? input.value : input;
|
|
32
|
+
const encodeFn = skipEncoding ? k => k.toString() : k => encodeURIComponent(k);
|
|
33
|
+
const encodedKey = encodeFn(key);
|
|
34
|
+
if (typeof value === 'undefined' && allowEmptyValue) {
|
|
35
|
+
return [[encodedKey, '']];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// file
|
|
39
|
+
if (isFile(value) || isArrayOfFile(value)) {
|
|
40
|
+
return [[encodedKey, value]];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// for OAS 3 Parameter Object for serialization
|
|
44
|
+
if (serializationOption) {
|
|
45
|
+
return formatKeyValueBySerializationOption(key, value, skipEncoding, serializationOption);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// for OAS 3 Encoding Object
|
|
49
|
+
if (encoding) {
|
|
50
|
+
if ([typeof encoding.style, typeof encoding.explode, typeof encoding.allowReserved].some(type => type !== 'undefined')) {
|
|
51
|
+
const {
|
|
52
|
+
style,
|
|
53
|
+
explode,
|
|
54
|
+
allowReserved
|
|
55
|
+
} = encoding;
|
|
56
|
+
return formatKeyValueBySerializationOption(key, value, skipEncoding, {
|
|
57
|
+
style,
|
|
58
|
+
explode,
|
|
59
|
+
allowReserved
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
if (typeof encoding.contentType === 'string') {
|
|
63
|
+
if (encoding.contentType.startsWith('application/json')) {
|
|
64
|
+
// if value is a string, assume value is already a JSON string
|
|
65
|
+
const json = typeof value === 'string' ? value : JSON.stringify(value);
|
|
66
|
+
const encodedJson = encodeFn(json);
|
|
67
|
+
const file = new FileWithData(encodedJson, 'blob', {
|
|
68
|
+
type: encoding.contentType
|
|
69
|
+
});
|
|
70
|
+
return [[encodedKey, file]];
|
|
71
|
+
}
|
|
72
|
+
const encodedData = encodeFn(String(value));
|
|
73
|
+
const blob = new FileWithData(encodedData, 'blob', {
|
|
74
|
+
type: encoding.contentType
|
|
75
|
+
});
|
|
76
|
+
return [[encodedKey, blob]];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Primitive
|
|
80
|
+
if (typeof value !== 'object') {
|
|
81
|
+
return [[encodedKey, encodeFn(value)]];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Array of primitives
|
|
85
|
+
if (Array.isArray(value) && value.every(v => typeof v !== 'object')) {
|
|
86
|
+
return [[encodedKey, value.map(encodeFn).join(',')]];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Array or object
|
|
90
|
+
return [[encodedKey, encodeFn(JSON.stringify(value))]];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// for OAS 2 Parameter Object
|
|
94
|
+
// Primitive
|
|
95
|
+
if (typeof value !== 'object') {
|
|
96
|
+
return [[encodedKey, encodeFn(value)]];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Array
|
|
100
|
+
if (Array.isArray(value)) {
|
|
101
|
+
if (collectionFormat === 'multi') {
|
|
102
|
+
// In case of multipart/formdata, it is used as array.
|
|
103
|
+
// Otherwise, the caller will convert it to a query by qs.stringify.
|
|
104
|
+
return [[encodedKey, value.map(encodeFn)]];
|
|
105
|
+
}
|
|
106
|
+
return [[encodedKey, value.map(encodeFn).join(SEPARATORS[collectionFormat || 'csv'])]];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Object
|
|
110
|
+
return [[encodedKey, '']];
|
|
111
|
+
}
|
|
112
|
+
function formatKeyValueBySerializationOption(key, value, skipEncoding, serializationOption) {
|
|
113
|
+
const style = serializationOption.style || 'form';
|
|
114
|
+
const explode = typeof serializationOption.explode === 'undefined' ? style === 'form' : serializationOption.explode;
|
|
115
|
+
// eslint-disable-next-line no-nested-ternary
|
|
116
|
+
const escape = skipEncoding ? false : serializationOption && serializationOption.allowReserved ? 'unsafe' : 'reserved';
|
|
117
|
+
const encodeFn = v => valueEncoder(v, escape);
|
|
118
|
+
const encodeKeyFn = skipEncoding ? k => k : k => encodeFn(k);
|
|
119
|
+
|
|
120
|
+
// Primitive
|
|
121
|
+
if (typeof value !== 'object') {
|
|
122
|
+
return [[encodeKeyFn(key), encodeFn(value)]];
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Array
|
|
126
|
+
if (Array.isArray(value)) {
|
|
127
|
+
if (explode) {
|
|
128
|
+
// In case of multipart/formdata, it is used as array.
|
|
129
|
+
// Otherwise, the caller will convert it to a query by qs.stringify.
|
|
130
|
+
return [[encodeKeyFn(key), value.map(encodeFn)]];
|
|
131
|
+
}
|
|
132
|
+
return [[encodeKeyFn(key), value.map(encodeFn).join(STYLE_SEPARATORS[style])]];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Object
|
|
136
|
+
if (style === 'deepObject') {
|
|
137
|
+
return Object.keys(value).map(valueKey => [encodeKeyFn(`${key}[${valueKey}]`), encodeFn(value[valueKey])]);
|
|
138
|
+
}
|
|
139
|
+
if (explode) {
|
|
140
|
+
return Object.keys(value).map(valueKey => [encodeKeyFn(valueKey), encodeFn(value[valueKey])]);
|
|
141
|
+
}
|
|
142
|
+
return [[encodeKeyFn(key), Object.keys(value).map(valueKey => [`${encodeKeyFn(valueKey)},${encodeFn(value[valueKey])}`]).join(',')]];
|
|
143
|
+
}
|