@orval/core 8.12.1 → 8.12.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/index.d.mts +13 -1
- package/dist/index.mjs +1521 -1494
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { entries, groupBy, isArray, isBoolean, isBoolean as isBoolean$1, isEmptyish, isFunction, isFunction as isFunction$1, isNullish, isNullish as isNullish$1, isNumber, isString, isString as isString$1, prop, unique, uniqueBy, uniqueWith } from "remeda";
|
|
4
4
|
import { keyword } from "esutils";
|
|
5
|
-
import
|
|
5
|
+
import nodePath from "node:path";
|
|
6
6
|
import { compare } from "compare-versions";
|
|
7
7
|
import debug from "debug";
|
|
8
8
|
import { pathToFileURL } from "node:url";
|
|
@@ -144,7 +144,7 @@ function isReference(obj) {
|
|
|
144
144
|
return !isNullish$1(obj) && Object.hasOwn(obj, "$ref");
|
|
145
145
|
}
|
|
146
146
|
function isDirectory(pathValue) {
|
|
147
|
-
return !
|
|
147
|
+
return !nodePath.extname(pathValue);
|
|
148
148
|
}
|
|
149
149
|
function isObject(x) {
|
|
150
150
|
return Object.prototype.toString.call(x) === "[object Object]";
|
|
@@ -507,8 +507,8 @@ async function dynamicImport(toImport, from = process.cwd(), takeDefault = true)
|
|
|
507
507
|
if (!toImport) return toImport;
|
|
508
508
|
try {
|
|
509
509
|
if (isString(toImport)) {
|
|
510
|
-
const filePath =
|
|
511
|
-
const extension =
|
|
510
|
+
const filePath = nodePath.resolve(from, toImport);
|
|
511
|
+
const extension = nodePath.extname(filePath);
|
|
512
512
|
if (TS_MODULE_EXTENSIONS.has(extension)) {
|
|
513
513
|
const data = await createJiti(from, { interopDefault: true }).import(filePath);
|
|
514
514
|
if (takeDefault && (isObject(data) || isModule(data)) && data.default) return data.default;
|
|
@@ -533,14 +533,14 @@ function getExtension(path) {
|
|
|
533
533
|
//#region src/utils/file.ts
|
|
534
534
|
function getFileInfo(target = "", { backupFilename = "filename", extension = ".ts" } = {}) {
|
|
535
535
|
const isDir = isDirectory(target);
|
|
536
|
-
const filePath = isDir ?
|
|
536
|
+
const filePath = isDir ? nodePath.join(target, backupFilename + extension) : target;
|
|
537
537
|
return {
|
|
538
538
|
path: filePath,
|
|
539
539
|
pathWithoutExtension: filePath.replace(/\.[^/.]+$/, ""),
|
|
540
540
|
extension,
|
|
541
541
|
isDirectory: isDir,
|
|
542
|
-
dirname:
|
|
543
|
-
filename:
|
|
542
|
+
dirname: nodePath.dirname(filePath),
|
|
543
|
+
filename: nodePath.basename(filePath, extension.startsWith(".") ? extension : `.${extension}`)
|
|
544
544
|
};
|
|
545
545
|
}
|
|
546
546
|
async function removeFilesAndEmptyFolders(patterns, dir) {
|
|
@@ -754,13 +754,13 @@ function toUnix(value) {
|
|
|
754
754
|
return value;
|
|
755
755
|
}
|
|
756
756
|
function join(...args) {
|
|
757
|
-
return toUnix(
|
|
757
|
+
return toUnix(nodePath.join(...args.map((a) => toUnix(a))));
|
|
758
758
|
}
|
|
759
759
|
/**
|
|
760
760
|
* Behaves exactly like `path.relative(from, to)`, but keeps the first meaningful "./"
|
|
761
761
|
*/
|
|
762
762
|
function relativeSafe(from, to) {
|
|
763
|
-
return normalizeSafe(`./${toUnix(
|
|
763
|
+
return normalizeSafe(`./${toUnix(nodePath.relative(toUnix(from), toUnix(to)))}`);
|
|
764
764
|
}
|
|
765
765
|
function getSchemaFileName(path) {
|
|
766
766
|
return path.replace(`.${getExtension(path)}`, "").slice(path.lastIndexOf("/") + 1);
|
|
@@ -768,13 +768,13 @@ function getSchemaFileName(path) {
|
|
|
768
768
|
function normalizeSafe(value) {
|
|
769
769
|
let result;
|
|
770
770
|
value = toUnix(value);
|
|
771
|
-
result = toUnix(
|
|
771
|
+
result = toUnix(nodePath.normalize(value));
|
|
772
772
|
if (value.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
|
|
773
773
|
else if (value.startsWith("//") && !result.startsWith("//")) result = value.startsWith("//./") ? "//." + result : "/" + result;
|
|
774
774
|
return result;
|
|
775
775
|
}
|
|
776
776
|
function joinSafe(...values) {
|
|
777
|
-
let result = toUnix(
|
|
777
|
+
let result = toUnix(nodePath.join(...values.map((v) => toUnix(v))));
|
|
778
778
|
if (values.length > 0) {
|
|
779
779
|
const firstValue = toUnix(values[0]);
|
|
780
780
|
if (firstValue.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
|
|
@@ -805,14 +805,14 @@ function joinSafe(...values) {
|
|
|
805
805
|
* @returns The relative import path string.
|
|
806
806
|
*/
|
|
807
807
|
function getRelativeImportPath(importerFilePath, exporterFilePath, includeFileExtension = false) {
|
|
808
|
-
if (!
|
|
809
|
-
if (!
|
|
810
|
-
const importerDir =
|
|
811
|
-
const relativePath =
|
|
812
|
-
let posixPath =
|
|
808
|
+
if (!nodePath.isAbsolute(importerFilePath)) throw new Error(`'importerFilePath' is not an absolute path. "${importerFilePath}"`);
|
|
809
|
+
if (!nodePath.isAbsolute(exporterFilePath)) throw new Error(`'exporterFilePath' is not an absolute path. "${exporterFilePath}"`);
|
|
810
|
+
const importerDir = nodePath.dirname(importerFilePath);
|
|
811
|
+
const relativePath = nodePath.relative(importerDir, exporterFilePath);
|
|
812
|
+
let posixPath = nodePath.posix.join(...relativePath.split(nodePath.sep));
|
|
813
813
|
if (!posixPath.startsWith("./") && !posixPath.startsWith("../")) posixPath = `./${posixPath}`;
|
|
814
814
|
if (!includeFileExtension) {
|
|
815
|
-
const ext =
|
|
815
|
+
const ext = nodePath.extname(posixPath);
|
|
816
816
|
if (ext && posixPath.endsWith(ext)) posixPath = posixPath.slice(0, -ext.length);
|
|
817
817
|
}
|
|
818
818
|
return posixPath;
|
|
@@ -821,20 +821,20 @@ function getRelativeImportPath(importerFilePath, exporterFilePath, includeFileEx
|
|
|
821
821
|
//#region src/utils/resolve-version.ts
|
|
822
822
|
function resolveInstalledVersion(packageName, fromDir) {
|
|
823
823
|
try {
|
|
824
|
-
const require = createRequire(
|
|
824
|
+
const require = createRequire(nodePath.join(fromDir, "noop.js"));
|
|
825
825
|
try {
|
|
826
826
|
return require(`${packageName}/package.json`).version;
|
|
827
827
|
} catch (directError) {
|
|
828
828
|
if (directError instanceof Error && "code" in directError && directError.code === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
|
|
829
829
|
const entryPath = require.resolve(packageName);
|
|
830
|
-
let dir =
|
|
831
|
-
while (dir !==
|
|
832
|
-
const pkgPath =
|
|
830
|
+
let dir = nodePath.dirname(entryPath);
|
|
831
|
+
while (dir !== nodePath.parse(dir).root) {
|
|
832
|
+
const pkgPath = nodePath.join(dir, "package.json");
|
|
833
833
|
if (existsSync(pkgPath)) {
|
|
834
834
|
const pkgData = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
835
835
|
if (pkgData.name === packageName) return pkgData.version;
|
|
836
836
|
}
|
|
837
|
-
dir =
|
|
837
|
+
dir = nodePath.dirname(dir);
|
|
838
838
|
}
|
|
839
839
|
return;
|
|
840
840
|
}
|
|
@@ -1358,1589 +1358,1616 @@ function getRefInfo($ref, context) {
|
|
|
1358
1358
|
};
|
|
1359
1359
|
}
|
|
1360
1360
|
//#endregion
|
|
1361
|
-
//#region src/
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
*
|
|
1369
|
-
* @see https://spec.openapis.org/oas/v3.0.3#reference-object
|
|
1370
|
-
* @see https://spec.openapis.org/oas/v3.1.0#reference-object
|
|
1371
|
-
*/
|
|
1372
|
-
function resolveRef(schema, context, imports = []) {
|
|
1373
|
-
const refPath = "$ref" in schema ? schema.$ref : void 0;
|
|
1374
|
-
const nestedSchema = "schema" in schema ? schema.schema : void 0;
|
|
1375
|
-
if (isObject(nestedSchema) && isReference(nestedSchema) && typeof nestedSchema.$ref === "string") {
|
|
1376
|
-
const resolvedRef = resolveRef(nestedSchema, context, imports);
|
|
1377
|
-
if ("examples" in schema) {
|
|
1378
|
-
const schemaWithExamples = schema;
|
|
1379
|
-
schemaWithExamples.examples = resolveExampleRefs(schemaWithExamples.examples, context);
|
|
1380
|
-
}
|
|
1381
|
-
if ("examples" in resolvedRef.schema) {
|
|
1382
|
-
const resolvedWithExamples = resolvedRef.schema;
|
|
1383
|
-
resolvedWithExamples.examples = resolveExampleRefs(resolvedWithExamples.examples, context);
|
|
1384
|
-
}
|
|
1385
|
-
return {
|
|
1386
|
-
schema: {
|
|
1387
|
-
...schema,
|
|
1388
|
-
schema: resolvedRef.schema
|
|
1389
|
-
},
|
|
1390
|
-
imports: resolvedRef.imports
|
|
1391
|
-
};
|
|
1392
|
-
}
|
|
1393
|
-
if (isDereferenced(schema)) {
|
|
1394
|
-
if ("examples" in schema) {
|
|
1395
|
-
const schemaWithExamples = schema;
|
|
1396
|
-
schemaWithExamples.examples = resolveExampleRefs(schemaWithExamples.examples, context);
|
|
1397
|
-
}
|
|
1361
|
+
//#region src/getters/imports.ts
|
|
1362
|
+
function getAliasedImports({ name, resolvedValue, context }) {
|
|
1363
|
+
return context.output.schemas && resolvedValue.isRef ? resolvedValue.imports.map((imp) => {
|
|
1364
|
+
if (!needCreateImportAlias({
|
|
1365
|
+
name,
|
|
1366
|
+
imp
|
|
1367
|
+
})) return imp;
|
|
1398
1368
|
return {
|
|
1399
|
-
|
|
1400
|
-
|
|
1369
|
+
...imp,
|
|
1370
|
+
alias: `__${imp.name}`
|
|
1401
1371
|
};
|
|
1402
|
-
}
|
|
1403
|
-
if (!refPath) throw new Error(`${REF_NOT_FOUND_PREFIX}: missing $ref`);
|
|
1404
|
-
const { currentSchema, refInfo: { name, originalName } } = getSchema$1(schema, context);
|
|
1405
|
-
if (!currentSchema) throw new Error(`${REF_NOT_FOUND_PREFIX}: ${refPath}`);
|
|
1406
|
-
return resolveRef(currentSchema, { ...context }, [...imports, {
|
|
1407
|
-
name,
|
|
1408
|
-
schemaName: originalName
|
|
1409
|
-
}]);
|
|
1372
|
+
}) : resolvedValue.imports;
|
|
1410
1373
|
}
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
*
|
|
1414
|
-
* Preserves OpenAPI 3.0 `nullable` and 3.1 type-array (`["object", "null"]`)
|
|
1415
|
-
* hints from the referencing schema onto the resolved target.
|
|
1416
|
-
*
|
|
1417
|
-
* @see https://spec.openapis.org/oas/v3.0.3#fixed-fields-18 (nullable)
|
|
1418
|
-
* @see https://spec.openapis.org/oas/v3.1.0#schema-object (type as array)
|
|
1419
|
-
*/
|
|
1420
|
-
function getSchema$1(schema, context) {
|
|
1421
|
-
if (!schema.$ref) throw new Error(`${REF_NOT_FOUND_PREFIX}: missing $ref`);
|
|
1422
|
-
const refInfo = getRefInfo(schema.$ref, context);
|
|
1423
|
-
const { refPaths } = refInfo;
|
|
1424
|
-
const schemaByRefPaths = Array.isArray(refPaths) ? prop(context.spec, ...refPaths) : void 0;
|
|
1425
|
-
if (isObject(schemaByRefPaths) && isReference(schemaByRefPaths)) return getSchema$1(schemaByRefPaths, context);
|
|
1426
|
-
let currentSchema = schemaByRefPaths;
|
|
1427
|
-
if (isObject(currentSchema) && "nullable" in schema) {
|
|
1428
|
-
const nullable = schema.nullable;
|
|
1429
|
-
currentSchema = {
|
|
1430
|
-
...currentSchema,
|
|
1431
|
-
nullable
|
|
1432
|
-
};
|
|
1433
|
-
}
|
|
1434
|
-
if (isObject(currentSchema) && "type" in schema && Array.isArray(schema.type)) {
|
|
1435
|
-
const type = schema.type;
|
|
1436
|
-
currentSchema = {
|
|
1437
|
-
...currentSchema,
|
|
1438
|
-
type
|
|
1439
|
-
};
|
|
1440
|
-
}
|
|
1441
|
-
return {
|
|
1442
|
-
currentSchema,
|
|
1443
|
-
refInfo
|
|
1444
|
-
};
|
|
1374
|
+
function needCreateImportAlias({ imp, name }) {
|
|
1375
|
+
return !imp.alias && imp.name === name;
|
|
1445
1376
|
}
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
return Array.isArray(examples) ? examples.map((example) => {
|
|
1450
|
-
if (isObject(example) && isReference(example)) {
|
|
1451
|
-
const { schema } = resolveRef(example, context);
|
|
1452
|
-
return schema.value;
|
|
1453
|
-
}
|
|
1454
|
-
return example;
|
|
1455
|
-
}) : (() => {
|
|
1456
|
-
const result = {};
|
|
1457
|
-
for (const [key, example] of Object.entries(examples)) result[key] = isObject(example) && isReference(example) ? resolveRef(example, context).schema.value : example;
|
|
1458
|
-
return result;
|
|
1459
|
-
})();
|
|
1377
|
+
function getImportAliasForRefOrValue({ context, imports, resolvedValue }) {
|
|
1378
|
+
if (!context.output.schemas || !resolvedValue.isRef) return resolvedValue.value;
|
|
1379
|
+
return imports.find((imp) => imp.name === resolvedValue.value)?.alias ?? resolvedValue.value;
|
|
1460
1380
|
}
|
|
1461
1381
|
//#endregion
|
|
1462
|
-
//#region src/
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
isRef: false
|
|
1491
|
-
};
|
|
1382
|
+
//#region src/getters/combine.ts
|
|
1383
|
+
const mergeableAllOfKeys = new Set([
|
|
1384
|
+
"type",
|
|
1385
|
+
"properties",
|
|
1386
|
+
"required"
|
|
1387
|
+
]);
|
|
1388
|
+
function isMergeableAllOfObject(schema) {
|
|
1389
|
+
if (isNullish$1(schema.properties)) return false;
|
|
1390
|
+
if (schema.allOf || schema.anyOf || schema.oneOf) return false;
|
|
1391
|
+
if (!isNullish$1(schema.type) && schema.type !== "object") return false;
|
|
1392
|
+
return Object.keys(schema).every((key) => mergeableAllOfKeys.has(key));
|
|
1393
|
+
}
|
|
1394
|
+
function normalizeAllOfSchema(schema) {
|
|
1395
|
+
const schemaAllOf = schema.allOf;
|
|
1396
|
+
if (!schemaAllOf) return schema;
|
|
1397
|
+
let didMerge = false;
|
|
1398
|
+
const schemaProperties = schema.properties;
|
|
1399
|
+
const schemaRequired = schema.required;
|
|
1400
|
+
const mergedProperties = schemaProperties ? { ...schemaProperties } : {};
|
|
1401
|
+
const mergedRequired = new Set(schemaRequired);
|
|
1402
|
+
const remainingAllOf = [];
|
|
1403
|
+
for (const subSchema of schemaAllOf) {
|
|
1404
|
+
if (isSchema(subSchema) && isMergeableAllOfObject(subSchema)) {
|
|
1405
|
+
didMerge = true;
|
|
1406
|
+
if (subSchema.properties) Object.assign(mergedProperties, subSchema.properties);
|
|
1407
|
+
const subRequired = subSchema.required;
|
|
1408
|
+
if (subRequired) for (const prop of subRequired) mergedRequired.add(prop);
|
|
1409
|
+
continue;
|
|
1492
1410
|
}
|
|
1493
|
-
|
|
1494
|
-
let hasReadonlyProps = false;
|
|
1495
|
-
const refName = resolvedImport.name;
|
|
1496
|
-
if (!context.parents?.includes(refName)) hasReadonlyProps = getScalar({
|
|
1497
|
-
item: schemaObject,
|
|
1498
|
-
name: refName,
|
|
1499
|
-
context: {
|
|
1500
|
-
...context,
|
|
1501
|
-
parents: [...context.parents ?? [], refName]
|
|
1502
|
-
}
|
|
1503
|
-
}).hasReadonlyProps;
|
|
1504
|
-
const isAnyOfNullable = schemaObject.anyOf?.some((anyOfItem) => !isReference(anyOfItem) && (anyOfItem.type === "null" || Array.isArray(anyOfItem.type) && anyOfItem.type.includes("null")));
|
|
1505
|
-
const schemaType = schemaObject.type;
|
|
1506
|
-
const nullable = Array.isArray(schemaType) && schemaType.includes("null") || schemaObject.nullable === true || isAnyOfNullable ? " | null" : "";
|
|
1507
|
-
return {
|
|
1508
|
-
value: resolvedImport.name + nullable,
|
|
1509
|
-
imports: [{
|
|
1510
|
-
name: resolvedImport.name,
|
|
1511
|
-
schemaName: resolvedImport.schemaName
|
|
1512
|
-
}],
|
|
1513
|
-
type: schemaObject.type ?? "object",
|
|
1514
|
-
schemas: [],
|
|
1515
|
-
isEnum: !!schemaObject.enum,
|
|
1516
|
-
originalSchema: schemaObject,
|
|
1517
|
-
hasReadonlyProps,
|
|
1518
|
-
isRef: true,
|
|
1519
|
-
dependencies: [resolvedImport.name]
|
|
1520
|
-
};
|
|
1411
|
+
remainingAllOf.push(subSchema);
|
|
1521
1412
|
}
|
|
1413
|
+
if (!didMerge || remainingAllOf.length === 0) return schema;
|
|
1522
1414
|
return {
|
|
1523
|
-
...
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
formDataContext
|
|
1528
|
-
}),
|
|
1529
|
-
originalSchema: schema,
|
|
1530
|
-
isRef: false
|
|
1531
|
-
};
|
|
1532
|
-
}
|
|
1533
|
-
//#endregion
|
|
1534
|
-
//#region src/resolvers/object.ts
|
|
1535
|
-
/**
|
|
1536
|
-
* Wraps inline object type in a type alias.
|
|
1537
|
-
* E.g. `{ foo: string }` → value becomes `FooBody`, schema gets `export type FooBody = { foo: string };`
|
|
1538
|
-
*/
|
|
1539
|
-
function createTypeAliasIfNeeded({ resolvedValue, propName, context }) {
|
|
1540
|
-
if (!propName) return;
|
|
1541
|
-
if (resolvedValue.isEnum || resolvedValue.type !== "object") return;
|
|
1542
|
-
const aliasPattern = context.output.override.aliasCombinedTypes ? String.raw`{|&|\|` : "{";
|
|
1543
|
-
if (!new RegExp(aliasPattern).test(resolvedValue.value)) return;
|
|
1544
|
-
const { originalSchema } = resolvedValue;
|
|
1545
|
-
const doc = jsDoc(originalSchema);
|
|
1546
|
-
const isConstant = "const" in originalSchema;
|
|
1547
|
-
const constantIsString = "type" in originalSchema && (originalSchema.type === "string" || Array.isArray(originalSchema.type) && originalSchema.type.includes("string"));
|
|
1548
|
-
const model = isConstant ? `${doc}export const ${propName} = ${constantIsString ? `'${originalSchema.const}'` : originalSchema.const} as const;\n` : `${doc}export type ${propName} = ${resolvedValue.value};\n`;
|
|
1549
|
-
return {
|
|
1550
|
-
value: propName,
|
|
1551
|
-
imports: [{
|
|
1552
|
-
name: propName,
|
|
1553
|
-
isConstant
|
|
1554
|
-
}],
|
|
1555
|
-
schemas: [...resolvedValue.schemas, {
|
|
1556
|
-
name: propName,
|
|
1557
|
-
model,
|
|
1558
|
-
imports: resolvedValue.imports,
|
|
1559
|
-
dependencies: resolvedValue.dependencies
|
|
1560
|
-
}],
|
|
1561
|
-
isEnum: false,
|
|
1562
|
-
type: "object",
|
|
1563
|
-
isRef: resolvedValue.isRef,
|
|
1564
|
-
hasReadonlyProps: resolvedValue.hasReadonlyProps,
|
|
1565
|
-
dependencies: resolvedValue.dependencies
|
|
1415
|
+
...schema,
|
|
1416
|
+
...Object.keys(mergedProperties).length > 0 && { properties: mergedProperties },
|
|
1417
|
+
...mergedRequired.size > 0 && { required: [...mergedRequired] },
|
|
1418
|
+
...remainingAllOf.length > 0 && { allOf: remainingAllOf }
|
|
1566
1419
|
};
|
|
1567
1420
|
}
|
|
1568
|
-
function
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1421
|
+
function combineValues({ resolvedData, resolvedValue, separator, context, parentSchema }) {
|
|
1422
|
+
if (resolvedData.isEnum.every(Boolean)) return `${resolvedData.values.join(` | `)}${resolvedValue ? ` | ${resolvedValue.value}` : ""}`;
|
|
1423
|
+
if (separator === "allOf") {
|
|
1424
|
+
let resolvedDataValue = resolvedData.values.map((v) => v.includes(" | ") ? `(${v})` : v).join(` & `);
|
|
1425
|
+
if (resolvedData.originalSchema.length > 0 && resolvedValue) {
|
|
1426
|
+
const discriminatedPropertySchemas = resolvedData.originalSchema.filter((s) => {
|
|
1427
|
+
const disc = s?.discriminator;
|
|
1428
|
+
return disc && resolvedValue.value.includes(` ${disc.propertyName}:`);
|
|
1429
|
+
});
|
|
1430
|
+
if (discriminatedPropertySchemas.length > 0) resolvedDataValue = `Omit<${resolvedDataValue}, '${discriminatedPropertySchemas.map((s) => s.discriminator?.propertyName).join("' | '")}'>`;
|
|
1431
|
+
}
|
|
1432
|
+
const resolvedValueStr = resolvedValue?.value.includes(" | ") ? `(${resolvedValue.value})` : resolvedValue?.value;
|
|
1433
|
+
const joined = `${resolvedDataValue}${resolvedValue ? ` & ${resolvedValueStr}` : ""}`;
|
|
1434
|
+
const overrideRequiredProperties = resolvedData.requiredProperties.filter((prop) => !resolvedData.originalSchema.some((schema) => {
|
|
1435
|
+
const props = schema?.properties;
|
|
1436
|
+
const req = schema?.required;
|
|
1437
|
+
return props?.[prop] && req?.includes(prop);
|
|
1438
|
+
}) && !(() => {
|
|
1439
|
+
const parentProps = parentSchema?.properties;
|
|
1440
|
+
const parentReq = parentSchema?.required;
|
|
1441
|
+
return !!(parentProps?.[prop] && parentReq?.includes(prop));
|
|
1442
|
+
})());
|
|
1443
|
+
if (overrideRequiredProperties.length > 0) return `${joined} & Required<Pick<${joined}, '${overrideRequiredProperties.join("' | '")}'>>`;
|
|
1444
|
+
return joined;
|
|
1445
|
+
}
|
|
1446
|
+
let values = resolvedData.values;
|
|
1447
|
+
if (resolvedData.allProperties.length && context.output.unionAddMissingProperties) {
|
|
1448
|
+
values = [];
|
|
1449
|
+
for (let i = 0; i < resolvedData.values.length; i += 1) {
|
|
1450
|
+
const subSchema = resolvedData.originalSchema[i];
|
|
1451
|
+
if (subSchema?.type !== "object" || !subSchema.properties) {
|
|
1452
|
+
values.push(resolvedData.values[i]);
|
|
1453
|
+
continue;
|
|
1454
|
+
}
|
|
1455
|
+
const subSchemaProps = subSchema.properties;
|
|
1456
|
+
const missingProperties = unique(resolvedData.allProperties.filter((p) => !Object.keys(subSchemaProps).includes(p)));
|
|
1457
|
+
values.push(`${resolvedData.values[i]}${missingProperties.length > 0 ? ` & {${missingProperties.map((p) => `${p}?: never`).join("; ")}}` : ""}`);
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
if (resolvedValue) return `(${values.join(` & ${resolvedValue.value}) | (`)} & ${resolvedValue.value})`;
|
|
1461
|
+
return values.join(" | ");
|
|
1462
|
+
}
|
|
1463
|
+
function combineSchemas({ name, schema, separator, context, nullable, formDataContext }) {
|
|
1464
|
+
const normalizedSchema = separator === "allOf" && !context.output.override.aliasCombinedTypes && !schema.oneOf && !schema.anyOf ? normalizeAllOfSchema(schema) : schema;
|
|
1465
|
+
const items = normalizedSchema[separator] ?? [];
|
|
1466
|
+
const resolvedData = {
|
|
1467
|
+
values: [],
|
|
1468
|
+
imports: [],
|
|
1469
|
+
schemas: [],
|
|
1470
|
+
isEnum: [],
|
|
1471
|
+
isRef: [],
|
|
1472
|
+
types: [],
|
|
1473
|
+
dependencies: [],
|
|
1474
|
+
originalSchema: [],
|
|
1475
|
+
allProperties: [],
|
|
1476
|
+
hasReadonlyProps: false,
|
|
1477
|
+
example: schema.example,
|
|
1478
|
+
examples: resolveExampleRefs(schema.examples, context),
|
|
1479
|
+
requiredProperties: separator === "allOf" ? schema.required ?? [] : []
|
|
1583
1480
|
};
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1481
|
+
for (const subSchema of items) {
|
|
1482
|
+
let propName;
|
|
1483
|
+
if (context.output.override.aliasCombinedTypes) {
|
|
1484
|
+
propName = name ? name + pascal(separator) : void 0;
|
|
1485
|
+
if (propName && resolvedData.schemas.length > 0) propName = propName + pascal(getNumberWord(resolvedData.schemas.length + 1));
|
|
1486
|
+
}
|
|
1487
|
+
if (separator === "allOf" && isSchema(subSchema) && subSchema.required) resolvedData.requiredProperties.push(...subSchema.required);
|
|
1488
|
+
const resolvedValue = resolveObject({
|
|
1489
|
+
schema: subSchema,
|
|
1490
|
+
propName,
|
|
1491
|
+
combined: true,
|
|
1492
|
+
context,
|
|
1493
|
+
formDataContext
|
|
1494
|
+
});
|
|
1495
|
+
const aliasedImports = getAliasedImports({
|
|
1496
|
+
context,
|
|
1497
|
+
name,
|
|
1498
|
+
resolvedValue
|
|
1499
|
+
});
|
|
1500
|
+
const value = getImportAliasForRefOrValue({
|
|
1501
|
+
context,
|
|
1502
|
+
resolvedValue,
|
|
1503
|
+
imports: aliasedImports
|
|
1504
|
+
});
|
|
1505
|
+
resolvedData.values.push(value);
|
|
1506
|
+
resolvedData.imports.push(...aliasedImports);
|
|
1507
|
+
resolvedData.schemas.push(...resolvedValue.schemas);
|
|
1508
|
+
resolvedData.dependencies.push(...resolvedValue.dependencies);
|
|
1509
|
+
resolvedData.isEnum.push(resolvedValue.isEnum);
|
|
1510
|
+
resolvedData.types.push(resolvedValue.type);
|
|
1511
|
+
resolvedData.isRef.push(resolvedValue.isRef);
|
|
1512
|
+
resolvedData.originalSchema.push(resolvedValue.originalSchema);
|
|
1513
|
+
if (resolvedValue.hasReadonlyProps) resolvedData.hasReadonlyProps = true;
|
|
1514
|
+
const originalProps = resolvedValue.originalSchema.properties;
|
|
1515
|
+
if (resolvedValue.type === "object" && originalProps) resolvedData.allProperties.push(...Object.keys(originalProps));
|
|
1516
|
+
}
|
|
1517
|
+
if (resolvedData.isEnum.every(Boolean) && name && items.length > 1 && context.output.override.enumGenerationType !== EnumGeneration.UNION) {
|
|
1518
|
+
const { value: combinedEnumValue, valueImports, hasNull } = getCombinedEnumValue(resolvedData.values.map((value, index) => ({
|
|
1519
|
+
value,
|
|
1520
|
+
isRef: resolvedData.isRef[index],
|
|
1521
|
+
schema: resolvedData.originalSchema[index]
|
|
1522
|
+
})));
|
|
1523
|
+
const newEnum = `export const ${pascal(name)} = ${combinedEnumValue}`;
|
|
1524
|
+
const valueImportSet = new Set(valueImports);
|
|
1525
|
+
const typeSuffix = `${nullable}${hasNull && !nullable.includes("null") ? " | null" : ""}`;
|
|
1587
1526
|
return {
|
|
1588
|
-
value:
|
|
1589
|
-
imports: [{ name:
|
|
1590
|
-
schemas: [...
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1527
|
+
value: `typeof ${pascal(name)}[keyof typeof ${pascal(name)}]${typeSuffix}`,
|
|
1528
|
+
imports: [{ name: pascal(name) }],
|
|
1529
|
+
schemas: [...resolvedData.schemas, {
|
|
1530
|
+
imports: resolvedData.imports.filter((toImport) => valueImportSet.has(toImport.alias ?? toImport.name)).map((toImport) => ({
|
|
1531
|
+
...toImport,
|
|
1532
|
+
values: true
|
|
1533
|
+
})),
|
|
1534
|
+
model: newEnum,
|
|
1535
|
+
name
|
|
1595
1536
|
}],
|
|
1596
1537
|
isEnum: false,
|
|
1597
|
-
type: "
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1538
|
+
type: "object",
|
|
1539
|
+
isRef: false,
|
|
1540
|
+
hasReadonlyProps: resolvedData.hasReadonlyProps,
|
|
1541
|
+
dependencies: resolvedData.dependencies,
|
|
1542
|
+
example: schema.example,
|
|
1543
|
+
examples: resolveExampleRefs(schema.examples, context)
|
|
1602
1544
|
};
|
|
1603
1545
|
}
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
const
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
combined,
|
|
1612
|
-
projectName: context.projectName ?? context.output.target,
|
|
1613
|
-
formDataContext
|
|
1614
|
-
});
|
|
1615
|
-
if (resolveObjectCacheMap.has(hashKey)) return resolveObjectCacheMap.get(hashKey);
|
|
1616
|
-
const result = resolveObjectOriginal({
|
|
1617
|
-
schema,
|
|
1618
|
-
propName,
|
|
1619
|
-
combined,
|
|
1546
|
+
let resolvedValue;
|
|
1547
|
+
const normalizedProperties = normalizedSchema.properties;
|
|
1548
|
+
const schemaOneOf = schema.oneOf;
|
|
1549
|
+
const schemaAnyOf = schema.anyOf;
|
|
1550
|
+
if (normalizedProperties) resolvedValue = getScalar({
|
|
1551
|
+
item: Object.fromEntries(Object.entries(normalizedSchema).filter(([key]) => key !== separator)),
|
|
1552
|
+
name,
|
|
1620
1553
|
context,
|
|
1621
1554
|
formDataContext
|
|
1622
1555
|
});
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
*
|
|
1631
|
-
* @param item item with type === "array"
|
|
1632
|
-
*/
|
|
1633
|
-
function getArray({ schema, name, context, formDataContext }) {
|
|
1634
|
-
const schemaPrefixItems = schema.prefixItems;
|
|
1635
|
-
const schemaItems = schema.items;
|
|
1636
|
-
const schemaExample = schema.example;
|
|
1637
|
-
const schemaExamples = schema.examples;
|
|
1638
|
-
const itemSuffix = context.output.override.components.schemas.itemSuffix;
|
|
1639
|
-
if (schemaPrefixItems) {
|
|
1640
|
-
const resolvedObjects = schemaPrefixItems.map((item, index) => resolveObject({
|
|
1641
|
-
schema: item,
|
|
1642
|
-
propName: name ? name + itemSuffix + String(index) : void 0,
|
|
1643
|
-
context
|
|
1644
|
-
}));
|
|
1645
|
-
if (schemaItems) {
|
|
1646
|
-
const additional = resolveObject({
|
|
1647
|
-
schema: schemaItems,
|
|
1648
|
-
propName: name ? name + itemSuffix + "Additional" : void 0,
|
|
1649
|
-
context
|
|
1650
|
-
});
|
|
1651
|
-
resolvedObjects.push({
|
|
1652
|
-
...additional,
|
|
1653
|
-
value: `...${additional.value}[]`
|
|
1654
|
-
});
|
|
1655
|
-
}
|
|
1656
|
-
return {
|
|
1657
|
-
type: "array",
|
|
1658
|
-
isEnum: false,
|
|
1659
|
-
isRef: false,
|
|
1660
|
-
value: `[${resolvedObjects.map((o) => o.value).join(", ")}]`,
|
|
1661
|
-
imports: resolvedObjects.flatMap((o) => o.imports),
|
|
1662
|
-
schemas: resolvedObjects.flatMap((o) => o.schemas),
|
|
1663
|
-
dependencies: resolvedObjects.flatMap((o) => o.dependencies),
|
|
1664
|
-
hasReadonlyProps: resolvedObjects.some((o) => o.hasReadonlyProps),
|
|
1665
|
-
example: schemaExample,
|
|
1666
|
-
examples: resolveExampleRefs(schemaExamples, context)
|
|
1667
|
-
};
|
|
1668
|
-
}
|
|
1669
|
-
if (schemaItems) {
|
|
1670
|
-
const resolvedObject = resolveObject({
|
|
1671
|
-
schema: schemaItems,
|
|
1672
|
-
propName: name ? name + itemSuffix : void 0,
|
|
1556
|
+
else if (separator === "allOf" && (schemaOneOf || schemaAnyOf)) {
|
|
1557
|
+
const siblingCombiner = schemaOneOf ? "oneOf" : "anyOf";
|
|
1558
|
+
const siblingSchemas = schemaOneOf ?? schemaAnyOf;
|
|
1559
|
+
resolvedValue = combineSchemas({
|
|
1560
|
+
schema: { [siblingCombiner]: siblingSchemas },
|
|
1561
|
+
name,
|
|
1562
|
+
separator: siblingCombiner,
|
|
1673
1563
|
context,
|
|
1674
|
-
|
|
1564
|
+
nullable: ""
|
|
1675
1565
|
});
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
} else if (compareVersions(context.spec.openapi ?? "3.0.0", "3.1", ">=")) return {
|
|
1689
|
-
value: "unknown[]",
|
|
1690
|
-
imports: [],
|
|
1691
|
-
schemas: [],
|
|
1692
|
-
dependencies: [],
|
|
1566
|
+
}
|
|
1567
|
+
return {
|
|
1568
|
+
value: dedupeUnionType(combineValues({
|
|
1569
|
+
resolvedData,
|
|
1570
|
+
separator,
|
|
1571
|
+
resolvedValue,
|
|
1572
|
+
context,
|
|
1573
|
+
parentSchema: normalizedSchema
|
|
1574
|
+
}) + nullable),
|
|
1575
|
+
imports: resolvedValue ? [...resolvedData.imports, ...resolvedValue.imports] : resolvedData.imports,
|
|
1576
|
+
schemas: resolvedValue ? [...resolvedData.schemas, ...resolvedValue.schemas] : resolvedData.schemas,
|
|
1577
|
+
dependencies: resolvedValue ? [...resolvedData.dependencies, ...resolvedValue.dependencies] : resolvedData.dependencies,
|
|
1693
1578
|
isEnum: false,
|
|
1694
|
-
type: "
|
|
1579
|
+
type: "object",
|
|
1695
1580
|
isRef: false,
|
|
1696
|
-
hasReadonlyProps: false
|
|
1581
|
+
hasReadonlyProps: resolvedData.hasReadonlyProps || (resolvedValue?.hasReadonlyProps ?? false),
|
|
1582
|
+
example: schema.example,
|
|
1583
|
+
examples: resolveExampleRefs(schema.examples, context)
|
|
1697
1584
|
};
|
|
1698
|
-
else throw new Error(`All arrays must have an \`items\` key defined (name=${name}, schema=${JSON.stringify(schema)})`);
|
|
1699
1585
|
}
|
|
1700
1586
|
//#endregion
|
|
1701
|
-
//#region src/getters/
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
const
|
|
1710
|
-
|
|
1711
|
-
const
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1587
|
+
//#region src/getters/keys.ts
|
|
1588
|
+
function getKey(key) {
|
|
1589
|
+
return keyword.isIdentifierNameES5(key) ? key : `'${key}'`;
|
|
1590
|
+
}
|
|
1591
|
+
//#endregion
|
|
1592
|
+
//#region src/getters/object.ts
|
|
1593
|
+
function getPropertyNamesEnumKeyType(item) {
|
|
1594
|
+
if (!("propertyNames" in item) || !item.propertyNames) return;
|
|
1595
|
+
const propertyNames = item.propertyNames;
|
|
1596
|
+
if (Array.isArray(propertyNames.enum)) {
|
|
1597
|
+
const enumValues = propertyNames.enum.filter((val) => isString(val));
|
|
1598
|
+
if (enumValues.length > 0) return {
|
|
1599
|
+
value: enumValues.map((val) => `'${escape(val)}'`).join(" | "),
|
|
1600
|
+
imports: [],
|
|
1601
|
+
dependencies: []
|
|
1602
|
+
};
|
|
1603
|
+
}
|
|
1604
|
+
if (isString(propertyNames.const)) return {
|
|
1605
|
+
value: `'${escape(propertyNames.const)}'`,
|
|
1606
|
+
imports: [],
|
|
1607
|
+
dependencies: []
|
|
1608
|
+
};
|
|
1609
|
+
}
|
|
1610
|
+
/**
|
|
1611
|
+
* Resolve a narrowed key type from OpenAPI 3.1 propertyNames.
|
|
1612
|
+
* Supports inline enum/const and $ref string enums.
|
|
1613
|
+
*/
|
|
1614
|
+
function getPropertyNamesKeyType(item, context) {
|
|
1615
|
+
const inlineKeyType = getPropertyNamesEnumKeyType(item);
|
|
1616
|
+
if (inlineKeyType) return inlineKeyType;
|
|
1617
|
+
const propertyNames = item.propertyNames;
|
|
1618
|
+
if (!propertyNames || !isReference(propertyNames)) return;
|
|
1619
|
+
const resolvedValue = resolveValue({
|
|
1620
|
+
schema: propertyNames,
|
|
1621
|
+
context
|
|
1729
1622
|
});
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1623
|
+
const resolvedConst = resolvedValue.originalSchema.const;
|
|
1624
|
+
const isStringConst = resolvedValue.type === "string" && isString(resolvedConst);
|
|
1625
|
+
if (!resolvedValue.isEnum && !isStringConst) return;
|
|
1626
|
+
return {
|
|
1627
|
+
value: resolvedValue.value,
|
|
1628
|
+
imports: resolvedValue.imports,
|
|
1629
|
+
dependencies: resolvedValue.dependencies
|
|
1733
1630
|
};
|
|
1734
|
-
return resolvedObject;
|
|
1735
1631
|
}
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1632
|
+
/**
|
|
1633
|
+
* Generate index signature key type based on propertyNames enum or const
|
|
1634
|
+
* Returns union type string like "'foo' | 'bar'", "'x'", or 'string' if neither
|
|
1635
|
+
*/
|
|
1636
|
+
function getIndexSignatureKey(item) {
|
|
1637
|
+
return getPropertyNamesEnumKeyType(item)?.value ?? "string";
|
|
1638
|
+
}
|
|
1639
|
+
function getPropertyNamesRecordType(item, valueType, context) {
|
|
1640
|
+
const keyType = getPropertyNamesKeyType(item, context);
|
|
1641
|
+
if (!keyType) return;
|
|
1642
|
+
return {
|
|
1643
|
+
...keyType,
|
|
1644
|
+
value: `Partial<Record<${keyType.value}, ${valueType}>>`
|
|
1645
|
+
};
|
|
1646
|
+
}
|
|
1647
|
+
/**
|
|
1648
|
+
* Return the output type from an object
|
|
1649
|
+
*
|
|
1650
|
+
* @param item item with type === "object"
|
|
1651
|
+
*/
|
|
1652
|
+
function getObject({ item, name, context, nullable, formDataContext }) {
|
|
1653
|
+
if (isReference(item)) {
|
|
1654
|
+
const { name } = getRefInfo(item.$ref, context);
|
|
1655
|
+
return {
|
|
1656
|
+
value: name + nullable,
|
|
1657
|
+
imports: [{ name }],
|
|
1658
|
+
schemas: [],
|
|
1659
|
+
isEnum: false,
|
|
1660
|
+
type: "object",
|
|
1661
|
+
isRef: true,
|
|
1662
|
+
hasReadonlyProps: item.readOnly ?? false,
|
|
1663
|
+
dependencies: [name],
|
|
1664
|
+
example: item.example,
|
|
1665
|
+
examples: resolveExampleRefs(item.examples, context)
|
|
1666
|
+
};
|
|
1667
|
+
}
|
|
1668
|
+
const schemaItem = item;
|
|
1669
|
+
const itemAllOf = schemaItem.allOf;
|
|
1670
|
+
const itemOneOf = schemaItem.oneOf;
|
|
1671
|
+
const itemAnyOf = schemaItem.anyOf;
|
|
1672
|
+
const itemType = schemaItem.type;
|
|
1673
|
+
if (itemAllOf || itemOneOf || itemAnyOf) return combineSchemas({
|
|
1674
|
+
schema: schemaItem,
|
|
1675
|
+
name,
|
|
1676
|
+
separator: itemAllOf ? "allOf" : itemOneOf ? "oneOf" : "anyOf",
|
|
1677
|
+
context,
|
|
1678
|
+
nullable,
|
|
1679
|
+
formDataContext
|
|
1680
|
+
});
|
|
1681
|
+
if (Array.isArray(itemType)) {
|
|
1682
|
+
const typeArray = itemType;
|
|
1683
|
+
const baseItem = schemaItem;
|
|
1684
|
+
return combineSchemas({
|
|
1685
|
+
schema: { anyOf: typeArray.map((type) => ({
|
|
1686
|
+
...baseItem,
|
|
1687
|
+
type
|
|
1688
|
+
})) },
|
|
1689
|
+
name,
|
|
1690
|
+
separator: "anyOf",
|
|
1691
|
+
context,
|
|
1692
|
+
nullable
|
|
1693
|
+
});
|
|
1694
|
+
}
|
|
1695
|
+
const itemProperties = schemaItem.properties;
|
|
1696
|
+
if (itemProperties && Object.entries(itemProperties).length > 0) {
|
|
1697
|
+
const entries = Object.entries(itemProperties);
|
|
1698
|
+
if (context.output.propertySortOrder === PropertySortOrder.ALPHABETICAL) entries.sort((a, b) => {
|
|
1699
|
+
return a[0].localeCompare(b[0], "en", { numeric: true });
|
|
1700
|
+
});
|
|
1701
|
+
const acc = {
|
|
1702
|
+
imports: [],
|
|
1703
|
+
schemas: [],
|
|
1704
|
+
value: "",
|
|
1705
|
+
isEnum: false,
|
|
1706
|
+
type: "object",
|
|
1707
|
+
isRef: false,
|
|
1708
|
+
hasReadonlyProps: false,
|
|
1709
|
+
useTypeAlias: false,
|
|
1710
|
+
dependencies: [],
|
|
1711
|
+
example: schemaItem.example,
|
|
1712
|
+
examples: resolveExampleRefs(schemaItem.examples, context)
|
|
1713
|
+
};
|
|
1714
|
+
const itemRequired = schemaItem.required;
|
|
1715
|
+
for (const [index, [key, schema]] of entries.entries()) {
|
|
1716
|
+
const isRequired = (Array.isArray(itemRequired) ? itemRequired : []).includes(key);
|
|
1717
|
+
let propName = "";
|
|
1718
|
+
if (name) {
|
|
1719
|
+
const isKeyStartWithUnderscore = key.startsWith("_");
|
|
1720
|
+
propName += pascal(`${isKeyStartWithUnderscore ? "_" : ""}${name}_${key}`);
|
|
1721
|
+
}
|
|
1722
|
+
const allSpecSchemas = context.spec.components?.schemas ?? {};
|
|
1723
|
+
if (Object.keys(allSpecSchemas).some((schemaName) => pascal(schemaName) === propName)) propName = propName + "Property";
|
|
1724
|
+
const propertyFormDataContext = formDataContext && !formDataContext.atPart ? {
|
|
1725
|
+
atPart: true,
|
|
1726
|
+
partContentType: formDataContext.encoding[key]?.contentType,
|
|
1727
|
+
urlEncoded: formDataContext.urlEncoded
|
|
1728
|
+
} : void 0;
|
|
1729
|
+
const resolvedValue = resolveObject({
|
|
1730
|
+
schema,
|
|
1731
|
+
propName,
|
|
1783
1732
|
context,
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
const
|
|
1733
|
+
formDataContext: propertyFormDataContext
|
|
1734
|
+
});
|
|
1735
|
+
const isReadOnly = Boolean(schemaItem.readOnly) || Boolean(schema.readOnly);
|
|
1736
|
+
if (!index) acc.value += "{";
|
|
1737
|
+
const doc = jsDoc(schema, true, context);
|
|
1738
|
+
const propertyDoc = doc ? `${doc.trimEnd().split("\n").map((line) => ` ${line}`).join("\n")}\n` : "";
|
|
1739
|
+
if (isReadOnly || resolvedValue.hasReadonlyProps) acc.hasReadonlyProps = true;
|
|
1740
|
+
const constValue = "const" in schema ? schema.const : void 0;
|
|
1741
|
+
const hasConst = constValue !== void 0;
|
|
1742
|
+
let constLiteral;
|
|
1743
|
+
if (!hasConst) constLiteral = void 0;
|
|
1744
|
+
else if (isString(constValue)) constLiteral = `'${escape(constValue)}'`;
|
|
1745
|
+
else constLiteral = JSON.stringify(constValue);
|
|
1746
|
+
const needsValueImport = hasConst && (resolvedValue.isEnum || resolvedValue.type === "enum");
|
|
1747
|
+
const usedResolvedValue = !hasConst || needsValueImport;
|
|
1748
|
+
const aliasedImports = needsValueImport ? resolvedValue.imports.map((imp) => ({
|
|
1749
|
+
...imp,
|
|
1750
|
+
isConstant: true
|
|
1751
|
+
})) : hasConst ? [] : getAliasedImports({
|
|
1789
1752
|
name,
|
|
1790
|
-
schemaObject: mediaType.schema,
|
|
1791
1753
|
context,
|
|
1792
|
-
|
|
1793
|
-
isUrlEncoded: true,
|
|
1794
|
-
isRef: true,
|
|
1795
|
-
encoding: mediaType.encoding
|
|
1796
|
-
}) : void 0;
|
|
1797
|
-
const additionalImports = getFormDataAdditionalImports({
|
|
1798
|
-
schemaObject: mediaType.schema,
|
|
1799
|
-
context
|
|
1754
|
+
resolvedValue
|
|
1800
1755
|
});
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
imports: [{
|
|
1804
|
-
name,
|
|
1805
|
-
schemaName
|
|
1806
|
-
}, ...additionalImports],
|
|
1807
|
-
schemas: [],
|
|
1808
|
-
type: "unknown",
|
|
1809
|
-
isEnum: false,
|
|
1810
|
-
hasReadonlyProps: false,
|
|
1811
|
-
dependencies: [name],
|
|
1812
|
-
formData,
|
|
1813
|
-
formUrlEncoded,
|
|
1814
|
-
isRef: true,
|
|
1815
|
-
originalSchema: mediaType.schema,
|
|
1816
|
-
example: mediaType.example,
|
|
1817
|
-
examples: resolveExampleRefs(mediaType.examples, context),
|
|
1818
|
-
key,
|
|
1819
|
-
contentType
|
|
1820
|
-
}];
|
|
1821
|
-
}
|
|
1822
|
-
if (res.content) return Object.entries(res.content).map(([contentType, mediaType], index, arr) => {
|
|
1823
|
-
let propName = key ? pascal(name) + pascal(key) : void 0;
|
|
1824
|
-
if (propName && arr.length > 1) propName = propName + pascal(getNumberWord(index + 1));
|
|
1825
|
-
const isFormData = formDataContentTypes.has(contentType);
|
|
1826
|
-
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
1827
|
-
let effectivePropName = propName;
|
|
1828
|
-
if (mediaType.schema && isReference(mediaType.schema)) {
|
|
1829
|
-
const { imports } = resolveSchemaRef(mediaType.schema, context);
|
|
1830
|
-
if (imports[0]?.name) effectivePropName = imports[0].name;
|
|
1831
|
-
} else if ((isFormData || isFormUrlEncoded) && mediaType.schema) {
|
|
1832
|
-
const combinedRefs = getSchemaOneOf(mediaType.schema) ?? getSchemaAnyOf(mediaType.schema);
|
|
1833
|
-
if (combinedRefs) {
|
|
1834
|
-
const names = [];
|
|
1835
|
-
for (const ref of combinedRefs) {
|
|
1836
|
-
if (!isReference(ref)) continue;
|
|
1837
|
-
const refName = resolveSchemaRef(ref, context).imports[0]?.name;
|
|
1838
|
-
if (refName) names.push(refName);
|
|
1839
|
-
}
|
|
1840
|
-
if (names.length > 0) effectivePropName = names.join("");
|
|
1841
|
-
}
|
|
1842
|
-
}
|
|
1843
|
-
const resolvedValue = getResReqContentTypes({
|
|
1844
|
-
mediaType,
|
|
1845
|
-
propName: effectivePropName,
|
|
1756
|
+
if (aliasedImports.length > 0) acc.imports.push(...aliasedImports);
|
|
1757
|
+
const alias = getImportAliasForRefOrValue({
|
|
1846
1758
|
context,
|
|
1847
|
-
|
|
1848
|
-
|
|
1759
|
+
resolvedValue,
|
|
1760
|
+
imports: aliasedImports
|
|
1849
1761
|
});
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1762
|
+
const propValue = needsValueImport ? alias : constLiteral ?? alias;
|
|
1763
|
+
const finalPropValue = isRequired ? propValue : context.output.override.useNullForOptional === true ? `${propValue} | null` : propValue;
|
|
1764
|
+
acc.value += `\n${propertyDoc}${isReadOnly && !context.output.override.suppressReadonlyModifier ? " readonly " : " "}${getKey(key)}${isRequired ? "" : "?"}: ${finalPropValue};`;
|
|
1765
|
+
if (usedResolvedValue) {
|
|
1766
|
+
acc.schemas.push(...resolvedValue.schemas);
|
|
1767
|
+
acc.dependencies.push(...resolvedValue.dependencies);
|
|
1768
|
+
}
|
|
1769
|
+
if (entries.length - 1 === index) {
|
|
1770
|
+
const additionalProps = schemaItem.additionalProperties;
|
|
1771
|
+
if (additionalProps) if (additionalProps === true) {
|
|
1772
|
+
const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
|
|
1773
|
+
if (recordType) {
|
|
1774
|
+
acc.value += "\n}";
|
|
1775
|
+
acc.value += ` & ${recordType.value}`;
|
|
1776
|
+
acc.useTypeAlias = true;
|
|
1777
|
+
acc.imports.push(...recordType.imports);
|
|
1778
|
+
acc.dependencies.push(...recordType.dependencies);
|
|
1779
|
+
} else {
|
|
1780
|
+
const keyType = getIndexSignatureKey(schemaItem);
|
|
1781
|
+
acc.value += `\n [key: ${keyType}]: unknown;\n }`;
|
|
1782
|
+
}
|
|
1783
|
+
} else {
|
|
1784
|
+
const resolvedValue = resolveValue({
|
|
1785
|
+
schema: additionalProps,
|
|
1786
|
+
name,
|
|
1787
|
+
context
|
|
1788
|
+
});
|
|
1789
|
+
const recordType = getPropertyNamesRecordType(schemaItem, resolvedValue.value, context);
|
|
1790
|
+
if (recordType) {
|
|
1791
|
+
acc.value += "\n}";
|
|
1792
|
+
acc.value += ` & ${recordType.value}`;
|
|
1793
|
+
acc.useTypeAlias = true;
|
|
1794
|
+
acc.imports.push(...recordType.imports);
|
|
1795
|
+
acc.dependencies.push(...recordType.dependencies);
|
|
1796
|
+
} else {
|
|
1797
|
+
const keyType = getIndexSignatureKey(schemaItem);
|
|
1798
|
+
acc.value += `\n [key: ${keyType}]: ${resolvedValue.value};\n}`;
|
|
1799
|
+
}
|
|
1800
|
+
acc.imports.push(...resolvedValue.imports);
|
|
1801
|
+
acc.schemas.push(...resolvedValue.schemas);
|
|
1802
|
+
acc.dependencies.push(...resolvedValue.dependencies);
|
|
1803
|
+
}
|
|
1804
|
+
else acc.value += "\n}";
|
|
1805
|
+
acc.value += nullable;
|
|
1863
1806
|
}
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1807
|
+
}
|
|
1808
|
+
return acc;
|
|
1809
|
+
}
|
|
1810
|
+
const outerAdditionalProps = schemaItem.additionalProperties;
|
|
1811
|
+
const readOnlyFlag = schemaItem.readOnly;
|
|
1812
|
+
if (outerAdditionalProps) {
|
|
1813
|
+
if (outerAdditionalProps === true) {
|
|
1814
|
+
const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
|
|
1815
|
+
if (recordType) return {
|
|
1816
|
+
value: recordType.value + nullable,
|
|
1817
|
+
imports: recordType.imports,
|
|
1818
|
+
schemas: [],
|
|
1819
|
+
isEnum: false,
|
|
1820
|
+
type: "object",
|
|
1821
|
+
isRef: false,
|
|
1822
|
+
hasReadonlyProps: readOnlyFlag ?? false,
|
|
1823
|
+
useTypeAlias: true,
|
|
1824
|
+
dependencies: recordType.dependencies
|
|
1871
1825
|
};
|
|
1872
|
-
const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
|
|
1873
|
-
name: effectivePropName,
|
|
1874
|
-
schemaObject: mediaType.schema,
|
|
1875
|
-
context,
|
|
1876
|
-
isRequestBodyOptional: res.required !== true,
|
|
1877
|
-
isRef: true,
|
|
1878
|
-
encoding: mediaType.encoding
|
|
1879
|
-
}) : void 0;
|
|
1880
|
-
const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
|
|
1881
|
-
name: effectivePropName,
|
|
1882
|
-
schemaObject: mediaType.schema,
|
|
1883
|
-
context,
|
|
1884
|
-
isUrlEncoded: true,
|
|
1885
|
-
isRequestBodyOptional: res.required !== true,
|
|
1886
|
-
isRef: true,
|
|
1887
|
-
encoding: mediaType.encoding
|
|
1888
|
-
}) : void 0;
|
|
1889
|
-
const additionalImports = getFormDataAdditionalImports({
|
|
1890
|
-
schemaObject: mediaType.schema,
|
|
1891
|
-
context
|
|
1892
|
-
});
|
|
1893
1826
|
return {
|
|
1894
|
-
|
|
1895
|
-
imports: [
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1827
|
+
value: `{ [key: ${getIndexSignatureKey(schemaItem)}]: unknown }` + nullable,
|
|
1828
|
+
imports: [],
|
|
1829
|
+
schemas: [],
|
|
1830
|
+
isEnum: false,
|
|
1831
|
+
type: "object",
|
|
1832
|
+
isRef: false,
|
|
1833
|
+
hasReadonlyProps: readOnlyFlag ?? false,
|
|
1834
|
+
useTypeAlias: false,
|
|
1835
|
+
dependencies: []
|
|
1901
1836
|
};
|
|
1902
|
-
}
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1837
|
+
}
|
|
1838
|
+
const resolvedValue = resolveValue({
|
|
1839
|
+
schema: outerAdditionalProps,
|
|
1840
|
+
name,
|
|
1841
|
+
context
|
|
1842
|
+
});
|
|
1843
|
+
const recordType = getPropertyNamesRecordType(schemaItem, resolvedValue.value, context);
|
|
1844
|
+
if (recordType) return {
|
|
1845
|
+
value: recordType.value + nullable,
|
|
1846
|
+
imports: [...recordType.imports, ...resolvedValue.imports],
|
|
1847
|
+
schemas: resolvedValue.schemas,
|
|
1848
|
+
isEnum: false,
|
|
1849
|
+
type: "object",
|
|
1850
|
+
isRef: false,
|
|
1851
|
+
hasReadonlyProps: resolvedValue.hasReadonlyProps,
|
|
1852
|
+
useTypeAlias: true,
|
|
1853
|
+
dependencies: [...recordType.dependencies, ...resolvedValue.dependencies]
|
|
1854
|
+
};
|
|
1855
|
+
return {
|
|
1856
|
+
value: `{[key: ${getIndexSignatureKey(schemaItem)}]: ${resolvedValue.value}}` + nullable,
|
|
1857
|
+
imports: resolvedValue.imports,
|
|
1858
|
+
schemas: resolvedValue.schemas,
|
|
1859
|
+
isEnum: false,
|
|
1860
|
+
type: "object",
|
|
1861
|
+
isRef: false,
|
|
1862
|
+
hasReadonlyProps: resolvedValue.hasReadonlyProps,
|
|
1863
|
+
useTypeAlias: false,
|
|
1864
|
+
dependencies: resolvedValue.dependencies
|
|
1865
|
+
};
|
|
1866
|
+
}
|
|
1867
|
+
const constValue = schemaItem.const;
|
|
1868
|
+
if (constValue !== void 0) {
|
|
1869
|
+
let type;
|
|
1870
|
+
if (Array.isArray(constValue)) type = "array";
|
|
1871
|
+
else if (constValue === null) type = "null";
|
|
1872
|
+
else if (typeof constValue === "string") type = "string";
|
|
1873
|
+
else if (typeof constValue === "number") type = "number";
|
|
1874
|
+
else if (typeof constValue === "boolean") type = "boolean";
|
|
1875
|
+
else type = "object";
|
|
1876
|
+
return {
|
|
1877
|
+
value: typeof constValue === "string" ? `'${escape(constValue)}'` : JSON.stringify(constValue),
|
|
1918
1878
|
imports: [],
|
|
1919
1879
|
schemas: [],
|
|
1920
|
-
type: defaultType,
|
|
1921
1880
|
isEnum: false,
|
|
1922
|
-
|
|
1923
|
-
key,
|
|
1881
|
+
type,
|
|
1924
1882
|
isRef: false,
|
|
1925
|
-
hasReadonlyProps: false,
|
|
1926
|
-
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1883
|
+
hasReadonlyProps: readOnlyFlag ?? false,
|
|
1884
|
+
dependencies: []
|
|
1885
|
+
};
|
|
1886
|
+
}
|
|
1887
|
+
const keyType = itemType === "object" ? getIndexSignatureKey(schemaItem) : "string";
|
|
1888
|
+
const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
|
|
1889
|
+
if (itemType === "object" && recordType) return {
|
|
1890
|
+
value: recordType.value + nullable,
|
|
1891
|
+
imports: recordType.imports,
|
|
1892
|
+
schemas: [],
|
|
1893
|
+
isEnum: false,
|
|
1894
|
+
type: "object",
|
|
1895
|
+
isRef: false,
|
|
1896
|
+
hasReadonlyProps: readOnlyFlag ?? false,
|
|
1897
|
+
useTypeAlias: true,
|
|
1898
|
+
dependencies: recordType.dependencies
|
|
1899
|
+
};
|
|
1900
|
+
return {
|
|
1901
|
+
value: (itemType === "object" ? `{ [key: ${keyType}]: unknown }` : "unknown") + nullable,
|
|
1902
|
+
imports: [],
|
|
1903
|
+
schemas: [],
|
|
1904
|
+
isEnum: false,
|
|
1905
|
+
type: "object",
|
|
1906
|
+
isRef: false,
|
|
1907
|
+
hasReadonlyProps: readOnlyFlag ?? false,
|
|
1908
|
+
useTypeAlias: false,
|
|
1909
|
+
dependencies: []
|
|
1910
|
+
};
|
|
1952
1911
|
}
|
|
1912
|
+
//#endregion
|
|
1913
|
+
//#region src/getters/scalar.ts
|
|
1953
1914
|
/**
|
|
1954
|
-
*
|
|
1955
|
-
*
|
|
1915
|
+
* Returns true when a schema describes a raw binary string scalar — i.e. one
|
|
1916
|
+
* that getScalar's `case 'string':` branch would coerce to `Blob` outside a
|
|
1917
|
+
* url-encoded context (see the formDataContext.urlEncoded gate below). Shared
|
|
1918
|
+
* with resolveValue so the component-`$ref` urlEncoded short-circuit and the
|
|
1919
|
+
* inline scalar path stay in lockstep when new binary shapes are added
|
|
1920
|
+
* (#1624 / #3395 / #2410).
|
|
1956
1921
|
*
|
|
1957
|
-
*
|
|
1958
|
-
*
|
|
1959
|
-
*/
|
|
1960
|
-
function
|
|
1961
|
-
|
|
1962
|
-
if (
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
function
|
|
1975
|
-
const
|
|
1976
|
-
const
|
|
1977
|
-
const
|
|
1978
|
-
|
|
1979
|
-
const
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
form += ` ${variableName}.append(key, new Blob([Uint8Array.from(value)]));\n`;
|
|
2003
|
-
form += ` } else if (Array.isArray(value)) {\n`;
|
|
2004
|
-
form += ` value.forEach(v => {\n`;
|
|
2005
|
-
form += ` if ((typeof File !== 'undefined' && v instanceof File) || v instanceof Blob) {\n`;
|
|
2006
|
-
form += ` ${variableName}.append(key, v);\n`;
|
|
2007
|
-
form += ` } else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(v)) {\n`;
|
|
2008
|
-
form += ` ${variableName}.append(key, new Blob([Uint8Array.from(v)]));\n`;
|
|
2009
|
-
form += ` } else {\n`;
|
|
2010
|
-
form += ` ${variableName}.append(key, typeof v === 'object' ? JSON.stringify(v) : String(v));\n`;
|
|
2011
|
-
form += ` }\n`;
|
|
2012
|
-
form += ` });\n`;
|
|
2013
|
-
form += ` } else if (typeof value === 'object') {\n`;
|
|
2014
|
-
form += ` ${variableName}.append(key, JSON.stringify(value));\n`;
|
|
2015
|
-
form += ` } else {\n`;
|
|
2016
|
-
form += ` ${variableName}.append(key, String(value));\n`;
|
|
2017
|
-
form += ` }\n`;
|
|
1922
|
+
* Accepts OAS 3.1 nullable unions (`type: ['string', 'null']`) since getScalar
|
|
1923
|
+
* normalizes those into `case 'string':` before invoking this predicate.
|
|
1924
|
+
*/
|
|
1925
|
+
function isBinaryScalarSchema(schema) {
|
|
1926
|
+
const schemaType = schema.type;
|
|
1927
|
+
if (!(schemaType === "string" || isArray(schemaType) && schemaType.includes("string") && schemaType.every((type) => type === "string" || type === "null"))) return false;
|
|
1928
|
+
if (schema.format === "binary") return true;
|
|
1929
|
+
const contentMediaType = schema.contentMediaType;
|
|
1930
|
+
const contentEncoding = schema.contentEncoding;
|
|
1931
|
+
return contentMediaType === "application/octet-stream" && !contentEncoding;
|
|
1932
|
+
}
|
|
1933
|
+
/**
|
|
1934
|
+
* Return the typescript equivalent of open-api data type
|
|
1935
|
+
*
|
|
1936
|
+
* @param item
|
|
1937
|
+
* @ref https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.1.md#data-types
|
|
1938
|
+
*/
|
|
1939
|
+
function getScalar({ item, name, context, formDataContext }) {
|
|
1940
|
+
const schemaEnum = item.enum;
|
|
1941
|
+
const schemaType = item.type;
|
|
1942
|
+
const schemaReadOnly = item.readOnly;
|
|
1943
|
+
const schemaExample = item.example;
|
|
1944
|
+
const schemaExamples = item.examples;
|
|
1945
|
+
const schemaConst = item.const;
|
|
1946
|
+
const schemaFormat = item.format;
|
|
1947
|
+
const schemaNullable = item.nullable;
|
|
1948
|
+
const nullable = isArray(schemaType) && schemaType.includes("null") || schemaNullable === true ? " | null" : "";
|
|
1949
|
+
const enumItems = schemaEnum?.filter((enumItem) => enumItem !== null);
|
|
1950
|
+
let itemType = schemaType;
|
|
1951
|
+
if (!itemType && item.items) {
|
|
1952
|
+
item.type = "array";
|
|
1953
|
+
itemType = "array";
|
|
1954
|
+
}
|
|
1955
|
+
if (isArray(schemaType) && schemaType.includes("null")) {
|
|
1956
|
+
const typesWithoutNull = schemaType.filter((x) => x !== "null");
|
|
1957
|
+
itemType = typesWithoutNull.length === 1 ? typesWithoutNull[0] : typesWithoutNull;
|
|
1958
|
+
}
|
|
1959
|
+
switch (itemType) {
|
|
1960
|
+
case "number":
|
|
1961
|
+
case "integer": {
|
|
1962
|
+
let value = context.output.override.useBigInt && (schemaFormat === "int64" || schemaFormat === "uint64") ? "bigint" : "number";
|
|
1963
|
+
let isEnum = false;
|
|
1964
|
+
if (enumItems) {
|
|
1965
|
+
value = enumItems.map((enumItem) => `${enumItem}`).join(" | ");
|
|
1966
|
+
isEnum = true;
|
|
2018
1967
|
}
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
}
|
|
2033
|
-
form += combinedSchemasFormData;
|
|
1968
|
+
value += nullable;
|
|
1969
|
+
if (schemaConst !== void 0) value = schemaConst;
|
|
1970
|
+
return {
|
|
1971
|
+
value,
|
|
1972
|
+
isEnum,
|
|
1973
|
+
type: "number",
|
|
1974
|
+
schemas: [],
|
|
1975
|
+
imports: [],
|
|
1976
|
+
isRef: false,
|
|
1977
|
+
hasReadonlyProps: schemaReadOnly ?? false,
|
|
1978
|
+
dependencies: [],
|
|
1979
|
+
example: schemaExample,
|
|
1980
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
1981
|
+
};
|
|
2034
1982
|
}
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
1983
|
+
case "boolean": {
|
|
1984
|
+
let value = "boolean";
|
|
1985
|
+
if (enumItems && !(enumItems.includes(true) && enumItems.includes(false))) value = enumItems.map((enumItem) => `${enumItem}`).join(" | ");
|
|
1986
|
+
value += nullable;
|
|
1987
|
+
if (schemaConst !== void 0) value = schemaConst;
|
|
1988
|
+
return {
|
|
1989
|
+
value,
|
|
1990
|
+
type: "boolean",
|
|
1991
|
+
isEnum: false,
|
|
1992
|
+
schemas: [],
|
|
1993
|
+
imports: [],
|
|
1994
|
+
isRef: false,
|
|
1995
|
+
hasReadonlyProps: schemaReadOnly ?? false,
|
|
1996
|
+
dependencies: [],
|
|
1997
|
+
example: schemaExample,
|
|
1998
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
1999
|
+
};
|
|
2000
|
+
}
|
|
2001
|
+
case "array": {
|
|
2002
|
+
const { value, ...rest } = getArray({
|
|
2003
|
+
schema: item,
|
|
2004
|
+
name,
|
|
2040
2005
|
context,
|
|
2041
|
-
|
|
2042
|
-
encoding
|
|
2006
|
+
formDataContext
|
|
2043
2007
|
});
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
let valueStr = "value";
|
|
2050
|
-
const schemaItems = getSchemaItems(schema);
|
|
2051
|
-
if (schemaItems) {
|
|
2052
|
-
const { schema: itemSchema } = resolveSchemaRef(schemaItems, context);
|
|
2053
|
-
if (itemSchema.type === "object" || itemSchema.type === "array") valueStr = "JSON.stringify(value)";
|
|
2054
|
-
else if (itemSchema.type === "number" || itemSchema.type === "integer" || itemSchema.type === "boolean") valueStr = "value.toString()";
|
|
2008
|
+
return {
|
|
2009
|
+
value: value + nullable,
|
|
2010
|
+
...rest,
|
|
2011
|
+
dependencies: rest.dependencies
|
|
2012
|
+
};
|
|
2055
2013
|
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
}
|
|
2061
|
-
|
|
2062
|
-
let formDataValues = "";
|
|
2063
|
-
const isUrlEncoded = variableName === "formUrlEncoded";
|
|
2064
|
-
const schemaProps = getSchemaProperties(schema) ?? {};
|
|
2065
|
-
for (const [key, value] of Object.entries(schemaProps)) {
|
|
2066
|
-
const { schema: property } = resolveSchemaRef(value, context);
|
|
2067
|
-
if (property.readOnly) continue;
|
|
2068
|
-
let formDataValue = "";
|
|
2069
|
-
const partContentType = (depth === 0 ? encoding?.[key] : void 0)?.contentType;
|
|
2070
|
-
const formattedKeyPrefix = isRequestBodyOptional ? keyword.isIdentifierNameES5(key) ? "?" : "?." : "";
|
|
2071
|
-
const formattedKey = keyword.isIdentifierNameES5(key) ? `.${key}` : `['${key}']`;
|
|
2072
|
-
const valueKey = `${propName}${formattedKeyPrefix}${formattedKey}`;
|
|
2073
|
-
const nonOptionalValueKey = `${propName}${formattedKey}`;
|
|
2074
|
-
const fileType = getFormDataFieldFileType(property, partContentType);
|
|
2075
|
-
const effectiveContentType = partContentType ?? property.contentMediaType;
|
|
2076
|
-
if (isUrlEncoded && (fileType || property.format === "binary")) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
2077
|
-
else if (fileType === "binary" || property.format === "binary") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
2078
|
-
else if (fileType === "text") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey} instanceof Blob ? ${nonOptionalValueKey} : new Blob([${nonOptionalValueKey}], { type: '${effectiveContentType}' }));\n`;
|
|
2079
|
-
else if (property.type === "object") formDataValue = context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE ? resolveSchemaPropertiesToFormData({
|
|
2080
|
-
schema: property,
|
|
2081
|
-
variableName,
|
|
2082
|
-
propName: nonOptionalValueKey,
|
|
2083
|
-
context,
|
|
2084
|
-
isRequestBodyOptional,
|
|
2085
|
-
keyPrefix: `${keyPrefix}${key}.`,
|
|
2086
|
-
depth: depth + 1,
|
|
2087
|
-
encoding
|
|
2088
|
-
}) : `${variableName}.append(\`${keyPrefix}${key}\`, JSON.stringify(${nonOptionalValueKey}));\n`;
|
|
2089
|
-
else if (property.type === "array") {
|
|
2090
|
-
let valueStr = "value";
|
|
2091
|
-
let hasNonPrimitiveChild = false;
|
|
2092
|
-
const propertyItems = getSchemaItems(property);
|
|
2093
|
-
if (propertyItems) {
|
|
2094
|
-
const { schema: itemSchema } = resolveSchemaRef(propertyItems, context);
|
|
2095
|
-
if (itemSchema.type === "object" || itemSchema.type === "array") if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
|
|
2096
|
-
hasNonPrimitiveChild = true;
|
|
2097
|
-
const resolvedValue = resolveSchemaPropertiesToFormData({
|
|
2098
|
-
schema: itemSchema,
|
|
2099
|
-
variableName,
|
|
2100
|
-
propName: "value",
|
|
2101
|
-
context,
|
|
2102
|
-
isRequestBodyOptional,
|
|
2103
|
-
keyPrefix: `${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}].`,
|
|
2104
|
-
depth: depth + 1
|
|
2105
|
-
});
|
|
2106
|
-
formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => {
|
|
2107
|
-
${resolvedValue}});\n`;
|
|
2108
|
-
} else valueStr = "JSON.stringify(value)";
|
|
2109
|
-
else {
|
|
2110
|
-
const itemType = getSchemaType$1(itemSchema);
|
|
2111
|
-
if (itemType === "number" || Array.isArray(itemType) && itemType.includes("number") || itemType === "integer" || Array.isArray(itemType) && itemType.includes("integer") || itemType === "boolean" || Array.isArray(itemType) && itemType.includes("boolean")) valueStr = "value.toString()";
|
|
2112
|
-
}
|
|
2014
|
+
case "string": {
|
|
2015
|
+
let value = "string";
|
|
2016
|
+
let isEnum = false;
|
|
2017
|
+
if (enumItems) {
|
|
2018
|
+
value = enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
|
|
2019
|
+
isEnum = true;
|
|
2113
2020
|
}
|
|
2114
|
-
if (
|
|
2115
|
-
if (
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
})()) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
2121
|
-
else formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
2122
|
-
let existSubSchemaNullable = false;
|
|
2123
|
-
const combine = getSchemaCombined(property);
|
|
2124
|
-
if (combine) {
|
|
2125
|
-
const subSchemas = combine.map((c) => resolveObject({
|
|
2126
|
-
schema: c,
|
|
2127
|
-
combined: true,
|
|
2128
|
-
context
|
|
2129
|
-
}));
|
|
2130
|
-
if (subSchemas.some((subSchema) => {
|
|
2131
|
-
return [
|
|
2132
|
-
"number",
|
|
2133
|
-
"integer",
|
|
2134
|
-
"boolean"
|
|
2135
|
-
].includes(subSchema.type);
|
|
2136
|
-
})) formDataValue = `${variableName}.append(\`${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
2137
|
-
if (subSchemas.some((subSchema) => {
|
|
2138
|
-
return subSchema.type === "null";
|
|
2139
|
-
})) existSubSchemaNullable = true;
|
|
2140
|
-
}
|
|
2141
|
-
const isRequired = getSchemaRequired(schema)?.includes(key) && !isRequestBodyOptional;
|
|
2142
|
-
const propType = getSchemaType$1(property);
|
|
2143
|
-
if (property.nullable || Array.isArray(propType) && propType.includes("null") || existSubSchemaNullable) {
|
|
2144
|
-
if (isRequired) {
|
|
2145
|
-
formDataValues += `if(${valueKey} !== null) {\n ${formDataValue} }\n`;
|
|
2146
|
-
continue;
|
|
2021
|
+
if (!formDataContext?.urlEncoded) {
|
|
2022
|
+
if (schemaFormat === "binary") value = "Blob";
|
|
2023
|
+
else if (formDataContext?.atPart) {
|
|
2024
|
+
const fileType = getFormDataFieldFileType(item, formDataContext.partContentType);
|
|
2025
|
+
if (fileType) value = fileType === "binary" ? "Blob" : "Blob | string";
|
|
2026
|
+
} else if (isBinaryScalarSchema(item)) value = "Blob";
|
|
2147
2027
|
}
|
|
2148
|
-
|
|
2149
|
-
|
|
2028
|
+
if (context.output.override.useDates && (schemaFormat === "date" || schemaFormat === "date-time")) value = "Date";
|
|
2029
|
+
value += nullable;
|
|
2030
|
+
if (schemaConst) value = `'${schemaConst}'`;
|
|
2031
|
+
return {
|
|
2032
|
+
value,
|
|
2033
|
+
isEnum,
|
|
2034
|
+
type: "string",
|
|
2035
|
+
imports: [],
|
|
2036
|
+
schemas: [],
|
|
2037
|
+
isRef: false,
|
|
2038
|
+
hasReadonlyProps: schemaReadOnly ?? false,
|
|
2039
|
+
dependencies: [],
|
|
2040
|
+
example: schemaExample,
|
|
2041
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
2042
|
+
};
|
|
2150
2043
|
}
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2044
|
+
case "null": return {
|
|
2045
|
+
value: "null",
|
|
2046
|
+
isEnum: false,
|
|
2047
|
+
type: "null",
|
|
2048
|
+
imports: [],
|
|
2049
|
+
schemas: [],
|
|
2050
|
+
isRef: false,
|
|
2051
|
+
hasReadonlyProps: schemaReadOnly ?? false,
|
|
2052
|
+
dependencies: []
|
|
2053
|
+
};
|
|
2054
|
+
default: {
|
|
2055
|
+
if (isArray(itemType)) return combineSchemas({
|
|
2056
|
+
schema: { anyOf: itemType.map((type) => Object.assign({}, item, { type })) },
|
|
2057
|
+
name,
|
|
2058
|
+
separator: "anyOf",
|
|
2059
|
+
context,
|
|
2060
|
+
nullable
|
|
2061
|
+
});
|
|
2062
|
+
if (enumItems) return {
|
|
2063
|
+
value: enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : String(enumItem)).filter(Boolean).join(` | `) + nullable,
|
|
2064
|
+
isEnum: true,
|
|
2065
|
+
type: "string",
|
|
2066
|
+
imports: [],
|
|
2067
|
+
schemas: [],
|
|
2068
|
+
isRef: false,
|
|
2069
|
+
hasReadonlyProps: schemaReadOnly ?? false,
|
|
2070
|
+
dependencies: [],
|
|
2071
|
+
example: schemaExample,
|
|
2072
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
2073
|
+
};
|
|
2074
|
+
const hasCombiners = item.allOf ?? item.anyOf ?? item.oneOf;
|
|
2075
|
+
const { value, ...rest } = getObject({
|
|
2076
|
+
item,
|
|
2077
|
+
name,
|
|
2078
|
+
context,
|
|
2079
|
+
nullable,
|
|
2080
|
+
formDataContext: formDataContext?.atPart === false || formDataContext?.atPart && hasCombiners ? formDataContext : void 0
|
|
2081
|
+
});
|
|
2082
|
+
return {
|
|
2083
|
+
value,
|
|
2084
|
+
...rest
|
|
2085
|
+
};
|
|
2154
2086
|
}
|
|
2155
|
-
formDataValues += `if(${valueKey} !== undefined) {\n ${formDataValue} }\n`;
|
|
2156
2087
|
}
|
|
2157
|
-
return formDataValues;
|
|
2158
2088
|
}
|
|
2159
2089
|
//#endregion
|
|
2160
|
-
//#region src/
|
|
2161
|
-
|
|
2162
|
-
const imports = filteredBodyTypes.flatMap(({ imports }) => imports);
|
|
2163
|
-
const schemas = filteredBodyTypes.flatMap(({ schemas }) => schemas);
|
|
2164
|
-
const definition = filteredBodyTypes.map(({ value }) => value).join(" | ");
|
|
2165
|
-
const nonReadonlyDefinition = filteredBodyTypes.some((x) => x.hasReadonlyProps) && definition && context.output.override.preserveReadonlyRequestBodies !== "preserve" ? `NonReadonly<${definition}>` : definition;
|
|
2166
|
-
let implementation = generalJSTypesWithArray.includes(definition.toLowerCase()) || filteredBodyTypes.length > 1 ? camel(operationName) + context.output.override.components.requestBodies.suffix : camel(definition);
|
|
2167
|
-
let isOptional = false;
|
|
2168
|
-
if (implementation) {
|
|
2169
|
-
implementation = sanitize(implementation, {
|
|
2170
|
-
underscore: "_",
|
|
2171
|
-
whitespace: "_",
|
|
2172
|
-
dash: true,
|
|
2173
|
-
es5keyword: true,
|
|
2174
|
-
es5IdentifierName: true
|
|
2175
|
-
});
|
|
2176
|
-
if (isReference(requestBody)) {
|
|
2177
|
-
const { schema: bodySchema } = resolveRef(requestBody, context);
|
|
2178
|
-
isOptional = bodySchema.required !== true;
|
|
2179
|
-
} else isOptional = requestBody.required !== true;
|
|
2180
|
-
}
|
|
2181
|
-
return {
|
|
2182
|
-
originalSchema: requestBody,
|
|
2183
|
-
definition: nonReadonlyDefinition,
|
|
2184
|
-
implementation,
|
|
2185
|
-
imports,
|
|
2186
|
-
schemas,
|
|
2187
|
-
isOptional,
|
|
2188
|
-
...filteredBodyTypes.length === 1 ? {
|
|
2189
|
-
formData: filteredBodyTypes[0].formData,
|
|
2190
|
-
formUrlEncoded: filteredBodyTypes[0].formUrlEncoded,
|
|
2191
|
-
contentType: filteredBodyTypes[0].contentType
|
|
2192
|
-
} : {
|
|
2193
|
-
formData: "",
|
|
2194
|
-
formUrlEncoded: "",
|
|
2195
|
-
contentType: ""
|
|
2196
|
-
}
|
|
2197
|
-
};
|
|
2198
|
-
}
|
|
2199
|
-
function getBody({ requestBody, operationName, context, contentType }) {
|
|
2200
|
-
return buildBody(filterByContentType(getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context), contentType), requestBody, operationName, context);
|
|
2201
|
-
}
|
|
2090
|
+
//#region src/resolvers/ref.ts
|
|
2091
|
+
const REF_NOT_FOUND_PREFIX = "Oops... 🍻. Ref not found";
|
|
2202
2092
|
/**
|
|
2203
|
-
*
|
|
2204
|
-
*
|
|
2093
|
+
* Recursively resolves a `$ref` in an OpenAPI document, following
|
|
2094
|
+
* nested schema refs and collecting imports along the way.
|
|
2095
|
+
*
|
|
2096
|
+
* Handles OpenAPI 3.0 `nullable` and 3.1 type-array hints on direct refs.
|
|
2097
|
+
*
|
|
2098
|
+
* @see https://spec.openapis.org/oas/v3.0.3#reference-object
|
|
2099
|
+
* @see https://spec.openapis.org/oas/v3.1.0#reference-object
|
|
2205
2100
|
*/
|
|
2206
|
-
function
|
|
2207
|
-
const
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2101
|
+
function resolveRef(schema, context, imports = []) {
|
|
2102
|
+
const refPath = "$ref" in schema ? schema.$ref : void 0;
|
|
2103
|
+
const nestedSchema = "schema" in schema ? schema.schema : void 0;
|
|
2104
|
+
if (isObject(nestedSchema) && isReference(nestedSchema) && typeof nestedSchema.$ref === "string") {
|
|
2105
|
+
const resolvedRef = resolveRef(nestedSchema, context, imports);
|
|
2106
|
+
if ("examples" in schema) {
|
|
2107
|
+
const schemaWithExamples = schema;
|
|
2108
|
+
schemaWithExamples.examples = resolveExampleRefs(schemaWithExamples.examples, context);
|
|
2109
|
+
}
|
|
2110
|
+
if ("examples" in resolvedRef.schema) {
|
|
2111
|
+
const resolvedWithExamples = resolvedRef.schema;
|
|
2112
|
+
resolvedWithExamples.examples = resolveExampleRefs(resolvedWithExamples.examples, context);
|
|
2113
|
+
}
|
|
2214
2114
|
return {
|
|
2215
|
-
|
|
2216
|
-
|
|
2115
|
+
schema: {
|
|
2116
|
+
...schema,
|
|
2117
|
+
schema: resolvedRef.schema
|
|
2118
|
+
},
|
|
2119
|
+
imports: resolvedRef.imports
|
|
2217
2120
|
};
|
|
2218
|
-
}
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
"text/plain": "Text",
|
|
2225
|
-
"application/xml": "Xml",
|
|
2226
|
-
"text/xml": "Xml",
|
|
2227
|
-
"application/octet-stream": "Blob"
|
|
2228
|
-
};
|
|
2229
|
-
function getContentTypeSuffix(contentType) {
|
|
2230
|
-
if (CONTENT_TYPE_SUFFIX_MAP[contentType]) return CONTENT_TYPE_SUFFIX_MAP[contentType];
|
|
2231
|
-
return (contentType.split("/")[1] ?? contentType).split(/[-+.]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
2232
|
-
}
|
|
2233
|
-
//#endregion
|
|
2234
|
-
//#region src/getters/imports.ts
|
|
2235
|
-
function getAliasedImports({ name, resolvedValue, context }) {
|
|
2236
|
-
return context.output.schemas && resolvedValue.isRef ? resolvedValue.imports.map((imp) => {
|
|
2237
|
-
if (!needCreateImportAlias({
|
|
2238
|
-
name,
|
|
2239
|
-
imp
|
|
2240
|
-
})) return imp;
|
|
2121
|
+
}
|
|
2122
|
+
if (isDereferenced(schema)) {
|
|
2123
|
+
if ("examples" in schema) {
|
|
2124
|
+
const schemaWithExamples = schema;
|
|
2125
|
+
schemaWithExamples.examples = resolveExampleRefs(schemaWithExamples.examples, context);
|
|
2126
|
+
}
|
|
2241
2127
|
return {
|
|
2242
|
-
|
|
2243
|
-
|
|
2128
|
+
schema,
|
|
2129
|
+
imports
|
|
2244
2130
|
};
|
|
2245
|
-
}
|
|
2246
|
-
}
|
|
2247
|
-
|
|
2248
|
-
|
|
2131
|
+
}
|
|
2132
|
+
if (!refPath) throw new Error(`${REF_NOT_FOUND_PREFIX}: missing $ref`);
|
|
2133
|
+
const { currentSchema, refInfo: { name, originalName } } = getSchema$1(schema, context);
|
|
2134
|
+
if (!currentSchema) throw new Error(`${REF_NOT_FOUND_PREFIX}: ${refPath}`);
|
|
2135
|
+
return resolveRef(currentSchema, { ...context }, [...imports, {
|
|
2136
|
+
name,
|
|
2137
|
+
schemaName: originalName
|
|
2138
|
+
}]);
|
|
2249
2139
|
}
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2140
|
+
/**
|
|
2141
|
+
* Looks up a schema by its `$ref` path in the spec, applying suffix resolution.
|
|
2142
|
+
*
|
|
2143
|
+
* Preserves OpenAPI 3.0 `nullable` and 3.1 type-array (`["object", "null"]`)
|
|
2144
|
+
* hints from the referencing schema onto the resolved target.
|
|
2145
|
+
*
|
|
2146
|
+
* @see https://spec.openapis.org/oas/v3.0.3#fixed-fields-18 (nullable)
|
|
2147
|
+
* @see https://spec.openapis.org/oas/v3.1.0#schema-object (type as array)
|
|
2148
|
+
*/
|
|
2149
|
+
function getSchema$1(schema, context) {
|
|
2150
|
+
if (!schema.$ref) throw new Error(`${REF_NOT_FOUND_PREFIX}: missing $ref`);
|
|
2151
|
+
const refInfo = getRefInfo(schema.$ref, context);
|
|
2152
|
+
const { refPaths } = refInfo;
|
|
2153
|
+
const schemaByRefPaths = Array.isArray(refPaths) ? prop(context.spec, ...refPaths) : void 0;
|
|
2154
|
+
if (isObject(schemaByRefPaths) && isReference(schemaByRefPaths)) return getSchema$1(schemaByRefPaths, context);
|
|
2155
|
+
let currentSchema = schemaByRefPaths;
|
|
2156
|
+
if (isObject(currentSchema) && "nullable" in schema) {
|
|
2157
|
+
const nullable = schema.nullable;
|
|
2158
|
+
currentSchema = {
|
|
2159
|
+
...currentSchema,
|
|
2160
|
+
nullable
|
|
2161
|
+
};
|
|
2162
|
+
}
|
|
2163
|
+
if (isObject(currentSchema) && "type" in schema && Array.isArray(schema.type)) {
|
|
2164
|
+
const type = schema.type;
|
|
2165
|
+
currentSchema = {
|
|
2166
|
+
...currentSchema,
|
|
2167
|
+
type
|
|
2168
|
+
};
|
|
2169
|
+
}
|
|
2170
|
+
return {
|
|
2171
|
+
currentSchema,
|
|
2172
|
+
refInfo
|
|
2173
|
+
};
|
|
2253
2174
|
}
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
return
|
|
2175
|
+
/** Recursively resolves `$ref` entries in an examples array or record. */
|
|
2176
|
+
function resolveExampleRefs(examples, context) {
|
|
2177
|
+
if (!examples) return;
|
|
2178
|
+
return Array.isArray(examples) ? examples.map((example) => {
|
|
2179
|
+
if (isObject(example) && isReference(example)) {
|
|
2180
|
+
const { schema } = resolveRef(example, context);
|
|
2181
|
+
return schema.value;
|
|
2182
|
+
}
|
|
2183
|
+
return example;
|
|
2184
|
+
}) : (() => {
|
|
2185
|
+
const result = {};
|
|
2186
|
+
for (const [key, example] of Object.entries(examples)) result[key] = isObject(example) && isReference(example) ? resolveRef(example, context).schema.value : example;
|
|
2187
|
+
return result;
|
|
2188
|
+
})();
|
|
2258
2189
|
}
|
|
2259
2190
|
//#endregion
|
|
2260
|
-
//#region src/
|
|
2261
|
-
function
|
|
2262
|
-
if (
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2191
|
+
//#region src/resolvers/value.ts
|
|
2192
|
+
function resolveValue({ schema, name, context, formDataContext }) {
|
|
2193
|
+
if (isReference(schema)) {
|
|
2194
|
+
const refValue = schema.$ref;
|
|
2195
|
+
const { schema: schemaObject, imports } = resolveRef(schema, context);
|
|
2196
|
+
if (refValue && !isComponentRef(refValue)) {
|
|
2197
|
+
if (context.parents?.includes(refValue)) return {
|
|
2198
|
+
value: "unknown",
|
|
2199
|
+
imports: [],
|
|
2200
|
+
schemas: [],
|
|
2201
|
+
type: "unknown",
|
|
2202
|
+
isEnum: false,
|
|
2203
|
+
originalSchema: schemaObject,
|
|
2204
|
+
hasReadonlyProps: false,
|
|
2205
|
+
isRef: false,
|
|
2206
|
+
dependencies: []
|
|
2207
|
+
};
|
|
2208
|
+
return {
|
|
2209
|
+
...getScalar({
|
|
2210
|
+
item: schemaObject,
|
|
2211
|
+
name,
|
|
2212
|
+
context: {
|
|
2213
|
+
...context,
|
|
2214
|
+
parents: [...context.parents ?? [], refValue]
|
|
2215
|
+
},
|
|
2216
|
+
formDataContext
|
|
2217
|
+
}),
|
|
2218
|
+
originalSchema: schemaObject,
|
|
2219
|
+
isRef: false
|
|
2220
|
+
};
|
|
2221
|
+
}
|
|
2222
|
+
if (formDataContext?.urlEncoded && isBinaryScalarSchema(schemaObject)) return {
|
|
2223
|
+
...getScalar({
|
|
2224
|
+
item: schemaObject,
|
|
2225
|
+
name,
|
|
2226
|
+
context,
|
|
2227
|
+
formDataContext
|
|
2228
|
+
}),
|
|
2229
|
+
originalSchema: schemaObject,
|
|
2230
|
+
isRef: false
|
|
2231
|
+
};
|
|
2232
|
+
const resolvedImport = imports[0];
|
|
2233
|
+
let hasReadonlyProps = false;
|
|
2234
|
+
const refName = resolvedImport.name;
|
|
2235
|
+
if (!context.parents?.includes(refName)) hasReadonlyProps = getScalar({
|
|
2236
|
+
item: schemaObject,
|
|
2237
|
+
name: refName,
|
|
2238
|
+
context: {
|
|
2239
|
+
...context,
|
|
2240
|
+
parents: [...context.parents ?? [], refName]
|
|
2241
|
+
}
|
|
2242
|
+
}).hasReadonlyProps;
|
|
2243
|
+
const isAnyOfNullable = schemaObject.anyOf?.some((anyOfItem) => !isReference(anyOfItem) && (anyOfItem.type === "null" || Array.isArray(anyOfItem.type) && anyOfItem.type.includes("null")));
|
|
2244
|
+
const schemaType = schemaObject.type;
|
|
2245
|
+
const nullable = Array.isArray(schemaType) && schemaType.includes("null") || schemaObject.nullable === true || isAnyOfNullable ? " | null" : "";
|
|
2246
|
+
return {
|
|
2247
|
+
value: resolvedImport.name + nullable,
|
|
2248
|
+
imports: [{
|
|
2249
|
+
name: resolvedImport.name,
|
|
2250
|
+
schemaName: resolvedImport.schemaName
|
|
2251
|
+
}],
|
|
2252
|
+
type: schemaObject.type ?? "object",
|
|
2253
|
+
schemas: [],
|
|
2254
|
+
isEnum: !!schemaObject.enum,
|
|
2255
|
+
originalSchema: schemaObject,
|
|
2256
|
+
hasReadonlyProps,
|
|
2257
|
+
isRef: true,
|
|
2258
|
+
dependencies: [resolvedImport.name]
|
|
2270
2259
|
};
|
|
2271
2260
|
}
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2261
|
+
return {
|
|
2262
|
+
...getScalar({
|
|
2263
|
+
item: schema,
|
|
2264
|
+
name,
|
|
2265
|
+
context,
|
|
2266
|
+
formDataContext
|
|
2267
|
+
}),
|
|
2268
|
+
originalSchema: schema,
|
|
2269
|
+
isRef: false
|
|
2276
2270
|
};
|
|
2277
2271
|
}
|
|
2272
|
+
//#endregion
|
|
2273
|
+
//#region src/resolvers/object.ts
|
|
2278
2274
|
/**
|
|
2279
|
-
*
|
|
2280
|
-
*
|
|
2275
|
+
* Wraps inline object type in a type alias.
|
|
2276
|
+
* E.g. `{ foo: string }` → value becomes `FooBody`, schema gets `export type FooBody = { foo: string };`
|
|
2281
2277
|
*/
|
|
2282
|
-
function
|
|
2283
|
-
|
|
2284
|
-
if (
|
|
2285
|
-
const
|
|
2286
|
-
if (!
|
|
2287
|
-
const
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
const
|
|
2292
|
-
const isStringConst = resolvedValue.type === "string" && isString(resolvedConst);
|
|
2293
|
-
if (!resolvedValue.isEnum && !isStringConst) return;
|
|
2278
|
+
function createTypeAliasIfNeeded({ resolvedValue, propName, context }) {
|
|
2279
|
+
if (!propName) return;
|
|
2280
|
+
if (resolvedValue.isEnum || resolvedValue.type !== "object") return;
|
|
2281
|
+
const aliasPattern = context.output.override.aliasCombinedTypes ? String.raw`{|&|\|` : "{";
|
|
2282
|
+
if (!new RegExp(aliasPattern).test(resolvedValue.value)) return;
|
|
2283
|
+
const { originalSchema } = resolvedValue;
|
|
2284
|
+
const doc = jsDoc(originalSchema);
|
|
2285
|
+
const isConstant = "const" in originalSchema;
|
|
2286
|
+
const constantIsString = "type" in originalSchema && (originalSchema.type === "string" || Array.isArray(originalSchema.type) && originalSchema.type.includes("string"));
|
|
2287
|
+
const model = isConstant ? `${doc}export const ${propName} = ${constantIsString ? `'${originalSchema.const}'` : originalSchema.const} as const;\n` : `${doc}export type ${propName} = ${resolvedValue.value};\n`;
|
|
2294
2288
|
return {
|
|
2295
|
-
value:
|
|
2296
|
-
imports:
|
|
2289
|
+
value: propName,
|
|
2290
|
+
imports: [{
|
|
2291
|
+
name: propName,
|
|
2292
|
+
isConstant
|
|
2293
|
+
}],
|
|
2294
|
+
schemas: [...resolvedValue.schemas, {
|
|
2295
|
+
name: propName,
|
|
2296
|
+
model,
|
|
2297
|
+
imports: resolvedValue.imports,
|
|
2298
|
+
dependencies: resolvedValue.dependencies
|
|
2299
|
+
}],
|
|
2300
|
+
isEnum: false,
|
|
2301
|
+
type: "object",
|
|
2302
|
+
isRef: resolvedValue.isRef,
|
|
2303
|
+
hasReadonlyProps: resolvedValue.hasReadonlyProps,
|
|
2297
2304
|
dependencies: resolvedValue.dependencies
|
|
2298
2305
|
};
|
|
2299
2306
|
}
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
}
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2307
|
+
function resolveObjectOriginal({ schema, propName, combined = false, context, formDataContext }) {
|
|
2308
|
+
const resolvedValue = resolveValue({
|
|
2309
|
+
schema,
|
|
2310
|
+
name: propName,
|
|
2311
|
+
context,
|
|
2312
|
+
formDataContext
|
|
2313
|
+
});
|
|
2314
|
+
const aliased = createTypeAliasIfNeeded({
|
|
2315
|
+
resolvedValue,
|
|
2316
|
+
propName,
|
|
2317
|
+
context
|
|
2318
|
+
});
|
|
2319
|
+
if (aliased) return {
|
|
2320
|
+
...aliased,
|
|
2321
|
+
originalSchema: resolvedValue.originalSchema
|
|
2313
2322
|
};
|
|
2323
|
+
if (propName && resolvedValue.isEnum && !combined && !resolvedValue.isRef) {
|
|
2324
|
+
const doc = jsDoc(resolvedValue.originalSchema);
|
|
2325
|
+
const enumValue = getEnum(resolvedValue.value, propName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention.enum);
|
|
2326
|
+
return {
|
|
2327
|
+
value: propName,
|
|
2328
|
+
imports: [{ name: propName }],
|
|
2329
|
+
schemas: [...resolvedValue.schemas, {
|
|
2330
|
+
name: propName,
|
|
2331
|
+
model: doc + enumValue,
|
|
2332
|
+
imports: resolvedValue.imports,
|
|
2333
|
+
dependencies: resolvedValue.dependencies
|
|
2334
|
+
}],
|
|
2335
|
+
isEnum: false,
|
|
2336
|
+
type: "enum",
|
|
2337
|
+
originalSchema: resolvedValue.originalSchema,
|
|
2338
|
+
isRef: resolvedValue.isRef,
|
|
2339
|
+
hasReadonlyProps: resolvedValue.hasReadonlyProps,
|
|
2340
|
+
dependencies: [...resolvedValue.dependencies, propName]
|
|
2341
|
+
};
|
|
2342
|
+
}
|
|
2343
|
+
return resolvedValue;
|
|
2344
|
+
}
|
|
2345
|
+
const resolveObjectCacheMap = /* @__PURE__ */ new Map();
|
|
2346
|
+
function resolveObject({ schema, propName, combined = false, context, formDataContext }) {
|
|
2347
|
+
const hashKey = JSON.stringify({
|
|
2348
|
+
schema,
|
|
2349
|
+
propName,
|
|
2350
|
+
combined,
|
|
2351
|
+
projectName: context.projectName ?? context.output.target,
|
|
2352
|
+
formDataContext
|
|
2353
|
+
});
|
|
2354
|
+
if (resolveObjectCacheMap.has(hashKey)) return resolveObjectCacheMap.get(hashKey);
|
|
2355
|
+
const result = resolveObjectOriginal({
|
|
2356
|
+
schema,
|
|
2357
|
+
propName,
|
|
2358
|
+
combined,
|
|
2359
|
+
context,
|
|
2360
|
+
formDataContext
|
|
2361
|
+
});
|
|
2362
|
+
resolveObjectCacheMap.set(hashKey, result);
|
|
2363
|
+
return result;
|
|
2314
2364
|
}
|
|
2365
|
+
//#endregion
|
|
2366
|
+
//#region src/getters/array.ts
|
|
2315
2367
|
/**
|
|
2316
|
-
* Return the output type from an
|
|
2368
|
+
* Return the output type from an array
|
|
2317
2369
|
*
|
|
2318
|
-
* @param item item with type === "
|
|
2370
|
+
* @param item item with type === "array"
|
|
2319
2371
|
*/
|
|
2320
|
-
function
|
|
2321
|
-
|
|
2322
|
-
|
|
2372
|
+
function getArray({ schema, name, context, formDataContext }) {
|
|
2373
|
+
const schemaPrefixItems = schema.prefixItems;
|
|
2374
|
+
const schemaItems = schema.items;
|
|
2375
|
+
const schemaExample = schema.example;
|
|
2376
|
+
const schemaExamples = schema.examples;
|
|
2377
|
+
const itemSuffix = context.output.override.components.schemas.itemSuffix;
|
|
2378
|
+
if (schemaPrefixItems) {
|
|
2379
|
+
const resolvedObjects = schemaPrefixItems.map((item, index) => resolveObject({
|
|
2380
|
+
schema: item,
|
|
2381
|
+
propName: name ? name + itemSuffix + String(index) : void 0,
|
|
2382
|
+
context
|
|
2383
|
+
}));
|
|
2384
|
+
if (schemaItems) {
|
|
2385
|
+
const additional = resolveObject({
|
|
2386
|
+
schema: schemaItems,
|
|
2387
|
+
propName: name ? name + itemSuffix + "Additional" : void 0,
|
|
2388
|
+
context
|
|
2389
|
+
});
|
|
2390
|
+
resolvedObjects.push({
|
|
2391
|
+
...additional,
|
|
2392
|
+
value: `...${additional.value}[]`
|
|
2393
|
+
});
|
|
2394
|
+
}
|
|
2323
2395
|
return {
|
|
2324
|
-
|
|
2325
|
-
imports: [{ name }],
|
|
2326
|
-
schemas: [],
|
|
2396
|
+
type: "array",
|
|
2327
2397
|
isEnum: false,
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2398
|
+
isRef: false,
|
|
2399
|
+
value: `[${resolvedObjects.map((o) => o.value).join(", ")}]`,
|
|
2400
|
+
imports: resolvedObjects.flatMap((o) => o.imports),
|
|
2401
|
+
schemas: resolvedObjects.flatMap((o) => o.schemas),
|
|
2402
|
+
dependencies: resolvedObjects.flatMap((o) => o.dependencies),
|
|
2403
|
+
hasReadonlyProps: resolvedObjects.some((o) => o.hasReadonlyProps),
|
|
2404
|
+
example: schemaExample,
|
|
2405
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
2334
2406
|
};
|
|
2335
2407
|
}
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2408
|
+
if (schemaItems) {
|
|
2409
|
+
const resolvedObject = resolveObject({
|
|
2410
|
+
schema: schemaItems,
|
|
2411
|
+
propName: name ? name + itemSuffix : void 0,
|
|
2412
|
+
context,
|
|
2413
|
+
formDataContext
|
|
2414
|
+
});
|
|
2415
|
+
return {
|
|
2416
|
+
value: `${schema.readOnly === true && !context.output.override.suppressReadonlyModifier ? "readonly " : ""}${resolvedObject.value.includes("|") || resolvedObject.value.includes("&") ? `(${resolvedObject.value})[]` : `${resolvedObject.value}[]`}`,
|
|
2417
|
+
imports: resolvedObject.imports,
|
|
2418
|
+
schemas: resolvedObject.schemas,
|
|
2419
|
+
dependencies: resolvedObject.dependencies,
|
|
2420
|
+
isEnum: false,
|
|
2421
|
+
type: "array",
|
|
2422
|
+
isRef: false,
|
|
2423
|
+
hasReadonlyProps: resolvedObject.hasReadonlyProps,
|
|
2424
|
+
example: schemaExample,
|
|
2425
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
2426
|
+
};
|
|
2427
|
+
} else if (compareVersions(context.spec.openapi ?? "3.0.0", "3.1", ">=")) return {
|
|
2428
|
+
value: "unknown[]",
|
|
2429
|
+
imports: [],
|
|
2430
|
+
schemas: [],
|
|
2431
|
+
dependencies: [],
|
|
2432
|
+
isEnum: false,
|
|
2433
|
+
type: "array",
|
|
2434
|
+
isRef: false,
|
|
2435
|
+
hasReadonlyProps: false
|
|
2436
|
+
};
|
|
2437
|
+
else throw new Error(`All arrays must have an \`items\` key defined (name=${name}, schema=${JSON.stringify(schema)})`);
|
|
2438
|
+
}
|
|
2439
|
+
//#endregion
|
|
2440
|
+
//#region src/getters/res-req-types.ts
|
|
2441
|
+
const getSchemaType$1 = (s) => s.type;
|
|
2442
|
+
const getSchemaCombined = (s) => s.oneOf ?? s.anyOf ?? s.allOf;
|
|
2443
|
+
const getSchemaOneOf = (s) => s.oneOf;
|
|
2444
|
+
const getSchemaAnyOf = (s) => s.anyOf;
|
|
2445
|
+
const getSchemaItems = (s) => s.items;
|
|
2446
|
+
const getSchemaRequired = (s) => s.required;
|
|
2447
|
+
const getSchemaProperties = (s) => s.properties;
|
|
2448
|
+
const resolveSchemaRef = (schema, context) => resolveRef(schema, context);
|
|
2449
|
+
const resolveResponseOrRequestRef = (schema, context) => resolveRef(schema, context);
|
|
2450
|
+
const formDataContentTypes = new Set(["multipart/form-data"]);
|
|
2451
|
+
const formUrlEncodedContentTypes = new Set(["application/x-www-form-urlencoded"]);
|
|
2452
|
+
function getResReqContentTypes({ mediaType, propName, context, isFormData, contentType }) {
|
|
2453
|
+
if (!mediaType.schema) return;
|
|
2454
|
+
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
2455
|
+
const formDataContext = isFormData ? {
|
|
2456
|
+
atPart: false,
|
|
2457
|
+
encoding: mediaType.encoding ?? {}
|
|
2458
|
+
} : isFormUrlEncoded ? {
|
|
2459
|
+
atPart: false,
|
|
2460
|
+
encoding: mediaType.encoding ?? {},
|
|
2461
|
+
urlEncoded: true
|
|
2462
|
+
} : void 0;
|
|
2463
|
+
const resolvedObject = resolveObject({
|
|
2464
|
+
schema: mediaType.schema,
|
|
2465
|
+
propName,
|
|
2345
2466
|
context,
|
|
2346
|
-
nullable,
|
|
2347
2467
|
formDataContext
|
|
2348
2468
|
});
|
|
2349
|
-
if (
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
context,
|
|
2401
|
-
formDataContext: propertyFormDataContext
|
|
2402
|
-
});
|
|
2403
|
-
const isReadOnly = Boolean(schemaItem.readOnly) || Boolean(schema.readOnly);
|
|
2404
|
-
if (!index) acc.value += "{";
|
|
2405
|
-
const doc = jsDoc(schema, true, context);
|
|
2406
|
-
const propertyDoc = doc ? `${doc.trimEnd().split("\n").map((line) => ` ${line}`).join("\n")}\n` : "";
|
|
2407
|
-
if (isReadOnly || resolvedValue.hasReadonlyProps) acc.hasReadonlyProps = true;
|
|
2408
|
-
const constValue = "const" in schema ? schema.const : void 0;
|
|
2409
|
-
const hasConst = constValue !== void 0;
|
|
2410
|
-
let constLiteral;
|
|
2411
|
-
if (!hasConst) constLiteral = void 0;
|
|
2412
|
-
else if (isString(constValue)) constLiteral = `'${escape(constValue)}'`;
|
|
2413
|
-
else constLiteral = JSON.stringify(constValue);
|
|
2414
|
-
const needsValueImport = hasConst && (resolvedValue.isEnum || resolvedValue.type === "enum");
|
|
2415
|
-
const usedResolvedValue = !hasConst || needsValueImport;
|
|
2416
|
-
const aliasedImports = needsValueImport ? resolvedValue.imports.map((imp) => ({
|
|
2417
|
-
...imp,
|
|
2418
|
-
isConstant: true
|
|
2419
|
-
})) : hasConst ? [] : getAliasedImports({
|
|
2469
|
+
if (!isFormData && isBinaryContentType(contentType)) return {
|
|
2470
|
+
...resolvedObject,
|
|
2471
|
+
value: "Blob"
|
|
2472
|
+
};
|
|
2473
|
+
return resolvedObject;
|
|
2474
|
+
}
|
|
2475
|
+
function getResReqTypes(responsesOrRequests, name, context, defaultType = "unknown", uniqueKey = (item) => item.value) {
|
|
2476
|
+
return uniqueBy(responsesOrRequests.filter(([, res]) => Boolean(res)).map(([key, res]) => {
|
|
2477
|
+
if (isReference(res)) {
|
|
2478
|
+
const { schema: bodySchema, imports: [{ name, schemaName }] } = resolveResponseOrRequestRef(res, context);
|
|
2479
|
+
const firstEntry = Object.entries(bodySchema.content ?? {}).at(0);
|
|
2480
|
+
if (!firstEntry) return [{
|
|
2481
|
+
value: name,
|
|
2482
|
+
imports: [{
|
|
2483
|
+
name,
|
|
2484
|
+
schemaName
|
|
2485
|
+
}],
|
|
2486
|
+
schemas: [],
|
|
2487
|
+
type: "unknown",
|
|
2488
|
+
isEnum: false,
|
|
2489
|
+
isRef: true,
|
|
2490
|
+
hasReadonlyProps: false,
|
|
2491
|
+
dependencies: [name],
|
|
2492
|
+
originalSchema: void 0,
|
|
2493
|
+
example: void 0,
|
|
2494
|
+
examples: void 0,
|
|
2495
|
+
key,
|
|
2496
|
+
contentType: ""
|
|
2497
|
+
}];
|
|
2498
|
+
const [contentType, mediaType] = firstEntry;
|
|
2499
|
+
const isFormData = formDataContentTypes.has(contentType);
|
|
2500
|
+
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
2501
|
+
if (!isFormData && !isFormUrlEncoded || !mediaType.schema) return [{
|
|
2502
|
+
value: name,
|
|
2503
|
+
imports: [{
|
|
2504
|
+
name,
|
|
2505
|
+
schemaName
|
|
2506
|
+
}],
|
|
2507
|
+
schemas: [],
|
|
2508
|
+
type: "unknown",
|
|
2509
|
+
isEnum: false,
|
|
2510
|
+
isRef: true,
|
|
2511
|
+
hasReadonlyProps: false,
|
|
2512
|
+
dependencies: [name],
|
|
2513
|
+
originalSchema: mediaType.schema,
|
|
2514
|
+
example: mediaType.example,
|
|
2515
|
+
examples: resolveExampleRefs(mediaType.examples, context),
|
|
2516
|
+
key,
|
|
2517
|
+
contentType
|
|
2518
|
+
}];
|
|
2519
|
+
const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
|
|
2420
2520
|
name,
|
|
2521
|
+
schemaObject: mediaType.schema,
|
|
2421
2522
|
context,
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2523
|
+
isRequestBodyOptional: bodySchema.required !== true,
|
|
2524
|
+
isRef: true,
|
|
2525
|
+
encoding: mediaType.encoding
|
|
2526
|
+
}) : void 0;
|
|
2527
|
+
const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
|
|
2528
|
+
name,
|
|
2529
|
+
schemaObject: mediaType.schema,
|
|
2426
2530
|
context,
|
|
2427
|
-
|
|
2428
|
-
|
|
2531
|
+
isRequestBodyOptional: bodySchema.required !== true,
|
|
2532
|
+
isUrlEncoded: true,
|
|
2533
|
+
isRef: true,
|
|
2534
|
+
encoding: mediaType.encoding
|
|
2535
|
+
}) : void 0;
|
|
2536
|
+
const additionalImports = getFormDataAdditionalImports({
|
|
2537
|
+
schemaObject: mediaType.schema,
|
|
2538
|
+
context
|
|
2429
2539
|
});
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2540
|
+
return [{
|
|
2541
|
+
value: name,
|
|
2542
|
+
imports: [{
|
|
2543
|
+
name,
|
|
2544
|
+
schemaName
|
|
2545
|
+
}, ...additionalImports],
|
|
2546
|
+
schemas: [],
|
|
2547
|
+
type: "unknown",
|
|
2548
|
+
isEnum: false,
|
|
2549
|
+
hasReadonlyProps: false,
|
|
2550
|
+
dependencies: [name],
|
|
2551
|
+
formData,
|
|
2552
|
+
formUrlEncoded,
|
|
2553
|
+
isRef: true,
|
|
2554
|
+
originalSchema: mediaType.schema,
|
|
2555
|
+
example: mediaType.example,
|
|
2556
|
+
examples: resolveExampleRefs(mediaType.examples, context),
|
|
2557
|
+
key,
|
|
2558
|
+
contentType
|
|
2559
|
+
}];
|
|
2560
|
+
}
|
|
2561
|
+
if (res.content) return Object.entries(res.content).map(([contentType, mediaType], index, arr) => {
|
|
2562
|
+
let propName = key ? pascal(name) + pascal(key) : void 0;
|
|
2563
|
+
if (propName && arr.length > 1) propName = propName + pascal(getNumberWord(index + 1));
|
|
2564
|
+
const isFormData = formDataContentTypes.has(contentType);
|
|
2565
|
+
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
2566
|
+
let effectivePropName = propName;
|
|
2567
|
+
if (mediaType.schema && isReference(mediaType.schema)) {
|
|
2568
|
+
const { imports } = resolveSchemaRef(mediaType.schema, context);
|
|
2569
|
+
if (imports[0]?.name) effectivePropName = imports[0].name;
|
|
2570
|
+
} else if ((isFormData || isFormUrlEncoded) && mediaType.schema) {
|
|
2571
|
+
const combinedRefs = getSchemaOneOf(mediaType.schema) ?? getSchemaAnyOf(mediaType.schema);
|
|
2572
|
+
if (combinedRefs) {
|
|
2573
|
+
const names = [];
|
|
2574
|
+
for (const ref of combinedRefs) {
|
|
2575
|
+
if (!isReference(ref)) continue;
|
|
2576
|
+
const refName = resolveSchemaRef(ref, context).imports[0]?.name;
|
|
2577
|
+
if (refName) names.push(refName);
|
|
2467
2578
|
}
|
|
2468
|
-
|
|
2469
|
-
acc.schemas.push(...resolvedValue.schemas);
|
|
2470
|
-
acc.dependencies.push(...resolvedValue.dependencies);
|
|
2579
|
+
if (names.length > 0) effectivePropName = names.join("");
|
|
2471
2580
|
}
|
|
2472
|
-
else acc.value += "\n}";
|
|
2473
|
-
acc.value += nullable;
|
|
2474
2581
|
}
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2582
|
+
const resolvedValue = getResReqContentTypes({
|
|
2583
|
+
mediaType,
|
|
2584
|
+
propName: effectivePropName,
|
|
2585
|
+
context,
|
|
2586
|
+
isFormData,
|
|
2587
|
+
contentType
|
|
2588
|
+
});
|
|
2589
|
+
if (!resolvedValue) {
|
|
2590
|
+
if (isBinaryContentType(contentType)) return {
|
|
2591
|
+
value: "Blob",
|
|
2592
|
+
imports: [],
|
|
2593
|
+
schemas: [],
|
|
2594
|
+
type: "Blob",
|
|
2595
|
+
isEnum: false,
|
|
2596
|
+
key,
|
|
2597
|
+
isRef: false,
|
|
2598
|
+
hasReadonlyProps: false,
|
|
2599
|
+
contentType
|
|
2600
|
+
};
|
|
2601
|
+
return;
|
|
2602
|
+
}
|
|
2603
|
+
if (!isFormData && !isFormUrlEncoded || !effectivePropName || !mediaType.schema) return {
|
|
2604
|
+
...resolvedValue,
|
|
2605
|
+
imports: resolvedValue.imports,
|
|
2606
|
+
dependencies: resolvedValue.dependencies,
|
|
2607
|
+
contentType,
|
|
2608
|
+
example: mediaType.example,
|
|
2609
|
+
examples: resolveExampleRefs(mediaType.examples, context)
|
|
2493
2610
|
};
|
|
2611
|
+
const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
|
|
2612
|
+
name: effectivePropName,
|
|
2613
|
+
schemaObject: mediaType.schema,
|
|
2614
|
+
context,
|
|
2615
|
+
isRequestBodyOptional: res.required !== true,
|
|
2616
|
+
isRef: true,
|
|
2617
|
+
encoding: mediaType.encoding
|
|
2618
|
+
}) : void 0;
|
|
2619
|
+
const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
|
|
2620
|
+
name: effectivePropName,
|
|
2621
|
+
schemaObject: mediaType.schema,
|
|
2622
|
+
context,
|
|
2623
|
+
isUrlEncoded: true,
|
|
2624
|
+
isRequestBodyOptional: res.required !== true,
|
|
2625
|
+
isRef: true,
|
|
2626
|
+
encoding: mediaType.encoding
|
|
2627
|
+
}) : void 0;
|
|
2628
|
+
const additionalImports = getFormDataAdditionalImports({
|
|
2629
|
+
schemaObject: mediaType.schema,
|
|
2630
|
+
context
|
|
2631
|
+
});
|
|
2494
2632
|
return {
|
|
2495
|
-
|
|
2496
|
-
imports: [],
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
useTypeAlias: false,
|
|
2503
|
-
dependencies: []
|
|
2633
|
+
...resolvedValue,
|
|
2634
|
+
imports: [...resolvedValue.imports, ...additionalImports],
|
|
2635
|
+
formData,
|
|
2636
|
+
formUrlEncoded,
|
|
2637
|
+
contentType,
|
|
2638
|
+
example: mediaType.example,
|
|
2639
|
+
examples: resolveExampleRefs(mediaType.examples, context)
|
|
2504
2640
|
};
|
|
2505
|
-
}
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
dependencies: [...recordType.dependencies, ...resolvedValue.dependencies]
|
|
2522
|
-
};
|
|
2523
|
-
return {
|
|
2524
|
-
value: `{[key: ${getIndexSignatureKey(schemaItem)}]: ${resolvedValue.value}}` + nullable,
|
|
2525
|
-
imports: resolvedValue.imports,
|
|
2526
|
-
schemas: resolvedValue.schemas,
|
|
2527
|
-
isEnum: false,
|
|
2528
|
-
type: "object",
|
|
2529
|
-
isRef: false,
|
|
2530
|
-
hasReadonlyProps: resolvedValue.hasReadonlyProps,
|
|
2531
|
-
useTypeAlias: false,
|
|
2532
|
-
dependencies: resolvedValue.dependencies
|
|
2533
|
-
};
|
|
2534
|
-
}
|
|
2535
|
-
const constValue = schemaItem.const;
|
|
2536
|
-
if (constValue !== void 0) {
|
|
2537
|
-
let type;
|
|
2538
|
-
if (Array.isArray(constValue)) type = "array";
|
|
2539
|
-
else if (constValue === null) type = "null";
|
|
2540
|
-
else if (typeof constValue === "string") type = "string";
|
|
2541
|
-
else if (typeof constValue === "number") type = "number";
|
|
2542
|
-
else if (typeof constValue === "boolean") type = "boolean";
|
|
2543
|
-
else type = "object";
|
|
2544
|
-
return {
|
|
2545
|
-
value: typeof constValue === "string" ? `'${escape(constValue)}'` : JSON.stringify(constValue),
|
|
2641
|
+
}).filter(Boolean).map((x) => ({
|
|
2642
|
+
...x,
|
|
2643
|
+
key
|
|
2644
|
+
}));
|
|
2645
|
+
const swaggerSchema = "schema" in res ? res.schema : void 0;
|
|
2646
|
+
if (swaggerSchema) return [{
|
|
2647
|
+
...resolveObject({
|
|
2648
|
+
schema: swaggerSchema,
|
|
2649
|
+
propName: key ? pascal(name) + pascal(key) : void 0,
|
|
2650
|
+
context
|
|
2651
|
+
}),
|
|
2652
|
+
contentType: "application/json",
|
|
2653
|
+
key
|
|
2654
|
+
}];
|
|
2655
|
+
return [{
|
|
2656
|
+
value: defaultType,
|
|
2546
2657
|
imports: [],
|
|
2547
2658
|
schemas: [],
|
|
2659
|
+
type: defaultType,
|
|
2548
2660
|
isEnum: false,
|
|
2549
|
-
|
|
2661
|
+
dependencies: [],
|
|
2662
|
+
key,
|
|
2550
2663
|
isRef: false,
|
|
2551
|
-
hasReadonlyProps:
|
|
2552
|
-
|
|
2553
|
-
};
|
|
2554
|
-
}
|
|
2555
|
-
const keyType = itemType === "object" ? getIndexSignatureKey(schemaItem) : "string";
|
|
2556
|
-
const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
|
|
2557
|
-
if (itemType === "object" && recordType) return {
|
|
2558
|
-
value: recordType.value + nullable,
|
|
2559
|
-
imports: recordType.imports,
|
|
2560
|
-
schemas: [],
|
|
2561
|
-
isEnum: false,
|
|
2562
|
-
type: "object",
|
|
2563
|
-
isRef: false,
|
|
2564
|
-
hasReadonlyProps: readOnlyFlag ?? false,
|
|
2565
|
-
useTypeAlias: true,
|
|
2566
|
-
dependencies: recordType.dependencies
|
|
2567
|
-
};
|
|
2568
|
-
return {
|
|
2569
|
-
value: (itemType === "object" ? `{ [key: ${keyType}]: unknown }` : "unknown") + nullable,
|
|
2570
|
-
imports: [],
|
|
2571
|
-
schemas: [],
|
|
2572
|
-
isEnum: false,
|
|
2573
|
-
type: "object",
|
|
2574
|
-
isRef: false,
|
|
2575
|
-
hasReadonlyProps: readOnlyFlag ?? false,
|
|
2576
|
-
useTypeAlias: false,
|
|
2577
|
-
dependencies: []
|
|
2578
|
-
};
|
|
2664
|
+
hasReadonlyProps: false,
|
|
2665
|
+
contentType: "application/json"
|
|
2666
|
+
}];
|
|
2667
|
+
}).flat(), uniqueKey);
|
|
2579
2668
|
}
|
|
2580
|
-
//#endregion
|
|
2581
|
-
//#region src/getters/scalar.ts
|
|
2582
2669
|
/**
|
|
2583
|
-
*
|
|
2584
|
-
*
|
|
2585
|
-
* @param item
|
|
2586
|
-
* @ref https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.1.md#data-types
|
|
2670
|
+
* Determine the responseType option based on success content types only.
|
|
2671
|
+
* This avoids error-response content types influencing the responseType.
|
|
2587
2672
|
*/
|
|
2588
|
-
function
|
|
2589
|
-
const
|
|
2590
|
-
|
|
2591
|
-
const
|
|
2592
|
-
const
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
value
|
|
2638
|
-
if (
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
if (!formDataContext?.urlEncoded) {
|
|
2673
|
-
if (schemaFormat === "binary") value = "Blob";
|
|
2674
|
-
else if (formDataContext?.atPart) {
|
|
2675
|
-
const fileType = getFormDataFieldFileType(item, formDataContext.partContentType);
|
|
2676
|
-
if (fileType) value = fileType === "binary" ? "Blob" : "Blob | string";
|
|
2677
|
-
} else if (schemaContentMediaType === "application/octet-stream" && !schemaContentEncoding) value = "Blob";
|
|
2673
|
+
function getSuccessResponseType(response) {
|
|
2674
|
+
const successContentTypes = response.types.success.map((t) => t.contentType).filter(Boolean);
|
|
2675
|
+
if (response.isBlob) return "blob";
|
|
2676
|
+
const hasJsonResponse = successContentTypes.some((contentType) => contentType.includes("json") || contentType.includes("+json"));
|
|
2677
|
+
const hasTextResponse = successContentTypes.some((contentType) => contentType.startsWith("text/") || contentType.includes("xml"));
|
|
2678
|
+
if (!hasJsonResponse && hasTextResponse) return "text";
|
|
2679
|
+
}
|
|
2680
|
+
/**
|
|
2681
|
+
* Determine the response type category for a given content type.
|
|
2682
|
+
* Used to set the correct responseType option in HTTP clients.
|
|
2683
|
+
*
|
|
2684
|
+
* @param contentType - The MIME content type (e.g., 'application/json', 'text/plain')
|
|
2685
|
+
* @returns The response type category to use for parsing
|
|
2686
|
+
*/
|
|
2687
|
+
function getResponseTypeCategory(contentType) {
|
|
2688
|
+
if (isBinaryContentType(contentType)) return "blob";
|
|
2689
|
+
if (contentType === "application/json" || contentType.includes("+json") || contentType.includes("-json")) return "json";
|
|
2690
|
+
return "text";
|
|
2691
|
+
}
|
|
2692
|
+
/**
|
|
2693
|
+
* Get the default content type from a list of content types.
|
|
2694
|
+
* Priority: application/json > any JSON-like type > first in list
|
|
2695
|
+
*
|
|
2696
|
+
* @param contentTypes - Array of content types from OpenAPI spec
|
|
2697
|
+
* @returns The default content type to use
|
|
2698
|
+
*/
|
|
2699
|
+
function getDefaultContentType(contentTypes) {
|
|
2700
|
+
if (contentTypes.length === 0) return "application/json";
|
|
2701
|
+
if (contentTypes.includes("application/json")) return "application/json";
|
|
2702
|
+
const jsonType = contentTypes.find((ct) => ct.includes("+json") || ct.includes("-json"));
|
|
2703
|
+
if (jsonType) return jsonType;
|
|
2704
|
+
return contentTypes[0];
|
|
2705
|
+
}
|
|
2706
|
+
function getFormDataAdditionalImports({ schemaObject, context }) {
|
|
2707
|
+
const { schema } = resolveSchemaRef(schemaObject, context);
|
|
2708
|
+
if (schema.type !== "object") return [];
|
|
2709
|
+
const combinedSchemas = getSchemaOneOf(schema) ?? getSchemaAnyOf(schema);
|
|
2710
|
+
if (!combinedSchemas) return [];
|
|
2711
|
+
return combinedSchemas.map((subSchema) => resolveSchemaRef(subSchema, context).imports[0]).filter(Boolean);
|
|
2712
|
+
}
|
|
2713
|
+
function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequestBodyOptional, isUrlEncoded, isRef, encoding }) {
|
|
2714
|
+
const { schema, imports } = resolveSchemaRef(schemaObject, context);
|
|
2715
|
+
const propName = camel(!isRef && isReference(schemaObject) ? imports[0].name : name);
|
|
2716
|
+
const variableName = isUrlEncoded ? "formUrlEncoded" : "formData";
|
|
2717
|
+
let form = isUrlEncoded ? `const ${variableName} = new URLSearchParams();\n` : `const ${variableName} = new FormData();\n`;
|
|
2718
|
+
const combinedSchemas = getSchemaCombined(schema);
|
|
2719
|
+
if (schema.type === "object" || schema.type === void 0 && combinedSchemas) {
|
|
2720
|
+
if (combinedSchemas) if (!!getSchemaOneOf(schema) || !!getSchemaAnyOf(schema)) {
|
|
2721
|
+
const directProperties = getSchemaProperties(schema);
|
|
2722
|
+
const directKeys = directProperties ? Object.entries(directProperties).filter(([, value]) => !resolveSchemaRef(value, context).schema.readOnly).map(([key]) => key) : [];
|
|
2723
|
+
const skipLine = directKeys.length > 0 ? ` if ([${directKeys.map((k) => JSON.stringify(k)).join(", ")}].includes(key)) return;\n` : "";
|
|
2724
|
+
form += `Object.entries(${propName} ?? {}).forEach(([key, value]) => {\n`;
|
|
2725
|
+
form += skipLine;
|
|
2726
|
+
form += ` if (value !== undefined && value !== null) {\n`;
|
|
2727
|
+
if (isUrlEncoded) {
|
|
2728
|
+
form += ` if (Array.isArray(value)) {\n`;
|
|
2729
|
+
form += ` value.forEach(v => {\n`;
|
|
2730
|
+
form += ` ${variableName}.append(key, typeof v === 'object' ? JSON.stringify(v) : String(v));\n`;
|
|
2731
|
+
form += ` });\n`;
|
|
2732
|
+
form += ` } else if (typeof value === 'object') {\n`;
|
|
2733
|
+
form += ` ${variableName}.append(key, JSON.stringify(value));\n`;
|
|
2734
|
+
form += ` } else {\n`;
|
|
2735
|
+
form += ` ${variableName}.append(key, String(value));\n`;
|
|
2736
|
+
form += ` }\n`;
|
|
2737
|
+
} else {
|
|
2738
|
+
form += ` if ((typeof File !== 'undefined' && value instanceof File) || value instanceof Blob) {\n`;
|
|
2739
|
+
form += ` ${variableName}.append(key, value);\n`;
|
|
2740
|
+
form += ` } else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {\n`;
|
|
2741
|
+
form += ` ${variableName}.append(key, new Blob([Uint8Array.from(value)]));\n`;
|
|
2742
|
+
form += ` } else if (Array.isArray(value)) {\n`;
|
|
2743
|
+
form += ` value.forEach(v => {\n`;
|
|
2744
|
+
form += ` if ((typeof File !== 'undefined' && v instanceof File) || v instanceof Blob) {\n`;
|
|
2745
|
+
form += ` ${variableName}.append(key, v);\n`;
|
|
2746
|
+
form += ` } else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(v)) {\n`;
|
|
2747
|
+
form += ` ${variableName}.append(key, new Blob([Uint8Array.from(v)]));\n`;
|
|
2748
|
+
form += ` } else {\n`;
|
|
2749
|
+
form += ` ${variableName}.append(key, typeof v === 'object' ? JSON.stringify(v) : String(v));\n`;
|
|
2750
|
+
form += ` }\n`;
|
|
2751
|
+
form += ` });\n`;
|
|
2752
|
+
form += ` } else if (typeof value === 'object') {\n`;
|
|
2753
|
+
form += ` ${variableName}.append(key, JSON.stringify(value));\n`;
|
|
2754
|
+
form += ` } else {\n`;
|
|
2755
|
+
form += ` ${variableName}.append(key, String(value));\n`;
|
|
2756
|
+
form += ` }\n`;
|
|
2678
2757
|
}
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2758
|
+
form += ` }\n`;
|
|
2759
|
+
form += `});\n`;
|
|
2760
|
+
} else {
|
|
2761
|
+
const combinedSchemasFormData = combinedSchemas.map((subSchema) => {
|
|
2762
|
+
const { schema: combinedSchema } = resolveSchemaRef(subSchema, context);
|
|
2763
|
+
return resolveSchemaPropertiesToFormData({
|
|
2764
|
+
schema: combinedSchema,
|
|
2765
|
+
variableName,
|
|
2766
|
+
propName,
|
|
2767
|
+
context,
|
|
2768
|
+
isRequestBodyOptional,
|
|
2769
|
+
encoding
|
|
2770
|
+
});
|
|
2771
|
+
}).filter(Boolean).join("\n");
|
|
2772
|
+
form += combinedSchemasFormData;
|
|
2694
2773
|
}
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
schemas: [],
|
|
2701
|
-
isRef: false,
|
|
2702
|
-
hasReadonlyProps: schemaReadOnly ?? false,
|
|
2703
|
-
dependencies: []
|
|
2704
|
-
};
|
|
2705
|
-
default: {
|
|
2706
|
-
if (isArray(itemType)) return combineSchemas({
|
|
2707
|
-
schema: { anyOf: itemType.map((type) => Object.assign({}, item, { type })) },
|
|
2708
|
-
name,
|
|
2709
|
-
separator: "anyOf",
|
|
2710
|
-
context,
|
|
2711
|
-
nullable
|
|
2712
|
-
});
|
|
2713
|
-
if (enumItems) return {
|
|
2714
|
-
value: enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : String(enumItem)).filter(Boolean).join(` | `) + nullable,
|
|
2715
|
-
isEnum: true,
|
|
2716
|
-
type: "string",
|
|
2717
|
-
imports: [],
|
|
2718
|
-
schemas: [],
|
|
2719
|
-
isRef: false,
|
|
2720
|
-
hasReadonlyProps: schemaReadOnly ?? false,
|
|
2721
|
-
dependencies: [],
|
|
2722
|
-
example: schemaExample,
|
|
2723
|
-
examples: resolveExampleRefs(schemaExamples, context)
|
|
2724
|
-
};
|
|
2725
|
-
const hasCombiners = item.allOf ?? item.anyOf ?? item.oneOf;
|
|
2726
|
-
const { value, ...rest } = getObject({
|
|
2727
|
-
item,
|
|
2728
|
-
name,
|
|
2774
|
+
if (schema.properties) {
|
|
2775
|
+
const formDataValues = resolveSchemaPropertiesToFormData({
|
|
2776
|
+
schema,
|
|
2777
|
+
variableName,
|
|
2778
|
+
propName,
|
|
2729
2779
|
context,
|
|
2730
|
-
|
|
2731
|
-
|
|
2780
|
+
isRequestBodyOptional,
|
|
2781
|
+
encoding
|
|
2732
2782
|
});
|
|
2733
|
-
|
|
2734
|
-
value,
|
|
2735
|
-
...rest
|
|
2736
|
-
};
|
|
2783
|
+
form += formDataValues;
|
|
2737
2784
|
}
|
|
2785
|
+
return form;
|
|
2738
2786
|
}
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
]);
|
|
2747
|
-
function isMergeableAllOfObject(schema) {
|
|
2748
|
-
if (isNullish$1(schema.properties)) return false;
|
|
2749
|
-
if (schema.allOf || schema.anyOf || schema.oneOf) return false;
|
|
2750
|
-
if (!isNullish$1(schema.type) && schema.type !== "object") return false;
|
|
2751
|
-
return Object.keys(schema).every((key) => mergeableAllOfKeys.has(key));
|
|
2752
|
-
}
|
|
2753
|
-
function normalizeAllOfSchema(schema) {
|
|
2754
|
-
const schemaAllOf = schema.allOf;
|
|
2755
|
-
if (!schemaAllOf) return schema;
|
|
2756
|
-
let didMerge = false;
|
|
2757
|
-
const schemaProperties = schema.properties;
|
|
2758
|
-
const schemaRequired = schema.required;
|
|
2759
|
-
const mergedProperties = schemaProperties ? { ...schemaProperties } : {};
|
|
2760
|
-
const mergedRequired = new Set(schemaRequired);
|
|
2761
|
-
const remainingAllOf = [];
|
|
2762
|
-
for (const subSchema of schemaAllOf) {
|
|
2763
|
-
if (isSchema(subSchema) && isMergeableAllOfObject(subSchema)) {
|
|
2764
|
-
didMerge = true;
|
|
2765
|
-
if (subSchema.properties) Object.assign(mergedProperties, subSchema.properties);
|
|
2766
|
-
const subRequired = subSchema.required;
|
|
2767
|
-
if (subRequired) for (const prop of subRequired) mergedRequired.add(prop);
|
|
2768
|
-
continue;
|
|
2787
|
+
if (schema.type === "array") {
|
|
2788
|
+
let valueStr = "value";
|
|
2789
|
+
const schemaItems = getSchemaItems(schema);
|
|
2790
|
+
if (schemaItems) {
|
|
2791
|
+
const { schema: itemSchema } = resolveSchemaRef(schemaItems, context);
|
|
2792
|
+
if (itemSchema.type === "object" || itemSchema.type === "array") valueStr = "JSON.stringify(value)";
|
|
2793
|
+
else if (itemSchema.type === "number" || itemSchema.type === "integer" || itemSchema.type === "boolean") valueStr = "value.toString()";
|
|
2769
2794
|
}
|
|
2770
|
-
|
|
2795
|
+
return `${form}${propName}.forEach(value => ${variableName}.append('data', ${valueStr}))\n`;
|
|
2771
2796
|
}
|
|
2772
|
-
if (
|
|
2773
|
-
return {
|
|
2774
|
-
...schema,
|
|
2775
|
-
...Object.keys(mergedProperties).length > 0 && { properties: mergedProperties },
|
|
2776
|
-
...mergedRequired.size > 0 && { required: [...mergedRequired] },
|
|
2777
|
-
...remainingAllOf.length > 0 && { allOf: remainingAllOf }
|
|
2778
|
-
};
|
|
2797
|
+
if (schema.type === "number" || schema.type === "integer" || schema.type === "boolean") return `${form}${variableName}.append('data', ${propName}.toString())\n`;
|
|
2798
|
+
return `${form}${variableName}.append('data', ${propName})\n`;
|
|
2779
2799
|
}
|
|
2780
|
-
function
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2800
|
+
function resolveSchemaPropertiesToFormData({ schema, variableName, propName, context, isRequestBodyOptional, keyPrefix = "", depth = 0, encoding }) {
|
|
2801
|
+
let formDataValues = "";
|
|
2802
|
+
const isUrlEncoded = variableName === "formUrlEncoded";
|
|
2803
|
+
const schemaProps = getSchemaProperties(schema) ?? {};
|
|
2804
|
+
for (const [key, value] of Object.entries(schemaProps)) {
|
|
2805
|
+
const { schema: property } = resolveSchemaRef(value, context);
|
|
2806
|
+
if (property.readOnly) continue;
|
|
2807
|
+
let formDataValue = "";
|
|
2808
|
+
const partContentType = (depth === 0 ? encoding?.[key] : void 0)?.contentType;
|
|
2809
|
+
const formattedKeyPrefix = isRequestBodyOptional ? keyword.isIdentifierNameES5(key) ? "?" : "?." : "";
|
|
2810
|
+
const formattedKey = keyword.isIdentifierNameES5(key) ? `.${key}` : `['${key}']`;
|
|
2811
|
+
const valueKey = `${propName}${formattedKeyPrefix}${formattedKey}`;
|
|
2812
|
+
const nonOptionalValueKey = `${propName}${formattedKey}`;
|
|
2813
|
+
const fileType = getFormDataFieldFileType(property, partContentType);
|
|
2814
|
+
const effectiveContentType = partContentType ?? property.contentMediaType;
|
|
2815
|
+
if (isUrlEncoded && (fileType || property.format === "binary")) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
2816
|
+
else if (fileType === "binary" || property.format === "binary") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
2817
|
+
else if (fileType === "text") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey} instanceof Blob ? ${nonOptionalValueKey} : new Blob([${nonOptionalValueKey}], { type: '${effectiveContentType}' }));\n`;
|
|
2818
|
+
else if (property.type === "object" || Array.isArray(property.type) && property.type.includes("object")) formDataValue = context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE ? resolveSchemaPropertiesToFormData({
|
|
2819
|
+
schema: property,
|
|
2820
|
+
variableName,
|
|
2821
|
+
propName: nonOptionalValueKey,
|
|
2822
|
+
context,
|
|
2823
|
+
isRequestBodyOptional,
|
|
2824
|
+
keyPrefix: `${keyPrefix}${key}.`,
|
|
2825
|
+
depth: depth + 1,
|
|
2826
|
+
encoding
|
|
2827
|
+
}) : `${variableName}.append(\`${keyPrefix}${key}\`, JSON.stringify(${nonOptionalValueKey}));\n`;
|
|
2828
|
+
else if (property.type === "array" || Array.isArray(property.type) && property.type.includes("array")) {
|
|
2829
|
+
let valueStr = "value";
|
|
2830
|
+
let hasNonPrimitiveChild = false;
|
|
2831
|
+
const propertyItems = getSchemaItems(property);
|
|
2832
|
+
if (propertyItems) {
|
|
2833
|
+
const { schema: itemSchema } = resolveSchemaRef(propertyItems, context);
|
|
2834
|
+
if (itemSchema.type === "object" || itemSchema.type === "array") if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
|
|
2835
|
+
hasNonPrimitiveChild = true;
|
|
2836
|
+
const resolvedValue = resolveSchemaPropertiesToFormData({
|
|
2837
|
+
schema: itemSchema,
|
|
2838
|
+
variableName,
|
|
2839
|
+
propName: "value",
|
|
2840
|
+
context,
|
|
2841
|
+
isRequestBodyOptional,
|
|
2842
|
+
keyPrefix: `${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}].`,
|
|
2843
|
+
depth: depth + 1
|
|
2844
|
+
});
|
|
2845
|
+
formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => {
|
|
2846
|
+
${resolvedValue}});\n`;
|
|
2847
|
+
} else valueStr = "JSON.stringify(value)";
|
|
2848
|
+
else {
|
|
2849
|
+
const itemType = getSchemaType$1(itemSchema);
|
|
2850
|
+
if (itemType === "number" || Array.isArray(itemType) && itemType.includes("number") || itemType === "integer" || Array.isArray(itemType) && itemType.includes("integer") || itemType === "boolean" || Array.isArray(itemType) && itemType.includes("boolean")) valueStr = "value.toString()";
|
|
2851
|
+
}
|
|
2852
|
+
}
|
|
2853
|
+
if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
|
|
2854
|
+
if (!hasNonPrimitiveChild) formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => ${variableName}.append(\`${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}]\`, ${valueStr}));\n`;
|
|
2855
|
+
} else formDataValue = `${valueKey}.forEach(value => ${variableName}.append(\`${keyPrefix}${key}${context.output.override.formData.arrayHandling === FormDataArrayHandling.SERIALIZE_WITH_BRACKETS ? "[]" : ""}\`, ${valueStr}));\n`;
|
|
2856
|
+
} else if ((() => {
|
|
2857
|
+
const propType = getSchemaType$1(property);
|
|
2858
|
+
return propType === "number" || Array.isArray(propType) && propType.includes("number") || propType === "integer" || Array.isArray(propType) && propType.includes("integer") || propType === "boolean" || Array.isArray(propType) && propType.includes("boolean");
|
|
2859
|
+
})()) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
2860
|
+
else formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
2861
|
+
let existSubSchemaNullable = false;
|
|
2862
|
+
const combine = getSchemaCombined(property);
|
|
2863
|
+
if (combine) {
|
|
2864
|
+
const subSchemas = combine.map((c) => resolveObject({
|
|
2865
|
+
schema: c,
|
|
2866
|
+
combined: true,
|
|
2867
|
+
context
|
|
2868
|
+
}));
|
|
2869
|
+
if (subSchemas.some((subSchema) => {
|
|
2870
|
+
return [
|
|
2871
|
+
"number",
|
|
2872
|
+
"integer",
|
|
2873
|
+
"boolean"
|
|
2874
|
+
].includes(subSchema.type);
|
|
2875
|
+
})) formDataValue = `${variableName}.append(\`${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
2876
|
+
if (subSchemas.some((subSchema) => {
|
|
2877
|
+
return subSchema.type === "null";
|
|
2878
|
+
})) existSubSchemaNullable = true;
|
|
2790
2879
|
}
|
|
2791
|
-
const
|
|
2792
|
-
const
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
return props?.[prop] && req?.includes(prop);
|
|
2797
|
-
}) && !(() => {
|
|
2798
|
-
const parentProps = parentSchema?.properties;
|
|
2799
|
-
const parentReq = parentSchema?.required;
|
|
2800
|
-
return !!(parentProps?.[prop] && parentReq?.includes(prop));
|
|
2801
|
-
})());
|
|
2802
|
-
if (overrideRequiredProperties.length > 0) return `${joined} & Required<Pick<${joined}, '${overrideRequiredProperties.join("' | '")}'>>`;
|
|
2803
|
-
return joined;
|
|
2804
|
-
}
|
|
2805
|
-
let values = resolvedData.values;
|
|
2806
|
-
if (resolvedData.allProperties.length && context.output.unionAddMissingProperties) {
|
|
2807
|
-
values = [];
|
|
2808
|
-
for (let i = 0; i < resolvedData.values.length; i += 1) {
|
|
2809
|
-
const subSchema = resolvedData.originalSchema[i];
|
|
2810
|
-
if (subSchema?.type !== "object" || !subSchema.properties) {
|
|
2811
|
-
values.push(resolvedData.values[i]);
|
|
2880
|
+
const isRequired = getSchemaRequired(schema)?.includes(key) && !isRequestBodyOptional;
|
|
2881
|
+
const propType = getSchemaType$1(property);
|
|
2882
|
+
if (property.nullable || Array.isArray(propType) && propType.includes("null") || existSubSchemaNullable) {
|
|
2883
|
+
if (isRequired) {
|
|
2884
|
+
formDataValues += `if(${valueKey} !== null) {\n ${formDataValue} }\n`;
|
|
2812
2885
|
continue;
|
|
2813
2886
|
}
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2887
|
+
formDataValues += `if(${valueKey} !== undefined && ${nonOptionalValueKey} !== null) {\n ${formDataValue} }\n`;
|
|
2888
|
+
continue;
|
|
2889
|
+
}
|
|
2890
|
+
if (isRequired) {
|
|
2891
|
+
formDataValues += formDataValue;
|
|
2892
|
+
continue;
|
|
2817
2893
|
}
|
|
2894
|
+
formDataValues += `if(${valueKey} !== undefined) {\n ${formDataValue} }\n`;
|
|
2818
2895
|
}
|
|
2819
|
-
|
|
2820
|
-
return values.join(" | ");
|
|
2896
|
+
return formDataValues;
|
|
2821
2897
|
}
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
const
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
requiredProperties: separator === "allOf" ? schema.required ?? [] : []
|
|
2839
|
-
};
|
|
2840
|
-
for (const subSchema of items) {
|
|
2841
|
-
let propName;
|
|
2842
|
-
if (context.output.override.aliasCombinedTypes) {
|
|
2843
|
-
propName = name ? name + pascal(separator) : void 0;
|
|
2844
|
-
if (propName && resolvedData.schemas.length > 0) propName = propName + pascal(getNumberWord(resolvedData.schemas.length + 1));
|
|
2845
|
-
}
|
|
2846
|
-
if (separator === "allOf" && isSchema(subSchema) && subSchema.required) resolvedData.requiredProperties.push(...subSchema.required);
|
|
2847
|
-
const resolvedValue = resolveObject({
|
|
2848
|
-
schema: subSchema,
|
|
2849
|
-
propName,
|
|
2850
|
-
combined: true,
|
|
2851
|
-
context,
|
|
2852
|
-
formDataContext
|
|
2853
|
-
});
|
|
2854
|
-
const aliasedImports = getAliasedImports({
|
|
2855
|
-
context,
|
|
2856
|
-
name,
|
|
2857
|
-
resolvedValue
|
|
2858
|
-
});
|
|
2859
|
-
const value = getImportAliasForRefOrValue({
|
|
2860
|
-
context,
|
|
2861
|
-
resolvedValue,
|
|
2862
|
-
imports: aliasedImports
|
|
2898
|
+
//#endregion
|
|
2899
|
+
//#region src/getters/body.ts
|
|
2900
|
+
function buildBody(filteredBodyTypes, requestBody, operationName, context) {
|
|
2901
|
+
const imports = filteredBodyTypes.flatMap(({ imports }) => imports);
|
|
2902
|
+
const schemas = filteredBodyTypes.flatMap(({ schemas }) => schemas);
|
|
2903
|
+
const definition = filteredBodyTypes.map(({ value }) => value).join(" | ");
|
|
2904
|
+
const nonReadonlyDefinition = filteredBodyTypes.some((x) => x.hasReadonlyProps) && definition && context.output.override.preserveReadonlyRequestBodies !== "preserve" ? `NonReadonly<${definition}>` : definition;
|
|
2905
|
+
let implementation = generalJSTypesWithArray.includes(definition.toLowerCase()) || filteredBodyTypes.length > 1 ? camel(operationName) + context.output.override.components.requestBodies.suffix : camel(definition);
|
|
2906
|
+
let isOptional = false;
|
|
2907
|
+
if (implementation) {
|
|
2908
|
+
implementation = sanitize(implementation, {
|
|
2909
|
+
underscore: "_",
|
|
2910
|
+
whitespace: "_",
|
|
2911
|
+
dash: true,
|
|
2912
|
+
es5keyword: true,
|
|
2913
|
+
es5IdentifierName: true
|
|
2863
2914
|
});
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
resolvedData.isEnum.push(resolvedValue.isEnum);
|
|
2869
|
-
resolvedData.types.push(resolvedValue.type);
|
|
2870
|
-
resolvedData.isRef.push(resolvedValue.isRef);
|
|
2871
|
-
resolvedData.originalSchema.push(resolvedValue.originalSchema);
|
|
2872
|
-
if (resolvedValue.hasReadonlyProps) resolvedData.hasReadonlyProps = true;
|
|
2873
|
-
const originalProps = resolvedValue.originalSchema.properties;
|
|
2874
|
-
if (resolvedValue.type === "object" && originalProps) resolvedData.allProperties.push(...Object.keys(originalProps));
|
|
2915
|
+
if (isReference(requestBody)) {
|
|
2916
|
+
const { schema: bodySchema } = resolveRef(requestBody, context);
|
|
2917
|
+
isOptional = bodySchema.required !== true;
|
|
2918
|
+
} else isOptional = requestBody.required !== true;
|
|
2875
2919
|
}
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2920
|
+
return {
|
|
2921
|
+
originalSchema: requestBody,
|
|
2922
|
+
definition: nonReadonlyDefinition,
|
|
2923
|
+
implementation,
|
|
2924
|
+
imports,
|
|
2925
|
+
schemas,
|
|
2926
|
+
isOptional,
|
|
2927
|
+
...filteredBodyTypes.length === 1 ? {
|
|
2928
|
+
formData: filteredBodyTypes[0].formData,
|
|
2929
|
+
formUrlEncoded: filteredBodyTypes[0].formUrlEncoded,
|
|
2930
|
+
contentType: filteredBodyTypes[0].contentType
|
|
2931
|
+
} : {
|
|
2932
|
+
formData: "",
|
|
2933
|
+
formUrlEncoded: "",
|
|
2934
|
+
contentType: ""
|
|
2935
|
+
}
|
|
2936
|
+
};
|
|
2937
|
+
}
|
|
2938
|
+
function getBody({ requestBody, operationName, context, contentType }) {
|
|
2939
|
+
return buildBody(filterByContentType(getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context), contentType), requestBody, operationName, context);
|
|
2940
|
+
}
|
|
2941
|
+
/**
|
|
2942
|
+
* Returns per-content-type bodies when `splitByContentType` is enabled.
|
|
2943
|
+
* Each entry includes a `contentTypeSuffix` for generating distinct function names.
|
|
2944
|
+
*/
|
|
2945
|
+
function getBodiesByContentType({ requestBody, operationName, context, contentType }) {
|
|
2946
|
+
const filteredBodyTypes = filterByContentType(getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context, void 0, (item) => `${item.value}::${item.contentType}`), contentType);
|
|
2947
|
+
if (filteredBodyTypes.length <= 1) return [{
|
|
2948
|
+
...buildBody(filteredBodyTypes, requestBody, operationName, context),
|
|
2949
|
+
contentTypeSuffix: ""
|
|
2950
|
+
}];
|
|
2951
|
+
return filteredBodyTypes.map((bodyType) => {
|
|
2952
|
+
const suffix = getContentTypeSuffix(bodyType.contentType);
|
|
2885
2953
|
return {
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
schemas: [...resolvedData.schemas, {
|
|
2889
|
-
imports: resolvedData.imports.filter((toImport) => valueImportSet.has(toImport.alias ?? toImport.name)).map((toImport) => ({
|
|
2890
|
-
...toImport,
|
|
2891
|
-
values: true
|
|
2892
|
-
})),
|
|
2893
|
-
model: newEnum,
|
|
2894
|
-
name
|
|
2895
|
-
}],
|
|
2896
|
-
isEnum: false,
|
|
2897
|
-
type: "object",
|
|
2898
|
-
isRef: false,
|
|
2899
|
-
hasReadonlyProps: resolvedData.hasReadonlyProps,
|
|
2900
|
-
dependencies: resolvedData.dependencies,
|
|
2901
|
-
example: schema.example,
|
|
2902
|
-
examples: resolveExampleRefs(schema.examples, context)
|
|
2954
|
+
...buildBody([bodyType], requestBody, operationName, context),
|
|
2955
|
+
contentTypeSuffix: suffix
|
|
2903
2956
|
};
|
|
2904
|
-
}
|
|
2905
|
-
let resolvedValue;
|
|
2906
|
-
const normalizedProperties = normalizedSchema.properties;
|
|
2907
|
-
const schemaOneOf = schema.oneOf;
|
|
2908
|
-
const schemaAnyOf = schema.anyOf;
|
|
2909
|
-
if (normalizedProperties) resolvedValue = getScalar({
|
|
2910
|
-
item: Object.fromEntries(Object.entries(normalizedSchema).filter(([key]) => key !== separator)),
|
|
2911
|
-
name,
|
|
2912
|
-
context,
|
|
2913
|
-
formDataContext
|
|
2914
2957
|
});
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
return
|
|
2927
|
-
|
|
2928
|
-
resolvedData,
|
|
2929
|
-
separator,
|
|
2930
|
-
resolvedValue,
|
|
2931
|
-
context,
|
|
2932
|
-
parentSchema: normalizedSchema
|
|
2933
|
-
}) + nullable),
|
|
2934
|
-
imports: resolvedValue ? [...resolvedData.imports, ...resolvedValue.imports] : resolvedData.imports,
|
|
2935
|
-
schemas: resolvedValue ? [...resolvedData.schemas, ...resolvedValue.schemas] : resolvedData.schemas,
|
|
2936
|
-
dependencies: resolvedValue ? [...resolvedData.dependencies, ...resolvedValue.dependencies] : resolvedData.dependencies,
|
|
2937
|
-
isEnum: false,
|
|
2938
|
-
type: "object",
|
|
2939
|
-
isRef: false,
|
|
2940
|
-
hasReadonlyProps: resolvedData.hasReadonlyProps || (resolvedValue?.hasReadonlyProps ?? false),
|
|
2941
|
-
example: schema.example,
|
|
2942
|
-
examples: resolveExampleRefs(schema.examples, context)
|
|
2943
|
-
};
|
|
2958
|
+
}
|
|
2959
|
+
const CONTENT_TYPE_SUFFIX_MAP = {
|
|
2960
|
+
"application/json": "Json",
|
|
2961
|
+
"multipart/form-data": "FormData",
|
|
2962
|
+
"application/x-www-form-urlencoded": "UrlEncoded",
|
|
2963
|
+
"text/plain": "Text",
|
|
2964
|
+
"application/xml": "Xml",
|
|
2965
|
+
"text/xml": "Xml",
|
|
2966
|
+
"application/octet-stream": "Blob"
|
|
2967
|
+
};
|
|
2968
|
+
function getContentTypeSuffix(contentType) {
|
|
2969
|
+
if (CONTENT_TYPE_SUFFIX_MAP[contentType]) return CONTENT_TYPE_SUFFIX_MAP[contentType];
|
|
2970
|
+
return (contentType.split("/")[1] ?? contentType).split(/[-+.]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
2944
2971
|
}
|
|
2945
2972
|
//#endregion
|
|
2946
2973
|
//#region src/getters/discriminators.ts
|
|
@@ -4636,8 +4663,8 @@ function getSchema({ schema: { imports, model }, header, namingConvention = Nami
|
|
|
4636
4663
|
file += model;
|
|
4637
4664
|
return file;
|
|
4638
4665
|
}
|
|
4639
|
-
function getPath(path
|
|
4640
|
-
return
|
|
4666
|
+
function getPath(path, name, fileExtension) {
|
|
4667
|
+
return nodePath.join(path, `${name}${fileExtension}`);
|
|
4641
4668
|
}
|
|
4642
4669
|
function writeModelInline(acc, model) {
|
|
4643
4670
|
return acc + `${model}\n`;
|
|
@@ -4689,7 +4716,7 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
4689
4716
|
});
|
|
4690
4717
|
}
|
|
4691
4718
|
if (indexFiles) {
|
|
4692
|
-
const schemaFilePath =
|
|
4719
|
+
const schemaFilePath = nodePath.join(schemaPath, `index.ts`);
|
|
4693
4720
|
await fs$1.ensureFile(schemaFilePath);
|
|
4694
4721
|
const ext = getImportExtension(fileExtension, tsconfig);
|
|
4695
4722
|
const conventionNamesSet = new Set(Object.values(schemaGroups).map((group) => conventionName(group[0].name, namingConvention)));
|
|
@@ -5000,7 +5027,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
5000
5027
|
packageJson: output.packageJson,
|
|
5001
5028
|
output
|
|
5002
5029
|
});
|
|
5003
|
-
const schemasPath = !output.schemas && needSchema ?
|
|
5030
|
+
const schemasPath = !output.schemas && needSchema ? nodePath.join(dirname, filename + ".schemas" + extension) : void 0;
|
|
5004
5031
|
if (schemasPath) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
|
|
5005
5032
|
if (mutators) implementationData += generateMutatorImports({
|
|
5006
5033
|
mutators,
|
|
@@ -5022,7 +5049,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
5022
5049
|
}
|
|
5023
5050
|
implementationData += `\n${implementation}`;
|
|
5024
5051
|
const implementationFilename = filename + (OutputClient.ANGULAR === output.client ? ".service" : "") + extension;
|
|
5025
|
-
const implementationPath =
|
|
5052
|
+
const implementationPath = nodePath.join(dirname, implementationFilename);
|
|
5026
5053
|
await writeGeneratedFile(implementationPath, implementationData);
|
|
5027
5054
|
const mockPaths = [];
|
|
5028
5055
|
for (const mockOutput of mockOutputs) {
|
|
@@ -5039,7 +5066,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
5039
5066
|
options: entry
|
|
5040
5067
|
});
|
|
5041
5068
|
mockData += `\n${mockOutput.implementation}`;
|
|
5042
|
-
const mockPath =
|
|
5069
|
+
const mockPath = nodePath.join(dirname, filename + "." + getMockFileExtensionByTypeName(entry) + extension);
|
|
5043
5070
|
await writeGeneratedFile(mockPath, mockData);
|
|
5044
5071
|
mockPaths.push(mockPath);
|
|
5045
5072
|
}
|
|
@@ -5235,7 +5262,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
5235
5262
|
const indexFilePathsByType = /* @__PURE__ */ new Map();
|
|
5236
5263
|
if (output.mock.indexMockFiles) for (const entry of generatorEntries) {
|
|
5237
5264
|
const ext = getMockFileExtensionByTypeName(entry);
|
|
5238
|
-
const indexPath =
|
|
5265
|
+
const indexPath = nodePath.join(dirname, `index.${ext}${extension}`);
|
|
5239
5266
|
indexFilePathsByType.set(ext, indexPath);
|
|
5240
5267
|
await fs$1.outputFile(indexPath, "");
|
|
5241
5268
|
}
|
|
@@ -5244,19 +5271,19 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
5244
5271
|
try {
|
|
5245
5272
|
const { imports, implementation, mockOutputs, mutators, clientMutators, formData, fetchReviver, formUrlEncoded, paramsSerializer, paramsFilter } = target;
|
|
5246
5273
|
let implementationData = header;
|
|
5247
|
-
const importerPath =
|
|
5274
|
+
const importerPath = nodePath.join(dirname, tag, tag + extension);
|
|
5248
5275
|
const relativeSchemasPath = output.schemas ? getRelativeImportPath(importerPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "../" + filename + ".schemas" + extension.replace(/\.ts$/, "");
|
|
5249
5276
|
const tagNames = new Set(tagEntries.map(([t]) => t));
|
|
5250
5277
|
const serviceSuffix = OutputClient.ANGULAR === output.client ? ".service" : "";
|
|
5251
5278
|
const importsForBuilder = generateImportsForBuilder(output, imports.map((imp) => {
|
|
5252
5279
|
if (!imp.importPath) return imp;
|
|
5253
5280
|
if (!imp.importPath.startsWith(".")) return imp;
|
|
5254
|
-
const resolvedPath =
|
|
5255
|
-
const targetBasename =
|
|
5281
|
+
const resolvedPath = nodePath.resolve(dirname, imp.importPath);
|
|
5282
|
+
const targetBasename = nodePath.basename(resolvedPath);
|
|
5256
5283
|
let targetFile;
|
|
5257
5284
|
if (tagNames.has(targetBasename)) {
|
|
5258
5285
|
const tagFilename = targetBasename + serviceSuffix + extension;
|
|
5259
|
-
targetFile =
|
|
5286
|
+
targetFile = nodePath.join(resolvedPath, tagFilename);
|
|
5260
5287
|
} else targetFile = resolvedPath + extension;
|
|
5261
5288
|
const adjustedPath = getRelativeImportPath(importerPath, targetFile);
|
|
5262
5289
|
return {
|
|
@@ -5277,7 +5304,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
5277
5304
|
packageJson: output.packageJson,
|
|
5278
5305
|
output
|
|
5279
5306
|
});
|
|
5280
|
-
const schemasPath = !output.schemas && needSchema ?
|
|
5307
|
+
const schemasPath = !output.schemas && needSchema ? nodePath.join(dirname, filename + ".schemas" + extension) : void 0;
|
|
5281
5308
|
if (schemasPath) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
|
|
5282
5309
|
if (mutators) implementationData += generateMutatorImports({
|
|
5283
5310
|
mutators,
|
|
@@ -5318,7 +5345,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
5318
5345
|
}
|
|
5319
5346
|
implementationData += `\n${implementation}`;
|
|
5320
5347
|
const implementationFilename = tag + (OutputClient.ANGULAR === output.client ? ".service" : "") + extension;
|
|
5321
|
-
const implementationPath =
|
|
5348
|
+
const implementationPath = nodePath.join(dirname, tag, implementationFilename);
|
|
5322
5349
|
await writeGeneratedFile(implementationPath, implementationData);
|
|
5323
5350
|
const mockPaths = [];
|
|
5324
5351
|
for (const mockOutput of mockOutputs) {
|
|
@@ -5335,7 +5362,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
5335
5362
|
options: entry
|
|
5336
5363
|
});
|
|
5337
5364
|
mockData += `\n${mockOutput.implementation}`;
|
|
5338
|
-
const mockPath =
|
|
5365
|
+
const mockPath = nodePath.join(dirname, tag, tag + "." + getMockFileExtensionByTypeName(entry) + extension);
|
|
5339
5366
|
await writeGeneratedFile(mockPath, mockData);
|
|
5340
5367
|
mockPaths.push(mockPath);
|
|
5341
5368
|
}
|
|
@@ -5413,7 +5440,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
5413
5440
|
options: entry && !isFunction(entry) ? entry : void 0
|
|
5414
5441
|
});
|
|
5415
5442
|
}
|
|
5416
|
-
const schemasPath = !output.schemas && needSchema ?
|
|
5443
|
+
const schemasPath = !output.schemas && needSchema ? nodePath.join(dirname, filename + ".schemas" + extension) : void 0;
|
|
5417
5444
|
if (schemasPath) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
|
|
5418
5445
|
if (mutators) data += generateMutatorImports({
|
|
5419
5446
|
mutators,
|
|
@@ -5439,7 +5466,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
5439
5466
|
data += "\n\n";
|
|
5440
5467
|
data += implementationMock;
|
|
5441
5468
|
}
|
|
5442
|
-
const implementationPath =
|
|
5469
|
+
const implementationPath = nodePath.join(dirname, `${kebab(tag)}${extension}`);
|
|
5443
5470
|
await writeGeneratedFile(implementationPath, data);
|
|
5444
5471
|
return [implementationPath, ...schemasPath ? [schemasPath] : []];
|
|
5445
5472
|
} catch (error) {
|
|
@@ -5448,6 +5475,6 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
5448
5475
|
}))).flat();
|
|
5449
5476
|
}
|
|
5450
5477
|
//#endregion
|
|
5451
|
-
export { BODY_TYPE_NAME, DefaultTag, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NAMED_COMPONENT_SECTIONS, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, SupportedFormatter, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, addDependency, asyncReduce, buildAngularParamsFilterExpression, camel, collectReferencedComponents, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, escapeRegExp, filterByContentType, filteredVerbs, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFormDataAndUrlEncodedFunction, generateImports, generateModelInline, generateModelsInline, generateMutator, generateMutatorConfig, generateMutatorImports, generateMutatorRequestOptions, generateOptions, generateParameterDefinition, generateQueryParamsAxiosConfig, generateSchemasDefinition, generateTarget, generateTargetForTags, generateVerbImports, generateVerbOptions, generateVerbsOptions, getAngularFilteredParamsCallExpression, getAngularFilteredParamsExpression, getAngularFilteredParamsHelperBody, getArray, getBaseUrlRuntimeImports, getBodiesByContentType, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getImportExtension, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getSuccessResponseType, getTypedResponse, getWarningCount, isBinaryContentType, isBoolean, isComponentRef, isDirectory, isFakerMock, isFunction, isModule, isMswMock, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, isVerbose, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, logVerbose, logWarning, makeRouteSafe, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resetWarnings, resolveDiscriminators, resolveExampleRefs, resolveInstalledVersion, resolveInstalledVersions, resolveObject, resolveRef, resolveValue, sanitize, setVerbose, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, wrapRouteParameters, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
|
|
5478
|
+
export { BODY_TYPE_NAME, DefaultTag, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NAMED_COMPONENT_SECTIONS, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, SupportedFormatter, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, addDependency, asyncReduce, buildAngularParamsFilterExpression, camel, collectReferencedComponents, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, escapeRegExp, filterByContentType, filteredVerbs, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFormDataAndUrlEncodedFunction, generateImports, generateModelInline, generateModelsInline, generateMutator, generateMutatorConfig, generateMutatorImports, generateMutatorRequestOptions, generateOptions, generateParameterDefinition, generateQueryParamsAxiosConfig, generateSchemasDefinition, generateTarget, generateTargetForTags, generateVerbImports, generateVerbOptions, generateVerbsOptions, getAngularFilteredParamsCallExpression, getAngularFilteredParamsExpression, getAngularFilteredParamsHelperBody, getArray, getBaseUrlRuntimeImports, getBodiesByContentType, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getImportExtension, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getSuccessResponseType, getTypedResponse, getWarningCount, isBinaryContentType, isBinaryScalarSchema, isBoolean, isComponentRef, isDirectory, isFakerMock, isFunction, isModule, isMswMock, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, isVerbose, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, logVerbose, logWarning, makeRouteSafe, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resetWarnings, resolveDiscriminators, resolveExampleRefs, resolveInstalledVersion, resolveInstalledVersions, resolveObject, resolveRef, resolveValue, sanitize, setVerbose, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, wrapRouteParameters, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
|
|
5452
5479
|
|
|
5453
5480
|
//# sourceMappingURL=index.mjs.map
|