@kubb/adapter-oas 5.0.0-alpha.2 → 5.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +235 -101
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +27 -0
- package/dist/index.js +235 -101
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/adapter.ts +16 -0
- package/src/oas/types.ts +19 -0
- package/src/parser.ts +104 -152
- package/src/types.ts +6 -0
- package/src/utils.ts +161 -0
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { DiscriminatorObject, OASDocument, SchemaObject } from "oas/types";
|
|
|
5
5
|
import BaseOas from "oas";
|
|
6
6
|
import * as oas_normalize_lib_types0 from "oas-normalize/lib/types";
|
|
7
7
|
import { Operation } from "oas/operation";
|
|
8
|
+
import { OpenAPIV3 } from "openapi-types";
|
|
8
9
|
|
|
9
10
|
//#region src/oas/types.d.ts
|
|
10
11
|
type contentType = 'application/json' | (string & {});
|
|
@@ -24,10 +25,30 @@ type SchemaObject$1 = SchemaObject & {
|
|
|
24
25
|
*/
|
|
25
26
|
contentMediaType?: string;
|
|
26
27
|
$ref?: string;
|
|
28
|
+
/**
|
|
29
|
+
* OAS 3.1 / JSON Schema: positional items in a tuple schema.
|
|
30
|
+
* Replaces the OAS 3.0 multi-item `items` array syntax.
|
|
31
|
+
*/
|
|
32
|
+
prefixItems?: Array<SchemaObject$1 | ReferenceObject>;
|
|
33
|
+
/**
|
|
34
|
+
* JSON Schema: maps regex patterns to sub-schemas for additional property validation.
|
|
35
|
+
*/
|
|
36
|
+
patternProperties?: Record<string, SchemaObject$1 | boolean>;
|
|
37
|
+
/**
|
|
38
|
+
* OAS 3.0 / JSON Schema: single-schema form.
|
|
39
|
+
* The OAS base type already includes this, but we re-declare it here to ensure
|
|
40
|
+
* the single-schema overload takes precedence over the multi-schema tuple form.
|
|
41
|
+
*/
|
|
42
|
+
items?: SchemaObject$1 | ReferenceObject;
|
|
43
|
+
/**
|
|
44
|
+
* Enum values for this schema (narrowed from `unknown[]` in the base type).
|
|
45
|
+
*/
|
|
46
|
+
enum?: Array<string | number | boolean | null>;
|
|
27
47
|
};
|
|
28
48
|
type Document = OASDocument;
|
|
29
49
|
type Operation$1 = Operation;
|
|
30
50
|
type DiscriminatorObject$1 = DiscriminatorObject;
|
|
51
|
+
type ReferenceObject = OpenAPIV3.ReferenceObject;
|
|
31
52
|
//#endregion
|
|
32
53
|
//#region src/oas/Oas.d.ts
|
|
33
54
|
type OasOptions = {
|
|
@@ -149,6 +170,12 @@ type OasAdapterResolvedOptions = {
|
|
|
149
170
|
integerType: NonNullable<OasAdapterOptions['integerType']>;
|
|
150
171
|
unknownType: NonNullable<OasAdapterOptions['unknownType']>;
|
|
151
172
|
emptySchemaType: NonNullable<OasAdapterOptions['emptySchemaType']>;
|
|
173
|
+
/**
|
|
174
|
+
* Map from original `$ref` paths to their collision-resolved schema names.
|
|
175
|
+
* Populated by the adapter after each `parse()` call.
|
|
176
|
+
* e.g. `'#/components/schemas/Order'` → `'OrderSchema'`
|
|
177
|
+
*/
|
|
178
|
+
nameMapping: Map<string, string>;
|
|
152
179
|
};
|
|
153
180
|
type OasAdapter = AdapterFactoryOptions<'oas', OasAdapterOptions, OasAdapterResolvedOptions>;
|
|
154
181
|
//#endregion
|
package/dist/index.js
CHANGED
|
@@ -900,6 +900,137 @@ function resolveCollisions(schemasWithMeta) {
|
|
|
900
900
|
};
|
|
901
901
|
}
|
|
902
902
|
//#endregion
|
|
903
|
+
//#region src/utils.ts
|
|
904
|
+
/**
|
|
905
|
+
* Extracts the schema name from a `$ref` string.
|
|
906
|
+
* For `#/components/schemas/Order` this returns `'Order'`.
|
|
907
|
+
* Falls back to the full ref string when no slash is present.
|
|
908
|
+
*/
|
|
909
|
+
function extractRefName($ref) {
|
|
910
|
+
return $ref.split("/").at(-1) ?? $ref;
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Replaces the discriminator property's schema inside an `ObjectSchemaNode`
|
|
914
|
+
* with an enum of the given `values`.
|
|
915
|
+
*
|
|
916
|
+
* - When `enumName` is provided the enum is named, which lets printers emit a
|
|
917
|
+
* standalone enum declaration + type reference (e.g. `PetTypeEnum`).
|
|
918
|
+
* - When `enumName` is omitted the enum stays anonymous, so printers inline it
|
|
919
|
+
* as a literal union (e.g. `'dog'`).
|
|
920
|
+
*
|
|
921
|
+
* Returns the node unchanged when it is not an object or lacks the target property.
|
|
922
|
+
*/
|
|
923
|
+
function applyDiscriminatorEnum({ node, propertyName, values, enumName }) {
|
|
924
|
+
if (node.type !== "object" || !node.properties?.length) return node;
|
|
925
|
+
if (!node.properties.some((prop) => prop.name === propertyName)) return node;
|
|
926
|
+
return createSchema({
|
|
927
|
+
...node,
|
|
928
|
+
properties: node.properties.map((prop) => {
|
|
929
|
+
if (prop.name !== propertyName) return prop;
|
|
930
|
+
const enumSchema = createSchema({
|
|
931
|
+
type: "enum",
|
|
932
|
+
primitive: "string",
|
|
933
|
+
enumValues: values,
|
|
934
|
+
name: enumName,
|
|
935
|
+
readOnly: prop.schema.readOnly,
|
|
936
|
+
writeOnly: prop.schema.writeOnly
|
|
937
|
+
});
|
|
938
|
+
return createProperty({
|
|
939
|
+
...prop,
|
|
940
|
+
schema: enumSchema
|
|
941
|
+
});
|
|
942
|
+
})
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* Merges consecutive anonymous (`name`-less) `ObjectSchemaNode`s in `members` into a
|
|
947
|
+
* single object by combining their `properties` arrays.
|
|
948
|
+
*
|
|
949
|
+
* Only adjacent pairs are merged — non-object or named nodes act as boundaries.
|
|
950
|
+
* This collapses patterns like `Address & { streetNumber } & { streetName }` into
|
|
951
|
+
* `Address & { streetNumber; streetName }`.
|
|
952
|
+
*/
|
|
953
|
+
function mergeAdjacentAnonymousObjects(members) {
|
|
954
|
+
return members.reduce((acc, member) => {
|
|
955
|
+
const obj = narrowSchema(member, "object");
|
|
956
|
+
if (obj && !obj.name) {
|
|
957
|
+
const prev = acc[acc.length - 1];
|
|
958
|
+
const prevObj = prev ? narrowSchema(prev, "object") : null;
|
|
959
|
+
if (prevObj && !prevObj.name) {
|
|
960
|
+
acc[acc.length - 1] = createSchema({
|
|
961
|
+
...prevObj,
|
|
962
|
+
properties: [...prevObj.properties ?? [], ...obj.properties ?? []]
|
|
963
|
+
});
|
|
964
|
+
return acc;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
acc.push(member);
|
|
968
|
+
return acc;
|
|
969
|
+
}, []);
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* Simplifies a union member list by removing `enum` nodes whose `primitive` type is
|
|
973
|
+
* already represented by a broader scalar node in the same union.
|
|
974
|
+
*
|
|
975
|
+
* For example `['placed', 'approved'] | string` collapses to `string` because
|
|
976
|
+
* `string` subsumes all string literals. `'' | string` similarly becomes `string`.
|
|
977
|
+
*
|
|
978
|
+
* Only scalar primitives (`string`, `number`, `integer`, `bigint`, `boolean`) are
|
|
979
|
+
* considered — object, array, and ref members are left untouched.
|
|
980
|
+
*/
|
|
981
|
+
function simplifyUnionMembers(members) {
|
|
982
|
+
const scalarPrimitives = new Set(members.filter((m) => [
|
|
983
|
+
"string",
|
|
984
|
+
"number",
|
|
985
|
+
"integer",
|
|
986
|
+
"bigint",
|
|
987
|
+
"boolean"
|
|
988
|
+
].includes(m.type)).map((m) => m.type));
|
|
989
|
+
if (!scalarPrimitives.size) return members;
|
|
990
|
+
return members.filter((m) => {
|
|
991
|
+
if (m.type !== "enum") return true;
|
|
992
|
+
const prim = m.primitive;
|
|
993
|
+
if (!prim) return true;
|
|
994
|
+
if (scalarPrimitives.has(prim)) return false;
|
|
995
|
+
if ((prim === "integer" || prim === "number") && (scalarPrimitives.has("integer") || scalarPrimitives.has("number"))) return false;
|
|
996
|
+
return true;
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
/**
|
|
1000
|
+
* `nameMapping`, and calls `resolve` to obtain the `{ name, path }` pair for
|
|
1001
|
+
* each import. When `oas` is supplied, only `$ref`s that are resolvable in the
|
|
1002
|
+
* spec are included; omit it to skip the existence check.
|
|
1003
|
+
*
|
|
1004
|
+
* This function is the pure, state-free alternative to `OasParser.getImports`.
|
|
1005
|
+
* Because it receives `nameMapping` explicitly it can be called without holding
|
|
1006
|
+
* a reference to the parser or the OAS instance.
|
|
1007
|
+
*
|
|
1008
|
+
* @example
|
|
1009
|
+
* ```ts
|
|
1010
|
+
* // Use adapter state directly — no parser reference needed
|
|
1011
|
+
* const imports = getImports({
|
|
1012
|
+
* node: schemaNode,
|
|
1013
|
+
* nameMapping: adapter.options.nameMapping,
|
|
1014
|
+
* resolve: (schemaName) => ({
|
|
1015
|
+
* name: schemaManager.getName(schemaName, { type: 'type' }),
|
|
1016
|
+
* path: schemaManager.getFile(schemaName).path,
|
|
1017
|
+
* }),
|
|
1018
|
+
* })
|
|
1019
|
+
* ```
|
|
1020
|
+
*/
|
|
1021
|
+
function getImports({ node, nameMapping, resolve }) {
|
|
1022
|
+
return collect(node, { schema(schemaNode) {
|
|
1023
|
+
if (schemaNode.type !== "ref" || !schemaNode.ref) return;
|
|
1024
|
+
const rawName = extractRefName(schemaNode.ref);
|
|
1025
|
+
const result = resolve(nameMapping.get(rawName) ?? rawName);
|
|
1026
|
+
if (!result) return;
|
|
1027
|
+
return {
|
|
1028
|
+
name: [result.name],
|
|
1029
|
+
path: result.path
|
|
1030
|
+
};
|
|
1031
|
+
} });
|
|
1032
|
+
}
|
|
1033
|
+
//#endregion
|
|
903
1034
|
//#region src/parser.ts
|
|
904
1035
|
/**
|
|
905
1036
|
* Default values for all `Options` fields.
|
|
@@ -920,14 +1051,6 @@ function formatToSchemaType(format) {
|
|
|
920
1051
|
return formatMap[format];
|
|
921
1052
|
}
|
|
922
1053
|
/**
|
|
923
|
-
* Extracts the final path segment of a JSON Pointer `$ref` string.
|
|
924
|
-
* For `#/components/schemas/Order` this returns `'Order'`.
|
|
925
|
-
* Falls back to the full ref string when no slash is present.
|
|
926
|
-
*/
|
|
927
|
-
function extractRefName($ref) {
|
|
928
|
-
return $ref.split("/").at(-1) ?? $ref;
|
|
929
|
-
}
|
|
930
|
-
/**
|
|
931
1054
|
* Maps an OAS primitive type string to its `PrimitiveSchemaType` equivalent.
|
|
932
1055
|
* Numeric types (`number`, `integer`, `bigint`) are returned unchanged;
|
|
933
1056
|
* `boolean` maps to `'boolean'`; everything else defaults to `'string'`.
|
|
@@ -945,26 +1068,6 @@ function toMediaType(contentType) {
|
|
|
945
1068
|
return knownMediaTypes.includes(contentType) ? contentType : void 0;
|
|
946
1069
|
}
|
|
947
1070
|
/**
|
|
948
|
-
* When a discriminator is present, replaces the discriminator property's schema with
|
|
949
|
-
* an enum of the mapping keys so downstream code emits a precise literal-union type.
|
|
950
|
-
* Returns the original schema unchanged when there is no discriminator or no mapping.
|
|
951
|
-
*/
|
|
952
|
-
function applyDiscriminatorEnum(schema) {
|
|
953
|
-
if (!isDiscriminator(schema)) return schema;
|
|
954
|
-
const propName = schema.discriminator.propertyName;
|
|
955
|
-
if (!schema.properties?.[propName]) return schema;
|
|
956
|
-
return {
|
|
957
|
-
...schema,
|
|
958
|
-
properties: {
|
|
959
|
-
...schema.properties,
|
|
960
|
-
[propName]: {
|
|
961
|
-
...schema.properties[propName],
|
|
962
|
-
enum: schema.discriminator.mapping ? Object.keys(schema.discriminator.mapping) : void 0
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
};
|
|
966
|
-
}
|
|
967
|
-
/**
|
|
968
1071
|
* Creates an OAS parser that converts an OpenAPI/Swagger spec into
|
|
969
1072
|
* the `@kubb/ast` tree.
|
|
970
1073
|
*
|
|
@@ -1055,18 +1158,17 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1055
1158
|
* reflected in generated JSDoc and type modifiers.
|
|
1056
1159
|
*/
|
|
1057
1160
|
function convertRef({ schema, nullable, defaultValue }) {
|
|
1058
|
-
const schemaObject = schema;
|
|
1059
1161
|
return createSchema({
|
|
1060
1162
|
type: "ref",
|
|
1061
|
-
name: extractRefName(
|
|
1062
|
-
ref:
|
|
1163
|
+
name: extractRefName(schema.$ref),
|
|
1164
|
+
ref: schema.$ref,
|
|
1063
1165
|
nullable,
|
|
1064
|
-
description:
|
|
1065
|
-
deprecated:
|
|
1066
|
-
readOnly:
|
|
1067
|
-
writeOnly:
|
|
1068
|
-
pattern:
|
|
1069
|
-
example:
|
|
1166
|
+
description: schema.description,
|
|
1167
|
+
deprecated: schema.deprecated,
|
|
1168
|
+
readOnly: schema.readOnly,
|
|
1169
|
+
writeOnly: schema.writeOnly,
|
|
1170
|
+
pattern: schema.type === "string" ? schema.pattern : void 0,
|
|
1171
|
+
example: schema.example,
|
|
1070
1172
|
default: defaultValue
|
|
1071
1173
|
});
|
|
1072
1174
|
}
|
|
@@ -1117,6 +1219,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1117
1219
|
const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
|
|
1118
1220
|
return !inOneOf && !inMapping;
|
|
1119
1221
|
}).map((s) => convertSchema({ schema: s }, options));
|
|
1222
|
+
const syntheticStart = allOfMembers.length;
|
|
1120
1223
|
if (Array.isArray(schema.required) && schema.required.length) {
|
|
1121
1224
|
const outerKeys = schema.properties ? new Set(Object.keys(schema.properties)) : /* @__PURE__ */ new Set();
|
|
1122
1225
|
const missingRequired = schema.required.filter((key) => !outerKeys.has(key));
|
|
@@ -1141,7 +1244,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1141
1244
|
}
|
|
1142
1245
|
return createSchema({
|
|
1143
1246
|
type: "intersection",
|
|
1144
|
-
members: allOfMembers,
|
|
1247
|
+
members: [...allOfMembers.slice(0, syntheticStart), ...mergeAdjacentAnonymousObjects(allOfMembers.slice(syntheticStart))],
|
|
1145
1248
|
...buildSchemaBase(schema, name, nullable, defaultValue)
|
|
1146
1249
|
});
|
|
1147
1250
|
}
|
|
@@ -1161,20 +1264,34 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1161
1264
|
};
|
|
1162
1265
|
if (schema.properties) {
|
|
1163
1266
|
const { oneOf: _oneOf, anyOf: _anyOf, ...schemaWithoutUnion } = schema;
|
|
1164
|
-
const
|
|
1267
|
+
const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
|
|
1268
|
+
const memberBaseSchema = discriminator ? Object.fromEntries(Object.entries(schemaWithoutUnion).filter(([key]) => key !== "discriminator")) : schemaWithoutUnion;
|
|
1165
1269
|
return createSchema({
|
|
1166
1270
|
type: "union",
|
|
1167
1271
|
...unionBase,
|
|
1168
|
-
members: unionMembers.map((s) =>
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1272
|
+
members: unionMembers.map((s) => {
|
|
1273
|
+
const ref = isReference(s) ? s.$ref : void 0;
|
|
1274
|
+
const discriminatorValue = discriminator?.mapping && ref ? Object.entries(discriminator.mapping).find(([, v]) => v === ref)?.[0] : void 0;
|
|
1275
|
+
let propertiesNode = convertSchema({
|
|
1276
|
+
schema: memberBaseSchema,
|
|
1277
|
+
name
|
|
1278
|
+
}, options);
|
|
1279
|
+
if (discriminatorValue && discriminator) propertiesNode = applyDiscriminatorEnum({
|
|
1280
|
+
node: propertiesNode,
|
|
1281
|
+
propertyName: discriminator.propertyName,
|
|
1282
|
+
values: [discriminatorValue]
|
|
1283
|
+
});
|
|
1284
|
+
return createSchema({
|
|
1285
|
+
type: "intersection",
|
|
1286
|
+
members: [convertSchema({ schema: s }, options), propertiesNode]
|
|
1287
|
+
});
|
|
1288
|
+
})
|
|
1172
1289
|
});
|
|
1173
1290
|
}
|
|
1174
1291
|
return createSchema({
|
|
1175
1292
|
type: "union",
|
|
1176
1293
|
...unionBase,
|
|
1177
|
-
members: unionMembers.map((s) => convertSchema({ schema: s }, options))
|
|
1294
|
+
members: simplifyUnionMembers(unionMembers.map((s) => convertSchema({ schema: s }, options)))
|
|
1178
1295
|
});
|
|
1179
1296
|
}
|
|
1180
1297
|
/**
|
|
@@ -1259,9 +1376,8 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1259
1376
|
*/
|
|
1260
1377
|
function convertEnum({ schema, name, nullable, type, options }) {
|
|
1261
1378
|
if (type === "array") {
|
|
1262
|
-
const rawSchema = schema;
|
|
1263
1379
|
const normalizedItems = {
|
|
1264
|
-
...typeof
|
|
1380
|
+
...typeof schema.items === "object" && !Array.isArray(schema.items) ? schema.items : {},
|
|
1265
1381
|
enum: schema.enum
|
|
1266
1382
|
};
|
|
1267
1383
|
const { enum: _enum, ...schemaWithoutEnum } = schema;
|
|
@@ -1341,22 +1457,28 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1341
1457
|
* - not required + nullable → `nullish: true`
|
|
1342
1458
|
*/
|
|
1343
1459
|
function convertObject({ schema, name, nullable, defaultValue, options, mergedOptions }) {
|
|
1344
|
-
const
|
|
1345
|
-
|
|
1346
|
-
const required = Array.isArray(resolvedSchema.required) ? resolvedSchema.required.includes(propName) : !!resolvedSchema.required;
|
|
1460
|
+
const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
|
|
1461
|
+
const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
|
|
1347
1462
|
const resolvedPropSchema = propSchema;
|
|
1348
1463
|
const propNullable = isNullable(resolvedPropSchema);
|
|
1464
|
+
const basePropName = name ? pascalCase([name, propName].join(" ")) : void 0;
|
|
1465
|
+
const propNode = convertSchema({
|
|
1466
|
+
schema: resolvedPropSchema,
|
|
1467
|
+
name: basePropName
|
|
1468
|
+
}, options);
|
|
1469
|
+
const isEnumNode = !!narrowSchema(propNode, "enum");
|
|
1470
|
+
const derivedPropName = isEnumNode && name ? pascalCase([
|
|
1471
|
+
name,
|
|
1472
|
+
propName,
|
|
1473
|
+
mergedOptions.enumSuffix
|
|
1474
|
+
].filter(Boolean).join(" ")) : basePropName;
|
|
1349
1475
|
return createProperty({
|
|
1350
1476
|
name: propName,
|
|
1351
1477
|
schema: {
|
|
1352
|
-
...
|
|
1353
|
-
|
|
1354
|
-
name:
|
|
1355
|
-
|
|
1356
|
-
propName,
|
|
1357
|
-
mergedOptions.enumSuffix
|
|
1358
|
-
].filter(Boolean).join(" ")) : void 0
|
|
1359
|
-
}, options),
|
|
1478
|
+
...isEnumNode && derivedPropName !== basePropName ? {
|
|
1479
|
+
...propNode,
|
|
1480
|
+
name: derivedPropName
|
|
1481
|
+
} : propNode,
|
|
1360
1482
|
nullable: propNullable || void 0,
|
|
1361
1483
|
optional: !required && !propNullable ? true : void 0,
|
|
1362
1484
|
nullish: !required && propNullable ? true : void 0
|
|
@@ -1364,15 +1486,15 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1364
1486
|
required
|
|
1365
1487
|
});
|
|
1366
1488
|
}) : [];
|
|
1367
|
-
const additionalProperties =
|
|
1489
|
+
const additionalProperties = schema.additionalProperties;
|
|
1368
1490
|
let additionalPropertiesNode;
|
|
1369
1491
|
if (additionalProperties === true) additionalPropertiesNode = true;
|
|
1370
1492
|
else if (additionalProperties && Object.keys(additionalProperties).length > 0) additionalPropertiesNode = convertSchema({ schema: additionalProperties }, options);
|
|
1371
1493
|
else if (additionalProperties === false) additionalPropertiesNode = void 0;
|
|
1372
1494
|
else if (additionalProperties) additionalPropertiesNode = createSchema({ type: resolveTypeOption(mergedOptions.unknownType) });
|
|
1373
|
-
const rawPatternProperties = "patternProperties" in
|
|
1374
|
-
const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || Object.keys(patternSchema).length === 0 ? createSchema({ type: resolveTypeOption(mergedOptions.unknownType) }) : convertSchema({ schema: patternSchema }, options)])) : void 0;
|
|
1375
|
-
|
|
1495
|
+
const rawPatternProperties = "patternProperties" in schema ? schema.patternProperties : void 0;
|
|
1496
|
+
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(mergedOptions.unknownType) }) : convertSchema({ schema: patternSchema }, options)])) : void 0;
|
|
1497
|
+
const objectNode = createSchema({
|
|
1376
1498
|
type: "object",
|
|
1377
1499
|
primitive: "object",
|
|
1378
1500
|
properties,
|
|
@@ -1380,6 +1502,20 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1380
1502
|
patternProperties,
|
|
1381
1503
|
...buildSchemaBase(schema, name, nullable, defaultValue)
|
|
1382
1504
|
});
|
|
1505
|
+
if (isDiscriminator(schema) && schema.discriminator.mapping) {
|
|
1506
|
+
const discPropName = schema.discriminator.propertyName;
|
|
1507
|
+
return applyDiscriminatorEnum({
|
|
1508
|
+
node: objectNode,
|
|
1509
|
+
propertyName: discPropName,
|
|
1510
|
+
values: Object.keys(schema.discriminator.mapping),
|
|
1511
|
+
enumName: name ? pascalCase([
|
|
1512
|
+
name,
|
|
1513
|
+
discPropName,
|
|
1514
|
+
mergedOptions.enumSuffix
|
|
1515
|
+
].filter(Boolean).join(" ")) : void 0
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
return objectNode;
|
|
1383
1519
|
}
|
|
1384
1520
|
/**
|
|
1385
1521
|
* Converts an OAS 3.1 `prefixItems` tuple into a `TupleSchemaNode`.
|
|
@@ -1388,12 +1524,11 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1388
1524
|
* after the prefix items is mapped to the rest parameter of the tuple.
|
|
1389
1525
|
*/
|
|
1390
1526
|
function convertTuple({ schema, name, nullable, defaultValue, options }) {
|
|
1391
|
-
const rawSchema = schema;
|
|
1392
1527
|
return createSchema({
|
|
1393
1528
|
type: "tuple",
|
|
1394
1529
|
primitive: "array",
|
|
1395
|
-
items:
|
|
1396
|
-
rest:
|
|
1530
|
+
items: (schema.prefixItems ?? []).map((item) => convertSchema({ schema: item }, options)),
|
|
1531
|
+
rest: schema.items ? convertSchema({ schema: schema.items }, options) : void 0,
|
|
1397
1532
|
min: schema.minItems,
|
|
1398
1533
|
max: schema.maxItems,
|
|
1399
1534
|
...buildSchemaBase(schema, name, nullable, defaultValue)
|
|
@@ -1406,13 +1541,13 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1406
1541
|
* `enumSuffix` is forwarded so generators can emit a named enum declaration.
|
|
1407
1542
|
*/
|
|
1408
1543
|
function convertArray({ schema, name, nullable, defaultValue, options, mergedOptions }) {
|
|
1409
|
-
const
|
|
1410
|
-
const itemName =
|
|
1544
|
+
const rawItems = schema.items;
|
|
1545
|
+
const itemName = rawItems?.enum?.length && name ? pascalCase([name, mergedOptions.enumSuffix].join(" ")) : void 0;
|
|
1411
1546
|
return createSchema({
|
|
1412
1547
|
type: "array",
|
|
1413
1548
|
primitive: "array",
|
|
1414
|
-
items:
|
|
1415
|
-
schema:
|
|
1549
|
+
items: rawItems ? [convertSchema({
|
|
1550
|
+
schema: rawItems,
|
|
1416
1551
|
name: itemName
|
|
1417
1552
|
}, options)] : [],
|
|
1418
1553
|
min: schema.minItems,
|
|
@@ -1528,10 +1663,13 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1528
1663
|
const arrayNullable = schema.type.includes("null") || nullable || void 0;
|
|
1529
1664
|
if (nonNullTypes.length > 1) return createSchema({
|
|
1530
1665
|
type: "union",
|
|
1531
|
-
members: nonNullTypes.map((t) => convertSchema({
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1666
|
+
members: nonNullTypes.map((t) => convertSchema({
|
|
1667
|
+
schema: {
|
|
1668
|
+
...schema,
|
|
1669
|
+
type: t
|
|
1670
|
+
},
|
|
1671
|
+
name
|
|
1672
|
+
}, options)),
|
|
1535
1673
|
...buildSchemaBase(schema, name, arrayNullable, defaultValue)
|
|
1536
1674
|
});
|
|
1537
1675
|
}
|
|
@@ -1560,12 +1698,16 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1560
1698
|
* When the parameter has no `schema` or its schema is a `$ref`, falls back to `unknownType`.
|
|
1561
1699
|
*/
|
|
1562
1700
|
function parseParameter(options, param) {
|
|
1701
|
+
const required = param["required"] ?? false;
|
|
1563
1702
|
const schema = param["schema"] && !isReference(param["schema"]) ? convertSchema({ schema: param["schema"] }, options) : createSchema({ type: resolveTypeOption(options.unknownType) });
|
|
1564
1703
|
return createParameter({
|
|
1565
1704
|
name: param["name"],
|
|
1566
1705
|
in: param["in"],
|
|
1567
|
-
schema
|
|
1568
|
-
|
|
1706
|
+
schema: {
|
|
1707
|
+
...schema,
|
|
1708
|
+
optional: !required || !!schema.optional ? true : void 0
|
|
1709
|
+
},
|
|
1710
|
+
required
|
|
1569
1711
|
});
|
|
1570
1712
|
}
|
|
1571
1713
|
/**
|
|
@@ -1594,7 +1736,7 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1594
1736
|
return createOperation({
|
|
1595
1737
|
operationId: operation.getOperationId(),
|
|
1596
1738
|
method: operation.method.toUpperCase(),
|
|
1597
|
-
path: operation.path,
|
|
1739
|
+
path: new URLPath(operation.path).URL,
|
|
1598
1740
|
tags: operation.getTags().map((tag) => tag.name),
|
|
1599
1741
|
summary: operation.getSummary() || void 0,
|
|
1600
1742
|
description: operation.getDescription() || void 0,
|
|
@@ -1651,31 +1793,11 @@ function createOasParser(oas, { contentType, collisionDetection } = {}) {
|
|
|
1651
1793
|
}
|
|
1652
1794
|
} });
|
|
1653
1795
|
}
|
|
1654
|
-
/**
|
|
1655
|
-
* Collects all `KubbFile.Import` descriptors needed by a `SchemaNode` tree.
|
|
1656
|
-
*
|
|
1657
|
-
* Walks the tree looking for `ref` nodes, verifies each `$ref` is resolvable in the spec,
|
|
1658
|
-
* applies collision-resolved names from `nameMapping`, and calls `resolve` to obtain the
|
|
1659
|
-
* import path and name. Returns an empty array for refs that cannot be resolved.
|
|
1660
|
-
*/
|
|
1661
|
-
function getImports(node, resolve) {
|
|
1662
|
-
return collect(node, { schema(schemaNode) {
|
|
1663
|
-
if (schemaNode.type !== "ref" || !schemaNode.ref) return;
|
|
1664
|
-
if (!oas.get(schemaNode.ref)) return;
|
|
1665
|
-
const rawName = extractRefName(schemaNode.ref);
|
|
1666
|
-
const result = resolve(nameMapping.get(rawName) ?? rawName);
|
|
1667
|
-
if (!result) return;
|
|
1668
|
-
return {
|
|
1669
|
-
name: [result.name],
|
|
1670
|
-
path: result.path
|
|
1671
|
-
};
|
|
1672
|
-
} });
|
|
1673
|
-
}
|
|
1674
1796
|
return {
|
|
1675
1797
|
parse,
|
|
1676
1798
|
convertSchema,
|
|
1677
1799
|
resolveRefs,
|
|
1678
|
-
|
|
1800
|
+
nameMapping
|
|
1679
1801
|
};
|
|
1680
1802
|
}
|
|
1681
1803
|
//#endregion
|
|
@@ -1701,6 +1823,7 @@ const adapterOasName = "oas";
|
|
|
1701
1823
|
*/
|
|
1702
1824
|
const adapterOas = defineAdapter((options) => {
|
|
1703
1825
|
const { validate = true, oasClass, contentType, serverIndex, serverVariables, discriminator = "strict", collisionDetection = false, dateType = "string", integerType = "number", unknownType = "any", emptySchemaType = unknownType } = options;
|
|
1826
|
+
const nameMapping = /* @__PURE__ */ new Map();
|
|
1704
1827
|
return {
|
|
1705
1828
|
name: "oas",
|
|
1706
1829
|
options: {
|
|
@@ -1714,7 +1837,15 @@ const adapterOas = defineAdapter((options) => {
|
|
|
1714
1837
|
dateType,
|
|
1715
1838
|
integerType,
|
|
1716
1839
|
unknownType,
|
|
1717
|
-
emptySchemaType
|
|
1840
|
+
emptySchemaType,
|
|
1841
|
+
nameMapping
|
|
1842
|
+
},
|
|
1843
|
+
getImports(node, resolve) {
|
|
1844
|
+
return getImports({
|
|
1845
|
+
node,
|
|
1846
|
+
nameMapping,
|
|
1847
|
+
resolve
|
|
1848
|
+
});
|
|
1718
1849
|
},
|
|
1719
1850
|
async parse(source) {
|
|
1720
1851
|
const oas = await parseFromConfig(sourceToFakeConfig(source), oasClass);
|
|
@@ -1728,11 +1859,14 @@ const adapterOas = defineAdapter((options) => {
|
|
|
1728
1859
|
} catch (_err) {}
|
|
1729
1860
|
const server = serverIndex !== void 0 ? oas.api.servers?.at(serverIndex) : void 0;
|
|
1730
1861
|
const baseURL = server?.url ? resolveServerUrl(server, serverVariables) : void 0;
|
|
1862
|
+
const parser = createOasParser(oas, {
|
|
1863
|
+
contentType,
|
|
1864
|
+
collisionDetection
|
|
1865
|
+
});
|
|
1866
|
+
nameMapping.clear();
|
|
1867
|
+
for (const [key, value] of parser.nameMapping) nameMapping.set(key, value);
|
|
1731
1868
|
return createRoot({
|
|
1732
|
-
...
|
|
1733
|
-
contentType,
|
|
1734
|
-
collisionDetection
|
|
1735
|
-
}).parse({
|
|
1869
|
+
...parser.parse({
|
|
1736
1870
|
dateType,
|
|
1737
1871
|
integerType,
|
|
1738
1872
|
unknownType,
|