@orval/core 8.12.2 → 8.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +182 -3
- package/dist/index.mjs +2357 -1473
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -143,6 +143,16 @@ const TEMPLATE_TAG_REGEX = /\${(.+?)}/g;
|
|
|
143
143
|
function isReference(obj) {
|
|
144
144
|
return !isNullish$1(obj) && Object.hasOwn(obj, "$ref");
|
|
145
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Discriminator helper for {@link OpenApiDynamicReferenceObject}.
|
|
148
|
+
*
|
|
149
|
+
* Returns `true` when `obj` has a `$dynamicRef` string property,
|
|
150
|
+
* indicating it is an OpenAPI 3.1 dynamic reference rather than a
|
|
151
|
+
* static `$ref`.
|
|
152
|
+
*/
|
|
153
|
+
function isDynamicReference(obj) {
|
|
154
|
+
return !isNullish$1(obj) && Object.hasOwn(obj, "$dynamicRef") && typeof obj.$dynamicRef === "string";
|
|
155
|
+
}
|
|
146
156
|
function isDirectory(pathValue) {
|
|
147
157
|
return !nodePath.extname(pathValue);
|
|
148
158
|
}
|
|
@@ -741,13 +751,21 @@ function count(str = "", key) {
|
|
|
741
751
|
var path_exports = /* @__PURE__ */ __exportAll({
|
|
742
752
|
getRelativeImportPath: () => getRelativeImportPath,
|
|
743
753
|
getSchemaFileName: () => getSchemaFileName,
|
|
754
|
+
isAbsolute: () => isAbsolute,
|
|
744
755
|
join: () => join,
|
|
745
756
|
joinSafe: () => joinSafe,
|
|
746
757
|
normalizeSafe: () => normalizeSafe,
|
|
747
758
|
relativeSafe: () => relativeSafe,
|
|
759
|
+
resolve: () => resolve,
|
|
748
760
|
separator: () => "/",
|
|
749
761
|
toUnix: () => toUnix
|
|
750
762
|
});
|
|
763
|
+
function isAbsolute(value) {
|
|
764
|
+
return nodePath.isAbsolute(value);
|
|
765
|
+
}
|
|
766
|
+
function resolve(...args) {
|
|
767
|
+
return toUnix(nodePath.resolve(...args));
|
|
768
|
+
}
|
|
751
769
|
function toUnix(value) {
|
|
752
770
|
value = value.replaceAll("\\", "/");
|
|
753
771
|
value = value.replaceAll(/(?<!^)\/+/g, "/");
|
|
@@ -1357,1591 +1375,1996 @@ function getRefInfo($ref, context) {
|
|
|
1357
1375
|
refPaths
|
|
1358
1376
|
};
|
|
1359
1377
|
}
|
|
1360
|
-
//#endregion
|
|
1361
|
-
//#region src/resolvers/ref.ts
|
|
1362
|
-
const REF_NOT_FOUND_PREFIX = "Oops... 🍻. Ref not found";
|
|
1363
1378
|
/**
|
|
1364
|
-
*
|
|
1365
|
-
* nested schema refs and collecting imports along the way.
|
|
1366
|
-
*
|
|
1367
|
-
* Handles OpenAPI 3.0 `nullable` and 3.1 type-array hints on direct refs.
|
|
1379
|
+
* Extracts the anchor name from a fragment-only `$dynamicRef` (e.g. `#category` → `category`).
|
|
1368
1380
|
*
|
|
1369
|
-
*
|
|
1370
|
-
*
|
|
1381
|
+
* Returns `undefined` for external-document `$dynamicRef` values (e.g. `other.json#anchor`)
|
|
1382
|
+
* which are not supported.
|
|
1371
1383
|
*/
|
|
1372
|
-
function
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
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
|
-
}
|
|
1384
|
+
function getDynamicAnchorName(dynamicRef) {
|
|
1385
|
+
if (!dynamicRef.startsWith("#") || dynamicRef.length <= 1) return;
|
|
1386
|
+
return dynamicRef.slice(1);
|
|
1387
|
+
}
|
|
1388
|
+
//#endregion
|
|
1389
|
+
//#region src/getters/imports.ts
|
|
1390
|
+
function getAliasedImports({ name, resolvedValue, context }) {
|
|
1391
|
+
return context.output.schemas && resolvedValue.isRef ? resolvedValue.imports.map((imp) => {
|
|
1392
|
+
if (!needCreateImportAlias({
|
|
1393
|
+
name,
|
|
1394
|
+
imp
|
|
1395
|
+
})) return imp;
|
|
1398
1396
|
return {
|
|
1399
|
-
|
|
1400
|
-
|
|
1397
|
+
...imp,
|
|
1398
|
+
alias: `__${imp.name}`
|
|
1401
1399
|
};
|
|
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
|
-
}]);
|
|
1400
|
+
}) : resolvedValue.imports;
|
|
1410
1401
|
}
|
|
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
|
-
};
|
|
1402
|
+
function needCreateImportAlias({ imp, name }) {
|
|
1403
|
+
return !imp.alias && imp.name === name;
|
|
1445
1404
|
}
|
|
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
|
-
})();
|
|
1405
|
+
function getImportAliasForRefOrValue({ context, imports, resolvedValue }) {
|
|
1406
|
+
if (!context.output.schemas || !resolvedValue.isRef) return resolvedValue.value;
|
|
1407
|
+
return imports.find((imp) => imp.name === resolvedValue.value)?.alias ?? resolvedValue.value;
|
|
1460
1408
|
}
|
|
1461
1409
|
//#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
|
-
};
|
|
1410
|
+
//#region src/getters/combine.ts
|
|
1411
|
+
const mergeableAllOfKeys = new Set([
|
|
1412
|
+
"type",
|
|
1413
|
+
"properties",
|
|
1414
|
+
"required"
|
|
1415
|
+
]);
|
|
1416
|
+
function isMergeableAllOfObject(schema) {
|
|
1417
|
+
if (isNullish$1(schema.properties)) return false;
|
|
1418
|
+
if (schema.allOf || schema.anyOf || schema.oneOf) return false;
|
|
1419
|
+
if (!isNullish$1(schema.type) && schema.type !== "object") return false;
|
|
1420
|
+
return Object.keys(schema).every((key) => mergeableAllOfKeys.has(key));
|
|
1421
|
+
}
|
|
1422
|
+
function normalizeAllOfSchema(schema) {
|
|
1423
|
+
const schemaAllOf = schema.allOf;
|
|
1424
|
+
if (!schemaAllOf) return schema;
|
|
1425
|
+
let didMerge = false;
|
|
1426
|
+
const schemaProperties = schema.properties;
|
|
1427
|
+
const schemaRequired = schema.required;
|
|
1428
|
+
const mergedProperties = schemaProperties ? { ...schemaProperties } : {};
|
|
1429
|
+
const mergedRequired = new Set(schemaRequired);
|
|
1430
|
+
const remainingAllOf = [];
|
|
1431
|
+
for (const subSchema of schemaAllOf) {
|
|
1432
|
+
if (isSchema(subSchema) && isMergeableAllOfObject(subSchema)) {
|
|
1433
|
+
didMerge = true;
|
|
1434
|
+
if (subSchema.properties) Object.assign(mergedProperties, subSchema.properties);
|
|
1435
|
+
const subRequired = subSchema.required;
|
|
1436
|
+
if (subRequired) for (const prop of subRequired) mergedRequired.add(prop);
|
|
1437
|
+
continue;
|
|
1492
1438
|
}
|
|
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
|
-
};
|
|
1439
|
+
remainingAllOf.push(subSchema);
|
|
1521
1440
|
}
|
|
1441
|
+
if (!didMerge || remainingAllOf.length === 0) return schema;
|
|
1522
1442
|
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
|
|
1443
|
+
...schema,
|
|
1444
|
+
...Object.keys(mergedProperties).length > 0 && { properties: mergedProperties },
|
|
1445
|
+
...mergedRequired.size > 0 && { required: [...mergedRequired] },
|
|
1446
|
+
...remainingAllOf.length > 0 && { allOf: remainingAllOf }
|
|
1566
1447
|
};
|
|
1567
1448
|
}
|
|
1568
|
-
function
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1449
|
+
function combineValues({ resolvedData, resolvedValue, separator, context, parentSchema }) {
|
|
1450
|
+
if (resolvedData.isEnum.every(Boolean)) return `${resolvedData.values.join(` | `)}${resolvedValue ? ` | ${resolvedValue.value}` : ""}`;
|
|
1451
|
+
if (separator === "allOf") {
|
|
1452
|
+
let resolvedDataValue = resolvedData.values.map((v) => v.includes(" | ") ? `(${v})` : v).join(` & `);
|
|
1453
|
+
if (resolvedData.originalSchema.length > 0 && resolvedValue) {
|
|
1454
|
+
const discriminatedPropertySchemas = resolvedData.originalSchema.filter((s) => {
|
|
1455
|
+
const disc = s?.discriminator;
|
|
1456
|
+
return disc && resolvedValue.value.includes(` ${disc.propertyName}:`);
|
|
1457
|
+
});
|
|
1458
|
+
if (discriminatedPropertySchemas.length > 0) resolvedDataValue = `Omit<${resolvedDataValue}, '${discriminatedPropertySchemas.map((s) => s.discriminator?.propertyName).join("' | '")}'>`;
|
|
1459
|
+
}
|
|
1460
|
+
const resolvedValueStr = resolvedValue?.value.includes(" | ") ? `(${resolvedValue.value})` : resolvedValue?.value;
|
|
1461
|
+
const joined = `${resolvedDataValue}${resolvedValue ? ` & ${resolvedValueStr}` : ""}`;
|
|
1462
|
+
const overrideRequiredProperties = resolvedData.requiredProperties.filter((prop) => !resolvedData.originalSchema.some((schema) => {
|
|
1463
|
+
const props = schema?.properties;
|
|
1464
|
+
const req = schema?.required;
|
|
1465
|
+
return props?.[prop] && req?.includes(prop);
|
|
1466
|
+
}) && !(() => {
|
|
1467
|
+
const parentProps = parentSchema?.properties;
|
|
1468
|
+
const parentReq = parentSchema?.required;
|
|
1469
|
+
return !!(parentProps?.[prop] && parentReq?.includes(prop));
|
|
1470
|
+
})());
|
|
1471
|
+
if (overrideRequiredProperties.length > 0) return `${joined} & Required<Pick<${joined}, '${overrideRequiredProperties.join("' | '")}'>>`;
|
|
1472
|
+
return joined;
|
|
1473
|
+
}
|
|
1474
|
+
let values = resolvedData.values;
|
|
1475
|
+
if (resolvedData.allProperties.length && context.output.unionAddMissingProperties) {
|
|
1476
|
+
values = [];
|
|
1477
|
+
for (let i = 0; i < resolvedData.values.length; i += 1) {
|
|
1478
|
+
const subSchema = resolvedData.originalSchema[i];
|
|
1479
|
+
if (subSchema?.type !== "object" || !subSchema.properties) {
|
|
1480
|
+
values.push(resolvedData.values[i]);
|
|
1481
|
+
continue;
|
|
1482
|
+
}
|
|
1483
|
+
const subSchemaProps = subSchema.properties;
|
|
1484
|
+
const missingProperties = unique(resolvedData.allProperties.filter((p) => !Object.keys(subSchemaProps).includes(p)));
|
|
1485
|
+
values.push(`${resolvedData.values[i]}${missingProperties.length > 0 ? ` & {${missingProperties.map((p) => `${p}?: never`).join("; ")}}` : ""}`);
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
if (resolvedValue) return `(${values.join(` & ${resolvedValue.value}) | (`)} & ${resolvedValue.value})`;
|
|
1489
|
+
return values.join(" | ");
|
|
1490
|
+
}
|
|
1491
|
+
function combineSchemas({ name, schema, separator, context, nullable, formDataContext }) {
|
|
1492
|
+
const normalizedSchema = separator === "allOf" && !context.output.override.aliasCombinedTypes && !schema.oneOf && !schema.anyOf ? normalizeAllOfSchema(schema) : schema;
|
|
1493
|
+
const items = normalizedSchema[separator] ?? [];
|
|
1494
|
+
const resolvedData = {
|
|
1495
|
+
values: [],
|
|
1496
|
+
imports: [],
|
|
1497
|
+
schemas: [],
|
|
1498
|
+
isEnum: [],
|
|
1499
|
+
isRef: [],
|
|
1500
|
+
types: [],
|
|
1501
|
+
dependencies: [],
|
|
1502
|
+
originalSchema: [],
|
|
1503
|
+
allProperties: [],
|
|
1504
|
+
hasReadonlyProps: false,
|
|
1505
|
+
example: schema.example,
|
|
1506
|
+
examples: resolveExampleRefs(schema.examples, context),
|
|
1507
|
+
requiredProperties: separator === "allOf" ? schema.required ?? [] : []
|
|
1583
1508
|
};
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1509
|
+
for (const subSchema of items) {
|
|
1510
|
+
let propName;
|
|
1511
|
+
if (context.output.override.aliasCombinedTypes) {
|
|
1512
|
+
propName = name ? name + pascal(separator) : void 0;
|
|
1513
|
+
if (propName && resolvedData.schemas.length > 0) propName = propName + pascal(getNumberWord(resolvedData.schemas.length + 1));
|
|
1514
|
+
}
|
|
1515
|
+
if (separator === "allOf" && isSchema(subSchema) && subSchema.required) resolvedData.requiredProperties.push(...subSchema.required);
|
|
1516
|
+
const resolvedValue = resolveObject({
|
|
1517
|
+
schema: subSchema,
|
|
1518
|
+
propName,
|
|
1519
|
+
combined: true,
|
|
1520
|
+
context,
|
|
1521
|
+
formDataContext
|
|
1522
|
+
});
|
|
1523
|
+
const aliasedImports = getAliasedImports({
|
|
1524
|
+
context,
|
|
1525
|
+
name,
|
|
1526
|
+
resolvedValue
|
|
1527
|
+
});
|
|
1528
|
+
const value = getImportAliasForRefOrValue({
|
|
1529
|
+
context,
|
|
1530
|
+
resolvedValue,
|
|
1531
|
+
imports: aliasedImports
|
|
1532
|
+
});
|
|
1533
|
+
resolvedData.values.push(value);
|
|
1534
|
+
resolvedData.imports.push(...aliasedImports);
|
|
1535
|
+
resolvedData.schemas.push(...resolvedValue.schemas);
|
|
1536
|
+
resolvedData.dependencies.push(...resolvedValue.dependencies);
|
|
1537
|
+
resolvedData.isEnum.push(resolvedValue.isEnum);
|
|
1538
|
+
resolvedData.types.push(resolvedValue.type);
|
|
1539
|
+
resolvedData.isRef.push(resolvedValue.isRef);
|
|
1540
|
+
resolvedData.originalSchema.push(resolvedValue.originalSchema);
|
|
1541
|
+
if (resolvedValue.hasReadonlyProps) resolvedData.hasReadonlyProps = true;
|
|
1542
|
+
const originalProps = resolvedValue.originalSchema.properties;
|
|
1543
|
+
if (resolvedValue.type === "object" && originalProps) resolvedData.allProperties.push(...Object.keys(originalProps));
|
|
1544
|
+
}
|
|
1545
|
+
const isAllEnums = resolvedData.isEnum.every(Boolean);
|
|
1546
|
+
const isNullableEnumComposition = (separator === "anyOf" || separator === "oneOf") && !isAllEnums && resolvedData.isEnum.some(Boolean) && resolvedData.isEnum.every((isEnum, index) => isEnum && !resolvedData.isRef[index] || resolvedData.types[index] === "null");
|
|
1547
|
+
if (isAllEnums && name && items.length > 1 && context.output.override.enumGenerationType !== EnumGeneration.UNION) {
|
|
1548
|
+
const { value: combinedEnumValue, valueImports, hasNull } = getCombinedEnumValue(resolvedData.values.map((value, index) => ({
|
|
1549
|
+
value,
|
|
1550
|
+
isRef: resolvedData.isRef[index],
|
|
1551
|
+
schema: resolvedData.originalSchema[index]
|
|
1552
|
+
})));
|
|
1553
|
+
const newEnum = `export const ${pascal(name)} = ${combinedEnumValue}`;
|
|
1554
|
+
const valueImportSet = new Set(valueImports);
|
|
1555
|
+
const typeSuffix = `${nullable}${hasNull && !nullable.includes("null") ? " | null" : ""}`;
|
|
1587
1556
|
return {
|
|
1588
|
-
value:
|
|
1589
|
-
imports: [{ name:
|
|
1590
|
-
schemas: [...
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1557
|
+
value: `typeof ${pascal(name)}[keyof typeof ${pascal(name)}]${typeSuffix}`,
|
|
1558
|
+
imports: [{ name: pascal(name) }],
|
|
1559
|
+
schemas: [...resolvedData.schemas, {
|
|
1560
|
+
imports: resolvedData.imports.filter((toImport) => valueImportSet.has(toImport.alias ?? toImport.name)).map((toImport) => ({
|
|
1561
|
+
...toImport,
|
|
1562
|
+
values: true
|
|
1563
|
+
})),
|
|
1564
|
+
model: newEnum,
|
|
1565
|
+
name
|
|
1595
1566
|
}],
|
|
1596
1567
|
isEnum: false,
|
|
1597
|
-
type: "
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1568
|
+
type: "object",
|
|
1569
|
+
isRef: false,
|
|
1570
|
+
hasReadonlyProps: resolvedData.hasReadonlyProps,
|
|
1571
|
+
dependencies: resolvedData.dependencies,
|
|
1572
|
+
example: schema.example,
|
|
1573
|
+
examples: resolveExampleRefs(schema.examples, context)
|
|
1602
1574
|
};
|
|
1603
1575
|
}
|
|
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,
|
|
1576
|
+
let resolvedValue;
|
|
1577
|
+
const normalizedProperties = normalizedSchema.properties;
|
|
1578
|
+
const schemaOneOf = schema.oneOf;
|
|
1579
|
+
const schemaAnyOf = schema.anyOf;
|
|
1580
|
+
if (normalizedProperties) resolvedValue = getScalar({
|
|
1581
|
+
item: Object.fromEntries(Object.entries(normalizedSchema).filter(([key]) => key !== separator)),
|
|
1582
|
+
name,
|
|
1620
1583
|
context,
|
|
1621
1584
|
formDataContext
|
|
1622
1585
|
});
|
|
1623
|
-
|
|
1624
|
-
|
|
1586
|
+
else if (separator === "allOf" && (schemaOneOf || schemaAnyOf)) {
|
|
1587
|
+
const siblingCombiner = schemaOneOf ? "oneOf" : "anyOf";
|
|
1588
|
+
const siblingSchemas = schemaOneOf ?? schemaAnyOf;
|
|
1589
|
+
resolvedValue = combineSchemas({
|
|
1590
|
+
schema: { [siblingCombiner]: siblingSchemas },
|
|
1591
|
+
name,
|
|
1592
|
+
separator: siblingCombiner,
|
|
1593
|
+
context,
|
|
1594
|
+
nullable: ""
|
|
1595
|
+
});
|
|
1596
|
+
}
|
|
1597
|
+
return {
|
|
1598
|
+
value: dedupeUnionType(combineValues({
|
|
1599
|
+
resolvedData,
|
|
1600
|
+
separator,
|
|
1601
|
+
resolvedValue,
|
|
1602
|
+
context,
|
|
1603
|
+
parentSchema: normalizedSchema
|
|
1604
|
+
}) + nullable),
|
|
1605
|
+
imports: resolvedValue ? [...resolvedData.imports, ...resolvedValue.imports] : resolvedData.imports,
|
|
1606
|
+
schemas: resolvedValue ? [...resolvedData.schemas, ...resolvedValue.schemas] : resolvedData.schemas,
|
|
1607
|
+
dependencies: resolvedValue ? [...resolvedData.dependencies, ...resolvedValue.dependencies] : resolvedData.dependencies,
|
|
1608
|
+
isEnum: isNullableEnumComposition,
|
|
1609
|
+
type: "object",
|
|
1610
|
+
isRef: false,
|
|
1611
|
+
hasReadonlyProps: resolvedData.hasReadonlyProps || (resolvedValue?.hasReadonlyProps ?? false),
|
|
1612
|
+
example: schema.example,
|
|
1613
|
+
examples: resolveExampleRefs(schema.examples, context)
|
|
1614
|
+
};
|
|
1625
1615
|
}
|
|
1626
1616
|
//#endregion
|
|
1627
|
-
//#region src/getters/
|
|
1617
|
+
//#region src/getters/keys.ts
|
|
1618
|
+
function getKey(key) {
|
|
1619
|
+
return keyword.isIdentifierNameES5(key) ? key : `'${key}'`;
|
|
1620
|
+
}
|
|
1621
|
+
//#endregion
|
|
1622
|
+
//#region src/getters/object.ts
|
|
1623
|
+
function getPropertyNamesEnumKeyType(item) {
|
|
1624
|
+
if (!("propertyNames" in item) || !item.propertyNames) return;
|
|
1625
|
+
const propertyNames = item.propertyNames;
|
|
1626
|
+
if (Array.isArray(propertyNames.enum)) {
|
|
1627
|
+
const enumValues = propertyNames.enum.filter((val) => isString(val));
|
|
1628
|
+
if (enumValues.length > 0) return {
|
|
1629
|
+
value: enumValues.map((val) => `'${escape(val)}'`).join(" | "),
|
|
1630
|
+
imports: [],
|
|
1631
|
+
dependencies: []
|
|
1632
|
+
};
|
|
1633
|
+
}
|
|
1634
|
+
if (isString(propertyNames.const)) return {
|
|
1635
|
+
value: `'${escape(propertyNames.const)}'`,
|
|
1636
|
+
imports: [],
|
|
1637
|
+
dependencies: []
|
|
1638
|
+
};
|
|
1639
|
+
}
|
|
1628
1640
|
/**
|
|
1629
|
-
*
|
|
1641
|
+
* Resolve a narrowed key type from OpenAPI 3.1 propertyNames.
|
|
1642
|
+
* Supports inline enum/const and $ref string enums.
|
|
1643
|
+
*/
|
|
1644
|
+
function getPropertyNamesKeyType(item, context) {
|
|
1645
|
+
const inlineKeyType = getPropertyNamesEnumKeyType(item);
|
|
1646
|
+
if (inlineKeyType) return inlineKeyType;
|
|
1647
|
+
const propertyNames = item.propertyNames;
|
|
1648
|
+
if (!propertyNames || !isReference(propertyNames)) return;
|
|
1649
|
+
const resolvedValue = resolveValue({
|
|
1650
|
+
schema: propertyNames,
|
|
1651
|
+
context
|
|
1652
|
+
});
|
|
1653
|
+
const resolvedConst = resolvedValue.originalSchema.const;
|
|
1654
|
+
const isStringConst = resolvedValue.type === "string" && isString(resolvedConst);
|
|
1655
|
+
if (!resolvedValue.isEnum && !isStringConst) return;
|
|
1656
|
+
return {
|
|
1657
|
+
value: resolvedValue.value,
|
|
1658
|
+
imports: resolvedValue.imports,
|
|
1659
|
+
dependencies: resolvedValue.dependencies
|
|
1660
|
+
};
|
|
1661
|
+
}
|
|
1662
|
+
/**
|
|
1663
|
+
* Generate index signature key type based on propertyNames enum or const
|
|
1664
|
+
* Returns union type string like "'foo' | 'bar'", "'x'", or 'string' if neither
|
|
1665
|
+
*/
|
|
1666
|
+
function getIndexSignatureKey(item) {
|
|
1667
|
+
return getPropertyNamesEnumKeyType(item)?.value ?? "string";
|
|
1668
|
+
}
|
|
1669
|
+
function getPropertyNamesRecordType(item, valueType, context) {
|
|
1670
|
+
const keyType = getPropertyNamesKeyType(item, context);
|
|
1671
|
+
if (!keyType) return;
|
|
1672
|
+
return {
|
|
1673
|
+
...keyType,
|
|
1674
|
+
value: `Partial<Record<${keyType.value}, ${valueType}>>`
|
|
1675
|
+
};
|
|
1676
|
+
}
|
|
1677
|
+
/**
|
|
1678
|
+
* Return the output type from an object
|
|
1630
1679
|
*
|
|
1631
|
-
* @param item item with type === "
|
|
1680
|
+
* @param item item with type === "object"
|
|
1632
1681
|
*/
|
|
1633
|
-
function
|
|
1634
|
-
|
|
1635
|
-
|
|
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
|
-
}
|
|
1682
|
+
function getObject({ item, name, context, nullable, formDataContext }) {
|
|
1683
|
+
if (isReference(item)) {
|
|
1684
|
+
const { name } = getRefInfo(item.$ref, context);
|
|
1656
1685
|
return {
|
|
1657
|
-
|
|
1686
|
+
value: name + nullable,
|
|
1687
|
+
imports: [{ name }],
|
|
1688
|
+
schemas: [],
|
|
1658
1689
|
isEnum: false,
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
example: schemaExample,
|
|
1666
|
-
examples: resolveExampleRefs(schemaExamples, context)
|
|
1690
|
+
type: "object",
|
|
1691
|
+
isRef: true,
|
|
1692
|
+
hasReadonlyProps: item.readOnly ?? false,
|
|
1693
|
+
dependencies: [name],
|
|
1694
|
+
example: item.example,
|
|
1695
|
+
examples: resolveExampleRefs(item.examples, context)
|
|
1667
1696
|
};
|
|
1668
1697
|
}
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1698
|
+
const schemaItem = item;
|
|
1699
|
+
const itemAllOf = schemaItem.allOf;
|
|
1700
|
+
const itemOneOf = schemaItem.oneOf;
|
|
1701
|
+
const itemAnyOf = schemaItem.anyOf;
|
|
1702
|
+
const itemType = schemaItem.type;
|
|
1703
|
+
if (itemAllOf || itemOneOf || itemAnyOf) return combineSchemas({
|
|
1704
|
+
schema: schemaItem,
|
|
1705
|
+
name,
|
|
1706
|
+
separator: itemAllOf ? "allOf" : itemOneOf ? "oneOf" : "anyOf",
|
|
1707
|
+
context,
|
|
1708
|
+
nullable,
|
|
1709
|
+
formDataContext
|
|
1710
|
+
});
|
|
1711
|
+
if (Array.isArray(itemType)) {
|
|
1712
|
+
const typeArray = itemType;
|
|
1713
|
+
const baseItem = schemaItem;
|
|
1714
|
+
return combineSchemas({
|
|
1715
|
+
schema: { anyOf: typeArray.map((type) => ({
|
|
1716
|
+
...baseItem,
|
|
1717
|
+
type
|
|
1718
|
+
})) },
|
|
1719
|
+
name,
|
|
1720
|
+
separator: "anyOf",
|
|
1673
1721
|
context,
|
|
1674
|
-
|
|
1722
|
+
nullable
|
|
1675
1723
|
});
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1724
|
+
}
|
|
1725
|
+
const itemProperties = schemaItem.properties;
|
|
1726
|
+
if (itemProperties && Object.entries(itemProperties).length > 0) {
|
|
1727
|
+
const entries = Object.entries(itemProperties);
|
|
1728
|
+
if (context.output.propertySortOrder === PropertySortOrder.ALPHABETICAL) entries.sort((a, b) => {
|
|
1729
|
+
return a[0].localeCompare(b[0], "en", { numeric: true });
|
|
1730
|
+
});
|
|
1731
|
+
const acc = {
|
|
1732
|
+
imports: [],
|
|
1733
|
+
schemas: [],
|
|
1734
|
+
value: "",
|
|
1681
1735
|
isEnum: false,
|
|
1682
|
-
type: "
|
|
1736
|
+
type: "object",
|
|
1683
1737
|
isRef: false,
|
|
1684
|
-
hasReadonlyProps:
|
|
1685
|
-
|
|
1686
|
-
|
|
1738
|
+
hasReadonlyProps: false,
|
|
1739
|
+
useTypeAlias: false,
|
|
1740
|
+
dependencies: [],
|
|
1741
|
+
example: schemaItem.example,
|
|
1742
|
+
examples: resolveExampleRefs(schemaItem.examples, context)
|
|
1687
1743
|
};
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
const
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
const getSchemaItems = (s) => s.items;
|
|
1707
|
-
const getSchemaRequired = (s) => s.required;
|
|
1708
|
-
const getSchemaProperties = (s) => s.properties;
|
|
1709
|
-
const resolveSchemaRef = (schema, context) => resolveRef(schema, context);
|
|
1710
|
-
const resolveResponseOrRequestRef = (schema, context) => resolveRef(schema, context);
|
|
1711
|
-
const formDataContentTypes = new Set(["multipart/form-data"]);
|
|
1712
|
-
const formUrlEncodedContentTypes = new Set(["application/x-www-form-urlencoded"]);
|
|
1713
|
-
function getResReqContentTypes({ mediaType, propName, context, isFormData, contentType }) {
|
|
1714
|
-
if (!mediaType.schema) return;
|
|
1715
|
-
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
1716
|
-
const formDataContext = isFormData ? {
|
|
1717
|
-
atPart: false,
|
|
1718
|
-
encoding: mediaType.encoding ?? {}
|
|
1719
|
-
} : isFormUrlEncoded ? {
|
|
1720
|
-
atPart: false,
|
|
1721
|
-
encoding: mediaType.encoding ?? {},
|
|
1722
|
-
urlEncoded: true
|
|
1723
|
-
} : void 0;
|
|
1724
|
-
const resolvedObject = resolveObject({
|
|
1725
|
-
schema: mediaType.schema,
|
|
1726
|
-
propName,
|
|
1727
|
-
context,
|
|
1728
|
-
formDataContext
|
|
1729
|
-
});
|
|
1730
|
-
if (!isFormData && isBinaryContentType(contentType)) return {
|
|
1731
|
-
...resolvedObject,
|
|
1732
|
-
value: "Blob"
|
|
1733
|
-
};
|
|
1734
|
-
return resolvedObject;
|
|
1735
|
-
}
|
|
1736
|
-
function getResReqTypes(responsesOrRequests, name, context, defaultType = "unknown", uniqueKey = (item) => item.value) {
|
|
1737
|
-
return uniqueBy(responsesOrRequests.filter(([, res]) => Boolean(res)).map(([key, res]) => {
|
|
1738
|
-
if (isReference(res)) {
|
|
1739
|
-
const { schema: bodySchema, imports: [{ name, schemaName }] } = resolveResponseOrRequestRef(res, context);
|
|
1740
|
-
const firstEntry = Object.entries(bodySchema.content ?? {}).at(0);
|
|
1741
|
-
if (!firstEntry) return [{
|
|
1742
|
-
value: name,
|
|
1743
|
-
imports: [{
|
|
1744
|
-
name,
|
|
1745
|
-
schemaName
|
|
1746
|
-
}],
|
|
1747
|
-
schemas: [],
|
|
1748
|
-
type: "unknown",
|
|
1749
|
-
isEnum: false,
|
|
1750
|
-
isRef: true,
|
|
1751
|
-
hasReadonlyProps: false,
|
|
1752
|
-
dependencies: [name],
|
|
1753
|
-
originalSchema: void 0,
|
|
1754
|
-
example: void 0,
|
|
1755
|
-
examples: void 0,
|
|
1756
|
-
key,
|
|
1757
|
-
contentType: ""
|
|
1758
|
-
}];
|
|
1759
|
-
const [contentType, mediaType] = firstEntry;
|
|
1760
|
-
const isFormData = formDataContentTypes.has(contentType);
|
|
1761
|
-
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
1762
|
-
if (!isFormData && !isFormUrlEncoded || !mediaType.schema) return [{
|
|
1763
|
-
value: name,
|
|
1764
|
-
imports: [{
|
|
1765
|
-
name,
|
|
1766
|
-
schemaName
|
|
1767
|
-
}],
|
|
1768
|
-
schemas: [],
|
|
1769
|
-
type: "unknown",
|
|
1770
|
-
isEnum: false,
|
|
1771
|
-
isRef: true,
|
|
1772
|
-
hasReadonlyProps: false,
|
|
1773
|
-
dependencies: [name],
|
|
1774
|
-
originalSchema: mediaType.schema,
|
|
1775
|
-
example: mediaType.example,
|
|
1776
|
-
examples: resolveExampleRefs(mediaType.examples, context),
|
|
1777
|
-
key,
|
|
1778
|
-
contentType
|
|
1779
|
-
}];
|
|
1780
|
-
const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
|
|
1781
|
-
name,
|
|
1782
|
-
schemaObject: mediaType.schema,
|
|
1744
|
+
const itemRequired = schemaItem.required;
|
|
1745
|
+
for (const [index, [key, schema]] of entries.entries()) {
|
|
1746
|
+
const isRequired = (Array.isArray(itemRequired) ? itemRequired : []).includes(key);
|
|
1747
|
+
let propName = "";
|
|
1748
|
+
if (name) {
|
|
1749
|
+
const isKeyStartWithUnderscore = key.startsWith("_");
|
|
1750
|
+
propName += pascal(`${isKeyStartWithUnderscore ? "_" : ""}${name}_${key}`);
|
|
1751
|
+
}
|
|
1752
|
+
const allSpecSchemas = context.spec.components?.schemas ?? {};
|
|
1753
|
+
if (Object.keys(allSpecSchemas).some((schemaName) => pascal(schemaName) === propName)) propName = propName + "Property";
|
|
1754
|
+
const propertyFormDataContext = formDataContext && !formDataContext.atPart ? {
|
|
1755
|
+
atPart: true,
|
|
1756
|
+
partContentType: formDataContext.encoding[key]?.contentType,
|
|
1757
|
+
urlEncoded: formDataContext.urlEncoded
|
|
1758
|
+
} : void 0;
|
|
1759
|
+
const resolvedValue = resolveObject({
|
|
1760
|
+
schema,
|
|
1761
|
+
propName,
|
|
1783
1762
|
context,
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
const
|
|
1763
|
+
formDataContext: propertyFormDataContext
|
|
1764
|
+
});
|
|
1765
|
+
const isReadOnly = Boolean(schemaItem.readOnly) || Boolean(schema.readOnly);
|
|
1766
|
+
if (!index) acc.value += "{";
|
|
1767
|
+
const doc = jsDoc(schema, true, context);
|
|
1768
|
+
const propertyDoc = doc ? `${doc.trimEnd().split("\n").map((line) => ` ${line}`).join("\n")}\n` : "";
|
|
1769
|
+
if (isReadOnly || resolvedValue.hasReadonlyProps) acc.hasReadonlyProps = true;
|
|
1770
|
+
const constValue = "const" in schema ? schema.const : void 0;
|
|
1771
|
+
const hasConst = constValue !== void 0;
|
|
1772
|
+
let constLiteral;
|
|
1773
|
+
if (!hasConst) constLiteral = void 0;
|
|
1774
|
+
else if (isString(constValue)) constLiteral = `'${escape(constValue)}'`;
|
|
1775
|
+
else constLiteral = JSON.stringify(constValue);
|
|
1776
|
+
const needsValueImport = hasConst && (resolvedValue.isEnum || resolvedValue.type === "enum");
|
|
1777
|
+
const usedResolvedValue = !hasConst || needsValueImport;
|
|
1778
|
+
const aliasedImports = needsValueImport ? resolvedValue.imports.map((imp) => ({
|
|
1779
|
+
...imp,
|
|
1780
|
+
isConstant: true
|
|
1781
|
+
})) : hasConst ? [] : getAliasedImports({
|
|
1789
1782
|
name,
|
|
1790
|
-
schemaObject: mediaType.schema,
|
|
1791
1783
|
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
|
|
1784
|
+
resolvedValue
|
|
1800
1785
|
});
|
|
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,
|
|
1786
|
+
if (aliasedImports.length > 0) acc.imports.push(...aliasedImports);
|
|
1787
|
+
const alias = getImportAliasForRefOrValue({
|
|
1846
1788
|
context,
|
|
1847
|
-
|
|
1848
|
-
|
|
1789
|
+
resolvedValue,
|
|
1790
|
+
imports: aliasedImports
|
|
1849
1791
|
});
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
isEnum: false,
|
|
1857
|
-
key,
|
|
1858
|
-
isRef: false,
|
|
1859
|
-
hasReadonlyProps: false,
|
|
1860
|
-
contentType
|
|
1861
|
-
};
|
|
1862
|
-
return;
|
|
1792
|
+
const propValue = needsValueImport ? alias : constLiteral ?? alias;
|
|
1793
|
+
const finalPropValue = isRequired ? propValue : context.output.override.useNullForOptional === true ? `${propValue} | null` : propValue;
|
|
1794
|
+
acc.value += `\n${propertyDoc}${isReadOnly && !context.output.override.suppressReadonlyModifier ? " readonly " : " "}${getKey(key)}${isRequired ? "" : "?"}: ${finalPropValue};`;
|
|
1795
|
+
if (usedResolvedValue) {
|
|
1796
|
+
acc.schemas.push(...resolvedValue.schemas);
|
|
1797
|
+
acc.dependencies.push(...resolvedValue.dependencies);
|
|
1863
1798
|
}
|
|
1864
|
-
if (
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1799
|
+
if (entries.length - 1 === index) {
|
|
1800
|
+
const additionalProps = schemaItem.additionalProperties;
|
|
1801
|
+
if (additionalProps) if (additionalProps === true) {
|
|
1802
|
+
const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
|
|
1803
|
+
if (recordType) {
|
|
1804
|
+
acc.value += "\n}";
|
|
1805
|
+
acc.value += ` & ${recordType.value}`;
|
|
1806
|
+
acc.useTypeAlias = true;
|
|
1807
|
+
acc.imports.push(...recordType.imports);
|
|
1808
|
+
acc.dependencies.push(...recordType.dependencies);
|
|
1809
|
+
} else {
|
|
1810
|
+
const keyType = getIndexSignatureKey(schemaItem);
|
|
1811
|
+
acc.value += `\n [key: ${keyType}]: unknown;\n }`;
|
|
1812
|
+
}
|
|
1813
|
+
} else {
|
|
1814
|
+
const resolvedValue = resolveValue({
|
|
1815
|
+
schema: additionalProps,
|
|
1816
|
+
name,
|
|
1817
|
+
context
|
|
1818
|
+
});
|
|
1819
|
+
const recordType = getPropertyNamesRecordType(schemaItem, resolvedValue.value, context);
|
|
1820
|
+
if (recordType) {
|
|
1821
|
+
acc.value += "\n}";
|
|
1822
|
+
acc.value += ` & ${recordType.value}`;
|
|
1823
|
+
acc.useTypeAlias = true;
|
|
1824
|
+
acc.imports.push(...recordType.imports);
|
|
1825
|
+
acc.dependencies.push(...recordType.dependencies);
|
|
1826
|
+
} else {
|
|
1827
|
+
const keyType = getIndexSignatureKey(schemaItem);
|
|
1828
|
+
acc.value += `\n [key: ${keyType}]: ${resolvedValue.value};\n}`;
|
|
1829
|
+
}
|
|
1830
|
+
acc.imports.push(...resolvedValue.imports);
|
|
1831
|
+
acc.schemas.push(...resolvedValue.schemas);
|
|
1832
|
+
acc.dependencies.push(...resolvedValue.dependencies);
|
|
1833
|
+
}
|
|
1834
|
+
else acc.value += "\n}";
|
|
1835
|
+
acc.value += nullable;
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
return acc;
|
|
1839
|
+
}
|
|
1840
|
+
const outerAdditionalProps = schemaItem.additionalProperties;
|
|
1841
|
+
const readOnlyFlag = schemaItem.readOnly;
|
|
1842
|
+
if (outerAdditionalProps) {
|
|
1843
|
+
if (outerAdditionalProps === true) {
|
|
1844
|
+
const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
|
|
1845
|
+
if (recordType) return {
|
|
1846
|
+
value: recordType.value + nullable,
|
|
1847
|
+
imports: recordType.imports,
|
|
1848
|
+
schemas: [],
|
|
1849
|
+
isEnum: false,
|
|
1850
|
+
type: "object",
|
|
1851
|
+
isRef: false,
|
|
1852
|
+
hasReadonlyProps: readOnlyFlag ?? false,
|
|
1853
|
+
useTypeAlias: true,
|
|
1854
|
+
dependencies: recordType.dependencies
|
|
1871
1855
|
};
|
|
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
1856
|
return {
|
|
1894
|
-
|
|
1895
|
-
imports: [
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1857
|
+
value: `{ [key: ${getIndexSignatureKey(schemaItem)}]: unknown }` + nullable,
|
|
1858
|
+
imports: [],
|
|
1859
|
+
schemas: [],
|
|
1860
|
+
isEnum: false,
|
|
1861
|
+
type: "object",
|
|
1862
|
+
isRef: false,
|
|
1863
|
+
hasReadonlyProps: readOnlyFlag ?? false,
|
|
1864
|
+
useTypeAlias: false,
|
|
1865
|
+
dependencies: []
|
|
1901
1866
|
};
|
|
1902
|
-
}
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1867
|
+
}
|
|
1868
|
+
const resolvedValue = resolveValue({
|
|
1869
|
+
schema: outerAdditionalProps,
|
|
1870
|
+
name,
|
|
1871
|
+
context
|
|
1872
|
+
});
|
|
1873
|
+
const recordType = getPropertyNamesRecordType(schemaItem, resolvedValue.value, context);
|
|
1874
|
+
if (recordType) return {
|
|
1875
|
+
value: recordType.value + nullable,
|
|
1876
|
+
imports: [...recordType.imports, ...resolvedValue.imports],
|
|
1877
|
+
schemas: resolvedValue.schemas,
|
|
1878
|
+
isEnum: false,
|
|
1879
|
+
type: "object",
|
|
1880
|
+
isRef: false,
|
|
1881
|
+
hasReadonlyProps: resolvedValue.hasReadonlyProps,
|
|
1882
|
+
useTypeAlias: true,
|
|
1883
|
+
dependencies: [...recordType.dependencies, ...resolvedValue.dependencies]
|
|
1884
|
+
};
|
|
1885
|
+
return {
|
|
1886
|
+
value: `{[key: ${getIndexSignatureKey(schemaItem)}]: ${resolvedValue.value}}` + nullable,
|
|
1887
|
+
imports: resolvedValue.imports,
|
|
1888
|
+
schemas: resolvedValue.schemas,
|
|
1889
|
+
isEnum: false,
|
|
1890
|
+
type: "object",
|
|
1891
|
+
isRef: false,
|
|
1892
|
+
hasReadonlyProps: resolvedValue.hasReadonlyProps,
|
|
1893
|
+
useTypeAlias: false,
|
|
1894
|
+
dependencies: resolvedValue.dependencies
|
|
1895
|
+
};
|
|
1896
|
+
}
|
|
1897
|
+
const constValue = schemaItem.const;
|
|
1898
|
+
if (constValue !== void 0) {
|
|
1899
|
+
let type;
|
|
1900
|
+
if (Array.isArray(constValue)) type = "array";
|
|
1901
|
+
else if (constValue === null) type = "null";
|
|
1902
|
+
else if (typeof constValue === "string") type = "string";
|
|
1903
|
+
else if (typeof constValue === "number") type = "number";
|
|
1904
|
+
else if (typeof constValue === "boolean") type = "boolean";
|
|
1905
|
+
else type = "object";
|
|
1906
|
+
return {
|
|
1907
|
+
value: typeof constValue === "string" ? `'${escape(constValue)}'` : JSON.stringify(constValue),
|
|
1918
1908
|
imports: [],
|
|
1919
1909
|
schemas: [],
|
|
1920
|
-
type: defaultType,
|
|
1921
1910
|
isEnum: false,
|
|
1922
|
-
|
|
1923
|
-
key,
|
|
1911
|
+
type,
|
|
1924
1912
|
isRef: false,
|
|
1925
|
-
hasReadonlyProps: false,
|
|
1926
|
-
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1913
|
+
hasReadonlyProps: readOnlyFlag ?? false,
|
|
1914
|
+
dependencies: []
|
|
1915
|
+
};
|
|
1916
|
+
}
|
|
1917
|
+
const keyType = itemType === "object" ? getIndexSignatureKey(schemaItem) : "string";
|
|
1918
|
+
const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
|
|
1919
|
+
if (itemType === "object" && recordType) return {
|
|
1920
|
+
value: recordType.value + nullable,
|
|
1921
|
+
imports: recordType.imports,
|
|
1922
|
+
schemas: [],
|
|
1923
|
+
isEnum: false,
|
|
1924
|
+
type: "object",
|
|
1925
|
+
isRef: false,
|
|
1926
|
+
hasReadonlyProps: readOnlyFlag ?? false,
|
|
1927
|
+
useTypeAlias: true,
|
|
1928
|
+
dependencies: recordType.dependencies
|
|
1929
|
+
};
|
|
1930
|
+
return {
|
|
1931
|
+
value: (itemType === "object" ? `{ [key: ${keyType}]: unknown }` : "unknown") + nullable,
|
|
1932
|
+
imports: [],
|
|
1933
|
+
schemas: [],
|
|
1934
|
+
isEnum: false,
|
|
1935
|
+
type: "object",
|
|
1936
|
+
isRef: false,
|
|
1937
|
+
hasReadonlyProps: readOnlyFlag ?? false,
|
|
1938
|
+
useTypeAlias: false,
|
|
1939
|
+
dependencies: []
|
|
1940
|
+
};
|
|
1929
1941
|
}
|
|
1942
|
+
//#endregion
|
|
1943
|
+
//#region src/getters/scalar.ts
|
|
1930
1944
|
/**
|
|
1931
|
-
*
|
|
1932
|
-
*
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
const hasJsonResponse = successContentTypes.some((contentType) => contentType.includes("json") || contentType.includes("+json"));
|
|
1938
|
-
const hasTextResponse = successContentTypes.some((contentType) => contentType.startsWith("text/") || contentType.includes("xml"));
|
|
1939
|
-
if (!hasJsonResponse && hasTextResponse) return "text";
|
|
1940
|
-
}
|
|
1941
|
-
/**
|
|
1942
|
-
* Determine the response type category for a given content type.
|
|
1943
|
-
* Used to set the correct responseType option in HTTP clients.
|
|
1945
|
+
* Returns true when a schema describes a raw binary string scalar — i.e. one
|
|
1946
|
+
* that getScalar's `case 'string':` branch would coerce to `Blob` outside a
|
|
1947
|
+
* url-encoded context (see the formDataContext.urlEncoded gate below). Shared
|
|
1948
|
+
* with resolveValue so the component-`$ref` urlEncoded short-circuit and the
|
|
1949
|
+
* inline scalar path stay in lockstep when new binary shapes are added
|
|
1950
|
+
* (#1624 / #3395 / #2410).
|
|
1944
1951
|
*
|
|
1945
|
-
*
|
|
1946
|
-
*
|
|
1952
|
+
* Accepts OAS 3.1 nullable unions (`type: ['string', 'null']`) since getScalar
|
|
1953
|
+
* normalizes those into `case 'string':` before invoking this predicate.
|
|
1947
1954
|
*/
|
|
1948
|
-
function
|
|
1949
|
-
|
|
1950
|
-
if (
|
|
1951
|
-
|
|
1955
|
+
function isBinaryScalarSchema(schema) {
|
|
1956
|
+
const schemaType = schema.type;
|
|
1957
|
+
if (!(schemaType === "string" || isArray(schemaType) && schemaType.includes("string") && schemaType.every((type) => type === "string" || type === "null"))) return false;
|
|
1958
|
+
if (schema.format === "binary") return true;
|
|
1959
|
+
const contentMediaType = schema.contentMediaType;
|
|
1960
|
+
const contentEncoding = schema.contentEncoding;
|
|
1961
|
+
return contentMediaType === "application/octet-stream" && !contentEncoding;
|
|
1952
1962
|
}
|
|
1953
1963
|
/**
|
|
1954
|
-
*
|
|
1955
|
-
* Priority: application/json > any JSON-like type > first in list
|
|
1964
|
+
* Return the typescript equivalent of open-api data type
|
|
1956
1965
|
*
|
|
1957
|
-
* @param
|
|
1958
|
-
* @
|
|
1966
|
+
* @param item
|
|
1967
|
+
* @ref https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.1.md#data-types
|
|
1959
1968
|
*/
|
|
1960
|
-
function
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
const
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
const
|
|
1969
|
-
|
|
1970
|
-
const
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
if (isUrlEncoded) {
|
|
1989
|
-
form += ` if (Array.isArray(value)) {\n`;
|
|
1990
|
-
form += ` value.forEach(v => {\n`;
|
|
1991
|
-
form += ` ${variableName}.append(key, typeof v === 'object' ? JSON.stringify(v) : String(v));\n`;
|
|
1992
|
-
form += ` });\n`;
|
|
1993
|
-
form += ` } else if (typeof value === 'object') {\n`;
|
|
1994
|
-
form += ` ${variableName}.append(key, JSON.stringify(value));\n`;
|
|
1995
|
-
form += ` } else {\n`;
|
|
1996
|
-
form += ` ${variableName}.append(key, String(value));\n`;
|
|
1997
|
-
form += ` }\n`;
|
|
1998
|
-
} else {
|
|
1999
|
-
form += ` if ((typeof File !== 'undefined' && value instanceof File) || value instanceof Blob) {\n`;
|
|
2000
|
-
form += ` ${variableName}.append(key, value);\n`;
|
|
2001
|
-
form += ` } else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {\n`;
|
|
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`;
|
|
1969
|
+
function getScalar({ item, name, context, formDataContext }) {
|
|
1970
|
+
const schemaEnum = item.enum;
|
|
1971
|
+
const schemaType = item.type;
|
|
1972
|
+
const schemaReadOnly = item.readOnly;
|
|
1973
|
+
const schemaExample = item.example;
|
|
1974
|
+
const schemaExamples = item.examples;
|
|
1975
|
+
const schemaConst = item.const;
|
|
1976
|
+
const schemaFormat = item.format;
|
|
1977
|
+
const schemaNullable = item.nullable;
|
|
1978
|
+
const nullable = isArray(schemaType) && schemaType.includes("null") || schemaNullable === true ? " | null" : "";
|
|
1979
|
+
const enumItems = schemaEnum?.filter((enumItem) => enumItem !== null);
|
|
1980
|
+
let itemType = schemaType;
|
|
1981
|
+
if (!itemType && item.items) {
|
|
1982
|
+
item.type = "array";
|
|
1983
|
+
itemType = "array";
|
|
1984
|
+
}
|
|
1985
|
+
if (isArray(schemaType) && schemaType.includes("null")) {
|
|
1986
|
+
const typesWithoutNull = schemaType.filter((x) => x !== "null");
|
|
1987
|
+
itemType = typesWithoutNull.length === 1 ? typesWithoutNull[0] : typesWithoutNull;
|
|
1988
|
+
}
|
|
1989
|
+
switch (itemType) {
|
|
1990
|
+
case "number":
|
|
1991
|
+
case "integer": {
|
|
1992
|
+
let value = context.output.override.useBigInt && (schemaFormat === "int64" || schemaFormat === "uint64") ? "bigint" : "number";
|
|
1993
|
+
let isEnum = false;
|
|
1994
|
+
if (enumItems) {
|
|
1995
|
+
value = enumItems.map((enumItem) => `${enumItem}`).join(" | ");
|
|
1996
|
+
isEnum = true;
|
|
2018
1997
|
}
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
}
|
|
2033
|
-
form += combinedSchemasFormData;
|
|
1998
|
+
value += nullable;
|
|
1999
|
+
if (schemaConst !== void 0) value = schemaConst;
|
|
2000
|
+
return {
|
|
2001
|
+
value,
|
|
2002
|
+
isEnum,
|
|
2003
|
+
type: "number",
|
|
2004
|
+
schemas: [],
|
|
2005
|
+
imports: [],
|
|
2006
|
+
isRef: false,
|
|
2007
|
+
hasReadonlyProps: schemaReadOnly ?? false,
|
|
2008
|
+
dependencies: [],
|
|
2009
|
+
example: schemaExample,
|
|
2010
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
2011
|
+
};
|
|
2034
2012
|
}
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2013
|
+
case "boolean": {
|
|
2014
|
+
let value = "boolean";
|
|
2015
|
+
if (enumItems && !(enumItems.includes(true) && enumItems.includes(false))) value = enumItems.map((enumItem) => `${enumItem}`).join(" | ");
|
|
2016
|
+
value += nullable;
|
|
2017
|
+
if (schemaConst !== void 0) value = schemaConst;
|
|
2018
|
+
return {
|
|
2019
|
+
value,
|
|
2020
|
+
type: "boolean",
|
|
2021
|
+
isEnum: false,
|
|
2022
|
+
schemas: [],
|
|
2023
|
+
imports: [],
|
|
2024
|
+
isRef: false,
|
|
2025
|
+
hasReadonlyProps: schemaReadOnly ?? false,
|
|
2026
|
+
dependencies: [],
|
|
2027
|
+
example: schemaExample,
|
|
2028
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
2029
|
+
};
|
|
2030
|
+
}
|
|
2031
|
+
case "array": {
|
|
2032
|
+
const { value, ...rest } = getArray({
|
|
2033
|
+
schema: item,
|
|
2034
|
+
name,
|
|
2040
2035
|
context,
|
|
2041
|
-
|
|
2042
|
-
encoding
|
|
2036
|
+
formDataContext
|
|
2043
2037
|
});
|
|
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()";
|
|
2038
|
+
return {
|
|
2039
|
+
value: value + nullable,
|
|
2040
|
+
...rest,
|
|
2041
|
+
dependencies: rest.dependencies
|
|
2042
|
+
};
|
|
2055
2043
|
}
|
|
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" || Array.isArray(property.type) && property.type.includes("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" || Array.isArray(property.type) && property.type.includes("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
|
-
}
|
|
2044
|
+
case "string": {
|
|
2045
|
+
let value = "string";
|
|
2046
|
+
let isEnum = false;
|
|
2047
|
+
if (enumItems) {
|
|
2048
|
+
value = enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
|
|
2049
|
+
isEnum = true;
|
|
2113
2050
|
}
|
|
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;
|
|
2051
|
+
if (!formDataContext?.urlEncoded) {
|
|
2052
|
+
if (schemaFormat === "binary") value = "Blob";
|
|
2053
|
+
else if (formDataContext?.atPart) {
|
|
2054
|
+
const fileType = getFormDataFieldFileType(item, formDataContext.partContentType);
|
|
2055
|
+
if (fileType) value = fileType === "binary" ? "Blob" : "Blob | string";
|
|
2056
|
+
} else if (isBinaryScalarSchema(item)) value = "Blob";
|
|
2147
2057
|
}
|
|
2148
|
-
|
|
2149
|
-
|
|
2058
|
+
if (context.output.override.useDates && (schemaFormat === "date" || schemaFormat === "date-time")) value = "Date";
|
|
2059
|
+
value += nullable;
|
|
2060
|
+
if (schemaConst) value = `'${schemaConst}'`;
|
|
2061
|
+
return {
|
|
2062
|
+
value,
|
|
2063
|
+
isEnum,
|
|
2064
|
+
type: "string",
|
|
2065
|
+
imports: [],
|
|
2066
|
+
schemas: [],
|
|
2067
|
+
isRef: false,
|
|
2068
|
+
hasReadonlyProps: schemaReadOnly ?? false,
|
|
2069
|
+
dependencies: [],
|
|
2070
|
+
example: schemaExample,
|
|
2071
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
2072
|
+
};
|
|
2150
2073
|
}
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2074
|
+
case "null": {
|
|
2075
|
+
const itemAllOf = item.allOf;
|
|
2076
|
+
const itemOneOf = item.oneOf;
|
|
2077
|
+
const itemAnyOf = item.anyOf;
|
|
2078
|
+
let separator;
|
|
2079
|
+
if (itemAllOf?.length) separator = "allOf";
|
|
2080
|
+
else if (itemOneOf?.length) separator = "oneOf";
|
|
2081
|
+
else if (itemAnyOf?.length) separator = "anyOf";
|
|
2082
|
+
if (separator) return combineSchemas({
|
|
2083
|
+
schema: Object.fromEntries(Object.entries(item).filter(([key]) => key !== "type")),
|
|
2084
|
+
name,
|
|
2085
|
+
separator,
|
|
2086
|
+
context,
|
|
2087
|
+
nullable: nullable || " | null",
|
|
2088
|
+
formDataContext
|
|
2089
|
+
});
|
|
2090
|
+
return {
|
|
2091
|
+
value: "null",
|
|
2092
|
+
isEnum: false,
|
|
2093
|
+
type: "null",
|
|
2094
|
+
imports: [],
|
|
2095
|
+
schemas: [],
|
|
2096
|
+
isRef: false,
|
|
2097
|
+
hasReadonlyProps: schemaReadOnly ?? false,
|
|
2098
|
+
dependencies: []
|
|
2099
|
+
};
|
|
2100
|
+
}
|
|
2101
|
+
default: {
|
|
2102
|
+
if (isArray(itemType)) return combineSchemas({
|
|
2103
|
+
schema: { anyOf: itemType.map((type) => Object.assign({}, item, { type })) },
|
|
2104
|
+
name,
|
|
2105
|
+
separator: "anyOf",
|
|
2106
|
+
context,
|
|
2107
|
+
nullable
|
|
2108
|
+
});
|
|
2109
|
+
if (enumItems) return {
|
|
2110
|
+
value: enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : String(enumItem)).filter(Boolean).join(` | `) + nullable,
|
|
2111
|
+
isEnum: true,
|
|
2112
|
+
type: "string",
|
|
2113
|
+
imports: [],
|
|
2114
|
+
schemas: [],
|
|
2115
|
+
isRef: false,
|
|
2116
|
+
hasReadonlyProps: schemaReadOnly ?? false,
|
|
2117
|
+
dependencies: [],
|
|
2118
|
+
example: schemaExample,
|
|
2119
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
2120
|
+
};
|
|
2121
|
+
const hasCombiners = item.allOf ?? item.anyOf ?? item.oneOf;
|
|
2122
|
+
const { value, ...rest } = getObject({
|
|
2123
|
+
item,
|
|
2124
|
+
name,
|
|
2125
|
+
context,
|
|
2126
|
+
nullable,
|
|
2127
|
+
formDataContext: formDataContext?.atPart === false || formDataContext?.atPart && hasCombiners ? formDataContext : void 0
|
|
2128
|
+
});
|
|
2129
|
+
return {
|
|
2130
|
+
value,
|
|
2131
|
+
...rest
|
|
2132
|
+
};
|
|
2154
2133
|
}
|
|
2155
|
-
formDataValues += `if(${valueKey} !== undefined) {\n ${formDataValue} }\n`;
|
|
2156
2134
|
}
|
|
2157
|
-
return formDataValues;
|
|
2158
2135
|
}
|
|
2159
2136
|
//#endregion
|
|
2160
|
-
//#region src/
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
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
|
-
};
|
|
2137
|
+
//#region src/resolvers/ref.ts
|
|
2138
|
+
/** Convert a `$dynamicAnchor` name to a valid TypeScript generic parameter identifier. */
|
|
2139
|
+
function dynamicAnchorToParamName(anchor) {
|
|
2140
|
+
return sanitize(anchor, {
|
|
2141
|
+
underscore: "_",
|
|
2142
|
+
whitespace: "_",
|
|
2143
|
+
dash: "_",
|
|
2144
|
+
es5keyword: true,
|
|
2145
|
+
es5IdentifierName: true
|
|
2146
|
+
});
|
|
2198
2147
|
}
|
|
2199
|
-
function
|
|
2200
|
-
|
|
2148
|
+
function dynamicAnchorsToUniqueParamNames(anchors) {
|
|
2149
|
+
const result = /* @__PURE__ */ new Map();
|
|
2150
|
+
const usedNames = /* @__PURE__ */ new Map();
|
|
2151
|
+
for (const anchor of anchors) {
|
|
2152
|
+
const base = dynamicAnchorToParamName(anchor);
|
|
2153
|
+
const count = usedNames.get(base) ?? 0;
|
|
2154
|
+
usedNames.set(base, count + 1);
|
|
2155
|
+
const paramName = count === 0 ? base : `${base}${count + 1}`;
|
|
2156
|
+
result.set(anchor, paramName);
|
|
2157
|
+
}
|
|
2158
|
+
return result;
|
|
2201
2159
|
}
|
|
2160
|
+
const REF_NOT_FOUND_PREFIX = "Oops... 🍻. Ref not found";
|
|
2202
2161
|
/**
|
|
2203
|
-
*
|
|
2204
|
-
*
|
|
2162
|
+
* Recursively resolves a `$ref` in an OpenAPI document, following
|
|
2163
|
+
* nested schema refs and collecting imports along the way.
|
|
2164
|
+
*
|
|
2165
|
+
* Handles OpenAPI 3.0 `nullable` and 3.1 type-array hints on direct refs.
|
|
2166
|
+
*
|
|
2167
|
+
* @see https://spec.openapis.org/oas/v3.0.3#reference-object
|
|
2168
|
+
* @see https://spec.openapis.org/oas/v3.1.0#reference-object
|
|
2205
2169
|
*/
|
|
2206
|
-
function
|
|
2207
|
-
const
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2170
|
+
function resolveRef(schema, context, imports = []) {
|
|
2171
|
+
const refPath = "$ref" in schema ? schema.$ref : void 0;
|
|
2172
|
+
const nestedSchema = "schema" in schema ? schema.schema : void 0;
|
|
2173
|
+
if (isObject(nestedSchema) && isReference(nestedSchema) && typeof nestedSchema.$ref === "string") {
|
|
2174
|
+
const resolvedRef = resolveRef(nestedSchema, context, imports);
|
|
2175
|
+
if ("examples" in schema) {
|
|
2176
|
+
const schemaWithExamples = schema;
|
|
2177
|
+
schemaWithExamples.examples = resolveExampleRefs(schemaWithExamples.examples, context);
|
|
2178
|
+
}
|
|
2179
|
+
if ("examples" in resolvedRef.schema) {
|
|
2180
|
+
const resolvedWithExamples = resolvedRef.schema;
|
|
2181
|
+
resolvedWithExamples.examples = resolveExampleRefs(resolvedWithExamples.examples, context);
|
|
2182
|
+
}
|
|
2214
2183
|
return {
|
|
2215
|
-
|
|
2216
|
-
|
|
2184
|
+
schema: {
|
|
2185
|
+
...schema,
|
|
2186
|
+
schema: resolvedRef.schema
|
|
2187
|
+
},
|
|
2188
|
+
imports: resolvedRef.imports
|
|
2217
2189
|
};
|
|
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;
|
|
2190
|
+
}
|
|
2191
|
+
if (isDereferenced(schema)) {
|
|
2192
|
+
if ("examples" in schema) {
|
|
2193
|
+
const schemaWithExamples = schema;
|
|
2194
|
+
schemaWithExamples.examples = resolveExampleRefs(schemaWithExamples.examples, context);
|
|
2195
|
+
}
|
|
2241
2196
|
return {
|
|
2242
|
-
|
|
2243
|
-
|
|
2197
|
+
schema,
|
|
2198
|
+
imports
|
|
2244
2199
|
};
|
|
2245
|
-
}
|
|
2246
|
-
}
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
}
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
}
|
|
2254
|
-
//#endregion
|
|
2255
|
-
//#region src/getters/keys.ts
|
|
2256
|
-
function getKey(key) {
|
|
2257
|
-
return keyword.isIdentifierNameES5(key) ? key : `'${key}'`;
|
|
2200
|
+
}
|
|
2201
|
+
if (!refPath) throw new Error(`${REF_NOT_FOUND_PREFIX}: missing $ref`);
|
|
2202
|
+
const { currentSchema, refInfo: { name, originalName } } = getSchema$1(schema, context);
|
|
2203
|
+
if (!currentSchema) throw new Error(`${REF_NOT_FOUND_PREFIX}: ${refPath}`);
|
|
2204
|
+
return resolveRef(currentSchema, { ...context }, [...imports, {
|
|
2205
|
+
name,
|
|
2206
|
+
schemaName: originalName
|
|
2207
|
+
}]);
|
|
2258
2208
|
}
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
if (!
|
|
2263
|
-
const
|
|
2264
|
-
|
|
2265
|
-
const
|
|
2266
|
-
if (
|
|
2267
|
-
value: enumValues.map((val) => `'${escape(val)}'`).join(" | "),
|
|
2268
|
-
imports: [],
|
|
2269
|
-
dependencies: []
|
|
2270
|
-
};
|
|
2209
|
+
/** Check whether a schema reference has at least one `$defs` entry with both `$dynamicAnchor` and `$ref`. */
|
|
2210
|
+
function isBoundAlias(schema) {
|
|
2211
|
+
const defs = schema.$defs;
|
|
2212
|
+
if (!defs || typeof defs !== "object") return false;
|
|
2213
|
+
for (const defSchema of Object.values(defs)) {
|
|
2214
|
+
if (!defSchema || typeof defSchema !== "object") continue;
|
|
2215
|
+
const rec = defSchema;
|
|
2216
|
+
if (typeof rec.$dynamicAnchor === "string" && typeof rec.$ref === "string") return true;
|
|
2271
2217
|
}
|
|
2272
|
-
|
|
2273
|
-
value: `'${escape(propertyNames.const)}'`,
|
|
2274
|
-
imports: [],
|
|
2275
|
-
dependencies: []
|
|
2276
|
-
};
|
|
2218
|
+
return false;
|
|
2277
2219
|
}
|
|
2278
2220
|
/**
|
|
2279
|
-
*
|
|
2280
|
-
*
|
|
2221
|
+
* Extract bound-alias information from a schema that references a generic template
|
|
2222
|
+
* and binds `$dynamicAnchor` entries to concrete types via `$defs`.
|
|
2281
2223
|
*/
|
|
2282
|
-
function
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2224
|
+
function extractBoundAliasInfo(schema, context) {
|
|
2225
|
+
let bindingElement;
|
|
2226
|
+
let extraSchemas;
|
|
2227
|
+
if (isReference(schema) && isBoundAlias(schema)) bindingElement = schema;
|
|
2228
|
+
else {
|
|
2229
|
+
const allOf = schema.allOf;
|
|
2230
|
+
if (Array.isArray(allOf)) for (let i = 0; i < allOf.length; i++) {
|
|
2231
|
+
const element = allOf[i];
|
|
2232
|
+
if (isReference(element) && isBoundAlias(element)) {
|
|
2233
|
+
bindingElement = element;
|
|
2234
|
+
extraSchemas = allOf.filter((_, j) => j !== i);
|
|
2235
|
+
break;
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
if (!bindingElement) return void 0;
|
|
2240
|
+
const defs = bindingElement.$defs;
|
|
2241
|
+
if (!defs || typeof defs !== "object") return void 0;
|
|
2242
|
+
const bindingByAnchor = /* @__PURE__ */ new Map();
|
|
2243
|
+
for (const defSchema of Object.values(defs)) {
|
|
2244
|
+
if (!defSchema || typeof defSchema !== "object") continue;
|
|
2245
|
+
const rec = defSchema;
|
|
2246
|
+
if (rec.$dynamicAnchor === void 0) continue;
|
|
2247
|
+
const ref = rec.$ref;
|
|
2248
|
+
if (!ref || !isComponentRef(ref)) continue;
|
|
2249
|
+
const anchor = rec.$dynamicAnchor;
|
|
2250
|
+
const { name, originalName } = getRefInfo(ref, context);
|
|
2251
|
+
bindingByAnchor.set(anchor, {
|
|
2252
|
+
typeName: name,
|
|
2253
|
+
originalName
|
|
2254
|
+
});
|
|
2255
|
+
}
|
|
2256
|
+
if (bindingByAnchor.size === 0) return void 0;
|
|
2257
|
+
const refPath = bindingElement.$ref;
|
|
2258
|
+
if (typeof refPath !== "string") return void 0;
|
|
2259
|
+
const { name: genericName, refPaths: templateRefPaths } = getRefInfo(refPath, context);
|
|
2260
|
+
const templateDefs = (templateRefPaths ? prop(context.spec, ...templateRefPaths) : void 0)?.$defs;
|
|
2261
|
+
const typeArgs = [];
|
|
2262
|
+
const genericParams = [];
|
|
2263
|
+
const imports = [];
|
|
2264
|
+
if (templateDefs && typeof templateDefs === "object") {
|
|
2265
|
+
const templateAnchors = [];
|
|
2266
|
+
for (const defSchema of Object.values(templateDefs)) {
|
|
2267
|
+
if (!defSchema || typeof defSchema !== "object") continue;
|
|
2268
|
+
const rec = defSchema;
|
|
2269
|
+
if (rec.$dynamicAnchor === void 0 || rec.$ref !== void 0) continue;
|
|
2270
|
+
templateAnchors.push(rec.$dynamicAnchor);
|
|
2271
|
+
}
|
|
2272
|
+
const uniqueNames = dynamicAnchorsToUniqueParamNames(templateAnchors);
|
|
2273
|
+
for (const anchor of templateAnchors) {
|
|
2274
|
+
const binding = bindingByAnchor.get(anchor);
|
|
2275
|
+
if (binding) {
|
|
2276
|
+
typeArgs.push(binding.typeName);
|
|
2277
|
+
imports.push({
|
|
2278
|
+
name: binding.typeName,
|
|
2279
|
+
schemaName: binding.originalName
|
|
2280
|
+
});
|
|
2281
|
+
} else {
|
|
2282
|
+
const paramName = uniqueNames.get(anchor) ?? dynamicAnchorToParamName(anchor);
|
|
2283
|
+
typeArgs.push(paramName);
|
|
2284
|
+
genericParams.push(paramName);
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
if (typeArgs.length === 0) for (const { typeName, originalName } of bindingByAnchor.values()) {
|
|
2289
|
+
typeArgs.push(typeName);
|
|
2290
|
+
imports.push({
|
|
2291
|
+
name: typeName,
|
|
2292
|
+
schemaName: originalName
|
|
2293
|
+
});
|
|
2294
|
+
}
|
|
2294
2295
|
return {
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2296
|
+
genericName,
|
|
2297
|
+
genericParams,
|
|
2298
|
+
typeArgs,
|
|
2299
|
+
imports,
|
|
2300
|
+
extraSchemas
|
|
2298
2301
|
};
|
|
2299
2302
|
}
|
|
2303
|
+
function getSchema$1(schema, context) {
|
|
2304
|
+
if (!schema.$ref) throw new Error(`${REF_NOT_FOUND_PREFIX}: missing $ref`);
|
|
2305
|
+
const refInfo = getRefInfo(schema.$ref, context);
|
|
2306
|
+
const { refPaths } = refInfo;
|
|
2307
|
+
const schemaByRefPaths = Array.isArray(refPaths) ? prop(context.spec, ...refPaths) : void 0;
|
|
2308
|
+
if (isObject(schemaByRefPaths) && isReference(schemaByRefPaths)) return getSchema$1(schemaByRefPaths, context);
|
|
2309
|
+
let currentSchema = schemaByRefPaths;
|
|
2310
|
+
if (isObject(currentSchema) && "nullable" in schema) {
|
|
2311
|
+
const nullable = schema.nullable;
|
|
2312
|
+
currentSchema = {
|
|
2313
|
+
...currentSchema,
|
|
2314
|
+
nullable
|
|
2315
|
+
};
|
|
2316
|
+
}
|
|
2317
|
+
if (isObject(currentSchema) && "type" in schema && Array.isArray(schema.type)) {
|
|
2318
|
+
const type = schema.type;
|
|
2319
|
+
currentSchema = {
|
|
2320
|
+
...currentSchema,
|
|
2321
|
+
type
|
|
2322
|
+
};
|
|
2323
|
+
}
|
|
2324
|
+
return {
|
|
2325
|
+
currentSchema,
|
|
2326
|
+
refInfo
|
|
2327
|
+
};
|
|
2328
|
+
}
|
|
2329
|
+
function encodeJsonPointerSegment(segment) {
|
|
2330
|
+
return segment.replaceAll("~", "~0").replaceAll("/", "~1");
|
|
2331
|
+
}
|
|
2300
2332
|
/**
|
|
2301
|
-
*
|
|
2302
|
-
*
|
|
2333
|
+
* Build the dynamic scope for a schema: maps `$dynamicAnchor` names to concrete
|
|
2334
|
+
* type entries for self-referential resolution, `$defs` bindings, and sibling anchors.
|
|
2303
2335
|
*/
|
|
2304
|
-
function
|
|
2305
|
-
|
|
2336
|
+
function buildDynamicScope(schemaName, schema, context) {
|
|
2337
|
+
const scope = {};
|
|
2338
|
+
const getSchemaScopeEntry = (name) => {
|
|
2339
|
+
const refInfo = getRefInfo(`#/components/schemas/${encodeJsonPointerSegment(name)}`, context);
|
|
2340
|
+
return {
|
|
2341
|
+
name: refInfo.name,
|
|
2342
|
+
schemaName: refInfo.originalName
|
|
2343
|
+
};
|
|
2344
|
+
};
|
|
2345
|
+
const schemaRecord = schema;
|
|
2346
|
+
if (typeof schemaRecord.$dynamicAnchor === "string") scope[schemaRecord.$dynamicAnchor] = getSchemaScopeEntry(schemaName);
|
|
2347
|
+
const defs = schemaRecord.$defs;
|
|
2348
|
+
if (defs && typeof defs === "object") {
|
|
2349
|
+
const unboundAnchors = [];
|
|
2350
|
+
for (const [, defSchema] of Object.entries(defs)) {
|
|
2351
|
+
if (!defSchema || typeof defSchema !== "object") continue;
|
|
2352
|
+
const defRecord = defSchema;
|
|
2353
|
+
if (typeof defRecord.$dynamicAnchor === "string") {
|
|
2354
|
+
const anchorName = defRecord.$dynamicAnchor;
|
|
2355
|
+
const refInDef = defSchema.$ref;
|
|
2356
|
+
if (refInDef?.startsWith("#/components/schemas/")) {
|
|
2357
|
+
const { name, originalName } = getRefInfo(refInDef, context);
|
|
2358
|
+
scope[anchorName] = {
|
|
2359
|
+
name,
|
|
2360
|
+
schemaName: originalName
|
|
2361
|
+
};
|
|
2362
|
+
} else if (!refInDef) unboundAnchors.push(anchorName);
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
if (unboundAnchors.length > 0) {
|
|
2366
|
+
const uniqueNames = dynamicAnchorsToUniqueParamNames(unboundAnchors);
|
|
2367
|
+
for (const anchor of unboundAnchors) {
|
|
2368
|
+
const paramName = uniqueNames.get(anchor);
|
|
2369
|
+
if (paramName === void 0) continue;
|
|
2370
|
+
scope[anchor] = {
|
|
2371
|
+
name: paramName,
|
|
2372
|
+
schemaName: paramName,
|
|
2373
|
+
isParameter: true
|
|
2374
|
+
};
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
return scope;
|
|
2306
2379
|
}
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2380
|
+
/**
|
|
2381
|
+
* Resolve a `$dynamicRef` anchor to its concrete type using the current dynamic scope.
|
|
2382
|
+
* Returns `{ schema: {}, resolvedTypeName: 'unknown' }` when no scope override exists.
|
|
2383
|
+
*/
|
|
2384
|
+
function resolveDynamicRef(anchorName, context, imports = []) {
|
|
2385
|
+
let scopeEntry = (context.dynamicScope ?? {})[anchorName];
|
|
2386
|
+
if (!scopeEntry) {
|
|
2387
|
+
const schemas = context.spec.components?.schemas;
|
|
2388
|
+
if (schemas && typeof schemas === "object") for (const [schemaName, schemaObj] of Object.entries(schemas)) {
|
|
2389
|
+
if (!schemaObj || typeof schemaObj !== "object") continue;
|
|
2390
|
+
if (schemaObj.$dynamicAnchor === anchorName) {
|
|
2391
|
+
const refInfo = getRefInfo(`#/components/schemas/${encodeJsonPointerSegment(schemaName)}`, context);
|
|
2392
|
+
scopeEntry = {
|
|
2393
|
+
name: refInfo.name,
|
|
2394
|
+
schemaName: refInfo.originalName
|
|
2395
|
+
};
|
|
2396
|
+
break;
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
}
|
|
2400
|
+
if (!scopeEntry) return {
|
|
2401
|
+
schema: {},
|
|
2402
|
+
imports,
|
|
2403
|
+
resolvedTypeName: "unknown"
|
|
2404
|
+
};
|
|
2405
|
+
if (scopeEntry.isParameter) return {
|
|
2406
|
+
schema: {},
|
|
2407
|
+
imports,
|
|
2408
|
+
resolvedTypeName: scopeEntry.name
|
|
2409
|
+
};
|
|
2410
|
+
const resolvedTypeName = scopeEntry.name;
|
|
2411
|
+
const schemaRef = `#/components/schemas/${encodeJsonPointerSegment(scopeEntry.schemaName)}`;
|
|
2412
|
+
try {
|
|
2413
|
+
const { schema: resolvedSchema, imports: resolvedImports } = resolveRef({ $ref: schemaRef }, context, imports);
|
|
2414
|
+
return {
|
|
2415
|
+
schema: resolvedSchema,
|
|
2416
|
+
imports: resolvedImports,
|
|
2417
|
+
resolvedTypeName
|
|
2418
|
+
};
|
|
2419
|
+
} catch {
|
|
2420
|
+
return {
|
|
2421
|
+
schema: {},
|
|
2422
|
+
imports,
|
|
2423
|
+
resolvedTypeName: "unknown"
|
|
2424
|
+
};
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
/** Recursively resolves `$ref` entries in an examples array or record. */
|
|
2428
|
+
function resolveExampleRefs(examples, context) {
|
|
2429
|
+
if (!examples) return;
|
|
2430
|
+
return Array.isArray(examples) ? examples.map((example) => {
|
|
2431
|
+
if (isObject(example) && isReference(example)) {
|
|
2432
|
+
const { schema } = resolveRef(example, context);
|
|
2433
|
+
return schema.value;
|
|
2434
|
+
}
|
|
2435
|
+
return example;
|
|
2436
|
+
}) : (() => {
|
|
2437
|
+
const result = {};
|
|
2438
|
+
for (const [key, example] of Object.entries(examples)) result[key] = isObject(example) && isReference(example) ? resolveRef(example, context).schema.value : example;
|
|
2439
|
+
return result;
|
|
2440
|
+
})();
|
|
2441
|
+
}
|
|
2442
|
+
//#endregion
|
|
2443
|
+
//#region src/resolvers/value.ts
|
|
2444
|
+
const schemaArrayKeys = [
|
|
2445
|
+
"allOf",
|
|
2446
|
+
"anyOf",
|
|
2447
|
+
"oneOf",
|
|
2448
|
+
"prefixItems"
|
|
2449
|
+
];
|
|
2450
|
+
const schemaObjectKeys = [
|
|
2451
|
+
"additionalProperties",
|
|
2452
|
+
"contains",
|
|
2453
|
+
"else",
|
|
2454
|
+
"if",
|
|
2455
|
+
"items",
|
|
2456
|
+
"not",
|
|
2457
|
+
"propertyNames",
|
|
2458
|
+
"then",
|
|
2459
|
+
"unevaluatedItems",
|
|
2460
|
+
"unevaluatedProperties"
|
|
2461
|
+
];
|
|
2462
|
+
const schemaMapKeys = [
|
|
2463
|
+
"$defs",
|
|
2464
|
+
"dependentSchemas",
|
|
2465
|
+
"patternProperties",
|
|
2466
|
+
"properties"
|
|
2467
|
+
];
|
|
2468
|
+
/**
|
|
2469
|
+
* Recursively walks a schema value and returns `true` if any nested
|
|
2470
|
+
* `$dynamicRef` resolves — via the current `context.dynamicScope` — to a
|
|
2471
|
+
* schema *other* than `refName`.
|
|
2472
|
+
*
|
|
2473
|
+
* Used by `resolveValue` to decide whether a `$ref`'d schema must be
|
|
2474
|
+
* instantiated with its bound type arguments rather than referenced by name.
|
|
2475
|
+
*
|
|
2476
|
+
* @param value - The schema node (or sub-node) to inspect.
|
|
2477
|
+
* @param context - Current resolution context, including the dynamic scope.
|
|
2478
|
+
* @param refName - The resolved name of the enclosing `$ref` schema; dynamic
|
|
2479
|
+
* refs that resolve to this same name are considered
|
|
2480
|
+
* self-references and do not count as "scope-affected".
|
|
2481
|
+
* @param seen - Cycle-guard; tracks already-visited objects.
|
|
2482
|
+
*/
|
|
2483
|
+
function hasScopeAffectedDynamicRef(value, context, refName, seen = /* @__PURE__ */ new WeakSet()) {
|
|
2484
|
+
if (!value || typeof value !== "object") return false;
|
|
2485
|
+
if (!context.dynamicScope || Object.keys(context.dynamicScope).length === 0) return false;
|
|
2486
|
+
if (seen.has(value)) return false;
|
|
2487
|
+
seen.add(value);
|
|
2488
|
+
if (isDynamicReference(value) && value.$dynamicRef.startsWith("#")) {
|
|
2489
|
+
const anchorName = getDynamicAnchorName(value.$dynamicRef);
|
|
2490
|
+
if (anchorName) {
|
|
2491
|
+
const scopeEntry = context.dynamicScope[anchorName];
|
|
2492
|
+
if (scopeEntry && scopeEntry.name !== refName) return true;
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
const schema = value;
|
|
2496
|
+
for (const key of schemaArrayKeys) {
|
|
2497
|
+
const items = schema[key];
|
|
2498
|
+
if (Array.isArray(items) && items.some((item) => hasScopeAffectedDynamicRef(item, context, refName, seen))) return true;
|
|
2499
|
+
}
|
|
2500
|
+
for (const key of schemaObjectKeys) if (hasScopeAffectedDynamicRef(schema[key], context, refName, seen)) return true;
|
|
2501
|
+
for (const key of schemaMapKeys) {
|
|
2502
|
+
const schemaMap = schema[key];
|
|
2503
|
+
if (schemaMap && typeof schemaMap === "object" && Object.values(schemaMap).some((item) => hasScopeAffectedDynamicRef(item, context, refName, seen))) return true;
|
|
2504
|
+
}
|
|
2505
|
+
return false;
|
|
2506
|
+
}
|
|
2507
|
+
function makeUnknownValue(originalSchema) {
|
|
2310
2508
|
return {
|
|
2311
|
-
|
|
2312
|
-
|
|
2509
|
+
value: "unknown",
|
|
2510
|
+
imports: [],
|
|
2511
|
+
type: "unknown",
|
|
2512
|
+
isEnum: false,
|
|
2513
|
+
schemas: [],
|
|
2514
|
+
isRef: false,
|
|
2515
|
+
hasReadonlyProps: false,
|
|
2516
|
+
originalSchema,
|
|
2517
|
+
dependencies: []
|
|
2313
2518
|
};
|
|
2314
2519
|
}
|
|
2315
2520
|
/**
|
|
2316
|
-
*
|
|
2521
|
+
* Resolves an OpenAPI schema or reference object to a {@link ResolverValue}
|
|
2522
|
+
* that carries the TypeScript type string, required imports, and metadata.
|
|
2317
2523
|
*
|
|
2318
|
-
*
|
|
2524
|
+
* Handles all schema forms in priority order:
|
|
2525
|
+
* 1. **Bound generic alias** — a `$ref` with `$defs` overrides; emits an
|
|
2526
|
+
* instantiated generic expression such as `Paginated<User>`.
|
|
2527
|
+
* 2. **Component `$ref`** — a named `$ref` pointing to `#/components/…`;
|
|
2528
|
+
* emits the schema name as a reference import.
|
|
2529
|
+
* 3. **Non-component `$ref`** — an anonymous or path-level ref; inlines the
|
|
2530
|
+
* resolved schema via {@link getScalar} (cycle-safe).
|
|
2531
|
+
* 4. **`$dynamicRef`** — resolved via the active dynamic scope; falls back to
|
|
2532
|
+
* `unknown` when the anchor is absent or the ref is a bare `#`.
|
|
2533
|
+
* 5. **Plain schema** — delegates to {@link getScalar} for all other cases
|
|
2534
|
+
* (primitives, objects, arrays, enums, …).
|
|
2319
2535
|
*/
|
|
2320
|
-
function
|
|
2321
|
-
if (isReference(
|
|
2322
|
-
const
|
|
2536
|
+
function resolveValue({ schema, name, context, formDataContext }) {
|
|
2537
|
+
if (isReference(schema)) {
|
|
2538
|
+
const alias = extractBoundAliasInfo(schema, context);
|
|
2539
|
+
if (alias) {
|
|
2540
|
+
const value = `${alias.genericName}<${alias.typeArgs.join(", ")}>`;
|
|
2541
|
+
const allImports = [{
|
|
2542
|
+
name: alias.genericName,
|
|
2543
|
+
schemaName: alias.genericName
|
|
2544
|
+
}, ...alias.imports];
|
|
2545
|
+
return {
|
|
2546
|
+
value,
|
|
2547
|
+
imports: allImports,
|
|
2548
|
+
type: "object",
|
|
2549
|
+
schemas: [],
|
|
2550
|
+
isEnum: false,
|
|
2551
|
+
originalSchema: schema,
|
|
2552
|
+
hasReadonlyProps: false,
|
|
2553
|
+
isRef: true,
|
|
2554
|
+
dependencies: allImports.map((i) => i.name)
|
|
2555
|
+
};
|
|
2556
|
+
}
|
|
2557
|
+
const refValue = schema.$ref;
|
|
2558
|
+
const { schema: schemaObject, imports } = resolveRef(schema, context);
|
|
2559
|
+
if (refValue && !isComponentRef(refValue)) {
|
|
2560
|
+
if (context.parents?.includes(refValue)) return {
|
|
2561
|
+
value: "unknown",
|
|
2562
|
+
imports: [],
|
|
2563
|
+
schemas: [],
|
|
2564
|
+
type: "unknown",
|
|
2565
|
+
isEnum: false,
|
|
2566
|
+
originalSchema: schemaObject,
|
|
2567
|
+
hasReadonlyProps: false,
|
|
2568
|
+
isRef: false,
|
|
2569
|
+
dependencies: []
|
|
2570
|
+
};
|
|
2571
|
+
return {
|
|
2572
|
+
...getScalar({
|
|
2573
|
+
item: schemaObject,
|
|
2574
|
+
name,
|
|
2575
|
+
context: {
|
|
2576
|
+
...context,
|
|
2577
|
+
parents: [...context.parents ?? [], refValue]
|
|
2578
|
+
},
|
|
2579
|
+
formDataContext
|
|
2580
|
+
}),
|
|
2581
|
+
originalSchema: schemaObject,
|
|
2582
|
+
isRef: false
|
|
2583
|
+
};
|
|
2584
|
+
}
|
|
2585
|
+
if (formDataContext?.urlEncoded && isBinaryScalarSchema(schemaObject)) return {
|
|
2586
|
+
...getScalar({
|
|
2587
|
+
item: schemaObject,
|
|
2588
|
+
name,
|
|
2589
|
+
context,
|
|
2590
|
+
formDataContext
|
|
2591
|
+
}),
|
|
2592
|
+
originalSchema: schemaObject,
|
|
2593
|
+
isRef: false
|
|
2594
|
+
};
|
|
2595
|
+
const resolvedImport = imports[0];
|
|
2596
|
+
let hasReadonlyProps = false;
|
|
2597
|
+
const refName = resolvedImport.name;
|
|
2598
|
+
if (!context.parents?.includes(refName) && hasScopeAffectedDynamicRef(schemaObject, context, refName)) return {
|
|
2599
|
+
...getScalar({
|
|
2600
|
+
item: schemaObject,
|
|
2601
|
+
name: name ?? refName,
|
|
2602
|
+
context: {
|
|
2603
|
+
...context,
|
|
2604
|
+
parents: [...context.parents ?? [], refName]
|
|
2605
|
+
},
|
|
2606
|
+
formDataContext
|
|
2607
|
+
}),
|
|
2608
|
+
originalSchema: schemaObject,
|
|
2609
|
+
isRef: false
|
|
2610
|
+
};
|
|
2611
|
+
if (!context.parents?.includes(refName)) hasReadonlyProps = getScalar({
|
|
2612
|
+
item: schemaObject,
|
|
2613
|
+
name: refName,
|
|
2614
|
+
context: {
|
|
2615
|
+
...context,
|
|
2616
|
+
parents: [...context.parents ?? [], refName]
|
|
2617
|
+
}
|
|
2618
|
+
}).hasReadonlyProps;
|
|
2619
|
+
const isAnyOfNullable = schemaObject.anyOf?.some((anyOfItem) => !isReference(anyOfItem) && (anyOfItem.type === "null" || Array.isArray(anyOfItem.type) && anyOfItem.type.includes("null")));
|
|
2620
|
+
const schemaType = schemaObject.type;
|
|
2621
|
+
const nullable = Array.isArray(schemaType) && schemaType.includes("null") || schemaObject.nullable === true || isAnyOfNullable ? " | null" : "";
|
|
2323
2622
|
return {
|
|
2324
|
-
value: name + nullable,
|
|
2325
|
-
imports: [{
|
|
2623
|
+
value: resolvedImport.name + nullable,
|
|
2624
|
+
imports: [{
|
|
2625
|
+
name: resolvedImport.name,
|
|
2626
|
+
schemaName: resolvedImport.schemaName
|
|
2627
|
+
}],
|
|
2628
|
+
type: schemaObject.type ?? "object",
|
|
2326
2629
|
schemas: [],
|
|
2327
|
-
isEnum:
|
|
2630
|
+
isEnum: !!schemaObject.enum,
|
|
2631
|
+
originalSchema: schemaObject,
|
|
2632
|
+
hasReadonlyProps,
|
|
2633
|
+
isRef: true,
|
|
2634
|
+
dependencies: [resolvedImport.name]
|
|
2635
|
+
};
|
|
2636
|
+
}
|
|
2637
|
+
if (isDynamicReference(schema)) {
|
|
2638
|
+
const dynamicRef = schema.$dynamicRef;
|
|
2639
|
+
if (!dynamicRef.startsWith("#")) return makeUnknownValue(schema);
|
|
2640
|
+
const anchorName = getDynamicAnchorName(dynamicRef);
|
|
2641
|
+
if (!anchorName) return makeUnknownValue(schema);
|
|
2642
|
+
const { imports: resolvedImports, resolvedTypeName } = resolveDynamicRef(anchorName, context);
|
|
2643
|
+
if (resolvedTypeName === "unknown") return makeUnknownValue(schema);
|
|
2644
|
+
return {
|
|
2645
|
+
value: resolvedTypeName,
|
|
2646
|
+
imports: resolvedImports,
|
|
2328
2647
|
type: "object",
|
|
2648
|
+
isEnum: false,
|
|
2649
|
+
schemas: [],
|
|
2329
2650
|
isRef: true,
|
|
2330
|
-
hasReadonlyProps:
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
examples: resolveExampleRefs(item.examples, context)
|
|
2651
|
+
hasReadonlyProps: false,
|
|
2652
|
+
originalSchema: schema,
|
|
2653
|
+
dependencies: [resolvedTypeName]
|
|
2334
2654
|
};
|
|
2335
2655
|
}
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
const itemAnyOf = schemaItem.anyOf;
|
|
2340
|
-
const itemType = schemaItem.type;
|
|
2341
|
-
if (itemAllOf || itemOneOf || itemAnyOf) return combineSchemas({
|
|
2342
|
-
schema: schemaItem,
|
|
2343
|
-
name,
|
|
2344
|
-
separator: itemAllOf ? "allOf" : itemOneOf ? "oneOf" : "anyOf",
|
|
2345
|
-
context,
|
|
2346
|
-
nullable,
|
|
2347
|
-
formDataContext
|
|
2348
|
-
});
|
|
2349
|
-
if (Array.isArray(itemType)) {
|
|
2350
|
-
const typeArray = itemType;
|
|
2351
|
-
const baseItem = schemaItem;
|
|
2352
|
-
return combineSchemas({
|
|
2353
|
-
schema: { anyOf: typeArray.map((type) => ({
|
|
2354
|
-
...baseItem,
|
|
2355
|
-
type
|
|
2356
|
-
})) },
|
|
2656
|
+
return {
|
|
2657
|
+
...getScalar({
|
|
2658
|
+
item: schema,
|
|
2357
2659
|
name,
|
|
2358
|
-
separator: "anyOf",
|
|
2359
2660
|
context,
|
|
2360
|
-
|
|
2361
|
-
})
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2661
|
+
formDataContext
|
|
2662
|
+
}),
|
|
2663
|
+
originalSchema: schema,
|
|
2664
|
+
isRef: false
|
|
2665
|
+
};
|
|
2666
|
+
}
|
|
2667
|
+
//#endregion
|
|
2668
|
+
//#region src/resolvers/object.ts
|
|
2669
|
+
/**
|
|
2670
|
+
* Wraps inline object type in a type alias.
|
|
2671
|
+
* E.g. `{ foo: string }` → value becomes `FooBody`, schema gets `export type FooBody = { foo: string };`
|
|
2672
|
+
*/
|
|
2673
|
+
function createTypeAliasIfNeeded({ resolvedValue, propName, context }) {
|
|
2674
|
+
if (!propName) return;
|
|
2675
|
+
if (resolvedValue.isEnum || resolvedValue.type !== "object") return;
|
|
2676
|
+
const aliasPattern = context.output.override.aliasCombinedTypes ? String.raw`{|&|\|` : "{";
|
|
2677
|
+
if (!new RegExp(aliasPattern).test(resolvedValue.value)) return;
|
|
2678
|
+
const { originalSchema } = resolvedValue;
|
|
2679
|
+
const doc = jsDoc(originalSchema);
|
|
2680
|
+
const isConstant = "const" in originalSchema;
|
|
2681
|
+
const constantIsString = "type" in originalSchema && (originalSchema.type === "string" || Array.isArray(originalSchema.type) && originalSchema.type.includes("string"));
|
|
2682
|
+
const model = isConstant ? `${doc}export const ${propName} = ${constantIsString ? `'${originalSchema.const}'` : originalSchema.const} as const;\n` : `${doc}export type ${propName} = ${resolvedValue.value};\n`;
|
|
2683
|
+
return {
|
|
2684
|
+
value: propName,
|
|
2685
|
+
imports: [{
|
|
2686
|
+
name: propName,
|
|
2687
|
+
isConstant
|
|
2688
|
+
}],
|
|
2689
|
+
schemas: [...resolvedValue.schemas, {
|
|
2690
|
+
name: propName,
|
|
2691
|
+
model,
|
|
2692
|
+
imports: resolvedValue.imports,
|
|
2693
|
+
dependencies: resolvedValue.dependencies
|
|
2694
|
+
}],
|
|
2695
|
+
isEnum: false,
|
|
2696
|
+
type: "object",
|
|
2697
|
+
isRef: resolvedValue.isRef,
|
|
2698
|
+
hasReadonlyProps: resolvedValue.hasReadonlyProps,
|
|
2699
|
+
dependencies: resolvedValue.dependencies
|
|
2700
|
+
};
|
|
2701
|
+
}
|
|
2702
|
+
function resolveObjectOriginal({ schema, propName, combined = false, context, formDataContext }) {
|
|
2703
|
+
const resolvedValue = resolveValue({
|
|
2704
|
+
schema,
|
|
2705
|
+
name: propName,
|
|
2706
|
+
context,
|
|
2707
|
+
formDataContext
|
|
2708
|
+
});
|
|
2709
|
+
const aliased = createTypeAliasIfNeeded({
|
|
2710
|
+
resolvedValue,
|
|
2711
|
+
propName,
|
|
2712
|
+
context
|
|
2713
|
+
});
|
|
2714
|
+
if (aliased) return {
|
|
2715
|
+
...aliased,
|
|
2716
|
+
originalSchema: resolvedValue.originalSchema
|
|
2717
|
+
};
|
|
2718
|
+
if (propName && resolvedValue.isEnum && !combined && !resolvedValue.isRef) {
|
|
2719
|
+
const doc = jsDoc(resolvedValue.originalSchema);
|
|
2720
|
+
const enumValue = getEnum(resolvedValue.value, propName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention.enum);
|
|
2721
|
+
return {
|
|
2722
|
+
value: propName,
|
|
2723
|
+
imports: [{ name: propName }],
|
|
2724
|
+
schemas: [...resolvedValue.schemas, {
|
|
2725
|
+
name: propName,
|
|
2726
|
+
model: doc + enumValue,
|
|
2727
|
+
imports: resolvedValue.imports,
|
|
2728
|
+
dependencies: resolvedValue.dependencies
|
|
2729
|
+
}],
|
|
2730
|
+
isEnum: false,
|
|
2731
|
+
type: "enum",
|
|
2732
|
+
originalSchema: resolvedValue.originalSchema,
|
|
2733
|
+
isRef: resolvedValue.isRef,
|
|
2734
|
+
hasReadonlyProps: resolvedValue.hasReadonlyProps,
|
|
2735
|
+
dependencies: [...resolvedValue.dependencies, propName]
|
|
2736
|
+
};
|
|
2737
|
+
}
|
|
2738
|
+
return resolvedValue;
|
|
2739
|
+
}
|
|
2740
|
+
const resolveObjectCacheMap = /* @__PURE__ */ new Map();
|
|
2741
|
+
function resolveObject({ schema, propName, combined = false, context, formDataContext }) {
|
|
2742
|
+
const hashKey = JSON.stringify({
|
|
2743
|
+
schema,
|
|
2744
|
+
propName,
|
|
2745
|
+
combined,
|
|
2746
|
+
projectName: context.projectName ?? context.output.target,
|
|
2747
|
+
formDataContext,
|
|
2748
|
+
dynamicScope: context.dynamicScope
|
|
2749
|
+
});
|
|
2750
|
+
if (resolveObjectCacheMap.has(hashKey)) return resolveObjectCacheMap.get(hashKey);
|
|
2751
|
+
const result = resolveObjectOriginal({
|
|
2752
|
+
schema,
|
|
2753
|
+
propName,
|
|
2754
|
+
combined,
|
|
2755
|
+
context,
|
|
2756
|
+
formDataContext
|
|
2757
|
+
});
|
|
2758
|
+
resolveObjectCacheMap.set(hashKey, result);
|
|
2759
|
+
return result;
|
|
2760
|
+
}
|
|
2761
|
+
//#endregion
|
|
2762
|
+
//#region src/getters/array.ts
|
|
2763
|
+
/**
|
|
2764
|
+
* Return the output type from an array
|
|
2765
|
+
*
|
|
2766
|
+
* @param item item with type === "array"
|
|
2767
|
+
*/
|
|
2768
|
+
function getArray({ schema, name, context, formDataContext }) {
|
|
2769
|
+
const schemaPrefixItems = schema.prefixItems;
|
|
2770
|
+
const schemaItems = schema.items;
|
|
2771
|
+
const schemaExample = schema.example;
|
|
2772
|
+
const schemaExamples = schema.examples;
|
|
2773
|
+
const itemSuffix = context.output.override.components.schemas.itemSuffix;
|
|
2774
|
+
if (schemaPrefixItems) {
|
|
2775
|
+
const resolvedObjects = schemaPrefixItems.map((item, index) => resolveObject({
|
|
2776
|
+
schema: item,
|
|
2777
|
+
propName: name ? name + itemSuffix + String(index) : void 0,
|
|
2778
|
+
context
|
|
2779
|
+
}));
|
|
2780
|
+
if (schemaItems) {
|
|
2781
|
+
const additional = resolveObject({
|
|
2782
|
+
schema: schemaItems,
|
|
2783
|
+
propName: name ? name + itemSuffix + "Additional" : void 0,
|
|
2784
|
+
context
|
|
2785
|
+
});
|
|
2786
|
+
resolvedObjects.push({
|
|
2787
|
+
...additional,
|
|
2788
|
+
value: `...${additional.value}[]`
|
|
2789
|
+
});
|
|
2790
|
+
}
|
|
2791
|
+
return {
|
|
2792
|
+
type: "array",
|
|
2793
|
+
isEnum: false,
|
|
2794
|
+
isRef: false,
|
|
2795
|
+
value: `[${resolvedObjects.map((o) => o.value).join(", ")}]`,
|
|
2796
|
+
imports: resolvedObjects.flatMap((o) => o.imports),
|
|
2797
|
+
schemas: resolvedObjects.flatMap((o) => o.schemas),
|
|
2798
|
+
dependencies: resolvedObjects.flatMap((o) => o.dependencies),
|
|
2799
|
+
hasReadonlyProps: resolvedObjects.some((o) => o.hasReadonlyProps),
|
|
2800
|
+
example: schemaExample,
|
|
2801
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
2802
|
+
};
|
|
2803
|
+
}
|
|
2804
|
+
if (schemaItems) {
|
|
2805
|
+
const resolvedObject = resolveObject({
|
|
2806
|
+
schema: schemaItems,
|
|
2807
|
+
propName: name ? name + itemSuffix : void 0,
|
|
2808
|
+
context,
|
|
2809
|
+
formDataContext
|
|
2368
2810
|
});
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2811
|
+
return {
|
|
2812
|
+
value: `${schema.readOnly === true && !context.output.override.suppressReadonlyModifier ? "readonly " : ""}${resolvedObject.value.includes("|") || resolvedObject.value.includes("&") ? `(${resolvedObject.value})[]` : `${resolvedObject.value}[]`}`,
|
|
2813
|
+
imports: resolvedObject.imports,
|
|
2814
|
+
schemas: resolvedObject.schemas,
|
|
2815
|
+
dependencies: resolvedObject.dependencies,
|
|
2373
2816
|
isEnum: false,
|
|
2374
|
-
type: "
|
|
2817
|
+
type: "array",
|
|
2375
2818
|
isRef: false,
|
|
2376
|
-
hasReadonlyProps:
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
example: schemaItem.example,
|
|
2380
|
-
examples: resolveExampleRefs(schemaItem.examples, context)
|
|
2819
|
+
hasReadonlyProps: resolvedObject.hasReadonlyProps,
|
|
2820
|
+
example: schemaExample,
|
|
2821
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
2381
2822
|
};
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2823
|
+
} else if (compareVersions(context.spec.openapi ?? "3.0.0", "3.1", ">=")) return {
|
|
2824
|
+
value: "unknown[]",
|
|
2825
|
+
imports: [],
|
|
2826
|
+
schemas: [],
|
|
2827
|
+
dependencies: [],
|
|
2828
|
+
isEnum: false,
|
|
2829
|
+
type: "array",
|
|
2830
|
+
isRef: false,
|
|
2831
|
+
hasReadonlyProps: false
|
|
2832
|
+
};
|
|
2833
|
+
else throw new Error(`All arrays must have an \`items\` key defined (name=${name}, schema=${JSON.stringify(schema)})`);
|
|
2834
|
+
}
|
|
2835
|
+
//#endregion
|
|
2836
|
+
//#region src/getters/res-req-types.ts
|
|
2837
|
+
const getSchemaType$1 = (s) => s.type;
|
|
2838
|
+
const getSchemaCombined = (s) => s.oneOf ?? s.anyOf ?? s.allOf;
|
|
2839
|
+
const getSchemaOneOf = (s) => s.oneOf;
|
|
2840
|
+
const getSchemaAnyOf = (s) => s.anyOf;
|
|
2841
|
+
const getSchemaItems = (s) => s.items;
|
|
2842
|
+
const getSchemaRequired = (s) => s.required;
|
|
2843
|
+
const getSchemaProperties = (s) => s.properties;
|
|
2844
|
+
const resolveSchemaRef = (schema, context) => resolveRef(schema, context);
|
|
2845
|
+
const resolveResponseOrRequestRef = (schema, context) => resolveRef(schema, context);
|
|
2846
|
+
const formDataContentTypes = new Set(["multipart/form-data"]);
|
|
2847
|
+
const formUrlEncodedContentTypes = new Set(["application/x-www-form-urlencoded"]);
|
|
2848
|
+
function getResReqContentTypes({ mediaType, propName, context, isFormData, contentType }) {
|
|
2849
|
+
if (!mediaType.schema) return;
|
|
2850
|
+
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
2851
|
+
const formDataContext = isFormData ? {
|
|
2852
|
+
atPart: false,
|
|
2853
|
+
encoding: mediaType.encoding ?? {}
|
|
2854
|
+
} : isFormUrlEncoded ? {
|
|
2855
|
+
atPart: false,
|
|
2856
|
+
encoding: mediaType.encoding ?? {},
|
|
2857
|
+
urlEncoded: true
|
|
2858
|
+
} : void 0;
|
|
2859
|
+
const resolvedObject = resolveObject({
|
|
2860
|
+
schema: mediaType.schema,
|
|
2861
|
+
propName,
|
|
2862
|
+
context,
|
|
2863
|
+
formDataContext
|
|
2864
|
+
});
|
|
2865
|
+
if (!isFormData && isBinaryContentType(contentType)) return {
|
|
2866
|
+
...resolvedObject,
|
|
2867
|
+
value: "Blob"
|
|
2868
|
+
};
|
|
2869
|
+
return resolvedObject;
|
|
2870
|
+
}
|
|
2871
|
+
function getResReqTypes(responsesOrRequests, name, context, defaultType = "unknown", uniqueKey = (item) => item.value) {
|
|
2872
|
+
return uniqueBy(responsesOrRequests.filter(([, res]) => Boolean(res)).map(([key, res]) => {
|
|
2873
|
+
if (isReference(res)) {
|
|
2874
|
+
const { schema: bodySchema, imports: [{ name, schemaName }] } = resolveResponseOrRequestRef(res, context);
|
|
2875
|
+
const firstEntry = Object.entries(bodySchema.content ?? {}).at(0);
|
|
2876
|
+
if (!firstEntry) return [{
|
|
2877
|
+
value: name,
|
|
2878
|
+
imports: [{
|
|
2879
|
+
name,
|
|
2880
|
+
schemaName
|
|
2881
|
+
}],
|
|
2882
|
+
schemas: [],
|
|
2883
|
+
type: "unknown",
|
|
2884
|
+
isEnum: false,
|
|
2885
|
+
isRef: true,
|
|
2886
|
+
hasReadonlyProps: false,
|
|
2887
|
+
dependencies: [name],
|
|
2888
|
+
originalSchema: void 0,
|
|
2889
|
+
example: void 0,
|
|
2890
|
+
examples: void 0,
|
|
2891
|
+
key,
|
|
2892
|
+
contentType: ""
|
|
2893
|
+
}];
|
|
2894
|
+
const [contentType, mediaType] = firstEntry;
|
|
2895
|
+
const isFormData = formDataContentTypes.has(contentType);
|
|
2896
|
+
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
2897
|
+
if (!isFormData && !isFormUrlEncoded || !mediaType.schema) return [{
|
|
2898
|
+
value: name,
|
|
2899
|
+
imports: [{
|
|
2900
|
+
name,
|
|
2901
|
+
schemaName
|
|
2902
|
+
}],
|
|
2903
|
+
schemas: [],
|
|
2904
|
+
type: "unknown",
|
|
2905
|
+
isEnum: false,
|
|
2906
|
+
isRef: true,
|
|
2907
|
+
hasReadonlyProps: false,
|
|
2908
|
+
dependencies: [name],
|
|
2909
|
+
originalSchema: mediaType.schema,
|
|
2910
|
+
example: mediaType.example,
|
|
2911
|
+
examples: resolveExampleRefs(mediaType.examples, context),
|
|
2912
|
+
key,
|
|
2913
|
+
contentType
|
|
2914
|
+
}];
|
|
2915
|
+
const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
|
|
2420
2916
|
name,
|
|
2917
|
+
schemaObject: mediaType.schema,
|
|
2421
2918
|
context,
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2919
|
+
isRequestBodyOptional: bodySchema.required !== true,
|
|
2920
|
+
isRef: true,
|
|
2921
|
+
encoding: mediaType.encoding
|
|
2922
|
+
}) : void 0;
|
|
2923
|
+
const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
|
|
2924
|
+
name,
|
|
2925
|
+
schemaObject: mediaType.schema,
|
|
2426
2926
|
context,
|
|
2427
|
-
|
|
2428
|
-
|
|
2927
|
+
isRequestBodyOptional: bodySchema.required !== true,
|
|
2928
|
+
isUrlEncoded: true,
|
|
2929
|
+
isRef: true,
|
|
2930
|
+
encoding: mediaType.encoding
|
|
2931
|
+
}) : void 0;
|
|
2932
|
+
const additionalImports = getFormDataAdditionalImports({
|
|
2933
|
+
schemaObject: mediaType.schema,
|
|
2934
|
+
context
|
|
2429
2935
|
});
|
|
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
|
-
|
|
2936
|
+
return [{
|
|
2937
|
+
value: name,
|
|
2938
|
+
imports: [{
|
|
2939
|
+
name,
|
|
2940
|
+
schemaName
|
|
2941
|
+
}, ...additionalImports],
|
|
2942
|
+
schemas: [],
|
|
2943
|
+
type: "unknown",
|
|
2944
|
+
isEnum: false,
|
|
2945
|
+
hasReadonlyProps: false,
|
|
2946
|
+
dependencies: [name],
|
|
2947
|
+
formData,
|
|
2948
|
+
formUrlEncoded,
|
|
2949
|
+
isRef: true,
|
|
2950
|
+
originalSchema: mediaType.schema,
|
|
2951
|
+
example: mediaType.example,
|
|
2952
|
+
examples: resolveExampleRefs(mediaType.examples, context),
|
|
2953
|
+
key,
|
|
2954
|
+
contentType
|
|
2955
|
+
}];
|
|
2956
|
+
}
|
|
2957
|
+
if (res.content) return Object.entries(res.content).map(([contentType, mediaType], index, arr) => {
|
|
2958
|
+
let propName = key ? pascal(name) + pascal(key) : void 0;
|
|
2959
|
+
if (propName && arr.length > 1) propName = propName + pascal(getNumberWord(index + 1));
|
|
2960
|
+
const isFormData = formDataContentTypes.has(contentType);
|
|
2961
|
+
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
2962
|
+
let effectivePropName = propName;
|
|
2963
|
+
if (mediaType.schema && isReference(mediaType.schema)) {
|
|
2964
|
+
const { imports } = resolveSchemaRef(mediaType.schema, context);
|
|
2965
|
+
if (imports[0]?.name) effectivePropName = imports[0].name;
|
|
2966
|
+
} else if ((isFormData || isFormUrlEncoded) && mediaType.schema) {
|
|
2967
|
+
const combinedRefs = getSchemaOneOf(mediaType.schema) ?? getSchemaAnyOf(mediaType.schema);
|
|
2968
|
+
if (combinedRefs) {
|
|
2969
|
+
const names = [];
|
|
2970
|
+
for (const ref of combinedRefs) {
|
|
2971
|
+
if (!isReference(ref)) continue;
|
|
2972
|
+
const refName = resolveSchemaRef(ref, context).imports[0]?.name;
|
|
2973
|
+
if (refName) names.push(refName);
|
|
2467
2974
|
}
|
|
2468
|
-
|
|
2469
|
-
acc.schemas.push(...resolvedValue.schemas);
|
|
2470
|
-
acc.dependencies.push(...resolvedValue.dependencies);
|
|
2975
|
+
if (names.length > 0) effectivePropName = names.join("");
|
|
2471
2976
|
}
|
|
2472
|
-
else acc.value += "\n}";
|
|
2473
|
-
acc.value += nullable;
|
|
2474
2977
|
}
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2978
|
+
const resolvedValue = getResReqContentTypes({
|
|
2979
|
+
mediaType,
|
|
2980
|
+
propName: effectivePropName,
|
|
2981
|
+
context,
|
|
2982
|
+
isFormData,
|
|
2983
|
+
contentType
|
|
2984
|
+
});
|
|
2985
|
+
if (!resolvedValue) {
|
|
2986
|
+
if (isBinaryContentType(contentType)) return {
|
|
2987
|
+
value: "Blob",
|
|
2988
|
+
imports: [],
|
|
2989
|
+
schemas: [],
|
|
2990
|
+
type: "Blob",
|
|
2991
|
+
isEnum: false,
|
|
2992
|
+
key,
|
|
2993
|
+
isRef: false,
|
|
2994
|
+
hasReadonlyProps: false,
|
|
2995
|
+
contentType
|
|
2996
|
+
};
|
|
2997
|
+
return;
|
|
2998
|
+
}
|
|
2999
|
+
if (!isFormData && !isFormUrlEncoded || !effectivePropName || !mediaType.schema) return {
|
|
3000
|
+
...resolvedValue,
|
|
3001
|
+
imports: resolvedValue.imports,
|
|
3002
|
+
dependencies: resolvedValue.dependencies,
|
|
3003
|
+
contentType,
|
|
3004
|
+
example: mediaType.example,
|
|
3005
|
+
examples: resolveExampleRefs(mediaType.examples, context)
|
|
2493
3006
|
};
|
|
3007
|
+
const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
|
|
3008
|
+
name: effectivePropName,
|
|
3009
|
+
schemaObject: mediaType.schema,
|
|
3010
|
+
context,
|
|
3011
|
+
isRequestBodyOptional: res.required !== true,
|
|
3012
|
+
isRef: true,
|
|
3013
|
+
encoding: mediaType.encoding
|
|
3014
|
+
}) : void 0;
|
|
3015
|
+
const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
|
|
3016
|
+
name: effectivePropName,
|
|
3017
|
+
schemaObject: mediaType.schema,
|
|
3018
|
+
context,
|
|
3019
|
+
isUrlEncoded: true,
|
|
3020
|
+
isRequestBodyOptional: res.required !== true,
|
|
3021
|
+
isRef: true,
|
|
3022
|
+
encoding: mediaType.encoding
|
|
3023
|
+
}) : void 0;
|
|
3024
|
+
const additionalImports = getFormDataAdditionalImports({
|
|
3025
|
+
schemaObject: mediaType.schema,
|
|
3026
|
+
context
|
|
3027
|
+
});
|
|
2494
3028
|
return {
|
|
2495
|
-
|
|
2496
|
-
imports: [],
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
useTypeAlias: false,
|
|
2503
|
-
dependencies: []
|
|
3029
|
+
...resolvedValue,
|
|
3030
|
+
imports: [...resolvedValue.imports, ...additionalImports],
|
|
3031
|
+
formData,
|
|
3032
|
+
formUrlEncoded,
|
|
3033
|
+
contentType,
|
|
3034
|
+
example: mediaType.example,
|
|
3035
|
+
examples: resolveExampleRefs(mediaType.examples, context)
|
|
2504
3036
|
};
|
|
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),
|
|
3037
|
+
}).filter(Boolean).map((x) => ({
|
|
3038
|
+
...x,
|
|
3039
|
+
key
|
|
3040
|
+
}));
|
|
3041
|
+
const swaggerSchema = "schema" in res ? res.schema : void 0;
|
|
3042
|
+
if (swaggerSchema) return [{
|
|
3043
|
+
...resolveObject({
|
|
3044
|
+
schema: swaggerSchema,
|
|
3045
|
+
propName: key ? pascal(name) + pascal(key) : void 0,
|
|
3046
|
+
context
|
|
3047
|
+
}),
|
|
3048
|
+
contentType: "application/json",
|
|
3049
|
+
key
|
|
3050
|
+
}];
|
|
3051
|
+
return [{
|
|
3052
|
+
value: defaultType,
|
|
2546
3053
|
imports: [],
|
|
2547
3054
|
schemas: [],
|
|
3055
|
+
type: defaultType,
|
|
2548
3056
|
isEnum: false,
|
|
2549
|
-
|
|
3057
|
+
dependencies: [],
|
|
3058
|
+
key,
|
|
2550
3059
|
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
|
-
};
|
|
3060
|
+
hasReadonlyProps: false,
|
|
3061
|
+
contentType: "application/json"
|
|
3062
|
+
}];
|
|
3063
|
+
}).flat(), uniqueKey);
|
|
2579
3064
|
}
|
|
2580
|
-
//#endregion
|
|
2581
|
-
//#region src/getters/scalar.ts
|
|
2582
3065
|
/**
|
|
2583
|
-
*
|
|
3066
|
+
* Determine the responseType option based on success content types only.
|
|
3067
|
+
* This avoids error-response content types influencing the responseType.
|
|
3068
|
+
*/
|
|
3069
|
+
function getSuccessResponseType(response) {
|
|
3070
|
+
const successContentTypes = response.types.success.map((t) => t.contentType).filter(Boolean);
|
|
3071
|
+
if (response.isBlob) return "blob";
|
|
3072
|
+
const hasJsonResponse = successContentTypes.some((contentType) => contentType.includes("json") || contentType.includes("+json"));
|
|
3073
|
+
const hasTextResponse = successContentTypes.some((contentType) => contentType.startsWith("text/") || contentType.includes("xml"));
|
|
3074
|
+
if (!hasJsonResponse && hasTextResponse) return "text";
|
|
3075
|
+
}
|
|
3076
|
+
/**
|
|
3077
|
+
* Determine the response type category for a given content type.
|
|
3078
|
+
* Used to set the correct responseType option in HTTP clients.
|
|
2584
3079
|
*
|
|
2585
|
-
* @param
|
|
2586
|
-
* @
|
|
3080
|
+
* @param contentType - The MIME content type (e.g., 'application/json', 'text/plain')
|
|
3081
|
+
* @returns The response type category to use for parsing
|
|
2587
3082
|
*/
|
|
2588
|
-
function
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
if (
|
|
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
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
value
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
});
|
|
2659
|
-
return {
|
|
2660
|
-
value: value + nullable,
|
|
2661
|
-
...rest,
|
|
2662
|
-
dependencies: rest.dependencies
|
|
2663
|
-
};
|
|
2664
|
-
}
|
|
2665
|
-
case "string": {
|
|
2666
|
-
let value = "string";
|
|
2667
|
-
let isEnum = false;
|
|
2668
|
-
if (enumItems) {
|
|
2669
|
-
value = enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
|
|
2670
|
-
isEnum = true;
|
|
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";
|
|
3083
|
+
function getResponseTypeCategory(contentType) {
|
|
3084
|
+
if (isBinaryContentType(contentType)) return "blob";
|
|
3085
|
+
if (contentType === "application/json" || contentType.includes("+json") || contentType.includes("-json")) return "json";
|
|
3086
|
+
return "text";
|
|
3087
|
+
}
|
|
3088
|
+
/**
|
|
3089
|
+
* Get the default content type from a list of content types.
|
|
3090
|
+
* Priority: application/json > any JSON-like type > first in list
|
|
3091
|
+
*
|
|
3092
|
+
* @param contentTypes - Array of content types from OpenAPI spec
|
|
3093
|
+
* @returns The default content type to use
|
|
3094
|
+
*/
|
|
3095
|
+
function getDefaultContentType(contentTypes) {
|
|
3096
|
+
if (contentTypes.length === 0) return "application/json";
|
|
3097
|
+
if (contentTypes.includes("application/json")) return "application/json";
|
|
3098
|
+
const jsonType = contentTypes.find((ct) => ct.includes("+json") || ct.includes("-json"));
|
|
3099
|
+
if (jsonType) return jsonType;
|
|
3100
|
+
return contentTypes[0];
|
|
3101
|
+
}
|
|
3102
|
+
function getFormDataAdditionalImports({ schemaObject, context }) {
|
|
3103
|
+
const { schema } = resolveSchemaRef(schemaObject, context);
|
|
3104
|
+
if (schema.type !== "object") return [];
|
|
3105
|
+
const combinedSchemas = getSchemaOneOf(schema) ?? getSchemaAnyOf(schema);
|
|
3106
|
+
if (!combinedSchemas) return [];
|
|
3107
|
+
return combinedSchemas.map((subSchema) => resolveSchemaRef(subSchema, context).imports[0]).filter(Boolean);
|
|
3108
|
+
}
|
|
3109
|
+
function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequestBodyOptional, isUrlEncoded, isRef, encoding }) {
|
|
3110
|
+
const { schema, imports } = resolveSchemaRef(schemaObject, context);
|
|
3111
|
+
const propName = camel(!isRef && isReference(schemaObject) ? imports[0].name : name);
|
|
3112
|
+
const variableName = isUrlEncoded ? "formUrlEncoded" : "formData";
|
|
3113
|
+
let form = isUrlEncoded ? `const ${variableName} = new URLSearchParams();\n` : `const ${variableName} = new FormData();\n`;
|
|
3114
|
+
const combinedSchemas = getSchemaCombined(schema);
|
|
3115
|
+
if (schema.type === "object" || schema.type === void 0 && combinedSchemas) {
|
|
3116
|
+
if (combinedSchemas) if (!!getSchemaOneOf(schema) || !!getSchemaAnyOf(schema)) {
|
|
3117
|
+
const directProperties = getSchemaProperties(schema);
|
|
3118
|
+
const directKeys = directProperties ? Object.entries(directProperties).filter(([, value]) => !resolveSchemaRef(value, context).schema.readOnly).map(([key]) => key) : [];
|
|
3119
|
+
const skipLine = directKeys.length > 0 ? ` if ([${directKeys.map((k) => JSON.stringify(k)).join(", ")}].includes(key)) return;\n` : "";
|
|
3120
|
+
form += `Object.entries(${propName} ?? {}).forEach(([key, value]) => {\n`;
|
|
3121
|
+
form += skipLine;
|
|
3122
|
+
form += ` if (value !== undefined && value !== null) {\n`;
|
|
3123
|
+
if (isUrlEncoded) {
|
|
3124
|
+
form += ` if (Array.isArray(value)) {\n`;
|
|
3125
|
+
form += ` value.forEach(v => {\n`;
|
|
3126
|
+
form += ` ${variableName}.append(key, typeof v === 'object' ? JSON.stringify(v) : String(v));\n`;
|
|
3127
|
+
form += ` });\n`;
|
|
3128
|
+
form += ` } else if (typeof value === 'object') {\n`;
|
|
3129
|
+
form += ` ${variableName}.append(key, JSON.stringify(value));\n`;
|
|
3130
|
+
form += ` } else {\n`;
|
|
3131
|
+
form += ` ${variableName}.append(key, String(value));\n`;
|
|
3132
|
+
form += ` }\n`;
|
|
3133
|
+
} else {
|
|
3134
|
+
form += ` if ((typeof File !== 'undefined' && value instanceof File) || value instanceof Blob) {\n`;
|
|
3135
|
+
form += ` ${variableName}.append(key, value);\n`;
|
|
3136
|
+
form += ` } else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {\n`;
|
|
3137
|
+
form += ` ${variableName}.append(key, new Blob([Uint8Array.from(value)]));\n`;
|
|
3138
|
+
form += ` } else if (Array.isArray(value)) {\n`;
|
|
3139
|
+
form += ` value.forEach(v => {\n`;
|
|
3140
|
+
form += ` if ((typeof File !== 'undefined' && v instanceof File) || v instanceof Blob) {\n`;
|
|
3141
|
+
form += ` ${variableName}.append(key, v);\n`;
|
|
3142
|
+
form += ` } else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(v)) {\n`;
|
|
3143
|
+
form += ` ${variableName}.append(key, new Blob([Uint8Array.from(v)]));\n`;
|
|
3144
|
+
form += ` } else {\n`;
|
|
3145
|
+
form += ` ${variableName}.append(key, typeof v === 'object' ? JSON.stringify(v) : String(v));\n`;
|
|
3146
|
+
form += ` }\n`;
|
|
3147
|
+
form += ` });\n`;
|
|
3148
|
+
form += ` } else if (typeof value === 'object') {\n`;
|
|
3149
|
+
form += ` ${variableName}.append(key, JSON.stringify(value));\n`;
|
|
3150
|
+
form += ` } else {\n`;
|
|
3151
|
+
form += ` ${variableName}.append(key, String(value));\n`;
|
|
3152
|
+
form += ` }\n`;
|
|
2678
3153
|
}
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
3154
|
+
form += ` }\n`;
|
|
3155
|
+
form += `});\n`;
|
|
3156
|
+
} else {
|
|
3157
|
+
const combinedSchemasFormData = combinedSchemas.map((subSchema) => {
|
|
3158
|
+
const { schema: combinedSchema } = resolveSchemaRef(subSchema, context);
|
|
3159
|
+
return resolveSchemaPropertiesToFormData({
|
|
3160
|
+
schema: combinedSchema,
|
|
3161
|
+
variableName,
|
|
3162
|
+
propName,
|
|
3163
|
+
context,
|
|
3164
|
+
isRequestBodyOptional,
|
|
3165
|
+
encoding
|
|
3166
|
+
});
|
|
3167
|
+
}).filter(Boolean).join("\n");
|
|
3168
|
+
form += combinedSchemasFormData;
|
|
2694
3169
|
}
|
|
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,
|
|
3170
|
+
if (schema.properties) {
|
|
3171
|
+
const formDataValues = resolveSchemaPropertiesToFormData({
|
|
3172
|
+
schema,
|
|
3173
|
+
variableName,
|
|
3174
|
+
propName,
|
|
2729
3175
|
context,
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
});
|
|
2733
|
-
return {
|
|
2734
|
-
value,
|
|
2735
|
-
...rest
|
|
2736
|
-
};
|
|
2737
|
-
}
|
|
2738
|
-
}
|
|
2739
|
-
}
|
|
2740
|
-
//#endregion
|
|
2741
|
-
//#region src/getters/combine.ts
|
|
2742
|
-
const mergeableAllOfKeys = new Set([
|
|
2743
|
-
"type",
|
|
2744
|
-
"properties",
|
|
2745
|
-
"required"
|
|
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;
|
|
2769
|
-
}
|
|
2770
|
-
remainingAllOf.push(subSchema);
|
|
2771
|
-
}
|
|
2772
|
-
if (!didMerge || remainingAllOf.length === 0) return schema;
|
|
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
|
-
};
|
|
2779
|
-
}
|
|
2780
|
-
function combineValues({ resolvedData, resolvedValue, separator, context, parentSchema }) {
|
|
2781
|
-
if (resolvedData.isEnum.every(Boolean)) return `${resolvedData.values.join(` | `)}${resolvedValue ? ` | ${resolvedValue.value}` : ""}`;
|
|
2782
|
-
if (separator === "allOf") {
|
|
2783
|
-
let resolvedDataValue = resolvedData.values.map((v) => v.includes(" | ") ? `(${v})` : v).join(` & `);
|
|
2784
|
-
if (resolvedData.originalSchema.length > 0 && resolvedValue) {
|
|
2785
|
-
const discriminatedPropertySchemas = resolvedData.originalSchema.filter((s) => {
|
|
2786
|
-
const disc = s?.discriminator;
|
|
2787
|
-
return disc && resolvedValue.value.includes(` ${disc.propertyName}:`);
|
|
3176
|
+
isRequestBodyOptional,
|
|
3177
|
+
encoding
|
|
2788
3178
|
});
|
|
2789
|
-
|
|
3179
|
+
form += formDataValues;
|
|
2790
3180
|
}
|
|
2791
|
-
|
|
2792
|
-
const joined = `${resolvedDataValue}${resolvedValue ? ` & ${resolvedValueStr}` : ""}`;
|
|
2793
|
-
const overrideRequiredProperties = resolvedData.requiredProperties.filter((prop) => !resolvedData.originalSchema.some((schema) => {
|
|
2794
|
-
const props = schema?.properties;
|
|
2795
|
-
const req = schema?.required;
|
|
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;
|
|
3181
|
+
return form;
|
|
2804
3182
|
}
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
const
|
|
2810
|
-
if (
|
|
2811
|
-
|
|
2812
|
-
continue;
|
|
2813
|
-
}
|
|
2814
|
-
const subSchemaProps = subSchema.properties;
|
|
2815
|
-
const missingProperties = unique(resolvedData.allProperties.filter((p) => !Object.keys(subSchemaProps).includes(p)));
|
|
2816
|
-
values.push(`${resolvedData.values[i]}${missingProperties.length > 0 ? ` & {${missingProperties.map((p) => `${p}?: never`).join("; ")}}` : ""}`);
|
|
3183
|
+
if (schema.type === "array") {
|
|
3184
|
+
let valueStr = "value";
|
|
3185
|
+
const schemaItems = getSchemaItems(schema);
|
|
3186
|
+
if (schemaItems) {
|
|
3187
|
+
const { schema: itemSchema } = resolveSchemaRef(schemaItems, context);
|
|
3188
|
+
if (itemSchema.type === "object" || itemSchema.type === "array") valueStr = "JSON.stringify(value)";
|
|
3189
|
+
else if (itemSchema.type === "number" || itemSchema.type === "integer" || itemSchema.type === "boolean") valueStr = "value.toString()";
|
|
2817
3190
|
}
|
|
3191
|
+
return `${form}${propName}.forEach(value => ${variableName}.append('data', ${valueStr}))\n`;
|
|
2818
3192
|
}
|
|
2819
|
-
if (
|
|
2820
|
-
return
|
|
3193
|
+
if (schema.type === "number" || schema.type === "integer" || schema.type === "boolean") return `${form}${variableName}.append('data', ${propName}.toString())\n`;
|
|
3194
|
+
return `${form}${variableName}.append('data', ${propName})\n`;
|
|
2821
3195
|
}
|
|
2822
|
-
function
|
|
2823
|
-
|
|
2824
|
-
const
|
|
2825
|
-
const
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
propName
|
|
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({
|
|
3196
|
+
function resolveSchemaPropertiesToFormData({ schema, variableName, propName, context, isRequestBodyOptional, keyPrefix = "", depth = 0, encoding }) {
|
|
3197
|
+
let formDataValues = "";
|
|
3198
|
+
const isUrlEncoded = variableName === "formUrlEncoded";
|
|
3199
|
+
const schemaProps = getSchemaProperties(schema) ?? {};
|
|
3200
|
+
for (const [key, value] of Object.entries(schemaProps)) {
|
|
3201
|
+
const { schema: property } = resolveSchemaRef(value, context);
|
|
3202
|
+
if (property.readOnly) continue;
|
|
3203
|
+
let formDataValue = "";
|
|
3204
|
+
const partContentType = (depth === 0 ? encoding?.[key] : void 0)?.contentType;
|
|
3205
|
+
const formattedKeyPrefix = isRequestBodyOptional ? keyword.isIdentifierNameES5(key) ? "?" : "?." : "";
|
|
3206
|
+
const formattedKey = keyword.isIdentifierNameES5(key) ? `.${key}` : `['${key}']`;
|
|
3207
|
+
const valueKey = `${propName}${formattedKeyPrefix}${formattedKey}`;
|
|
3208
|
+
const nonOptionalValueKey = `${propName}${formattedKey}`;
|
|
3209
|
+
const fileType = getFormDataFieldFileType(property, partContentType);
|
|
3210
|
+
const effectiveContentType = partContentType ?? property.contentMediaType;
|
|
3211
|
+
if (isUrlEncoded && (fileType || property.format === "binary")) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
3212
|
+
else if (fileType === "binary" || property.format === "binary") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
3213
|
+
else if (fileType === "text") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey} instanceof Blob ? ${nonOptionalValueKey} : new Blob([${nonOptionalValueKey}], { type: '${effectiveContentType}' }));\n`;
|
|
3214
|
+
else if (property.type === "object" || Array.isArray(property.type) && property.type.includes("object")) formDataValue = context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE ? resolveSchemaPropertiesToFormData({
|
|
3215
|
+
schema: property,
|
|
3216
|
+
variableName,
|
|
3217
|
+
propName: nonOptionalValueKey,
|
|
2860
3218
|
context,
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
}))
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
3219
|
+
isRequestBodyOptional,
|
|
3220
|
+
keyPrefix: `${keyPrefix}${key}.`,
|
|
3221
|
+
depth: depth + 1,
|
|
3222
|
+
encoding
|
|
3223
|
+
}) : `${variableName}.append(\`${keyPrefix}${key}\`, JSON.stringify(${nonOptionalValueKey}));\n`;
|
|
3224
|
+
else if (property.type === "array" || Array.isArray(property.type) && property.type.includes("array")) {
|
|
3225
|
+
let valueStr = "value";
|
|
3226
|
+
let hasNonPrimitiveChild = false;
|
|
3227
|
+
const propertyItems = getSchemaItems(property);
|
|
3228
|
+
if (propertyItems) {
|
|
3229
|
+
const { schema: itemSchema } = resolveSchemaRef(propertyItems, context);
|
|
3230
|
+
if (itemSchema.type === "object" || itemSchema.type === "array") if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
|
|
3231
|
+
hasNonPrimitiveChild = true;
|
|
3232
|
+
const resolvedValue = resolveSchemaPropertiesToFormData({
|
|
3233
|
+
schema: itemSchema,
|
|
3234
|
+
variableName,
|
|
3235
|
+
propName: "value",
|
|
3236
|
+
context,
|
|
3237
|
+
isRequestBodyOptional,
|
|
3238
|
+
keyPrefix: `${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}].`,
|
|
3239
|
+
depth: depth + 1
|
|
3240
|
+
});
|
|
3241
|
+
formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => {
|
|
3242
|
+
${resolvedValue}});\n`;
|
|
3243
|
+
} else valueStr = "JSON.stringify(value)";
|
|
3244
|
+
else {
|
|
3245
|
+
const itemType = getSchemaType$1(itemSchema);
|
|
3246
|
+
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()";
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
|
|
3250
|
+
if (!hasNonPrimitiveChild) formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => ${variableName}.append(\`${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}]\`, ${valueStr}));\n`;
|
|
3251
|
+
} else formDataValue = `${valueKey}.forEach(value => ${variableName}.append(\`${keyPrefix}${key}${context.output.override.formData.arrayHandling === FormDataArrayHandling.SERIALIZE_WITH_BRACKETS ? "[]" : ""}\`, ${valueStr}));\n`;
|
|
3252
|
+
} else if ((() => {
|
|
3253
|
+
const propType = getSchemaType$1(property);
|
|
3254
|
+
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");
|
|
3255
|
+
})()) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
3256
|
+
else formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
3257
|
+
let existSubSchemaNullable = false;
|
|
3258
|
+
const combine = getSchemaCombined(property);
|
|
3259
|
+
if (combine) {
|
|
3260
|
+
const subSchemas = combine.map((c) => resolveObject({
|
|
3261
|
+
schema: c,
|
|
3262
|
+
combined: true,
|
|
3263
|
+
context
|
|
3264
|
+
}));
|
|
3265
|
+
if (subSchemas.some((subSchema) => {
|
|
3266
|
+
return [
|
|
3267
|
+
"number",
|
|
3268
|
+
"integer",
|
|
3269
|
+
"boolean"
|
|
3270
|
+
].includes(subSchema.type);
|
|
3271
|
+
})) formDataValue = `${variableName}.append(\`${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
3272
|
+
if (subSchemas.some((subSchema) => {
|
|
3273
|
+
return subSchema.type === "null";
|
|
3274
|
+
})) existSubSchemaNullable = true;
|
|
3275
|
+
}
|
|
3276
|
+
const isRequired = getSchemaRequired(schema)?.includes(key) && !isRequestBodyOptional;
|
|
3277
|
+
const propType = getSchemaType$1(property);
|
|
3278
|
+
if (property.nullable || Array.isArray(propType) && propType.includes("null") || existSubSchemaNullable) {
|
|
3279
|
+
if (isRequired) {
|
|
3280
|
+
formDataValues += `if(${valueKey} !== null) {\n ${formDataValue} }\n`;
|
|
3281
|
+
continue;
|
|
3282
|
+
}
|
|
3283
|
+
formDataValues += `if(${valueKey} !== undefined && ${nonOptionalValueKey} !== null) {\n ${formDataValue} }\n`;
|
|
3284
|
+
continue;
|
|
3285
|
+
}
|
|
3286
|
+
if (isRequired) {
|
|
3287
|
+
formDataValues += formDataValue;
|
|
3288
|
+
continue;
|
|
3289
|
+
}
|
|
3290
|
+
formDataValues += `if(${valueKey} !== undefined) {\n ${formDataValue} }\n`;
|
|
2904
3291
|
}
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
nullable: ""
|
|
3292
|
+
return formDataValues;
|
|
3293
|
+
}
|
|
3294
|
+
//#endregion
|
|
3295
|
+
//#region src/getters/body.ts
|
|
3296
|
+
function buildBody(filteredBodyTypes, requestBody, operationName, context) {
|
|
3297
|
+
const imports = filteredBodyTypes.flatMap(({ imports }) => imports);
|
|
3298
|
+
const schemas = filteredBodyTypes.flatMap(({ schemas }) => schemas);
|
|
3299
|
+
const definition = filteredBodyTypes.map(({ value }) => value).join(" | ");
|
|
3300
|
+
const nonReadonlyDefinition = filteredBodyTypes.some((x) => x.hasReadonlyProps) && definition && context.output.override.preserveReadonlyRequestBodies !== "preserve" ? `NonReadonly<${definition}>` : definition;
|
|
3301
|
+
let implementation = generalJSTypesWithArray.includes(definition.toLowerCase()) || filteredBodyTypes.length > 1 ? camel(operationName) + context.output.override.components.requestBodies.suffix : camel(definition);
|
|
3302
|
+
let isOptional = false;
|
|
3303
|
+
if (implementation) {
|
|
3304
|
+
implementation = sanitize(implementation, {
|
|
3305
|
+
underscore: "_",
|
|
3306
|
+
whitespace: "_",
|
|
3307
|
+
dash: true,
|
|
3308
|
+
es5keyword: true,
|
|
3309
|
+
es5IdentifierName: true
|
|
2924
3310
|
});
|
|
3311
|
+
if (isReference(requestBody)) {
|
|
3312
|
+
const { schema: bodySchema } = resolveRef(requestBody, context);
|
|
3313
|
+
isOptional = bodySchema.required !== true;
|
|
3314
|
+
} else isOptional = requestBody.required !== true;
|
|
2925
3315
|
}
|
|
2926
3316
|
return {
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
examples: resolveExampleRefs(schema.examples, context)
|
|
3317
|
+
originalSchema: requestBody,
|
|
3318
|
+
definition: nonReadonlyDefinition,
|
|
3319
|
+
implementation,
|
|
3320
|
+
imports,
|
|
3321
|
+
schemas,
|
|
3322
|
+
isOptional,
|
|
3323
|
+
...filteredBodyTypes.length === 1 ? {
|
|
3324
|
+
formData: filteredBodyTypes[0].formData,
|
|
3325
|
+
formUrlEncoded: filteredBodyTypes[0].formUrlEncoded,
|
|
3326
|
+
contentType: filteredBodyTypes[0].contentType
|
|
3327
|
+
} : {
|
|
3328
|
+
formData: "",
|
|
3329
|
+
formUrlEncoded: "",
|
|
3330
|
+
contentType: ""
|
|
3331
|
+
}
|
|
2943
3332
|
};
|
|
2944
3333
|
}
|
|
3334
|
+
function getBody({ requestBody, operationName, context, contentType }) {
|
|
3335
|
+
return buildBody(filterByContentType(getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context), contentType), requestBody, operationName, context);
|
|
3336
|
+
}
|
|
3337
|
+
/**
|
|
3338
|
+
* Returns per-content-type bodies when `splitByContentType` is enabled.
|
|
3339
|
+
* Each entry includes a `contentTypeSuffix` for generating distinct function names.
|
|
3340
|
+
*/
|
|
3341
|
+
function getBodiesByContentType({ requestBody, operationName, context, contentType }) {
|
|
3342
|
+
const filteredBodyTypes = filterByContentType(getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context, void 0, (item) => `${item.value}::${item.contentType}`), contentType);
|
|
3343
|
+
if (filteredBodyTypes.length <= 1) return [{
|
|
3344
|
+
...buildBody(filteredBodyTypes, requestBody, operationName, context),
|
|
3345
|
+
contentTypeSuffix: ""
|
|
3346
|
+
}];
|
|
3347
|
+
return filteredBodyTypes.map((bodyType) => {
|
|
3348
|
+
const suffix = getContentTypeSuffix(bodyType.contentType);
|
|
3349
|
+
return {
|
|
3350
|
+
...buildBody([bodyType], requestBody, operationName, context),
|
|
3351
|
+
contentTypeSuffix: suffix
|
|
3352
|
+
};
|
|
3353
|
+
});
|
|
3354
|
+
}
|
|
3355
|
+
const CONTENT_TYPE_SUFFIX_MAP = {
|
|
3356
|
+
"application/json": "Json",
|
|
3357
|
+
"multipart/form-data": "FormData",
|
|
3358
|
+
"application/x-www-form-urlencoded": "UrlEncoded",
|
|
3359
|
+
"text/plain": "Text",
|
|
3360
|
+
"application/xml": "Xml",
|
|
3361
|
+
"text/xml": "Xml",
|
|
3362
|
+
"application/octet-stream": "Blob"
|
|
3363
|
+
};
|
|
3364
|
+
function getContentTypeSuffix(contentType) {
|
|
3365
|
+
if (CONTENT_TYPE_SUFFIX_MAP[contentType]) return CONTENT_TYPE_SUFFIX_MAP[contentType];
|
|
3366
|
+
return (contentType.split("/")[1] ?? contentType).split(/[-+.]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
3367
|
+
}
|
|
2945
3368
|
//#endregion
|
|
2946
3369
|
//#region src/getters/discriminators.ts
|
|
2947
3370
|
function resolveDiscriminators(schemas, context) {
|
|
@@ -2991,6 +3414,61 @@ function resolveDiscriminators(schemas, context) {
|
|
|
2991
3414
|
}
|
|
2992
3415
|
}
|
|
2993
3416
|
}
|
|
3417
|
+
for (const [parentName, parentSchema] of Object.entries(transformedSchemas)) {
|
|
3418
|
+
if (isBoolean$1(parentSchema)) continue;
|
|
3419
|
+
if (!parentSchema.oneOf || !parentSchema.discriminator?.mapping) continue;
|
|
3420
|
+
const { mapping, propertyName } = parentSchema.discriminator;
|
|
3421
|
+
if (!propertyName) continue;
|
|
3422
|
+
const parentProperties = parentSchema.properties;
|
|
3423
|
+
const parentRequired = parentSchema.required;
|
|
3424
|
+
const inheritableProps = {};
|
|
3425
|
+
if (parentProperties) {
|
|
3426
|
+
for (const [key, value] of Object.entries(parentProperties)) if (key !== propertyName) inheritableProps[key] = value;
|
|
3427
|
+
}
|
|
3428
|
+
const inheritableRequired = parentRequired?.filter((key) => key !== propertyName);
|
|
3429
|
+
const hasInheritableProps = Object.keys(inheritableProps).length > 0;
|
|
3430
|
+
for (const mappingValue of Object.values(mapping)) {
|
|
3431
|
+
let variantSchema;
|
|
3432
|
+
try {
|
|
3433
|
+
const { originalName } = getRefInfo(mappingValue, context);
|
|
3434
|
+
variantSchema = transformedSchemas[pascal(originalName)] ?? transformedSchemas[originalName];
|
|
3435
|
+
} catch {
|
|
3436
|
+
variantSchema = transformedSchemas[mappingValue];
|
|
3437
|
+
}
|
|
3438
|
+
if (!variantSchema || isBoolean$1(variantSchema)) continue;
|
|
3439
|
+
const variantAllOf = variantSchema.allOf;
|
|
3440
|
+
if (!variantAllOf) continue;
|
|
3441
|
+
const rewritten = [];
|
|
3442
|
+
for (const item of variantAllOf) {
|
|
3443
|
+
if (!isReference(item) || !item.$ref) {
|
|
3444
|
+
rewritten.push(item);
|
|
3445
|
+
continue;
|
|
3446
|
+
}
|
|
3447
|
+
let refOriginalName;
|
|
3448
|
+
try {
|
|
3449
|
+
refOriginalName = getRefInfo(item.$ref, context).originalName;
|
|
3450
|
+
} catch {
|
|
3451
|
+
refOriginalName = void 0;
|
|
3452
|
+
}
|
|
3453
|
+
if (!(refOriginalName === parentName || refOriginalName !== void 0 && pascal(refOriginalName) === pascal(parentName))) {
|
|
3454
|
+
rewritten.push(item);
|
|
3455
|
+
continue;
|
|
3456
|
+
}
|
|
3457
|
+
const inlinedParent = { ...parentSchema };
|
|
3458
|
+
delete inlinedParent.oneOf;
|
|
3459
|
+
delete inlinedParent.discriminator;
|
|
3460
|
+
delete inlinedParent.allOf;
|
|
3461
|
+
delete inlinedParent.anyOf;
|
|
3462
|
+
if (hasInheritableProps) inlinedParent.properties = { ...inheritableProps };
|
|
3463
|
+
else delete inlinedParent.properties;
|
|
3464
|
+
if (inheritableRequired && inheritableRequired.length > 0) inlinedParent.required = [...inheritableRequired];
|
|
3465
|
+
else delete inlinedParent.required;
|
|
3466
|
+
if (Object.keys(inlinedParent).filter((key) => key !== "type").length > 0) rewritten.push(inlinedParent);
|
|
3467
|
+
}
|
|
3468
|
+
if (rewritten.length === 0) delete variantSchema.allOf;
|
|
3469
|
+
else variantSchema.allOf = rewritten;
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
2994
3472
|
return transformedSchemas;
|
|
2995
3473
|
}
|
|
2996
3474
|
//#endregion
|
|
@@ -3243,7 +3721,8 @@ function getQueryParamsTypes(queryParams, operationName, context) {
|
|
|
3243
3721
|
};
|
|
3244
3722
|
if (resolvedValue.isEnum && !resolvedValue.isRef) {
|
|
3245
3723
|
const enumName = queryName;
|
|
3246
|
-
const
|
|
3724
|
+
const parameterAsSchema = parameter;
|
|
3725
|
+
const enumValue = getEnum(resolvedValue.value, enumName, getEnumNames(resolvedValue.originalSchema) ?? getEnumNames(parameterAsSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema) ?? getEnumDescriptions(parameterAsSchema), context.output.override.namingConvention.enum);
|
|
3247
3726
|
return {
|
|
3248
3727
|
name,
|
|
3249
3728
|
required,
|
|
@@ -3285,6 +3764,7 @@ function getQueryParams({ queryParams, operationName, context, suffix = "params"
|
|
|
3285
3764
|
},
|
|
3286
3765
|
deps: schemas,
|
|
3287
3766
|
isOptional: allOptional,
|
|
3767
|
+
paramNames: types.map(({ name }) => name),
|
|
3288
3768
|
requiredNullableKeys,
|
|
3289
3769
|
...nonPrimitiveKeys.length > 0 ? { nonPrimitiveKeys } : {}
|
|
3290
3770
|
};
|
|
@@ -3443,6 +3923,231 @@ function generateComponentDefinition(responses = {}, context, suffix) {
|
|
|
3443
3923
|
return generatorSchemas;
|
|
3444
3924
|
}
|
|
3445
3925
|
//#endregion
|
|
3926
|
+
//#region src/generators/factory.ts
|
|
3927
|
+
const circularRefCache = /* @__PURE__ */ new WeakMap();
|
|
3928
|
+
function getSchemasPath(context) {
|
|
3929
|
+
const { schemas, target } = context.output;
|
|
3930
|
+
if (schemas) return normalizeSafe(isString(schemas) ? schemas : schemas.path);
|
|
3931
|
+
const { dirname, filename } = getFileInfo(target);
|
|
3932
|
+
return joinSafe(dirname, filename + ".schemas");
|
|
3933
|
+
}
|
|
3934
|
+
function getSchemaImportPath(refName, context) {
|
|
3935
|
+
if (context.output.factoryMethods?.mode === "single") return;
|
|
3936
|
+
let outputDir = context.output.factoryMethods?.outputDirectory;
|
|
3937
|
+
let schemasPath = getSchemasPath(context);
|
|
3938
|
+
if (context.output.workspace) {
|
|
3939
|
+
if (outputDir && !isAbsolute(outputDir)) outputDir = resolve(context.output.workspace, outputDir);
|
|
3940
|
+
if (schemasPath && !isAbsolute(schemasPath)) schemasPath = resolve(context.output.workspace, schemasPath);
|
|
3941
|
+
}
|
|
3942
|
+
return joinSafe(outputDir ? relativeSafe(outputDir, schemasPath) : "./", conventionName(refName, context.output.namingConvention));
|
|
3943
|
+
}
|
|
3944
|
+
function isReference$1(schema) {
|
|
3945
|
+
return "$ref" in schema;
|
|
3946
|
+
}
|
|
3947
|
+
function getResolvedRef(schema, context) {
|
|
3948
|
+
return resolveRef(schema, context);
|
|
3949
|
+
}
|
|
3950
|
+
function getProperties(schema) {
|
|
3951
|
+
return schema.properties ?? {};
|
|
3952
|
+
}
|
|
3953
|
+
function getItems(schema) {
|
|
3954
|
+
return schema.items;
|
|
3955
|
+
}
|
|
3956
|
+
function getAdditionalProperties(schema) {
|
|
3957
|
+
return schema.additionalProperties;
|
|
3958
|
+
}
|
|
3959
|
+
function getSchemas(schemas) {
|
|
3960
|
+
return schemas;
|
|
3961
|
+
}
|
|
3962
|
+
function getExtendedProps(schema) {
|
|
3963
|
+
const extended = schema;
|
|
3964
|
+
return {
|
|
3965
|
+
constValue: extended.const,
|
|
3966
|
+
prefixItems: extended.prefixItems,
|
|
3967
|
+
minItems: extended.minItems
|
|
3968
|
+
};
|
|
3969
|
+
}
|
|
3970
|
+
function generateFactory(schema, name, context) {
|
|
3971
|
+
if (!canGenerateSchema(schema) || !context.output.factoryMethods) return void 0;
|
|
3972
|
+
const { functionNamePrefix, mode } = context.output.factoryMethods;
|
|
3973
|
+
const factoryName = `${functionNamePrefix}${pascal(name)}`;
|
|
3974
|
+
const imports = [];
|
|
3975
|
+
const payload = buildPayload(schema, context, [name], imports);
|
|
3976
|
+
if (mode !== "single") {
|
|
3977
|
+
const schemaImportPath = getSchemaImportPath(name, context);
|
|
3978
|
+
imports.push({
|
|
3979
|
+
name,
|
|
3980
|
+
importPath: schemaImportPath
|
|
3981
|
+
});
|
|
3982
|
+
}
|
|
3983
|
+
return {
|
|
3984
|
+
model: `export function ${factoryName}(): ${name} {\n return ${payload};\n}\n`,
|
|
3985
|
+
imports
|
|
3986
|
+
};
|
|
3987
|
+
}
|
|
3988
|
+
function canGenerateSchema(schema) {
|
|
3989
|
+
return schema.type === "object" || schema.type === "array" || !!schema.properties || !!schema.allOf || !!schema.oneOf || !!schema.anyOf || !!schema.items || !!schema.enum;
|
|
3990
|
+
}
|
|
3991
|
+
function hasCircularReference(target, sourceName, context, visited = /* @__PURE__ */ new Set()) {
|
|
3992
|
+
if (isReference$1(target)) {
|
|
3993
|
+
const { imports, schema } = getResolvedRef(target, context);
|
|
3994
|
+
const refName = imports[0]?.name;
|
|
3995
|
+
if (refName === sourceName) return true;
|
|
3996
|
+
if (refName && visited.has(refName)) return false;
|
|
3997
|
+
if (refName) visited.add(refName);
|
|
3998
|
+
let cache = circularRefCache.get(context);
|
|
3999
|
+
if (!cache) {
|
|
4000
|
+
cache = /* @__PURE__ */ new Map();
|
|
4001
|
+
circularRefCache.set(context, cache);
|
|
4002
|
+
}
|
|
4003
|
+
const cacheKey = refName ? `${sourceName}::${refName}` : void 0;
|
|
4004
|
+
if (cacheKey) {
|
|
4005
|
+
const cached = cache.get(cacheKey);
|
|
4006
|
+
if (cached !== void 0) return cached;
|
|
4007
|
+
}
|
|
4008
|
+
const result = hasCircularReference(schema, sourceName, context, visited);
|
|
4009
|
+
if (cacheKey) cache.set(cacheKey, result);
|
|
4010
|
+
return result;
|
|
4011
|
+
}
|
|
4012
|
+
const check = (schemas) => schemas?.some((s) => hasCircularReference(s, sourceName, context, visited)) ?? false;
|
|
4013
|
+
const items = getItems(target);
|
|
4014
|
+
const additionalProperties = getAdditionalProperties(target);
|
|
4015
|
+
return check(getSchemas(target.allOf)) || check(getSchemas(target.oneOf)) || check(getSchemas(target.anyOf)) || Object.values(getProperties(target)).some((s) => hasCircularReference(s, sourceName, context, visited)) || !!items && hasCircularReference(items, sourceName, context, visited) || typeof additionalProperties === "object" && hasCircularReference(additionalProperties, sourceName, context, visited);
|
|
4016
|
+
}
|
|
4017
|
+
function buildPayload(target, context, parents, imports) {
|
|
4018
|
+
if (isReference$1(target)) return buildRefPayload(target, context, parents, imports);
|
|
4019
|
+
const schema = target;
|
|
4020
|
+
if (schema.allOf) return buildAllOfPayload(getSchemas(schema.allOf) ?? [], context, parents, imports);
|
|
4021
|
+
if (schema.oneOf) return buildFirstOfPayload(getSchemas(schema.oneOf) ?? [], context, parents, imports);
|
|
4022
|
+
if (schema.anyOf) return buildFirstOfPayload(getSchemas(schema.anyOf) ?? [], context, parents, imports);
|
|
4023
|
+
const { constValue } = getExtendedProps(schema);
|
|
4024
|
+
if (constValue !== void 0) return formatValue(constValue);
|
|
4025
|
+
if (schema.default !== void 0) return buildDefaultPayload(schema, context);
|
|
4026
|
+
const schemaType = inferSchemaType(schema);
|
|
4027
|
+
if (schemaType === "object" || schema.properties) return buildObjectPayload(schema, context, parents, imports);
|
|
4028
|
+
if (schemaType === "array") return buildArrayPayload(schema, context, parents, imports);
|
|
4029
|
+
return buildPrimitivePayload(schema, schemaType, context);
|
|
4030
|
+
}
|
|
4031
|
+
function buildRefPayload(schema, context, parents, imports) {
|
|
4032
|
+
const { schema: resolved, imports: refImports } = getResolvedRef(schema, context);
|
|
4033
|
+
const refName = refImports[0]?.name;
|
|
4034
|
+
if (!refName) return "{}";
|
|
4035
|
+
if (parents.includes(refName) || hasCircularReference(resolved, parents[0], context)) {
|
|
4036
|
+
imports.push({
|
|
4037
|
+
name: refName,
|
|
4038
|
+
importPath: getSchemaImportPath(refName, context)
|
|
4039
|
+
});
|
|
4040
|
+
return `{} as ${refName}`;
|
|
4041
|
+
}
|
|
4042
|
+
const { functionNamePrefix = "create", mode = "single" } = context.output.factoryMethods ?? {};
|
|
4043
|
+
const refFactoryName = `${functionNamePrefix}${pascal(refName)}`;
|
|
4044
|
+
if (mode !== "single-split") {
|
|
4045
|
+
const importPath = resolveImportPath(mode, refName, context);
|
|
4046
|
+
imports.push({
|
|
4047
|
+
name: refFactoryName,
|
|
4048
|
+
importPath,
|
|
4049
|
+
isConstant: true
|
|
4050
|
+
});
|
|
4051
|
+
}
|
|
4052
|
+
imports.push({
|
|
4053
|
+
name: refName,
|
|
4054
|
+
importPath: getSchemaImportPath(refName, context)
|
|
4055
|
+
});
|
|
4056
|
+
return `${refFactoryName}()`;
|
|
4057
|
+
}
|
|
4058
|
+
function resolveImportPath(mode, refName, context) {
|
|
4059
|
+
const baseName = conventionName(refName, context.output.namingConvention);
|
|
4060
|
+
switch (mode) {
|
|
4061
|
+
case "split": return `./${baseName}.factory`;
|
|
4062
|
+
case "single-split": return `./${conventionName("factoryMethods", context.output.namingConvention)}`;
|
|
4063
|
+
case "single": return `./${baseName}`;
|
|
4064
|
+
}
|
|
4065
|
+
}
|
|
4066
|
+
function buildAllOfPayload(allOf, context, parents, imports) {
|
|
4067
|
+
const payloads = allOf.map((s) => buildPayload(s, context, parents, imports));
|
|
4068
|
+
return payloads.length > 0 ? `Object.assign({}, ${payloads.join(", ")})` : "{}";
|
|
4069
|
+
}
|
|
4070
|
+
function buildFirstOfPayload(schemas, context, parents, imports) {
|
|
4071
|
+
const first = schemas[0];
|
|
4072
|
+
return first ? buildPayload(first, context, parents, imports) : "{}";
|
|
4073
|
+
}
|
|
4074
|
+
function buildObjectPayload(schema, context, parents, imports) {
|
|
4075
|
+
const { includeOptionalProperty = false } = context.output.factoryMethods ?? {};
|
|
4076
|
+
const props = getProperties(schema);
|
|
4077
|
+
const requiredProps = schema.required ?? [];
|
|
4078
|
+
const entries = Object.entries(props);
|
|
4079
|
+
if (context.output.propertySortOrder === PropertySortOrder.ALPHABETICAL) entries.sort(([a], [b]) => a.localeCompare(b));
|
|
4080
|
+
const includeOptional = includeOptionalProperty;
|
|
4081
|
+
const lines = [];
|
|
4082
|
+
for (const [key, prop] of entries) {
|
|
4083
|
+
const isRequired = requiredProps.includes(key);
|
|
4084
|
+
const resolved = isReference$1(prop) ? getResolvedRef(prop, context).schema : prop;
|
|
4085
|
+
const isReadOnly = !!prop.readOnly || !!resolved.readOnly;
|
|
4086
|
+
const isWriteOnly = !!prop.writeOnly || !!resolved.writeOnly;
|
|
4087
|
+
if (!isRequired) {
|
|
4088
|
+
if (isReadOnly) continue;
|
|
4089
|
+
if (!isWriteOnly && !includeOptional) continue;
|
|
4090
|
+
}
|
|
4091
|
+
const payload = buildPayload(prop, context, parents, imports);
|
|
4092
|
+
const safeKey = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? key : JSON.stringify(key);
|
|
4093
|
+
lines.push(`${safeKey}: ${payload}`);
|
|
4094
|
+
}
|
|
4095
|
+
return `{\n ${lines.join(",\n ")}\n }`;
|
|
4096
|
+
}
|
|
4097
|
+
function buildArrayPayload(schema, context, parents, imports) {
|
|
4098
|
+
const { prefixItems, minItems } = getExtendedProps(schema);
|
|
4099
|
+
const items = getItems(schema);
|
|
4100
|
+
if (prefixItems && prefixItems.length > 0) return `[${prefixItems.map((item) => buildPayload(item, context, parents, imports)).join(", ")}]`;
|
|
4101
|
+
if (minItems && items) {
|
|
4102
|
+
const MAX_MIN_ITEMS = 50;
|
|
4103
|
+
if (minItems > MAX_MIN_ITEMS) logWarning(`Warning: minItems is ${minItems}, capping at ${MAX_MIN_ITEMS} to prevent massive payload.`);
|
|
4104
|
+
const count = Math.min(minItems, MAX_MIN_ITEMS);
|
|
4105
|
+
const itemPayload = buildPayload(items, context, parents, imports);
|
|
4106
|
+
return `[${Array.from({ length: count }).fill(itemPayload).join(", ")}]`;
|
|
4107
|
+
}
|
|
4108
|
+
return "[]";
|
|
4109
|
+
}
|
|
4110
|
+
function inferSchemaType(schema) {
|
|
4111
|
+
let type = schema.type;
|
|
4112
|
+
if (Array.isArray(type)) {
|
|
4113
|
+
const nonNull = type.filter((t) => t !== "null");
|
|
4114
|
+
type = nonNull.length > 0 ? nonNull[0] : "null";
|
|
4115
|
+
}
|
|
4116
|
+
if (!type && schema.items) return "array";
|
|
4117
|
+
if (!type && schema.enum) {
|
|
4118
|
+
const first = schema.enum[0];
|
|
4119
|
+
if (typeof first === "number") return "number";
|
|
4120
|
+
if (typeof first === "boolean") return "boolean";
|
|
4121
|
+
return "string";
|
|
4122
|
+
}
|
|
4123
|
+
return type;
|
|
4124
|
+
}
|
|
4125
|
+
function buildDefaultPayload(schema, context) {
|
|
4126
|
+
if (context.output.override.useDates && typeof schema.default === "string" && (schema.format === "date" || schema.format === "date-time")) return `new Date('${schema.default}')`;
|
|
4127
|
+
return formatValue(schema.default);
|
|
4128
|
+
}
|
|
4129
|
+
function buildPrimitivePayload(schema, schemaType, context) {
|
|
4130
|
+
if (schemaType === "null") return "null";
|
|
4131
|
+
const enumValues = schema.enum;
|
|
4132
|
+
if (schemaType === "boolean") return enumValues && enumValues.length > 0 ? String(enumValues[0]) : "false";
|
|
4133
|
+
if (schemaType === "number" || schemaType === "integer") return enumValues && enumValues.length > 0 ? String(enumValues[0]) : "0";
|
|
4134
|
+
if (schemaType === "string") {
|
|
4135
|
+
if (enumValues && enumValues.length > 0) {
|
|
4136
|
+
const first = enumValues[0];
|
|
4137
|
+
return typeof first === "string" ? JSON.stringify(first) : String(first);
|
|
4138
|
+
}
|
|
4139
|
+
if (schema.format === "date" || schema.format === "date-time") return context.output.override.useDates ? "new Date(0)" : `'${(/* @__PURE__ */ new Date(0)).toISOString()}'`;
|
|
4140
|
+
return "''";
|
|
4141
|
+
}
|
|
4142
|
+
return "undefined as unknown";
|
|
4143
|
+
}
|
|
4144
|
+
function formatValue(val) {
|
|
4145
|
+
if (val === null) return "null";
|
|
4146
|
+
if (typeof val === "string") return JSON.stringify(val);
|
|
4147
|
+
if (typeof val === "object") return JSON.stringify(val);
|
|
4148
|
+
return String(val);
|
|
4149
|
+
}
|
|
4150
|
+
//#endregion
|
|
3446
4151
|
//#region src/generators/imports.ts
|
|
3447
4152
|
function generateImports({ imports, namingConvention = NamingConvention.CAMEL_CASE, importExtension = "" }) {
|
|
3448
4153
|
if (imports.length === 0) return "";
|
|
@@ -4133,7 +4838,7 @@ function generateParameterDefinition(parameters = {}, context, suffix) {
|
|
|
4133
4838
|
* @param name interface name
|
|
4134
4839
|
* @param schema
|
|
4135
4840
|
*/
|
|
4136
|
-
function generateInterface({ name, schema, context }) {
|
|
4841
|
+
function generateInterface({ name, schema, context, genericParams }) {
|
|
4137
4842
|
const scalar = getScalar({
|
|
4138
4843
|
item: schema,
|
|
4139
4844
|
name,
|
|
@@ -4141,6 +4846,7 @@ function generateInterface({ name, schema, context }) {
|
|
|
4141
4846
|
});
|
|
4142
4847
|
const isEmptyObject = scalar.value === "{}";
|
|
4143
4848
|
const shouldUseTypeAlias = context.output.override.useTypeOverInterfaces ?? scalar.useTypeAlias;
|
|
4849
|
+
const genericSuffix = genericParams && genericParams.length > 0 ? `<${genericParams.join(", ")}>` : "";
|
|
4144
4850
|
let model = "";
|
|
4145
4851
|
model += jsDoc(schema);
|
|
4146
4852
|
if (isEmptyObject) model += "// eslint-disable-next-line @typescript-eslint/no-empty-interface\n";
|
|
@@ -4148,12 +4854,12 @@ function generateInterface({ name, schema, context }) {
|
|
|
4148
4854
|
const properties = schema.properties;
|
|
4149
4855
|
if (properties && Object.values(properties).length > 0 && Object.values(properties).every((item) => "const" in item)) {
|
|
4150
4856
|
const mappedScalarValue = scalar.value.replaceAll(";", ",").replaceAll("?:", ":");
|
|
4151
|
-
model += `export const ${name}Value = ${mappedScalarValue} as const;\nexport type ${name} = typeof ${name}Value;\n`;
|
|
4857
|
+
model += `export const ${name}Value = ${mappedScalarValue} as const;\nexport type ${name}${genericSuffix} = typeof ${name}Value;\n`;
|
|
4152
4858
|
} else {
|
|
4153
4859
|
const blankInterfaceValue = scalar.value === "unknown" ? "{}" : scalar.value;
|
|
4154
|
-
model += `export interface ${name} ${blankInterfaceValue}\n`;
|
|
4860
|
+
model += `export interface ${name}${genericSuffix} ${blankInterfaceValue}\n`;
|
|
4155
4861
|
}
|
|
4156
|
-
} else model += `export type ${name} = ${scalar.value};\n`;
|
|
4862
|
+
} else model += `export type ${name}${genericSuffix} = ${scalar.value};\n`;
|
|
4157
4863
|
const externalModulesImportsOnly = scalar.imports.filter((importName) => importName.alias ? importName.alias !== name : importName.name !== name);
|
|
4158
4864
|
return [...scalar.schemas, {
|
|
4159
4865
|
name,
|
|
@@ -4187,6 +4893,17 @@ function generateSchemasDefinition(schemas = {}, context, suffix, filters) {
|
|
|
4187
4893
|
const normalizedName = conventionName(schema.name, context.output.namingConvention);
|
|
4188
4894
|
if (!seenNames.has(normalizedName)) {
|
|
4189
4895
|
seenNames.add(normalizedName);
|
|
4896
|
+
if (context.output.factoryMethods && schema.schema) {
|
|
4897
|
+
const factoryData = generateFactory(schema.schema, schema.name, context);
|
|
4898
|
+
if (factoryData) if (context.output.factoryMethods.mode === "single") {
|
|
4899
|
+
schema.model += `\n${factoryData.model}`;
|
|
4900
|
+
for (const imp of factoryData.imports) if (!schema.imports.some((existing) => existing.name === imp.name)) schema.imports.push(imp);
|
|
4901
|
+
} else {
|
|
4902
|
+
schema.factory = factoryData.model;
|
|
4903
|
+
schema.factoryImports = factoryData.imports;
|
|
4904
|
+
schema.factoryMode = context.output.factoryMethods.mode;
|
|
4905
|
+
}
|
|
4906
|
+
}
|
|
4190
4907
|
deduplicatedModels.push(schema);
|
|
4191
4908
|
}
|
|
4192
4909
|
}
|
|
@@ -4231,6 +4948,21 @@ function shouldCreateInterface(schema) {
|
|
|
4231
4948
|
const isNullable = isArray(schema.type) && schema.type.includes("null");
|
|
4232
4949
|
return (!schema.type || schema.type === "object") && !schema.allOf && !schema.oneOf && !schema.anyOf && isDereferenced(schema) && !schema.enum && !isNullable;
|
|
4233
4950
|
}
|
|
4951
|
+
function collectGenericParams(schema) {
|
|
4952
|
+
const defs = schema.$defs;
|
|
4953
|
+
if (!defs || typeof defs !== "object") return [];
|
|
4954
|
+
const anchors = [];
|
|
4955
|
+
for (const defSchema of Object.values(defs)) {
|
|
4956
|
+
if (!defSchema || typeof defSchema !== "object") continue;
|
|
4957
|
+
const rec = defSchema;
|
|
4958
|
+
if (rec.$dynamicAnchor !== void 0 && rec.$ref === void 0) anchors.push(rec.$dynamicAnchor);
|
|
4959
|
+
}
|
|
4960
|
+
const uniqueNames = dynamicAnchorsToUniqueParamNames(anchors);
|
|
4961
|
+
return anchors.map((anchor) => ({
|
|
4962
|
+
anchorName: anchor,
|
|
4963
|
+
paramName: uniqueNames.get(anchor) ?? dynamicAnchorToParamName(anchor)
|
|
4964
|
+
}));
|
|
4965
|
+
}
|
|
4234
4966
|
function generateSchemaDefinitions(schemaName, schema, context, suffix) {
|
|
4235
4967
|
const sanitizedSchemaName = sanitize(`${pascal(schemaName)}${suffix}`, {
|
|
4236
4968
|
underscore: "_",
|
|
@@ -4245,22 +4977,82 @@ function generateSchemaDefinitions(schemaName, schema, context, suffix) {
|
|
|
4245
4977
|
imports: [],
|
|
4246
4978
|
schema
|
|
4247
4979
|
}];
|
|
4980
|
+
const alias = extractBoundAliasInfo(schema, context);
|
|
4981
|
+
if (alias) {
|
|
4982
|
+
const genericParams = alias.genericParams.map((paramName) => ({
|
|
4983
|
+
anchorName: paramName,
|
|
4984
|
+
paramName
|
|
4985
|
+
}));
|
|
4986
|
+
const genericSuffix = genericParams.length > 0 ? `<${genericParams.map((p) => p.paramName).join(", ")}>` : "";
|
|
4987
|
+
const typeArgsStr = alias.typeArgs.join(", ");
|
|
4988
|
+
const genericPart = `${alias.genericName}<${typeArgsStr}>`;
|
|
4989
|
+
const schemaType = schema.type;
|
|
4990
|
+
const nullable = Array.isArray(schemaType) && schemaType.includes("null") || schema.nullable === true ? " | null" : "";
|
|
4991
|
+
let model;
|
|
4992
|
+
const allImports = [{
|
|
4993
|
+
name: alias.genericName,
|
|
4994
|
+
schemaName: alias.genericName
|
|
4995
|
+
}, ...alias.imports];
|
|
4996
|
+
if (alias.extraSchemas && alias.extraSchemas.length > 0) {
|
|
4997
|
+
const aliasScopedContext = {
|
|
4998
|
+
...context,
|
|
4999
|
+
dynamicScope: buildDynamicScope(schemaName, schema, context)
|
|
5000
|
+
};
|
|
5001
|
+
const subSchemas = [];
|
|
5002
|
+
model = `export type ${sanitizedSchemaName}${genericSuffix} = (${[genericPart, ...alias.extraSchemas.map((extraSchema) => {
|
|
5003
|
+
const resolved = resolveValue({
|
|
5004
|
+
schema: extraSchema,
|
|
5005
|
+
name: sanitizedSchemaName,
|
|
5006
|
+
context: aliasScopedContext
|
|
5007
|
+
});
|
|
5008
|
+
for (const imp of resolved.imports) {
|
|
5009
|
+
const impSchemaName = imp.schemaName ?? imp.name;
|
|
5010
|
+
if (!allImports.some((a) => a.name === imp.name && a.schemaName === impSchemaName)) allImports.push({
|
|
5011
|
+
name: imp.name,
|
|
5012
|
+
schemaName: impSchemaName
|
|
5013
|
+
});
|
|
5014
|
+
}
|
|
5015
|
+
for (const sub of resolved.schemas) if (sub.name !== sanitizedSchemaName) subSchemas.push(sub);
|
|
5016
|
+
return resolved.value;
|
|
5017
|
+
})].join(" & ")})${nullable};\n`;
|
|
5018
|
+
return [...subSchemas, {
|
|
5019
|
+
name: sanitizedSchemaName,
|
|
5020
|
+
model,
|
|
5021
|
+
imports: allImports,
|
|
5022
|
+
dependencies: allImports.map((i) => i.name),
|
|
5023
|
+
schema
|
|
5024
|
+
}];
|
|
5025
|
+
} else model = `export type ${sanitizedSchemaName}${genericSuffix} = ${genericPart}${nullable};\n`;
|
|
5026
|
+
return [{
|
|
5027
|
+
name: sanitizedSchemaName,
|
|
5028
|
+
model,
|
|
5029
|
+
imports: allImports,
|
|
5030
|
+
dependencies: allImports.map((i) => i.name),
|
|
5031
|
+
schema
|
|
5032
|
+
}];
|
|
5033
|
+
}
|
|
5034
|
+
const scopedContext = isBoolean(schema) ? context : {
|
|
5035
|
+
...context,
|
|
5036
|
+
dynamicScope: buildDynamicScope(schemaName, schema, context)
|
|
5037
|
+
};
|
|
5038
|
+
const genericParams = collectGenericParams(schema);
|
|
4248
5039
|
if (shouldCreateInterface(schema)) return generateInterface({
|
|
4249
5040
|
name: sanitizedSchemaName,
|
|
4250
5041
|
schema,
|
|
4251
|
-
context
|
|
5042
|
+
context: scopedContext,
|
|
5043
|
+
genericParams: genericParams.length > 0 ? genericParams.map((p) => p.paramName) : void 0
|
|
4252
5044
|
});
|
|
4253
5045
|
const resolvedValue = resolveValue({
|
|
4254
5046
|
schema,
|
|
4255
5047
|
name: sanitizedSchemaName,
|
|
4256
|
-
context
|
|
5048
|
+
context: scopedContext
|
|
4257
5049
|
});
|
|
4258
5050
|
let output = "";
|
|
4259
5051
|
let imports = resolvedValue.imports;
|
|
4260
5052
|
output += jsDoc(schema);
|
|
4261
5053
|
if (resolvedValue.isEnum && !resolvedValue.isRef) output += getEnum(resolvedValue.value, sanitizedSchemaName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention.enum);
|
|
4262
5054
|
else if (sanitizedSchemaName === resolvedValue.value && resolvedValue.isRef) {
|
|
4263
|
-
const { schema: referredSchema } = resolveRef(schema,
|
|
5055
|
+
const { schema: referredSchema } = resolveRef(schema, scopedContext);
|
|
4264
5056
|
if (!shouldCreateInterface(referredSchema)) {
|
|
4265
5057
|
const imp = resolvedValue.imports.find((imp) => imp.name === sanitizedSchemaName);
|
|
4266
5058
|
if (imp) {
|
|
@@ -4281,7 +5073,8 @@ function generateSchemaDefinitions(schemaName, schema, context, suffix) {
|
|
|
4281
5073
|
resolvedValue.dependencies.push(...schema.dependencies ?? []);
|
|
4282
5074
|
return false;
|
|
4283
5075
|
});
|
|
4284
|
-
|
|
5076
|
+
const genericSuffix = genericParams.length > 0 ? `<${genericParams.map((p) => p.paramName).join(", ")}>` : "";
|
|
5077
|
+
output += `export type ${sanitizedSchemaName}${genericSuffix} = ${resolvedValue.value};\n`;
|
|
4285
5078
|
}
|
|
4286
5079
|
return [...resolvedValue.schemas, {
|
|
4287
5080
|
name: sanitizedSchemaName,
|
|
@@ -4593,33 +5386,54 @@ function getCanonicalMap(schemaGroups, schemaPath, namingConvention, fileExtensi
|
|
|
4593
5386
|
canonicalNameMap
|
|
4594
5387
|
};
|
|
4595
5388
|
}
|
|
4596
|
-
function normalizeCanonicalImportPaths(schemas, canonicalPathMap, canonicalNameMap, schemaPath, namingConvention, fileExtension, tsconfig) {
|
|
5389
|
+
function normalizeCanonicalImportPaths(schemas, canonicalPathMap, canonicalNameMap, schemaPath, namingConvention, fileExtension, tsconfig, factoryOutputDirectory) {
|
|
4597
5390
|
const importExtension = getImportExtension(fileExtension, tsconfig);
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
5391
|
+
const factoryDir = factoryOutputDirectory ?? schemaPath;
|
|
5392
|
+
for (const schema of schemas) {
|
|
5393
|
+
schema.imports = schema.imports.map((imp) => {
|
|
5394
|
+
const canonicalByName = canonicalNameMap.get(imp.name);
|
|
5395
|
+
const resolvedImportKey = resolveImportKey(schemaPath, imp.importPath ?? `./${conventionName(imp.name, namingConvention)}`, fileExtension);
|
|
5396
|
+
const canonicalByPath = canonicalPathMap.get(resolvedImportKey);
|
|
5397
|
+
const canonical = canonicalByName ?? canonicalByPath;
|
|
5398
|
+
if (!canonical?.importPath) return imp;
|
|
5399
|
+
const relative = relativeSafe(schemaPath, canonical.importPath.replaceAll("\\", "/"));
|
|
5400
|
+
const importPath = `${relative.endsWith(fileExtension) ? relative.slice(0, -fileExtension.length) : relative.replace(/\.ts$/, "")}${importExtension}`;
|
|
5401
|
+
return {
|
|
5402
|
+
...imp,
|
|
5403
|
+
importPath
|
|
5404
|
+
};
|
|
5405
|
+
});
|
|
5406
|
+
if (schema.factoryImports) schema.factoryImports = schema.factoryImports.map((imp) => {
|
|
5407
|
+
const canonicalByName = canonicalNameMap.get(imp.name);
|
|
5408
|
+
const resolvedImportKey = resolveImportKey(factoryDir, imp.importPath ?? `./${conventionName(imp.name, namingConvention)}`, fileExtension);
|
|
5409
|
+
const canonicalByPath = canonicalPathMap.get(resolvedImportKey);
|
|
5410
|
+
const canonical = canonicalByName ?? canonicalByPath;
|
|
5411
|
+
if (!canonical?.importPath) return imp;
|
|
5412
|
+
const relative = relativeSafe(factoryDir, canonical.importPath.replaceAll("\\", "/"));
|
|
5413
|
+
const importPath = `${relative.endsWith(fileExtension) ? relative.slice(0, -fileExtension.length) : relative.replace(/\.ts$/, "")}${importExtension}`;
|
|
5414
|
+
return {
|
|
5415
|
+
...imp,
|
|
5416
|
+
importPath
|
|
5417
|
+
};
|
|
5418
|
+
});
|
|
5419
|
+
}
|
|
4611
5420
|
}
|
|
4612
5421
|
function mergeSchemaGroup(schemas) {
|
|
4613
5422
|
const baseSchemaName = schemas[0].name;
|
|
4614
5423
|
const baseSchema = schemas[0].schema;
|
|
4615
5424
|
const mergedImports = [...new Map(schemas.flatMap((schema) => schema.imports).map((imp) => [JSON.stringify(imp), imp])).values()];
|
|
4616
5425
|
const mergedDependencies = [...new Set(schemas.flatMap((schema) => schema.dependencies ?? []))];
|
|
5426
|
+
const mergedFactory = schemas.map((s) => s.factory).filter(Boolean).join("\n");
|
|
5427
|
+
const mergedFactoryImports = [...new Map(schemas.flatMap((schema) => schema.factoryImports ?? []).map((imp) => [JSON.stringify(imp), imp])).values()];
|
|
4617
5428
|
return {
|
|
4618
5429
|
name: baseSchemaName,
|
|
4619
5430
|
schema: baseSchema,
|
|
4620
5431
|
model: schemas.map((schema) => schema.model).join("\n"),
|
|
4621
5432
|
imports: mergedImports,
|
|
4622
|
-
dependencies: mergedDependencies
|
|
5433
|
+
dependencies: mergedDependencies,
|
|
5434
|
+
factory: mergedFactory || void 0,
|
|
5435
|
+
factoryImports: mergedFactoryImports,
|
|
5436
|
+
factoryMode: schemas[0].factoryMode
|
|
4623
5437
|
};
|
|
4624
5438
|
}
|
|
4625
5439
|
function resolveImportKey(schemaPath, importPath, fileExtension) {
|
|
@@ -4661,10 +5475,39 @@ async function writeSchema({ path, schema, target, namingConvention, fileExtensi
|
|
|
4661
5475
|
throw new Error(`Oups... 🍻. An Error occurred while writing schema ${name} => ${String(error)}`, { cause: error });
|
|
4662
5476
|
}
|
|
4663
5477
|
}
|
|
4664
|
-
async function
|
|
5478
|
+
async function emitFactoryForSchema(schema, namingConvention, header, factoryDir, fileExtension, helpers) {
|
|
5479
|
+
if (schema.factory && schema.factoryMode) {
|
|
5480
|
+
const mode = schema.factoryMode;
|
|
5481
|
+
if (mode === "split") {
|
|
5482
|
+
const factoryName = `${conventionName(schema.name, namingConvention)}.factory`;
|
|
5483
|
+
helpers.separateFactoryNames.push(factoryName);
|
|
5484
|
+
const factoryFile = `${header}\n${generateImports({
|
|
5485
|
+
imports: schema.factoryImports ?? [],
|
|
5486
|
+
namingConvention
|
|
5487
|
+
})}\n\n${schema.factory}`;
|
|
5488
|
+
await writeGeneratedFile(getPath(factoryDir, factoryName, fileExtension), factoryFile);
|
|
5489
|
+
} else if (mode === "single-split") {
|
|
5490
|
+
helpers.isCombined.value = true;
|
|
5491
|
+
helpers.combinedFactoryContent.value += `${schema.factory}\n`;
|
|
5492
|
+
helpers.combinedFactoryImports.push(...schema.factoryImports ?? []);
|
|
5493
|
+
}
|
|
5494
|
+
}
|
|
5495
|
+
}
|
|
5496
|
+
async function writeSchemas({ schemaPath, schemas, target, namingConvention, fileExtension, header, indexFiles, tsconfig, factoryOutputDirectory }) {
|
|
4665
5497
|
const schemaGroups = getSchemaGroups(schemaPath, schemas, namingConvention, fileExtension);
|
|
4666
5498
|
const { canonicalPathMap, canonicalNameMap } = getCanonicalMap(schemaGroups, schemaPath, namingConvention, fileExtension);
|
|
4667
|
-
normalizeCanonicalImportPaths(schemas, canonicalPathMap, canonicalNameMap, schemaPath, namingConvention, fileExtension, tsconfig);
|
|
5499
|
+
normalizeCanonicalImportPaths(schemas, canonicalPathMap, canonicalNameMap, schemaPath, namingConvention, fileExtension, tsconfig, factoryOutputDirectory);
|
|
5500
|
+
const factoryDir = factoryOutputDirectory ?? schemaPath;
|
|
5501
|
+
const combinedFactoryContent = { value: "" };
|
|
5502
|
+
const combinedFactoryImports = [];
|
|
5503
|
+
const isCombined = { value: false };
|
|
5504
|
+
const separateFactoryNames = [];
|
|
5505
|
+
const factoryHelpers = {
|
|
5506
|
+
separateFactoryNames,
|
|
5507
|
+
combinedFactoryContent,
|
|
5508
|
+
combinedFactoryImports,
|
|
5509
|
+
isCombined
|
|
5510
|
+
};
|
|
4668
5511
|
for (const groupSchemas of Object.values(schemaGroups)) {
|
|
4669
5512
|
if (groupSchemas.length === 1) {
|
|
4670
5513
|
await writeSchema({
|
|
@@ -4676,17 +5519,29 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
4676
5519
|
header,
|
|
4677
5520
|
tsconfig
|
|
4678
5521
|
});
|
|
5522
|
+
const singleSchema = groupSchemas[0];
|
|
5523
|
+
await emitFactoryForSchema(singleSchema, namingConvention, header, factoryDir, fileExtension, factoryHelpers);
|
|
4679
5524
|
continue;
|
|
4680
5525
|
}
|
|
5526
|
+
const mergedSchema = mergeSchemaGroup(groupSchemas);
|
|
4681
5527
|
await writeSchema({
|
|
4682
5528
|
path: schemaPath,
|
|
4683
|
-
schema:
|
|
5529
|
+
schema: mergedSchema,
|
|
4684
5530
|
target,
|
|
4685
5531
|
namingConvention,
|
|
4686
5532
|
fileExtension,
|
|
4687
5533
|
header,
|
|
4688
5534
|
tsconfig
|
|
4689
5535
|
});
|
|
5536
|
+
await emitFactoryForSchema(mergedSchema, namingConvention, header, factoryDir, fileExtension, factoryHelpers);
|
|
5537
|
+
}
|
|
5538
|
+
if (isCombined.value) {
|
|
5539
|
+
const factoryFileName = conventionName("factoryMethods", namingConvention);
|
|
5540
|
+
const factoryFile = `${header}\n${generateImports({
|
|
5541
|
+
imports: combinedFactoryImports,
|
|
5542
|
+
namingConvention
|
|
5543
|
+
})}\n\n${combinedFactoryContent.value}`;
|
|
5544
|
+
await writeGeneratedFile(getPath(factoryDir, factoryFileName, fileExtension), factoryFile);
|
|
4690
5545
|
}
|
|
4691
5546
|
if (indexFiles) {
|
|
4692
5547
|
const schemaFilePath = nodePath.join(schemaPath, `index.ts`);
|
|
@@ -4694,7 +5549,25 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
4694
5549
|
const ext = getImportExtension(fileExtension, tsconfig);
|
|
4695
5550
|
const conventionNamesSet = new Set(Object.values(schemaGroups).map((group) => conventionName(group[0].name, namingConvention)));
|
|
4696
5551
|
try {
|
|
4697
|
-
|
|
5552
|
+
const currentExports = [...conventionNamesSet].map((schemaName) => `export * from './${schemaName}${ext}';`);
|
|
5553
|
+
if (factoryOutputDirectory && normalizeSafe(factoryOutputDirectory) !== normalizeSafe(schemaPath) && (isCombined.value || separateFactoryNames.length > 0)) {
|
|
5554
|
+
const factoryIndexFilePath = nodePath.join(factoryOutputDirectory, `index.ts`);
|
|
5555
|
+
await fs$1.ensureFile(factoryIndexFilePath);
|
|
5556
|
+
const factoryExports = [];
|
|
5557
|
+
if (isCombined.value) {
|
|
5558
|
+
const factoryFileName = conventionName("factoryMethods", namingConvention);
|
|
5559
|
+
factoryExports.push(`export * from './${factoryFileName}${ext}';`);
|
|
5560
|
+
}
|
|
5561
|
+
for (const fName of separateFactoryNames) factoryExports.push(`export * from './${fName}${ext}';`);
|
|
5562
|
+
await writeGeneratedFile(factoryIndexFilePath, `${header}\n${factoryExports.join("\n")}\n`);
|
|
5563
|
+
} else {
|
|
5564
|
+
if (isCombined.value) {
|
|
5565
|
+
const factoryFileName = conventionName("factoryMethods", namingConvention);
|
|
5566
|
+
currentExports.push(`export * from './${factoryFileName}${ext}';`);
|
|
5567
|
+
}
|
|
5568
|
+
for (const fName of separateFactoryNames) currentExports.push(`export * from './${fName}${ext}';`);
|
|
5569
|
+
}
|
|
5570
|
+
await writeGeneratedFile(schemaFilePath, `${header}\n${[...new Set(currentExports)].toSorted((a, b) => a.localeCompare(b, "en", { numeric: true })).join("\n")}\n`);
|
|
4698
5571
|
} catch (error) {
|
|
4699
5572
|
throw new Error(`Oups... 🍻. An Error occurred while writing schema index file ${schemaFilePath} => ${String(error)}`, { cause: error });
|
|
4700
5573
|
}
|
|
@@ -4704,6 +5577,13 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
4704
5577
|
//#region src/writers/generate-imports-for-builder.ts
|
|
4705
5578
|
function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
4706
5579
|
const isZodSchemaOutput = isObject(output.schemas) && output.schemas.type === "zod";
|
|
5580
|
+
const schemaFactoryImports = imports.filter((i) => i.schemaFactory);
|
|
5581
|
+
const schemaFactoryImportExtension = getImportExtension(output.fileExtension, output.tsconfig);
|
|
5582
|
+
const schemaFactoryDeps = schemaFactoryImports.length > 0 ? [{
|
|
5583
|
+
exports: uniqueBy(schemaFactoryImports, (entry) => `${entry.name}|${entry.alias ?? ""}`),
|
|
5584
|
+
dependency: joinSafe(relativeSchemasPath, `index.faker${schemaFactoryImportExtension}`)
|
|
5585
|
+
}] : [];
|
|
5586
|
+
imports = imports.filter((i) => !i.schemaFactory);
|
|
4707
5587
|
let schemaImports;
|
|
4708
5588
|
if (output.indexFiles) schemaImports = isZodSchemaOutput ? [{
|
|
4709
5589
|
exports: imports.filter((i) => !i.importPath),
|
|
@@ -4730,7 +5610,11 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
|
4730
5610
|
dependency: i.importPath
|
|
4731
5611
|
};
|
|
4732
5612
|
});
|
|
4733
|
-
return [
|
|
5613
|
+
return [
|
|
5614
|
+
...schemaImports,
|
|
5615
|
+
...schemaFactoryDeps,
|
|
5616
|
+
...otherImports
|
|
5617
|
+
];
|
|
4734
5618
|
}
|
|
4735
5619
|
//#endregion
|
|
4736
5620
|
//#region src/writers/mock-outputs.ts
|
|
@@ -5448,6 +6332,6 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
5448
6332
|
}))).flat();
|
|
5449
6333
|
}
|
|
5450
6334
|
//#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 };
|
|
6335
|
+
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, buildDynamicScope, camel, collectReferencedComponents, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicAnchorToParamName, dynamicAnchorsToUniqueParamNames, dynamicImport, escape, escapeRegExp, extractBoundAliasInfo, filterByContentType, filteredVerbs, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFactory, 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, getDynamicAnchorName, 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, isDynamicReference, 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, resolveDynamicRef, resolveExampleRefs, resolveInstalledVersion, resolveInstalledVersions, resolveObject, resolveRef, resolveValue, sanitize, setVerbose, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, wrapRouteParameters, writeGeneratedFile, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
|
|
5452
6336
|
|
|
5453
6337
|
//# sourceMappingURL=index.mjs.map
|