openapi-typesafe-fetch 1.0.0-rc.2 → 1.0.0-rc.4
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/CHANGELOG.md +763 -0
- package/README.md +2 -2
- package/dist/helpers.cjs +3 -0
- package/dist/helpers.cjs.map +1 -0
- package/dist/helpers.d.cts +299 -0
- package/dist/helpers.d.mts +299 -0
- package/dist/helpers.d.ts +299 -0
- package/dist/helpers.mjs +2 -0
- package/dist/helpers.mjs.map +1 -0
- package/dist/index.cjs +190 -131
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -17
- package/dist/index.d.mts +64 -17
- package/dist/index.d.ts +64 -17
- package/dist/index.mjs +190 -131
- package/dist/index.mjs.map +1 -1
- package/package.json +18 -9
- package/src/helpers.ts +437 -0
- package/src/index.d.ts +60 -16
- package/src/index.js +305 -183
package/dist/index.cjs
CHANGED
|
@@ -3,13 +3,15 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
const PATH_PARAM_RE = /\{[^{}]+\}/g;
|
|
6
|
-
const DOT_SEGMENT_RE =
|
|
6
|
+
const DOT_SEGMENT_RE = /^\.\.?$/;
|
|
7
7
|
const QUERY_OR_FRAGMENT_RE = /[?#]/;
|
|
8
|
-
const JSON_MEDIA_TYPE_RE =
|
|
8
|
+
const JSON_MEDIA_TYPE_RE = /^[^/]+\/([^;]*\+)?json\s*(;|$)/i;
|
|
9
|
+
const TEXT_MEDIA_TYPE_RE = /^text\//i;
|
|
9
10
|
const FORM_MEDIA_TYPE_RE = /^application\/x-www-form-urlencoded(;|$)/i;
|
|
10
11
|
const MULTIPART_MEDIA_TYPE_RE = /^multipart\/form-data(;|$)/i;
|
|
11
12
|
const NESTED_FORM_VALUE_MESSAGE = "Nested form values need your own `bodySerializer()`.";
|
|
12
13
|
const BOUNDARY_PARAMETER_RE = /;\s*boundary=/i;
|
|
14
|
+
const CLIENT_BUILT_FORM = Symbol.for("openapi-typesafe-fetch/form");
|
|
13
15
|
const supportsRequestInitExt = () => {
|
|
14
16
|
return typeof process === "object" && process.versions?.undici;
|
|
15
17
|
};
|
|
@@ -80,12 +82,14 @@ function createClient(clientOptions) {
|
|
|
80
82
|
headers,
|
|
81
83
|
params.header
|
|
82
84
|
);
|
|
83
|
-
if (serializedBody
|
|
84
|
-
finalHeaders
|
|
85
|
+
if (isPlatformInstance(serializedBody, "FormData")) {
|
|
86
|
+
dropFormContentType(finalHeaders, serializedBody[CLIENT_BUILT_FORM] === true);
|
|
85
87
|
}
|
|
86
88
|
const finalMiddlewares = [...globalMiddlewares, ...requestMiddlewares];
|
|
87
89
|
const requestInit = {
|
|
88
90
|
redirect: "follow",
|
|
91
|
+
// The Fetch standard requires `duplex: "half"` (its only value) for a stream body.
|
|
92
|
+
duplex: isStreamBody(serializedBody) ? "half" : void 0,
|
|
89
93
|
...baseOptions,
|
|
90
94
|
...init,
|
|
91
95
|
body: serializedBody,
|
|
@@ -145,8 +149,8 @@ function createClient(clientOptions) {
|
|
|
145
149
|
if (!response) {
|
|
146
150
|
try {
|
|
147
151
|
response = await fetch(request, requestInitExt);
|
|
148
|
-
} catch (
|
|
149
|
-
let errorAfterMiddleware =
|
|
152
|
+
} catch (error) {
|
|
153
|
+
let errorAfterMiddleware = error;
|
|
150
154
|
if (finalMiddlewares.length) {
|
|
151
155
|
for (let i = finalMiddlewares.length - 1; i >= 0; i--) {
|
|
152
156
|
const m = finalMiddlewares[i];
|
|
@@ -178,6 +182,9 @@ function createClient(clientOptions) {
|
|
|
178
182
|
throw errorAfterMiddleware;
|
|
179
183
|
}
|
|
180
184
|
}
|
|
185
|
+
if (!isResponse(response)) {
|
|
186
|
+
throw new Error("fetch: must return new Response()");
|
|
187
|
+
}
|
|
181
188
|
if (finalMiddlewares.length) {
|
|
182
189
|
for (let i = finalMiddlewares.length - 1; i >= 0; i--) {
|
|
183
190
|
const m = finalMiddlewares[i];
|
|
@@ -207,28 +214,9 @@ function createClient(clientOptions) {
|
|
|
207
214
|
return response.ok ? { data: void 0, response } : { error: void 0, response };
|
|
208
215
|
}
|
|
209
216
|
if (response.ok) {
|
|
210
|
-
|
|
211
|
-
if (parseAs === "stream") {
|
|
212
|
-
return response.body;
|
|
213
|
-
}
|
|
214
|
-
if (parseAs === "json" && !contentLength) {
|
|
215
|
-
const raw2 = await response.text();
|
|
216
|
-
return raw2 ? JSON.parse(raw2) : void 0;
|
|
217
|
-
}
|
|
218
|
-
return await response[parseAs]();
|
|
219
|
-
};
|
|
220
|
-
return { data: await getResponseData(), response };
|
|
221
|
-
}
|
|
222
|
-
const raw = await response.text();
|
|
223
|
-
if (!raw) {
|
|
224
|
-
return { error: void 0, response };
|
|
225
|
-
}
|
|
226
|
-
let error = raw;
|
|
227
|
-
try {
|
|
228
|
-
error = JSON.parse(raw);
|
|
229
|
-
} catch {
|
|
217
|
+
return { data: await readSuccessBody(response, parseAs), response };
|
|
230
218
|
}
|
|
231
|
-
return { error, response };
|
|
219
|
+
return { error: await readErrorBody(response), response };
|
|
232
220
|
}
|
|
233
221
|
return {
|
|
234
222
|
request(method, url, init) {
|
|
@@ -352,6 +340,11 @@ function wrapAsPathBasedClient(coreClient) {
|
|
|
352
340
|
function createPathBasedClient(clientOptions) {
|
|
353
341
|
return wrapAsPathBasedClient(createClient(clientOptions));
|
|
354
342
|
}
|
|
343
|
+
function dropFormContentType(headers, isClientBuilt) {
|
|
344
|
+
if (isClientBuilt || !BOUNDARY_PARAMETER_RE.test(headers.get("Content-Type"))) {
|
|
345
|
+
headers.delete("Content-Type");
|
|
346
|
+
}
|
|
347
|
+
}
|
|
355
348
|
function isHeaders(value) {
|
|
356
349
|
return typeof value?.get === "function";
|
|
357
350
|
}
|
|
@@ -359,142 +352,183 @@ function isRequest(value) {
|
|
|
359
352
|
return typeof value?.method === "string" && typeof value.url === "string" && isHeaders(value.headers);
|
|
360
353
|
}
|
|
361
354
|
function isResponse(value) {
|
|
362
|
-
return typeof value?.status === "number" && isHeaders(value.headers);
|
|
355
|
+
return typeof value?.ok === "boolean" && typeof value.status === "number" && typeof value.text === "function" && isHeaders(value.headers);
|
|
356
|
+
}
|
|
357
|
+
function parseJSON(raw, response) {
|
|
358
|
+
try {
|
|
359
|
+
return JSON.parse(raw);
|
|
360
|
+
} catch {
|
|
361
|
+
const contentType = response.headers.get("Content-Type");
|
|
362
|
+
const hint = TEXT_MEDIA_TYPE_RE.test(contentType) ? 'set `parseAs: "text"`' : "set `parseAs`";
|
|
363
|
+
const subject = `Response ${response.status} (${contentType ?? "no Content-Type"})`;
|
|
364
|
+
throw new SyntaxError(`${subject} is not JSON (${raw.length} characters); ${hint}`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
async function readSuccessBody(response, parseAs) {
|
|
368
|
+
if (parseAs === "stream") {
|
|
369
|
+
return response.body;
|
|
370
|
+
}
|
|
371
|
+
if (parseAs !== "json") {
|
|
372
|
+
return response[parseAs]();
|
|
373
|
+
}
|
|
374
|
+
const raw = await response.text();
|
|
375
|
+
return raw ? parseJSON(raw, response) : void 0;
|
|
376
|
+
}
|
|
377
|
+
async function readErrorBody(response) {
|
|
378
|
+
const raw = await response.text();
|
|
379
|
+
if (!raw) {
|
|
380
|
+
return void 0;
|
|
381
|
+
}
|
|
382
|
+
try {
|
|
383
|
+
return JSON.parse(raw);
|
|
384
|
+
} catch {
|
|
385
|
+
return raw;
|
|
386
|
+
}
|
|
363
387
|
}
|
|
364
388
|
const KEPT_NAME_ESCAPES = /%(?:5B|5D|24|3A|40|2C)/g;
|
|
365
389
|
function encodeName(name) {
|
|
366
390
|
return encodeURIComponent(name).replace(KEPT_NAME_ESCAPES, decodeURIComponent);
|
|
367
391
|
}
|
|
392
|
+
function isDate(value) {
|
|
393
|
+
return typeof value?.toISOString === "function";
|
|
394
|
+
}
|
|
395
|
+
function valueText(value) {
|
|
396
|
+
return isDate(value) ? value.toISOString() : value;
|
|
397
|
+
}
|
|
398
|
+
function encodeValue(value, allowReserved) {
|
|
399
|
+
const text = valueText(value);
|
|
400
|
+
return allowReserved === true ? text : encodeURIComponent(text);
|
|
401
|
+
}
|
|
368
402
|
function serializePrimitiveParam(name, value, options) {
|
|
369
403
|
if (value === void 0 || value === null) {
|
|
370
404
|
return "";
|
|
371
405
|
}
|
|
372
|
-
if (typeof value === "object") {
|
|
406
|
+
if (typeof value === "object" && !isDate(value)) {
|
|
373
407
|
throw new Error(
|
|
374
408
|
"Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
|
|
375
409
|
);
|
|
376
410
|
}
|
|
377
|
-
return `${name}=${options?.allowReserved
|
|
411
|
+
return `${name}=${encodeValue(value, options?.allowReserved)}`;
|
|
412
|
+
}
|
|
413
|
+
function joinExploded(values, style) {
|
|
414
|
+
const joiner = { simple: ",", label: ".", matrix: ";" }[style] || "&";
|
|
415
|
+
const final = values.join(joiner);
|
|
416
|
+
return style === "label" || style === "matrix" ? `${joiner}${final}` : final;
|
|
417
|
+
}
|
|
418
|
+
function serializeUnexplodedObject(name, value, options) {
|
|
419
|
+
const values = [];
|
|
420
|
+
for (const k in value) {
|
|
421
|
+
values.push(encodeValue(k), encodeValue(value[k], options.allowReserved));
|
|
422
|
+
}
|
|
423
|
+
const final = values.join(",");
|
|
424
|
+
switch (options.style) {
|
|
425
|
+
case "form": {
|
|
426
|
+
return `${name}=${final}`;
|
|
427
|
+
}
|
|
428
|
+
case "label": {
|
|
429
|
+
return `.${final}`;
|
|
430
|
+
}
|
|
431
|
+
case "matrix": {
|
|
432
|
+
return `;${name}=${final}`;
|
|
433
|
+
}
|
|
434
|
+
default: {
|
|
435
|
+
return final;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
378
438
|
}
|
|
379
439
|
function serializeObjectParam(name, value, options) {
|
|
380
|
-
if (!value || typeof value !== "object") {
|
|
440
|
+
if (!value || typeof value !== "object" || !Object.keys(value).length) {
|
|
381
441
|
return "";
|
|
382
442
|
}
|
|
383
|
-
const values = [];
|
|
384
|
-
const joiner = {
|
|
385
|
-
simple: ",",
|
|
386
|
-
label: ".",
|
|
387
|
-
matrix: ";"
|
|
388
|
-
}[options.style] || "&";
|
|
389
443
|
if (options.style !== "deepObject" && options.explode === false) {
|
|
390
|
-
|
|
391
|
-
values.push(
|
|
392
|
-
encodeName(k),
|
|
393
|
-
options.allowReserved === true ? value[k] : encodeURIComponent(value[k])
|
|
394
|
-
);
|
|
395
|
-
}
|
|
396
|
-
const final2 = values.join(",");
|
|
397
|
-
switch (options.style) {
|
|
398
|
-
case "form": {
|
|
399
|
-
return `${name}=${final2}`;
|
|
400
|
-
}
|
|
401
|
-
case "label": {
|
|
402
|
-
return `.${final2}`;
|
|
403
|
-
}
|
|
404
|
-
case "matrix": {
|
|
405
|
-
return `;${name}=${final2}`;
|
|
406
|
-
}
|
|
407
|
-
default: {
|
|
408
|
-
return final2;
|
|
409
|
-
}
|
|
410
|
-
}
|
|
444
|
+
return serializeUnexplodedObject(name, value, options);
|
|
411
445
|
}
|
|
446
|
+
const values = [];
|
|
412
447
|
for (const k in value) {
|
|
413
|
-
const
|
|
414
|
-
|
|
448
|
+
const key = encodeValue(k);
|
|
449
|
+
const finalName = options.style === "deepObject" ? `${name}[${key}]` : key;
|
|
450
|
+
if (value[k] != null) {
|
|
451
|
+
values.push(serializePrimitiveParam(finalName, value[k], options));
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
return values.length ? joinExploded(values, options.style) : "";
|
|
455
|
+
}
|
|
456
|
+
function serializeUnexplodedArray(name, value, options) {
|
|
457
|
+
const joiner = { form: ",", spaceDelimited: "%20", pipeDelimited: "|" }[options.style] || ",";
|
|
458
|
+
const final = value.map((v) => encodeValue(v, options.allowReserved)).join(joiner);
|
|
459
|
+
switch (options.style) {
|
|
460
|
+
case "simple": {
|
|
461
|
+
return final;
|
|
462
|
+
}
|
|
463
|
+
case "label": {
|
|
464
|
+
return `.${final}`;
|
|
465
|
+
}
|
|
466
|
+
case "matrix": {
|
|
467
|
+
return `;${name}=${final}`;
|
|
468
|
+
}
|
|
469
|
+
default: {
|
|
470
|
+
return `${name}=${final}`;
|
|
471
|
+
}
|
|
415
472
|
}
|
|
416
|
-
const final = values.join(joiner);
|
|
417
|
-
return options.style === "label" || options.style === "matrix" ? `${joiner}${final}` : final;
|
|
418
473
|
}
|
|
419
474
|
function serializeArrayParam(name, value, options) {
|
|
420
|
-
if (!Array.isArray(value)) {
|
|
475
|
+
if (!Array.isArray(value) || !value.length) {
|
|
421
476
|
return "";
|
|
422
477
|
}
|
|
423
478
|
if (options.explode === false) {
|
|
424
|
-
|
|
425
|
-
const final = (options.allowReserved === true ? value : value.map((v) => encodeURIComponent(v))).join(joiner2);
|
|
426
|
-
switch (options.style) {
|
|
427
|
-
case "simple": {
|
|
428
|
-
return final;
|
|
429
|
-
}
|
|
430
|
-
case "label": {
|
|
431
|
-
return `.${final}`;
|
|
432
|
-
}
|
|
433
|
-
case "matrix": {
|
|
434
|
-
return `;${name}=${final}`;
|
|
435
|
-
}
|
|
436
|
-
// case "spaceDelimited":
|
|
437
|
-
// case "pipeDelimited":
|
|
438
|
-
default: {
|
|
439
|
-
return `${name}=${final}`;
|
|
440
|
-
}
|
|
441
|
-
}
|
|
479
|
+
return serializeUnexplodedArray(name, value, options);
|
|
442
480
|
}
|
|
443
|
-
const joiner = { simple: ",", label: ".", matrix: ";" }[options.style] || "&";
|
|
444
481
|
const values = [];
|
|
445
482
|
for (const v of value) {
|
|
446
483
|
if (options.style === "simple" || options.style === "label") {
|
|
447
|
-
values.push(options.allowReserved
|
|
448
|
-
} else {
|
|
484
|
+
values.push(encodeValue(v, options.allowReserved));
|
|
485
|
+
} else if (v != null) {
|
|
449
486
|
values.push(serializePrimitiveParam(name, v, options));
|
|
450
487
|
}
|
|
451
488
|
}
|
|
452
|
-
return
|
|
489
|
+
return values.length ? joinExploded(values, options.style) : "";
|
|
490
|
+
}
|
|
491
|
+
function serializeQueryParam(name, value, options) {
|
|
492
|
+
const allowReserved = options?.allowReserved || false;
|
|
493
|
+
if (Array.isArray(value)) {
|
|
494
|
+
return serializeArrayParam(name, value, {
|
|
495
|
+
style: "form",
|
|
496
|
+
explode: true,
|
|
497
|
+
...options?.array,
|
|
498
|
+
allowReserved
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
if (value && typeof value === "object" && !isDate(value)) {
|
|
502
|
+
return serializeObjectParam(name, value, {
|
|
503
|
+
style: "deepObject",
|
|
504
|
+
explode: true,
|
|
505
|
+
...options?.object,
|
|
506
|
+
allowReserved
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
return serializePrimitiveParam(name, value, options);
|
|
453
510
|
}
|
|
454
511
|
function createQuerySerializer(options) {
|
|
455
512
|
return function querySerializer(queryParams) {
|
|
456
513
|
const search = [];
|
|
457
514
|
if (queryParams && typeof queryParams === "object") {
|
|
458
515
|
for (const key in queryParams) {
|
|
459
|
-
const
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
continue;
|
|
463
|
-
}
|
|
464
|
-
if (Array.isArray(value)) {
|
|
465
|
-
if (value.length === 0) {
|
|
466
|
-
continue;
|
|
467
|
-
}
|
|
468
|
-
search.push(
|
|
469
|
-
serializeArrayParam(name, value, {
|
|
470
|
-
style: "form",
|
|
471
|
-
explode: true,
|
|
472
|
-
...options?.array,
|
|
473
|
-
allowReserved: options?.allowReserved || false
|
|
474
|
-
})
|
|
475
|
-
);
|
|
476
|
-
continue;
|
|
477
|
-
}
|
|
478
|
-
if (typeof value === "object") {
|
|
479
|
-
search.push(
|
|
480
|
-
serializeObjectParam(name, value, {
|
|
481
|
-
style: "deepObject",
|
|
482
|
-
explode: true,
|
|
483
|
-
...options?.object,
|
|
484
|
-
allowReserved: options?.allowReserved || false
|
|
485
|
-
})
|
|
486
|
-
);
|
|
487
|
-
continue;
|
|
516
|
+
const part = serializeQueryParam(encodeName(key), queryParams[key], options);
|
|
517
|
+
if (part) {
|
|
518
|
+
search.push(part);
|
|
488
519
|
}
|
|
489
|
-
search.push(serializePrimitiveParam(name, value, options));
|
|
490
520
|
}
|
|
491
521
|
}
|
|
492
522
|
return search.join("&");
|
|
493
523
|
};
|
|
494
524
|
}
|
|
495
525
|
function defaultPathSerializer(pathname, pathParams) {
|
|
526
|
+
const matches = pathname.match(PATH_PARAM_RE);
|
|
527
|
+
if (!matches) {
|
|
528
|
+
return pathname;
|
|
529
|
+
}
|
|
496
530
|
let nextURL = pathname;
|
|
497
|
-
for (const match of
|
|
531
|
+
for (const match of matches) {
|
|
498
532
|
let name = match.substring(1, match.length - 1);
|
|
499
533
|
let explode = false;
|
|
500
534
|
let style = "simple";
|
|
@@ -516,26 +550,49 @@ function defaultPathSerializer(pathname, pathParams) {
|
|
|
516
550
|
let serialized;
|
|
517
551
|
if (Array.isArray(value)) {
|
|
518
552
|
serialized = serializeArrayParam(name, value, { style, explode });
|
|
519
|
-
} else if (typeof value === "object") {
|
|
553
|
+
} else if (typeof value === "object" && !isDate(value)) {
|
|
520
554
|
serialized = serializeObjectParam(name, value, { style, explode });
|
|
521
555
|
} else if (style === "matrix") {
|
|
522
556
|
serialized = `;${serializePrimitiveParam(name, value)}`;
|
|
523
557
|
} else {
|
|
524
|
-
serialized = style === "label" ? `.${
|
|
558
|
+
serialized = style === "label" ? `.${encodeValue(value)}` : encodeValue(value);
|
|
525
559
|
}
|
|
526
560
|
nextURL = nextURL.replace(match, () => serialized);
|
|
527
561
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
562
|
+
checkSerializedPath(pathname, nextURL);
|
|
563
|
+
return nextURL;
|
|
564
|
+
}
|
|
565
|
+
function checkSerializedPath(template, url) {
|
|
566
|
+
const fixed = template.slice(0, template.search(PATH_PARAM_RE));
|
|
567
|
+
const path = url.split(QUERY_OR_FRAGMENT_RE, 1)[0];
|
|
568
|
+
const first = fixed.split("/").length - 1;
|
|
569
|
+
let index = path.split("/").findIndex((segment, at) => at >= first && DOT_SEGMENT_RE.test(segment));
|
|
570
|
+
let problem = "Dot";
|
|
571
|
+
if (index === -1 && path.startsWith("//") && !fixed.startsWith("//")) {
|
|
572
|
+
[index, problem] = [1, "Empty first"];
|
|
531
573
|
}
|
|
532
|
-
if (
|
|
533
|
-
|
|
574
|
+
if (index !== -1) {
|
|
575
|
+
const name = template.split(QUERY_OR_FRAGMENT_RE, 1)[0].split("/")[index];
|
|
576
|
+
throw new Error(`${problem} path segment in "${name}"`);
|
|
534
577
|
}
|
|
535
|
-
|
|
578
|
+
}
|
|
579
|
+
function isPlatformInstance(value, name) {
|
|
580
|
+
const type = globalThis[name];
|
|
581
|
+
return typeof type === "function" && value instanceof type;
|
|
582
|
+
}
|
|
583
|
+
function isStreamBody(body) {
|
|
584
|
+
return isPlatformInstance(body, "ReadableStream") || typeof body?.[Symbol.asyncIterator] === "function";
|
|
536
585
|
}
|
|
537
586
|
function isRawBody(body) {
|
|
538
|
-
return
|
|
587
|
+
return ["FormData", "Blob", "URLSearchParams", "ArrayBuffer"].some(
|
|
588
|
+
(name) => isPlatformInstance(body, name)
|
|
589
|
+
) || ArrayBuffer.isView(body) || isStreamBody(body);
|
|
590
|
+
}
|
|
591
|
+
function isNestedFormValue(value) {
|
|
592
|
+
return value && typeof value === "object" && !isDate(value);
|
|
593
|
+
}
|
|
594
|
+
function formItems(value) {
|
|
595
|
+
return Array.isArray(value) ? Array.from(value) : [value];
|
|
539
596
|
}
|
|
540
597
|
function formBody(body) {
|
|
541
598
|
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
@@ -543,25 +600,27 @@ function formBody(body) {
|
|
|
543
600
|
}
|
|
544
601
|
const form = new URLSearchParams();
|
|
545
602
|
for (const [name, value] of Object.entries(body)) {
|
|
546
|
-
|
|
603
|
+
const items = formItems(value);
|
|
604
|
+
if (items.some(isNestedFormValue)) {
|
|
547
605
|
throw new Error(NESTED_FORM_VALUE_MESSAGE);
|
|
548
606
|
}
|
|
549
607
|
if (value != null) {
|
|
550
|
-
form.append(name,
|
|
608
|
+
form.append(name, items.map(valueText).join(","));
|
|
551
609
|
}
|
|
552
610
|
}
|
|
553
611
|
return form.toString();
|
|
554
612
|
}
|
|
555
613
|
function multipartBody(body) {
|
|
556
614
|
const formData = new FormData();
|
|
615
|
+
formData[CLIENT_BUILT_FORM] = true;
|
|
557
616
|
for (const [name, value] of Object.entries(body)) {
|
|
558
|
-
for (const item of
|
|
559
|
-
if (item
|
|
617
|
+
for (const item of formItems(value)) {
|
|
618
|
+
if (isPlatformInstance(item, "Blob")) {
|
|
560
619
|
formData.append(name, item);
|
|
561
|
-
} else if (item
|
|
620
|
+
} else if (isNestedFormValue(item)) {
|
|
562
621
|
throw new Error(NESTED_FORM_VALUE_MESSAGE);
|
|
563
622
|
} else if (item != null) {
|
|
564
|
-
formData.append(name, String(item));
|
|
623
|
+
formData.append(name, String(valueText(item)));
|
|
565
624
|
}
|
|
566
625
|
}
|
|
567
626
|
}
|