@kubb/adapter-oas 5.0.0-beta.57 → 5.0.0-beta.59

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.js CHANGED
@@ -5,7 +5,7 @@ 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 { childName, enumPropName, extractRefName, findDiscriminator } from "@kubb/ast/utils";
8
+ import { childName, containsCircularRef, enumPropName, extractRefName, findCircularSchemas } from "@kubb/ast/utils";
9
9
  import { collect, narrowSchema } from "@kubb/ast";
10
10
  //#region src/constants.ts
11
11
  /**
@@ -91,7 +91,7 @@ const structuralKeys = new Set([
91
91
  *
92
92
  * Only formats whose AST type differs from the OAS `type` field appear here.
93
93
  * Formats that depend on runtime options (`int64`, `date-time`, `date`, `time`) are handled separately
94
- * in the parser. `ipv4` and `ipv6` map to their own dedicated schema types; `hostname` and
94
+ * in the parser. `ipv4` and `ipv6` map to their own dedicated schema types. `hostname` and
95
95
  * `idn-hostname` map to `'url'` as the closest generic string-format type.
96
96
  *
97
97
  * @example
@@ -144,8 +144,8 @@ const formatMap = {
144
144
  */
145
145
  const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
146
146
  /**
147
- * Maps `'any' | 'unknown' | 'void'` option strings to their `ScalarSchemaType` constant.
148
- * Replaces a plain object lookup with a `Map` for explicit key membership testing via `.has()`.
147
+ * Maps the `unknownType`/`emptySchemaType` option string to its `ScalarSchemaType` constant.
148
+ * A `Map` (over a plain object) lets callers test key membership with `.has()`.
149
149
  */
150
150
  const typeOptionMap = new Map([
151
151
  ["any", ast.schemaTypes.any],
@@ -840,6 +840,120 @@ const oasDialect = ast.defineSchemaDialect({
840
840
  resolveRef
841
841
  });
842
842
  //#endregion
843
+ //#region src/discriminator.ts
844
+ /**
845
+ * Builds a map of child schema names → discriminator patch data by scanning the given
846
+ * top-level AST schema nodes for union schemas that carry a `discriminatorPropertyName`.
847
+ *
848
+ * The streaming path calls this on a small pre-parsed subset of schemas (only the
849
+ * discriminator parents) rather than on all schemas at once.
850
+ */
851
+ function buildDiscriminatorChildMap(schemas) {
852
+ const childMap = /* @__PURE__ */ new Map();
853
+ for (const schema of schemas) {
854
+ let unionNode = ast.narrowSchema(schema, "union");
855
+ if (!unionNode) {
856
+ const intersectionMembers = ast.narrowSchema(schema, "intersection")?.members;
857
+ if (intersectionMembers) for (const m of intersectionMembers) {
858
+ const u = ast.narrowSchema(m, "union");
859
+ if (u) {
860
+ unionNode = u;
861
+ break;
862
+ }
863
+ }
864
+ }
865
+ if (!unionNode?.discriminatorPropertyName || !unionNode.members) continue;
866
+ const { discriminatorPropertyName, members } = unionNode;
867
+ for (const member of members) {
868
+ const intersectionNode = ast.narrowSchema(member, "intersection");
869
+ if (!intersectionNode?.members) continue;
870
+ let refNode = null;
871
+ let objNode = null;
872
+ for (const m of intersectionNode.members) {
873
+ refNode ??= ast.narrowSchema(m, "ref");
874
+ objNode ??= ast.narrowSchema(m, "object");
875
+ }
876
+ if (!refNode?.name || !objNode) continue;
877
+ const prop = objNode.properties.find((p) => p.name === discriminatorPropertyName);
878
+ const enumNode = prop ? ast.narrowSchema(prop.schema, "enum") : null;
879
+ if (!enumNode?.enumValues?.length) continue;
880
+ const enumValues = enumNode.enumValues.filter((v) => v !== null);
881
+ if (!enumValues.length) continue;
882
+ const existing = childMap.get(refNode.name);
883
+ if (!existing) {
884
+ childMap.set(refNode.name, {
885
+ propertyName: discriminatorPropertyName,
886
+ enumValues: [...enumValues]
887
+ });
888
+ continue;
889
+ }
890
+ existing.enumValues.push(...enumValues);
891
+ }
892
+ }
893
+ return childMap;
894
+ }
895
+ /**
896
+ * Patches a single top-level `SchemaNode` with its discriminator entry (adds or replaces
897
+ * the discriminant property). Used by the streaming path to apply patches inline per yield
898
+ * without buffering all schemas.
899
+ */
900
+ function patchDiscriminatorNode(node, entry) {
901
+ const objectNode = ast.narrowSchema(node, "object");
902
+ if (!objectNode) return node;
903
+ const { propertyName, enumValues } = entry;
904
+ const enumSchema = ast.factory.createSchema({
905
+ type: "enum",
906
+ enumValues
907
+ });
908
+ const newProp = ast.factory.createProperty({
909
+ name: propertyName,
910
+ required: true,
911
+ schema: enumSchema
912
+ });
913
+ const existingIdx = objectNode.properties.findIndex((p) => p.name === propertyName);
914
+ const newProperties = existingIdx >= 0 ? objectNode.properties.map((p, i) => i === existingIdx ? newProp : p) : [...objectNode.properties, newProp];
915
+ return {
916
+ ...objectNode,
917
+ properties: newProperties
918
+ };
919
+ }
920
+ /**
921
+ * Creates a single-property object schema used as a discriminator literal.
922
+ *
923
+ * @example
924
+ * ```ts
925
+ * createDiscriminantNode({ propertyName: 'type', value: 'dog' })
926
+ * // -> { type: 'object', properties: [{ name: 'type', required: true, schema: enum('dog') }] }
927
+ * ```
928
+ */
929
+ function createDiscriminantNode({ propertyName, value }) {
930
+ return ast.factory.createSchema({
931
+ type: "object",
932
+ primitive: "object",
933
+ properties: [ast.factory.createProperty({
934
+ name: propertyName,
935
+ schema: ast.factory.createSchema({
936
+ type: "enum",
937
+ primitive: "string",
938
+ enumValues: [value]
939
+ }),
940
+ required: true
941
+ })]
942
+ });
943
+ }
944
+ /**
945
+ * Returns the discriminator key whose mapping value matches `ref`, or `null` when there is no match.
946
+ *
947
+ * @example
948
+ * ```ts
949
+ * findDiscriminator({ dog: '#/components/schemas/Dog' }, '#/components/schemas/Dog') // 'dog'
950
+ * ```
951
+ */
952
+ function findDiscriminator(mapping, ref) {
953
+ if (!mapping || !ref) return null;
954
+ return Object.entries(mapping).find(([, value]) => value === ref)?.[0] ?? null;
955
+ }
956
+ //#endregion
843
957
  //#region src/mime.ts
844
958
  /**
845
959
  * MIME type fragments that mark a media type as JSON-like.
@@ -1328,7 +1442,7 @@ function getSchemas(document, { contentType }) {
1328
1442
  }
1329
1443
  /**
1330
1444
  * Resolves the AST type descriptor for a date/time format, honoring the `dateType` option.
1331
- * Returns `null` when `dateType: false`, signalling the format should fall through to `string`.
1445
+ * Returns `null` when `dateType: false`, so the format falls through to `string`.
1332
1446
  */
1333
1447
  function getDateType(options, format) {
1334
1448
  if (!options.dateType) return null;
@@ -1430,9 +1544,9 @@ function getResponseBodyContentTypes(document, operation, statusCode) {
1430
1544
  * Normalizes malformed `{ type: 'array', enum: [...] }` schemas by moving enum values into items.
1431
1545
  *
1432
1546
  * This pattern violates the OpenAPI spec but appears in real specs. The fix moves enum values
1433
- * from the array to its items sub-schema, making them valid for downstream processing.
1547
+ * from the array to its items sub-schema, so they are valid for downstream processing.
1434
1548
  *
1435
- * @note This is a defensive measure for robustness with non-compliant specs.
1549
+ * @note A defensive measure for non-compliant specs.
1436
1550
  */
1437
1551
  function normalizeArrayEnum(schema) {
1438
1552
  const normalizedItems = {
@@ -1450,7 +1564,7 @@ function normalizeArrayEnum(schema) {
1450
1564
  *
1451
1565
  * Returns closures that share mutable state (`resolvingRefs` set for cycle detection).
1452
1566
  * Each converter branch (`convertRef`, `convertAllOf`, etc.) mutually recursively calls `parseSchema`,
1453
- * made possible by hoisting of function declarations.
1567
+ * which works because function declarations hoist.
1454
1568
  *
1455
1569
  * @internal
1456
1570
  */
@@ -1495,7 +1609,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1495
1609
  }
1496
1610
  resolvedSchema = resolvedRefCache.get(refPath) ?? null;
1497
1611
  }
1498
- return ast.createSchema({
1612
+ return ast.factory.createSchema({
1499
1613
  ...buildSchemaNode(schema, name, nullable, defaultValue),
1500
1614
  type: "ref",
1501
1615
  name: extractRefName(schema.$ref),
@@ -1516,7 +1630,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1516
1630
  const { kind: _kind, ...memberNodeProps } = memberNode;
1517
1631
  const mergedNullable = nullable || memberNode.nullable || void 0;
1518
1632
  const mergedDefault = schema.default === null && mergedNullable ? void 0 : schema.default ?? memberNode.default;
1519
- return ast.createSchema({
1633
+ return ast.factory.createSchema({
1520
1634
  ...memberNodeProps,
1521
1635
  name,
1522
1636
  title: schema.title ?? memberNode.title,
@@ -1580,11 +1694,11 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1580
1694
  const { allOf: _allOf, ...schemaWithoutAllOf } = schema;
1581
1695
  allOfMembers.push(parseSchema({ schema: schemaWithoutAllOf }, rawOptions));
1582
1696
  }
1583
- for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push(ast.createDiscriminantNode({
1697
+ for (const { propertyName, value } of filteredDiscriminantValues) allOfMembers.push(createDiscriminantNode({
1584
1698
  propertyName,
1585
1699
  value
1586
1700
  }));
1587
- return ast.createSchema({
1701
+ return ast.factory.createSchema({
1588
1702
  type: "intersection",
1589
1703
  members: [...ast.mergeAdjacentObjectsLazy(allOfMembers.slice(0, syntheticStart)), ...ast.mergeAdjacentObjectsLazy(allOfMembers.slice(syntheticStart))],
1590
1704
  ...buildSchemaNode(schema, name, nullable, defaultValue)
@@ -1597,7 +1711,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1597
1711
  function pickDiscriminatorPropertyNode(node, propertyName) {
1598
1712
  const discriminatorProperty = ast.narrowSchema(node, "object")?.properties?.find((property) => property.name === propertyName);
1599
1713
  if (!discriminatorProperty) return null;
1600
- return ast.createSchema({
1714
+ return ast.factory.createSchema({
1601
1715
  type: "object",
1602
1716
  primitive: "object",
1603
1717
  properties: [discriminatorProperty]
@@ -1632,27 +1746,27 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1632
1746
  propertyName: discriminator.propertyName,
1633
1747
  values: [discriminatorValue]
1634
1748
  }), discriminator.propertyName) : void 0;
1635
- return ast.createSchema({
1749
+ return ast.factory.createSchema({
1636
1750
  type: "intersection",
1637
- members: [memberNode, narrowedDiscriminatorNode ?? ast.createDiscriminantNode({
1751
+ members: [memberNode, narrowedDiscriminatorNode ?? createDiscriminantNode({
1638
1752
  propertyName: discriminator.propertyName,
1639
1753
  value: discriminatorValue
1640
1754
  })]
1641
1755
  });
1642
1756
  });
1643
- const unionNode = ast.createSchema({
1757
+ const unionNode = ast.factory.createSchema({
1644
1758
  type: "union",
1645
1759
  ...unionBase,
1646
1760
  members
1647
1761
  });
1648
1762
  if (!sharedPropertiesNode) return unionNode;
1649
- return ast.createSchema({
1763
+ return ast.factory.createSchema({
1650
1764
  type: "intersection",
1651
1765
  ...buildSchemaNode(schema, name, nullable, defaultValue),
1652
1766
  members: [unionNode, sharedPropertiesNode]
1653
1767
  });
1654
1768
  }
1655
- return ast.createSchema({
1769
+ return ast.factory.createSchema({
1656
1770
  type: "union",
1657
1771
  ...unionBase,
1658
1772
  members: ast.simplifyUnion(unionMembers.map((s) => parseSchema({
@@ -1666,7 +1780,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1666
1780
  */
1667
1781
  function convertConst({ schema, name, nullable, defaultValue }) {
1668
1782
  const constValue = schema.const;
1669
- if (constValue === null) return ast.createSchema({
1783
+ if (constValue === null) return ast.factory.createSchema({
1670
1784
  type: "null",
1671
1785
  primitive: "null",
1672
1786
  name,
@@ -1676,7 +1790,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1676
1790
  format: schema.format
1677
1791
  });
1678
1792
  const constPrimitive = getPrimitiveType(typeof constValue === "number" ? "number" : typeof constValue === "boolean" ? "boolean" : "string");
1679
- return ast.createSchema({
1793
+ return ast.factory.createSchema({
1680
1794
  type: "enum",
1681
1795
  primitive: constPrimitive,
1682
1796
  enumValues: [constValue],
@@ -1689,7 +1803,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1689
1803
  */
1690
1804
  function convertFormat({ schema, name, nullable, defaultValue, options }) {
1691
1805
  const base = buildSchemaNode(schema, name, nullable, defaultValue);
1692
- if (schema.format === "int64") return ast.createSchema({
1806
+ if (schema.format === "int64") return ast.factory.createSchema({
1693
1807
  type: options.integerType === "bigint" ? "bigint" : "integer",
1694
1808
  primitive: "integer",
1695
1809
  ...base,
@@ -1701,14 +1815,14 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1701
1815
  if (schema.format === "date-time" || schema.format === "date" || schema.format === "time") {
1702
1816
  const dateType = getDateType(options, schema.format);
1703
1817
  if (!dateType) return null;
1704
- if (dateType.type === "datetime") return ast.createSchema({
1818
+ if (dateType.type === "datetime") return ast.factory.createSchema({
1705
1819
  ...base,
1706
1820
  primitive: "string",
1707
1821
  type: "datetime",
1708
1822
  offset: dateType.offset,
1709
1823
  local: dateType.local
1710
1824
  });
1711
- return ast.createSchema({
1825
+ return ast.factory.createSchema({
1712
1826
  ...base,
1713
1827
  primitive: "string",
1714
1828
  type: dateType.type,
@@ -1718,36 +1832,36 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1718
1832
  const specialType = getSchemaType(schema.format);
1719
1833
  if (!specialType) return null;
1720
1834
  const specialPrimitive = specialType === "number" || specialType === "integer" || specialType === "bigint" ? specialType : "string";
1721
- if (specialType === "number" || specialType === "integer" || specialType === "bigint") return ast.createSchema({
1835
+ if (specialType === "number" || specialType === "integer" || specialType === "bigint") return ast.factory.createSchema({
1722
1836
  ...base,
1723
1837
  primitive: specialPrimitive,
1724
1838
  type: specialType
1725
1839
  });
1726
- if (specialType === "url") return ast.createSchema({
1840
+ if (specialType === "url") return ast.factory.createSchema({
1727
1841
  ...base,
1728
1842
  primitive: "string",
1729
1843
  type: "url",
1730
1844
  min: schema.minLength,
1731
1845
  max: schema.maxLength
1732
1846
  });
1733
- if (specialType === "ipv4") return ast.createSchema({
1847
+ if (specialType === "ipv4") return ast.factory.createSchema({
1734
1848
  ...base,
1735
1849
  primitive: "string",
1736
1850
  type: "ipv4"
1737
1851
  });
1738
- if (specialType === "ipv6") return ast.createSchema({
1852
+ if (specialType === "ipv6") return ast.factory.createSchema({
1739
1853
  ...base,
1740
1854
  primitive: "string",
1741
1855
  type: "ipv6"
1742
1856
  });
1743
- if (specialType === "uuid" || specialType === "email") return ast.createSchema({
1857
+ if (specialType === "uuid" || specialType === "email") return ast.factory.createSchema({
1744
1858
  ...base,
1745
1859
  primitive: "string",
1746
1860
  type: specialType,
1747
1861
  min: schema.minLength,
1748
1862
  max: schema.maxLength
1749
1863
  });
1750
- return ast.createSchema({
1864
+ return ast.factory.createSchema({
1751
1865
  ...base,
1752
1866
  primitive: specialPrimitive,
1753
1867
  type: specialType
@@ -1763,7 +1877,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1763
1877
  }, rawOptions);
1764
1878
  const nullInEnum = schema.enum.includes(null);
1765
1879
  const filteredValues = nullInEnum ? schema.enum.filter((v) => v !== null) : schema.enum;
1766
- if (nullInEnum && filteredValues.length === 0) return ast.createSchema({
1880
+ if (nullInEnum && filteredValues.length === 0) return ast.factory.createSchema({
1767
1881
  type: "null",
1768
1882
  primitive: "null",
1769
1883
  name,
@@ -1795,7 +1909,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1795
1909
  const rawEnumNames = extensionKey ? schema[extensionKey] : void 0;
1796
1910
  const uniqueValues = [...new Set(filteredValues)];
1797
1911
  const seenNames = /* @__PURE__ */ new Set();
1798
- return ast.createSchema({
1912
+ return ast.factory.createSchema({
1799
1913
  ...enumBase,
1800
1914
  primitive: enumPrimitiveType,
1801
1915
  namedEnumValues: uniqueValues.map((value, index) => ({
@@ -1809,7 +1923,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1809
1923
  })
1810
1924
  });
1811
1925
  }
1812
- return ast.createSchema({
1926
+ return ast.factory.createSchema({
1813
1927
  ...enumBase,
1814
1928
  enumValues: [...new Set(filteredValues)]
1815
1929
  });
@@ -1838,7 +1952,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1838
1952
  }
1839
1953
  return node;
1840
1954
  })();
1841
- return ast.createProperty({
1955
+ return ast.factory.createProperty({
1842
1956
  name: propName,
1843
1957
  schema: {
1844
1958
  ...schemaNode,
@@ -1852,11 +1966,11 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1852
1966
  if (additionalProperties === true) return true;
1853
1967
  if (additionalProperties === false) return false;
1854
1968
  if (additionalProperties && Object.keys(additionalProperties).length > 0) return parseSchema({ schema: additionalProperties }, rawOptions);
1855
- if (additionalProperties) return ast.createSchema({ type: typeOptionMap.get(options.unknownType) });
1969
+ if (additionalProperties) return ast.factory.createSchema({ type: typeOptionMap.get(options.unknownType) });
1856
1970
  })();
1857
1971
  const rawPatternProperties = "patternProperties" in schema ? schema.patternProperties : void 0;
1858
- const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || typeof patternSchema === "object" && Object.keys(patternSchema).length === 0 ? ast.createSchema({ type: typeOptionMap.get(options.unknownType) }) : parseSchema({ schema: patternSchema }, rawOptions)])) : void 0;
1859
- const objectNode = ast.createSchema({
1972
+ const patternProperties = rawPatternProperties ? Object.fromEntries(Object.entries(rawPatternProperties).map(([pattern, patternSchema]) => [pattern, patternSchema === true || typeof patternSchema === "object" && Object.keys(patternSchema).length === 0 ? ast.factory.createSchema({ type: typeOptionMap.get(options.unknownType) }) : parseSchema({ schema: patternSchema }, rawOptions)])) : void 0;
1973
+ const objectNode = ast.factory.createSchema({
1860
1974
  type: "object",
1861
1975
  primitive: "object",
1862
1976
  properties,
@@ -1884,8 +1998,8 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1884
1998
  */
1885
1999
  function convertTuple({ schema, name, nullable, defaultValue, rawOptions }) {
1886
2000
  const tupleItems = (schema.prefixItems ?? []).map((item) => parseSchema({ schema: item }, rawOptions));
1887
- const rest = schema.items ? parseSchema({ schema: schema.items }, rawOptions) : ast.createSchema({ type: "any" });
1888
- return ast.createSchema({
2001
+ const rest = schema.items ? parseSchema({ schema: schema.items }, rawOptions) : ast.factory.createSchema({ type: "any" });
2002
+ return ast.factory.createSchema({
1889
2003
  type: "tuple",
1890
2004
  primitive: "array",
1891
2005
  items: tupleItems,
@@ -1905,7 +2019,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1905
2019
  schema: rawItems,
1906
2020
  name: itemName
1907
2021
  }, rawOptions)] : [];
1908
- return ast.createSchema({
2022
+ return ast.factory.createSchema({
1909
2023
  type: "array",
1910
2024
  primitive: "array",
1911
2025
  items,
@@ -1919,7 +2033,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1919
2033
  * Converts a `type: 'string'` schema into a `StringSchemaNode`.
1920
2034
  */
1921
2035
  function convertString({ schema, name, nullable, defaultValue }) {
1922
- return ast.createSchema({
2036
+ return ast.factory.createSchema({
1923
2037
  type: "string",
1924
2038
  primitive: "string",
1925
2039
  min: schema.minLength,
@@ -1932,7 +2046,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1932
2046
  * Converts a `type: 'number'` or `type: 'integer'` schema.
1933
2047
  */
1934
2048
  function convertNumeric({ schema, name, nullable, defaultValue }, type) {
1935
- return ast.createSchema({
2049
+ return ast.factory.createSchema({
1936
2050
  type,
1937
2051
  primitive: type,
1938
2052
  min: schema.minimum,
@@ -1947,7 +2061,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1947
2061
  * Converts a `type: 'boolean'` schema.
1948
2062
  */
1949
2063
  function convertBoolean({ schema, name, nullable, defaultValue }) {
1950
- return ast.createSchema({
2064
+ return ast.factory.createSchema({
1951
2065
  type: "boolean",
1952
2066
  primitive: "boolean",
1953
2067
  ...buildSchemaNode(schema, name, nullable, defaultValue)
@@ -1957,7 +2071,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1957
2071
  * Converts an explicit `type: 'null'` schema.
1958
2072
  */
1959
2073
  function convertNull({ schema, name, nullable }) {
1960
- return ast.createSchema({
2074
+ return ast.factory.createSchema({
1961
2075
  type: "null",
1962
2076
  primitive: "null",
1963
2077
  name,
@@ -1973,7 +2087,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1973
2087
  * into a `blob` node.
1974
2088
  */
1975
2089
  function convertBlob({ schema, name, nullable, defaultValue }) {
1976
- return ast.createSchema({
2090
+ return ast.factory.createSchema({
1977
2091
  type: "blob",
1978
2092
  primitive: "string",
1979
2093
  ...buildSchemaNode(schema, name, nullable, defaultValue)
@@ -1990,7 +2104,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
1990
2104
  const nonNullTypes = types.filter((t) => t !== "null");
1991
2105
  if (nonNullTypes.length <= 1) return null;
1992
2106
  const arrayNullable = types.includes("null") || nullable || void 0;
1993
- return ast.createSchema({
2107
+ return ast.factory.createSchema({
1994
2108
  type: "union",
1995
2109
  members: nonNullTypes.map((t) => parseSchema({
1996
2110
  schema: {
@@ -2133,7 +2247,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2133
2247
  if (node) return node;
2134
2248
  }
2135
2249
  const emptyType = typeOptionMap.get(options.emptySchemaType);
2136
- return ast.createSchema({
2250
+ return ast.factory.createSchema({
2137
2251
  type: emptyType,
2138
2252
  name,
2139
2253
  title: schema.title,
@@ -2151,8 +2265,8 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2151
2265
  const schema = param["schema"] ? parseSchema({
2152
2266
  schema: param["schema"],
2153
2267
  name: schemaName
2154
- }, options) : ast.createSchema({ type: typeOptionMap.get(options.unknownType) });
2155
- return ast.createParameter({
2268
+ }, options) : ast.factory.createSchema({ type: typeOptionMap.get(options.unknownType) });
2269
+ return ast.factory.createParameter({
2156
2270
  name: paramName,
2157
2271
  in: param["in"],
2158
2272
  schema: {
@@ -2239,7 +2353,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2239
2353
  schema: raw && Object.keys(raw).length > 0 ? parseSchema({
2240
2354
  schema: raw,
2241
2355
  name: responseName
2242
- }, options) : ast.createSchema({ type: typeOptionMap.get(options.emptySchemaType) }),
2356
+ }, options) : ast.factory.createSchema({ type: typeOptionMap.get(options.emptySchemaType) }),
2243
2357
  keysToOmit: collectPropertyKeysByFlag(raw, "writeOnly")
2244
2358
  };
2245
2359
  };
@@ -2254,7 +2368,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2254
2368
  }) || "application/json",
2255
2369
  ...parseEntrySchema(ctx.contentType)
2256
2370
  });
2257
- return ast.createResponse({
2371
+ return ast.factory.createResponse({
2258
2372
  statusCode,
2259
2373
  description,
2260
2374
  content
@@ -2268,7 +2382,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2268
2382
  const fallback = pathItemDoc?.[key];
2269
2383
  return typeof fallback === "string" ? fallback : void 0;
2270
2384
  };
2271
- return ast.createOperation({
2385
+ return ast.factory.createOperation({
2272
2386
  operationId,
2273
2387
  protocol: "http",
2274
2388
  method: operation.method.toUpperCase(),
@@ -2289,84 +2403,6 @@ function createSchemaParser(ctx, dialect = oasDialect) {
2289
2403
  };
2290
2404
  }
2291
2405
  //#endregion
2292
- //#region src/discriminator.ts
2293
- /**
2294
- * Builds a map of child schema names → discriminator patch data by scanning the given
2295
- * top-level AST schema nodes for union schemas that carry a `discriminatorPropertyName`.
2296
- *
2297
- * The streaming path calls this on a small pre-parsed subset of schemas (only the
2298
- * discriminator parents) rather than on all schemas at once.
2299
- */
2300
- function buildDiscriminatorChildMap(schemas) {
2301
- const childMap = /* @__PURE__ */ new Map();
2302
- for (const schema of schemas) {
2303
- let unionNode = ast.narrowSchema(schema, "union");
2304
- if (!unionNode) {
2305
- const intersectionMembers = ast.narrowSchema(schema, "intersection")?.members;
2306
- if (intersectionMembers) for (const m of intersectionMembers) {
2307
- const u = ast.narrowSchema(m, "union");
2308
- if (u) {
2309
- unionNode = u;
2310
- break;
2311
- }
2312
- }
2313
- }
2314
- if (!unionNode?.discriminatorPropertyName || !unionNode.members) continue;
2315
- const { discriminatorPropertyName, members } = unionNode;
2316
- for (const member of members) {
2317
- const intersectionNode = ast.narrowSchema(member, "intersection");
2318
- if (!intersectionNode?.members) continue;
2319
- let refNode = null;
2320
- let objNode = null;
2321
- for (const m of intersectionNode.members) {
2322
- refNode ??= ast.narrowSchema(m, "ref");
2323
- objNode ??= ast.narrowSchema(m, "object");
2324
- }
2325
- if (!refNode?.name || !objNode) continue;
2326
- const prop = objNode.properties.find((p) => p.name === discriminatorPropertyName);
2327
- const enumNode = prop ? ast.narrowSchema(prop.schema, "enum") : null;
2328
- if (!enumNode?.enumValues?.length) continue;
2329
- const enumValues = enumNode.enumValues.filter((v) => v !== null);
2330
- if (!enumValues.length) continue;
2331
- const existing = childMap.get(refNode.name);
2332
- if (!existing) {
2333
- childMap.set(refNode.name, {
2334
- propertyName: discriminatorPropertyName,
2335
- enumValues: [...enumValues]
2336
- });
2337
- continue;
2338
- }
2339
- existing.enumValues.push(...enumValues);
2340
- }
2341
- }
2342
- return childMap;
2343
- }
2344
- /**
2345
- * Patches a single top-level `SchemaNode` with its discriminator entry (adds or replaces
2346
- * the discriminant property). Used by the streaming path to apply patches inline per yield
2347
- * without buffering all schemas.
2348
- */
2349
- function patchDiscriminatorNode(node, entry) {
2350
- const objectNode = ast.narrowSchema(node, "object");
2351
- if (!objectNode) return node;
2352
- const { propertyName, enumValues } = entry;
2353
- const enumSchema = ast.createSchema({
2354
- type: "enum",
2355
- enumValues
2356
- });
2357
- const newProp = ast.createProperty({
2358
- name: propertyName,
2359
- required: true,
2360
- schema: enumSchema
2361
- });
2362
- const existingIdx = objectNode.properties.findIndex((p) => p.name === propertyName);
2363
- const newProperties = existingIdx >= 0 ? objectNode.properties.map((p, i) => i === existingIdx ? newProp : p) : [...objectNode.properties, newProp];
2364
- return {
2365
- ...objectNode,
2366
- properties: newProperties
2367
- };
2368
- }
2369
- //#endregion
2370
2406
  //#region src/schemaDiagnostics.ts
2371
2407
  /**
2372
2408
  * Reports the advisory diagnostics (`KUBB_UNSUPPORTED_FORMAT`, `KUBB_DEPRECATED`) for one
@@ -2429,7 +2465,7 @@ function visit(node, pointer) {
2429
2465
  *
2430
2466
  * Only enums and objects are candidates, and object shapes that reference a circular schema are
2431
2467
  * rejected to avoid hoisting recursive structures. Inline shapes reuse their context-derived
2432
- * name (collision-resolved against existing component names); shapes without a name stay inline.
2468
+ * name (collision-resolved against existing component names). Shapes without a name stay inline.
2433
2469
  */
2434
2470
  function createDedupePlan({ schemaNodes, operationNodes, schemaNames, circularNames }) {
2435
2471
  const circularSchemas = new Set(circularNames);
@@ -2439,7 +2475,7 @@ function createDedupePlan({ schemaNodes, operationNodes, schemaNames, circularNa
2439
2475
  if (node.type === "enum") return true;
2440
2476
  if (node.type !== "object") return false;
2441
2477
  if (node.name && circularSchemas.has(node.name)) return false;
2442
- return !ast.containsCircularRef(node, { circularSchemas });
2478
+ return !containsCircularRef(node, { circularSchemas });
2443
2479
  },
2444
2480
  nameFor: (node) => {
2445
2481
  const base = node.name;
@@ -2513,7 +2549,7 @@ function preScan({ schemas, parseSchema, parseOperation, document, parserOptions
2513
2549
  if (ast.narrowSchema(node, ast.schemaTypes.enum) && node.name) enumNames.push(node.name);
2514
2550
  if (discriminator === "inherit" && (schema.oneOf ?? schema.anyOf) && schema.discriminator?.propertyName) discriminatorParentNodes.push(node);
2515
2551
  }
2516
- const circularNames = [...ast.findCircularSchemas(allNodes)];
2552
+ const circularNames = [...findCircularSchemas(allNodes)];
2517
2553
  const discriminatorChildMap = discriminatorParentNodes.length > 0 ? buildDiscriminatorChildMap(discriminatorParentNodes) : null;
2518
2554
  let dedupePlan = null;
2519
2555
  if (dedupe) {
@@ -2561,7 +2597,7 @@ function createInputStream({ schemas, parseSchema, parseOperation, document, par
2561
2597
  const rewriteTopLevelSchema = (node) => {
2562
2598
  if (!dedupePlan) return node;
2563
2599
  const canonical = dedupePlan.canonicalBySignature.get(ast.signatureOf(node));
2564
- if (canonical && canonical.name !== node.name) return ast.createSchema({
2600
+ if (canonical && canonical.name !== node.name) return ast.factory.createSchema({
2565
2601
  type: "ref",
2566
2602
  name: node.name ?? null,
2567
2603
  ref: canonical.ref,
@@ -2602,7 +2638,12 @@ function createInputStream({ schemas, parseSchema, parseOperation, document, par
2602
2638
  }
2603
2639
  })();
2604
2640
  } };
2605
- return ast.createStreamInput(schemasIterable, operationsIterable, meta);
2641
+ return ast.factory.createInput({
2642
+ stream: true,
2643
+ schemas: schemasIterable,
2644
+ operations: operationsIterable,
2645
+ meta
2646
+ });
2606
2647
  }
2607
2648
  //#endregion
2608
2649
  //#region src/adapter.ts
@@ -2761,7 +2802,7 @@ const adapterOas = createAdapter((options) => {
2761
2802
  const rawName = extractRefName(schemaRef.ref);
2762
2803
  const result = resolve(nameMapping.get(rawName) ?? rawName);
2763
2804
  if (!result) return null;
2764
- return ast.createImport({
2805
+ return ast.factory.createImport({
2765
2806
  name: [result.name],
2766
2807
  path: result.path
2767
2808
  });
@@ -2770,7 +2811,7 @@ const adapterOas = createAdapter((options) => {
2770
2811
  async parse(source) {
2771
2812
  const streamNode = await createStream(source);
2772
2813
  const [schemas, operations] = await Promise.all([Array.fromAsync(streamNode.schemas), Array.fromAsync(streamNode.operations)]);
2773
- return ast.createInput({
2814
+ return ast.factory.createInput({
2774
2815
  schemas,
2775
2816
  operations,
2776
2817
  meta: streamNode.meta