@kubb/adapter-oas 5.0.0-alpha.15 → 5.0.0-alpha.17
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 +126 -373
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -25
- package/dist/index.js +126 -373
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/adapter.ts +10 -3
- package/src/constants.ts +1 -51
- package/src/oas/types.ts +10 -4
- package/src/parser.ts +161 -335
- package/src/types.ts +1 -26
- package/src/utils.ts +0 -168
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./chunk--u3MIqq1.js";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { childName, collectImports, createDiscriminantNode, createOperation, createParameter, createProperty, createResponse, createRoot, createSchema, enumPropName, extractRefName, findDiscriminator, mediaTypes, mergeAdjacentObjects, narrowSchema, resolveNames, schemaTypes, setDiscriminatorEnum, setEnumName, simplifyUnion } 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,136 +882,6 @@ function resolveCollisions(schemasWithMeta) {
|
|
|
916
882
|
};
|
|
917
883
|
}
|
|
918
884
|
//#endregion
|
|
919
|
-
//#region src/utils.ts
|
|
920
|
-
/**
|
|
921
|
-
* Extracts the schema name from a `$ref` string.
|
|
922
|
-
* For `#/components/schemas/Order` this returns `'Order'`.
|
|
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;
|
|
927
|
-
}
|
|
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;
|
|
942
|
-
return createSchema({
|
|
943
|
-
...node,
|
|
944
|
-
properties: node.properties.map((prop) => {
|
|
945
|
-
if (prop.name !== propertyName) return prop;
|
|
946
|
-
const enumSchema = createSchema({
|
|
947
|
-
type: "enum",
|
|
948
|
-
primitive: "string",
|
|
949
|
-
enumValues: values,
|
|
950
|
-
name: enumName,
|
|
951
|
-
readOnly: prop.schema.readOnly,
|
|
952
|
-
writeOnly: prop.schema.writeOnly
|
|
953
|
-
});
|
|
954
|
-
return createProperty({
|
|
955
|
-
...prop,
|
|
956
|
-
schema: enumSchema
|
|
957
|
-
});
|
|
958
|
-
})
|
|
959
|
-
});
|
|
960
|
-
}
|
|
961
|
-
/**
|
|
962
|
-
* Merges consecutive anonymous (`name`-less) `ObjectSchemaNode`s in `members` into a
|
|
963
|
-
* single object by combining their `properties` arrays.
|
|
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
|
-
}, []);
|
|
986
|
-
}
|
|
987
|
-
/**
|
|
988
|
-
* Simplifies a union member list by removing `enum` nodes whose `primitive` type is
|
|
989
|
-
* already represented by a broader scalar node in the same union.
|
|
990
|
-
*
|
|
991
|
-
* For example `['placed', 'approved'] | string` collapses to `string` because
|
|
992
|
-
* `string` subsumes all string literals. `'' | string` similarly becomes `string`.
|
|
993
|
-
*
|
|
994
|
-
* Only scalar primitives (`string`, `number`, `integer`, `bigint`, `boolean`) are
|
|
995
|
-
* considered — object, array, and ref members are left untouched.
|
|
996
|
-
*
|
|
997
|
-
* Const-derived enums (those without an `enumType`, produced from an OpenAPI `const`
|
|
998
|
-
* keyword) are **never** removed — `'accepted' | string` must stay as-is because the
|
|
999
|
-
* literal is intentional.
|
|
1000
|
-
*/
|
|
1001
|
-
function simplifyUnionMembers(members) {
|
|
1002
|
-
const scalarPrimitives = new Set(members.filter((m) => SCALAR_PRIMITIVE_TYPES.has(m.type)).map((m) => m.type));
|
|
1003
|
-
if (!scalarPrimitives.size) return members;
|
|
1004
|
-
return members.filter((m) => {
|
|
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
|
-
});
|
|
1013
|
-
}
|
|
1014
|
-
/**
|
|
1015
|
-
* `nameMapping`, and calls `resolve` to obtain the `{ name, path }` pair for
|
|
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
|
-
* ```
|
|
1035
|
-
*/
|
|
1036
|
-
function getImports({ node, nameMapping, resolve }) {
|
|
1037
|
-
return collect(node, { schema(schemaNode) {
|
|
1038
|
-
if (schemaNode.type !== "ref" || !schemaNode.ref) return;
|
|
1039
|
-
const rawName = extractRefName(schemaNode.ref);
|
|
1040
|
-
const result = resolve(nameMapping.get(rawName) ?? rawName);
|
|
1041
|
-
if (!result) return;
|
|
1042
|
-
return {
|
|
1043
|
-
name: [result.name],
|
|
1044
|
-
path: result.path
|
|
1045
|
-
};
|
|
1046
|
-
} });
|
|
1047
|
-
}
|
|
1048
|
-
//#endregion
|
|
1049
885
|
//#region src/parser.ts
|
|
1050
886
|
/**
|
|
1051
887
|
* Looks up the Kubb `SchemaType` for a given OAS `format` string.
|
|
@@ -1070,7 +906,7 @@ function getPrimitiveType(type) {
|
|
|
1070
906
|
* Returns `undefined` for content types not present in `KNOWN_MEDIA_TYPES`.
|
|
1071
907
|
*/
|
|
1072
908
|
function toMediaType(contentType) {
|
|
1073
|
-
return
|
|
909
|
+
return Object.values(mediaTypes).includes(contentType) ? contentType : void 0;
|
|
1074
910
|
}
|
|
1075
911
|
/**
|
|
1076
912
|
* Creates an OAS parser that converts an OpenAPI/Swagger spec into
|
|
@@ -1093,14 +929,28 @@ function toMediaType(contentType) {
|
|
|
1093
929
|
*/
|
|
1094
930
|
function createOasParser(oas, { contentType } = {}) {
|
|
1095
931
|
const { schemas: schemaObjects, nameMapping } = oas.getSchemas({ contentType });
|
|
932
|
+
const TYPE_OPTION_MAP = {
|
|
933
|
+
any: schemaTypes.any,
|
|
934
|
+
unknown: schemaTypes.unknown,
|
|
935
|
+
void: schemaTypes.void
|
|
936
|
+
};
|
|
1096
937
|
/**
|
|
1097
938
|
* Maps an `'any' | 'unknown' | 'void'` option string to the corresponding `SchemaType` constant.
|
|
1098
939
|
* Used for both `unknownType` (unannotated schemas) and `emptySchemaType` (empty `{}` schemas).
|
|
1099
940
|
*/
|
|
1100
941
|
function resolveTypeOption(value) {
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
942
|
+
return TYPE_OPTION_MAP[value];
|
|
943
|
+
}
|
|
944
|
+
function normalizeArrayEnum(schema) {
|
|
945
|
+
const normalizedItems = {
|
|
946
|
+
...typeof schema.items === "object" && !Array.isArray(schema.items) ? schema.items : {},
|
|
947
|
+
enum: schema.enum
|
|
948
|
+
};
|
|
949
|
+
const { enum: _enum, ...schemaWithoutEnum } = schema;
|
|
950
|
+
return {
|
|
951
|
+
...schemaWithoutEnum,
|
|
952
|
+
items: normalizedItems
|
|
953
|
+
};
|
|
1104
954
|
}
|
|
1105
955
|
/**
|
|
1106
956
|
* Resolves the AST type and datetime modifiers for a date/time format, honoring the `dateType` option.
|
|
@@ -1189,10 +1039,10 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1189
1039
|
* Circular references through discriminator parents are detected and skipped to prevent
|
|
1190
1040
|
* infinite recursion during code generation.
|
|
1191
1041
|
*/
|
|
1192
|
-
function convertAllOf({ schema, name, nullable, defaultValue,
|
|
1042
|
+
function convertAllOf({ schema, name, nullable, defaultValue, rawOptions }) {
|
|
1193
1043
|
if (schema.allOf.length === 1 && !schema.properties && !(Array.isArray(schema.required) && schema.required.length) && schema.additionalProperties === void 0) {
|
|
1194
1044
|
const [memberSchema] = schema.allOf;
|
|
1195
|
-
const memberNode = convertSchema({ schema: memberSchema },
|
|
1045
|
+
const memberNode = convertSchema({ schema: memberSchema }, rawOptions);
|
|
1196
1046
|
const { kind: _kind, ...memberNodeProps } = memberNode;
|
|
1197
1047
|
const mergedNullable = nullable || memberNode.nullable || void 0;
|
|
1198
1048
|
const mergedDefault = schema.default === null && mergedNullable ? void 0 : schema.default ?? memberNode.default;
|
|
@@ -1221,7 +1071,7 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1221
1071
|
const inOneOf = parentUnion.some((oneOfItem) => isReference(oneOfItem) && oneOfItem.$ref === childRef);
|
|
1222
1072
|
const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
|
|
1223
1073
|
if (inOneOf || inMapping) {
|
|
1224
|
-
const discriminatorValue =
|
|
1074
|
+
const discriminatorValue = findDiscriminator(deref.discriminator.mapping, childRef);
|
|
1225
1075
|
if (discriminatorValue) filteredDiscriminantValues.push({
|
|
1226
1076
|
propertyName: deref.discriminator.propertyName,
|
|
1227
1077
|
value: discriminatorValue
|
|
@@ -1229,7 +1079,7 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1229
1079
|
return false;
|
|
1230
1080
|
}
|
|
1231
1081
|
return true;
|
|
1232
|
-
}).map((s) => convertSchema({ schema: s },
|
|
1082
|
+
}).map((s) => convertSchema({ schema: s }, rawOptions));
|
|
1233
1083
|
const syntheticStart = allOfMembers.length;
|
|
1234
1084
|
if (Array.isArray(schema.required) && schema.required.length) {
|
|
1235
1085
|
const outerKeys = schema.properties ? new Set(Object.keys(schema.properties)) : /* @__PURE__ */ new Set();
|
|
@@ -1244,31 +1094,22 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1244
1094
|
allOfMembers.push(convertSchema({ schema: {
|
|
1245
1095
|
properties: { [key]: resolved.properties[key] },
|
|
1246
1096
|
required: [key]
|
|
1247
|
-
} },
|
|
1097
|
+
} }, rawOptions));
|
|
1248
1098
|
break;
|
|
1249
1099
|
}
|
|
1250
1100
|
}
|
|
1251
1101
|
}
|
|
1252
1102
|
if (schema.properties) {
|
|
1253
1103
|
const { allOf: _allOf, ...schemaWithoutAllOf } = schema;
|
|
1254
|
-
allOfMembers.push(convertSchema({ schema: schemaWithoutAllOf },
|
|
1104
|
+
allOfMembers.push(convertSchema({ schema: schemaWithoutAllOf }, rawOptions));
|
|
1255
1105
|
}
|
|
1256
|
-
for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push(
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
properties: [createProperty({
|
|
1260
|
-
name: propertyName,
|
|
1261
|
-
schema: createSchema({
|
|
1262
|
-
type: "enum",
|
|
1263
|
-
primitive: "string",
|
|
1264
|
-
enumValues: [value]
|
|
1265
|
-
}),
|
|
1266
|
-
required: true
|
|
1267
|
-
})]
|
|
1106
|
+
for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push(createDiscriminantNode({
|
|
1107
|
+
propertyName,
|
|
1108
|
+
value
|
|
1268
1109
|
}));
|
|
1269
1110
|
return createSchema({
|
|
1270
1111
|
type: "intersection",
|
|
1271
|
-
members: [...
|
|
1112
|
+
members: [...mergeAdjacentObjects(allOfMembers.slice(0, syntheticStart)), ...mergeAdjacentObjects(allOfMembers.slice(syntheticStart))],
|
|
1272
1113
|
...renderSchemaBase(schema, name, nullable, defaultValue)
|
|
1273
1114
|
});
|
|
1274
1115
|
}
|
|
@@ -1280,69 +1121,63 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1280
1121
|
* individually intersected with the shared properties node to match the OAS pattern of
|
|
1281
1122
|
* adding common fields next to a discriminated union.
|
|
1282
1123
|
*/
|
|
1283
|
-
function convertUnion({ schema, name, nullable, defaultValue,
|
|
1124
|
+
function convertUnion({ schema, name, nullable, defaultValue, rawOptions }) {
|
|
1125
|
+
function pickDiscriminatorPropertyNode(node, propertyName) {
|
|
1126
|
+
const discriminatorProperty = narrowSchema(node, "object")?.properties?.find((property) => property.name === propertyName);
|
|
1127
|
+
if (!discriminatorProperty) return;
|
|
1128
|
+
return createSchema({
|
|
1129
|
+
type: "object",
|
|
1130
|
+
primitive: "object",
|
|
1131
|
+
properties: [discriminatorProperty]
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1284
1134
|
const unionMembers = [...schema.oneOf ?? [], ...schema.anyOf ?? []];
|
|
1285
1135
|
const unionBase = {
|
|
1286
1136
|
...renderSchemaBase(schema, name, nullable, defaultValue),
|
|
1287
1137
|
discriminatorPropertyName: isDiscriminator(schema) ? schema.discriminator.propertyName : void 0
|
|
1288
1138
|
};
|
|
1289
|
-
|
|
1139
|
+
const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
|
|
1140
|
+
const sharedPropertiesNode = schema.properties ? (() => {
|
|
1290
1141
|
const { oneOf: _oneOf, anyOf: _anyOf, ...schemaWithoutUnion } = schema;
|
|
1291
|
-
|
|
1292
|
-
const sharedPropertiesNode = convertSchema({
|
|
1142
|
+
return convertSchema({
|
|
1293
1143
|
schema: discriminator ? Object.fromEntries(Object.entries(schemaWithoutUnion).filter(([key]) => key !== "discriminator")) : schemaWithoutUnion,
|
|
1294
1144
|
name
|
|
1295
|
-
},
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
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({
|
|
1317
|
-
type: "union",
|
|
1318
|
-
...unionBase,
|
|
1319
|
-
members: unionMembers.map((s) => {
|
|
1145
|
+
}, rawOptions);
|
|
1146
|
+
})() : void 0;
|
|
1147
|
+
if (sharedPropertiesNode || discriminator?.mapping) {
|
|
1148
|
+
const members = unionMembers.map((s) => {
|
|
1320
1149
|
const ref = isReference(s) ? s.$ref : void 0;
|
|
1321
|
-
const discriminatorValue =
|
|
1322
|
-
const memberNode = convertSchema({ schema: s },
|
|
1323
|
-
if (!discriminatorValue) return memberNode;
|
|
1150
|
+
const discriminatorValue = findDiscriminator(discriminator?.mapping, ref);
|
|
1151
|
+
const memberNode = convertSchema({ schema: s }, rawOptions);
|
|
1152
|
+
if (!discriminatorValue || !discriminator) return memberNode;
|
|
1324
1153
|
return createSchema({
|
|
1325
1154
|
type: "intersection",
|
|
1326
|
-
members: [memberNode,
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
primitive: "string",
|
|
1334
|
-
enumValues: [discriminatorValue]
|
|
1335
|
-
}),
|
|
1336
|
-
required: true
|
|
1337
|
-
})]
|
|
1155
|
+
members: [memberNode, (sharedPropertiesNode ? pickDiscriminatorPropertyNode(setDiscriminatorEnum({
|
|
1156
|
+
node: sharedPropertiesNode,
|
|
1157
|
+
propertyName: discriminator.propertyName,
|
|
1158
|
+
values: [discriminatorValue]
|
|
1159
|
+
}), discriminator.propertyName) : void 0) ?? createDiscriminantNode({
|
|
1160
|
+
propertyName: discriminator.propertyName,
|
|
1161
|
+
value: discriminatorValue
|
|
1338
1162
|
})]
|
|
1339
1163
|
});
|
|
1340
|
-
})
|
|
1341
|
-
|
|
1164
|
+
});
|
|
1165
|
+
const unionNode = createSchema({
|
|
1166
|
+
type: "union",
|
|
1167
|
+
...unionBase,
|
|
1168
|
+
members
|
|
1169
|
+
});
|
|
1170
|
+
if (!sharedPropertiesNode) return unionNode;
|
|
1171
|
+
return createSchema({
|
|
1172
|
+
type: "intersection",
|
|
1173
|
+
...renderSchemaBase(schema, name, nullable, defaultValue),
|
|
1174
|
+
members: [unionNode, sharedPropertiesNode]
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1342
1177
|
return createSchema({
|
|
1343
1178
|
type: "union",
|
|
1344
1179
|
...unionBase,
|
|
1345
|
-
members:
|
|
1180
|
+
members: simplifyUnion(unionMembers.map((s) => convertSchema({ schema: s }, rawOptions)))
|
|
1346
1181
|
});
|
|
1347
1182
|
}
|
|
1348
1183
|
/**
|
|
@@ -1372,10 +1207,10 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1372
1207
|
* Returns `undefined` when the format should fall through to string handling
|
|
1373
1208
|
* (i.e. `format: 'date-time'` with `dateType: false`).
|
|
1374
1209
|
*/
|
|
1375
|
-
function convertFormat({ schema, name, nullable, defaultValue,
|
|
1210
|
+
function convertFormat({ schema, name, nullable, defaultValue, options }) {
|
|
1376
1211
|
const base = renderSchemaBase(schema, name, nullable, defaultValue);
|
|
1377
1212
|
if (schema.format === "int64") return createSchema({
|
|
1378
|
-
type:
|
|
1213
|
+
type: options.integerType === "bigint" ? "bigint" : "integer",
|
|
1379
1214
|
primitive: "integer",
|
|
1380
1215
|
...base,
|
|
1381
1216
|
min: schema.minimum,
|
|
@@ -1384,7 +1219,7 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1384
1219
|
exclusiveMaximum: typeof schema.exclusiveMaximum === "number" ? schema.exclusiveMaximum : void 0
|
|
1385
1220
|
});
|
|
1386
1221
|
if (schema.format === "date-time" || schema.format === "date" || schema.format === "time") {
|
|
1387
|
-
const dateType = getDateType(
|
|
1222
|
+
const dateType = getDateType(options, schema.format);
|
|
1388
1223
|
if (!dateType) return void 0;
|
|
1389
1224
|
if (dateType.type === "datetime") return createSchema({
|
|
1390
1225
|
...base,
|
|
@@ -1429,28 +1264,19 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1429
1264
|
* - Numeric and boolean enums require a const-map representation because most generators cannot
|
|
1430
1265
|
* use string-enum syntax for non-string values.
|
|
1431
1266
|
*/
|
|
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
|
-
}
|
|
1267
|
+
function convertEnum({ schema, name, nullable, type, rawOptions }) {
|
|
1268
|
+
if (type === "array") return convertSchema({
|
|
1269
|
+
schema: normalizeArrayEnum(schema),
|
|
1270
|
+
name
|
|
1271
|
+
}, rawOptions);
|
|
1447
1272
|
const nullInEnum = schema.enum.includes(null);
|
|
1448
1273
|
const filteredValues = nullInEnum ? schema.enum.filter((v) => v !== null) : schema.enum;
|
|
1449
1274
|
const enumNullable = nullable || nullInEnum || void 0;
|
|
1450
1275
|
const enumDefault = schema.default === null && enumNullable ? void 0 : schema.default;
|
|
1276
|
+
const enumPrimitive = getPrimitiveType(type);
|
|
1451
1277
|
const enumBase = {
|
|
1452
1278
|
type: "enum",
|
|
1453
|
-
primitive:
|
|
1279
|
+
primitive: enumPrimitive,
|
|
1454
1280
|
name,
|
|
1455
1281
|
title: schema.title,
|
|
1456
1282
|
description: schema.description,
|
|
@@ -1462,38 +1288,19 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1462
1288
|
example: schema.example
|
|
1463
1289
|
};
|
|
1464
1290
|
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";
|
|
1291
|
+
if (extensionKey || enumPrimitive === "number" || enumPrimitive === "integer" || enumPrimitive === "boolean") {
|
|
1292
|
+
const enumPrimitiveType = enumPrimitive === "number" || enumPrimitive === "integer" ? "number" : enumPrimitive === "boolean" ? "boolean" : "string";
|
|
1293
|
+
const sourceValues = extensionKey ? [...new Set(schema[extensionKey])] : [...new Set(filteredValues)];
|
|
1469
1294
|
return createSchema({
|
|
1470
1295
|
...enumBase,
|
|
1471
|
-
|
|
1472
|
-
namedEnumValues:
|
|
1296
|
+
primitive: enumPrimitiveType,
|
|
1297
|
+
namedEnumValues: sourceValues.map((label, index) => ({
|
|
1473
1298
|
name: String(label),
|
|
1474
|
-
value: filteredValues[index] ?? label,
|
|
1475
|
-
|
|
1299
|
+
value: extensionKey ? filteredValues[index] ?? label : label,
|
|
1300
|
+
primitive: enumPrimitiveType
|
|
1476
1301
|
}))
|
|
1477
1302
|
});
|
|
1478
1303
|
}
|
|
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
1304
|
return createSchema({
|
|
1498
1305
|
...enumBase,
|
|
1499
1306
|
enumValues: [...new Set(filteredValues)]
|
|
@@ -1511,57 +1318,18 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1511
1318
|
* - not required + not nullable → `optional: true`
|
|
1512
1319
|
* - not required + nullable → `nullish: true`
|
|
1513
1320
|
*/
|
|
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 }) {
|
|
1321
|
+
function convertObject({ schema, name, nullable, defaultValue, rawOptions, options }) {
|
|
1554
1322
|
const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
|
|
1555
1323
|
const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
|
|
1556
1324
|
const resolvedPropSchema = propSchema;
|
|
1557
1325
|
const propNullable = isNullable(resolvedPropSchema);
|
|
1558
|
-
let schemaNode =
|
|
1326
|
+
let schemaNode = setEnumName(convertSchema({
|
|
1559
1327
|
schema: resolvedPropSchema,
|
|
1560
|
-
name:
|
|
1561
|
-
},
|
|
1328
|
+
name: childName(name, propName)
|
|
1329
|
+
}, rawOptions), name, propName, options.enumSuffix);
|
|
1562
1330
|
const tupleNode = narrowSchema(schemaNode, "tuple");
|
|
1563
1331
|
if (tupleNode?.items) {
|
|
1564
|
-
const namedItems = tupleNode.items.map((item) =>
|
|
1332
|
+
const namedItems = tupleNode.items.map((item) => setEnumName(item, name, propName, options.enumSuffix));
|
|
1565
1333
|
if (namedItems.some((item, i) => item !== tupleNode.items[i])) schemaNode = {
|
|
1566
1334
|
...tupleNode,
|
|
1567
1335
|
items: namedItems
|
|
@@ -1579,11 +1347,11 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1579
1347
|
const additionalProperties = schema.additionalProperties;
|
|
1580
1348
|
let additionalPropertiesNode;
|
|
1581
1349
|
if (additionalProperties === true) additionalPropertiesNode = true;
|
|
1582
|
-
else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = convertSchema({ schema: additionalProperties },
|
|
1350
|
+
else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = convertSchema({ schema: additionalProperties }, rawOptions);
|
|
1583
1351
|
else if (additionalProperties === false) additionalPropertiesNode = void 0;
|
|
1584
|
-
else if (additionalProperties) additionalPropertiesNode = createSchema({ type: resolveTypeOption(
|
|
1352
|
+
else if (additionalProperties) additionalPropertiesNode = createSchema({ type: resolveTypeOption(options.unknownType) });
|
|
1585
1353
|
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(
|
|
1354
|
+
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
1355
|
const objectNode = createSchema({
|
|
1588
1356
|
type: "object",
|
|
1589
1357
|
primitive: "object",
|
|
@@ -1594,11 +1362,11 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1594
1362
|
});
|
|
1595
1363
|
if (isDiscriminator(schema) && schema.discriminator.mapping) {
|
|
1596
1364
|
const discPropName = schema.discriminator.propertyName;
|
|
1597
|
-
return
|
|
1365
|
+
return setDiscriminatorEnum({
|
|
1598
1366
|
node: objectNode,
|
|
1599
1367
|
propertyName: discPropName,
|
|
1600
1368
|
values: Object.keys(schema.discriminator.mapping),
|
|
1601
|
-
enumName: name ?
|
|
1369
|
+
enumName: name ? enumPropName(name, discPropName, options.enumSuffix) : void 0
|
|
1602
1370
|
});
|
|
1603
1371
|
}
|
|
1604
1372
|
return objectNode;
|
|
@@ -1611,12 +1379,12 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1611
1379
|
* a rest element of type `any` is emitted to match JSON Schema semantics (absent `items`
|
|
1612
1380
|
* means additional items are allowed).
|
|
1613
1381
|
*/
|
|
1614
|
-
function convertTuple({ schema, name, nullable, defaultValue,
|
|
1382
|
+
function convertTuple({ schema, name, nullable, defaultValue, rawOptions }) {
|
|
1615
1383
|
return createSchema({
|
|
1616
1384
|
type: "tuple",
|
|
1617
1385
|
primitive: "array",
|
|
1618
|
-
items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item },
|
|
1619
|
-
rest: schema.items ? convertSchema({ schema: schema.items },
|
|
1386
|
+
items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item }, rawOptions)),
|
|
1387
|
+
rest: schema.items ? convertSchema({ schema: schema.items }, rawOptions) : createSchema({ type: "any" }),
|
|
1620
1388
|
min: schema.minItems,
|
|
1621
1389
|
max: schema.maxItems,
|
|
1622
1390
|
...renderSchemaBase(schema, name, nullable, defaultValue)
|
|
@@ -1628,16 +1396,16 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1628
1396
|
* When the items schema is an inline enum, a name derived from the parent array's name and
|
|
1629
1397
|
* `enumSuffix` is forwarded so generators can emit a named enum declaration.
|
|
1630
1398
|
*/
|
|
1631
|
-
function convertArray({ schema, name, nullable, defaultValue,
|
|
1399
|
+
function convertArray({ schema, name, nullable, defaultValue, rawOptions, options }) {
|
|
1632
1400
|
const rawItems = schema.items;
|
|
1633
|
-
const itemName = rawItems?.enum?.length && name ?
|
|
1401
|
+
const itemName = rawItems?.enum?.length && name ? enumPropName(void 0, name, options.enumSuffix) : void 0;
|
|
1634
1402
|
return createSchema({
|
|
1635
1403
|
type: "array",
|
|
1636
1404
|
primitive: "array",
|
|
1637
1405
|
items: rawItems ? [convertSchema({
|
|
1638
1406
|
schema: rawItems,
|
|
1639
1407
|
name: itemName
|
|
1640
|
-
},
|
|
1408
|
+
}, rawOptions)] : [],
|
|
1641
1409
|
min: schema.minItems,
|
|
1642
1410
|
max: schema.maxItems,
|
|
1643
1411
|
unique: schema.uniqueItems ?? void 0,
|
|
@@ -1711,16 +1479,16 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1711
1479
|
* 10. Object / array / tuple / scalar by `type`
|
|
1712
1480
|
* 11. Empty schema fallback (`emptySchemaType` option)
|
|
1713
1481
|
*/
|
|
1714
|
-
function convertSchema({ schema, name },
|
|
1715
|
-
const
|
|
1482
|
+
function convertSchema({ schema, name }, rawOptions) {
|
|
1483
|
+
const options = {
|
|
1716
1484
|
...DEFAULT_PARSER_OPTIONS,
|
|
1717
|
-
...
|
|
1485
|
+
...rawOptions
|
|
1718
1486
|
};
|
|
1719
1487
|
const flattenedSchema = flattenSchema(schema);
|
|
1720
1488
|
if (flattenedSchema && flattenedSchema !== schema) return convertSchema({
|
|
1721
1489
|
schema: flattenedSchema,
|
|
1722
1490
|
name
|
|
1723
|
-
},
|
|
1491
|
+
}, rawOptions);
|
|
1724
1492
|
const nullable = isNullable(schema) || void 0;
|
|
1725
1493
|
const defaultValue = schema.default === null && nullable ? void 0 : schema.default;
|
|
1726
1494
|
const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
|
|
@@ -1730,8 +1498,8 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1730
1498
|
nullable,
|
|
1731
1499
|
defaultValue,
|
|
1732
1500
|
type,
|
|
1733
|
-
|
|
1734
|
-
|
|
1501
|
+
rawOptions,
|
|
1502
|
+
options
|
|
1735
1503
|
};
|
|
1736
1504
|
if (isReference(schema)) return convertRef(ctx);
|
|
1737
1505
|
if (schema.allOf?.length) return convertAllOf(ctx);
|
|
@@ -1757,7 +1525,7 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1757
1525
|
type: t
|
|
1758
1526
|
},
|
|
1759
1527
|
name
|
|
1760
|
-
},
|
|
1528
|
+
}, rawOptions)),
|
|
1761
1529
|
...renderSchemaBase(schema, name, arrayNullable, defaultValue)
|
|
1762
1530
|
});
|
|
1763
1531
|
}
|
|
@@ -1775,7 +1543,7 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1775
1543
|
if (type === "boolean") return convertBoolean(ctx);
|
|
1776
1544
|
if (type === "null") return convertNull(ctx);
|
|
1777
1545
|
return createSchema({
|
|
1778
|
-
type: resolveTypeOption(
|
|
1546
|
+
type: resolveTypeOption(options.emptySchemaType),
|
|
1779
1547
|
name,
|
|
1780
1548
|
title: schema.title,
|
|
1781
1549
|
description: schema.description
|
|
@@ -1861,34 +1629,12 @@ function createOasParser(oas, { contentType } = {}) {
|
|
|
1861
1629
|
operations: Object.entries(paths).flatMap(([_path, methods]) => Object.entries(methods).map(([, operation]) => operation ? parseOperation(mergedOptions, oas, operation) : null).filter((op) => op !== null))
|
|
1862
1630
|
});
|
|
1863
1631
|
}
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
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
|
-
}
|
|
1632
|
+
const resolveRefs = (node, resolveName, resolveEnumName) => resolveNames({
|
|
1633
|
+
node,
|
|
1634
|
+
nameMapping,
|
|
1635
|
+
resolveName,
|
|
1636
|
+
resolveEnumName
|
|
1637
|
+
});
|
|
1892
1638
|
return {
|
|
1893
1639
|
parse,
|
|
1894
1640
|
convertSchema,
|
|
@@ -1937,10 +1683,17 @@ const adapterOas = createAdapter((options) => {
|
|
|
1937
1683
|
nameMapping
|
|
1938
1684
|
},
|
|
1939
1685
|
getImports(node, resolve) {
|
|
1940
|
-
return
|
|
1686
|
+
return collectImports({
|
|
1941
1687
|
node,
|
|
1942
1688
|
nameMapping,
|
|
1943
|
-
resolve
|
|
1689
|
+
resolve: (schemaName) => {
|
|
1690
|
+
const result = resolve(schemaName);
|
|
1691
|
+
if (!result) return;
|
|
1692
|
+
return {
|
|
1693
|
+
name: [result.name],
|
|
1694
|
+
path: result.path
|
|
1695
|
+
};
|
|
1696
|
+
}
|
|
1944
1697
|
});
|
|
1945
1698
|
},
|
|
1946
1699
|
async parse(source) {
|