@kubb/adapter-oas 5.0.0-alpha.1 → 5.0.0-alpha.11
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 +432 -220
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +71 -27
- package/dist/index.js +433 -221
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/adapter.ts +28 -8
- package/src/constants.ts +19 -9
- package/src/oas/Oas.ts +16 -9
- package/src/oas/types.ts +19 -0
- package/src/oas/utils.ts +1 -1
- package/src/parser.ts +209 -228
- package/src/types.ts +41 -19
- package/src/utils.ts +168 -0
package/dist/index.cjs
CHANGED
|
@@ -39,6 +39,110 @@ jsonpointer = __toESM(jsonpointer);
|
|
|
39
39
|
let oas = require("oas");
|
|
40
40
|
oas = __toESM(oas);
|
|
41
41
|
let oas_utils = require("oas/utils");
|
|
42
|
+
//#region src/constants.ts
|
|
43
|
+
/**
|
|
44
|
+
* Default values for all `Options` fields.
|
|
45
|
+
*/
|
|
46
|
+
const DEFAULT_PARSER_OPTIONS = {
|
|
47
|
+
dateType: "string",
|
|
48
|
+
integerType: "number",
|
|
49
|
+
unknownType: "any",
|
|
50
|
+
emptySchemaType: "any",
|
|
51
|
+
enumSuffix: "enum"
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* OpenAPI version string written into merged document stubs.
|
|
55
|
+
*/
|
|
56
|
+
const MERGE_OPENAPI_VERSION = "3.0.0";
|
|
57
|
+
/**
|
|
58
|
+
* Fallback `info.title` used when merging multiple API documents.
|
|
59
|
+
*/
|
|
60
|
+
const MERGE_DEFAULT_TITLE = "Merged API";
|
|
61
|
+
/**
|
|
62
|
+
* Fallback `info.version` used when merging multiple API documents.
|
|
63
|
+
*/
|
|
64
|
+
const MERGE_DEFAULT_VERSION = "1.0.0";
|
|
65
|
+
/**
|
|
66
|
+
* JSON Schema keywords that indicate structural composition.
|
|
67
|
+
* A schema fragment containing any of these keys must not be inlined into its
|
|
68
|
+
* parent during `allOf` flattening — it carries semantic meaning of its own.
|
|
69
|
+
*/
|
|
70
|
+
const structuralKeys = new Set([
|
|
71
|
+
"properties",
|
|
72
|
+
"items",
|
|
73
|
+
"additionalProperties",
|
|
74
|
+
"oneOf",
|
|
75
|
+
"anyOf",
|
|
76
|
+
"allOf",
|
|
77
|
+
"not"
|
|
78
|
+
]);
|
|
79
|
+
/**
|
|
80
|
+
* Maps OAS/JSON Schema `format` strings to their Kubb `SchemaType` equivalents.
|
|
81
|
+
*
|
|
82
|
+
* Only formats that need a type different from the raw OAS `type` are listed.
|
|
83
|
+
* `int64`, `date-time`, `date`, and `time` are handled separately because their
|
|
84
|
+
* mapping depends on runtime parser options.
|
|
85
|
+
*
|
|
86
|
+
* Note: `ipv4`, `ipv6`, and `hostname` map to `'url'` — the closest supported
|
|
87
|
+
* scalar type in the Kubb AST, even though these are not strictly URLs.
|
|
88
|
+
*/
|
|
89
|
+
const formatMap = {
|
|
90
|
+
uuid: "uuid",
|
|
91
|
+
email: "email",
|
|
92
|
+
"idn-email": "email",
|
|
93
|
+
uri: "url",
|
|
94
|
+
"uri-reference": "url",
|
|
95
|
+
url: "url",
|
|
96
|
+
ipv4: "url",
|
|
97
|
+
ipv6: "url",
|
|
98
|
+
hostname: "url",
|
|
99
|
+
"idn-hostname": "url",
|
|
100
|
+
binary: "blob",
|
|
101
|
+
byte: "blob",
|
|
102
|
+
int32: "integer",
|
|
103
|
+
float: "number",
|
|
104
|
+
double: "number"
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Exhaustive list of media types that Kubb recognizes.
|
|
108
|
+
*/
|
|
109
|
+
const knownMediaTypes = new Set([
|
|
110
|
+
"application/json",
|
|
111
|
+
"application/xml",
|
|
112
|
+
"application/x-www-form-urlencoded",
|
|
113
|
+
"application/octet-stream",
|
|
114
|
+
"application/pdf",
|
|
115
|
+
"application/zip",
|
|
116
|
+
"application/graphql",
|
|
117
|
+
"multipart/form-data",
|
|
118
|
+
"text/plain",
|
|
119
|
+
"text/html",
|
|
120
|
+
"text/csv",
|
|
121
|
+
"text/xml",
|
|
122
|
+
"image/png",
|
|
123
|
+
"image/jpeg",
|
|
124
|
+
"image/gif",
|
|
125
|
+
"image/webp",
|
|
126
|
+
"image/svg+xml",
|
|
127
|
+
"audio/mpeg",
|
|
128
|
+
"video/mp4"
|
|
129
|
+
]);
|
|
130
|
+
/**
|
|
131
|
+
* Vendor extension keys used to attach human-readable labels to enum values.
|
|
132
|
+
* Checked in priority order: the first key found wins.
|
|
133
|
+
*/
|
|
134
|
+
const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
|
|
135
|
+
/**
|
|
136
|
+
* Scalar primitive schema types used for union member simplification.
|
|
137
|
+
*/
|
|
138
|
+
const SCALAR_PRIMITIVE_TYPES = new Set([
|
|
139
|
+
"string",
|
|
140
|
+
"number",
|
|
141
|
+
"integer",
|
|
142
|
+
"bigint",
|
|
143
|
+
"boolean"
|
|
144
|
+
]);
|
|
145
|
+
//#endregion
|
|
42
146
|
//#region src/oas/resolveServerUrl.ts
|
|
43
147
|
/**
|
|
44
148
|
* Resolves an OpenAPI server URL by substituting `{variable}` placeholders.
|
|
@@ -117,6 +221,27 @@ function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
|
|
|
117
221
|
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
|
|
118
222
|
}
|
|
119
223
|
//#endregion
|
|
224
|
+
//#region ../../internals/utils/src/names.ts
|
|
225
|
+
/**
|
|
226
|
+
* Returns a unique name by appending an incrementing numeric suffix when the name has already been used.
|
|
227
|
+
* Mutates `data` in-place as a usage counter so subsequent calls remain consistent.
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* const seen: Record<string, number> = {}
|
|
231
|
+
* getUniqueName('Foo', seen) // 'Foo'
|
|
232
|
+
* getUniqueName('Foo', seen) // 'Foo2'
|
|
233
|
+
* getUniqueName('Foo', seen) // 'Foo3'
|
|
234
|
+
*/
|
|
235
|
+
function getUniqueName(originalName, data) {
|
|
236
|
+
let used = data[originalName] || 0;
|
|
237
|
+
if (used) {
|
|
238
|
+
data[originalName] = ++used;
|
|
239
|
+
originalName += used;
|
|
240
|
+
}
|
|
241
|
+
data[originalName] = 1;
|
|
242
|
+
return originalName;
|
|
243
|
+
}
|
|
244
|
+
//#endregion
|
|
120
245
|
//#region ../../internals/utils/src/reserved.ts
|
|
121
246
|
/**
|
|
122
247
|
* Returns `true` when `name` is a syntactically valid JavaScript variable name.
|
|
@@ -233,91 +358,6 @@ var URLPath = class {
|
|
|
233
358
|
}
|
|
234
359
|
};
|
|
235
360
|
//#endregion
|
|
236
|
-
//#region src/constants.ts
|
|
237
|
-
/**
|
|
238
|
-
* OpenAPI version string written into merged document stubs.
|
|
239
|
-
*/
|
|
240
|
-
const MERGE_OPENAPI_VERSION = "3.0.0";
|
|
241
|
-
/**
|
|
242
|
-
* Fallback `info.title` used when merging multiple API documents.
|
|
243
|
-
*/
|
|
244
|
-
const MERGE_DEFAULT_TITLE = "Merged API";
|
|
245
|
-
/**
|
|
246
|
-
* Fallback `info.version` used when merging multiple API documents.
|
|
247
|
-
*/
|
|
248
|
-
const MERGE_DEFAULT_VERSION = "1.0.0";
|
|
249
|
-
/**
|
|
250
|
-
* JSON Schema keywords that indicate structural composition.
|
|
251
|
-
* A schema fragment containing any of these keys must not be inlined into its
|
|
252
|
-
* parent during `allOf` flattening — it carries semantic meaning of its own.
|
|
253
|
-
*/
|
|
254
|
-
const structuralKeys = new Set([
|
|
255
|
-
"properties",
|
|
256
|
-
"items",
|
|
257
|
-
"additionalProperties",
|
|
258
|
-
"oneOf",
|
|
259
|
-
"anyOf",
|
|
260
|
-
"allOf",
|
|
261
|
-
"not"
|
|
262
|
-
]);
|
|
263
|
-
/**
|
|
264
|
-
* Maps OAS/JSON Schema `format` strings to their Kubb `SchemaType` equivalents.
|
|
265
|
-
*
|
|
266
|
-
* Only formats that need a type different from the raw OAS `type` are listed.
|
|
267
|
-
* `int64`, `date-time`, `date`, and `time` are handled separately because their
|
|
268
|
-
* mapping depends on runtime parser options.
|
|
269
|
-
*
|
|
270
|
-
* Note: `ipv4`, `ipv6`, and `hostname` map to `'url'` — the closest supported
|
|
271
|
-
* scalar type in the Kubb AST, even though these are not strictly URLs.
|
|
272
|
-
*/
|
|
273
|
-
const formatMap = {
|
|
274
|
-
uuid: "uuid",
|
|
275
|
-
email: "email",
|
|
276
|
-
"idn-email": "email",
|
|
277
|
-
uri: "url",
|
|
278
|
-
"uri-reference": "url",
|
|
279
|
-
url: "url",
|
|
280
|
-
ipv4: "url",
|
|
281
|
-
ipv6: "url",
|
|
282
|
-
hostname: "url",
|
|
283
|
-
"idn-hostname": "url",
|
|
284
|
-
binary: "blob",
|
|
285
|
-
byte: "blob",
|
|
286
|
-
int32: "integer",
|
|
287
|
-
float: "number",
|
|
288
|
-
double: "number"
|
|
289
|
-
};
|
|
290
|
-
/**
|
|
291
|
-
* Exhaustive list of media types that Kubb recognizes.
|
|
292
|
-
* Kept as a module-level constant to avoid re-allocating the array on every call.
|
|
293
|
-
*/
|
|
294
|
-
const knownMediaTypes = [
|
|
295
|
-
"application/json",
|
|
296
|
-
"application/xml",
|
|
297
|
-
"application/x-www-form-urlencoded",
|
|
298
|
-
"application/octet-stream",
|
|
299
|
-
"application/pdf",
|
|
300
|
-
"application/zip",
|
|
301
|
-
"application/graphql",
|
|
302
|
-
"multipart/form-data",
|
|
303
|
-
"text/plain",
|
|
304
|
-
"text/html",
|
|
305
|
-
"text/csv",
|
|
306
|
-
"text/xml",
|
|
307
|
-
"image/png",
|
|
308
|
-
"image/jpeg",
|
|
309
|
-
"image/gif",
|
|
310
|
-
"image/webp",
|
|
311
|
-
"image/svg+xml",
|
|
312
|
-
"audio/mpeg",
|
|
313
|
-
"video/mp4"
|
|
314
|
-
];
|
|
315
|
-
/**
|
|
316
|
-
* Vendor extension keys used to attach human-readable labels to enum values.
|
|
317
|
-
* Checked in priority order: the first key found wins.
|
|
318
|
-
*/
|
|
319
|
-
const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
|
|
320
|
-
//#endregion
|
|
321
361
|
//#region src/oas/Oas.ts
|
|
322
362
|
/**
|
|
323
363
|
* Prefix used to create synthetic `$ref` values for anonymous (inline) discriminator schemas.
|
|
@@ -529,8 +569,15 @@ var Oas = class extends oas.default {
|
|
|
529
569
|
if (!schema) return;
|
|
530
570
|
return this.dereferenceWithRef(schema);
|
|
531
571
|
}
|
|
532
|
-
|
|
533
|
-
|
|
572
|
+
/**
|
|
573
|
+
* Returns all resolved parameters for an operation, merging path-level and operation-level
|
|
574
|
+
* parameters and deduplicating by `in:name` (operation-level takes precedence).
|
|
575
|
+
*
|
|
576
|
+
* oas v31+ filters out `$ref` parameters in `getParameters()`, so this method accesses the
|
|
577
|
+
* raw `operation.schema.parameters` and path-item parameters directly and resolves `$ref`
|
|
578
|
+
* pointers via `dereferenceWithRef` to preserve backward compatibility.
|
|
579
|
+
*/
|
|
580
|
+
getParameters(operation) {
|
|
534
581
|
const resolveParams = (params) => params.map((p) => this.dereferenceWithRef(p)).filter((p) => !!p && typeof p === "object" && "in" in p && "name" in p);
|
|
535
582
|
const operationParams = resolveParams(operation.schema?.parameters || []);
|
|
536
583
|
const pathItem = this.api?.paths?.[operation.path];
|
|
@@ -538,7 +585,11 @@ var Oas = class extends oas.default {
|
|
|
538
585
|
const paramMap = /* @__PURE__ */ new Map();
|
|
539
586
|
for (const p of pathLevelParams) if (p.name && p.in) paramMap.set(`${p.in}:${p.name}`, p);
|
|
540
587
|
for (const p of operationParams) if (p.name && p.in) paramMap.set(`${p.in}:${p.name}`, p);
|
|
541
|
-
|
|
588
|
+
return Array.from(paramMap.values());
|
|
589
|
+
}
|
|
590
|
+
getParametersSchema(operation, inKey) {
|
|
591
|
+
const { contentType = operation.getContentType() } = this.#options;
|
|
592
|
+
const params = this.getParameters(operation).filter((v) => v.in === inKey);
|
|
542
593
|
if (!params.length) return null;
|
|
543
594
|
return params.reduce((schema, pathParameters) => {
|
|
544
595
|
const property = pathParameters.content?.[contentType]?.schema ?? pathParameters.schema;
|
|
@@ -928,17 +979,137 @@ function resolveCollisions(schemasWithMeta) {
|
|
|
928
979
|
};
|
|
929
980
|
}
|
|
930
981
|
//#endregion
|
|
931
|
-
//#region src/
|
|
982
|
+
//#region src/utils.ts
|
|
932
983
|
/**
|
|
933
|
-
*
|
|
984
|
+
* Extracts the schema name from a `$ref` string.
|
|
985
|
+
* For `#/components/schemas/Order` this returns `'Order'`.
|
|
986
|
+
* Falls back to the full ref string when no slash is present.
|
|
934
987
|
*/
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
988
|
+
function extractRefName($ref) {
|
|
989
|
+
return $ref.split("/").at(-1) ?? $ref;
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* Replaces the discriminator property's schema inside an `ObjectSchemaNode`
|
|
993
|
+
* with an enum of the given `values`.
|
|
994
|
+
*
|
|
995
|
+
* - When `enumName` is provided the enum is named, which lets printers emit a
|
|
996
|
+
* standalone enum declaration + type reference (e.g. `PetTypeEnum`).
|
|
997
|
+
* - When `enumName` is omitted the enum stays anonymous, so printers inline it
|
|
998
|
+
* as a literal union (e.g. `'dog'`).
|
|
999
|
+
*
|
|
1000
|
+
* Returns the node unchanged when it is not an object or lacks the target property.
|
|
1001
|
+
*/
|
|
1002
|
+
function applyDiscriminatorEnum({ node, propertyName, values, enumName }) {
|
|
1003
|
+
if (node.type !== "object" || !node.properties?.length) return node;
|
|
1004
|
+
if (!node.properties.some((prop) => prop.name === propertyName)) return node;
|
|
1005
|
+
return (0, _kubb_ast.createSchema)({
|
|
1006
|
+
...node,
|
|
1007
|
+
properties: node.properties.map((prop) => {
|
|
1008
|
+
if (prop.name !== propertyName) return prop;
|
|
1009
|
+
const enumSchema = (0, _kubb_ast.createSchema)({
|
|
1010
|
+
type: "enum",
|
|
1011
|
+
primitive: "string",
|
|
1012
|
+
enumValues: values,
|
|
1013
|
+
name: enumName,
|
|
1014
|
+
readOnly: prop.schema.readOnly,
|
|
1015
|
+
writeOnly: prop.schema.writeOnly
|
|
1016
|
+
});
|
|
1017
|
+
return (0, _kubb_ast.createProperty)({
|
|
1018
|
+
...prop,
|
|
1019
|
+
schema: enumSchema
|
|
1020
|
+
});
|
|
1021
|
+
})
|
|
1022
|
+
});
|
|
1023
|
+
}
|
|
1024
|
+
/**
|
|
1025
|
+
* Merges consecutive anonymous (`name`-less) `ObjectSchemaNode`s in `members` into a
|
|
1026
|
+
* single object by combining their `properties` arrays.
|
|
1027
|
+
*
|
|
1028
|
+
* Only adjacent pairs are merged — non-object or named nodes act as boundaries.
|
|
1029
|
+
* This collapses patterns like `Address & { streetNumber } & { streetName }` into
|
|
1030
|
+
* `Address & { streetNumber; streetName }`.
|
|
1031
|
+
*/
|
|
1032
|
+
function mergeAdjacentAnonymousObjects(members) {
|
|
1033
|
+
return members.reduce((acc, member) => {
|
|
1034
|
+
const obj = (0, _kubb_ast.narrowSchema)(member, "object");
|
|
1035
|
+
if (obj && !obj.name) {
|
|
1036
|
+
const prev = acc[acc.length - 1];
|
|
1037
|
+
const prevObj = prev ? (0, _kubb_ast.narrowSchema)(prev, "object") : null;
|
|
1038
|
+
if (prevObj && !prevObj.name) {
|
|
1039
|
+
acc[acc.length - 1] = (0, _kubb_ast.createSchema)({
|
|
1040
|
+
...prevObj,
|
|
1041
|
+
properties: [...prevObj.properties ?? [], ...obj.properties ?? []]
|
|
1042
|
+
});
|
|
1043
|
+
return acc;
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
acc.push(member);
|
|
1047
|
+
return acc;
|
|
1048
|
+
}, []);
|
|
1049
|
+
}
|
|
1050
|
+
/**
|
|
1051
|
+
* Simplifies a union member list by removing `enum` nodes whose `primitive` type is
|
|
1052
|
+
* already represented by a broader scalar node in the same union.
|
|
1053
|
+
*
|
|
1054
|
+
* For example `['placed', 'approved'] | string` collapses to `string` because
|
|
1055
|
+
* `string` subsumes all string literals. `'' | string` similarly becomes `string`.
|
|
1056
|
+
*
|
|
1057
|
+
* Only scalar primitives (`string`, `number`, `integer`, `bigint`, `boolean`) are
|
|
1058
|
+
* considered — object, array, and ref members are left untouched.
|
|
1059
|
+
*
|
|
1060
|
+
* Const-derived enums (those without an `enumType`, produced from an OpenAPI `const`
|
|
1061
|
+
* keyword) are **never** removed — `'accepted' | string` must stay as-is because the
|
|
1062
|
+
* literal is intentional.
|
|
1063
|
+
*/
|
|
1064
|
+
function simplifyUnionMembers(members) {
|
|
1065
|
+
const scalarPrimitives = new Set(members.filter((m) => SCALAR_PRIMITIVE_TYPES.has(m.type)).map((m) => m.type));
|
|
1066
|
+
if (!scalarPrimitives.size) return members;
|
|
1067
|
+
return members.filter((m) => {
|
|
1068
|
+
if (m.type !== "enum") return true;
|
|
1069
|
+
const prim = m.primitive;
|
|
1070
|
+
if (!prim) return true;
|
|
1071
|
+
if (!m.enumType) return true;
|
|
1072
|
+
if (scalarPrimitives.has(prim)) return false;
|
|
1073
|
+
if ((prim === "integer" || prim === "number") && (scalarPrimitives.has("integer") || scalarPrimitives.has("number"))) return false;
|
|
1074
|
+
return true;
|
|
1075
|
+
});
|
|
1076
|
+
}
|
|
1077
|
+
/**
|
|
1078
|
+
* `nameMapping`, and calls `resolve` to obtain the `{ name, path }` pair for
|
|
1079
|
+
* each import. When `oas` is supplied, only `$ref`s that are resolvable in the
|
|
1080
|
+
* spec are included; omit it to skip the existence check.
|
|
1081
|
+
*
|
|
1082
|
+
* This function is the pure, state-free alternative to `OasParser.getImports`.
|
|
1083
|
+
* Because it receives `nameMapping` explicitly it can be called without holding
|
|
1084
|
+
* a reference to the parser or the OAS instance.
|
|
1085
|
+
*
|
|
1086
|
+
* @example
|
|
1087
|
+
* ```ts
|
|
1088
|
+
* // Use adapter state directly — no parser reference needed
|
|
1089
|
+
* const imports = getImports({
|
|
1090
|
+
* node: schemaNode,
|
|
1091
|
+
* nameMapping: adapter.options.nameMapping,
|
|
1092
|
+
* resolve: (schemaName) => ({
|
|
1093
|
+
* name: schemaManager.getName(schemaName, { type: 'type' }),
|
|
1094
|
+
* path: schemaManager.getFile(schemaName).path,
|
|
1095
|
+
* }),
|
|
1096
|
+
* })
|
|
1097
|
+
* ```
|
|
1098
|
+
*/
|
|
1099
|
+
function getImports({ node, nameMapping, resolve }) {
|
|
1100
|
+
return (0, _kubb_ast.collect)(node, { schema(schemaNode) {
|
|
1101
|
+
if (schemaNode.type !== "ref" || !schemaNode.ref) return;
|
|
1102
|
+
const rawName = extractRefName(schemaNode.ref);
|
|
1103
|
+
const result = resolve(nameMapping.get(rawName) ?? rawName);
|
|
1104
|
+
if (!result) return;
|
|
1105
|
+
return {
|
|
1106
|
+
name: [result.name],
|
|
1107
|
+
path: result.path
|
|
1108
|
+
};
|
|
1109
|
+
} });
|
|
1110
|
+
}
|
|
1111
|
+
//#endregion
|
|
1112
|
+
//#region src/parser.ts
|
|
942
1113
|
/**
|
|
943
1114
|
* Looks up the Kubb `SchemaType` for a given OAS `format` string.
|
|
944
1115
|
* Returns `undefined` for formats not in `formatMap` (e.g. `int64`, `date-time`),
|
|
@@ -948,14 +1119,6 @@ function formatToSchemaType(format) {
|
|
|
948
1119
|
return formatMap[format];
|
|
949
1120
|
}
|
|
950
1121
|
/**
|
|
951
|
-
* Extracts the final path segment of a JSON Pointer `$ref` string.
|
|
952
|
-
* For `#/components/schemas/Order` this returns `'Order'`.
|
|
953
|
-
* Falls back to the full ref string when no slash is present.
|
|
954
|
-
*/
|
|
955
|
-
function extractRefName($ref) {
|
|
956
|
-
return $ref.split("/").at(-1) ?? $ref;
|
|
957
|
-
}
|
|
958
|
-
/**
|
|
959
1122
|
* Maps an OAS primitive type string to its `PrimitiveSchemaType` equivalent.
|
|
960
1123
|
* Numeric types (`number`, `integer`, `bigint`) are returned unchanged;
|
|
961
1124
|
* `boolean` maps to `'boolean'`; everything else defaults to `'string'`.
|
|
@@ -970,27 +1133,7 @@ function getPrimitiveType(type) {
|
|
|
970
1133
|
* Returns `undefined` for content types not present in `KNOWN_MEDIA_TYPES`.
|
|
971
1134
|
*/
|
|
972
1135
|
function toMediaType(contentType) {
|
|
973
|
-
return knownMediaTypes.
|
|
974
|
-
}
|
|
975
|
-
/**
|
|
976
|
-
* When a discriminator is present, replaces the discriminator property's schema with
|
|
977
|
-
* an enum of the mapping keys so downstream code emits a precise literal-union type.
|
|
978
|
-
* Returns the original schema unchanged when there is no discriminator or no mapping.
|
|
979
|
-
*/
|
|
980
|
-
function applyDiscriminatorEnum(schema) {
|
|
981
|
-
if (!isDiscriminator(schema)) return schema;
|
|
982
|
-
const propName = schema.discriminator.propertyName;
|
|
983
|
-
if (!schema.properties?.[propName]) return schema;
|
|
984
|
-
return {
|
|
985
|
-
...schema,
|
|
986
|
-
properties: {
|
|
987
|
-
...schema.properties,
|
|
988
|
-
[propName]: {
|
|
989
|
-
...schema.properties[propName],
|
|
990
|
-
enum: schema.discriminator.mapping ? Object.keys(schema.discriminator.mapping) : void 0
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
};
|
|
1136
|
+
return knownMediaTypes.has(contentType) ? contentType : void 0;
|
|
994
1137
|
}
|
|
995
1138
|
/**
|
|
996
1139
|
* Creates an OAS parser that converts an OpenAPI/Swagger spec into
|
|
@@ -1016,6 +1159,8 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1016
1159
|
contentType,
|
|
1017
1160
|
collisionDetection
|
|
1018
1161
|
});
|
|
1162
|
+
const usedEnumNames = {};
|
|
1163
|
+
const isLegacyNaming = collisionDetection === false;
|
|
1019
1164
|
/**
|
|
1020
1165
|
* Maps an `'any' | 'unknown' | 'void'` option string to the corresponding `SchemaType` constant.
|
|
1021
1166
|
* Used for both `unknownType` (unannotated schemas) and `emptySchemaType` (empty `{}` schemas).
|
|
@@ -1062,7 +1207,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1062
1207
|
* Shared metadata fields included in every `createSchema` call.
|
|
1063
1208
|
* Centralizes the common properties so sub-handlers don't repeat them.
|
|
1064
1209
|
*/
|
|
1065
|
-
function
|
|
1210
|
+
function renderSchemaBase(schema, name, nullable, defaultValue) {
|
|
1066
1211
|
return {
|
|
1067
1212
|
name,
|
|
1068
1213
|
nullable,
|
|
@@ -1083,18 +1228,17 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1083
1228
|
* reflected in generated JSDoc and type modifiers.
|
|
1084
1229
|
*/
|
|
1085
1230
|
function convertRef({ schema, nullable, defaultValue }) {
|
|
1086
|
-
const schemaObject = schema;
|
|
1087
1231
|
return (0, _kubb_ast.createSchema)({
|
|
1088
1232
|
type: "ref",
|
|
1089
|
-
name: extractRefName(
|
|
1090
|
-
ref:
|
|
1233
|
+
name: extractRefName(schema.$ref),
|
|
1234
|
+
ref: schema.$ref,
|
|
1091
1235
|
nullable,
|
|
1092
|
-
description:
|
|
1093
|
-
deprecated:
|
|
1094
|
-
readOnly:
|
|
1095
|
-
writeOnly:
|
|
1096
|
-
pattern:
|
|
1097
|
-
example:
|
|
1236
|
+
description: schema.description,
|
|
1237
|
+
deprecated: schema.deprecated,
|
|
1238
|
+
readOnly: schema.readOnly,
|
|
1239
|
+
writeOnly: schema.writeOnly,
|
|
1240
|
+
pattern: schema.type === "string" ? schema.pattern : void 0,
|
|
1241
|
+
example: schema.example,
|
|
1098
1242
|
default: defaultValue
|
|
1099
1243
|
});
|
|
1100
1244
|
}
|
|
@@ -1145,6 +1289,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1145
1289
|
const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
|
|
1146
1290
|
return !inOneOf && !inMapping;
|
|
1147
1291
|
}).map((s) => convertSchema({ schema: s }, options));
|
|
1292
|
+
const syntheticStart = allOfMembers.length;
|
|
1148
1293
|
if (Array.isArray(schema.required) && schema.required.length) {
|
|
1149
1294
|
const outerKeys = schema.properties ? new Set(Object.keys(schema.properties)) : /* @__PURE__ */ new Set();
|
|
1150
1295
|
const missingRequired = schema.required.filter((key) => !outerKeys.has(key));
|
|
@@ -1169,8 +1314,8 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1169
1314
|
}
|
|
1170
1315
|
return (0, _kubb_ast.createSchema)({
|
|
1171
1316
|
type: "intersection",
|
|
1172
|
-
members: allOfMembers,
|
|
1173
|
-
...
|
|
1317
|
+
members: [...allOfMembers.slice(0, syntheticStart), ...mergeAdjacentAnonymousObjects(allOfMembers.slice(syntheticStart))],
|
|
1318
|
+
...renderSchemaBase(schema, name, nullable, defaultValue)
|
|
1174
1319
|
});
|
|
1175
1320
|
}
|
|
1176
1321
|
/**
|
|
@@ -1184,25 +1329,39 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1184
1329
|
function convertUnion({ schema, name, nullable, defaultValue, options }) {
|
|
1185
1330
|
const unionMembers = [...schema.oneOf ?? [], ...schema.anyOf ?? []];
|
|
1186
1331
|
const unionBase = {
|
|
1187
|
-
...
|
|
1332
|
+
...renderSchemaBase(schema, name, nullable, defaultValue),
|
|
1188
1333
|
discriminatorPropertyName: isDiscriminator(schema) ? schema.discriminator.propertyName : void 0
|
|
1189
1334
|
};
|
|
1190
1335
|
if (schema.properties) {
|
|
1191
1336
|
const { oneOf: _oneOf, anyOf: _anyOf, ...schemaWithoutUnion } = schema;
|
|
1192
|
-
const
|
|
1337
|
+
const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
|
|
1338
|
+
const sharedPropertiesNode = convertSchema({
|
|
1339
|
+
schema: discriminator ? Object.fromEntries(Object.entries(schemaWithoutUnion).filter(([key]) => key !== "discriminator")) : schemaWithoutUnion,
|
|
1340
|
+
name: isLegacyNaming ? void 0 : name
|
|
1341
|
+
}, options);
|
|
1193
1342
|
return (0, _kubb_ast.createSchema)({
|
|
1194
1343
|
type: "union",
|
|
1195
1344
|
...unionBase,
|
|
1196
|
-
members: unionMembers.map((s) =>
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1345
|
+
members: unionMembers.map((s) => {
|
|
1346
|
+
const ref = isReference(s) ? s.$ref : void 0;
|
|
1347
|
+
const discriminatorValue = discriminator?.mapping && ref ? Object.entries(discriminator.mapping).find(([, v]) => v === ref)?.[0] : void 0;
|
|
1348
|
+
let propertiesNode = sharedPropertiesNode;
|
|
1349
|
+
if (discriminatorValue && discriminator) propertiesNode = applyDiscriminatorEnum({
|
|
1350
|
+
node: propertiesNode,
|
|
1351
|
+
propertyName: discriminator.propertyName,
|
|
1352
|
+
values: [discriminatorValue]
|
|
1353
|
+
});
|
|
1354
|
+
return (0, _kubb_ast.createSchema)({
|
|
1355
|
+
type: "intersection",
|
|
1356
|
+
members: [convertSchema({ schema: s }, options), propertiesNode]
|
|
1357
|
+
});
|
|
1358
|
+
})
|
|
1200
1359
|
});
|
|
1201
1360
|
}
|
|
1202
1361
|
return (0, _kubb_ast.createSchema)({
|
|
1203
1362
|
type: "union",
|
|
1204
1363
|
...unionBase,
|
|
1205
|
-
members: unionMembers.map((s) => convertSchema({ schema: s }, options))
|
|
1364
|
+
members: simplifyUnionMembers(unionMembers.map((s) => convertSchema({ schema: s }, options)))
|
|
1206
1365
|
});
|
|
1207
1366
|
}
|
|
1208
1367
|
/**
|
|
@@ -1225,7 +1384,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1225
1384
|
type: "enum",
|
|
1226
1385
|
primitive: getPrimitiveType(typeof constValue === "number" ? "number" : typeof constValue === "boolean" ? "boolean" : "string"),
|
|
1227
1386
|
enumValues: [constValue],
|
|
1228
|
-
...
|
|
1387
|
+
...renderSchemaBase(schema, name, nullable, defaultValue)
|
|
1229
1388
|
});
|
|
1230
1389
|
}
|
|
1231
1390
|
/**
|
|
@@ -1234,7 +1393,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1234
1393
|
* (i.e. `format: 'date-time'` with `dateType: false`).
|
|
1235
1394
|
*/
|
|
1236
1395
|
function convertFormat({ schema, name, nullable, defaultValue, mergedOptions }) {
|
|
1237
|
-
const base =
|
|
1396
|
+
const base = renderSchemaBase(schema, name, nullable, defaultValue);
|
|
1238
1397
|
if (schema.format === "int64") return (0, _kubb_ast.createSchema)({
|
|
1239
1398
|
type: mergedOptions.integerType === "bigint" ? "bigint" : "integer",
|
|
1240
1399
|
primitive: "integer",
|
|
@@ -1269,6 +1428,11 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1269
1428
|
primitive: specialPrimitive,
|
|
1270
1429
|
type: specialType
|
|
1271
1430
|
});
|
|
1431
|
+
if (specialType === "url") return (0, _kubb_ast.createSchema)({
|
|
1432
|
+
...base,
|
|
1433
|
+
primitive: "string",
|
|
1434
|
+
type: "url"
|
|
1435
|
+
});
|
|
1272
1436
|
return (0, _kubb_ast.createSchema)({
|
|
1273
1437
|
...base,
|
|
1274
1438
|
primitive: specialPrimitive,
|
|
@@ -1287,9 +1451,8 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1287
1451
|
*/
|
|
1288
1452
|
function convertEnum({ schema, name, nullable, type, options }) {
|
|
1289
1453
|
if (type === "array") {
|
|
1290
|
-
const rawSchema = schema;
|
|
1291
1454
|
const normalizedItems = {
|
|
1292
|
-
...typeof
|
|
1455
|
+
...typeof schema.items === "object" && !Array.isArray(schema.items) ? schema.items : {},
|
|
1293
1456
|
enum: schema.enum
|
|
1294
1457
|
};
|
|
1295
1458
|
const { enum: _enum, ...schemaWithoutEnum } = schema;
|
|
@@ -1368,23 +1531,62 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1368
1531
|
* - not required + not nullable → `optional: true`
|
|
1369
1532
|
* - not required + nullable → `nullish: true`
|
|
1370
1533
|
*/
|
|
1534
|
+
/**
|
|
1535
|
+
* Builds the propagation name for a child property during recursive schema conversion.
|
|
1536
|
+
*
|
|
1537
|
+
* - **Legacy naming** (`isLegacyNaming`): only the immediate property key is used
|
|
1538
|
+
* (e.g. `Params` for property `params`), keeping nested names short.
|
|
1539
|
+
* - **Default naming**: the parent name is prepended so the full path is encoded
|
|
1540
|
+
* (e.g. `OrderParams` when parent is `Order`).
|
|
1541
|
+
*/
|
|
1542
|
+
function resolveChildName(parentName, propName) {
|
|
1543
|
+
if (isLegacyNaming) return pascalCase(propName);
|
|
1544
|
+
return parentName ? pascalCase([parentName, propName].join(" ")) : void 0;
|
|
1545
|
+
}
|
|
1546
|
+
/**
|
|
1547
|
+
* Derives the final name for an enum property schema node.
|
|
1548
|
+
*
|
|
1549
|
+
* The raw name always includes the enum suffix (e.g. `StatusEnum`).
|
|
1550
|
+
* In legacy mode an additional deduplication step appends a numeric suffix
|
|
1551
|
+
* when the same name has already been used (e.g. `ParamsStatusEnum2`).
|
|
1552
|
+
*/
|
|
1553
|
+
function resolveEnumPropName(parentName, propName, enumSuffix) {
|
|
1554
|
+
const raw = pascalCase([
|
|
1555
|
+
parentName,
|
|
1556
|
+
propName,
|
|
1557
|
+
enumSuffix
|
|
1558
|
+
].filter(Boolean).join(" "));
|
|
1559
|
+
return isLegacyNaming ? getUniqueName(raw, usedEnumNames) : raw;
|
|
1560
|
+
}
|
|
1561
|
+
/**
|
|
1562
|
+
* Given a freshly-converted property schema, returns the node with a correct
|
|
1563
|
+
* `name` attached — or stripped — depending on whether the node is a named
|
|
1564
|
+
* enum, a boolean const-enum (always inlined), or a regular schema.
|
|
1565
|
+
*/
|
|
1566
|
+
function applyEnumName(propNode, parentName, propName, enumSuffix) {
|
|
1567
|
+
const enumNode = (0, _kubb_ast.narrowSchema)(propNode, "enum");
|
|
1568
|
+
if (enumNode?.primitive === "boolean") return {
|
|
1569
|
+
...propNode,
|
|
1570
|
+
name: void 0
|
|
1571
|
+
};
|
|
1572
|
+
if (enumNode) return {
|
|
1573
|
+
...propNode,
|
|
1574
|
+
name: resolveEnumPropName(parentName, propName, enumSuffix)
|
|
1575
|
+
};
|
|
1576
|
+
return propNode;
|
|
1577
|
+
}
|
|
1371
1578
|
function convertObject({ schema, name, nullable, defaultValue, options, mergedOptions }) {
|
|
1372
|
-
const
|
|
1373
|
-
|
|
1374
|
-
const required = Array.isArray(resolvedSchema.required) ? resolvedSchema.required.includes(propName) : !!resolvedSchema.required;
|
|
1579
|
+
const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
|
|
1580
|
+
const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
|
|
1375
1581
|
const resolvedPropSchema = propSchema;
|
|
1376
1582
|
const propNullable = isNullable(resolvedPropSchema);
|
|
1377
1583
|
return (0, _kubb_ast.createProperty)({
|
|
1378
1584
|
name: propName,
|
|
1379
1585
|
schema: {
|
|
1380
|
-
...convertSchema({
|
|
1586
|
+
...applyEnumName(convertSchema({
|
|
1381
1587
|
schema: resolvedPropSchema,
|
|
1382
|
-
name: name
|
|
1383
|
-
|
|
1384
|
-
propName,
|
|
1385
|
-
mergedOptions.enumSuffix
|
|
1386
|
-
].filter(Boolean).join(" ")) : void 0
|
|
1387
|
-
}, options),
|
|
1588
|
+
name: resolveChildName(name, propName)
|
|
1589
|
+
}, options), name, propName, mergedOptions.enumSuffix),
|
|
1388
1590
|
nullable: propNullable || void 0,
|
|
1389
1591
|
optional: !required && !propNullable ? true : void 0,
|
|
1390
1592
|
nullish: !required && propNullable ? true : void 0
|
|
@@ -1392,22 +1594,32 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1392
1594
|
required
|
|
1393
1595
|
});
|
|
1394
1596
|
}) : [];
|
|
1395
|
-
const additionalProperties =
|
|
1597
|
+
const additionalProperties = schema.additionalProperties;
|
|
1396
1598
|
let additionalPropertiesNode;
|
|
1397
1599
|
if (additionalProperties === true) additionalPropertiesNode = true;
|
|
1398
1600
|
else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = convertSchema({ schema: additionalProperties }, options);
|
|
1399
1601
|
else if (additionalProperties === false) additionalPropertiesNode = void 0;
|
|
1400
1602
|
else if (additionalProperties) additionalPropertiesNode = (0, _kubb_ast.createSchema)({ type: resolveTypeOption(mergedOptions.unknownType) });
|
|
1401
|
-
const rawPatternProperties = "patternProperties" in
|
|
1402
|
-
const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || Object.keys(patternSchema).length === 0 ? (0, _kubb_ast.createSchema)({ type: resolveTypeOption(mergedOptions.unknownType) }) : convertSchema({ schema: patternSchema }, options)])) : void 0;
|
|
1403
|
-
|
|
1603
|
+
const rawPatternProperties = "patternProperties" in schema ? schema.patternProperties : void 0;
|
|
1604
|
+
const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || typeof patternSchema === "object" && Object.keys(patternSchema).length === 0 ? (0, _kubb_ast.createSchema)({ type: resolveTypeOption(mergedOptions.unknownType) }) : convertSchema({ schema: patternSchema }, options)])) : void 0;
|
|
1605
|
+
const objectNode = (0, _kubb_ast.createSchema)({
|
|
1404
1606
|
type: "object",
|
|
1405
1607
|
primitive: "object",
|
|
1406
1608
|
properties,
|
|
1407
1609
|
additionalProperties: additionalPropertiesNode,
|
|
1408
1610
|
patternProperties,
|
|
1409
|
-
...
|
|
1611
|
+
...renderSchemaBase(schema, name, nullable, defaultValue)
|
|
1410
1612
|
});
|
|
1613
|
+
if (isDiscriminator(schema) && schema.discriminator.mapping) {
|
|
1614
|
+
const discPropName = schema.discriminator.propertyName;
|
|
1615
|
+
return applyDiscriminatorEnum({
|
|
1616
|
+
node: objectNode,
|
|
1617
|
+
propertyName: discPropName,
|
|
1618
|
+
values: Object.keys(schema.discriminator.mapping),
|
|
1619
|
+
enumName: name ? resolveEnumPropName(name, discPropName, mergedOptions.enumSuffix) : void 0
|
|
1620
|
+
});
|
|
1621
|
+
}
|
|
1622
|
+
return objectNode;
|
|
1411
1623
|
}
|
|
1412
1624
|
/**
|
|
1413
1625
|
* Converts an OAS 3.1 `prefixItems` tuple into a `TupleSchemaNode`.
|
|
@@ -1416,15 +1628,14 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1416
1628
|
* after the prefix items is mapped to the rest parameter of the tuple.
|
|
1417
1629
|
*/
|
|
1418
1630
|
function convertTuple({ schema, name, nullable, defaultValue, options }) {
|
|
1419
|
-
const rawSchema = schema;
|
|
1420
1631
|
return (0, _kubb_ast.createSchema)({
|
|
1421
1632
|
type: "tuple",
|
|
1422
1633
|
primitive: "array",
|
|
1423
|
-
items:
|
|
1424
|
-
rest:
|
|
1634
|
+
items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item }, options)),
|
|
1635
|
+
rest: schema.items ? convertSchema({ schema: schema.items }, options) : void 0,
|
|
1425
1636
|
min: schema.minItems,
|
|
1426
1637
|
max: schema.maxItems,
|
|
1427
|
-
...
|
|
1638
|
+
...renderSchemaBase(schema, name, nullable, defaultValue)
|
|
1428
1639
|
});
|
|
1429
1640
|
}
|
|
1430
1641
|
/**
|
|
@@ -1434,19 +1645,19 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1434
1645
|
* `enumSuffix` is forwarded so generators can emit a named enum declaration.
|
|
1435
1646
|
*/
|
|
1436
1647
|
function convertArray({ schema, name, nullable, defaultValue, options, mergedOptions }) {
|
|
1437
|
-
const
|
|
1438
|
-
const itemName =
|
|
1648
|
+
const rawItems = schema.items;
|
|
1649
|
+
const itemName = rawItems?.enum?.length && name ? resolveEnumPropName(void 0, name, mergedOptions.enumSuffix) : void 0;
|
|
1439
1650
|
return (0, _kubb_ast.createSchema)({
|
|
1440
1651
|
type: "array",
|
|
1441
1652
|
primitive: "array",
|
|
1442
|
-
items:
|
|
1443
|
-
schema:
|
|
1653
|
+
items: rawItems ? [convertSchema({
|
|
1654
|
+
schema: rawItems,
|
|
1444
1655
|
name: itemName
|
|
1445
1656
|
}, options)] : [],
|
|
1446
1657
|
min: schema.minItems,
|
|
1447
1658
|
max: schema.maxItems,
|
|
1448
1659
|
unique: schema.uniqueItems ?? void 0,
|
|
1449
|
-
...
|
|
1660
|
+
...renderSchemaBase(schema, name, nullable, defaultValue)
|
|
1450
1661
|
});
|
|
1451
1662
|
}
|
|
1452
1663
|
/**
|
|
@@ -1459,7 +1670,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1459
1670
|
min: schema.minLength,
|
|
1460
1671
|
max: schema.maxLength,
|
|
1461
1672
|
pattern: schema.pattern,
|
|
1462
|
-
...
|
|
1673
|
+
...renderSchemaBase(schema, name, nullable, defaultValue)
|
|
1463
1674
|
});
|
|
1464
1675
|
}
|
|
1465
1676
|
/**
|
|
@@ -1473,7 +1684,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1473
1684
|
max: schema.maximum,
|
|
1474
1685
|
exclusiveMinimum: typeof schema.exclusiveMinimum === "number" ? schema.exclusiveMinimum : void 0,
|
|
1475
1686
|
exclusiveMaximum: typeof schema.exclusiveMaximum === "number" ? schema.exclusiveMaximum : void 0,
|
|
1476
|
-
...
|
|
1687
|
+
...renderSchemaBase(schema, name, nullable, defaultValue)
|
|
1477
1688
|
});
|
|
1478
1689
|
}
|
|
1479
1690
|
/**
|
|
@@ -1483,7 +1694,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1483
1694
|
return (0, _kubb_ast.createSchema)({
|
|
1484
1695
|
type: "boolean",
|
|
1485
1696
|
primitive: "boolean",
|
|
1486
|
-
...
|
|
1697
|
+
...renderSchemaBase(schema, name, nullable, defaultValue)
|
|
1487
1698
|
});
|
|
1488
1699
|
}
|
|
1489
1700
|
/**
|
|
@@ -1518,7 +1729,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1518
1729
|
*/
|
|
1519
1730
|
function convertSchema({ schema, name }, options) {
|
|
1520
1731
|
const mergedOptions = {
|
|
1521
|
-
...
|
|
1732
|
+
...DEFAULT_PARSER_OPTIONS,
|
|
1522
1733
|
...options
|
|
1523
1734
|
};
|
|
1524
1735
|
const flattenedSchema = flattenSchema(schema);
|
|
@@ -1549,18 +1760,21 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1549
1760
|
if (schema.type === "string" && schema.contentMediaType === "application/octet-stream") return (0, _kubb_ast.createSchema)({
|
|
1550
1761
|
type: "blob",
|
|
1551
1762
|
primitive: "string",
|
|
1552
|
-
...
|
|
1763
|
+
...renderSchemaBase(schema, name, nullable, defaultValue)
|
|
1553
1764
|
});
|
|
1554
1765
|
if (Array.isArray(schema.type) && schema.type.length > 1) {
|
|
1555
1766
|
const nonNullTypes = schema.type.filter((t) => t !== "null");
|
|
1556
1767
|
const arrayNullable = schema.type.includes("null") || nullable || void 0;
|
|
1557
1768
|
if (nonNullTypes.length > 1) return (0, _kubb_ast.createSchema)({
|
|
1558
1769
|
type: "union",
|
|
1559
|
-
members: nonNullTypes.map((t) => convertSchema({
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1770
|
+
members: nonNullTypes.map((t) => convertSchema({
|
|
1771
|
+
schema: {
|
|
1772
|
+
...schema,
|
|
1773
|
+
type: t
|
|
1774
|
+
},
|
|
1775
|
+
name
|
|
1776
|
+
}, options)),
|
|
1777
|
+
...renderSchemaBase(schema, name, arrayNullable, defaultValue)
|
|
1564
1778
|
});
|
|
1565
1779
|
}
|
|
1566
1780
|
if (!type) {
|
|
@@ -1588,12 +1802,17 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1588
1802
|
* When the parameter has no `schema` or its schema is a `$ref`, falls back to `unknownType`.
|
|
1589
1803
|
*/
|
|
1590
1804
|
function parseParameter(options, param) {
|
|
1805
|
+
const required = param["required"] ?? false;
|
|
1591
1806
|
const schema = param["schema"] && !isReference(param["schema"]) ? convertSchema({ schema: param["schema"] }, options) : (0, _kubb_ast.createSchema)({ type: resolveTypeOption(options.unknownType) });
|
|
1592
1807
|
return (0, _kubb_ast.createParameter)({
|
|
1593
1808
|
name: param["name"],
|
|
1594
1809
|
in: param["in"],
|
|
1595
|
-
schema
|
|
1596
|
-
|
|
1810
|
+
schema: {
|
|
1811
|
+
...schema,
|
|
1812
|
+
description: param["description"] ?? schema.description,
|
|
1813
|
+
optional: !required || !!schema.optional ? true : void 0
|
|
1814
|
+
},
|
|
1815
|
+
required
|
|
1597
1816
|
});
|
|
1598
1817
|
}
|
|
1599
1818
|
/**
|
|
@@ -1601,15 +1820,13 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1601
1820
|
* request body, and all response codes into their AST node equivalents.
|
|
1602
1821
|
*/
|
|
1603
1822
|
function parseOperation(options, oas, operation) {
|
|
1604
|
-
const parameters =
|
|
1605
|
-
return parseParameter(options, oas.dereferenceWithRef(param));
|
|
1606
|
-
});
|
|
1823
|
+
const parameters = oas.getParameters(operation).map((param) => parseParameter(options, param));
|
|
1607
1824
|
const requestBodySchema = oas.getRequestSchema(operation);
|
|
1608
1825
|
const requestBody = requestBodySchema ? convertSchema({ schema: requestBodySchema }, options) : void 0;
|
|
1609
1826
|
const responses = operation.getResponseStatusCodes().map((statusCode) => {
|
|
1610
1827
|
const responseObj = operation.getResponseByStatusCode(statusCode);
|
|
1611
1828
|
const responseSchema = oas.getResponseSchema(operation, statusCode);
|
|
1612
|
-
const schema = responseSchema && Object.keys(responseSchema).length > 0 ? convertSchema({ schema: responseSchema }, options) :
|
|
1829
|
+
const schema = responseSchema && Object.keys(responseSchema).length > 0 ? convertSchema({ schema: responseSchema }, options) : (0, _kubb_ast.createSchema)({ type: resolveTypeOption(options.emptySchemaType) });
|
|
1613
1830
|
const description = typeof responseObj === "object" && responseObj !== null && !Array.isArray(responseObj) ? responseObj.description : void 0;
|
|
1614
1831
|
const rawContent = typeof responseObj === "object" && responseObj !== null && !Array.isArray(responseObj) ? responseObj.content : void 0;
|
|
1615
1832
|
return (0, _kubb_ast.createResponse)({
|
|
@@ -1622,7 +1839,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1622
1839
|
return (0, _kubb_ast.createOperation)({
|
|
1623
1840
|
operationId: operation.getOperationId(),
|
|
1624
1841
|
method: operation.method.toUpperCase(),
|
|
1625
|
-
path: operation.path,
|
|
1842
|
+
path: new URLPath(operation.path).URL,
|
|
1626
1843
|
tags: operation.getTags().map((tag) => tag.name),
|
|
1627
1844
|
summary: operation.getSummary() || void 0,
|
|
1628
1845
|
description: operation.getDescription() || void 0,
|
|
@@ -1638,7 +1855,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1638
1855
|
*/
|
|
1639
1856
|
function parse(options) {
|
|
1640
1857
|
const mergedOptions = {
|
|
1641
|
-
...
|
|
1858
|
+
...DEFAULT_PARSER_OPTIONS,
|
|
1642
1859
|
...options
|
|
1643
1860
|
};
|
|
1644
1861
|
const schemas = Object.entries(schemaObjects).map(([name, schemaObject]) => convertSchema({
|
|
@@ -1679,31 +1896,11 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1679
1896
|
}
|
|
1680
1897
|
} });
|
|
1681
1898
|
}
|
|
1682
|
-
/**
|
|
1683
|
-
* Collects all `KubbFile.Import` descriptors needed by a `SchemaNode` tree.
|
|
1684
|
-
*
|
|
1685
|
-
* Walks the tree looking for `ref` nodes, verifies each `$ref` is resolvable in the spec,
|
|
1686
|
-
* applies collision-resolved names from `nameMapping`, and calls `resolve` to obtain the
|
|
1687
|
-
* import path and name. Returns an empty array for refs that cannot be resolved.
|
|
1688
|
-
*/
|
|
1689
|
-
function getImports(node, resolve) {
|
|
1690
|
-
return (0, _kubb_ast.collect)(node, { schema(schemaNode) {
|
|
1691
|
-
if (schemaNode.type !== "ref" || !schemaNode.ref) return;
|
|
1692
|
-
if (!oas.get(schemaNode.ref)) return;
|
|
1693
|
-
const rawName = extractRefName(schemaNode.ref);
|
|
1694
|
-
const result = resolve(nameMapping.get(rawName) ?? rawName);
|
|
1695
|
-
if (!result) return;
|
|
1696
|
-
return {
|
|
1697
|
-
name: [result.name],
|
|
1698
|
-
path: result.path
|
|
1699
|
-
};
|
|
1700
|
-
} });
|
|
1701
|
-
}
|
|
1702
1899
|
return {
|
|
1703
1900
|
parse,
|
|
1704
1901
|
convertSchema,
|
|
1705
1902
|
resolveRefs,
|
|
1706
|
-
|
|
1903
|
+
nameMapping
|
|
1707
1904
|
};
|
|
1708
1905
|
}
|
|
1709
1906
|
//#endregion
|
|
@@ -1727,8 +1924,9 @@ const adapterOasName = "oas";
|
|
|
1727
1924
|
* })
|
|
1728
1925
|
* ```
|
|
1729
1926
|
*/
|
|
1730
|
-
const adapterOas = (0, _kubb_core.
|
|
1731
|
-
const { validate = true, oasClass, contentType, serverIndex, serverVariables, discriminator = "strict", collisionDetection =
|
|
1927
|
+
const adapterOas = (0, _kubb_core.createAdapter)((options) => {
|
|
1928
|
+
const { validate = true, oasClass, contentType, serverIndex, serverVariables, discriminator = "strict", collisionDetection = true, dateType = DEFAULT_PARSER_OPTIONS.dateType, integerType = DEFAULT_PARSER_OPTIONS.integerType, unknownType = DEFAULT_PARSER_OPTIONS.unknownType, enumSuffix = DEFAULT_PARSER_OPTIONS.enumSuffix, emptySchemaType = unknownType || DEFAULT_PARSER_OPTIONS.emptySchemaType } = options;
|
|
1929
|
+
const nameMapping = /* @__PURE__ */ new Map();
|
|
1732
1930
|
return {
|
|
1733
1931
|
name: "oas",
|
|
1734
1932
|
options: {
|
|
@@ -1742,7 +1940,16 @@ const adapterOas = (0, _kubb_core.defineAdapter)((options) => {
|
|
|
1742
1940
|
dateType,
|
|
1743
1941
|
integerType,
|
|
1744
1942
|
unknownType,
|
|
1745
|
-
emptySchemaType
|
|
1943
|
+
emptySchemaType,
|
|
1944
|
+
enumSuffix,
|
|
1945
|
+
nameMapping
|
|
1946
|
+
},
|
|
1947
|
+
getImports(node, resolve) {
|
|
1948
|
+
return getImports({
|
|
1949
|
+
node,
|
|
1950
|
+
nameMapping,
|
|
1951
|
+
resolve
|
|
1952
|
+
});
|
|
1746
1953
|
},
|
|
1747
1954
|
async parse(source) {
|
|
1748
1955
|
const oas = await parseFromConfig(sourceToFakeConfig(source), oasClass);
|
|
@@ -1756,18 +1963,23 @@ const adapterOas = (0, _kubb_core.defineAdapter)((options) => {
|
|
|
1756
1963
|
} catch (_err) {}
|
|
1757
1964
|
const server = serverIndex !== void 0 ? oas.api.servers?.at(serverIndex) : void 0;
|
|
1758
1965
|
const baseURL = server?.url ? resolveServerUrl(server, serverVariables) : void 0;
|
|
1966
|
+
const parser = createOasParser(oas, {
|
|
1967
|
+
contentType,
|
|
1968
|
+
collisionDetection
|
|
1969
|
+
});
|
|
1970
|
+
nameMapping.clear();
|
|
1971
|
+
for (const [key, value] of parser.nameMapping) nameMapping.set(key, value);
|
|
1759
1972
|
return (0, _kubb_ast.createRoot)({
|
|
1760
|
-
...
|
|
1761
|
-
contentType,
|
|
1762
|
-
collisionDetection
|
|
1763
|
-
}).parse({
|
|
1973
|
+
...parser.parse({
|
|
1764
1974
|
dateType,
|
|
1765
1975
|
integerType,
|
|
1766
1976
|
unknownType,
|
|
1767
|
-
emptySchemaType
|
|
1977
|
+
emptySchemaType,
|
|
1978
|
+
enumSuffix
|
|
1768
1979
|
}),
|
|
1769
1980
|
meta: {
|
|
1770
1981
|
title: oas.api.info?.title,
|
|
1982
|
+
description: oas.api.info?.description,
|
|
1771
1983
|
version: oas.api.info?.version,
|
|
1772
1984
|
baseURL
|
|
1773
1985
|
}
|