@orval/core 8.1.0 → 8.2.0
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/index.d.mts +83 -42
- package/dist/index.mjs +776 -762
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -388,6 +388,57 @@ function conventionName(name, convention) {
|
|
|
388
388
|
return nameConventionTransform(name);
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
+
//#endregion
|
|
392
|
+
//#region src/utils/content-type.ts
|
|
393
|
+
/**
|
|
394
|
+
* Determine if a content type is binary (vs text-based).
|
|
395
|
+
*/
|
|
396
|
+
function isBinaryContentType(contentType) {
|
|
397
|
+
if (contentType === "application/octet-stream") return true;
|
|
398
|
+
if (contentType.startsWith("image/")) return true;
|
|
399
|
+
if (contentType.startsWith("audio/")) return true;
|
|
400
|
+
if (contentType.startsWith("video/")) return true;
|
|
401
|
+
if (contentType.startsWith("font/")) return true;
|
|
402
|
+
if (contentType.startsWith("text/")) return false;
|
|
403
|
+
if ([
|
|
404
|
+
"+json",
|
|
405
|
+
"-json",
|
|
406
|
+
"+xml",
|
|
407
|
+
"-xml",
|
|
408
|
+
"+yaml",
|
|
409
|
+
"-yaml",
|
|
410
|
+
"+rss",
|
|
411
|
+
"-rss",
|
|
412
|
+
"+csv",
|
|
413
|
+
"-csv"
|
|
414
|
+
].some((suffix) => contentType.includes(suffix))) return false;
|
|
415
|
+
return !new Set([
|
|
416
|
+
"application/json",
|
|
417
|
+
"application/xml",
|
|
418
|
+
"application/yaml",
|
|
419
|
+
"application/x-www-form-urlencoded",
|
|
420
|
+
"application/javascript",
|
|
421
|
+
"application/ecmascript",
|
|
422
|
+
"application/graphql"
|
|
423
|
+
]).has(contentType);
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Determine if a form-data field should be treated as a file (binary or text).
|
|
427
|
+
*
|
|
428
|
+
* Precedence (per OAS 3.1): encoding.contentType > schema.contentMediaType
|
|
429
|
+
*
|
|
430
|
+
* Returns:
|
|
431
|
+
* - 'binary': binary file (Blob)
|
|
432
|
+
* - 'text': text file (Blob | string)
|
|
433
|
+
* - undefined: not a file, use standard string resolution
|
|
434
|
+
*/
|
|
435
|
+
function getFormDataFieldFileType(resolvedSchema, partContentType) {
|
|
436
|
+
if (resolvedSchema.type !== "string") return;
|
|
437
|
+
if (resolvedSchema.contentEncoding) return;
|
|
438
|
+
const effectiveContentType = partContentType ?? resolvedSchema.contentMediaType;
|
|
439
|
+
if (effectiveContentType) return isBinaryContentType(effectiveContentType) ? "binary" : "text";
|
|
440
|
+
}
|
|
441
|
+
|
|
391
442
|
//#endregion
|
|
392
443
|
//#region src/utils/compare-version.ts
|
|
393
444
|
function compareVersions(firstVersion, secondVersions, operator = ">=") {
|
|
@@ -797,11 +848,13 @@ function escape(str, char = "'") {
|
|
|
797
848
|
* @param input String to escape
|
|
798
849
|
*/
|
|
799
850
|
function jsStringEscape(input) {
|
|
800
|
-
return input.replaceAll(/["'\\\n\r\u2028\u2029]/g, (character) => {
|
|
851
|
+
return input.replaceAll(/["'\\\n\r\u2028\u2029/*]/g, (character) => {
|
|
801
852
|
switch (character) {
|
|
802
853
|
case "\"":
|
|
803
854
|
case "'":
|
|
804
|
-
case "\\":
|
|
855
|
+
case "\\":
|
|
856
|
+
case "/":
|
|
857
|
+
case "*": return "\\" + character;
|
|
805
858
|
case "\n": return String.raw`\n`;
|
|
806
859
|
case "\r": return String.raw`\r`;
|
|
807
860
|
case "\u2028": return String.raw`\u2028`;
|
|
@@ -813,9 +866,32 @@ function jsStringEscape(input) {
|
|
|
813
866
|
/**
|
|
814
867
|
* Deduplicates a TypeScript union type string.
|
|
815
868
|
* Handles types like "A | B | B" → "A | B" and "null | null" → "null".
|
|
869
|
+
* Only splits on top-level | (not inside {} () [] <> or string literals).
|
|
816
870
|
*/
|
|
817
871
|
function dedupeUnionType(unionType) {
|
|
818
|
-
const parts =
|
|
872
|
+
const parts = [];
|
|
873
|
+
let current = "";
|
|
874
|
+
let depth = 0;
|
|
875
|
+
let quote = "";
|
|
876
|
+
let escaped = false;
|
|
877
|
+
for (const c of unionType) {
|
|
878
|
+
if (!escaped && (c === "'" || c === "\"")) {
|
|
879
|
+
if (!quote) quote = c;
|
|
880
|
+
else if (quote === c) quote = "";
|
|
881
|
+
}
|
|
882
|
+
if (!quote) {
|
|
883
|
+
if ("{([<".includes(c)) depth++;
|
|
884
|
+
if ("})]>".includes(c)) depth--;
|
|
885
|
+
if (c === "|" && depth === 0) {
|
|
886
|
+
parts.push(current.trim());
|
|
887
|
+
current = "";
|
|
888
|
+
continue;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
current += c;
|
|
892
|
+
escaped = !!quote && !escaped && c === "\\";
|
|
893
|
+
}
|
|
894
|
+
if (current.trim()) parts.push(current.trim());
|
|
819
895
|
return [...new Set(parts)].join(" | ");
|
|
820
896
|
}
|
|
821
897
|
|
|
@@ -1060,6 +1136,10 @@ function getSchema$1(schema, context) {
|
|
|
1060
1136
|
...currentSchema,
|
|
1061
1137
|
nullable: schema.nullable
|
|
1062
1138
|
};
|
|
1139
|
+
if ("type" in schema && Array.isArray(schema.type)) currentSchema = {
|
|
1140
|
+
...currentSchema,
|
|
1141
|
+
type: schema.type
|
|
1142
|
+
};
|
|
1063
1143
|
return {
|
|
1064
1144
|
currentSchema,
|
|
1065
1145
|
refInfo
|
|
@@ -1085,7 +1165,7 @@ function resolveExampleRefs(examples, context) {
|
|
|
1085
1165
|
|
|
1086
1166
|
//#endregion
|
|
1087
1167
|
//#region src/resolvers/value.ts
|
|
1088
|
-
function resolveValue({ schema, name, context }) {
|
|
1168
|
+
function resolveValue({ schema, name, context, formDataContext }) {
|
|
1089
1169
|
if (isReference(schema)) {
|
|
1090
1170
|
const { schema: schemaObject, imports } = resolveRef(schema, context);
|
|
1091
1171
|
const resolvedImport = imports[0];
|
|
@@ -1119,7 +1199,8 @@ function resolveValue({ schema, name, context }) {
|
|
|
1119
1199
|
...getScalar({
|
|
1120
1200
|
item: schema,
|
|
1121
1201
|
name,
|
|
1122
|
-
context
|
|
1202
|
+
context,
|
|
1203
|
+
formDataContext
|
|
1123
1204
|
}),
|
|
1124
1205
|
originalSchema: schema,
|
|
1125
1206
|
isRef: false
|
|
@@ -1161,11 +1242,12 @@ function createTypeAliasIfNeeded({ resolvedValue, propName, context }) {
|
|
|
1161
1242
|
dependencies: resolvedValue.dependencies
|
|
1162
1243
|
};
|
|
1163
1244
|
}
|
|
1164
|
-
function resolveObjectOriginal({ schema, propName, combined = false, context }) {
|
|
1245
|
+
function resolveObjectOriginal({ schema, propName, combined = false, context, formDataContext }) {
|
|
1165
1246
|
const resolvedValue = resolveValue({
|
|
1166
1247
|
schema,
|
|
1167
1248
|
name: propName,
|
|
1168
|
-
context
|
|
1249
|
+
context,
|
|
1250
|
+
formDataContext
|
|
1169
1251
|
});
|
|
1170
1252
|
const aliased = createTypeAliasIfNeeded({
|
|
1171
1253
|
resolvedValue,
|
|
@@ -1199,19 +1281,21 @@ function resolveObjectOriginal({ schema, propName, combined = false, context })
|
|
|
1199
1281
|
return resolvedValue;
|
|
1200
1282
|
}
|
|
1201
1283
|
const resolveObjectCacheMap = /* @__PURE__ */ new Map();
|
|
1202
|
-
function resolveObject({ schema, propName, combined = false, context }) {
|
|
1284
|
+
function resolveObject({ schema, propName, combined = false, context, formDataContext }) {
|
|
1203
1285
|
const hashKey = JSON.stringify({
|
|
1204
1286
|
schema,
|
|
1205
1287
|
propName,
|
|
1206
1288
|
combined,
|
|
1207
|
-
projectName: context.projectName ?? context.output.target
|
|
1289
|
+
projectName: context.projectName ?? context.output.target,
|
|
1290
|
+
formDataContext
|
|
1208
1291
|
});
|
|
1209
1292
|
if (resolveObjectCacheMap.has(hashKey)) return resolveObjectCacheMap.get(hashKey);
|
|
1210
1293
|
const result = resolveObjectOriginal({
|
|
1211
1294
|
schema,
|
|
1212
1295
|
propName,
|
|
1213
1296
|
combined,
|
|
1214
|
-
context
|
|
1297
|
+
context,
|
|
1298
|
+
formDataContext
|
|
1215
1299
|
});
|
|
1216
1300
|
resolveObjectCacheMap.set(hashKey, result);
|
|
1217
1301
|
return result;
|
|
@@ -1224,18 +1308,19 @@ function resolveObject({ schema, propName, combined = false, context }) {
|
|
|
1224
1308
|
*
|
|
1225
1309
|
* @param item item with type === "array"
|
|
1226
1310
|
*/
|
|
1227
|
-
function getArray({ schema, name, context }) {
|
|
1311
|
+
function getArray({ schema, name, context, formDataContext }) {
|
|
1228
1312
|
const schema31 = schema;
|
|
1313
|
+
const itemSuffix = context.output.override.components.schemas.itemSuffix;
|
|
1229
1314
|
if (schema31.prefixItems) {
|
|
1230
1315
|
const resolvedObjects = schema31.prefixItems.map((item, index) => resolveObject({
|
|
1231
1316
|
schema: item,
|
|
1232
|
-
propName: name +
|
|
1317
|
+
propName: name ? name + itemSuffix + index : void 0,
|
|
1233
1318
|
context
|
|
1234
1319
|
}));
|
|
1235
1320
|
if (schema31.items) {
|
|
1236
1321
|
const additional = resolveObject({
|
|
1237
1322
|
schema: schema31.items,
|
|
1238
|
-
propName: name +
|
|
1323
|
+
propName: name ? name + itemSuffix + "Additional" : void 0,
|
|
1239
1324
|
context
|
|
1240
1325
|
});
|
|
1241
1326
|
resolvedObjects.push({
|
|
@@ -1259,8 +1344,9 @@ function getArray({ schema, name, context }) {
|
|
|
1259
1344
|
if (schema.items) {
|
|
1260
1345
|
const resolvedObject = resolveObject({
|
|
1261
1346
|
schema: schema.items,
|
|
1262
|
-
propName: name +
|
|
1263
|
-
context
|
|
1347
|
+
propName: name ? name + itemSuffix : void 0,
|
|
1348
|
+
context,
|
|
1349
|
+
formDataContext
|
|
1264
1350
|
});
|
|
1265
1351
|
return {
|
|
1266
1352
|
value: `${schema.readOnly === true && !context.output.override.suppressReadonlyModifier ? "readonly " : ""}${resolvedObject.value.includes("|") ? `(${resolvedObject.value})[]` : `${resolvedObject.value}[]`}`,
|
|
@@ -1288,321 +1374,424 @@ function getArray({ schema, name, context }) {
|
|
|
1288
1374
|
}
|
|
1289
1375
|
|
|
1290
1376
|
//#endregion
|
|
1291
|
-
//#region src/getters/
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1377
|
+
//#region src/getters/res-req-types.ts
|
|
1378
|
+
const formDataContentTypes = new Set(["multipart/form-data"]);
|
|
1379
|
+
const formUrlEncodedContentTypes = new Set(["application/x-www-form-urlencoded"]);
|
|
1380
|
+
function getResReqContentTypes({ mediaType, propName, context, isFormData, contentType }) {
|
|
1381
|
+
if (!mediaType.schema) return;
|
|
1382
|
+
const formDataContext = isFormData ? {
|
|
1383
|
+
atPart: false,
|
|
1384
|
+
encoding: mediaType.encoding ?? {}
|
|
1385
|
+
} : void 0;
|
|
1386
|
+
const resolvedObject = resolveObject({
|
|
1387
|
+
schema: mediaType.schema,
|
|
1388
|
+
propName,
|
|
1389
|
+
context,
|
|
1390
|
+
formDataContext
|
|
1391
|
+
});
|
|
1392
|
+
if (!isFormData && isBinaryContentType(contentType)) return {
|
|
1393
|
+
...resolvedObject,
|
|
1394
|
+
value: "Blob"
|
|
1395
|
+
};
|
|
1396
|
+
return resolvedObject;
|
|
1310
1397
|
}
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
if (!itemType && item.items) {
|
|
1325
|
-
item.type = "array";
|
|
1326
|
-
itemType = "array";
|
|
1327
|
-
}
|
|
1328
|
-
if (isArray(item.type) && item.type.includes("null")) {
|
|
1329
|
-
const typesWithoutNull = item.type.filter((x) => x !== "null");
|
|
1330
|
-
itemType = typesWithoutNull.length === 1 ? typesWithoutNull[0] : typesWithoutNull;
|
|
1331
|
-
}
|
|
1332
|
-
switch (itemType) {
|
|
1333
|
-
case "number":
|
|
1334
|
-
case "integer": {
|
|
1335
|
-
let value = context.output.override.useBigInt && (item.format === "int64" || item.format === "uint64") ? "bigint" : "number";
|
|
1336
|
-
let isEnum = false;
|
|
1337
|
-
if (enumItems) {
|
|
1338
|
-
value = enumItems.map((enumItem) => `${enumItem}`).join(" | ");
|
|
1339
|
-
isEnum = true;
|
|
1340
|
-
}
|
|
1341
|
-
value += nullable;
|
|
1342
|
-
const itemWithConst = item;
|
|
1343
|
-
if (itemWithConst.const !== void 0) value = itemWithConst.const;
|
|
1344
|
-
return {
|
|
1345
|
-
value,
|
|
1346
|
-
isEnum,
|
|
1347
|
-
type: "number",
|
|
1398
|
+
function getResReqTypes(responsesOrRequests, name, context, defaultType = "unknown", uniqueKey = (item) => item.value) {
|
|
1399
|
+
return uniqueBy(responsesOrRequests.filter(([_, res]) => Boolean(res)).map(([key, res]) => {
|
|
1400
|
+
if (isReference(res)) {
|
|
1401
|
+
const { schema: bodySchema, imports: [{ name: name$1, schemaName }] } = resolveRef(res, context);
|
|
1402
|
+
const [contentType, mediaType] = Object.entries(bodySchema.content ?? {})[0] ?? [];
|
|
1403
|
+
const isFormData = formDataContentTypes.has(contentType);
|
|
1404
|
+
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
1405
|
+
if (!isFormData && !isFormUrlEncoded || !mediaType.schema) return [{
|
|
1406
|
+
value: name$1,
|
|
1407
|
+
imports: [{
|
|
1408
|
+
name: name$1,
|
|
1409
|
+
schemaName
|
|
1410
|
+
}],
|
|
1348
1411
|
schemas: [],
|
|
1349
|
-
|
|
1350
|
-
isRef: false,
|
|
1351
|
-
hasReadonlyProps: item.readOnly || false,
|
|
1352
|
-
dependencies: [],
|
|
1353
|
-
example: item.example,
|
|
1354
|
-
examples: resolveExampleRefs(item.examples, context)
|
|
1355
|
-
};
|
|
1356
|
-
}
|
|
1357
|
-
case "boolean": {
|
|
1358
|
-
let value = "boolean" + nullable;
|
|
1359
|
-
const itemWithConst = item;
|
|
1360
|
-
if (itemWithConst.const !== void 0) value = itemWithConst.const;
|
|
1361
|
-
return {
|
|
1362
|
-
value,
|
|
1363
|
-
type: "boolean",
|
|
1412
|
+
type: "unknown",
|
|
1364
1413
|
isEnum: false,
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
};
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1414
|
+
isRef: true,
|
|
1415
|
+
hasReadonlyProps: false,
|
|
1416
|
+
originalSchema: mediaType?.schema,
|
|
1417
|
+
example: mediaType?.example,
|
|
1418
|
+
examples: resolveExampleRefs(mediaType?.examples, context),
|
|
1419
|
+
key,
|
|
1420
|
+
contentType
|
|
1421
|
+
}];
|
|
1422
|
+
const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
|
|
1423
|
+
name: name$1,
|
|
1424
|
+
schemaObject: mediaType.schema,
|
|
1425
|
+
context,
|
|
1426
|
+
isRequestBodyOptional: "required" in bodySchema && bodySchema.required === false,
|
|
1427
|
+
isRef: true,
|
|
1428
|
+
encoding: mediaType.encoding
|
|
1429
|
+
}) : void 0;
|
|
1430
|
+
const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
|
|
1431
|
+
name: name$1,
|
|
1432
|
+
schemaObject: mediaType.schema,
|
|
1433
|
+
context,
|
|
1434
|
+
isRequestBodyOptional: "required" in bodySchema && bodySchema.required === false,
|
|
1435
|
+
isUrlEncoded: true,
|
|
1436
|
+
isRef: true,
|
|
1437
|
+
encoding: mediaType.encoding
|
|
1438
|
+
}) : void 0;
|
|
1439
|
+
const additionalImports = getFormDataAdditionalImports({
|
|
1440
|
+
schemaObject: mediaType.schema,
|
|
1378
1441
|
context
|
|
1379
1442
|
});
|
|
1380
|
-
return {
|
|
1381
|
-
value:
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
case "string": {
|
|
1387
|
-
let value = "string";
|
|
1388
|
-
let isEnum = false;
|
|
1389
|
-
if (enumItems) {
|
|
1390
|
-
value = enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
|
|
1391
|
-
isEnum = true;
|
|
1392
|
-
}
|
|
1393
|
-
if (item.format === "binary") value = "Blob";
|
|
1394
|
-
if (context.output.override.useDates && (item.format === "date" || item.format === "date-time")) value = "Date";
|
|
1395
|
-
value += nullable;
|
|
1396
|
-
const itemWithConst = item;
|
|
1397
|
-
if (itemWithConst.const) value = `'${itemWithConst.const}'`;
|
|
1398
|
-
return {
|
|
1399
|
-
value,
|
|
1400
|
-
isEnum,
|
|
1401
|
-
type: "string",
|
|
1402
|
-
imports: [],
|
|
1443
|
+
return [{
|
|
1444
|
+
value: name$1,
|
|
1445
|
+
imports: [{
|
|
1446
|
+
name: name$1,
|
|
1447
|
+
schemaName
|
|
1448
|
+
}, ...additionalImports],
|
|
1403
1449
|
schemas: [],
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1450
|
+
type: "unknown",
|
|
1451
|
+
isEnum: false,
|
|
1452
|
+
hasReadonlyProps: false,
|
|
1453
|
+
formData,
|
|
1454
|
+
formUrlEncoded,
|
|
1455
|
+
isRef: true,
|
|
1456
|
+
originalSchema: mediaType.schema,
|
|
1457
|
+
example: mediaType.example,
|
|
1458
|
+
examples: resolveExampleRefs(mediaType.examples, context),
|
|
1459
|
+
key,
|
|
1460
|
+
contentType
|
|
1461
|
+
}];
|
|
1410
1462
|
}
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
if (isArray(itemType)) return combineSchemas({
|
|
1424
|
-
schema: { anyOf: itemType.map((type) => ({
|
|
1425
|
-
...item,
|
|
1426
|
-
type
|
|
1427
|
-
})) },
|
|
1428
|
-
name,
|
|
1429
|
-
separator: "anyOf",
|
|
1463
|
+
if (res.content) return Object.entries(res.content).map(([contentType, mediaType], index, arr) => {
|
|
1464
|
+
let propName = key ? pascal(name) + pascal(key) : void 0;
|
|
1465
|
+
if (propName && arr.length > 1) propName = propName + pascal(getNumberWord(index + 1));
|
|
1466
|
+
let effectivePropName = propName;
|
|
1467
|
+
if (mediaType.schema && isReference(mediaType.schema)) {
|
|
1468
|
+
const { imports } = resolveRef(mediaType.schema, context);
|
|
1469
|
+
if (imports[0]?.name) effectivePropName = imports[0].name;
|
|
1470
|
+
}
|
|
1471
|
+
const isFormData = formDataContentTypes.has(contentType);
|
|
1472
|
+
const resolvedValue = getResReqContentTypes({
|
|
1473
|
+
mediaType,
|
|
1474
|
+
propName: effectivePropName,
|
|
1430
1475
|
context,
|
|
1431
|
-
|
|
1476
|
+
isFormData,
|
|
1477
|
+
contentType
|
|
1432
1478
|
});
|
|
1433
|
-
if (
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1479
|
+
if (!resolvedValue) {
|
|
1480
|
+
if (isBinaryContentType(contentType)) return {
|
|
1481
|
+
value: "Blob",
|
|
1482
|
+
imports: [],
|
|
1483
|
+
schemas: [],
|
|
1484
|
+
type: "Blob",
|
|
1485
|
+
isEnum: false,
|
|
1486
|
+
key,
|
|
1487
|
+
isRef: false,
|
|
1488
|
+
hasReadonlyProps: false,
|
|
1489
|
+
contentType
|
|
1490
|
+
};
|
|
1491
|
+
return;
|
|
1492
|
+
}
|
|
1493
|
+
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
1494
|
+
if (!isFormData && !isFormUrlEncoded || !effectivePropName) return {
|
|
1495
|
+
...resolvedValue,
|
|
1496
|
+
imports: resolvedValue.imports,
|
|
1497
|
+
contentType,
|
|
1498
|
+
example: mediaType.example,
|
|
1499
|
+
examples: resolveExampleRefs(mediaType.examples, context)
|
|
1444
1500
|
};
|
|
1445
|
-
const
|
|
1446
|
-
|
|
1447
|
-
|
|
1501
|
+
const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
|
|
1502
|
+
name: effectivePropName,
|
|
1503
|
+
schemaObject: mediaType.schema,
|
|
1448
1504
|
context,
|
|
1449
|
-
|
|
1505
|
+
isRequestBodyOptional: "required" in res && res.required === false,
|
|
1506
|
+
isRef: true,
|
|
1507
|
+
encoding: mediaType.encoding
|
|
1508
|
+
}) : void 0;
|
|
1509
|
+
const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
|
|
1510
|
+
name: effectivePropName,
|
|
1511
|
+
schemaObject: mediaType.schema,
|
|
1512
|
+
context,
|
|
1513
|
+
isUrlEncoded: true,
|
|
1514
|
+
isRequestBodyOptional: "required" in res && res.required === false,
|
|
1515
|
+
isRef: true,
|
|
1516
|
+
encoding: mediaType.encoding
|
|
1517
|
+
}) : void 0;
|
|
1518
|
+
const additionalImports = getFormDataAdditionalImports({
|
|
1519
|
+
schemaObject: mediaType.schema,
|
|
1520
|
+
context
|
|
1450
1521
|
});
|
|
1451
1522
|
return {
|
|
1452
|
-
|
|
1453
|
-
...
|
|
1523
|
+
...resolvedValue,
|
|
1524
|
+
imports: [...resolvedValue.imports, ...additionalImports],
|
|
1525
|
+
formData,
|
|
1526
|
+
formUrlEncoded,
|
|
1527
|
+
contentType,
|
|
1528
|
+
example: mediaType.example,
|
|
1529
|
+
examples: resolveExampleRefs(mediaType.examples, context)
|
|
1454
1530
|
};
|
|
1455
|
-
}
|
|
1456
|
-
|
|
1531
|
+
}).filter(Boolean).map((x) => ({
|
|
1532
|
+
...x,
|
|
1533
|
+
key
|
|
1534
|
+
}));
|
|
1535
|
+
const swaggerSchema = "schema" in res ? res.schema : void 0;
|
|
1536
|
+
if (swaggerSchema) return [{
|
|
1537
|
+
...resolveObject({
|
|
1538
|
+
schema: swaggerSchema,
|
|
1539
|
+
propName: key ? pascal(name) + pascal(key) : void 0,
|
|
1540
|
+
context
|
|
1541
|
+
}),
|
|
1542
|
+
contentType: "application/json",
|
|
1543
|
+
key
|
|
1544
|
+
}];
|
|
1545
|
+
return [{
|
|
1546
|
+
value: defaultType,
|
|
1547
|
+
imports: [],
|
|
1548
|
+
schemas: [],
|
|
1549
|
+
type: defaultType,
|
|
1550
|
+
isEnum: false,
|
|
1551
|
+
key,
|
|
1552
|
+
isRef: false,
|
|
1553
|
+
hasReadonlyProps: false,
|
|
1554
|
+
contentType: "application/json"
|
|
1555
|
+
}];
|
|
1556
|
+
}).flat(), uniqueKey);
|
|
1457
1557
|
}
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1558
|
+
/**
|
|
1559
|
+
* Determine the response type category for a given content type.
|
|
1560
|
+
* Used to set the correct responseType option in HTTP clients.
|
|
1561
|
+
*
|
|
1562
|
+
* @param contentType - The MIME content type (e.g., 'application/json', 'text/plain')
|
|
1563
|
+
* @returns The response type category to use for parsing
|
|
1564
|
+
*/
|
|
1565
|
+
function getResponseTypeCategory(contentType) {
|
|
1566
|
+
if (isBinaryContentType(contentType)) return "blob";
|
|
1567
|
+
if (contentType === "application/json" || contentType.includes("+json") || contentType.includes("-json")) return "json";
|
|
1568
|
+
return "text";
|
|
1569
|
+
}
|
|
1570
|
+
/**
|
|
1571
|
+
* Get the default content type from a list of content types.
|
|
1572
|
+
* Priority: application/json > any JSON-like type > first in list
|
|
1573
|
+
*
|
|
1574
|
+
* @param contentTypes - Array of content types from OpenAPI spec
|
|
1575
|
+
* @returns The default content type to use
|
|
1576
|
+
*/
|
|
1577
|
+
function getDefaultContentType(contentTypes) {
|
|
1578
|
+
if (contentTypes.length === 0) return "application/json";
|
|
1579
|
+
if (contentTypes.includes("application/json")) return "application/json";
|
|
1580
|
+
const jsonType = contentTypes.find((ct) => ct.includes("+json") || ct.includes("-json"));
|
|
1581
|
+
if (jsonType) return jsonType;
|
|
1582
|
+
return contentTypes[0];
|
|
1583
|
+
}
|
|
1584
|
+
function getFormDataAdditionalImports({ schemaObject, context }) {
|
|
1585
|
+
const { schema } = resolveRef(schemaObject, context);
|
|
1586
|
+
if (schema.type !== "object") return [];
|
|
1587
|
+
const combinedSchemas = schema.oneOf || schema.anyOf;
|
|
1588
|
+
if (!combinedSchemas) return [];
|
|
1589
|
+
return combinedSchemas.map((schema$1) => resolveRef(schema$1, context).imports[0]).filter(Boolean);
|
|
1590
|
+
}
|
|
1591
|
+
function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequestBodyOptional, isUrlEncoded, isRef, encoding }) {
|
|
1592
|
+
const { schema, imports } = resolveRef(schemaObject, context);
|
|
1593
|
+
const propName = camel(!isRef && isReference(schemaObject) ? imports[0].name : name);
|
|
1594
|
+
const additionalImports = [];
|
|
1595
|
+
const variableName = isUrlEncoded ? "formUrlEncoded" : "formData";
|
|
1596
|
+
let form = isUrlEncoded ? `const ${variableName} = new URLSearchParams();\n` : `const ${variableName} = new FormData();\n`;
|
|
1597
|
+
const combinedSchemas = schema.oneOf || schema.anyOf || schema.allOf;
|
|
1598
|
+
if (schema.type === "object" || schema.type === void 0 && combinedSchemas) {
|
|
1599
|
+
if (combinedSchemas) {
|
|
1600
|
+
const shouldCast = !!schema.oneOf || !!schema.anyOf;
|
|
1601
|
+
const combinedSchemasFormData = combinedSchemas.map((schema$1) => {
|
|
1602
|
+
const { schema: combinedSchema, imports: imports$1 } = resolveRef(schema$1, context);
|
|
1603
|
+
let newPropName = propName;
|
|
1604
|
+
let newPropDefinition = "";
|
|
1605
|
+
if (shouldCast && imports$1[0]) {
|
|
1606
|
+
additionalImports.push(imports$1[0]);
|
|
1607
|
+
newPropName = `${propName}${pascal(imports$1[0].name)}`;
|
|
1608
|
+
newPropDefinition = `const ${newPropName} = (${propName} as ${imports$1[0].name}${isRequestBodyOptional ? " | undefined" : ""});\n`;
|
|
1609
|
+
}
|
|
1610
|
+
return newPropDefinition + resolveSchemaPropertiesToFormData({
|
|
1611
|
+
schema: combinedSchema,
|
|
1612
|
+
variableName,
|
|
1613
|
+
propName: newPropName,
|
|
1614
|
+
context,
|
|
1615
|
+
isRequestBodyOptional,
|
|
1616
|
+
encoding
|
|
1617
|
+
});
|
|
1618
|
+
}).filter(Boolean).join("\n");
|
|
1619
|
+
form += combinedSchemasFormData;
|
|
1468
1620
|
}
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1621
|
+
if (schema.properties) {
|
|
1622
|
+
const formDataValues = resolveSchemaPropertiesToFormData({
|
|
1623
|
+
schema,
|
|
1624
|
+
variableName,
|
|
1625
|
+
propName,
|
|
1626
|
+
context,
|
|
1627
|
+
isRequestBodyOptional,
|
|
1628
|
+
encoding
|
|
1629
|
+
});
|
|
1630
|
+
form += formDataValues;
|
|
1631
|
+
}
|
|
1632
|
+
return form;
|
|
1474
1633
|
}
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
if (
|
|
1481
|
-
values.push(resolvedData.values[i]);
|
|
1482
|
-
continue;
|
|
1483
|
-
}
|
|
1484
|
-
const missingProperties = unique(resolvedData.allProperties.filter((p) => !Object.keys(subSchema.properties).includes(p)));
|
|
1485
|
-
values.push(`${resolvedData.values[i]}${missingProperties.length > 0 ? ` & {${missingProperties.map((p) => `${p}?: never`).join("; ")}}` : ""}`);
|
|
1634
|
+
if (schema.type === "array") {
|
|
1635
|
+
let valueStr = "value";
|
|
1636
|
+
if (schema.items) {
|
|
1637
|
+
const { schema: itemSchema } = resolveRef(schema.items, context);
|
|
1638
|
+
if (itemSchema.type === "object" || itemSchema.type === "array") valueStr = "JSON.stringify(value)";
|
|
1639
|
+
else if (itemSchema.type === "number" || itemSchema.type === "integer" || itemSchema.type === "boolean") valueStr = "value.toString()";
|
|
1486
1640
|
}
|
|
1641
|
+
return `${form}${propName}.forEach(value => ${variableName}.append('data', ${valueStr}))\n`;
|
|
1487
1642
|
}
|
|
1488
|
-
if (
|
|
1489
|
-
return
|
|
1643
|
+
if (schema.type === "number" || schema.type === "integer" || schema.type === "boolean") return `${form}${variableName}.append('data', ${propName}.toString())\n`;
|
|
1644
|
+
return `${form}${variableName}.append('data', ${propName})\n`;
|
|
1490
1645
|
}
|
|
1491
|
-
function
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
}
|
|
1499
|
-
|
|
1500
|
-
const
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1646
|
+
function resolveSchemaPropertiesToFormData({ schema, variableName, propName, context, isRequestBodyOptional, keyPrefix = "", depth = 0, encoding }) {
|
|
1647
|
+
return Object.entries(schema.properties ?? {}).reduce((acc, [key, value]) => {
|
|
1648
|
+
const { schema: property } = resolveRef(value, context);
|
|
1649
|
+
if (property.readOnly) return acc;
|
|
1650
|
+
let formDataValue = "";
|
|
1651
|
+
const partContentType = (depth === 0 ? encoding?.[key] : void 0)?.contentType;
|
|
1652
|
+
const formattedKeyPrefix = isRequestBodyOptional ? keyword.isIdentifierNameES5(key) ? "?" : "?." : "";
|
|
1653
|
+
const formattedKey = keyword.isIdentifierNameES5(key) ? `.${key}` : `['${key}']`;
|
|
1654
|
+
const valueKey = `${propName}${formattedKeyPrefix}${formattedKey}`;
|
|
1655
|
+
const nonOptionalValueKey = `${propName}${formattedKey}`;
|
|
1656
|
+
const fileType = getFormDataFieldFileType(property, partContentType);
|
|
1657
|
+
const effectiveContentType = partContentType ?? property.contentMediaType;
|
|
1658
|
+
if (fileType === "binary" || property.format === "binary") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
1659
|
+
else if (fileType === "text") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey} instanceof Blob ? ${nonOptionalValueKey} : new Blob([${nonOptionalValueKey}], { type: '${effectiveContentType}' }));\n`;
|
|
1660
|
+
else if (property.type === "object") formDataValue = context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE ? resolveSchemaPropertiesToFormData({
|
|
1661
|
+
schema: property,
|
|
1662
|
+
variableName,
|
|
1663
|
+
propName: nonOptionalValueKey,
|
|
1507
1664
|
context,
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1665
|
+
isRequestBodyOptional,
|
|
1666
|
+
keyPrefix: `${keyPrefix}${key}.`,
|
|
1667
|
+
depth: depth + 1,
|
|
1668
|
+
encoding
|
|
1669
|
+
}) : partContentType ? `${variableName}.append(\`${keyPrefix}${key}\`, new Blob([JSON.stringify(${nonOptionalValueKey})], { type: '${partContentType}' }));\n` : `${variableName}.append(\`${keyPrefix}${key}\`, JSON.stringify(${nonOptionalValueKey}));\n`;
|
|
1670
|
+
else if (property.type === "array") {
|
|
1671
|
+
let valueStr = "value";
|
|
1672
|
+
let hasNonPrimitiveChild = false;
|
|
1673
|
+
if (property.items) {
|
|
1674
|
+
const { schema: itemSchema } = resolveRef(property.items, context);
|
|
1675
|
+
if (itemSchema.type === "object" || itemSchema.type === "array") if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
|
|
1676
|
+
hasNonPrimitiveChild = true;
|
|
1677
|
+
const resolvedValue = resolveSchemaPropertiesToFormData({
|
|
1678
|
+
schema: itemSchema,
|
|
1679
|
+
variableName,
|
|
1680
|
+
propName: "value",
|
|
1681
|
+
context,
|
|
1682
|
+
isRequestBodyOptional,
|
|
1683
|
+
keyPrefix: `${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}].`,
|
|
1684
|
+
depth: depth + 1
|
|
1685
|
+
});
|
|
1686
|
+
formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => {
|
|
1687
|
+
${resolvedValue}});\n`;
|
|
1688
|
+
} else valueStr = "JSON.stringify(value)";
|
|
1689
|
+
else if (itemSchema.type === "number" || itemSchema.type?.includes("number") || itemSchema.type === "integer" || itemSchema.type?.includes("integer") || itemSchema.type === "boolean" || itemSchema.type?.includes("boolean")) valueStr = "value.toString()";
|
|
1690
|
+
}
|
|
1691
|
+
if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
|
|
1692
|
+
if (!hasNonPrimitiveChild) formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => ${variableName}.append(\`${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}]\`, ${valueStr}));\n`;
|
|
1693
|
+
} else formDataValue = `${valueKey}.forEach(value => ${variableName}.append(\`${keyPrefix}${key}${context.output.override.formData.arrayHandling === FormDataArrayHandling.SERIALIZE_WITH_BRACKETS ? "[]" : ""}\`, ${valueStr}));\n`;
|
|
1694
|
+
} else if (property.type === "number" || property.type?.includes("number") || property.type === "integer" || property.type?.includes("integer") || property.type === "boolean" || property.type?.includes("boolean")) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
1695
|
+
else formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
1696
|
+
let existSubSchemaNullable = false;
|
|
1697
|
+
if (property.allOf || property.anyOf || property.oneOf) {
|
|
1698
|
+
const subSchemas = (property.allOf || property.anyOf || property.oneOf)?.map((c) => resolveObject({
|
|
1699
|
+
schema: c,
|
|
1700
|
+
combined: true,
|
|
1701
|
+
context
|
|
1702
|
+
}));
|
|
1703
|
+
if (subSchemas?.some((subSchema) => {
|
|
1704
|
+
return [
|
|
1705
|
+
"number",
|
|
1706
|
+
"integer",
|
|
1707
|
+
"boolean"
|
|
1708
|
+
].includes(subSchema.type);
|
|
1709
|
+
})) formDataValue = `${variableName}.append(\`${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
1710
|
+
if (subSchemas?.some((subSchema) => {
|
|
1711
|
+
return subSchema.type === "null";
|
|
1712
|
+
})) existSubSchemaNullable = true;
|
|
1713
|
+
}
|
|
1714
|
+
const isRequired = schema.required?.includes(key) && !isRequestBodyOptional;
|
|
1715
|
+
if (property.nullable || property.type?.includes("null") || existSubSchemaNullable) {
|
|
1716
|
+
if (isRequired) return acc + `if(${valueKey} !== null) {\n ${formDataValue} }\n`;
|
|
1717
|
+
return acc + `if(${valueKey} !== undefined && ${nonOptionalValueKey} !== null) {\n ${formDataValue} }\n`;
|
|
1718
|
+
}
|
|
1719
|
+
if (isRequired) return acc + formDataValue;
|
|
1720
|
+
return acc + `if(${valueKey} !== undefined) {\n ${formDataValue} }\n`;
|
|
1721
|
+
}, "");
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
//#endregion
|
|
1725
|
+
//#region src/getters/body.ts
|
|
1726
|
+
function getBody({ requestBody, operationName, context, contentType }) {
|
|
1727
|
+
const allBodyTypes = getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context);
|
|
1728
|
+
const filteredBodyTypes = contentType ? allBodyTypes.filter((type) => {
|
|
1729
|
+
let include = true;
|
|
1730
|
+
let exclude = false;
|
|
1731
|
+
if (contentType.include) include = contentType.include.includes(type.contentType);
|
|
1732
|
+
if (contentType.exclude) exclude = contentType.exclude.includes(type.contentType);
|
|
1733
|
+
return include && !exclude;
|
|
1734
|
+
}) : allBodyTypes;
|
|
1735
|
+
const imports = filteredBodyTypes.flatMap(({ imports: imports$1 }) => imports$1);
|
|
1736
|
+
const schemas = filteredBodyTypes.flatMap(({ schemas: schemas$1 }) => schemas$1);
|
|
1737
|
+
const definition = filteredBodyTypes.map(({ value }) => value).join(" | ");
|
|
1738
|
+
const nonReadonlyDefinition = filteredBodyTypes.some((x) => x.hasReadonlyProps) && definition ? `NonReadonly<${definition}>` : definition;
|
|
1739
|
+
let implementation = generalJSTypesWithArray.includes(definition.toLowerCase()) || filteredBodyTypes.length > 1 ? camel(operationName) + context.output.override.components.requestBodies.suffix : camel(definition);
|
|
1740
|
+
let isOptional = false;
|
|
1741
|
+
if (implementation) {
|
|
1742
|
+
implementation = sanitize(implementation, {
|
|
1743
|
+
underscore: "_",
|
|
1744
|
+
whitespace: "_",
|
|
1745
|
+
dash: true,
|
|
1746
|
+
es5keyword: true,
|
|
1747
|
+
es5IdentifierName: true
|
|
1585
1748
|
});
|
|
1749
|
+
if (isReference(requestBody)) {
|
|
1750
|
+
const { schema: bodySchema } = resolveRef(requestBody, context);
|
|
1751
|
+
if (bodySchema.required !== void 0) isOptional = !bodySchema.required;
|
|
1752
|
+
} else if (requestBody.required !== void 0) isOptional = !requestBody.required;
|
|
1586
1753
|
}
|
|
1587
1754
|
return {
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1755
|
+
originalSchema: requestBody,
|
|
1756
|
+
definition: nonReadonlyDefinition,
|
|
1757
|
+
implementation,
|
|
1758
|
+
imports,
|
|
1759
|
+
schemas,
|
|
1760
|
+
isOptional,
|
|
1761
|
+
...filteredBodyTypes.length === 1 ? {
|
|
1762
|
+
formData: filteredBodyTypes[0].formData,
|
|
1763
|
+
formUrlEncoded: filteredBodyTypes[0].formUrlEncoded,
|
|
1764
|
+
contentType: filteredBodyTypes[0].contentType
|
|
1765
|
+
} : {
|
|
1766
|
+
formData: "",
|
|
1767
|
+
formUrlEncoded: "",
|
|
1768
|
+
contentType: ""
|
|
1769
|
+
}
|
|
1603
1770
|
};
|
|
1604
1771
|
}
|
|
1605
1772
|
|
|
1773
|
+
//#endregion
|
|
1774
|
+
//#region src/getters/imports.ts
|
|
1775
|
+
function getAliasedImports({ name, resolvedValue, context }) {
|
|
1776
|
+
return context.output.schemas && resolvedValue.isRef ? resolvedValue.imports.map((imp) => {
|
|
1777
|
+
if (!needCreateImportAlias({
|
|
1778
|
+
name,
|
|
1779
|
+
imp
|
|
1780
|
+
})) return imp;
|
|
1781
|
+
return {
|
|
1782
|
+
...imp,
|
|
1783
|
+
alias: `__${imp.name}`
|
|
1784
|
+
};
|
|
1785
|
+
}) : resolvedValue.imports;
|
|
1786
|
+
}
|
|
1787
|
+
function needCreateImportAlias({ imp, name }) {
|
|
1788
|
+
return !imp.alias && imp.name === name;
|
|
1789
|
+
}
|
|
1790
|
+
function getImportAliasForRefOrValue({ context, imports, resolvedValue }) {
|
|
1791
|
+
if (!context.output.schemas || !resolvedValue.isRef) return resolvedValue.value;
|
|
1792
|
+
return imports.find((imp) => imp.name === resolvedValue.value)?.alias ?? resolvedValue.value;
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1606
1795
|
//#endregion
|
|
1607
1796
|
//#region src/getters/keys.ts
|
|
1608
1797
|
function getKey(key) {
|
|
@@ -1637,7 +1826,7 @@ function getPropertyNamesRecordType(item, valueType) {
|
|
|
1637
1826
|
*
|
|
1638
1827
|
* @param item item with type === "object"
|
|
1639
1828
|
*/
|
|
1640
|
-
function getObject({ item, name, context, nullable,
|
|
1829
|
+
function getObject({ item, name, context, nullable, formDataContext }) {
|
|
1641
1830
|
if (isReference(item)) {
|
|
1642
1831
|
const { name: name$1 } = getRefInfo(item.$ref, context);
|
|
1643
1832
|
return {
|
|
@@ -1658,7 +1847,8 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
|
|
|
1658
1847
|
name,
|
|
1659
1848
|
separator: item.allOf ? "allOf" : item.oneOf ? "oneOf" : "anyOf",
|
|
1660
1849
|
context,
|
|
1661
|
-
nullable
|
|
1850
|
+
nullable,
|
|
1851
|
+
formDataContext
|
|
1662
1852
|
});
|
|
1663
1853
|
if (Array.isArray(item.type)) return combineSchemas({
|
|
1664
1854
|
schema: { anyOf: item.type.map((type) => ({
|
|
@@ -1684,10 +1874,15 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
|
|
|
1684
1874
|
}
|
|
1685
1875
|
const allSpecSchemas = context.spec.components?.schemas ?? {};
|
|
1686
1876
|
if (Object.keys(allSpecSchemas).some((schemaName) => pascal(schemaName) === propName)) propName = propName + "Property";
|
|
1687
|
-
const
|
|
1877
|
+
const propertyFormDataContext = formDataContext && !formDataContext.atPart ? {
|
|
1878
|
+
atPart: true,
|
|
1879
|
+
partContentType: formDataContext.encoding[key]?.contentType
|
|
1880
|
+
} : void 0;
|
|
1881
|
+
const resolvedValue = resolveObject({
|
|
1688
1882
|
schema,
|
|
1689
1883
|
propName,
|
|
1690
|
-
context
|
|
1884
|
+
context,
|
|
1885
|
+
formDataContext: propertyFormDataContext
|
|
1691
1886
|
});
|
|
1692
1887
|
const isReadOnly = item.readOnly || schema.readOnly;
|
|
1693
1888
|
if (!index) acc.value += "{";
|
|
@@ -1859,485 +2054,304 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
|
|
|
1859
2054
|
}
|
|
1860
2055
|
|
|
1861
2056
|
//#endregion
|
|
1862
|
-
//#region src/getters/
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
2057
|
+
//#region src/getters/scalar.ts
|
|
2058
|
+
/**
|
|
2059
|
+
* Return the typescript equivalent of open-api data type
|
|
2060
|
+
*
|
|
2061
|
+
* @param item
|
|
2062
|
+
* @ref https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.1.md#data-types
|
|
2063
|
+
*/
|
|
2064
|
+
function getScalar({ item, name, context, formDataContext }) {
|
|
2065
|
+
const nullable = isArray(item.type) && item.type.includes("null") || item.nullable === true ? " | null" : "";
|
|
2066
|
+
const enumItems = item.enum?.filter((enumItem) => enumItem !== null);
|
|
2067
|
+
let itemType = item.type;
|
|
2068
|
+
if (!itemType && item.items) {
|
|
2069
|
+
item.type = "array";
|
|
2070
|
+
itemType = "array";
|
|
1875
2071
|
}
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
}
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
const
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
imports: [{
|
|
1897
|
-
name: name$1,
|
|
1898
|
-
schemaName
|
|
1899
|
-
}],
|
|
2072
|
+
if (isArray(item.type) && item.type.includes("null")) {
|
|
2073
|
+
const typesWithoutNull = item.type.filter((x) => x !== "null");
|
|
2074
|
+
itemType = typesWithoutNull.length === 1 ? typesWithoutNull[0] : typesWithoutNull;
|
|
2075
|
+
}
|
|
2076
|
+
switch (itemType) {
|
|
2077
|
+
case "number":
|
|
2078
|
+
case "integer": {
|
|
2079
|
+
let value = context.output.override.useBigInt && (item.format === "int64" || item.format === "uint64") ? "bigint" : "number";
|
|
2080
|
+
let isEnum = false;
|
|
2081
|
+
if (enumItems) {
|
|
2082
|
+
value = enumItems.map((enumItem) => `${enumItem}`).join(" | ");
|
|
2083
|
+
isEnum = true;
|
|
2084
|
+
}
|
|
2085
|
+
value += nullable;
|
|
2086
|
+
const itemWithConst = item;
|
|
2087
|
+
if (itemWithConst.const !== void 0) value = itemWithConst.const;
|
|
2088
|
+
return {
|
|
2089
|
+
value,
|
|
2090
|
+
isEnum,
|
|
2091
|
+
type: "number",
|
|
1900
2092
|
schemas: [],
|
|
1901
|
-
|
|
2093
|
+
imports: [],
|
|
2094
|
+
isRef: false,
|
|
2095
|
+
hasReadonlyProps: item.readOnly || false,
|
|
2096
|
+
dependencies: [],
|
|
2097
|
+
example: item.example,
|
|
2098
|
+
examples: resolveExampleRefs(item.examples, context)
|
|
2099
|
+
};
|
|
2100
|
+
}
|
|
2101
|
+
case "boolean": {
|
|
2102
|
+
let value = "boolean" + nullable;
|
|
2103
|
+
const itemWithConst = item;
|
|
2104
|
+
if (itemWithConst.const !== void 0) value = itemWithConst.const;
|
|
2105
|
+
return {
|
|
2106
|
+
value,
|
|
2107
|
+
type: "boolean",
|
|
1902
2108
|
isEnum: false,
|
|
1903
|
-
isRef: true,
|
|
1904
|
-
hasReadonlyProps: false,
|
|
1905
|
-
originalSchema: mediaType?.schema,
|
|
1906
|
-
example: mediaType?.example,
|
|
1907
|
-
examples: resolveExampleRefs(mediaType?.examples, context),
|
|
1908
|
-
key,
|
|
1909
|
-
contentType
|
|
1910
|
-
}];
|
|
1911
|
-
const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
|
|
1912
|
-
name: name$1,
|
|
1913
|
-
schemaObject: mediaType.schema,
|
|
1914
|
-
context,
|
|
1915
|
-
isRequestBodyOptional: "required" in bodySchema && bodySchema.required === false,
|
|
1916
|
-
isRef: true,
|
|
1917
|
-
encoding: mediaType.encoding
|
|
1918
|
-
}) : void 0;
|
|
1919
|
-
const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
|
|
1920
|
-
name: name$1,
|
|
1921
|
-
schemaObject: mediaType.schema,
|
|
1922
|
-
context,
|
|
1923
|
-
isRequestBodyOptional: "required" in bodySchema && bodySchema.required === false,
|
|
1924
|
-
isUrlEncoded: true,
|
|
1925
|
-
isRef: true,
|
|
1926
|
-
encoding: mediaType.encoding
|
|
1927
|
-
}) : void 0;
|
|
1928
|
-
const additionalImports = getFormDataAdditionalImports({
|
|
1929
|
-
schemaObject: mediaType.schema,
|
|
1930
|
-
context
|
|
1931
|
-
});
|
|
1932
|
-
return [{
|
|
1933
|
-
value: name$1,
|
|
1934
|
-
imports: [{
|
|
1935
|
-
name: name$1,
|
|
1936
|
-
schemaName
|
|
1937
|
-
}, ...additionalImports],
|
|
1938
2109
|
schemas: [],
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
hasReadonlyProps: false,
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
example: mediaType.example,
|
|
1947
|
-
examples: resolveExampleRefs(mediaType.examples, context),
|
|
1948
|
-
key,
|
|
1949
|
-
contentType
|
|
1950
|
-
}];
|
|
2110
|
+
imports: [],
|
|
2111
|
+
isRef: false,
|
|
2112
|
+
hasReadonlyProps: item.readOnly || false,
|
|
2113
|
+
dependencies: [],
|
|
2114
|
+
example: item.example,
|
|
2115
|
+
examples: resolveExampleRefs(item.examples, context)
|
|
2116
|
+
};
|
|
1951
2117
|
}
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
if (mediaType.schema && isReference(mediaType.schema)) {
|
|
1957
|
-
const { imports } = resolveRef(mediaType.schema, context);
|
|
1958
|
-
if (imports[0]?.name) effectivePropName = imports[0].name;
|
|
1959
|
-
}
|
|
1960
|
-
const isFormData = formDataContentTypes.has(contentType);
|
|
1961
|
-
const resolvedValue = getResReqContentTypes({
|
|
1962
|
-
mediaType,
|
|
1963
|
-
propName: effectivePropName,
|
|
2118
|
+
case "array": {
|
|
2119
|
+
const { value, ...rest } = getArray({
|
|
2120
|
+
schema: item,
|
|
2121
|
+
name,
|
|
1964
2122
|
context,
|
|
1965
|
-
|
|
1966
|
-
contentType
|
|
2123
|
+
formDataContext
|
|
1967
2124
|
});
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
return;
|
|
2125
|
+
return {
|
|
2126
|
+
value: value + nullable,
|
|
2127
|
+
...rest,
|
|
2128
|
+
dependencies: rest.dependencies ?? []
|
|
2129
|
+
};
|
|
2130
|
+
}
|
|
2131
|
+
case "string": {
|
|
2132
|
+
let value = "string";
|
|
2133
|
+
let isEnum = false;
|
|
2134
|
+
if (enumItems) {
|
|
2135
|
+
value = enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
|
|
2136
|
+
isEnum = true;
|
|
1981
2137
|
}
|
|
1982
|
-
|
|
1983
|
-
if (
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
2138
|
+
if (item.format === "binary") value = "Blob";
|
|
2139
|
+
else if (formDataContext?.atPart) {
|
|
2140
|
+
const fileType = getFormDataFieldFileType(item, formDataContext.partContentType);
|
|
2141
|
+
if (fileType) value = fileType === "binary" ? "Blob" : "Blob | string";
|
|
2142
|
+
}
|
|
2143
|
+
if (context.output.override.useDates && (item.format === "date" || item.format === "date-time")) value = "Date";
|
|
2144
|
+
value += nullable;
|
|
2145
|
+
const itemWithConst = item;
|
|
2146
|
+
if (itemWithConst.const) value = `'${itemWithConst.const}'`;
|
|
2147
|
+
return {
|
|
2148
|
+
value,
|
|
2149
|
+
isEnum,
|
|
2150
|
+
type: "string",
|
|
2151
|
+
imports: [],
|
|
2152
|
+
schemas: [],
|
|
2153
|
+
isRef: false,
|
|
2154
|
+
hasReadonlyProps: item.readOnly || false,
|
|
2155
|
+
dependencies: [],
|
|
2156
|
+
example: item.example,
|
|
2157
|
+
examples: resolveExampleRefs(item.examples, context)
|
|
1989
2158
|
};
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
2159
|
+
}
|
|
2160
|
+
case "null": return {
|
|
2161
|
+
value: "null",
|
|
2162
|
+
isEnum: false,
|
|
2163
|
+
type: "null",
|
|
2164
|
+
imports: [],
|
|
2165
|
+
schemas: [],
|
|
2166
|
+
isRef: false,
|
|
2167
|
+
hasReadonlyProps: item.readOnly || false,
|
|
2168
|
+
dependencies: []
|
|
2169
|
+
};
|
|
2170
|
+
case "object":
|
|
2171
|
+
default: {
|
|
2172
|
+
if (isArray(itemType)) return combineSchemas({
|
|
2173
|
+
schema: { anyOf: itemType.map((type) => ({
|
|
2174
|
+
...item,
|
|
2175
|
+
type
|
|
2176
|
+
})) },
|
|
2177
|
+
name,
|
|
2178
|
+
separator: "anyOf",
|
|
1993
2179
|
context,
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2180
|
+
nullable
|
|
2181
|
+
});
|
|
2182
|
+
if (enumItems) return {
|
|
2183
|
+
value: enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `) + nullable,
|
|
2184
|
+
isEnum: true,
|
|
2185
|
+
type: "string",
|
|
2186
|
+
imports: [],
|
|
2187
|
+
schemas: [],
|
|
2188
|
+
isRef: false,
|
|
2189
|
+
hasReadonlyProps: item.readOnly || false,
|
|
2190
|
+
dependencies: [],
|
|
2191
|
+
example: item.example,
|
|
2192
|
+
examples: resolveExampleRefs(item.examples, context)
|
|
2193
|
+
};
|
|
2194
|
+
const hasCombiners = item.allOf || item.anyOf || item.oneOf;
|
|
2195
|
+
const { value, ...rest } = getObject({
|
|
2196
|
+
item,
|
|
2197
|
+
name,
|
|
2001
2198
|
context,
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
isRef: true,
|
|
2005
|
-
encoding: mediaType.encoding
|
|
2006
|
-
}) : void 0;
|
|
2007
|
-
const additionalImports = getFormDataAdditionalImports({
|
|
2008
|
-
schemaObject: mediaType.schema,
|
|
2009
|
-
context
|
|
2199
|
+
nullable,
|
|
2200
|
+
formDataContext: formDataContext?.atPart === false || formDataContext?.atPart && hasCombiners ? formDataContext : void 0
|
|
2010
2201
|
});
|
|
2011
2202
|
return {
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
formData,
|
|
2015
|
-
formUrlEncoded,
|
|
2016
|
-
contentType,
|
|
2017
|
-
example: mediaType.example,
|
|
2018
|
-
examples: resolveExampleRefs(mediaType.examples, context)
|
|
2203
|
+
value,
|
|
2204
|
+
...rest
|
|
2019
2205
|
};
|
|
2020
|
-
}
|
|
2021
|
-
|
|
2022
|
-
key
|
|
2023
|
-
}));
|
|
2024
|
-
const swaggerSchema = "schema" in res ? res.schema : void 0;
|
|
2025
|
-
if (swaggerSchema) return [{
|
|
2026
|
-
...resolveObject({
|
|
2027
|
-
schema: swaggerSchema,
|
|
2028
|
-
propName: key ? pascal(name) + pascal(key) : void 0,
|
|
2029
|
-
context
|
|
2030
|
-
}),
|
|
2031
|
-
contentType: "application/json",
|
|
2032
|
-
key
|
|
2033
|
-
}];
|
|
2034
|
-
return [{
|
|
2035
|
-
value: defaultType,
|
|
2036
|
-
imports: [],
|
|
2037
|
-
schemas: [],
|
|
2038
|
-
type: defaultType,
|
|
2039
|
-
isEnum: false,
|
|
2040
|
-
key,
|
|
2041
|
-
isRef: false,
|
|
2042
|
-
hasReadonlyProps: false,
|
|
2043
|
-
contentType: "application/json"
|
|
2044
|
-
}];
|
|
2045
|
-
}).flat(), uniqueKey);
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2046
2208
|
}
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
if (
|
|
2052
|
-
if (
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
"+xml",
|
|
2058
|
-
"-xml",
|
|
2059
|
-
"+yaml",
|
|
2060
|
-
"-yaml",
|
|
2061
|
-
"+rss",
|
|
2062
|
-
"-rss",
|
|
2063
|
-
"+csv",
|
|
2064
|
-
"-csv"
|
|
2065
|
-
].some((suffix) => contentType.includes(suffix))) return false;
|
|
2066
|
-
return !new Set([
|
|
2067
|
-
"application/json",
|
|
2068
|
-
"application/xml",
|
|
2069
|
-
"application/yaml",
|
|
2070
|
-
"application/x-www-form-urlencoded",
|
|
2071
|
-
"application/javascript",
|
|
2072
|
-
"application/ecmascript",
|
|
2073
|
-
"application/graphql"
|
|
2074
|
-
]).has(contentType);
|
|
2075
|
-
}
|
|
2076
|
-
/**
|
|
2077
|
-
* Determine the response type category for a given content type.
|
|
2078
|
-
* Used to set the correct responseType option in HTTP clients.
|
|
2079
|
-
*
|
|
2080
|
-
* @param contentType - The MIME content type (e.g., 'application/json', 'text/plain')
|
|
2081
|
-
* @returns The response type category to use for parsing
|
|
2082
|
-
*/
|
|
2083
|
-
function getResponseTypeCategory(contentType) {
|
|
2084
|
-
if (isBinaryContentType(contentType)) return "blob";
|
|
2085
|
-
if (contentType === "application/json" || contentType.includes("+json") || contentType.includes("-json")) return "json";
|
|
2086
|
-
return "text";
|
|
2087
|
-
}
|
|
2088
|
-
/**
|
|
2089
|
-
* Get the default content type from a list of content types.
|
|
2090
|
-
* Priority: application/json > any JSON-like type > first in list
|
|
2091
|
-
*
|
|
2092
|
-
* @param contentTypes - Array of content types from OpenAPI spec
|
|
2093
|
-
* @returns The default content type to use
|
|
2094
|
-
*/
|
|
2095
|
-
function getDefaultContentType(contentTypes) {
|
|
2096
|
-
if (contentTypes.length === 0) return "application/json";
|
|
2097
|
-
if (contentTypes.includes("application/json")) return "application/json";
|
|
2098
|
-
const jsonType = contentTypes.find((ct) => ct.includes("+json") || ct.includes("-json"));
|
|
2099
|
-
if (jsonType) return jsonType;
|
|
2100
|
-
return contentTypes[0];
|
|
2101
|
-
}
|
|
2102
|
-
/**
|
|
2103
|
-
* Determine if a form-data root field should be treated as binary or text file
|
|
2104
|
-
* based on encoding.contentType or contentMediaType.
|
|
2105
|
-
*
|
|
2106
|
-
* Returns:
|
|
2107
|
-
* - 'binary': field is a binary file (Blob in types, File in zod)
|
|
2108
|
-
* - 'text': field is a text file that can accept string (Blob | string in types, File | string in zod)
|
|
2109
|
-
* - undefined: no override, use standard resolution
|
|
2110
|
-
*/
|
|
2111
|
-
function getFormDataFieldFileType(resolvedSchema, encodingContentType) {
|
|
2112
|
-
if (resolvedSchema.type !== "string") return;
|
|
2113
|
-
if (resolvedSchema.contentEncoding) return;
|
|
2114
|
-
const effectiveContentType = encodingContentType ?? resolvedSchema.contentMediaType;
|
|
2115
|
-
if (effectiveContentType) return isBinaryContentType(effectiveContentType) ? "binary" : "text";
|
|
2116
|
-
}
|
|
2117
|
-
/**
|
|
2118
|
-
* Resolve form-data root object with file type overrides.
|
|
2119
|
-
* Returns undefined if no file type overrides needed (caller should use normal resolution).
|
|
2120
|
-
*/
|
|
2121
|
-
function resolveFormDataRootObject({ schemaOrRef, propName, context, encoding }) {
|
|
2122
|
-
const { schema } = resolveRef(schemaOrRef, context);
|
|
2123
|
-
if (!schema.properties) return;
|
|
2124
|
-
const propertyOverrides = {};
|
|
2125
|
-
for (const key of Object.keys(schema.properties)) {
|
|
2126
|
-
const propSchema = schema.properties[key];
|
|
2127
|
-
const { schema: resolvedSchema } = resolveRef(propSchema, context);
|
|
2128
|
-
const fileType = getFormDataFieldFileType(resolvedSchema, encoding?.[key]?.contentType);
|
|
2129
|
-
if (fileType) propertyOverrides[key] = {
|
|
2130
|
-
...getScalar({
|
|
2131
|
-
item: resolvedSchema,
|
|
2132
|
-
name: propName,
|
|
2133
|
-
context
|
|
2134
|
-
}),
|
|
2135
|
-
value: fileType === "binary" ? "Blob" : "Blob | string"
|
|
2136
|
-
};
|
|
2137
|
-
}
|
|
2138
|
-
if (Object.keys(propertyOverrides).length === 0) return;
|
|
2139
|
-
const result = getObject({
|
|
2140
|
-
item: schema,
|
|
2141
|
-
name: propName,
|
|
2142
|
-
context,
|
|
2143
|
-
nullable: "",
|
|
2144
|
-
propertyOverrides
|
|
2145
|
-
});
|
|
2146
|
-
return createTypeAliasIfNeeded({
|
|
2147
|
-
resolvedValue: {
|
|
2148
|
-
...result,
|
|
2149
|
-
originalSchema: schema
|
|
2150
|
-
},
|
|
2151
|
-
propName,
|
|
2152
|
-
context
|
|
2153
|
-
}) ?? result;
|
|
2154
|
-
}
|
|
2155
|
-
function getFormDataAdditionalImports({ schemaObject, context }) {
|
|
2156
|
-
const { schema } = resolveRef(schemaObject, context);
|
|
2157
|
-
if (schema.type !== "object") return [];
|
|
2158
|
-
const combinedSchemas = schema.oneOf || schema.anyOf;
|
|
2159
|
-
if (!combinedSchemas) return [];
|
|
2160
|
-
return combinedSchemas.map((schema$1) => resolveRef(schema$1, context).imports[0]).filter(Boolean);
|
|
2161
|
-
}
|
|
2162
|
-
function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequestBodyOptional, isUrlEncoded, isRef, encoding }) {
|
|
2163
|
-
const { schema, imports } = resolveRef(schemaObject, context);
|
|
2164
|
-
const propName = camel(!isRef && isReference(schemaObject) ? imports[0].name : name);
|
|
2165
|
-
const additionalImports = [];
|
|
2166
|
-
const variableName = isUrlEncoded ? "formUrlEncoded" : "formData";
|
|
2167
|
-
let form = isUrlEncoded ? `const ${variableName} = new URLSearchParams();\n` : `const ${variableName} = new FormData();\n`;
|
|
2168
|
-
const combinedSchemas = schema.oneOf || schema.anyOf || schema.allOf;
|
|
2169
|
-
if (schema.type === "object" || schema.type === void 0 && combinedSchemas) {
|
|
2170
|
-
if (combinedSchemas) {
|
|
2171
|
-
const shouldCast = !!schema.oneOf || !!schema.anyOf;
|
|
2172
|
-
const combinedSchemasFormData = combinedSchemas.map((schema$1) => {
|
|
2173
|
-
const { schema: combinedSchema, imports: imports$1 } = resolveRef(schema$1, context);
|
|
2174
|
-
let newPropName = propName;
|
|
2175
|
-
let newPropDefinition = "";
|
|
2176
|
-
if (shouldCast && imports$1[0]) {
|
|
2177
|
-
additionalImports.push(imports$1[0]);
|
|
2178
|
-
newPropName = `${propName}${pascal(imports$1[0].name)}`;
|
|
2179
|
-
newPropDefinition = `const ${newPropName} = (${propName} as ${imports$1[0].name}${isRequestBodyOptional ? " | undefined" : ""});\n`;
|
|
2180
|
-
}
|
|
2181
|
-
return newPropDefinition + resolveSchemaPropertiesToFormData({
|
|
2182
|
-
schema: combinedSchema,
|
|
2183
|
-
variableName,
|
|
2184
|
-
propName: newPropName,
|
|
2185
|
-
context,
|
|
2186
|
-
isRequestBodyOptional,
|
|
2187
|
-
encoding
|
|
2188
|
-
});
|
|
2189
|
-
}).filter(Boolean).join("\n");
|
|
2190
|
-
form += combinedSchemasFormData;
|
|
2191
|
-
}
|
|
2192
|
-
if (schema.properties) {
|
|
2193
|
-
const formDataValues = resolveSchemaPropertiesToFormData({
|
|
2194
|
-
schema,
|
|
2195
|
-
variableName,
|
|
2196
|
-
propName,
|
|
2197
|
-
context,
|
|
2198
|
-
isRequestBodyOptional,
|
|
2199
|
-
encoding
|
|
2200
|
-
});
|
|
2201
|
-
form += formDataValues;
|
|
2209
|
+
|
|
2210
|
+
//#endregion
|
|
2211
|
+
//#region src/getters/combine.ts
|
|
2212
|
+
function combineValues({ resolvedData, resolvedValue, separator: separator$1, context }) {
|
|
2213
|
+
if (resolvedData.isEnum.every(Boolean)) return `${resolvedData.values.join(` | `)}${resolvedValue ? ` | ${resolvedValue.value}` : ""}`;
|
|
2214
|
+
if (separator$1 === "allOf") {
|
|
2215
|
+
let resolvedDataValue = resolvedData.values.map((v) => v.includes(" | ") ? `(${v})` : v).join(` & `);
|
|
2216
|
+
if (resolvedData.originalSchema.length > 0 && resolvedValue) {
|
|
2217
|
+
const discriminatedPropertySchemas = resolvedData.originalSchema.filter((s) => s?.discriminator && resolvedValue.value.includes(` ${s.discriminator.propertyName}:`));
|
|
2218
|
+
if (discriminatedPropertySchemas.length > 0) resolvedDataValue = `Omit<${resolvedDataValue}, '${discriminatedPropertySchemas.map((s) => s.discriminator?.propertyName).join("' | '")}'>`;
|
|
2202
2219
|
}
|
|
2203
|
-
|
|
2220
|
+
const resolvedValueStr = resolvedValue?.value.includes(" | ") ? `(${resolvedValue.value})` : resolvedValue?.value;
|
|
2221
|
+
const joined = `${resolvedDataValue}${resolvedValue ? ` & ${resolvedValueStr}` : ""}`;
|
|
2222
|
+
const overrideRequiredProperties = resolvedData.requiredProperties.filter((prop$1) => !resolvedData.originalSchema.some((schema) => schema?.properties?.[prop$1] && schema.required?.includes(prop$1)));
|
|
2223
|
+
if (overrideRequiredProperties.length > 0) return `${joined} & Required<Pick<${joined}, '${overrideRequiredProperties.join("' | '")}'>>`;
|
|
2224
|
+
return joined;
|
|
2204
2225
|
}
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2226
|
+
let values = resolvedData.values;
|
|
2227
|
+
if (resolvedData.allProperties.length && context.output.unionAddMissingProperties) {
|
|
2228
|
+
values = [];
|
|
2229
|
+
for (let i = 0; i < resolvedData.values.length; i += 1) {
|
|
2230
|
+
const subSchema = resolvedData.originalSchema[i];
|
|
2231
|
+
if (subSchema?.type !== "object") {
|
|
2232
|
+
values.push(resolvedData.values[i]);
|
|
2233
|
+
continue;
|
|
2234
|
+
}
|
|
2235
|
+
const missingProperties = unique(resolvedData.allProperties.filter((p) => !Object.keys(subSchema.properties).includes(p)));
|
|
2236
|
+
values.push(`${resolvedData.values[i]}${missingProperties.length > 0 ? ` & {${missingProperties.map((p) => `${p}?: never`).join("; ")}}` : ""}`);
|
|
2211
2237
|
}
|
|
2212
|
-
return `${form}${propName}.forEach(value => ${variableName}.append('data', ${valueStr}))\n`;
|
|
2213
2238
|
}
|
|
2214
|
-
if (
|
|
2215
|
-
return
|
|
2239
|
+
if (resolvedValue) return `(${values.join(` & ${resolvedValue.value}) | (`)} & ${resolvedValue.value})`;
|
|
2240
|
+
return values.join(" | ");
|
|
2216
2241
|
}
|
|
2217
|
-
function
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
const formattedKey = keyword.isIdentifierNameES5(key) ? `.${key}` : `['${key}']`;
|
|
2225
|
-
const valueKey = `${propName}${formattedKeyPrefix}${formattedKey}`;
|
|
2226
|
-
const nonOptionalValueKey = `${propName}${formattedKey}`;
|
|
2227
|
-
const fileType = getFormDataFieldFileType(property, encodingContentType);
|
|
2228
|
-
const effectiveContentType = encodingContentType ?? property.contentMediaType;
|
|
2229
|
-
if (fileType === "binary" || property.format === "binary") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
2230
|
-
else if (fileType === "text") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey} instanceof Blob ? ${nonOptionalValueKey} : new Blob([${nonOptionalValueKey}], { type: '${effectiveContentType}' }));\n`;
|
|
2231
|
-
else if (property.type === "object") formDataValue = context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE ? resolveSchemaPropertiesToFormData({
|
|
2232
|
-
schema: property,
|
|
2233
|
-
variableName,
|
|
2234
|
-
propName: nonOptionalValueKey,
|
|
2235
|
-
context,
|
|
2236
|
-
isRequestBodyOptional,
|
|
2237
|
-
keyPrefix: `${keyPrefix}${key}.`,
|
|
2238
|
-
depth: depth + 1,
|
|
2239
|
-
encoding
|
|
2240
|
-
}) : encodingContentType ? `${variableName}.append(\`${keyPrefix}${key}\`, new Blob([JSON.stringify(${nonOptionalValueKey})], { type: '${encodingContentType}' }));\n` : `${variableName}.append(\`${keyPrefix}${key}\`, JSON.stringify(${nonOptionalValueKey}));\n`;
|
|
2241
|
-
else if (property.type === "array") {
|
|
2242
|
-
let valueStr = "value";
|
|
2243
|
-
let hasNonPrimitiveChild = false;
|
|
2244
|
-
if (property.items) {
|
|
2245
|
-
const { schema: itemSchema } = resolveRef(property.items, context);
|
|
2246
|
-
if (itemSchema.type === "object" || itemSchema.type === "array") if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
|
|
2247
|
-
hasNonPrimitiveChild = true;
|
|
2248
|
-
const resolvedValue = resolveSchemaPropertiesToFormData({
|
|
2249
|
-
schema: itemSchema,
|
|
2250
|
-
variableName,
|
|
2251
|
-
propName: "value",
|
|
2252
|
-
context,
|
|
2253
|
-
isRequestBodyOptional,
|
|
2254
|
-
keyPrefix: `${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}].`,
|
|
2255
|
-
depth: depth + 1
|
|
2256
|
-
});
|
|
2257
|
-
formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => {
|
|
2258
|
-
${resolvedValue}});\n`;
|
|
2259
|
-
} else valueStr = "JSON.stringify(value)";
|
|
2260
|
-
else if (itemSchema.type === "number" || itemSchema.type?.includes("number") || itemSchema.type === "integer" || itemSchema.type?.includes("integer") || itemSchema.type === "boolean" || itemSchema.type?.includes("boolean")) valueStr = "value.toString()";
|
|
2261
|
-
}
|
|
2262
|
-
if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
|
|
2263
|
-
if (!hasNonPrimitiveChild) formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => ${variableName}.append(\`${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}]\`, ${valueStr}));\n`;
|
|
2264
|
-
} else formDataValue = `${valueKey}.forEach(value => ${variableName}.append(\`${keyPrefix}${key}${context.output.override.formData.arrayHandling === FormDataArrayHandling.SERIALIZE_WITH_BRACKETS ? "[]" : ""}\`, ${valueStr}));\n`;
|
|
2265
|
-
} else if (property.type === "number" || property.type?.includes("number") || property.type === "integer" || property.type?.includes("integer") || property.type === "boolean" || property.type?.includes("boolean")) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
2266
|
-
else formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
2267
|
-
let existSubSchemaNullable = false;
|
|
2268
|
-
if (property.allOf || property.anyOf || property.oneOf) {
|
|
2269
|
-
const subSchemas = (property.allOf || property.anyOf || property.oneOf)?.map((c) => resolveObject({
|
|
2270
|
-
schema: c,
|
|
2271
|
-
combined: true,
|
|
2272
|
-
context
|
|
2273
|
-
}));
|
|
2274
|
-
if (subSchemas?.some((subSchema) => {
|
|
2275
|
-
return [
|
|
2276
|
-
"number",
|
|
2277
|
-
"integer",
|
|
2278
|
-
"boolean"
|
|
2279
|
-
].includes(subSchema.type);
|
|
2280
|
-
})) formDataValue = `${variableName}.append(\`${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
2281
|
-
if (subSchemas?.some((subSchema) => {
|
|
2282
|
-
return subSchema.type === "null";
|
|
2283
|
-
})) existSubSchemaNullable = true;
|
|
2284
|
-
}
|
|
2285
|
-
const isRequired = schema.required?.includes(key) && !isRequestBodyOptional;
|
|
2286
|
-
if (property.nullable || property.type?.includes("null") || existSubSchemaNullable) {
|
|
2287
|
-
if (isRequired) return acc + `if(${valueKey} !== null) {\n ${formDataValue} }\n`;
|
|
2288
|
-
return acc + `if(${valueKey} !== undefined && ${nonOptionalValueKey} !== null) {\n ${formDataValue} }\n`;
|
|
2242
|
+
function combineSchemas({ name, schema, separator: separator$1, context, nullable, formDataContext }) {
|
|
2243
|
+
const items = schema[separator$1] ?? [];
|
|
2244
|
+
const resolvedData = items.reduce((acc, subSchema) => {
|
|
2245
|
+
let propName;
|
|
2246
|
+
if (context.output.override.aliasCombinedTypes) {
|
|
2247
|
+
propName = name ? name + pascal(separator$1) : void 0;
|
|
2248
|
+
if (propName && acc.schemas.length > 0) propName = propName + pascal(getNumberWord(acc.schemas.length + 1));
|
|
2289
2249
|
}
|
|
2290
|
-
if (
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2250
|
+
if (separator$1 === "allOf" && isSchema(subSchema) && subSchema.required) acc.requiredProperties.push(...subSchema.required);
|
|
2251
|
+
const resolvedValue$1 = resolveObject({
|
|
2252
|
+
schema: subSchema,
|
|
2253
|
+
propName,
|
|
2254
|
+
combined: true,
|
|
2255
|
+
context,
|
|
2256
|
+
formDataContext
|
|
2257
|
+
});
|
|
2258
|
+
const aliasedImports = getAliasedImports({
|
|
2259
|
+
context,
|
|
2260
|
+
name,
|
|
2261
|
+
resolvedValue: resolvedValue$1
|
|
2262
|
+
});
|
|
2263
|
+
const value = getImportAliasForRefOrValue({
|
|
2264
|
+
context,
|
|
2265
|
+
resolvedValue: resolvedValue$1,
|
|
2266
|
+
imports: aliasedImports
|
|
2267
|
+
});
|
|
2268
|
+
acc.values.push(value);
|
|
2269
|
+
acc.imports.push(...aliasedImports);
|
|
2270
|
+
acc.schemas.push(...resolvedValue$1.schemas);
|
|
2271
|
+
acc.dependencies.push(...resolvedValue$1.dependencies);
|
|
2272
|
+
acc.isEnum.push(resolvedValue$1.isEnum);
|
|
2273
|
+
acc.types.push(resolvedValue$1.type);
|
|
2274
|
+
acc.isRef.push(resolvedValue$1.isRef);
|
|
2275
|
+
acc.originalSchema.push(resolvedValue$1.originalSchema);
|
|
2276
|
+
acc.hasReadonlyProps ||= resolvedValue$1.hasReadonlyProps;
|
|
2277
|
+
if (resolvedValue$1.type === "object" && resolvedValue$1.originalSchema.properties) acc.allProperties.push(...Object.keys(resolvedValue$1.originalSchema.properties));
|
|
2278
|
+
return acc;
|
|
2279
|
+
}, {
|
|
2280
|
+
values: [],
|
|
2281
|
+
imports: [],
|
|
2282
|
+
schemas: [],
|
|
2283
|
+
isEnum: [],
|
|
2284
|
+
isRef: [],
|
|
2285
|
+
types: [],
|
|
2286
|
+
dependencies: [],
|
|
2287
|
+
originalSchema: [],
|
|
2288
|
+
allProperties: [],
|
|
2289
|
+
hasReadonlyProps: false,
|
|
2290
|
+
example: schema.example,
|
|
2291
|
+
examples: resolveExampleRefs(schema.examples, context),
|
|
2292
|
+
requiredProperties: separator$1 === "allOf" ? schema.required ?? [] : []
|
|
2293
|
+
});
|
|
2294
|
+
if (resolvedData.isEnum.every(Boolean) && name && items.length > 1 && context.output.override.enumGenerationType !== EnumGeneration.UNION) {
|
|
2295
|
+
const { value: combinedEnumValue, valueImports, hasNull } = getCombinedEnumValue(resolvedData.values.map((value, index) => ({
|
|
2296
|
+
value,
|
|
2297
|
+
isRef: resolvedData.isRef[index],
|
|
2298
|
+
schema: resolvedData.originalSchema[index]
|
|
2299
|
+
})));
|
|
2300
|
+
const newEnum = `export const ${pascal(name)} = ${combinedEnumValue}`;
|
|
2301
|
+
const valueImportSet = new Set(valueImports);
|
|
2302
|
+
const typeSuffix = `${nullable}${hasNull && !nullable.includes("null") ? " | null" : ""}`;
|
|
2303
|
+
return {
|
|
2304
|
+
value: `typeof ${pascal(name)}[keyof typeof ${pascal(name)}]${typeSuffix}`,
|
|
2305
|
+
imports: [{ name: pascal(name) }],
|
|
2306
|
+
schemas: [...resolvedData.schemas, {
|
|
2307
|
+
imports: resolvedData.imports.filter((toImport) => valueImportSet.has(toImport.alias ?? toImport.name)).map((toImport) => ({
|
|
2308
|
+
...toImport,
|
|
2309
|
+
values: true
|
|
2310
|
+
})),
|
|
2311
|
+
model: newEnum,
|
|
2312
|
+
name
|
|
2313
|
+
}],
|
|
2314
|
+
isEnum: false,
|
|
2315
|
+
type: "object",
|
|
2316
|
+
isRef: false,
|
|
2317
|
+
hasReadonlyProps: resolvedData.hasReadonlyProps,
|
|
2318
|
+
dependencies: resolvedData.dependencies,
|
|
2319
|
+
example: schema.example,
|
|
2320
|
+
examples: resolveExampleRefs(schema.examples, context)
|
|
2321
|
+
};
|
|
2322
|
+
}
|
|
2323
|
+
let resolvedValue;
|
|
2324
|
+
if (schema.properties) resolvedValue = getScalar({
|
|
2325
|
+
item: Object.fromEntries(Object.entries(schema).filter(([key]) => key !== separator$1)),
|
|
2326
|
+
name,
|
|
2327
|
+
context
|
|
2328
|
+
});
|
|
2329
|
+
else if (separator$1 === "allOf" && (schema.oneOf || schema.anyOf)) {
|
|
2330
|
+
const siblingCombiner = schema.oneOf ? "oneOf" : "anyOf";
|
|
2331
|
+
resolvedValue = combineSchemas({
|
|
2332
|
+
schema: { [siblingCombiner]: schema[siblingCombiner] },
|
|
2333
|
+
name,
|
|
2334
|
+
separator: siblingCombiner,
|
|
2335
|
+
context,
|
|
2336
|
+
nullable: ""
|
|
2319
2337
|
});
|
|
2320
|
-
if (isReference(requestBody)) {
|
|
2321
|
-
const { schema: bodySchema } = resolveRef(requestBody, context);
|
|
2322
|
-
if (bodySchema.required !== void 0) isOptional = !bodySchema.required;
|
|
2323
|
-
} else if (requestBody.required !== void 0) isOptional = !requestBody.required;
|
|
2324
2338
|
}
|
|
2325
2339
|
return {
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
...
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2340
|
+
value: dedupeUnionType(combineValues({
|
|
2341
|
+
resolvedData,
|
|
2342
|
+
separator: separator$1,
|
|
2343
|
+
resolvedValue,
|
|
2344
|
+
context
|
|
2345
|
+
}) + nullable),
|
|
2346
|
+
imports: resolvedValue ? [...resolvedData.imports, ...resolvedValue.imports] : resolvedData.imports,
|
|
2347
|
+
schemas: resolvedValue ? [...resolvedData.schemas, ...resolvedValue.schemas] : resolvedData.schemas,
|
|
2348
|
+
dependencies: resolvedValue ? [...resolvedData.dependencies, ...resolvedValue.dependencies] : resolvedData.dependencies,
|
|
2349
|
+
isEnum: false,
|
|
2350
|
+
type: "object",
|
|
2351
|
+
isRef: false,
|
|
2352
|
+
hasReadonlyProps: resolvedData?.hasReadonlyProps || resolvedValue?.hasReadonlyProps || false,
|
|
2353
|
+
example: schema.example,
|
|
2354
|
+
examples: resolveExampleRefs(schema.examples, context)
|
|
2341
2355
|
};
|
|
2342
2356
|
}
|
|
2343
2357
|
|