@kubb/adapter-oas 5.0.0-beta.62 → 5.0.0-beta.63
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 +216 -94
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +216 -94
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/adapter.ts +1 -1
- package/src/constants.ts +13 -14
- package/src/dedupe.ts +237 -0
- package/src/dialect.ts +2 -20
- package/src/discriminator.ts +1 -1
- package/src/factory.ts +1 -1
- package/src/mime.ts +2 -3
- package/src/operation.ts +2 -2
- package/src/parser.ts +16 -22
- package/src/refs.ts +4 -3
- package/src/resolvers.ts +13 -5
- package/src/stream.ts +16 -59
- package/src/types.ts +1 -1
package/dist/index.cjs
CHANGED
|
@@ -37,10 +37,9 @@ let _kubb_ast = require("@kubb/ast");
|
|
|
37
37
|
*
|
|
38
38
|
* @example
|
|
39
39
|
* ```ts
|
|
40
|
-
* import { DEFAULT_PARSER_OPTIONS } from '@kubb/adapter-oas'
|
|
40
|
+
* import { DEFAULT_PARSER_OPTIONS, parseOas } from '@kubb/adapter-oas'
|
|
41
41
|
*
|
|
42
|
-
* const
|
|
43
|
-
* const root = parser.parse({ ...DEFAULT_PARSER_OPTIONS, dateType: 'date' })
|
|
42
|
+
* const { root } = parseOas(document, { ...DEFAULT_PARSER_OPTIONS, dateType: 'date' })
|
|
44
43
|
* ```
|
|
45
44
|
*/
|
|
46
45
|
const DEFAULT_PARSER_OPTIONS = {
|
|
@@ -111,12 +110,24 @@ const structuralKeys = new Set([
|
|
|
111
110
|
"not"
|
|
112
111
|
]);
|
|
113
112
|
/**
|
|
113
|
+
* Formats `convertFormat` maps to a dedicated type without going through `formatMap`:
|
|
114
|
+
* `int64` and the date/time family. Keep this in sync with the `convertFormat`
|
|
115
|
+
* special-cases in `parser.ts`. `isHandledFormat` reads it so the
|
|
116
|
+
* `KUBB_UNSUPPORTED_FORMAT` diagnostic and the parser agree on what is handled.
|
|
117
|
+
*/
|
|
118
|
+
const specialCasedFormats = new Set([
|
|
119
|
+
"int64",
|
|
120
|
+
"date-time",
|
|
121
|
+
"date",
|
|
122
|
+
"time"
|
|
123
|
+
]);
|
|
124
|
+
/**
|
|
114
125
|
* Static map from OAS `format` strings to Kubb `SchemaType` values.
|
|
115
126
|
*
|
|
116
127
|
* Only formats whose AST type differs from the OAS `type` field appear here.
|
|
117
|
-
* Formats that depend on runtime options (`int64`, `date-time`, `date`, `time`) are handled
|
|
118
|
-
* in the parser. `ipv4` and `ipv6` map to their own dedicated schema types. `hostname`
|
|
119
|
-
* `idn-hostname` map to `'url'` as the closest generic string-format type.
|
|
128
|
+
* Formats that depend on runtime options (`int64`, `date-time`, `date`, `time`) are handled
|
|
129
|
+
* separately in the parser. `ipv4` and `ipv6` map to their own dedicated schema types. `hostname`
|
|
130
|
+
* and `idn-hostname` map to `'url'` as the closest generic string-format type.
|
|
120
131
|
*
|
|
121
132
|
* @example
|
|
122
133
|
* ```ts
|
|
@@ -127,18 +138,6 @@ const structuralKeys = new Set([
|
|
|
127
138
|
* formatMap['float'] // 'number'
|
|
128
139
|
* ```
|
|
129
140
|
*/
|
|
130
|
-
/**
|
|
131
|
-
* Formats `convertFormat` maps to a dedicated type without going through `formatMap`:
|
|
132
|
-
* `int64` and the date/time family. Keep this in sync with the `convertFormat`
|
|
133
|
-
* special-cases in `parser.ts`. `isHandledFormat` reads it so the
|
|
134
|
-
* `KUBB_UNSUPPORTED_FORMAT` diagnostic and the parser agree on what is handled.
|
|
135
|
-
*/
|
|
136
|
-
const specialCasedFormats = new Set([
|
|
137
|
-
"int64",
|
|
138
|
-
"date-time",
|
|
139
|
-
"date",
|
|
140
|
-
"time"
|
|
141
|
-
]);
|
|
142
141
|
const formatMap = {
|
|
143
142
|
uuid: "uuid",
|
|
144
143
|
email: "email",
|
|
@@ -659,7 +658,7 @@ function isDiscriminator(obj) {
|
|
|
659
658
|
//#endregion
|
|
660
659
|
//#region src/factory.ts
|
|
661
660
|
/**
|
|
662
|
-
* Loads and
|
|
661
|
+
* Loads and bundles an OpenAPI document, returning the raw `Document`.
|
|
663
662
|
*
|
|
664
663
|
* Accepts a file path string or an already-parsed document object. File paths and URLs are
|
|
665
664
|
* bundled via `api-ref-bundler`, hoisting external file schemas into named `components.schemas`
|
|
@@ -770,17 +769,180 @@ async function validateDocument(document, { throwOnError = false } = {}) {
|
|
|
770
769
|
}
|
|
771
770
|
}
|
|
772
771
|
//#endregion
|
|
772
|
+
//#region src/dedupe.ts
|
|
773
|
+
/**
|
|
774
|
+
* Minimum occurrences before a shape is deduplicated.
|
|
775
|
+
*/
|
|
776
|
+
const MIN_OCCURRENCES = 2;
|
|
777
|
+
/**
|
|
778
|
+
* Builds the shared `ref` replacement for a duplicate occurrence, carrying the
|
|
779
|
+
* usage-slot and documentation fields that are not part of the shared type.
|
|
780
|
+
*/
|
|
781
|
+
function createRefNode(node, target) {
|
|
782
|
+
return _kubb_core.ast.factory.createSchema({
|
|
783
|
+
type: "ref",
|
|
784
|
+
name: target.name,
|
|
785
|
+
ref: target.ref,
|
|
786
|
+
optional: node.optional,
|
|
787
|
+
nullish: node.nullish,
|
|
788
|
+
readOnly: node.readOnly,
|
|
789
|
+
writeOnly: node.writeOnly,
|
|
790
|
+
deprecated: node.deprecated,
|
|
791
|
+
description: node.description,
|
|
792
|
+
default: node.default,
|
|
793
|
+
example: node.example
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Strips usage-slot flags from an extracted definition and applies its name.
|
|
798
|
+
* A standalone definition is never optional, so `optional`/`nullish` are cleared.
|
|
799
|
+
*/
|
|
800
|
+
function cleanDefinition(node, name) {
|
|
801
|
+
return {
|
|
802
|
+
...node,
|
|
803
|
+
name,
|
|
804
|
+
optional: void 0,
|
|
805
|
+
nullish: void 0
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
/**
|
|
809
|
+
* Returns `true` when a node is eligible for deduplication. Only enums and objects qualify, and
|
|
810
|
+
* object shapes that take part in a circular chain are rejected so recursive structures are not
|
|
811
|
+
* extracted (which would break the cycle).
|
|
812
|
+
*/
|
|
813
|
+
function isCandidate(node, circularSchemas) {
|
|
814
|
+
if (node.type === "enum") return true;
|
|
815
|
+
if (node.type !== "object") return false;
|
|
816
|
+
if (node.name && circularSchemas.has(node.name)) return false;
|
|
817
|
+
return !(0, _kubb_ast_utils.containsCircularRef)(node, { circularSchemas });
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* Produces the name for an inline shape with no existing named component, resolving
|
|
821
|
+
* collisions against `usedNames`. Returns `null` for an unnamed shape, which stays inline.
|
|
822
|
+
*/
|
|
823
|
+
function nameFor(node, usedNames) {
|
|
824
|
+
const base = node.name;
|
|
825
|
+
if (!base) return null;
|
|
826
|
+
let name = base;
|
|
827
|
+
let counter = 2;
|
|
828
|
+
while (usedNames.has(name)) name = `${base}${counter++}`;
|
|
829
|
+
usedNames.add(name);
|
|
830
|
+
return name;
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Scans a forest of schema and operation nodes and produces a {@link Plan}.
|
|
834
|
+
*
|
|
835
|
+
* A shape that occurs at least {@link MIN_OCCURRENCES} times is deduplicated: if any occurrence is
|
|
836
|
+
* a named top-level schema, the first one becomes the target (so other top-level duplicates and
|
|
837
|
+
* inline copies turn into references to it). Other top-level names with the same content are
|
|
838
|
+
* recorded as aliases. Otherwise a new definition is extracted using {@link nameFor}. The returned
|
|
839
|
+
* plan rewrites nodes against those decisions.
|
|
840
|
+
*
|
|
841
|
+
* @example
|
|
842
|
+
* ```ts
|
|
843
|
+
* const dedupePlan = plan([...schemaNodes, ...operationNodes], { circularSchemas, usedNames })
|
|
844
|
+
* ```
|
|
845
|
+
*/
|
|
846
|
+
function plan(roots, context) {
|
|
847
|
+
const { circularSchemas, usedNames } = context;
|
|
848
|
+
const topLevelNodes = /* @__PURE__ */ new Set();
|
|
849
|
+
const groups = /* @__PURE__ */ new Map();
|
|
850
|
+
for (const root of roots) {
|
|
851
|
+
if (root.kind === "Schema") topLevelNodes.add(root);
|
|
852
|
+
for (const schemaNode of _kubb_core.ast.collect(root, { schema: (node) => node })) {
|
|
853
|
+
if (!isCandidate(schemaNode, circularSchemas)) continue;
|
|
854
|
+
const signature = _kubb_core.ast.signatureOf(schemaNode);
|
|
855
|
+
const isTopLevel = topLevelNodes.has(schemaNode) && !!schemaNode.name;
|
|
856
|
+
const group = groups.get(signature);
|
|
857
|
+
if (group) {
|
|
858
|
+
group.count++;
|
|
859
|
+
if (isTopLevel) group.topLevelNames.push(schemaNode.name);
|
|
860
|
+
} else groups.set(signature, {
|
|
861
|
+
count: 1,
|
|
862
|
+
representative: schemaNode,
|
|
863
|
+
topLevelNames: isTopLevel ? [schemaNode.name] : []
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
const bySignature = /* @__PURE__ */ new Map();
|
|
868
|
+
const byName = /* @__PURE__ */ new Map();
|
|
869
|
+
const pendingExtractions = [];
|
|
870
|
+
for (const [signature, group] of groups) {
|
|
871
|
+
if (group.count < MIN_OCCURRENCES) continue;
|
|
872
|
+
const [firstName, ...duplicateNames] = group.topLevelNames;
|
|
873
|
+
if (firstName) {
|
|
874
|
+
const target = {
|
|
875
|
+
name: firstName,
|
|
876
|
+
ref: `${SCHEMA_REF_PREFIX}${firstName}`
|
|
877
|
+
};
|
|
878
|
+
bySignature.set(signature, target);
|
|
879
|
+
for (const duplicate of duplicateNames) byName.set(duplicate, target);
|
|
880
|
+
continue;
|
|
881
|
+
}
|
|
882
|
+
const name = nameFor(group.representative, usedNames);
|
|
883
|
+
if (!name) continue;
|
|
884
|
+
bySignature.set(signature, {
|
|
885
|
+
name,
|
|
886
|
+
ref: `${SCHEMA_REF_PREFIX}${name}`
|
|
887
|
+
});
|
|
888
|
+
pendingExtractions.push({
|
|
889
|
+
name,
|
|
890
|
+
representative: group.representative
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
function rewrite(node, skipRootMatch) {
|
|
894
|
+
if (bySignature.size === 0 && byName.size === 0) return node;
|
|
895
|
+
const root = node;
|
|
896
|
+
return _kubb_core.ast.transform(node, { schema(schemaNode) {
|
|
897
|
+
if (schemaNode.type === "ref") {
|
|
898
|
+
const refName = schemaNode.ref ? (0, _kubb_ast_utils.extractRefName)(schemaNode.ref) : schemaNode.name;
|
|
899
|
+
const target = refName ? byName.get(refName) : void 0;
|
|
900
|
+
return target ? {
|
|
901
|
+
...schemaNode,
|
|
902
|
+
name: target.name,
|
|
903
|
+
ref: target.ref
|
|
904
|
+
} : void 0;
|
|
905
|
+
}
|
|
906
|
+
if (skipRootMatch && schemaNode === root) return void 0;
|
|
907
|
+
const target = bySignature.get(_kubb_core.ast.signatureOf(schemaNode));
|
|
908
|
+
if (!target) return void 0;
|
|
909
|
+
return createRefNode(schemaNode, target);
|
|
910
|
+
} });
|
|
911
|
+
}
|
|
912
|
+
return {
|
|
913
|
+
extracted: pendingExtractions.map(({ name, representative }) => cleanDefinition(rewrite(representative, true), name)),
|
|
914
|
+
apply(node) {
|
|
915
|
+
return rewrite(node, false);
|
|
916
|
+
},
|
|
917
|
+
applyTopLevel(node) {
|
|
918
|
+
const target = bySignature.get(_kubb_core.ast.signatureOf(node));
|
|
919
|
+
if (target && target.name !== node.name) return _kubb_core.ast.factory.createSchema({
|
|
920
|
+
type: "ref",
|
|
921
|
+
name: node.name ?? null,
|
|
922
|
+
ref: target.ref,
|
|
923
|
+
description: node.description,
|
|
924
|
+
deprecated: node.deprecated
|
|
925
|
+
});
|
|
926
|
+
return rewrite(node, true);
|
|
927
|
+
},
|
|
928
|
+
isAlias(name) {
|
|
929
|
+
return byName.has(name);
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
//#endregion
|
|
773
934
|
//#region src/refs.ts
|
|
774
935
|
const _refCache = /* @__PURE__ */ new WeakMap();
|
|
775
936
|
/**
|
|
776
937
|
* Resolves a local JSON pointer reference from a document.
|
|
777
938
|
*
|
|
778
|
-
* Accepts `#/...` refs. Returns `null` for empty or non-local
|
|
779
|
-
*
|
|
939
|
+
* Accepts `#/...` refs. Returns `null` for an empty or non-local ref. When the pointer cannot be
|
|
940
|
+
* resolved, reports a `refNotFound` diagnostic into the active build and returns `null`. Outside a
|
|
941
|
+
* build there is no sink to collect it, so it throws instead.
|
|
780
942
|
*
|
|
781
943
|
* @example
|
|
782
944
|
* ```ts
|
|
783
|
-
* resolveRef<SchemaObject>(document, '#/components/schemas/Pet')
|
|
945
|
+
* resolveRef<SchemaObject>(document, '#/components/schemas/Pet')
|
|
784
946
|
* ```
|
|
785
947
|
*/
|
|
786
948
|
function resolveRef(document, $ref) {
|
|
@@ -837,23 +999,6 @@ function dereferenceWithRef(document, schema) {
|
|
|
837
999
|
//#endregion
|
|
838
1000
|
//#region src/dialect.ts
|
|
839
1001
|
/**
|
|
840
|
-
* Derives a schema's `optional`/`nullish` flags from a parent's `required` value and the
|
|
841
|
-
* schema's own `nullable`. How "required" and "nullable" combine is OpenAPI-specific, so it
|
|
842
|
-
* lives in the dialect.
|
|
843
|
-
*
|
|
844
|
-
* - Non-required + non-nullable → `optional: true`.
|
|
845
|
-
* - Non-required + nullable → `nullish: true`.
|
|
846
|
-
* - Required → both flags cleared.
|
|
847
|
-
*/
|
|
848
|
-
function optionality(schema, required) {
|
|
849
|
-
const nullable = schema.nullable ?? false;
|
|
850
|
-
return {
|
|
851
|
-
...schema,
|
|
852
|
-
optional: !required && !nullable ? true : void 0,
|
|
853
|
-
nullish: !required && nullable ? true : void 0
|
|
854
|
-
};
|
|
855
|
-
}
|
|
856
|
-
/**
|
|
857
1002
|
* The OpenAPI / Swagger dialect, the default used by `@kubb/adapter-oas`.
|
|
858
1003
|
*
|
|
859
1004
|
* Implements the spec-agnostic {@link ast.SchemaDialect} contract: it isolates the
|
|
@@ -879,14 +1024,14 @@ const oasDialect = _kubb_core.ast.defineDialect({
|
|
|
879
1024
|
isReference,
|
|
880
1025
|
isDiscriminator,
|
|
881
1026
|
isBinary: (schema) => schema.type === "string" && schema.contentMediaType === "application/octet-stream",
|
|
882
|
-
resolveRef
|
|
883
|
-
|
|
884
|
-
}
|
|
1027
|
+
resolveRef
|
|
1028
|
+
},
|
|
1029
|
+
dedupe: { plan }
|
|
885
1030
|
});
|
|
886
1031
|
//#endregion
|
|
887
1032
|
//#region src/discriminator.ts
|
|
888
1033
|
/**
|
|
889
|
-
*
|
|
1034
|
+
* Maps each child schema name to its discriminator patch data by scanning the given
|
|
890
1035
|
* top-level AST schema nodes for union schemas that carry a `discriminatorPropertyName`.
|
|
891
1036
|
*
|
|
892
1037
|
* The streaming path calls this on a small pre-parsed subset of schemas (only the
|
|
@@ -1002,9 +1147,8 @@ function findDiscriminator(mapping, ref) {
|
|
|
1002
1147
|
/**
|
|
1003
1148
|
* MIME type fragments that mark a media type as JSON-like.
|
|
1004
1149
|
*
|
|
1005
|
-
*
|
|
1006
|
-
*
|
|
1007
|
-
* `application/vnd.api+json`.
|
|
1150
|
+
* A content type is JSON when it contains any of these substrings. The `+json` entry catches
|
|
1151
|
+
* structured-syntax suffixes such as `application/vnd.api+json`.
|
|
1008
1152
|
*/
|
|
1009
1153
|
const jsonMimeFragments = [
|
|
1010
1154
|
"application/json",
|
|
@@ -1100,8 +1244,8 @@ function getRequestContent({ document, operation, mediaType }) {
|
|
|
1100
1244
|
return available ? [available, content[available]] : false;
|
|
1101
1245
|
}
|
|
1102
1246
|
/**
|
|
1103
|
-
* Returns the primary request content type. Prefers a JSON-like media type (the last one wins
|
|
1104
|
-
*
|
|
1247
|
+
* Returns the primary request content type. Prefers a JSON-like media type (the last one wins
|
|
1248
|
+
* when several are declared), then the first declared one, defaulting to `'application/json'`.
|
|
1105
1249
|
*/
|
|
1106
1250
|
function getRequestContentType({ document, operation }) {
|
|
1107
1251
|
const content = getRequestBodyContent({
|
|
@@ -1196,9 +1340,9 @@ function getSchemaType(format) {
|
|
|
1196
1340
|
return formatMap[format] ?? null;
|
|
1197
1341
|
}
|
|
1198
1342
|
/**
|
|
1199
|
-
* Whether the parser maps `format` to a dedicated type. True for any `formatMap` entry
|
|
1200
|
-
* `specialCasedFormats` `convertFormat` handles directly. False means the format falls back to
|
|
1201
|
-
* base type, which is what `KUBB_UNSUPPORTED_FORMAT` flags. Reading both sources keeps the
|
|
1343
|
+
* Whether the parser maps `format` to a dedicated type. True for any `formatMap` entry, plus the
|
|
1344
|
+
* `specialCasedFormats` that `convertFormat` handles directly. False means the format falls back to
|
|
1345
|
+
* the base type, which is what `KUBB_UNSUPPORTED_FORMAT` flags. Reading both sources keeps the
|
|
1202
1346
|
* diagnostic in step with the parser as `formatMap` grows.
|
|
1203
1347
|
*/
|
|
1204
1348
|
function isHandledFormat(format) {
|
|
@@ -1216,7 +1360,7 @@ function getPrimitiveType(type) {
|
|
|
1216
1360
|
/**
|
|
1217
1361
|
* Returns all parameters for an operation, merging path-level and operation-level entries.
|
|
1218
1362
|
* Operation-level parameters override path-level ones with the same `in:name` key.
|
|
1219
|
-
* `$ref`
|
|
1363
|
+
* Each `$ref` parameter is dereferenced via `dereferenceWithRef` before merging.
|
|
1220
1364
|
*
|
|
1221
1365
|
* @example
|
|
1222
1366
|
* ```ts
|
|
@@ -1317,7 +1461,10 @@ function getRequestSchema(document, operation, options = {}) {
|
|
|
1317
1461
|
* ```ts
|
|
1318
1462
|
* flattenSchema({ allOf: [{ description: 'A pet' }], type: 'object', properties: {} })
|
|
1319
1463
|
* // { type: 'object', properties: {}, description: 'A pet' }
|
|
1464
|
+
* ```
|
|
1320
1465
|
*
|
|
1466
|
+
* @example
|
|
1467
|
+
* ```ts
|
|
1321
1468
|
* flattenSchema({ allOf: [{ $ref: '#/components/schemas/Pet' }] })
|
|
1322
1469
|
* // returned unchanged, contains a $ref
|
|
1323
1470
|
* ```
|
|
@@ -2011,7 +2158,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2011
2158
|
nullable: schemaNode.type === "null" ? void 0 : propNullable || void 0
|
|
2012
2159
|
},
|
|
2013
2160
|
required
|
|
2014
|
-
}
|
|
2161
|
+
});
|
|
2015
2162
|
}) : [];
|
|
2016
2163
|
const additionalProperties = schema.additionalProperties;
|
|
2017
2164
|
const additionalPropertiesNode = (() => {
|
|
@@ -2325,7 +2472,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2325
2472
|
description: param["description"] ?? schema.description
|
|
2326
2473
|
},
|
|
2327
2474
|
required
|
|
2328
|
-
}
|
|
2475
|
+
});
|
|
2329
2476
|
}
|
|
2330
2477
|
/**
|
|
2331
2478
|
* Reads the inline `requestBody` metadata (description / required) that OAS exposes
|
|
@@ -2378,7 +2525,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2378
2525
|
if (!schema) return [];
|
|
2379
2526
|
return [_kubb_core.ast.factory.createContent({
|
|
2380
2527
|
contentType: ct,
|
|
2381
|
-
schema:
|
|
2528
|
+
schema: _kubb_core.ast.optionality(parseSchema({
|
|
2382
2529
|
schema,
|
|
2383
2530
|
name: requestBodyName
|
|
2384
2531
|
}, options), requestBodyMeta.required),
|
|
@@ -2581,30 +2728,15 @@ function preScan({ schemas, parseSchema, parseOperation, document, parserOptions
|
|
|
2581
2728
|
}
|
|
2582
2729
|
const circularSchemas = new Set(circularNames);
|
|
2583
2730
|
const usedNames = new Set(Object.keys(schemas));
|
|
2584
|
-
dedupePlan =
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
if (node.type !== "object") return false;
|
|
2588
|
-
if (node.name && circularSchemas.has(node.name)) return false;
|
|
2589
|
-
return !(0, _kubb_ast_utils.containsCircularRef)(node, { circularSchemas });
|
|
2590
|
-
},
|
|
2591
|
-
nameFor: (node) => {
|
|
2592
|
-
const base = node.name;
|
|
2593
|
-
if (!base) return null;
|
|
2594
|
-
let name = base;
|
|
2595
|
-
let counter = 2;
|
|
2596
|
-
while (usedNames.has(name)) name = `${base}${counter++}`;
|
|
2597
|
-
usedNames.add(name);
|
|
2598
|
-
return name;
|
|
2599
|
-
},
|
|
2600
|
-
refFor: (name) => `${SCHEMA_REF_PREFIX}${name}`
|
|
2731
|
+
dedupePlan = oasDialect.dedupe.plan([...allNodes, ...operationNodes], {
|
|
2732
|
+
circularSchemas,
|
|
2733
|
+
usedNames
|
|
2601
2734
|
});
|
|
2602
|
-
for (const definition of dedupePlan.
|
|
2735
|
+
for (const definition of dedupePlan.extracted) if (definition.type === "enum" && definition.name) enumNames.push(definition.name);
|
|
2603
2736
|
}
|
|
2604
|
-
const aliasNames = dedupePlan?.aliasNames;
|
|
2605
2737
|
return {
|
|
2606
2738
|
refAliasMap,
|
|
2607
|
-
enumNames:
|
|
2739
|
+
enumNames: dedupePlan ? enumNames.filter((name) => !dedupePlan.isAlias(name)) : enumNames,
|
|
2608
2740
|
circularNames,
|
|
2609
2741
|
discriminatorChildMap,
|
|
2610
2742
|
dedupePlan
|
|
@@ -2629,39 +2761,29 @@ function preScan({ schemas, parseSchema, parseOperation, document, parserOptions
|
|
|
2629
2761
|
* ```
|
|
2630
2762
|
*/
|
|
2631
2763
|
function createInputStream({ schemas, parseSchema, parseOperation, document, parserOptions, refAliasMap, discriminatorChildMap, dedupePlan, meta }) {
|
|
2632
|
-
const rewriteTopLevelSchema = (node) => {
|
|
2633
|
-
if (!dedupePlan) return node;
|
|
2634
|
-
const canonical = dedupePlan.canonicalBySignature.get(_kubb_core.ast.signatureOf(node));
|
|
2635
|
-
if (canonical && canonical.name !== node.name) return _kubb_core.ast.factory.createSchema({
|
|
2636
|
-
type: "ref",
|
|
2637
|
-
name: node.name ?? null,
|
|
2638
|
-
ref: canonical.ref,
|
|
2639
|
-
description: node.description,
|
|
2640
|
-
deprecated: node.deprecated
|
|
2641
|
-
});
|
|
2642
|
-
return _kubb_core.ast.applyDedupe(node, dedupePlan, true);
|
|
2643
|
-
};
|
|
2644
2764
|
const schemasIterable = { [Symbol.asyncIterator]() {
|
|
2645
2765
|
return (async function* () {
|
|
2646
|
-
if (dedupePlan) for (const definition of dedupePlan.
|
|
2766
|
+
if (dedupePlan) for (const definition of dedupePlan.extracted) yield definition;
|
|
2647
2767
|
for (const [name, schema] of Object.entries(schemas)) {
|
|
2648
|
-
if (dedupePlan?.
|
|
2768
|
+
if (dedupePlan?.isAlias(name)) continue;
|
|
2649
2769
|
const alias = refAliasMap.get(name);
|
|
2650
2770
|
if (alias?.name && schemas[alias.name]) {
|
|
2651
|
-
|
|
2771
|
+
const aliasNode = {
|
|
2652
2772
|
...parseSchema({
|
|
2653
2773
|
schema: schemas[alias.name],
|
|
2654
2774
|
name: alias.name
|
|
2655
2775
|
}, parserOptions),
|
|
2656
2776
|
name
|
|
2657
|
-
}
|
|
2777
|
+
};
|
|
2778
|
+
yield dedupePlan ? dedupePlan.applyTopLevel(aliasNode) : aliasNode;
|
|
2658
2779
|
continue;
|
|
2659
2780
|
}
|
|
2660
2781
|
const parsed = parseSchema({
|
|
2661
2782
|
schema,
|
|
2662
2783
|
name
|
|
2663
2784
|
}, parserOptions);
|
|
2664
|
-
|
|
2785
|
+
const node = discriminatorChildMap?.get(name) ? patchDiscriminatorNode(parsed, discriminatorChildMap.get(name)) : parsed;
|
|
2786
|
+
yield dedupePlan ? dedupePlan.applyTopLevel(node) : node;
|
|
2665
2787
|
}
|
|
2666
2788
|
})();
|
|
2667
2789
|
} };
|
|
@@ -2669,7 +2791,7 @@ function createInputStream({ schemas, parseSchema, parseOperation, document, par
|
|
|
2669
2791
|
return (async function* () {
|
|
2670
2792
|
for (const operation of getOperations(document)) {
|
|
2671
2793
|
const node = parseOperation(parserOptions, operation);
|
|
2672
|
-
if (node) yield dedupePlan ?
|
|
2794
|
+
if (node) yield dedupePlan ? dedupePlan.apply(node) : node;
|
|
2673
2795
|
}
|
|
2674
2796
|
})();
|
|
2675
2797
|
} };
|
|
@@ -2683,7 +2805,7 @@ function createInputStream({ schemas, parseSchema, parseOperation, document, par
|
|
|
2683
2805
|
//#endregion
|
|
2684
2806
|
//#region src/adapter.ts
|
|
2685
2807
|
/**
|
|
2686
|
-
*
|
|
2808
|
+
* The `name` of `@kubb/adapter-oas`, used to identify this adapter in a Kubb config.
|
|
2687
2809
|
*/
|
|
2688
2810
|
const adapterOasName = "oas";
|
|
2689
2811
|
/**
|