@kubb/adapter-oas 5.0.0-beta.30 → 5.0.0-beta.31
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 +90 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.js +90 -13
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/adapter.ts +13 -4
- package/src/parser.ts +16 -0
- package/src/stream.ts +105 -4
- package/src/types.ts +13 -0
package/dist/index.cjs
CHANGED
|
@@ -1510,6 +1510,15 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1510
1510
|
}, rawOptions);
|
|
1511
1511
|
const nullInEnum = schema.enum.includes(null);
|
|
1512
1512
|
const filteredValues = nullInEnum ? schema.enum.filter((v) => v !== null) : schema.enum;
|
|
1513
|
+
if (nullInEnum && filteredValues.length === 0) return _kubb_core.ast.createSchema({
|
|
1514
|
+
type: "null",
|
|
1515
|
+
primitive: "null",
|
|
1516
|
+
name,
|
|
1517
|
+
title: schema.title,
|
|
1518
|
+
description: schema.description,
|
|
1519
|
+
deprecated: schema.deprecated,
|
|
1520
|
+
format: schema.format
|
|
1521
|
+
});
|
|
1513
1522
|
const enumNullable = nullable || nullInEnum || void 0;
|
|
1514
1523
|
const enumDefault = schema.default === null && enumNullable ? void 0 : schema.default;
|
|
1515
1524
|
const enumPrimitive = getPrimitiveType(type);
|
|
@@ -2091,6 +2100,36 @@ function patchDiscriminatorNode(node, entry) {
|
|
|
2091
2100
|
//#endregion
|
|
2092
2101
|
//#region src/stream.ts
|
|
2093
2102
|
/**
|
|
2103
|
+
* Builds the deduplication plan from the already-parsed top-level schema nodes plus a
|
|
2104
|
+
* single extra parse pass over operations (so duplicates in request/response bodies are seen).
|
|
2105
|
+
*
|
|
2106
|
+
* Only enums and objects are candidates, and object shapes that reference a circular schema are
|
|
2107
|
+
* rejected to avoid hoisting recursive structures. Inline shapes reuse their context-derived
|
|
2108
|
+
* name (collision-resolved against existing component names); shapes without a name stay inline.
|
|
2109
|
+
*/
|
|
2110
|
+
function createDedupePlan({ schemaNodes, operationNodes, schemaNames, circularNames }) {
|
|
2111
|
+
const circularSchemas = new Set(circularNames);
|
|
2112
|
+
const usedNames = new Set(schemaNames);
|
|
2113
|
+
return _kubb_core.ast.buildDedupePlan([...schemaNodes, ...operationNodes], {
|
|
2114
|
+
isCandidate: (node) => {
|
|
2115
|
+
if (node.type === "enum") return true;
|
|
2116
|
+
if (node.type !== "object") return false;
|
|
2117
|
+
if (node.name && circularSchemas.has(node.name)) return false;
|
|
2118
|
+
return !_kubb_core.ast.containsCircularRef(node, { circularSchemas });
|
|
2119
|
+
},
|
|
2120
|
+
nameFor: (node) => {
|
|
2121
|
+
const base = node.name;
|
|
2122
|
+
if (!base) return null;
|
|
2123
|
+
let name = base;
|
|
2124
|
+
let counter = 2;
|
|
2125
|
+
while (usedNames.has(name)) name = `${base}${counter++}`;
|
|
2126
|
+
usedNames.add(name);
|
|
2127
|
+
return name;
|
|
2128
|
+
},
|
|
2129
|
+
refFor: (name) => `${SCHEMA_REF_PREFIX}${name}`
|
|
2130
|
+
});
|
|
2131
|
+
}
|
|
2132
|
+
/**
|
|
2094
2133
|
* Reads the server URL from the document's `servers` array at `serverIndex`,
|
|
2095
2134
|
* interpolating any `serverVariables` into the URL template.
|
|
2096
2135
|
*
|
|
@@ -2131,7 +2170,7 @@ function resolveBaseUrl({ document, serverIndex, serverVariables }) {
|
|
|
2131
2170
|
* })
|
|
2132
2171
|
* ```
|
|
2133
2172
|
*/
|
|
2134
|
-
function preScan({ schemas, parseSchema, parserOptions, discriminator }) {
|
|
2173
|
+
function preScan({ schemas, parseSchema, parseOperation, baseOas, parserOptions, discriminator, dedupe }) {
|
|
2135
2174
|
const allNodes = [];
|
|
2136
2175
|
const refAliasMap = /* @__PURE__ */ new Map();
|
|
2137
2176
|
const enumNames = [];
|
|
@@ -2146,11 +2185,30 @@ function preScan({ schemas, parseSchema, parserOptions, discriminator }) {
|
|
|
2146
2185
|
if (_kubb_core.ast.narrowSchema(node, _kubb_core.ast.schemaTypes.enum) && node.name) enumNames.push(node.name);
|
|
2147
2186
|
if (discriminator === "inherit" && (schema.oneOf ?? schema.anyOf) && schema.discriminator?.propertyName) discriminatorParentNodes.push(node);
|
|
2148
2187
|
}
|
|
2188
|
+
const circularNames = [..._kubb_core.ast.findCircularSchemas(allNodes)];
|
|
2189
|
+
const discriminatorChildMap = discriminatorParentNodes.length > 0 ? buildDiscriminatorChildMap(discriminatorParentNodes) : null;
|
|
2190
|
+
let dedupePlan = null;
|
|
2191
|
+
if (dedupe) {
|
|
2192
|
+
const operationNodes = [];
|
|
2193
|
+
for (const methods of Object.values(baseOas.getPaths())) for (const operation of Object.values(methods)) {
|
|
2194
|
+
if (!operation) continue;
|
|
2195
|
+
const operationNode = parseOperation(parserOptions, operation);
|
|
2196
|
+
if (operationNode) operationNodes.push(operationNode);
|
|
2197
|
+
}
|
|
2198
|
+
dedupePlan = createDedupePlan({
|
|
2199
|
+
schemaNodes: allNodes,
|
|
2200
|
+
operationNodes,
|
|
2201
|
+
schemaNames: Object.keys(schemas),
|
|
2202
|
+
circularNames
|
|
2203
|
+
});
|
|
2204
|
+
for (const definition of dedupePlan.hoisted) if (definition.type === "enum" && definition.name) enumNames.push(definition.name);
|
|
2205
|
+
}
|
|
2149
2206
|
return {
|
|
2150
2207
|
refAliasMap,
|
|
2151
2208
|
enumNames,
|
|
2152
|
-
circularNames
|
|
2153
|
-
discriminatorChildMap
|
|
2209
|
+
circularNames,
|
|
2210
|
+
discriminatorChildMap,
|
|
2211
|
+
dedupePlan
|
|
2154
2212
|
};
|
|
2155
2213
|
}
|
|
2156
2214
|
/**
|
|
@@ -2171,26 +2229,39 @@ function preScan({ schemas, parseSchema, parserOptions, discriminator }) {
|
|
|
2171
2229
|
* }
|
|
2172
2230
|
* ```
|
|
2173
2231
|
*/
|
|
2174
|
-
function createInputStream({ schemas, parseSchema, parseOperation, baseOas, parserOptions, refAliasMap, discriminatorChildMap, meta }) {
|
|
2232
|
+
function createInputStream({ schemas, parseSchema, parseOperation, baseOas, parserOptions, refAliasMap, discriminatorChildMap, dedupePlan, meta }) {
|
|
2233
|
+
const rewriteTopLevelSchema = (node) => {
|
|
2234
|
+
if (!dedupePlan) return node;
|
|
2235
|
+
const canonical = dedupePlan.canonicalBySignature.get(_kubb_core.ast.schemaSignature(node));
|
|
2236
|
+
if (canonical && canonical.name !== node.name) return _kubb_core.ast.createSchema({
|
|
2237
|
+
type: "ref",
|
|
2238
|
+
name: node.name ?? null,
|
|
2239
|
+
ref: canonical.ref,
|
|
2240
|
+
description: node.description,
|
|
2241
|
+
deprecated: node.deprecated
|
|
2242
|
+
});
|
|
2243
|
+
return _kubb_core.ast.applyDedupe(node, dedupePlan.canonicalBySignature, true);
|
|
2244
|
+
};
|
|
2175
2245
|
const schemasIterable = { [Symbol.asyncIterator]() {
|
|
2176
2246
|
return (async function* () {
|
|
2247
|
+
if (dedupePlan) for (const definition of dedupePlan.hoisted) yield definition;
|
|
2177
2248
|
for (const [name, schema] of Object.entries(schemas)) {
|
|
2178
2249
|
const alias = refAliasMap.get(name);
|
|
2179
2250
|
if (alias?.name && schemas[alias.name]) {
|
|
2180
|
-
yield {
|
|
2251
|
+
yield rewriteTopLevelSchema({
|
|
2181
2252
|
...parseSchema({
|
|
2182
2253
|
schema: schemas[alias.name],
|
|
2183
2254
|
name: alias.name
|
|
2184
2255
|
}, parserOptions),
|
|
2185
2256
|
name
|
|
2186
|
-
};
|
|
2257
|
+
});
|
|
2187
2258
|
continue;
|
|
2188
2259
|
}
|
|
2189
2260
|
const parsed = parseSchema({
|
|
2190
2261
|
schema,
|
|
2191
2262
|
name
|
|
2192
2263
|
}, parserOptions);
|
|
2193
|
-
yield discriminatorChildMap?.get(name) ? patchDiscriminatorNode(parsed, discriminatorChildMap.get(name)) : parsed;
|
|
2264
|
+
yield rewriteTopLevelSchema(discriminatorChildMap?.get(name) ? patchDiscriminatorNode(parsed, discriminatorChildMap.get(name)) : parsed);
|
|
2194
2265
|
}
|
|
2195
2266
|
})();
|
|
2196
2267
|
} };
|
|
@@ -2199,7 +2270,7 @@ function createInputStream({ schemas, parseSchema, parseOperation, baseOas, pars
|
|
|
2199
2270
|
for (const methods of Object.values(baseOas.getPaths())) for (const operation of Object.values(methods)) {
|
|
2200
2271
|
if (!operation) continue;
|
|
2201
2272
|
const node = parseOperation(parserOptions, operation);
|
|
2202
|
-
if (node) yield node;
|
|
2273
|
+
if (node) yield dedupePlan ? _kubb_core.ast.applyDedupe(node, dedupePlan.canonicalBySignature) : node;
|
|
2203
2274
|
}
|
|
2204
2275
|
})();
|
|
2205
2276
|
} };
|
|
@@ -2239,7 +2310,7 @@ const adapterOasName = "oas";
|
|
|
2239
2310
|
* ```
|
|
2240
2311
|
*/
|
|
2241
2312
|
const adapterOas = (0, _kubb_core.createAdapter)((options) => {
|
|
2242
|
-
const { validate = true, contentType, serverIndex, serverVariables, discriminator = "strict", dateType = DEFAULT_PARSER_OPTIONS.dateType, integerType = DEFAULT_PARSER_OPTIONS.integerType, unknownType = DEFAULT_PARSER_OPTIONS.unknownType, enumSuffix = DEFAULT_PARSER_OPTIONS.enumSuffix, emptySchemaType = unknownType || DEFAULT_PARSER_OPTIONS.emptySchemaType } = options;
|
|
2313
|
+
const { validate = true, contentType, serverIndex, serverVariables, discriminator = "strict", dedupe = true, dateType = DEFAULT_PARSER_OPTIONS.dateType, integerType = DEFAULT_PARSER_OPTIONS.integerType, unknownType = DEFAULT_PARSER_OPTIONS.unknownType, enumSuffix = DEFAULT_PARSER_OPTIONS.enumSuffix, emptySchemaType = unknownType || DEFAULT_PARSER_OPTIONS.emptySchemaType } = options;
|
|
2243
2314
|
const parserOptions = {
|
|
2244
2315
|
...DEFAULT_PARSER_OPTIONS,
|
|
2245
2316
|
dateType,
|
|
@@ -2266,25 +2337,30 @@ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
|
|
|
2266
2337
|
document,
|
|
2267
2338
|
contentType
|
|
2268
2339
|
}));
|
|
2269
|
-
const ensurePreScan = once((schemas, parseSchema) => preScan({
|
|
2340
|
+
const ensurePreScan = once((schemas, parseSchema, parseOperation, baseOas) => preScan({
|
|
2270
2341
|
schemas,
|
|
2271
2342
|
parseSchema,
|
|
2343
|
+
parseOperation,
|
|
2344
|
+
baseOas,
|
|
2272
2345
|
parserOptions,
|
|
2273
|
-
discriminator
|
|
2346
|
+
discriminator,
|
|
2347
|
+
dedupe
|
|
2274
2348
|
}));
|
|
2275
2349
|
async function createStream(source) {
|
|
2276
2350
|
const document = await ensureDocument(source);
|
|
2277
2351
|
const schemas = await ensureSchemas(document);
|
|
2278
2352
|
const { parseSchema, parseOperation } = ensureSchemaParser(document);
|
|
2279
|
-
const
|
|
2353
|
+
const baseOas = ensureBaseOas(document);
|
|
2354
|
+
const { refAliasMap, enumNames, circularNames, discriminatorChildMap, dedupePlan } = ensurePreScan(schemas, parseSchema, parseOperation, baseOas);
|
|
2280
2355
|
return createInputStream({
|
|
2281
2356
|
schemas,
|
|
2282
2357
|
parseSchema,
|
|
2283
2358
|
parseOperation,
|
|
2284
|
-
baseOas
|
|
2359
|
+
baseOas,
|
|
2285
2360
|
parserOptions,
|
|
2286
2361
|
refAliasMap,
|
|
2287
2362
|
discriminatorChildMap,
|
|
2363
|
+
dedupePlan,
|
|
2288
2364
|
meta: {
|
|
2289
2365
|
title: document.info?.title,
|
|
2290
2366
|
description: document.info?.description,
|
|
@@ -2308,6 +2384,7 @@ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
|
|
|
2308
2384
|
serverIndex,
|
|
2309
2385
|
serverVariables,
|
|
2310
2386
|
discriminator,
|
|
2387
|
+
dedupe,
|
|
2311
2388
|
dateType,
|
|
2312
2389
|
integerType,
|
|
2313
2390
|
unknownType,
|