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