@kubb/adapter-oas 5.0.0-beta.74 → 5.0.0-beta.76
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 +67 -289
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +67 -289
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -132,6 +132,17 @@ const formatMap = {
|
|
|
132
132
|
* ```
|
|
133
133
|
*/
|
|
134
134
|
const enumExtensionKeys = ["x-enumNames", "x-enum-varnames"];
|
|
135
|
+
/**
|
|
136
|
+
* Vendor extension keys that attach human-readable descriptions to enum values, checked in priority order.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```ts
|
|
140
|
+
* import { enumDescriptionKeys } from '@kubb/adapter-oas'
|
|
141
|
+
*
|
|
142
|
+
* const key = enumDescriptionKeys.find((k) => k in schema) // 'x-enumDescriptions' | 'x-enum-descriptions' | undefined
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
const enumDescriptionKeys = ["x-enumDescriptions", "x-enum-descriptions"];
|
|
135
146
|
//#endregion
|
|
136
147
|
//#region ../../internals/utils/src/casing.ts
|
|
137
148
|
/**
|
|
@@ -148,18 +159,6 @@ function toCamelOrPascal(text, pascal) {
|
|
|
148
159
|
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
149
160
|
}
|
|
150
161
|
/**
|
|
151
|
-
* Converts `text` to camelCase.
|
|
152
|
-
*
|
|
153
|
-
* @example Word boundaries
|
|
154
|
-
* `camelCase('hello-world') // 'helloWorld'`
|
|
155
|
-
*
|
|
156
|
-
* @example With a prefix
|
|
157
|
-
* `camelCase('tag', { prefix: 'create' }) // 'createTag'`
|
|
158
|
-
*/
|
|
159
|
-
function camelCase(text, { prefix = "", suffix = "" } = {}) {
|
|
160
|
-
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
162
|
* Converts `text` to PascalCase.
|
|
164
163
|
*
|
|
165
164
|
* @example Word boundaries
|
|
@@ -272,209 +271,6 @@ async function read(path) {
|
|
|
272
271
|
return readFile(path, { encoding: "utf8" });
|
|
273
272
|
}
|
|
274
273
|
//#endregion
|
|
275
|
-
//#region ../../internals/utils/src/reserved.ts
|
|
276
|
-
/**
|
|
277
|
-
* JavaScript and Java reserved words.
|
|
278
|
-
* @link https://github.com/jonschlinkert/reserved/blob/master/index.js
|
|
279
|
-
*/
|
|
280
|
-
const reservedWords = new Set([
|
|
281
|
-
"abstract",
|
|
282
|
-
"arguments",
|
|
283
|
-
"boolean",
|
|
284
|
-
"break",
|
|
285
|
-
"byte",
|
|
286
|
-
"case",
|
|
287
|
-
"catch",
|
|
288
|
-
"char",
|
|
289
|
-
"class",
|
|
290
|
-
"const",
|
|
291
|
-
"continue",
|
|
292
|
-
"debugger",
|
|
293
|
-
"default",
|
|
294
|
-
"delete",
|
|
295
|
-
"do",
|
|
296
|
-
"double",
|
|
297
|
-
"else",
|
|
298
|
-
"enum",
|
|
299
|
-
"eval",
|
|
300
|
-
"export",
|
|
301
|
-
"extends",
|
|
302
|
-
"false",
|
|
303
|
-
"final",
|
|
304
|
-
"finally",
|
|
305
|
-
"float",
|
|
306
|
-
"for",
|
|
307
|
-
"function",
|
|
308
|
-
"goto",
|
|
309
|
-
"if",
|
|
310
|
-
"implements",
|
|
311
|
-
"import",
|
|
312
|
-
"in",
|
|
313
|
-
"instanceof",
|
|
314
|
-
"int",
|
|
315
|
-
"interface",
|
|
316
|
-
"let",
|
|
317
|
-
"long",
|
|
318
|
-
"native",
|
|
319
|
-
"new",
|
|
320
|
-
"null",
|
|
321
|
-
"package",
|
|
322
|
-
"private",
|
|
323
|
-
"protected",
|
|
324
|
-
"public",
|
|
325
|
-
"return",
|
|
326
|
-
"short",
|
|
327
|
-
"static",
|
|
328
|
-
"super",
|
|
329
|
-
"switch",
|
|
330
|
-
"synchronized",
|
|
331
|
-
"this",
|
|
332
|
-
"throw",
|
|
333
|
-
"throws",
|
|
334
|
-
"transient",
|
|
335
|
-
"true",
|
|
336
|
-
"try",
|
|
337
|
-
"typeof",
|
|
338
|
-
"var",
|
|
339
|
-
"void",
|
|
340
|
-
"volatile",
|
|
341
|
-
"while",
|
|
342
|
-
"with",
|
|
343
|
-
"yield",
|
|
344
|
-
"Array",
|
|
345
|
-
"Date",
|
|
346
|
-
"hasOwnProperty",
|
|
347
|
-
"Infinity",
|
|
348
|
-
"isFinite",
|
|
349
|
-
"isNaN",
|
|
350
|
-
"isPrototypeOf",
|
|
351
|
-
"length",
|
|
352
|
-
"Math",
|
|
353
|
-
"name",
|
|
354
|
-
"NaN",
|
|
355
|
-
"Number",
|
|
356
|
-
"Object",
|
|
357
|
-
"prototype",
|
|
358
|
-
"String",
|
|
359
|
-
"toString",
|
|
360
|
-
"undefined",
|
|
361
|
-
"valueOf"
|
|
362
|
-
]);
|
|
363
|
-
/**
|
|
364
|
-
* Returns `true` when `name` is a syntactically valid JavaScript variable name.
|
|
365
|
-
*
|
|
366
|
-
* @example
|
|
367
|
-
* ```ts
|
|
368
|
-
* isValidVarName('status') // true
|
|
369
|
-
* isValidVarName('class') // false (reserved word)
|
|
370
|
-
* isValidVarName('42foo') // false (starts with digit)
|
|
371
|
-
* ```
|
|
372
|
-
*/
|
|
373
|
-
function isValidVarName(name) {
|
|
374
|
-
if (!name || reservedWords.has(name)) return false;
|
|
375
|
-
return isIdentifier(name);
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
|
|
379
|
-
*
|
|
380
|
-
* Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
|
|
381
|
-
* even though they are not valid variable names, so use this (not {@link isValidVarName}) when
|
|
382
|
-
* deciding whether an object key needs quoting.
|
|
383
|
-
*
|
|
384
|
-
* @example
|
|
385
|
-
* ```ts
|
|
386
|
-
* isIdentifier('name') // true
|
|
387
|
-
* isIdentifier('x-total')// false
|
|
388
|
-
* ```
|
|
389
|
-
*/
|
|
390
|
-
function isIdentifier(name) {
|
|
391
|
-
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
392
|
-
}
|
|
393
|
-
//#endregion
|
|
394
|
-
//#region ../../internals/utils/src/url.ts
|
|
395
|
-
function transformParam(raw, casing) {
|
|
396
|
-
const param = isValidVarName(raw) ? raw : camelCase(raw);
|
|
397
|
-
return casing === "camelcase" ? camelCase(param) : param;
|
|
398
|
-
}
|
|
399
|
-
function toParamsObject(path, { replacer, casing } = {}) {
|
|
400
|
-
const params = {};
|
|
401
|
-
for (const match of path.matchAll(/\{([^}]+)\}/g)) {
|
|
402
|
-
const param = transformParam(match[1], casing);
|
|
403
|
-
const key = replacer ? replacer(param) : param;
|
|
404
|
-
params[key] = key;
|
|
405
|
-
}
|
|
406
|
-
return Object.keys(params).length > 0 ? params : null;
|
|
407
|
-
}
|
|
408
|
-
/**
|
|
409
|
-
* Helpers for OpenAPI/Swagger paths, plus a thin wrapper over the native `URL`.
|
|
410
|
-
*/
|
|
411
|
-
var Url = class Url {
|
|
412
|
-
/**
|
|
413
|
-
* Reports whether `url` is a parseable absolute URL. Delegates to the native `URL.canParse`.
|
|
414
|
-
*
|
|
415
|
-
* @example
|
|
416
|
-
* Url.canParse('https://petstore.swagger.io/v2') // true
|
|
417
|
-
* Url.canParse('/pet/{petId}') // false
|
|
418
|
-
*/
|
|
419
|
-
static canParse(url, base) {
|
|
420
|
-
return URL.canParse(url, base);
|
|
421
|
-
}
|
|
422
|
-
/**
|
|
423
|
-
* Converts an OpenAPI/Swagger path to Express-style colon syntax.
|
|
424
|
-
*
|
|
425
|
-
* @example
|
|
426
|
-
* Url.toPath('/pet/{petId}') // '/pet/:petId'
|
|
427
|
-
*/
|
|
428
|
-
static toPath(path) {
|
|
429
|
-
return path.replace(/\{([^}]+)\}/g, ":$1");
|
|
430
|
-
}
|
|
431
|
-
/**
|
|
432
|
-
* Converts an OpenAPI/Swagger path to a TypeScript template literal string.
|
|
433
|
-
* `prefix` is prepended inside the literal, `replacer` transforms each parameter name,
|
|
434
|
-
* and `casing` controls parameter identifier casing.
|
|
435
|
-
*
|
|
436
|
-
* @example
|
|
437
|
-
* Url.toTemplateString('/pet/{petId}') // '`/pet/${petId}`'
|
|
438
|
-
*
|
|
439
|
-
* @example
|
|
440
|
-
* Url.toTemplateString('/pet/{petId}', { prefix: 'https://api' }) // '`https://api/pet/${petId}`'
|
|
441
|
-
*/
|
|
442
|
-
static toTemplateString(path, { prefix, replacer, casing } = {}) {
|
|
443
|
-
const result = path.split(/\{([^}]+)\}/).map((part, i) => {
|
|
444
|
-
if (i % 2 === 0) return part;
|
|
445
|
-
const param = transformParam(part, casing);
|
|
446
|
-
return `\${${replacer ? replacer(param) : param}}`;
|
|
447
|
-
}).join("");
|
|
448
|
-
return `\`${prefix ?? ""}${result}\``;
|
|
449
|
-
}
|
|
450
|
-
/**
|
|
451
|
-
* Returns the path and its extracted params as a structured `URLObject`, or as a stringified
|
|
452
|
-
* expression when `stringify` is set.
|
|
453
|
-
*
|
|
454
|
-
* @example
|
|
455
|
-
* Url.toObject('/pet/{petId}')
|
|
456
|
-
* // { url: '/pet/:petId', params: { petId: 'petId' } }
|
|
457
|
-
*/
|
|
458
|
-
static toObject(path, { type = "path", replacer, stringify, casing } = {}) {
|
|
459
|
-
const object = {
|
|
460
|
-
url: type === "path" ? Url.toPath(path) : Url.toTemplateString(path, {
|
|
461
|
-
replacer,
|
|
462
|
-
casing
|
|
463
|
-
}),
|
|
464
|
-
params: toParamsObject(path, {
|
|
465
|
-
replacer,
|
|
466
|
-
casing
|
|
467
|
-
})
|
|
468
|
-
};
|
|
469
|
-
if (stringify) {
|
|
470
|
-
if (type === "template") return JSON.stringify(object).replaceAll("'", "").replaceAll(`"`, "");
|
|
471
|
-
if (object.params) return `{ url: '${object.url}', params: ${JSON.stringify(object.params).replaceAll("'", "").replaceAll(`"`, "")} }`;
|
|
472
|
-
return `{ url: '${object.url}' }`;
|
|
473
|
-
}
|
|
474
|
-
return object;
|
|
475
|
-
}
|
|
476
|
-
};
|
|
477
|
-
//#endregion
|
|
478
274
|
//#region src/bundler.ts
|
|
479
275
|
const urlRegExp = /^https?:\/+/i;
|
|
480
276
|
async function readSource(sourcePath) {
|
|
@@ -552,7 +348,7 @@ async function parseDocument(pathOrApi) {
|
|
|
552
348
|
*/
|
|
553
349
|
async function parseFromConfig(source) {
|
|
554
350
|
if (source.type === "data") return parseDocument(typeof source.data === "string" ? parse(source.data) : structuredClone(source.data));
|
|
555
|
-
if (
|
|
351
|
+
if (URL.canParse(source.path)) return parseDocument(source.path);
|
|
556
352
|
const resolved = path.resolve(path.dirname(source.path), source.path);
|
|
557
353
|
await assertInputExists(resolved);
|
|
558
354
|
return parseDocument(resolved);
|
|
@@ -563,7 +359,7 @@ async function parseFromConfig(source) {
|
|
|
563
359
|
* its parse error instead.
|
|
564
360
|
*/
|
|
565
361
|
async function assertInputExists(input) {
|
|
566
|
-
if (
|
|
362
|
+
if (URL.canParse(input)) return;
|
|
567
363
|
if (!await exists(input)) throw new Diagnostics.Error({
|
|
568
364
|
code: Diagnostics.code.inputNotFound,
|
|
569
365
|
severity: "error",
|
|
@@ -1465,7 +1261,7 @@ function normalizeArrayEnum(schema) {
|
|
|
1465
1261
|
* Builds a `null` scalar node carrying the schema's documentation. Shared by the `const: null`
|
|
1466
1262
|
* and the drf-spectacular `NullEnum` (`{ enum: [null] }`) branches, which render identically.
|
|
1467
1263
|
*/
|
|
1468
|
-
function createNullSchema(schema, name) {
|
|
1264
|
+
function createNullSchema(schema, name, nullable) {
|
|
1469
1265
|
return ast.factory.createSchema({
|
|
1470
1266
|
type: "null",
|
|
1471
1267
|
primitive: "null",
|
|
@@ -1473,6 +1269,7 @@ function createNullSchema(schema, name) {
|
|
|
1473
1269
|
title: schema.title,
|
|
1474
1270
|
description: schema.description,
|
|
1475
1271
|
deprecated: schema.deprecated,
|
|
1272
|
+
nullable,
|
|
1476
1273
|
format: schema.format
|
|
1477
1274
|
});
|
|
1478
1275
|
}
|
|
@@ -1651,6 +1448,34 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1651
1448
|
properties: [discriminatorProperty]
|
|
1652
1449
|
});
|
|
1653
1450
|
}
|
|
1451
|
+
function resolveRefSilent($ref) {
|
|
1452
|
+
if (!$ref.startsWith("#")) return null;
|
|
1453
|
+
return decodeURIComponent($ref.substring(1)).split("/").filter(Boolean).reduce((obj, key) => obj?.[key], document) ?? null;
|
|
1454
|
+
}
|
|
1455
|
+
function implicitDiscriminantValue(member) {
|
|
1456
|
+
if (!discriminator || discriminator.mapping || !dialect.schema.isReference(member)) return null;
|
|
1457
|
+
const value = extractRefName(member.$ref);
|
|
1458
|
+
if (!value) return null;
|
|
1459
|
+
const variant = resolveRefSilent(member.$ref);
|
|
1460
|
+
if (!variant) return null;
|
|
1461
|
+
const propertyName = discriminator.propertyName;
|
|
1462
|
+
const seen = new Set([member.$ref]);
|
|
1463
|
+
function constrains(v) {
|
|
1464
|
+
const prop = v.properties?.[propertyName];
|
|
1465
|
+
const resolved = prop && dialect.schema.isReference(prop) ? resolveRefSilent(prop.$ref) : prop;
|
|
1466
|
+
if (resolved && (Array.isArray(resolved.enum) || resolved.const !== void 0)) return true;
|
|
1467
|
+
const composition = v.allOf ?? v.oneOf ?? v.anyOf;
|
|
1468
|
+
if (!composition) return false;
|
|
1469
|
+
return composition.some((m) => {
|
|
1470
|
+
if (!dialect.schema.isReference(m)) return constrains(m);
|
|
1471
|
+
if (seen.has(m.$ref)) return false;
|
|
1472
|
+
seen.add(m.$ref);
|
|
1473
|
+
const r = resolveRefSilent(m.$ref);
|
|
1474
|
+
return r ? constrains(r) : false;
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
1477
|
+
return constrains(variant) ? null : value;
|
|
1478
|
+
}
|
|
1654
1479
|
const unionMembers = [...schema.oneOf ?? [], ...schema.anyOf ?? []];
|
|
1655
1480
|
const strategy = schema.oneOf ? "one" : "any";
|
|
1656
1481
|
const unionBase = {
|
|
@@ -1659,17 +1484,15 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1659
1484
|
strategy
|
|
1660
1485
|
};
|
|
1661
1486
|
const discriminator = dialect.schema.isDiscriminator(schema) ? schema.discriminator : void 0;
|
|
1662
|
-
const
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
})() : void 0;
|
|
1669
|
-
if (sharedPropertiesNode || discriminator?.mapping) {
|
|
1487
|
+
const { oneOf: _o, anyOf: _a, discriminator: _d, ...memberBaseSchema } = schema;
|
|
1488
|
+
const sharedPropertiesNode = schema.properties ? parseSchema({
|
|
1489
|
+
schema: memberBaseSchema,
|
|
1490
|
+
name
|
|
1491
|
+
}, rawOptions) : void 0;
|
|
1492
|
+
if (sharedPropertiesNode || discriminator) {
|
|
1670
1493
|
const members = unionMembers.map((s) => {
|
|
1671
1494
|
const ref = dialect.schema.isReference(s) ? s.$ref : void 0;
|
|
1672
|
-
const discriminatorValue = findDiscriminator(discriminator?.mapping, ref);
|
|
1495
|
+
const discriminatorValue = findDiscriminator(discriminator?.mapping, ref) ?? implicitDiscriminantValue(s);
|
|
1673
1496
|
const memberNode = parseSchema({
|
|
1674
1497
|
schema: s,
|
|
1675
1498
|
name
|
|
@@ -1822,9 +1645,11 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1822
1645
|
format: schema.format
|
|
1823
1646
|
};
|
|
1824
1647
|
const extensionKey = enumExtensionKeys.find((key) => key in schema);
|
|
1825
|
-
|
|
1648
|
+
const descriptionKey = enumDescriptionKeys.find((key) => key in schema);
|
|
1649
|
+
if (extensionKey || descriptionKey || enumPrimitive === "number" || enumPrimitive === "integer" || enumPrimitive === "boolean") {
|
|
1826
1650
|
const enumPrimitiveType = enumPrimitive === "number" || enumPrimitive === "integer" ? "number" : enumPrimitive === "boolean" ? "boolean" : "string";
|
|
1827
1651
|
const rawEnumNames = extensionKey ? schema[extensionKey] : void 0;
|
|
1652
|
+
const rawEnumDescriptions = descriptionKey ? schema[descriptionKey] : void 0;
|
|
1828
1653
|
const uniqueValues = [...new Set(filteredValues)];
|
|
1829
1654
|
const seenNames = /* @__PURE__ */ new Set();
|
|
1830
1655
|
return ast.factory.createSchema({
|
|
@@ -1833,7 +1658,8 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1833
1658
|
namedEnumValues: uniqueValues.map((value, index) => ({
|
|
1834
1659
|
name: String(rawEnumNames?.[index] ?? value),
|
|
1835
1660
|
value,
|
|
1836
|
-
primitive: enumPrimitiveType
|
|
1661
|
+
primitive: enumPrimitiveType,
|
|
1662
|
+
description: rawEnumDescriptions?.[index]
|
|
1837
1663
|
})).filter((entry) => {
|
|
1838
1664
|
if (seenNames.has(entry.name)) return false;
|
|
1839
1665
|
seenNames.add(entry.name);
|
|
@@ -1903,22 +1729,11 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1903
1729
|
return objectNode;
|
|
1904
1730
|
}
|
|
1905
1731
|
/**
|
|
1906
|
-
* Resolves a tuple's rest-element schema from the `items` keyword that sits alongside `prefixItems`.
|
|
1907
|
-
*
|
|
1908
|
-
* `items: false` closes the tuple, so no rest element is emitted. An absent `items` widens the tail
|
|
1909
|
-
* to `any`, and a schema object (or `items: true`) becomes the homogeneous rest type.
|
|
1910
|
-
*/
|
|
1911
|
-
function resolveTupleRest(items, rawOptions) {
|
|
1912
|
-
if (items === false) return void 0;
|
|
1913
|
-
if (!items || items === true) return ast.factory.createSchema({ type: "any" });
|
|
1914
|
-
return parseSchema({ schema: items }, rawOptions);
|
|
1915
|
-
}
|
|
1916
|
-
/**
|
|
1917
1732
|
* Converts an OAS 3.1 `prefixItems` tuple into a `TupleSchemaNode`.
|
|
1918
1733
|
*/
|
|
1919
1734
|
function convertTuple({ schema, name, nullable, defaultValue, rawOptions }) {
|
|
1920
1735
|
const tupleItems = (schema.prefixItems ?? []).map((item) => parseSchema({ schema: item }, rawOptions));
|
|
1921
|
-
const rest =
|
|
1736
|
+
const rest = schema.items === false ? void 0 : !schema.items || schema.items === true ? ast.factory.createSchema({ type: "any" }) : parseSchema({ schema: schema.items }, rawOptions);
|
|
1922
1737
|
return ast.factory.createSchema({
|
|
1923
1738
|
type: "tuple",
|
|
1924
1739
|
primitive: "array",
|
|
@@ -1988,21 +1803,6 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
1988
1803
|
});
|
|
1989
1804
|
}
|
|
1990
1805
|
/**
|
|
1991
|
-
* Converts an explicit `type: 'null'` schema.
|
|
1992
|
-
*/
|
|
1993
|
-
function convertNull({ schema, name, nullable }) {
|
|
1994
|
-
return ast.factory.createSchema({
|
|
1995
|
-
type: "null",
|
|
1996
|
-
primitive: "null",
|
|
1997
|
-
name,
|
|
1998
|
-
title: schema.title,
|
|
1999
|
-
description: schema.description,
|
|
2000
|
-
deprecated: schema.deprecated,
|
|
2001
|
-
nullable,
|
|
2002
|
-
format: schema.format
|
|
2003
|
-
});
|
|
2004
|
-
}
|
|
2005
|
-
/**
|
|
2006
1806
|
* Converts a binary string schema (`type: 'string'`, `contentMediaType: 'application/octet-stream'`)
|
|
2007
1807
|
* into a `blob` node.
|
|
2008
1808
|
*/
|
|
@@ -2044,94 +1844,76 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2044
1844
|
*/
|
|
2045
1845
|
const schemaRules = [
|
|
2046
1846
|
{
|
|
2047
|
-
name: "ref",
|
|
2048
1847
|
match: ({ schema }) => dialect.schema.isReference(schema),
|
|
2049
1848
|
convert: convertRef
|
|
2050
1849
|
},
|
|
2051
1850
|
{
|
|
2052
|
-
name: "allOf",
|
|
2053
1851
|
match: ({ schema }) => !!schema.allOf?.length,
|
|
2054
1852
|
convert: convertAllOf
|
|
2055
1853
|
},
|
|
2056
1854
|
{
|
|
2057
|
-
name: "union",
|
|
2058
1855
|
match: ({ schema }) => !!(schema.oneOf?.length || schema.anyOf?.length),
|
|
2059
1856
|
convert: convertUnion
|
|
2060
1857
|
},
|
|
2061
1858
|
{
|
|
2062
|
-
name: "const",
|
|
2063
1859
|
match: ({ schema }) => "const" in schema && schema.const !== void 0,
|
|
2064
1860
|
convert: convertConst
|
|
2065
1861
|
},
|
|
2066
1862
|
{
|
|
2067
|
-
name: "format",
|
|
2068
1863
|
match: ({ schema }) => !!schema.format,
|
|
2069
1864
|
convert: convertFormat
|
|
2070
1865
|
},
|
|
2071
1866
|
{
|
|
2072
|
-
name: "blob",
|
|
2073
1867
|
match: ({ schema }) => dialect.schema.isBinary(schema),
|
|
2074
1868
|
convert: convertBlob
|
|
2075
1869
|
},
|
|
2076
1870
|
{
|
|
2077
|
-
name: "multi-type",
|
|
2078
1871
|
match: ({ schema }) => Array.isArray(schema.type) && schema.type.length > 1,
|
|
2079
1872
|
convert: convertMultiType
|
|
2080
1873
|
},
|
|
2081
1874
|
{
|
|
2082
|
-
name: "constrained-string",
|
|
2083
1875
|
match: ({ schema, type }) => !type && (schema.minLength !== void 0 || schema.maxLength !== void 0 || schema.pattern !== void 0),
|
|
2084
1876
|
convert: convertString
|
|
2085
1877
|
},
|
|
2086
1878
|
{
|
|
2087
|
-
name: "constrained-number",
|
|
2088
1879
|
match: ({ schema, type }) => !type && (schema.minimum !== void 0 || schema.maximum !== void 0),
|
|
2089
1880
|
convert: (ctx) => convertNumeric(ctx, "number")
|
|
2090
1881
|
},
|
|
2091
1882
|
{
|
|
2092
|
-
name: "enum",
|
|
2093
1883
|
match: ({ schema }) => !!schema.enum?.length,
|
|
2094
1884
|
convert: convertEnum
|
|
2095
1885
|
},
|
|
2096
1886
|
{
|
|
2097
|
-
name: "object",
|
|
2098
1887
|
match: ({ schema, type }) => type === "object" || !!schema.properties || !!schema.additionalProperties || "patternProperties" in schema,
|
|
2099
1888
|
convert: convertObject
|
|
2100
1889
|
},
|
|
2101
1890
|
{
|
|
2102
|
-
name: "tuple",
|
|
2103
1891
|
match: ({ schema }) => "prefixItems" in schema,
|
|
2104
1892
|
convert: convertTuple
|
|
2105
1893
|
},
|
|
2106
1894
|
{
|
|
2107
|
-
name: "array",
|
|
2108
1895
|
match: ({ schema, type }) => type === "array" || "items" in schema,
|
|
2109
1896
|
convert: convertArray
|
|
2110
1897
|
},
|
|
2111
1898
|
{
|
|
2112
|
-
name: "string",
|
|
2113
1899
|
match: ({ type }) => type === "string",
|
|
2114
1900
|
convert: convertString
|
|
2115
1901
|
},
|
|
2116
1902
|
{
|
|
2117
|
-
name: "number",
|
|
2118
1903
|
match: ({ type }) => type === "number",
|
|
2119
1904
|
convert: (ctx) => convertNumeric(ctx, "number")
|
|
2120
1905
|
},
|
|
2121
1906
|
{
|
|
2122
|
-
name: "integer",
|
|
2123
1907
|
match: ({ type }) => type === "integer",
|
|
2124
1908
|
convert: (ctx) => convertNumeric(ctx, "integer")
|
|
2125
1909
|
},
|
|
2126
1910
|
{
|
|
2127
|
-
name: "boolean",
|
|
2128
1911
|
match: ({ type }) => type === "boolean",
|
|
2129
1912
|
convert: convertBoolean
|
|
2130
1913
|
},
|
|
2131
1914
|
{
|
|
2132
|
-
name: "null",
|
|
2133
1915
|
match: ({ type }) => type === "null",
|
|
2134
|
-
convert:
|
|
1916
|
+
convert: ({ schema, name, nullable }) => createNullSchema(schema, name, nullable)
|
|
2135
1917
|
}
|
|
2136
1918
|
];
|
|
2137
1919
|
/**
|
|
@@ -2186,6 +1968,8 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2186
1968
|
schema: param["schema"],
|
|
2187
1969
|
name: schemaName
|
|
2188
1970
|
}, options) : ast.factory.createSchema({ type: options.unknownType });
|
|
1971
|
+
const style = param["style"];
|
|
1972
|
+
const explode = param["explode"];
|
|
2189
1973
|
return ast.factory.createParameter({
|
|
2190
1974
|
name: paramName,
|
|
2191
1975
|
in: param["in"],
|
|
@@ -2193,7 +1977,9 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2193
1977
|
...schema,
|
|
2194
1978
|
description: param["description"] ?? schema.description
|
|
2195
1979
|
},
|
|
2196
|
-
required
|
|
1980
|
+
required,
|
|
1981
|
+
...style !== void 0 ? { style } : {},
|
|
1982
|
+
...explode !== void 0 ? { explode } : {}
|
|
2197
1983
|
});
|
|
2198
1984
|
}
|
|
2199
1985
|
/**
|
|
@@ -2209,17 +1995,6 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2209
1995
|
};
|
|
2210
1996
|
}
|
|
2211
1997
|
/**
|
|
2212
|
-
* Reads the inline response object (not a `$ref`) and returns its description plus its `content` map.
|
|
2213
|
-
*/
|
|
2214
|
-
function getResponseMeta(responseObj) {
|
|
2215
|
-
if (typeof responseObj !== "object" || responseObj === null || Array.isArray(responseObj)) return {};
|
|
2216
|
-
const inline = responseObj;
|
|
2217
|
-
return {
|
|
2218
|
-
description: inline.description,
|
|
2219
|
-
content: inline.content
|
|
2220
|
-
};
|
|
2221
|
-
}
|
|
2222
|
-
/**
|
|
2223
1998
|
* Collects property names whose schema has a truthy boolean flag (`readOnly` or `writeOnly`).
|
|
2224
1999
|
* `$ref` entries are skipped since their flags live on the dereferenced target.
|
|
2225
2000
|
*/
|
|
@@ -2266,7 +2041,7 @@ function createSchemaParser(ctx, dialect = oasDialect) {
|
|
|
2266
2041
|
statusCode
|
|
2267
2042
|
});
|
|
2268
2043
|
const responseName = operationName ? `${operationName}Status${statusCode}` : void 0;
|
|
2269
|
-
const
|
|
2044
|
+
const description = typeof responseObj === "object" && responseObj !== null ? responseObj.description : void 0;
|
|
2270
2045
|
const parseEntrySchema = (contentType) => {
|
|
2271
2046
|
const raw = getResponseSchema(document, operation, statusCode, { contentType });
|
|
2272
2047
|
return {
|
|
@@ -2335,6 +2110,7 @@ function collectInlineEnums(roots, topLevelNames) {
|
|
|
2335
2110
|
const isSchemaRoot = root.kind === "Schema";
|
|
2336
2111
|
for (const node of ast.collect(root, { schema: (schemaNode) => schemaNode })) {
|
|
2337
2112
|
if (node.type !== "enum" || !node.name) continue;
|
|
2113
|
+
if ((node.namedEnumValues ?? node.enumValues ?? []).length === 1) continue;
|
|
2338
2114
|
if (isSchemaRoot && node === root) continue;
|
|
2339
2115
|
if (topLevelNames.has(node.name)) continue;
|
|
2340
2116
|
if (!promoted.has(node.name)) promoted.set(node.name, {
|
|
@@ -2484,7 +2260,9 @@ function preScan({ schemas, parseSchema, parseOperation, document, parserOptions
|
|
|
2484
2260
|
name
|
|
2485
2261
|
});
|
|
2486
2262
|
if (node.type === "ref" && node.name && node.name !== name) refAliasMap.set(name, node);
|
|
2487
|
-
|
|
2263
|
+
const enumNode = ast.narrowSchema(node, ast.schemaTypes.enum);
|
|
2264
|
+
const isConstEnum = (enumNode?.namedEnumValues ?? enumNode?.enumValues ?? []).length === 1;
|
|
2265
|
+
if (enumNode && node.name && !isConstEnum) enumNames.push(node.name);
|
|
2488
2266
|
if (discriminator === "propagate" && (schema.oneOf ?? schema.anyOf) && schema.discriminator?.propertyName) discriminatorParentNodes.push(node);
|
|
2489
2267
|
}
|
|
2490
2268
|
const circularNames = [...findCircularSchemas(allNodes)];
|