@kubb/adapter-oas 5.0.0-beta.60 → 5.0.0-beta.62
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 +121 -109
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +122 -110
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/dialect.ts +28 -6
- package/src/parser.ts +98 -83
- package/src/stream.ts +28 -47
package/dist/index.js
CHANGED
|
@@ -5,7 +5,8 @@ import { access, readFile } from "node:fs/promises";
|
|
|
5
5
|
import { compileErrors, validate } from "@readme/openapi-parser";
|
|
6
6
|
import { parse } from "yaml";
|
|
7
7
|
import { bundle } from "api-ref-bundler";
|
|
8
|
-
import {
|
|
8
|
+
import { macroDiscriminatorEnum, macroEnumName, macroSimplifyUnion } from "@kubb/ast/macros";
|
|
9
|
+
import { childName, containsCircularRef, enumPropName, extractRefName, findCircularSchemas, mergeAdjacentObjectsLazy } from "@kubb/ast/utils";
|
|
9
10
|
import { collect, narrowSchema } from "@kubb/ast";
|
|
10
11
|
//#region src/constants.ts
|
|
11
12
|
/**
|
|
@@ -813,6 +814,23 @@ function dereferenceWithRef(document, schema) {
|
|
|
813
814
|
//#endregion
|
|
814
815
|
//#region src/dialect.ts
|
|
815
816
|
/**
|
|
817
|
+
* Derives a schema's `optional`/`nullish` flags from a parent's `required` value and the
|
|
818
|
+
* schema's own `nullable`. How "required" and "nullable" combine is OpenAPI-specific, so it
|
|
819
|
+
* lives in the dialect.
|
|
820
|
+
*
|
|
821
|
+
* - Non-required + non-nullable → `optional: true`.
|
|
822
|
+
* - Non-required + nullable → `nullish: true`.
|
|
823
|
+
* - Required → both flags cleared.
|
|
824
|
+
*/
|
|
825
|
+
function optionality(schema, required) {
|
|
826
|
+
const nullable = schema.nullable ?? false;
|
|
827
|
+
return {
|
|
828
|
+
...schema,
|
|
829
|
+
optional: !required && !nullable ? true : void 0,
|
|
830
|
+
nullish: !required && nullable ? true : void 0
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
816
834
|
* The OpenAPI / Swagger dialect, the default used by `@kubb/adapter-oas`.
|
|
817
835
|
*
|
|
818
836
|
* Implements the spec-agnostic {@link ast.SchemaDialect} contract: it isolates the
|
|
@@ -831,13 +849,16 @@ function dereferenceWithRef(document, schema) {
|
|
|
831
849
|
* const parser = createSchemaParser(context, oasDialect) // explicit
|
|
832
850
|
* ```
|
|
833
851
|
*/
|
|
834
|
-
const oasDialect = ast.
|
|
852
|
+
const oasDialect = ast.defineDialect({
|
|
835
853
|
name: "oas",
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
854
|
+
schema: {
|
|
855
|
+
isNullable,
|
|
856
|
+
isReference,
|
|
857
|
+
isDiscriminator,
|
|
858
|
+
isBinary: (schema) => schema.type === "string" && schema.contentMediaType === "application/octet-stream",
|
|
859
|
+
resolveRef,
|
|
860
|
+
optionality
|
|
861
|
+
}
|
|
841
862
|
});
|
|
842
863
|
//#endregion
|
|
843
864
|
//#region src/discriminator.ts
|
|
@@ -1560,6 +1581,38 @@ function normalizeArrayEnum(schema) {
|
|
|
1560
1581
|
};
|
|
1561
1582
|
}
|
|
1562
1583
|
/**
|
|
1584
|
+
* Builds a `null` scalar node carrying the schema's documentation. Shared by the `const: null`
|
|
1585
|
+
* and the drf-spectacular `NullEnum` (`{ enum: [null] }`) branches, which render identically.
|
|
1586
|
+
*/
|
|
1587
|
+
function createNullSchema(schema, name) {
|
|
1588
|
+
return ast.factory.createSchema({
|
|
1589
|
+
type: "null",
|
|
1590
|
+
primitive: "null",
|
|
1591
|
+
name,
|
|
1592
|
+
title: schema.title,
|
|
1593
|
+
description: schema.description,
|
|
1594
|
+
deprecated: schema.deprecated,
|
|
1595
|
+
format: schema.format
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
/**
|
|
1599
|
+
* Names the inline enums on a property's schema, and on each item when the property is a tuple, from
|
|
1600
|
+
* the parent and property name. Wraps `macroEnumName` at the property construction site.
|
|
1601
|
+
*/
|
|
1602
|
+
function nameEnums(node, options) {
|
|
1603
|
+
const macro = macroEnumName(options);
|
|
1604
|
+
const named = ast.applyMacros(node, [macro], { depth: "shallow" });
|
|
1605
|
+
const tupleNode = ast.narrowSchema(named, "tuple");
|
|
1606
|
+
if (tupleNode?.items) {
|
|
1607
|
+
const namedItems = tupleNode.items.map((item) => ast.applyMacros(item, [macro], { depth: "shallow" }));
|
|
1608
|
+
if (namedItems.some((item, i) => item !== tupleNode.items[i])) return {
|
|
1609
|
+
...tupleNode,
|
|
1610
|
+
items: namedItems
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
return named;
|
|
1614
|
+
}
|
|
1615
|
+
/**
|
|
1563
1616
|
* Factory function that creates schema and operation converters for a given OpenAPI context.
|
|
1564
1617
|
*
|
|
1565
1618
|
* Returns closures that share mutable state (`resolvingRefs` set for cycle detection).
|
|
@@ -1598,7 +1651,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1598
1651
|
if (refPath && !resolvingRefs.has(refPath)) {
|
|
1599
1652
|
if (!resolvedRefCache.has(refPath)) {
|
|
1600
1653
|
try {
|
|
1601
|
-
const referenced = dialect.resolveRef(document, refPath);
|
|
1654
|
+
const referenced = dialect.schema.resolveRef(document, refPath);
|
|
1602
1655
|
if (referenced) {
|
|
1603
1656
|
resolvingRefs.add(refPath);
|
|
1604
1657
|
resolvedSchema = parseSchema({ schema: referenced }, rawOptions);
|
|
@@ -1647,13 +1700,13 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1647
1700
|
}
|
|
1648
1701
|
const filteredDiscriminantValues = [];
|
|
1649
1702
|
const allOfMembers = schema.allOf.filter((item) => {
|
|
1650
|
-
if (!dialect.isReference(item) || !name) return true;
|
|
1651
|
-
const deref = dialect.resolveRef(document, item.$ref);
|
|
1652
|
-
if (!deref || !dialect.isDiscriminator(deref)) return true;
|
|
1703
|
+
if (!dialect.schema.isReference(item) || !name) return true;
|
|
1704
|
+
const deref = dialect.schema.resolveRef(document, item.$ref);
|
|
1705
|
+
if (!deref || !dialect.schema.isDiscriminator(deref)) return true;
|
|
1653
1706
|
const parentUnion = deref.oneOf ?? deref.anyOf;
|
|
1654
1707
|
if (!parentUnion) return true;
|
|
1655
1708
|
const childRef = `${SCHEMA_REF_PREFIX}${name}`;
|
|
1656
|
-
const inOneOf = parentUnion.some((oneOfItem) => dialect.isReference(oneOfItem) && oneOfItem.$ref === childRef);
|
|
1709
|
+
const inOneOf = parentUnion.some((oneOfItem) => dialect.schema.isReference(oneOfItem) && oneOfItem.$ref === childRef);
|
|
1657
1710
|
const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
|
|
1658
1711
|
if (inOneOf || inMapping) {
|
|
1659
1712
|
const discriminatorValue = findDiscriminator(deref.discriminator.mapping, childRef);
|
|
@@ -1674,9 +1727,9 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1674
1727
|
const missingRequired = schema.required.filter((key) => !outerKeys.has(key));
|
|
1675
1728
|
if (missingRequired.length) {
|
|
1676
1729
|
const resolvedMembers = schema.allOf.flatMap((item) => {
|
|
1677
|
-
if (!dialect.isReference(item)) return [item];
|
|
1678
|
-
const deref = dialect.resolveRef(document, item.$ref);
|
|
1679
|
-
return deref && !dialect.isReference(deref) ? [deref] : [];
|
|
1730
|
+
if (!dialect.schema.isReference(item)) return [item];
|
|
1731
|
+
const deref = dialect.schema.resolveRef(document, item.$ref);
|
|
1732
|
+
return deref && !dialect.schema.isReference(deref) ? [deref] : [];
|
|
1680
1733
|
});
|
|
1681
1734
|
for (const key of missingRequired) for (const resolved of resolvedMembers) if (resolved.properties?.[key]) {
|
|
1682
1735
|
allOfMembers.push(parseSchema({
|
|
@@ -1700,7 +1753,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1700
1753
|
}));
|
|
1701
1754
|
return ast.factory.createSchema({
|
|
1702
1755
|
type: "intersection",
|
|
1703
|
-
members: [...
|
|
1756
|
+
members: [...mergeAdjacentObjectsLazy(allOfMembers.slice(0, syntheticStart)), ...mergeAdjacentObjectsLazy(allOfMembers.slice(syntheticStart))],
|
|
1704
1757
|
...buildSchemaNode(schema, name, nullable, defaultValue)
|
|
1705
1758
|
});
|
|
1706
1759
|
}
|
|
@@ -1721,10 +1774,10 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1721
1774
|
const strategy = schema.oneOf ? "one" : "any";
|
|
1722
1775
|
const unionBase = {
|
|
1723
1776
|
...buildSchemaNode(schema, name, nullable, defaultValue),
|
|
1724
|
-
discriminatorPropertyName: dialect.isDiscriminator(schema) ? schema.discriminator.propertyName : void 0,
|
|
1777
|
+
discriminatorPropertyName: dialect.schema.isDiscriminator(schema) ? schema.discriminator.propertyName : void 0,
|
|
1725
1778
|
strategy
|
|
1726
1779
|
};
|
|
1727
|
-
const discriminator = dialect.isDiscriminator(schema) ? schema.discriminator : void 0;
|
|
1780
|
+
const discriminator = dialect.schema.isDiscriminator(schema) ? schema.discriminator : void 0;
|
|
1728
1781
|
const sharedPropertiesNode = schema.properties ? (() => {
|
|
1729
1782
|
const { oneOf: _oneOf, anyOf: _anyOf, ...schemaWithoutUnion } = schema;
|
|
1730
1783
|
return parseSchema({
|
|
@@ -1734,18 +1787,17 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1734
1787
|
})() : void 0;
|
|
1735
1788
|
if (sharedPropertiesNode || discriminator?.mapping) {
|
|
1736
1789
|
const members = unionMembers.map((s) => {
|
|
1737
|
-
const ref = dialect.isReference(s) ? s.$ref : void 0;
|
|
1790
|
+
const ref = dialect.schema.isReference(s) ? s.$ref : void 0;
|
|
1738
1791
|
const discriminatorValue = findDiscriminator(discriminator?.mapping, ref);
|
|
1739
1792
|
const memberNode = parseSchema({
|
|
1740
1793
|
schema: s,
|
|
1741
1794
|
name
|
|
1742
1795
|
}, rawOptions);
|
|
1743
1796
|
if (!discriminatorValue || !discriminator) return memberNode;
|
|
1744
|
-
const narrowedDiscriminatorNode = sharedPropertiesNode ? pickDiscriminatorPropertyNode(ast.
|
|
1745
|
-
node: sharedPropertiesNode,
|
|
1797
|
+
const narrowedDiscriminatorNode = sharedPropertiesNode ? pickDiscriminatorPropertyNode(ast.applyMacros(sharedPropertiesNode, [macroDiscriminatorEnum({
|
|
1746
1798
|
propertyName: discriminator.propertyName,
|
|
1747
1799
|
values: [discriminatorValue]
|
|
1748
|
-
}), discriminator.propertyName) : void 0;
|
|
1800
|
+
})], { depth: "shallow" }), discriminator.propertyName) : void 0;
|
|
1749
1801
|
return ast.factory.createSchema({
|
|
1750
1802
|
type: "intersection",
|
|
1751
1803
|
members: [memberNode, narrowedDiscriminatorNode ?? createDiscriminantNode({
|
|
@@ -1766,29 +1818,22 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1766
1818
|
members: [unionNode, sharedPropertiesNode]
|
|
1767
1819
|
});
|
|
1768
1820
|
}
|
|
1769
|
-
|
|
1821
|
+
const unionNode = ast.factory.createSchema({
|
|
1770
1822
|
type: "union",
|
|
1771
1823
|
...unionBase,
|
|
1772
|
-
members:
|
|
1824
|
+
members: unionMembers.map((s) => parseSchema({
|
|
1773
1825
|
schema: s,
|
|
1774
1826
|
name
|
|
1775
|
-
}, rawOptions))
|
|
1827
|
+
}, rawOptions))
|
|
1776
1828
|
});
|
|
1829
|
+
return ast.applyMacros(unionNode, [macroSimplifyUnion], { depth: "shallow" });
|
|
1777
1830
|
}
|
|
1778
1831
|
/**
|
|
1779
1832
|
* Converts an OAS 3.1 `const` schema into a null scalar or a single-value `EnumSchemaNode`.
|
|
1780
1833
|
*/
|
|
1781
1834
|
function convertConst({ schema, name, nullable, defaultValue }) {
|
|
1782
1835
|
const constValue = schema.const;
|
|
1783
|
-
if (constValue === null) return
|
|
1784
|
-
type: "null",
|
|
1785
|
-
primitive: "null",
|
|
1786
|
-
name,
|
|
1787
|
-
title: schema.title,
|
|
1788
|
-
description: schema.description,
|
|
1789
|
-
deprecated: schema.deprecated,
|
|
1790
|
-
format: schema.format
|
|
1791
|
-
});
|
|
1836
|
+
if (constValue === null) return createNullSchema(schema, name);
|
|
1792
1837
|
const constPrimitive = getPrimitiveType(typeof constValue === "number" ? "number" : typeof constValue === "boolean" ? "boolean" : "string");
|
|
1793
1838
|
return ast.factory.createSchema({
|
|
1794
1839
|
type: "enum",
|
|
@@ -1877,15 +1922,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1877
1922
|
}, rawOptions);
|
|
1878
1923
|
const nullInEnum = schema.enum.includes(null);
|
|
1879
1924
|
const filteredValues = nullInEnum ? schema.enum.filter((v) => v !== null) : schema.enum;
|
|
1880
|
-
if (nullInEnum && filteredValues.length === 0) return
|
|
1881
|
-
type: "null",
|
|
1882
|
-
primitive: "null",
|
|
1883
|
-
name,
|
|
1884
|
-
title: schema.title,
|
|
1885
|
-
description: schema.description,
|
|
1886
|
-
deprecated: schema.deprecated,
|
|
1887
|
-
format: schema.format
|
|
1888
|
-
});
|
|
1925
|
+
if (nullInEnum && filteredValues.length === 0) return createNullSchema(schema, name);
|
|
1889
1926
|
const enumNullable = nullable || nullInEnum || void 0;
|
|
1890
1927
|
const enumDefault = schema.default === null && enumNullable ? void 0 : schema.default;
|
|
1891
1928
|
const enumPrimitive = getPrimitiveType(type);
|
|
@@ -1935,23 +1972,15 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1935
1972
|
const properties = schema.properties ? Object.entries(schema.properties).map(([propName, propSchema]) => {
|
|
1936
1973
|
const required = Array.isArray(schema.required) ? schema.required.includes(propName) : !!schema.required;
|
|
1937
1974
|
const resolvedPropSchema = propSchema;
|
|
1938
|
-
const propNullable = dialect.isNullable(resolvedPropSchema);
|
|
1939
|
-
const
|
|
1975
|
+
const propNullable = dialect.schema.isNullable(resolvedPropSchema);
|
|
1976
|
+
const schemaNode = nameEnums(parseSchema({
|
|
1940
1977
|
schema: resolvedPropSchema,
|
|
1941
1978
|
name: childName(name, propName)
|
|
1942
|
-
}, rawOptions)
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
const namedItems = tupleNode.items.map((item) => ast.setEnumName(item, name, propName, options.enumSuffix));
|
|
1948
|
-
if (namedItems.some((item, i) => item !== tupleNode.items[i])) return {
|
|
1949
|
-
...tupleNode,
|
|
1950
|
-
items: namedItems
|
|
1951
|
-
};
|
|
1952
|
-
}
|
|
1953
|
-
return node;
|
|
1954
|
-
})();
|
|
1979
|
+
}, rawOptions), {
|
|
1980
|
+
parentName: name,
|
|
1981
|
+
propName,
|
|
1982
|
+
enumSuffix: options.enumSuffix
|
|
1983
|
+
});
|
|
1955
1984
|
return ast.factory.createProperty({
|
|
1956
1985
|
name: propName,
|
|
1957
1986
|
schema: {
|
|
@@ -1959,7 +1988,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1959
1988
|
nullable: schemaNode.type === "null" ? void 0 : propNullable || void 0
|
|
1960
1989
|
},
|
|
1961
1990
|
required
|
|
1962
|
-
});
|
|
1991
|
+
}, dialect);
|
|
1963
1992
|
}) : [];
|
|
1964
1993
|
const additionalProperties = schema.additionalProperties;
|
|
1965
1994
|
const additionalPropertiesNode = (() => {
|
|
@@ -1980,16 +2009,15 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1980
2009
|
maxProperties: schema.maxProperties,
|
|
1981
2010
|
...buildSchemaNode(schema, name, nullable, defaultValue)
|
|
1982
2011
|
});
|
|
1983
|
-
if (dialect.isDiscriminator(schema) && schema.discriminator.mapping) {
|
|
2012
|
+
if (dialect.schema.isDiscriminator(schema) && schema.discriminator.mapping) {
|
|
1984
2013
|
const discPropName = schema.discriminator.propertyName;
|
|
1985
2014
|
const values = Object.keys(schema.discriminator.mapping);
|
|
1986
2015
|
const enumName = name ? enumPropName(name, discPropName, options.enumSuffix) : void 0;
|
|
1987
|
-
return ast.
|
|
1988
|
-
node: objectNode,
|
|
2016
|
+
return ast.applyMacros(objectNode, [macroDiscriminatorEnum({
|
|
1989
2017
|
propertyName: discPropName,
|
|
1990
2018
|
values,
|
|
1991
2019
|
enumName
|
|
1992
|
-
});
|
|
2020
|
+
})], { depth: "shallow" });
|
|
1993
2021
|
}
|
|
1994
2022
|
return objectNode;
|
|
1995
2023
|
}
|
|
@@ -2125,7 +2153,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2125
2153
|
const schemaRules = [
|
|
2126
2154
|
{
|
|
2127
2155
|
name: "ref",
|
|
2128
|
-
match: ({ schema }) => dialect.isReference(schema),
|
|
2156
|
+
match: ({ schema }) => dialect.schema.isReference(schema),
|
|
2129
2157
|
convert: convertRef
|
|
2130
2158
|
},
|
|
2131
2159
|
{
|
|
@@ -2150,7 +2178,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2150
2178
|
},
|
|
2151
2179
|
{
|
|
2152
2180
|
name: "blob",
|
|
2153
|
-
match: ({ schema }) => dialect.isBinary(schema),
|
|
2181
|
+
match: ({ schema }) => dialect.schema.isBinary(schema),
|
|
2154
2182
|
convert: convertBlob
|
|
2155
2183
|
},
|
|
2156
2184
|
{
|
|
@@ -2231,7 +2259,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2231
2259
|
schema: flattenedSchema,
|
|
2232
2260
|
name
|
|
2233
2261
|
}, rawOptions);
|
|
2234
|
-
const nullable = dialect.isNullable(schema) || void 0;
|
|
2262
|
+
const nullable = dialect.schema.isNullable(schema) || void 0;
|
|
2235
2263
|
const schemaCtx = {
|
|
2236
2264
|
schema,
|
|
2237
2265
|
name,
|
|
@@ -2274,7 +2302,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2274
2302
|
description: param["description"] ?? schema.description
|
|
2275
2303
|
},
|
|
2276
2304
|
required
|
|
2277
|
-
});
|
|
2305
|
+
}, dialect);
|
|
2278
2306
|
}
|
|
2279
2307
|
/**
|
|
2280
2308
|
* Reads the inline `requestBody` metadata (description / required) that OAS exposes
|
|
@@ -2308,7 +2336,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2308
2336
|
const keys = [];
|
|
2309
2337
|
for (const key in schema.properties) {
|
|
2310
2338
|
const prop = schema.properties[key];
|
|
2311
|
-
if (prop && !dialect.isReference(prop) && prop[flag]) keys.push(key);
|
|
2339
|
+
if (prop && !dialect.schema.isReference(prop) && prop[flag]) keys.push(key);
|
|
2312
2340
|
}
|
|
2313
2341
|
return keys.length ? keys : null;
|
|
2314
2342
|
}
|
|
@@ -2325,14 +2353,14 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2325
2353
|
const content = allContentTypes.flatMap((ct) => {
|
|
2326
2354
|
const schema = getRequestSchema(document, operation, { contentType: ct });
|
|
2327
2355
|
if (!schema) return [];
|
|
2328
|
-
return [{
|
|
2356
|
+
return [ast.factory.createContent({
|
|
2329
2357
|
contentType: ct,
|
|
2330
|
-
schema:
|
|
2358
|
+
schema: dialect.schema.optionality(parseSchema({
|
|
2331
2359
|
schema,
|
|
2332
2360
|
name: requestBodyName
|
|
2333
2361
|
}, options), requestBodyMeta.required),
|
|
2334
2362
|
keysToOmit: collectPropertyKeysByFlag(schema, "readOnly")
|
|
2335
|
-
}];
|
|
2363
|
+
})];
|
|
2336
2364
|
});
|
|
2337
2365
|
const requestBody = content.length > 0 || requestBodyMeta.description ? {
|
|
2338
2366
|
description: requestBodyMeta.description,
|
|
@@ -2357,17 +2385,17 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2357
2385
|
keysToOmit: collectPropertyKeysByFlag(raw, "writeOnly")
|
|
2358
2386
|
};
|
|
2359
2387
|
};
|
|
2360
|
-
const content = (ctx.contentType ? [ctx.contentType] : getResponseBodyContentTypes(document, operation, statusCode)).map((contentType) => ({
|
|
2388
|
+
const content = (ctx.contentType ? [ctx.contentType] : getResponseBodyContentTypes(document, operation, statusCode)).map((contentType) => ast.factory.createContent({
|
|
2361
2389
|
contentType,
|
|
2362
2390
|
...parseEntrySchema(contentType)
|
|
2363
2391
|
}));
|
|
2364
|
-
if (content.length === 0) content.push({
|
|
2392
|
+
if (content.length === 0) content.push(ast.factory.createContent({
|
|
2365
2393
|
contentType: getRequestContentType({
|
|
2366
2394
|
document,
|
|
2367
2395
|
operation
|
|
2368
2396
|
}) || "application/json",
|
|
2369
2397
|
...parseEntrySchema(ctx.contentType)
|
|
2370
|
-
});
|
|
2398
|
+
}));
|
|
2371
2399
|
return ast.factory.createResponse({
|
|
2372
2400
|
statusCode,
|
|
2373
2401
|
description,
|
|
@@ -2375,7 +2403,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2375
2403
|
});
|
|
2376
2404
|
});
|
|
2377
2405
|
const pathItem = document.paths?.[operation.path];
|
|
2378
|
-
const pathItemDoc = pathItem && !dialect.isReference(pathItem) ? pathItem : void 0;
|
|
2406
|
+
const pathItemDoc = pathItem && !dialect.schema.isReference(pathItem) ? pathItem : void 0;
|
|
2379
2407
|
const pickDoc = (key) => {
|
|
2380
2408
|
const own = operation.schema[key];
|
|
2381
2409
|
if (typeof own === "string") return own;
|
|
@@ -2460,36 +2488,6 @@ function visit(node, pointer) {
|
|
|
2460
2488
|
//#endregion
|
|
2461
2489
|
//#region src/stream.ts
|
|
2462
2490
|
/**
|
|
2463
|
-
* Builds the deduplication plan from the already-parsed top-level schema nodes plus a
|
|
2464
|
-
* single extra parse pass over operations (so duplicates in request/response bodies are seen).
|
|
2465
|
-
*
|
|
2466
|
-
* Only enums and objects are candidates, and object shapes that reference a circular schema are
|
|
2467
|
-
* rejected to avoid hoisting recursive structures. Inline shapes reuse their context-derived
|
|
2468
|
-
* name (collision-resolved against existing component names). Shapes without a name stay inline.
|
|
2469
|
-
*/
|
|
2470
|
-
function createDedupePlan({ schemaNodes, operationNodes, schemaNames, circularNames }) {
|
|
2471
|
-
const circularSchemas = new Set(circularNames);
|
|
2472
|
-
const usedNames = new Set(schemaNames);
|
|
2473
|
-
return ast.buildDedupePlan([...schemaNodes, ...operationNodes], {
|
|
2474
|
-
isCandidate: (node) => {
|
|
2475
|
-
if (node.type === "enum") return true;
|
|
2476
|
-
if (node.type !== "object") return false;
|
|
2477
|
-
if (node.name && circularSchemas.has(node.name)) return false;
|
|
2478
|
-
return !containsCircularRef(node, { circularSchemas });
|
|
2479
|
-
},
|
|
2480
|
-
nameFor: (node) => {
|
|
2481
|
-
const base = node.name;
|
|
2482
|
-
if (!base) return null;
|
|
2483
|
-
let name = base;
|
|
2484
|
-
let counter = 2;
|
|
2485
|
-
while (usedNames.has(name)) name = `${base}${counter++}`;
|
|
2486
|
-
usedNames.add(name);
|
|
2487
|
-
return name;
|
|
2488
|
-
},
|
|
2489
|
-
refFor: (name) => `${SCHEMA_REF_PREFIX}${name}`
|
|
2490
|
-
});
|
|
2491
|
-
}
|
|
2492
|
-
/**
|
|
2493
2491
|
* Reads the server URL from the document's `servers` array at `serverIndex`,
|
|
2494
2492
|
* interpolating any `serverVariables` into the URL template.
|
|
2495
2493
|
*
|
|
@@ -2558,11 +2556,25 @@ function preScan({ schemas, parseSchema, parseOperation, document, parserOptions
|
|
|
2558
2556
|
const operationNode = parseOperation(parserOptions, operation);
|
|
2559
2557
|
if (operationNode) operationNodes.push(operationNode);
|
|
2560
2558
|
}
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2559
|
+
const circularSchemas = new Set(circularNames);
|
|
2560
|
+
const usedNames = new Set(Object.keys(schemas));
|
|
2561
|
+
dedupePlan = ast.buildDedupePlan([...allNodes, ...operationNodes], {
|
|
2562
|
+
isCandidate: (node) => {
|
|
2563
|
+
if (node.type === "enum") return true;
|
|
2564
|
+
if (node.type !== "object") return false;
|
|
2565
|
+
if (node.name && circularSchemas.has(node.name)) return false;
|
|
2566
|
+
return !containsCircularRef(node, { circularSchemas });
|
|
2567
|
+
},
|
|
2568
|
+
nameFor: (node) => {
|
|
2569
|
+
const base = node.name;
|
|
2570
|
+
if (!base) return null;
|
|
2571
|
+
let name = base;
|
|
2572
|
+
let counter = 2;
|
|
2573
|
+
while (usedNames.has(name)) name = `${base}${counter++}`;
|
|
2574
|
+
usedNames.add(name);
|
|
2575
|
+
return name;
|
|
2576
|
+
},
|
|
2577
|
+
refFor: (name) => `${SCHEMA_REF_PREFIX}${name}`
|
|
2566
2578
|
});
|
|
2567
2579
|
for (const definition of dedupePlan.hoisted) if (definition.type === "enum" && definition.name) enumNames.push(definition.name);
|
|
2568
2580
|
}
|