@kubb/adapter-oas 5.0.0-alpha.15 → 5.0.0-alpha.16
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.cjs +157 -343
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +151 -341
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/adapter.ts +1 -1
- package/src/constants.ts +0 -49
- package/src/discriminator.ts +25 -0
- package/src/infer.ts +85 -0
- package/src/naming.ts +25 -0
- package/src/oas/types.ts +10 -4
- package/src/parser.ts +122 -323
- package/src/refResolver.ts +65 -0
- package/src/utils.ts +0 -168
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "./chunk--u3MIqq1.js";
|
|
1
|
+
import { t as __name } from "./chunk--u3MIqq1.js";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { collect, createOperation, createParameter, createProperty, createResponse, createRoot, createSchema, narrowSchema, schemaTypes, transform } from "@kubb/ast";
|
|
3
|
+
import { applyDiscriminatorEnum, collect, createOperation, createParameter, createProperty, createResponse, createRoot, createSchema, extractRefName, mediaTypes, mergeAdjacentAnonymousObjects, narrowSchema, schemaTypes, simplifyUnionMembers, transform } from "@kubb/ast";
|
|
4
4
|
import { createAdapter } from "@kubb/core";
|
|
5
5
|
import { bundle, loadConfig } from "@redocly/openapi-core";
|
|
6
6
|
import yaml from "@stoplight/yaml";
|
|
@@ -76,44 +76,10 @@ const formatMap = {
|
|
|
76
76
|
double: "number"
|
|
77
77
|
};
|
|
78
78
|
/**
|
|
79
|
-
* Exhaustive list of media types that Kubb recognizes.
|
|
80
|
-
*/
|
|
81
|
-
const knownMediaTypes = new Set([
|
|
82
|
-
"application/json",
|
|
83
|
-
"application/xml",
|
|
84
|
-
"application/x-www-form-urlencoded",
|
|
85
|
-
"application/octet-stream",
|
|
86
|
-
"application/pdf",
|
|
87
|
-
"application/zip",
|
|
88
|
-
"application/graphql",
|
|
89
|
-
"multipart/form-data",
|
|
90
|
-
"text/plain",
|
|
91
|
-
"text/html",
|
|
92
|
-
"text/csv",
|
|
93
|
-
"text/xml",
|
|
94
|
-
"image/png",
|
|
95
|
-
"image/jpeg",
|
|
96
|
-
"image/gif",
|
|
97
|
-
"image/webp",
|
|
98
|
-
"image/svg+xml",
|
|
99
|
-
"audio/mpeg",
|
|
100
|
-
"video/mp4"
|
|
101
|
-
]);
|
|
102
|
-
/**
|
|
103
79
|
* Vendor extension keys used to attach human-readable labels to enum values.
|
|
104
80
|
* Checked in priority order: the first key found wins.
|
|
105
81
|
*/
|
|
106
82
|
const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
|
|
107
|
-
/**
|
|
108
|
-
* Scalar primitive schema types used for union member simplification.
|
|
109
|
-
*/
|
|
110
|
-
const SCALAR_PRIMITIVE_TYPES = new Set([
|
|
111
|
-
"string",
|
|
112
|
-
"number",
|
|
113
|
-
"integer",
|
|
114
|
-
"bigint",
|
|
115
|
-
"boolean"
|
|
116
|
-
]);
|
|
117
83
|
//#endregion
|
|
118
84
|
//#region src/oas/resolveServerUrl.ts
|
|
119
85
|
/**
|
|
@@ -916,122 +882,54 @@ function resolveCollisions(schemasWithMeta) {
|
|
|
916
882
|
};
|
|
917
883
|
}
|
|
918
884
|
//#endregion
|
|
919
|
-
//#region src/
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
* Falls back to the full ref string when no slash is present.
|
|
924
|
-
*/
|
|
925
|
-
function extractRefName($ref) {
|
|
926
|
-
return $ref.split("/").at(-1) ?? $ref;
|
|
885
|
+
//#region src/discriminator.ts
|
|
886
|
+
function resolveDiscriminatorValue(mapping, ref) {
|
|
887
|
+
if (!mapping || !ref) return void 0;
|
|
888
|
+
return Object.entries(mapping).find(([, value]) => value === ref)?.[0];
|
|
927
889
|
}
|
|
928
|
-
|
|
929
|
-
* Replaces the discriminator property's schema inside an `ObjectSchemaNode`
|
|
930
|
-
* with an enum of the given `values`.
|
|
931
|
-
*
|
|
932
|
-
* - When `enumName` is provided the enum is named, which lets printers emit a
|
|
933
|
-
* standalone enum declaration + type reference (e.g. `PetTypeEnum`).
|
|
934
|
-
* - When `enumName` is omitted the enum stays anonymous, so printers inline it
|
|
935
|
-
* as a literal union (e.g. `'dog'`).
|
|
936
|
-
*
|
|
937
|
-
* Returns the node unchanged when it is not an object or lacks the target property.
|
|
938
|
-
*/
|
|
939
|
-
function applyDiscriminatorEnum({ node, propertyName, values, enumName }) {
|
|
940
|
-
if (node.type !== "object" || !node.properties?.length) return node;
|
|
941
|
-
if (!node.properties.some((prop) => prop.name === propertyName)) return node;
|
|
890
|
+
function createDiscriminantNode(propertyName, value) {
|
|
942
891
|
return createSchema({
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
892
|
+
type: "object",
|
|
893
|
+
primitive: "object",
|
|
894
|
+
properties: [createProperty({
|
|
895
|
+
name: propertyName,
|
|
896
|
+
schema: createSchema({
|
|
947
897
|
type: "enum",
|
|
948
898
|
primitive: "string",
|
|
949
|
-
enumValues:
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
});
|
|
954
|
-
return createProperty({
|
|
955
|
-
...prop,
|
|
956
|
-
schema: enumSchema
|
|
957
|
-
});
|
|
958
|
-
})
|
|
899
|
+
enumValues: [value]
|
|
900
|
+
}),
|
|
901
|
+
required: true
|
|
902
|
+
})]
|
|
959
903
|
});
|
|
960
904
|
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
* Only adjacent pairs are merged — non-object or named nodes act as boundaries.
|
|
966
|
-
* This collapses patterns like `Address & { streetNumber } & { streetName }` into
|
|
967
|
-
* `Address & { streetNumber; streetName }`.
|
|
968
|
-
*/
|
|
969
|
-
function mergeAdjacentAnonymousObjects(members) {
|
|
970
|
-
return members.reduce((acc, member) => {
|
|
971
|
-
const obj = narrowSchema(member, "object");
|
|
972
|
-
if (obj && !obj.name) {
|
|
973
|
-
const prev = acc[acc.length - 1];
|
|
974
|
-
const prevObj = prev ? narrowSchema(prev, "object") : null;
|
|
975
|
-
if (prevObj && !prevObj.name) {
|
|
976
|
-
acc[acc.length - 1] = createSchema({
|
|
977
|
-
...prevObj,
|
|
978
|
-
properties: [...prevObj.properties ?? [], ...obj.properties ?? []]
|
|
979
|
-
});
|
|
980
|
-
return acc;
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
acc.push(member);
|
|
984
|
-
return acc;
|
|
985
|
-
}, []);
|
|
905
|
+
//#endregion
|
|
906
|
+
//#region src/naming.ts
|
|
907
|
+
function resolveChildName(parentName, propName) {
|
|
908
|
+
return parentName ? pascalCase([parentName, propName].join(" ")) : void 0;
|
|
986
909
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
return
|
|
1005
|
-
if (m.type !== "enum") return true;
|
|
1006
|
-
const prim = m.primitive;
|
|
1007
|
-
if (!prim) return true;
|
|
1008
|
-
if (!m.enumType) return true;
|
|
1009
|
-
if (scalarPrimitives.has(prim)) return false;
|
|
1010
|
-
if ((prim === "integer" || prim === "number") && (scalarPrimitives.has("integer") || scalarPrimitives.has("number"))) return false;
|
|
1011
|
-
return true;
|
|
1012
|
-
});
|
|
910
|
+
function resolveEnumPropName(parentName, propName, enumSuffix) {
|
|
911
|
+
return pascalCase([
|
|
912
|
+
parentName,
|
|
913
|
+
propName,
|
|
914
|
+
enumSuffix
|
|
915
|
+
].filter(Boolean).join(" "));
|
|
916
|
+
}
|
|
917
|
+
function applyEnumName(propNode, parentName, propName, enumSuffix) {
|
|
918
|
+
const enumNode = narrowSchema(propNode, "enum");
|
|
919
|
+
if (enumNode?.primitive === "boolean") return {
|
|
920
|
+
...propNode,
|
|
921
|
+
name: void 0
|
|
922
|
+
};
|
|
923
|
+
if (enumNode) return {
|
|
924
|
+
...propNode,
|
|
925
|
+
name: resolveEnumPropName(parentName, propName, enumSuffix)
|
|
926
|
+
};
|
|
927
|
+
return propNode;
|
|
1013
928
|
}
|
|
929
|
+
//#endregion
|
|
930
|
+
//#region src/refResolver.ts
|
|
1014
931
|
/**
|
|
1015
|
-
*
|
|
1016
|
-
* each import. When `oas` is supplied, only `$ref`s that are resolvable in the
|
|
1017
|
-
* spec are included; omit it to skip the existence check.
|
|
1018
|
-
*
|
|
1019
|
-
* This function is the pure, state-free alternative to `OasParser.getImports`.
|
|
1020
|
-
* Because it receives `nameMapping` explicitly it can be called without holding
|
|
1021
|
-
* a reference to the parser or the OAS instance.
|
|
1022
|
-
*
|
|
1023
|
-
* @example
|
|
1024
|
-
* ```ts
|
|
1025
|
-
* // Use adapter state directly — no parser reference needed
|
|
1026
|
-
* const imports = getImports({
|
|
1027
|
-
* node: schemaNode,
|
|
1028
|
-
* nameMapping: adapter.options.nameMapping,
|
|
1029
|
-
* resolve: (schemaName) => ({
|
|
1030
|
-
* name: schemaManager.getName(schemaName, { type: 'type' }),
|
|
1031
|
-
* path: schemaManager.getFile(schemaName).path,
|
|
1032
|
-
* }),
|
|
1033
|
-
* })
|
|
1034
|
-
* ```
|
|
932
|
+
* Collects import entries for all `ref` schema nodes in `node`.
|
|
1035
933
|
*/
|
|
1036
934
|
function getImports({ node, nameMapping, resolve }) {
|
|
1037
935
|
return collect(node, { schema(schemaNode) {
|
|
@@ -1045,6 +943,29 @@ function getImports({ node, nameMapping, resolve }) {
|
|
|
1045
943
|
};
|
|
1046
944
|
} });
|
|
1047
945
|
}
|
|
946
|
+
/**
|
|
947
|
+
* Walks a schema tree and resolves `ref`/`enum` names through callbacks.
|
|
948
|
+
*/
|
|
949
|
+
function resolveRefs({ node, nameMapping, resolveName, resolveEnumName }) {
|
|
950
|
+
return transform(node, { schema(schemaNode) {
|
|
951
|
+
const schemaRef = narrowSchema(schemaNode, schemaTypes.ref);
|
|
952
|
+
if (schemaRef && (schemaRef.ref || schemaRef.name)) {
|
|
953
|
+
const rawRef = schemaRef.ref ?? schemaRef.name;
|
|
954
|
+
const resolved = resolveName(nameMapping.get(rawRef) ?? rawRef);
|
|
955
|
+
if (resolved) return {
|
|
956
|
+
...schemaNode,
|
|
957
|
+
name: resolved
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
if (schemaNode.type === "enum" && schemaNode.name) {
|
|
961
|
+
const resolved = (resolveEnumName ?? resolveName)(schemaNode.name);
|
|
962
|
+
if (resolved) return {
|
|
963
|
+
...schemaNode,
|
|
964
|
+
name: resolved
|
|
965
|
+
};
|
|
966
|
+
}
|
|
967
|
+
} });
|
|
968
|
+
}
|
|
1048
969
|
//#endregion
|
|
1049
970
|
//#region src/parser.ts
|
|
1050
971
|
/**
|
|
@@ -1070,7 +991,7 @@ function getPrimitiveType(type) {
|
|
|
1070
991
|
* Returns `undefined` for content types not present in `KNOWN_MEDIA_TYPES`.
|
|
1071
992
|
*/
|
|
1072
993
|
function toMediaType(contentType) {
|
|
1073
|
-
return
|
|
994
|
+
return Object.values(mediaTypes).includes(contentType) ? contentType : void 0;
|
|
1074
995
|
}
|
|
1075
996
|
/**
|
|
1076
997
|
* Creates an OAS parser that converts an OpenAPI/Swagger spec into
|
|
@@ -1093,14 +1014,28 @@ function toMediaType(contentType) {
|
|
|
1093
1014
|
*/
|
|
1094
1015
|
function createOasParser(oas, { contentType } = {}) {
|
|
1095
1016
|
const { schemas: schemaObjects, nameMapping } = oas.getSchemas({ contentType });
|
|
1017
|
+
const TYPE_OPTION_MAP = {
|
|
1018
|
+
any: schemaTypes.any,
|
|
1019
|
+
unknown: schemaTypes.unknown,
|
|
1020
|
+
void: schemaTypes.void
|
|
1021
|
+
};
|
|
1096
1022
|
/**
|
|
1097
1023
|
* Maps an `'any' | 'unknown' | 'void'` option string to the corresponding `SchemaType` constant.
|
|
1098
1024
|
* Used for both `unknownType` (unannotated schemas) and `emptySchemaType` (empty `{}` schemas).
|
|
1099
1025
|
*/
|
|
1100
1026
|
function resolveTypeOption(value) {
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1027
|
+
return TYPE_OPTION_MAP[value];
|
|
1028
|
+
}
|
|
1029
|
+
function normalizeArrayEnum(schema) {
|
|
1030
|
+
const normalizedItems = {
|
|
1031
|
+
...typeof schema.items === "object" && !Array.isArray(schema.items) ? schema.items : {},
|
|
1032
|
+
enum: schema.enum
|
|
1033
|
+
};
|
|
1034
|
+
const { enum: _enum, ...schemaWithoutEnum } = schema;
|
|
1035
|
+
return {
|
|
1036
|
+
...schemaWithoutEnum,
|
|
1037
|
+
items: normalizedItems
|
|
1038
|
+
};
|
|
1104
1039
|
}
|
|
1105
1040
|
/**
|
|
1106
1041
|
* Resolves the AST type and datetime modifiers for a date/time format, honoring the `dateType` option.
|
|
@@ -1189,10 +1124,10 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1189
1124
|
* Circular references through discriminator parents are detected and skipped to prevent
|
|
1190
1125
|
* infinite recursion during code generation.
|
|
1191
1126
|
*/
|
|
1192
|
-
function convertAllOf({ schema, name, nullable, defaultValue,
|
|
1127
|
+
function convertAllOf({ schema, name, nullable, defaultValue, rawOptions }) {
|
|
1193
1128
|
if (schema.allOf.length === 1 && !schema.properties && !(Array.isArray(schema.required) && schema.required.length) && schema.additionalProperties === void 0) {
|
|
1194
1129
|
const [memberSchema] = schema.allOf;
|
|
1195
|
-
const memberNode = convertSchema({ schema: memberSchema },
|
|
1130
|
+
const memberNode = convertSchema({ schema: memberSchema }, rawOptions);
|
|
1196
1131
|
const { kind: _kind, ...memberNodeProps } = memberNode;
|
|
1197
1132
|
const mergedNullable = nullable || memberNode.nullable || void 0;
|
|
1198
1133
|
const mergedDefault = schema.default === null && mergedNullable ? void 0 : schema.default ?? memberNode.default;
|
|
@@ -1221,7 +1156,7 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1221
1156
|
const inOneOf = parentUnion.some((oneOfItem) => isReference(oneOfItem) && oneOfItem.$ref === childRef);
|
|
1222
1157
|
const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
|
|
1223
1158
|
if (inOneOf || inMapping) {
|
|
1224
|
-
const discriminatorValue =
|
|
1159
|
+
const discriminatorValue = resolveDiscriminatorValue(deref.discriminator.mapping, childRef);
|
|
1225
1160
|
if (discriminatorValue) filteredDiscriminantValues.push({
|
|
1226
1161
|
propertyName: deref.discriminator.propertyName,
|
|
1227
1162
|
value: discriminatorValue
|
|
@@ -1229,7 +1164,7 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1229
1164
|
return false;
|
|
1230
1165
|
}
|
|
1231
1166
|
return true;
|
|
1232
|
-
}).map((s) => convertSchema({ schema: s },
|
|
1167
|
+
}).map((s) => convertSchema({ schema: s }, rawOptions));
|
|
1233
1168
|
const syntheticStart = allOfMembers.length;
|
|
1234
1169
|
if (Array.isArray(schema.required) && schema.required.length) {
|
|
1235
1170
|
const outerKeys = schema.properties ? new Set(Object.keys(schema.properties)) : /* @__PURE__ */ new Set();
|
|
@@ -1244,28 +1179,16 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1244
1179
|
allOfMembers.push(convertSchema({ schema: {
|
|
1245
1180
|
properties: { [key]: resolved.properties[key] },
|
|
1246
1181
|
required: [key]
|
|
1247
|
-
} },
|
|
1182
|
+
} }, rawOptions));
|
|
1248
1183
|
break;
|
|
1249
1184
|
}
|
|
1250
1185
|
}
|
|
1251
1186
|
}
|
|
1252
1187
|
if (schema.properties) {
|
|
1253
1188
|
const { allOf: _allOf, ...schemaWithoutAllOf } = schema;
|
|
1254
|
-
allOfMembers.push(convertSchema({ schema: schemaWithoutAllOf },
|
|
1189
|
+
allOfMembers.push(convertSchema({ schema: schemaWithoutAllOf }, rawOptions));
|
|
1255
1190
|
}
|
|
1256
|
-
for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push(
|
|
1257
|
-
type: "object",
|
|
1258
|
-
primitive: "object",
|
|
1259
|
-
properties: [createProperty({
|
|
1260
|
-
name: propertyName,
|
|
1261
|
-
schema: createSchema({
|
|
1262
|
-
type: "enum",
|
|
1263
|
-
primitive: "string",
|
|
1264
|
-
enumValues: [value]
|
|
1265
|
-
}),
|
|
1266
|
-
required: true
|
|
1267
|
-
})]
|
|
1268
|
-
}));
|
|
1191
|
+
for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push(createDiscriminantNode(propertyName, value));
|
|
1269
1192
|
return createSchema({
|
|
1270
1193
|
type: "intersection",
|
|
1271
1194
|
members: [...mergeAdjacentAnonymousObjects(allOfMembers.slice(0, syntheticStart)), ...mergeAdjacentAnonymousObjects(allOfMembers.slice(syntheticStart))],
|
|
@@ -1280,69 +1203,46 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1280
1203
|
* individually intersected with the shared properties node to match the OAS pattern of
|
|
1281
1204
|
* adding common fields next to a discriminated union.
|
|
1282
1205
|
*/
|
|
1283
|
-
function convertUnion({ schema, name, nullable, defaultValue,
|
|
1206
|
+
function convertUnion({ schema, name, nullable, defaultValue, rawOptions }) {
|
|
1284
1207
|
const unionMembers = [...schema.oneOf ?? [], ...schema.anyOf ?? []];
|
|
1285
1208
|
const unionBase = {
|
|
1286
1209
|
...renderSchemaBase(schema, name, nullable, defaultValue),
|
|
1287
1210
|
discriminatorPropertyName: isDiscriminator(schema) ? schema.discriminator.propertyName : void 0
|
|
1288
1211
|
};
|
|
1289
|
-
|
|
1212
|
+
const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
|
|
1213
|
+
const sharedPropertiesNode = schema.properties ? (() => {
|
|
1290
1214
|
const { oneOf: _oneOf, anyOf: _anyOf, ...schemaWithoutUnion } = schema;
|
|
1291
|
-
|
|
1292
|
-
const sharedPropertiesNode = convertSchema({
|
|
1215
|
+
return convertSchema({
|
|
1293
1216
|
schema: discriminator ? Object.fromEntries(Object.entries(schemaWithoutUnion).filter(([key]) => key !== "discriminator")) : schemaWithoutUnion,
|
|
1294
1217
|
name
|
|
1295
|
-
},
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
...unionBase,
|
|
1299
|
-
members: unionMembers.map((s) => {
|
|
1300
|
-
const ref = isReference(s) ? s.$ref : void 0;
|
|
1301
|
-
const discriminatorValue = discriminator?.mapping && ref ? Object.entries(discriminator.mapping).find(([, v]) => v === ref)?.[0] : void 0;
|
|
1302
|
-
let propertiesNode = sharedPropertiesNode;
|
|
1303
|
-
if (discriminatorValue && discriminator) propertiesNode = applyDiscriminatorEnum({
|
|
1304
|
-
node: propertiesNode,
|
|
1305
|
-
propertyName: discriminator.propertyName,
|
|
1306
|
-
values: [discriminatorValue]
|
|
1307
|
-
});
|
|
1308
|
-
return createSchema({
|
|
1309
|
-
type: "intersection",
|
|
1310
|
-
members: [convertSchema({ schema: s }, options), propertiesNode]
|
|
1311
|
-
});
|
|
1312
|
-
})
|
|
1313
|
-
});
|
|
1314
|
-
}
|
|
1315
|
-
const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
|
|
1316
|
-
if (discriminator?.mapping) return createSchema({
|
|
1218
|
+
}, rawOptions);
|
|
1219
|
+
})() : void 0;
|
|
1220
|
+
if (sharedPropertiesNode || discriminator?.mapping) return createSchema({
|
|
1317
1221
|
type: "union",
|
|
1318
1222
|
...unionBase,
|
|
1319
1223
|
members: unionMembers.map((s) => {
|
|
1320
1224
|
const ref = isReference(s) ? s.$ref : void 0;
|
|
1321
|
-
const discriminatorValue =
|
|
1322
|
-
const memberNode = convertSchema({ schema: s },
|
|
1323
|
-
if (
|
|
1225
|
+
const discriminatorValue = resolveDiscriminatorValue(discriminator?.mapping, ref);
|
|
1226
|
+
const memberNode = convertSchema({ schema: s }, rawOptions);
|
|
1227
|
+
if (sharedPropertiesNode) return createSchema({
|
|
1228
|
+
type: "intersection",
|
|
1229
|
+
members: [memberNode, discriminatorValue && discriminator ? applyDiscriminatorEnum({
|
|
1230
|
+
node: sharedPropertiesNode,
|
|
1231
|
+
propertyName: discriminator.propertyName,
|
|
1232
|
+
values: [discriminatorValue]
|
|
1233
|
+
}) : sharedPropertiesNode]
|
|
1234
|
+
});
|
|
1235
|
+
if (!discriminatorValue || !discriminator) return memberNode;
|
|
1324
1236
|
return createSchema({
|
|
1325
1237
|
type: "intersection",
|
|
1326
|
-
members: [memberNode,
|
|
1327
|
-
type: "object",
|
|
1328
|
-
primitive: "object",
|
|
1329
|
-
properties: [createProperty({
|
|
1330
|
-
name: discriminator.propertyName,
|
|
1331
|
-
schema: createSchema({
|
|
1332
|
-
type: "enum",
|
|
1333
|
-
primitive: "string",
|
|
1334
|
-
enumValues: [discriminatorValue]
|
|
1335
|
-
}),
|
|
1336
|
-
required: true
|
|
1337
|
-
})]
|
|
1338
|
-
})]
|
|
1238
|
+
members: [memberNode, createDiscriminantNode(discriminator.propertyName, discriminatorValue)]
|
|
1339
1239
|
});
|
|
1340
1240
|
})
|
|
1341
1241
|
});
|
|
1342
1242
|
return createSchema({
|
|
1343
1243
|
type: "union",
|
|
1344
1244
|
...unionBase,
|
|
1345
|
-
members: simplifyUnionMembers(unionMembers.map((s) => convertSchema({ schema: s },
|
|
1245
|
+
members: simplifyUnionMembers(unionMembers.map((s) => convertSchema({ schema: s }, rawOptions)))
|
|
1346
1246
|
});
|
|
1347
1247
|
}
|
|
1348
1248
|
/**
|
|
@@ -1372,10 +1272,10 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1372
1272
|
* Returns `undefined` when the format should fall through to string handling
|
|
1373
1273
|
* (i.e. `format: 'date-time'` with `dateType: false`).
|
|
1374
1274
|
*/
|
|
1375
|
-
function convertFormat({ schema, name, nullable, defaultValue,
|
|
1275
|
+
function convertFormat({ schema, name, nullable, defaultValue, options }) {
|
|
1376
1276
|
const base = renderSchemaBase(schema, name, nullable, defaultValue);
|
|
1377
1277
|
if (schema.format === "int64") return createSchema({
|
|
1378
|
-
type:
|
|
1278
|
+
type: options.integerType === "bigint" ? "bigint" : "integer",
|
|
1379
1279
|
primitive: "integer",
|
|
1380
1280
|
...base,
|
|
1381
1281
|
min: schema.minimum,
|
|
@@ -1384,7 +1284,7 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1384
1284
|
exclusiveMaximum: typeof schema.exclusiveMaximum === "number" ? schema.exclusiveMaximum : void 0
|
|
1385
1285
|
});
|
|
1386
1286
|
if (schema.format === "date-time" || schema.format === "date" || schema.format === "time") {
|
|
1387
|
-
const dateType = getDateType(
|
|
1287
|
+
const dateType = getDateType(options, schema.format);
|
|
1388
1288
|
if (!dateType) return void 0;
|
|
1389
1289
|
if (dateType.type === "datetime") return createSchema({
|
|
1390
1290
|
...base,
|
|
@@ -1429,28 +1329,19 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1429
1329
|
* - Numeric and boolean enums require a const-map representation because most generators cannot
|
|
1430
1330
|
* use string-enum syntax for non-string values.
|
|
1431
1331
|
*/
|
|
1432
|
-
function convertEnum({ schema, name, nullable, type,
|
|
1433
|
-
if (type === "array") {
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
};
|
|
1438
|
-
const { enum: _enum, ...schemaWithoutEnum } = schema;
|
|
1439
|
-
return convertSchema({
|
|
1440
|
-
schema: {
|
|
1441
|
-
...schemaWithoutEnum,
|
|
1442
|
-
items: normalizedItems
|
|
1443
|
-
},
|
|
1444
|
-
name
|
|
1445
|
-
}, options);
|
|
1446
|
-
}
|
|
1332
|
+
function convertEnum({ schema, name, nullable, type, rawOptions }) {
|
|
1333
|
+
if (type === "array") return convertSchema({
|
|
1334
|
+
schema: normalizeArrayEnum(schema),
|
|
1335
|
+
name
|
|
1336
|
+
}, rawOptions);
|
|
1447
1337
|
const nullInEnum = schema.enum.includes(null);
|
|
1448
1338
|
const filteredValues = nullInEnum ? schema.enum.filter((v) => v !== null) : schema.enum;
|
|
1449
1339
|
const enumNullable = nullable || nullInEnum || void 0;
|
|
1450
1340
|
const enumDefault = schema.default === null && enumNullable ? void 0 : schema.default;
|
|
1341
|
+
const enumPrimitive = getPrimitiveType(type);
|
|
1451
1342
|
const enumBase = {
|
|
1452
1343
|
type: "enum",
|
|
1453
|
-
primitive:
|
|
1344
|
+
primitive: enumPrimitive,
|
|
1454
1345
|
name,
|
|
1455
1346
|
title: schema.title,
|
|
1456
1347
|
description: schema.description,
|
|
@@ -1462,38 +1353,19 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1462
1353
|
example: schema.example
|
|
1463
1354
|
};
|
|
1464
1355
|
const extensionKey = enumExtensionKeys.find((key) => key in schema);
|
|
1465
|
-
if (extensionKey) {
|
|
1466
|
-
const
|
|
1467
|
-
const
|
|
1468
|
-
const enumType = getPrimitiveType(type) === "number" || getPrimitiveType(type) === "integer" ? "number" : getPrimitiveType(type) === "boolean" ? "boolean" : "string";
|
|
1356
|
+
if (extensionKey || enumPrimitive === "number" || enumPrimitive === "integer" || enumPrimitive === "boolean") {
|
|
1357
|
+
const enumType = enumPrimitive === "number" || enumPrimitive === "integer" ? "number" : enumPrimitive === "boolean" ? "boolean" : "string";
|
|
1358
|
+
const sourceValues = extensionKey ? [...new Set(schema[extensionKey])] : [...new Set(filteredValues)];
|
|
1469
1359
|
return createSchema({
|
|
1470
1360
|
...enumBase,
|
|
1471
1361
|
enumType,
|
|
1472
|
-
namedEnumValues:
|
|
1362
|
+
namedEnumValues: sourceValues.map((label, index) => ({
|
|
1473
1363
|
name: String(label),
|
|
1474
|
-
value: filteredValues[index] ?? label,
|
|
1364
|
+
value: extensionKey ? filteredValues[index] ?? label : label,
|
|
1475
1365
|
format: enumType
|
|
1476
1366
|
}))
|
|
1477
1367
|
});
|
|
1478
1368
|
}
|
|
1479
|
-
if (type === "number" || type === "integer") return createSchema({
|
|
1480
|
-
...enumBase,
|
|
1481
|
-
enumType: "number",
|
|
1482
|
-
namedEnumValues: [...new Set(filteredValues)].map((value) => ({
|
|
1483
|
-
name: String(value),
|
|
1484
|
-
value,
|
|
1485
|
-
format: "number"
|
|
1486
|
-
}))
|
|
1487
|
-
});
|
|
1488
|
-
if (type === "boolean") return createSchema({
|
|
1489
|
-
...enumBase,
|
|
1490
|
-
enumType: "boolean",
|
|
1491
|
-
namedEnumValues: [...new Set(filteredValues)].map((value) => ({
|
|
1492
|
-
name: String(value),
|
|
1493
|
-
value,
|
|
1494
|
-
format: "boolean"
|
|
1495
|
-
}))
|
|
1496
|
-
});
|
|
1497
1369
|
return createSchema({
|
|
1498
1370
|
...enumBase,
|
|
1499
1371
|
enumValues: [...new Set(filteredValues)]
|
|
@@ -1511,46 +1383,7 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1511
1383
|
* - not required + not nullable → `optional: true`
|
|
1512
1384
|
* - not required + nullable → `nullish: true`
|
|
1513
1385
|
*/
|
|
1514
|
-
|
|
1515
|
-
* Builds the propagation name for a child property during recursive schema conversion.
|
|
1516
|
-
*
|
|
1517
|
-
* The parent name is prepended so the full path is encoded
|
|
1518
|
-
* (e.g. `OrderParams` when parent is `Order`).
|
|
1519
|
-
*/
|
|
1520
|
-
function resolveChildName(parentName, propName) {
|
|
1521
|
-
return parentName ? pascalCase([parentName, propName].join(" ")) : void 0;
|
|
1522
|
-
}
|
|
1523
|
-
/**
|
|
1524
|
-
* Derives the final name for an enum property schema node.
|
|
1525
|
-
*
|
|
1526
|
-
* The resulting name always includes the enum suffix and full parent path context
|
|
1527
|
-
* (e.g. `OrderParamsStatusEnum`).
|
|
1528
|
-
*/
|
|
1529
|
-
function resolveEnumPropName(parentName, propName, enumSuffix) {
|
|
1530
|
-
return pascalCase([
|
|
1531
|
-
parentName,
|
|
1532
|
-
propName,
|
|
1533
|
-
enumSuffix
|
|
1534
|
-
].filter(Boolean).join(" "));
|
|
1535
|
-
}
|
|
1536
|
-
/**
|
|
1537
|
-
* Given a freshly-converted property schema, returns the node with a correct
|
|
1538
|
-
* `name` attached — or stripped — depending on whether the node is a named
|
|
1539
|
-
* enum, a boolean const-enum (always inlined), or a regular schema.
|
|
1540
|
-
*/
|
|
1541
|
-
function applyEnumName(propNode, parentName, propName, enumSuffix) {
|
|
1542
|
-
const enumNode = narrowSchema(propNode, "enum");
|
|
1543
|
-
if (enumNode?.primitive === "boolean") return {
|
|
1544
|
-
...propNode,
|
|
1545
|
-
name: void 0
|
|
1546
|
-
};
|
|
1547
|
-
if (enumNode) return {
|
|
1548
|
-
...propNode,
|
|
1549
|
-
name: resolveEnumPropName(parentName, propName, enumSuffix)
|
|
1550
|
-
};
|
|
1551
|
-
return propNode;
|
|
1552
|
-
}
|
|
1553
|
-
function convertObject({ schema, name, nullable, defaultValue, options, mergedOptions }) {
|
|
1386
|
+
function convertObject({ schema, name, nullable, defaultValue, rawOptions, options }) {
|
|
1554
1387
|
const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
|
|
1555
1388
|
const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
|
|
1556
1389
|
const resolvedPropSchema = propSchema;
|
|
@@ -1558,10 +1391,10 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1558
1391
|
let schemaNode = applyEnumName(convertSchema({
|
|
1559
1392
|
schema: resolvedPropSchema,
|
|
1560
1393
|
name: resolveChildName(name, propName)
|
|
1561
|
-
},
|
|
1394
|
+
}, rawOptions), name, propName, options.enumSuffix);
|
|
1562
1395
|
const tupleNode = narrowSchema(schemaNode, "tuple");
|
|
1563
1396
|
if (tupleNode?.items) {
|
|
1564
|
-
const namedItems = tupleNode.items.map((item) => applyEnumName(item, name, propName,
|
|
1397
|
+
const namedItems = tupleNode.items.map((item) => applyEnumName(item, name, propName, options.enumSuffix));
|
|
1565
1398
|
if (namedItems.some((item, i) => item !== tupleNode.items[i])) schemaNode = {
|
|
1566
1399
|
...tupleNode,
|
|
1567
1400
|
items: namedItems
|
|
@@ -1579,11 +1412,11 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1579
1412
|
const additionalProperties = schema.additionalProperties;
|
|
1580
1413
|
let additionalPropertiesNode;
|
|
1581
1414
|
if (additionalProperties === true) additionalPropertiesNode = true;
|
|
1582
|
-
else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = convertSchema({ schema: additionalProperties },
|
|
1415
|
+
else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = convertSchema({ schema: additionalProperties }, rawOptions);
|
|
1583
1416
|
else if (additionalProperties === false) additionalPropertiesNode = void 0;
|
|
1584
|
-
else if (additionalProperties) additionalPropertiesNode = createSchema({ type: resolveTypeOption(
|
|
1417
|
+
else if (additionalProperties) additionalPropertiesNode = createSchema({ type: resolveTypeOption(options.unknownType) });
|
|
1585
1418
|
const rawPatternProperties = "patternProperties" in schema ? schema.patternProperties : void 0;
|
|
1586
|
-
const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || typeof patternSchema === "object" && Object.keys(patternSchema).length === 0 ? createSchema({ type: resolveTypeOption(
|
|
1419
|
+
const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || typeof patternSchema === "object" && Object.keys(patternSchema).length === 0 ? createSchema({ type: resolveTypeOption(options.unknownType) }) : convertSchema({ schema: patternSchema }, rawOptions)])) : void 0;
|
|
1587
1420
|
const objectNode = createSchema({
|
|
1588
1421
|
type: "object",
|
|
1589
1422
|
primitive: "object",
|
|
@@ -1598,7 +1431,7 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1598
1431
|
node: objectNode,
|
|
1599
1432
|
propertyName: discPropName,
|
|
1600
1433
|
values: Object.keys(schema.discriminator.mapping),
|
|
1601
|
-
enumName: name ? resolveEnumPropName(name, discPropName,
|
|
1434
|
+
enumName: name ? resolveEnumPropName(name, discPropName, options.enumSuffix) : void 0
|
|
1602
1435
|
});
|
|
1603
1436
|
}
|
|
1604
1437
|
return objectNode;
|
|
@@ -1611,12 +1444,12 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1611
1444
|
* a rest element of type `any` is emitted to match JSON Schema semantics (absent `items`
|
|
1612
1445
|
* means additional items are allowed).
|
|
1613
1446
|
*/
|
|
1614
|
-
function convertTuple({ schema, name, nullable, defaultValue,
|
|
1447
|
+
function convertTuple({ schema, name, nullable, defaultValue, rawOptions }) {
|
|
1615
1448
|
return createSchema({
|
|
1616
1449
|
type: "tuple",
|
|
1617
1450
|
primitive: "array",
|
|
1618
|
-
items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item },
|
|
1619
|
-
rest: schema.items ? convertSchema({ schema: schema.items },
|
|
1451
|
+
items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item }, rawOptions)),
|
|
1452
|
+
rest: schema.items ? convertSchema({ schema: schema.items }, rawOptions) : createSchema({ type: "any" }),
|
|
1620
1453
|
min: schema.minItems,
|
|
1621
1454
|
max: schema.maxItems,
|
|
1622
1455
|
...renderSchemaBase(schema, name, nullable, defaultValue)
|
|
@@ -1628,16 +1461,16 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1628
1461
|
* When the items schema is an inline enum, a name derived from the parent array's name and
|
|
1629
1462
|
* `enumSuffix` is forwarded so generators can emit a named enum declaration.
|
|
1630
1463
|
*/
|
|
1631
|
-
function convertArray({ schema, name, nullable, defaultValue,
|
|
1464
|
+
function convertArray({ schema, name, nullable, defaultValue, rawOptions, options }) {
|
|
1632
1465
|
const rawItems = schema.items;
|
|
1633
|
-
const itemName = rawItems?.enum?.length && name ? resolveEnumPropName(void 0, name,
|
|
1466
|
+
const itemName = rawItems?.enum?.length && name ? resolveEnumPropName(void 0, name, options.enumSuffix) : void 0;
|
|
1634
1467
|
return createSchema({
|
|
1635
1468
|
type: "array",
|
|
1636
1469
|
primitive: "array",
|
|
1637
1470
|
items: rawItems ? [convertSchema({
|
|
1638
1471
|
schema: rawItems,
|
|
1639
1472
|
name: itemName
|
|
1640
|
-
},
|
|
1473
|
+
}, rawOptions)] : [],
|
|
1641
1474
|
min: schema.minItems,
|
|
1642
1475
|
max: schema.maxItems,
|
|
1643
1476
|
unique: schema.uniqueItems ?? void 0,
|
|
@@ -1711,16 +1544,16 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1711
1544
|
* 10. Object / array / tuple / scalar by `type`
|
|
1712
1545
|
* 11. Empty schema fallback (`emptySchemaType` option)
|
|
1713
1546
|
*/
|
|
1714
|
-
function convertSchema({ schema, name },
|
|
1715
|
-
const
|
|
1547
|
+
function convertSchema({ schema, name }, rawOptions) {
|
|
1548
|
+
const options = {
|
|
1716
1549
|
...DEFAULT_PARSER_OPTIONS,
|
|
1717
|
-
...
|
|
1550
|
+
...rawOptions
|
|
1718
1551
|
};
|
|
1719
1552
|
const flattenedSchema = flattenSchema(schema);
|
|
1720
1553
|
if (flattenedSchema && flattenedSchema !== schema) return convertSchema({
|
|
1721
1554
|
schema: flattenedSchema,
|
|
1722
1555
|
name
|
|
1723
|
-
},
|
|
1556
|
+
}, rawOptions);
|
|
1724
1557
|
const nullable = isNullable(schema) || void 0;
|
|
1725
1558
|
const defaultValue = schema.default === null && nullable ? void 0 : schema.default;
|
|
1726
1559
|
const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
|
|
@@ -1730,8 +1563,8 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1730
1563
|
nullable,
|
|
1731
1564
|
defaultValue,
|
|
1732
1565
|
type,
|
|
1733
|
-
|
|
1734
|
-
|
|
1566
|
+
rawOptions,
|
|
1567
|
+
options
|
|
1735
1568
|
};
|
|
1736
1569
|
if (isReference(schema)) return convertRef(ctx);
|
|
1737
1570
|
if (schema.allOf?.length) return convertAllOf(ctx);
|
|
@@ -1757,7 +1590,7 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1757
1590
|
type: t
|
|
1758
1591
|
},
|
|
1759
1592
|
name
|
|
1760
|
-
},
|
|
1593
|
+
}, rawOptions)),
|
|
1761
1594
|
...renderSchemaBase(schema, name, arrayNullable, defaultValue)
|
|
1762
1595
|
});
|
|
1763
1596
|
}
|
|
@@ -1775,7 +1608,7 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1775
1608
|
if (type === "boolean") return convertBoolean(ctx);
|
|
1776
1609
|
if (type === "null") return convertNull(ctx);
|
|
1777
1610
|
return createSchema({
|
|
1778
|
-
type: resolveTypeOption(
|
|
1611
|
+
type: resolveTypeOption(options.emptySchemaType),
|
|
1779
1612
|
name,
|
|
1780
1613
|
title: schema.title,
|
|
1781
1614
|
description: schema.description
|
|
@@ -1861,38 +1694,15 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1861
1694
|
operations: Object.entries(paths).flatMap(([_path, methods]) => Object.entries(methods).map(([, operation]) => operation ? parseOperation(mergedOptions, oas, operation) : null).filter((op) => op !== null))
|
|
1862
1695
|
});
|
|
1863
1696
|
}
|
|
1864
|
-
/**
|
|
1865
|
-
* Walks a `SchemaNode` tree and resolves all `ref` node names through the provided callbacks.
|
|
1866
|
-
*
|
|
1867
|
-
* `resolveName` handles all schema types; `resolveEnumName` (when provided) takes precedence
|
|
1868
|
-
* for `enum` nodes, enabling a separate naming strategy for enums (e.g. different suffix).
|
|
1869
|
-
*
|
|
1870
|
-
* Collision-resolved names (from `nameMapping`) are applied before user-supplied resolvers.
|
|
1871
|
-
*/
|
|
1872
|
-
function resolveRefs(node, resolveName, resolveEnumName) {
|
|
1873
|
-
return transform(node, { schema(schemaNode) {
|
|
1874
|
-
const schemaRef = narrowSchema(schemaNode, schemaTypes.ref);
|
|
1875
|
-
if (schemaRef && (schemaRef.ref || schemaRef.name)) {
|
|
1876
|
-
const rawRef = schemaRef.ref ?? schemaRef.name;
|
|
1877
|
-
const resolved = resolveName(nameMapping.get(rawRef) ?? rawRef);
|
|
1878
|
-
if (resolved) return {
|
|
1879
|
-
...schemaNode,
|
|
1880
|
-
name: resolved
|
|
1881
|
-
};
|
|
1882
|
-
}
|
|
1883
|
-
if (schemaNode.type === "enum" && schemaNode.name) {
|
|
1884
|
-
const resolved = (resolveEnumName ?? resolveName)(schemaNode.name);
|
|
1885
|
-
if (resolved) return {
|
|
1886
|
-
...schemaNode,
|
|
1887
|
-
name: resolved
|
|
1888
|
-
};
|
|
1889
|
-
}
|
|
1890
|
-
} });
|
|
1891
|
-
}
|
|
1892
1697
|
return {
|
|
1893
1698
|
parse,
|
|
1894
1699
|
convertSchema,
|
|
1895
|
-
resolveRefs,
|
|
1700
|
+
resolveRefs: /* @__PURE__ */ __name((node, resolveName, resolveEnumName) => resolveRefs({
|
|
1701
|
+
node,
|
|
1702
|
+
nameMapping,
|
|
1703
|
+
resolveName,
|
|
1704
|
+
resolveEnumName
|
|
1705
|
+
}), "resolveRefs"),
|
|
1896
1706
|
nameMapping
|
|
1897
1707
|
};
|
|
1898
1708
|
}
|