@kubb/adapter-oas 5.17.1 → 5.18.0
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 +441 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -6
- package/dist/index.d.ts +22 -6
- package/dist/index.js +442 -62
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { defineExtension } from "@kubb/core";
|
|
2
2
|
import { Diagnostics, ast, childName, enumPrimitive, enumPropName, extractRefName, macroDedupeUnion, macroDiscriminatorEnum, macroEnumName, mergeAdjacentObjectsLazy } from "@kubb/kit";
|
|
3
|
-
import { join } from "node:path";
|
|
3
|
+
import { dirname, join, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
4
5
|
import { access, readFile } from "node:fs/promises";
|
|
5
6
|
import { upgrade } from "@scalar/openapi-upgrader";
|
|
6
7
|
import { bundle } from "api-ref-bundler";
|
|
@@ -19,7 +20,7 @@ var compatibility = {
|
|
|
19
20
|
"node": ">=22.22"
|
|
20
21
|
};
|
|
21
22
|
// package.json
|
|
22
|
-
var version = "5.
|
|
23
|
+
var version = "5.18.0";
|
|
23
24
|
// src/constants.ts
|
|
24
25
|
/**
|
|
25
26
|
* Default parser options applied when no explicit options are provided.
|
|
@@ -401,6 +402,21 @@ function isOpenApi32(document) {
|
|
|
401
402
|
const [major = 0, minor = 0] = String(document.openapi).split(".").map(Number);
|
|
402
403
|
return major > 3 || major === 3 && minor >= 2;
|
|
403
404
|
}
|
|
405
|
+
function pickStrings(source, keys) {
|
|
406
|
+
if (!source || typeof source !== "object") return void 0;
|
|
407
|
+
const entries = keys.flatMap((key) => {
|
|
408
|
+
const value = source[key];
|
|
409
|
+
return typeof value === "string" ? [[key, value]] : [];
|
|
410
|
+
});
|
|
411
|
+
return entries.length ? Object.fromEntries(entries) : void 0;
|
|
412
|
+
}
|
|
413
|
+
function getExternalDocs(source) {
|
|
414
|
+
const docs = pickStrings(source, ["url", "description"]);
|
|
415
|
+
return docs?.url ? {
|
|
416
|
+
url: docs.url,
|
|
417
|
+
...docs.description !== void 0 && { description: docs.description }
|
|
418
|
+
} : void 0;
|
|
419
|
+
}
|
|
404
420
|
/**
|
|
405
421
|
* Returns the `x-*` keys of `source` as-is, or `undefined` when there are none.
|
|
406
422
|
*/
|
|
@@ -415,12 +431,12 @@ function isReference(obj) {
|
|
|
415
431
|
return !!obj && typeof obj === "object" && "$ref" in obj;
|
|
416
432
|
}
|
|
417
433
|
/**
|
|
418
|
-
* Returns `true` when `obj` is a schema with a structured OAS 3.x `discriminator` object
|
|
419
|
-
* excluding the Swagger 2 string form.
|
|
434
|
+
* Returns `true` when `obj` is a schema with a structured OAS 3.x `discriminator` object that names a
|
|
435
|
+
* `propertyName`, excluding the Swagger 2 string form and a 3.2 discriminator that only sets `defaultMapping`.
|
|
420
436
|
*/
|
|
421
437
|
function isDiscriminator(obj) {
|
|
422
|
-
const
|
|
423
|
-
return !!
|
|
438
|
+
const discriminator = obj?.["discriminator"];
|
|
439
|
+
return !!discriminator && typeof discriminator === "object" && typeof discriminator.propertyName === "string";
|
|
424
440
|
}
|
|
425
441
|
/**
|
|
426
442
|
* Returns `true` when a schema is a raw binary payload.
|
|
@@ -593,6 +609,65 @@ function createRefs(document) {
|
|
|
593
609
|
derefKeepingRef
|
|
594
610
|
};
|
|
595
611
|
}
|
|
612
|
+
// src/load/schemaIds.ts
|
|
613
|
+
const DATA_KEYS = /* @__PURE__ */ new Set([
|
|
614
|
+
"example",
|
|
615
|
+
"examples",
|
|
616
|
+
"const",
|
|
617
|
+
"enum",
|
|
618
|
+
"default"
|
|
619
|
+
]);
|
|
620
|
+
const NAMED_ENTRY_KEYS = /* @__PURE__ */ new Set([
|
|
621
|
+
"properties",
|
|
622
|
+
"patternProperties",
|
|
623
|
+
"$defs",
|
|
624
|
+
"definitions",
|
|
625
|
+
"schemas",
|
|
626
|
+
"dependentSchemas"
|
|
627
|
+
]);
|
|
628
|
+
function walk(node, pointer, visit, parentKey) {
|
|
629
|
+
if (!node || typeof node !== "object") return;
|
|
630
|
+
if (!Array.isArray(node)) visit(node, pointer);
|
|
631
|
+
const named = parentKey !== void 0 && NAMED_ENTRY_KEYS.has(parentKey);
|
|
632
|
+
for (const [key, value] of Object.entries(node)) {
|
|
633
|
+
if (!named && (DATA_KEYS.has(key) || key.startsWith("x-"))) continue;
|
|
634
|
+
walk(value, `${pointer}/${escapePointerToken(key)}`, visit, Array.isArray(node) ? parentKey : key);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* The declaration in the nearest enclosing schema, else the only one, else `undefined`.
|
|
639
|
+
*/
|
|
640
|
+
function pick(declarations, pointer) {
|
|
641
|
+
if (!declarations) return void 0;
|
|
642
|
+
const enclosing = declarations.filter((target) => pointer === target || pointer.startsWith(`${target}/`));
|
|
643
|
+
if (enclosing.length) return enclosing.reduce((a, b) => b.length > a.length ? b : a);
|
|
644
|
+
return declarations.length === 1 ? declarations[0] : void 0;
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Rewrites, in place, each `$ref` to an `$id`, `$anchor` or `$dynamicAnchor`, and each `$dynamicRef`, into a
|
|
648
|
+
* `#/...` pointer, so it is not fetched. Instance data and `x-` extensions are left as written.
|
|
649
|
+
*
|
|
650
|
+
* shortcut: `$id` matches the `$ref` string exactly and `$dynamicRef` resolves statically to the nearest
|
|
651
|
+
* enclosing anchor, so a relative `$id` base or a recursively extended schema is not followed, upgrade when a spec needs that.
|
|
652
|
+
*/
|
|
653
|
+
function resolveSchemaIds(document) {
|
|
654
|
+
const targets = /* @__PURE__ */ new Map();
|
|
655
|
+
const declare = (key, pointer) => targets.set(key, [...targets.get(key) ?? [], pointer]);
|
|
656
|
+
walk(document, "#", (node, pointer) => {
|
|
657
|
+
if (typeof node["$id"] === "string") declare(node["$id"], pointer);
|
|
658
|
+
for (const key of ["$anchor", "$dynamicAnchor"]) if (typeof node[key] === "string") declare(`#${node[key]}`, pointer);
|
|
659
|
+
});
|
|
660
|
+
if (!targets.size) return;
|
|
661
|
+
walk(document, "#", (node, pointer) => {
|
|
662
|
+
const ref = typeof node["$ref"] === "string" ? pick(targets.get(node["$ref"]), pointer) : void 0;
|
|
663
|
+
if (ref) node["$ref"] = ref;
|
|
664
|
+
const dynamicRef = typeof node["$dynamicRef"] === "string" ? pick(targets.get(node["$dynamicRef"]), pointer) : void 0;
|
|
665
|
+
if (dynamicRef && node["$ref"] === void 0) {
|
|
666
|
+
node["$ref"] = dynamicRef;
|
|
667
|
+
delete node["$dynamicRef"];
|
|
668
|
+
}
|
|
669
|
+
});
|
|
670
|
+
}
|
|
596
671
|
// src/load/source.ts
|
|
597
672
|
const urlRegExp = /^https?:\/+/i;
|
|
598
673
|
/**
|
|
@@ -762,6 +837,21 @@ function isExtensionPath(path) {
|
|
|
762
837
|
return path.some((token, index) => String(token).startsWith("x-") && !namedEntryKeys.has(String(path[index - 1])));
|
|
763
838
|
}
|
|
764
839
|
/**
|
|
840
|
+
* Returns the base for relative `$ref`s: the 3.2 `$self` resolved against `pathOrUrl`, else `pathOrUrl`.
|
|
841
|
+
*/
|
|
842
|
+
function getBaseUri(pathOrUrl, root) {
|
|
843
|
+
const self = root && typeof root === "object" ? root.$self : void 0;
|
|
844
|
+
if (typeof self !== "string" || !self) return pathOrUrl;
|
|
845
|
+
try {
|
|
846
|
+
if (urlRegExp.test(self)) return new URL(self).href;
|
|
847
|
+
if (/^file:/i.test(self)) return fileURLToPath(self);
|
|
848
|
+
if (/^[a-z][a-z\d+.-]*:/i.test(self)) return pathOrUrl;
|
|
849
|
+
return urlRegExp.test(pathOrUrl) ? new URL(self, pathOrUrl).href : resolve(dirname(pathOrUrl), self);
|
|
850
|
+
} catch {
|
|
851
|
+
return pathOrUrl;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
765
855
|
* Bundles a multi-file OpenAPI document into a single document via `api-ref-bundler`.
|
|
766
856
|
*
|
|
767
857
|
* External file schemas are hoisted into named `components.schemas` entries, so a property
|
|
@@ -774,8 +864,9 @@ function isExtensionPath(path) {
|
|
|
774
864
|
* all-internal document it is a no-op that still walks the whole tree to confirm that, which
|
|
775
865
|
* costs real time on a large spec.
|
|
776
866
|
*
|
|
777
|
-
* `document` stands in for the file at `pathOrUrl`, such as inline input.
|
|
778
|
-
*
|
|
867
|
+
* `document` stands in for the file at `pathOrUrl`, such as inline input. Relative `$ref`s resolve
|
|
868
|
+
* against the OpenAPI 3.2 `$self` when the document sets one. Every other file or URL read,
|
|
869
|
+
* including one that fails, lands in `sources`. A `$ref` that cannot be read reports
|
|
779
870
|
* `KUBB_REF_NOT_FOUND` at the key that holds it, as a warning when it sits inside an `x-` extension.
|
|
780
871
|
*
|
|
781
872
|
* @example Local file
|
|
@@ -787,8 +878,10 @@ function isExtensionPath(path) {
|
|
|
787
878
|
async function bundleDocument(pathOrUrl, { document, sources = [] } = {}) {
|
|
788
879
|
const cache = /* @__PURE__ */ new Map();
|
|
789
880
|
const toKey = (sourcePath) => urlRegExp.test(sourcePath) ? new URL(sourcePath).href : sourcePath;
|
|
881
|
+
let entry = pathOrUrl;
|
|
882
|
+
let entryDocument = document;
|
|
790
883
|
const resolver = (sourcePath) => {
|
|
791
|
-
if (
|
|
884
|
+
if (entryDocument !== void 0 && toKey(sourcePath) === toKey(entry)) return Promise.resolve(entryDocument);
|
|
792
885
|
const key = toKey(sourcePath);
|
|
793
886
|
const cached = cache.get(key);
|
|
794
887
|
if (cached) return cached;
|
|
@@ -798,9 +891,12 @@ async function bundleDocument(pathOrUrl, { document, sources = [] } = {}) {
|
|
|
798
891
|
return result;
|
|
799
892
|
};
|
|
800
893
|
const root = await resolver(pathOrUrl);
|
|
894
|
+
resolveSchemaIds(root);
|
|
801
895
|
if (typeof root === "object" && root !== null && !hasExternalRef(root)) return root;
|
|
802
|
-
|
|
803
|
-
|
|
896
|
+
entry = getBaseUri(pathOrUrl, root);
|
|
897
|
+
entryDocument = root;
|
|
898
|
+
return await bundle(entry, resolver, { hooks: { onError: (message, { path, state }) => {
|
|
899
|
+
const pointer = toKey(state.baseFile) === toKey(entry) ? `#/${path.map((token) => escapePointerToken(String(token))).join("/")}` : void 0;
|
|
804
900
|
const diagnostic = {
|
|
805
901
|
code: Diagnostics.code.refNotFound,
|
|
806
902
|
severity: isExtensionPath(path) ? "warning" : "error",
|
|
@@ -839,10 +935,12 @@ async function parseFromConfig(source, sources = []) {
|
|
|
839
935
|
origin: "the inline `input` string",
|
|
840
936
|
help: "Fix the syntax at the reported line. Kubb reads `input` as an inline spec, not a file path, because it starts with `{`, `[`, `openapi:`, or `swagger:`, or spans several lines."
|
|
841
937
|
}) : structuredClone(source.data);
|
|
842
|
-
|
|
938
|
+
if (source.root && hasExternalRef(data)) return bundleDocument(join(source.root, inlineInputName), {
|
|
843
939
|
document: data,
|
|
844
940
|
sources
|
|
845
|
-
})
|
|
941
|
+
});
|
|
942
|
+
resolveSchemaIds(data);
|
|
943
|
+
return data;
|
|
846
944
|
}
|
|
847
945
|
await assertInputExists(source.path);
|
|
848
946
|
return bundleDocument(source.path, { sources });
|
|
@@ -1167,6 +1265,80 @@ function getSchemas(document, { contentType }, refs) {
|
|
|
1167
1265
|
pointers
|
|
1168
1266
|
};
|
|
1169
1267
|
}
|
|
1268
|
+
// src/model/security.ts
|
|
1269
|
+
const SCHEME_POINTER = "#/components/securitySchemes/";
|
|
1270
|
+
const API_KEY_LOCATIONS = /* @__PURE__ */ new Set([
|
|
1271
|
+
"header",
|
|
1272
|
+
"query",
|
|
1273
|
+
"cookie"
|
|
1274
|
+
]);
|
|
1275
|
+
function getCredential(scheme) {
|
|
1276
|
+
if (scheme.type === "apiKey") return scheme.name && scheme.in && API_KEY_LOCATIONS.has(scheme.in) ? {
|
|
1277
|
+
type: "apiKey",
|
|
1278
|
+
in: scheme.in,
|
|
1279
|
+
name: scheme.name
|
|
1280
|
+
} : void 0;
|
|
1281
|
+
if (scheme.type === "http") return scheme.scheme ? {
|
|
1282
|
+
type: "http",
|
|
1283
|
+
scheme: scheme.scheme.toLowerCase(),
|
|
1284
|
+
...scheme.bearerFormat && { bearerFormat: scheme.bearerFormat }
|
|
1285
|
+
} : void 0;
|
|
1286
|
+
if (scheme.type === "openIdConnect") return {
|
|
1287
|
+
type: "openIdConnect",
|
|
1288
|
+
...scheme.openIdConnectUrl && { url: scheme.openIdConnectUrl }
|
|
1289
|
+
};
|
|
1290
|
+
if (scheme.type === "oauth2") {
|
|
1291
|
+
const flows = Object.entries(scheme.flows ?? {}).map(([name, flow]) => {
|
|
1292
|
+
const scopes = flow && typeof flow === "object" && flow.scopes && typeof flow.scopes === "object" ? { scopes: flow.scopes } : {};
|
|
1293
|
+
return [name, {
|
|
1294
|
+
...pickStrings(flow, [
|
|
1295
|
+
"authorizationUrl",
|
|
1296
|
+
"deviceAuthorizationUrl",
|
|
1297
|
+
"tokenUrl",
|
|
1298
|
+
"refreshUrl"
|
|
1299
|
+
]),
|
|
1300
|
+
...scopes
|
|
1301
|
+
}];
|
|
1302
|
+
});
|
|
1303
|
+
return {
|
|
1304
|
+
type: "oauth2",
|
|
1305
|
+
flows: Object.fromEntries(flows),
|
|
1306
|
+
...scheme.oauth2MetadataUrl && { metadataUrl: scheme.oauth2MetadataUrl }
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
return scheme.type === "mutualTLS" ? { type: "mutualTLS" } : void 0;
|
|
1310
|
+
}
|
|
1311
|
+
/**
|
|
1312
|
+
* Maps `components.securitySchemes` to `AuthScheme` entries, leaving out a scheme a client cannot place.
|
|
1313
|
+
*/
|
|
1314
|
+
function toAuthSchemes(schemes, refs) {
|
|
1315
|
+
return Object.entries(schemes ?? {}).flatMap(([name, value]) => {
|
|
1316
|
+
const scheme = refs.deref(value);
|
|
1317
|
+
const credential = scheme && getCredential(scheme);
|
|
1318
|
+
if (!scheme || !credential) return [];
|
|
1319
|
+
return [{
|
|
1320
|
+
name,
|
|
1321
|
+
...scheme.description && { description: scheme.description },
|
|
1322
|
+
...scheme.deprecated && { deprecated: true },
|
|
1323
|
+
credential
|
|
1324
|
+
}];
|
|
1325
|
+
});
|
|
1326
|
+
}
|
|
1327
|
+
/**
|
|
1328
|
+
* Maps security requirements to `AuthRequirement` entries. A 3.2 URI key becomes the scheme name.
|
|
1329
|
+
*/
|
|
1330
|
+
function toAuthRequirements(requirements, document) {
|
|
1331
|
+
if (!Array.isArray(requirements)) return void 0;
|
|
1332
|
+
const schemes = document.components?.securitySchemes ?? {};
|
|
1333
|
+
const toName = (key) => {
|
|
1334
|
+
const index = key.indexOf(SCHEME_POINTER);
|
|
1335
|
+
return Object.hasOwn(schemes, key) || index === -1 ? key : unescapePointerToken(key.slice(index + 29));
|
|
1336
|
+
};
|
|
1337
|
+
return requirements.filter((requirement) => !!requirement && typeof requirement === "object").map((requirement) => Object.entries(requirement).map(([key, scopes]) => ({
|
|
1338
|
+
scheme: toName(key),
|
|
1339
|
+
...Array.isArray(scopes) && scopes.length && { scopes: scopes.map(String) }
|
|
1340
|
+
})));
|
|
1341
|
+
}
|
|
1170
1342
|
// src/model/server.ts
|
|
1171
1343
|
/**
|
|
1172
1344
|
* Reads the server URL from the document's `servers` array at `server.index`,
|
|
@@ -1223,8 +1395,11 @@ function resolveServerUrl(server, overrides) {
|
|
|
1223
1395
|
* Maps OpenAPI servers to `InputServer` entries: drops entries without a `url` and fills `{variable}` defaults.
|
|
1224
1396
|
*/
|
|
1225
1397
|
function toInputServers(servers) {
|
|
1226
|
-
return servers.filter((entry) => entry.url).map(({ url, description, variables }) => {
|
|
1227
|
-
const declared =
|
|
1398
|
+
return servers.filter((entry) => entry.url).map(({ url, name, description, variables }) => {
|
|
1399
|
+
const declared = {
|
|
1400
|
+
...name !== void 0 && { name },
|
|
1401
|
+
...variables && Object.keys(variables).length > 0 && { variables }
|
|
1402
|
+
};
|
|
1228
1403
|
try {
|
|
1229
1404
|
return {
|
|
1230
1405
|
url: resolveServerUrl({
|
|
@@ -1243,6 +1418,20 @@ function toInputServers(servers) {
|
|
|
1243
1418
|
}
|
|
1244
1419
|
});
|
|
1245
1420
|
}
|
|
1421
|
+
// src/model/tag.ts
|
|
1422
|
+
function toInputTags(tags) {
|
|
1423
|
+
return tags.filter((tag) => typeof tag.name === "string").map(({ name, summary, description, parent, kind, externalDocs }) => {
|
|
1424
|
+
const docs = getExternalDocs(externalDocs);
|
|
1425
|
+
return {
|
|
1426
|
+
name,
|
|
1427
|
+
...typeof summary === "string" && { summary },
|
|
1428
|
+
...typeof description === "string" && { description },
|
|
1429
|
+
...typeof parent === "string" && { parent },
|
|
1430
|
+
...typeof kind === "string" && { kind },
|
|
1431
|
+
...docs && { externalDocs: docs }
|
|
1432
|
+
};
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1246
1435
|
// src/model/mediaType.ts
|
|
1247
1436
|
/**
|
|
1248
1437
|
* The media type without its parameters, so `text/event-stream; charset=utf-8` matches the bare name.
|
|
@@ -1600,7 +1789,8 @@ const PARAMETER_STYLES = /* @__PURE__ */ new Set([
|
|
|
1600
1789
|
"simple",
|
|
1601
1790
|
"spaceDelimited",
|
|
1602
1791
|
"pipeDelimited",
|
|
1603
|
-
"deepObject"
|
|
1792
|
+
"deepObject",
|
|
1793
|
+
"cookie"
|
|
1604
1794
|
]);
|
|
1605
1795
|
function pickStyleFields({ style, explode, allowReserved }) {
|
|
1606
1796
|
return {
|
|
@@ -1609,16 +1799,45 @@ function pickStyleFields({ style, explode, allowReserved }) {
|
|
|
1609
1799
|
...allowReserved !== void 0 ? { allowReserved } : {}
|
|
1610
1800
|
};
|
|
1611
1801
|
}
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
const node = {
|
|
1616
|
-
...contentType !== void 0 ? { contentType } : {},
|
|
1617
|
-
...pickStyleFields(rest)
|
|
1618
|
-
};
|
|
1802
|
+
function getEncodingFields({ encoding, prefixEncoding, itemEncoding }) {
|
|
1803
|
+
const entries = Object.entries(encoding ?? {}).flatMap(([property, entry]) => {
|
|
1804
|
+
const node = toEncodingNode(entry);
|
|
1619
1805
|
return Object.keys(node).length ? [[property, node]] : [];
|
|
1620
1806
|
});
|
|
1621
|
-
|
|
1807
|
+
const item = itemEncoding && toEncodingNode(itemEncoding);
|
|
1808
|
+
return {
|
|
1809
|
+
...entries.length && { encoding: Object.fromEntries(entries) },
|
|
1810
|
+
...prefixEncoding?.length && { prefixEncoding: prefixEncoding.map(toEncodingNode) },
|
|
1811
|
+
...item && Object.keys(item).length && { itemEncoding: item }
|
|
1812
|
+
};
|
|
1813
|
+
}
|
|
1814
|
+
function toEncodingNode({ contentType, encoding, prefixEncoding, itemEncoding, ...rest }) {
|
|
1815
|
+
return {
|
|
1816
|
+
...contentType !== void 0 && { contentType },
|
|
1817
|
+
...pickStyleFields(rest),
|
|
1818
|
+
...getEncodingFields({
|
|
1819
|
+
encoding,
|
|
1820
|
+
prefixEncoding,
|
|
1821
|
+
itemEncoding
|
|
1822
|
+
})
|
|
1823
|
+
};
|
|
1824
|
+
}
|
|
1825
|
+
function getExamples({ example, examples }, refs) {
|
|
1826
|
+
const named = Object.entries(examples ?? {}).flatMap(([name, entry]) => {
|
|
1827
|
+
const resolved = refs.deref(entry);
|
|
1828
|
+
if (!resolved) return [];
|
|
1829
|
+
const { summary, description, dataValue, value, serializedValue } = resolved;
|
|
1830
|
+
const data = dataValue !== void 0 ? dataValue : value;
|
|
1831
|
+
return [{
|
|
1832
|
+
name,
|
|
1833
|
+
...typeof summary === "string" && { summary },
|
|
1834
|
+
...typeof description === "string" && { description },
|
|
1835
|
+
...data !== void 0 && { value: data },
|
|
1836
|
+
...typeof serializedValue === "string" && { serializedValue }
|
|
1837
|
+
}];
|
|
1838
|
+
});
|
|
1839
|
+
if (named.length) return { examples: named };
|
|
1840
|
+
return example !== void 0 ? { examples: [{ value: example }] } : {};
|
|
1622
1841
|
}
|
|
1623
1842
|
/**
|
|
1624
1843
|
* Returns the media type entry for `contentType`, resolving a `$ref` into `components.mediaTypes`. `null` when absent.
|
|
@@ -1647,6 +1866,24 @@ function getBodySchema({ content, contentType, refs, document }) {
|
|
|
1647
1866
|
if (binary) return binary;
|
|
1648
1867
|
return schema ? refs.derefKeepingRef(schema) : null;
|
|
1649
1868
|
}
|
|
1869
|
+
function getLinks(links, refs) {
|
|
1870
|
+
const entries = Object.entries(links ?? {}).flatMap(([name, value]) => {
|
|
1871
|
+
const link = refs.deref(value);
|
|
1872
|
+
if (!link) return [];
|
|
1873
|
+
const server = link.server ? toInputServers([link.server])[0] : void 0;
|
|
1874
|
+
return [[name, {
|
|
1875
|
+
...pickStrings(link, [
|
|
1876
|
+
"operationId",
|
|
1877
|
+
"operationRef",
|
|
1878
|
+
"description"
|
|
1879
|
+
]),
|
|
1880
|
+
...link.parameters && { parameters: link.parameters },
|
|
1881
|
+
..."requestBody" in link && { requestBody: link.requestBody },
|
|
1882
|
+
...server && { server }
|
|
1883
|
+
}]];
|
|
1884
|
+
});
|
|
1885
|
+
return entries.length ? Object.fromEntries(entries) : void 0;
|
|
1886
|
+
}
|
|
1650
1887
|
/** The `stream` field of a content node, set when the media type is a stream. `node` is the parsed item schema. */
|
|
1651
1888
|
function getStreamField({ contentType, mediaType, refs, document, node }) {
|
|
1652
1889
|
if (!isStream(contentType, mediaType)) return {};
|
|
@@ -1717,11 +1954,12 @@ function collectPropertyKeysByFlag(schema, flag) {
|
|
|
1717
1954
|
function parseParameter({ param, pointer, parentName, options, parseSchema, refs }) {
|
|
1718
1955
|
const schemaName = parentName && param.name ? pascalCase(`${parentName} ${param.name}`) : void 0;
|
|
1719
1956
|
const contentType = param.schema ? void 0 : Object.keys(param.content ?? {})[0];
|
|
1720
|
-
const
|
|
1957
|
+
const mediaType = getMediaType({
|
|
1721
1958
|
content: param.content,
|
|
1722
1959
|
contentType,
|
|
1723
1960
|
refs
|
|
1724
|
-
})
|
|
1961
|
+
});
|
|
1962
|
+
const rawSchema = param.schema ?? mediaType?.schema;
|
|
1725
1963
|
const schema = rawSchema ? parseSchema({
|
|
1726
1964
|
schema: rawSchema,
|
|
1727
1965
|
name: schemaName
|
|
@@ -1737,7 +1975,10 @@ function parseParameter({ param, pointer, parentName, options, parseSchema, refs
|
|
|
1737
1975
|
},
|
|
1738
1976
|
required: param.required ?? false,
|
|
1739
1977
|
...pickStyleFields(param),
|
|
1740
|
-
...contentType !== void 0 ? { contentType } : {}
|
|
1978
|
+
...contentType !== void 0 ? { contentType } : {},
|
|
1979
|
+
...getExamples(mediaType ?? param, refs),
|
|
1980
|
+
...param.deprecated && { deprecated: true },
|
|
1981
|
+
...param.allowEmptyValue && { allowEmptyValue: true }
|
|
1741
1982
|
});
|
|
1742
1983
|
}
|
|
1743
1984
|
/**
|
|
@@ -1782,12 +2023,12 @@ function parseOperation({ operation, ...ctx }) {
|
|
|
1782
2023
|
name: requestBodyName
|
|
1783
2024
|
}), bodyRequired);
|
|
1784
2025
|
scanSchema(node, `${mediaTypePointer(body?.content, ct, `${pointer}/requestBody/content/${escapePointerToken(ct)}`)}/${schemaKeyword(mediaType)}`);
|
|
1785
|
-
const encoding = getEncoding(mediaType?.encoding);
|
|
1786
2026
|
return [ast.factory.createContent({
|
|
1787
2027
|
contentType: ct,
|
|
1788
2028
|
schema: node,
|
|
1789
2029
|
keysToOmit: collectPropertyKeysByFlag(schema, "readOnly"),
|
|
1790
|
-
...
|
|
2030
|
+
...mediaType && getEncodingFields(mediaType),
|
|
2031
|
+
...mediaType && getExamples(mediaType, refs),
|
|
1791
2032
|
...getStreamField({
|
|
1792
2033
|
contentType: ct,
|
|
1793
2034
|
mediaType,
|
|
@@ -1830,6 +2071,8 @@ function parseOperation({ operation, ...ctx }) {
|
|
|
1830
2071
|
return {
|
|
1831
2072
|
schema: node,
|
|
1832
2073
|
keysToOmit: collectPropertyKeysByFlag(raw, "writeOnly"),
|
|
2074
|
+
...mediaType && getEncodingFields(mediaType),
|
|
2075
|
+
...mediaType && getExamples(mediaType, refs),
|
|
1833
2076
|
...ct ? getStreamField({
|
|
1834
2077
|
contentType: ct,
|
|
1835
2078
|
mediaType,
|
|
@@ -1848,11 +2091,32 @@ function parseOperation({ operation, ...ctx }) {
|
|
|
1848
2091
|
contentType: "",
|
|
1849
2092
|
...parseEntrySchema(contentType)
|
|
1850
2093
|
}));
|
|
2094
|
+
const responsePointer = `${pointer}/responses/${statusCode}`;
|
|
2095
|
+
const headers = Object.entries(response?.headers ?? {}).flatMap(([name, value]) => {
|
|
2096
|
+
const header = name.toLowerCase() === "content-type" ? null : refs.deref(value);
|
|
2097
|
+
if (!header) return [];
|
|
2098
|
+
return [parseParameter({
|
|
2099
|
+
param: {
|
|
2100
|
+
...header,
|
|
2101
|
+
name,
|
|
2102
|
+
in: "header"
|
|
2103
|
+
},
|
|
2104
|
+
pointer: `${responsePointer}/headers/${escapePointerToken(name)}`,
|
|
2105
|
+
parentName: responseName,
|
|
2106
|
+
options,
|
|
2107
|
+
parseSchema,
|
|
2108
|
+
refs
|
|
2109
|
+
})];
|
|
2110
|
+
});
|
|
2111
|
+
const links = getLinks(response?.links, refs);
|
|
1851
2112
|
return ast.factory.createResponse({
|
|
1852
|
-
pointer:
|
|
2113
|
+
pointer: responsePointer,
|
|
1853
2114
|
statusCode,
|
|
2115
|
+
summary: response?.summary,
|
|
1854
2116
|
description: response?.description,
|
|
1855
|
-
content: responseContent
|
|
2117
|
+
content: responseContent,
|
|
2118
|
+
...headers.length && { headers },
|
|
2119
|
+
...links && { links }
|
|
1856
2120
|
});
|
|
1857
2121
|
});
|
|
1858
2122
|
const pickDoc = (key) => {
|
|
@@ -1862,6 +2126,7 @@ function parseOperation({ operation, ...ctx }) {
|
|
|
1862
2126
|
return typeof fallback === "string" ? fallback : void 0;
|
|
1863
2127
|
};
|
|
1864
2128
|
const servers = operation.schema.servers ?? operation.pathItem.servers;
|
|
2129
|
+
const auth = toAuthRequirements(operation.schema.security ?? document.security, document);
|
|
1865
2130
|
return ast.factory.createOperation({
|
|
1866
2131
|
pointer,
|
|
1867
2132
|
operationId,
|
|
@@ -1872,11 +2137,13 @@ function parseOperation({ operation, ...ctx }) {
|
|
|
1872
2137
|
summary: pickDoc("summary") || void 0,
|
|
1873
2138
|
description: pickDoc("description") || void 0,
|
|
1874
2139
|
deprecated: operation.schema.deprecated || void 0,
|
|
2140
|
+
externalDocs: getExternalDocs(operation.schema.externalDocs),
|
|
1875
2141
|
parameters,
|
|
1876
2142
|
requestBody,
|
|
1877
2143
|
responses,
|
|
1878
2144
|
extensions: pickExtensions(operation.schema),
|
|
1879
|
-
...servers && { servers: toInputServers(servers) }
|
|
2145
|
+
...servers && { servers: toInputServers(servers) },
|
|
2146
|
+
...auth && { auth }
|
|
1880
2147
|
});
|
|
1881
2148
|
}
|
|
1882
2149
|
// src/emit/createNode.ts
|
|
@@ -1897,6 +2164,7 @@ function createNode({ schema, name, nullable, defaultValue }, extras) {
|
|
|
1897
2164
|
default: defaultValue,
|
|
1898
2165
|
examples: extractExamples(schema),
|
|
1899
2166
|
format: schema.format,
|
|
2167
|
+
externalDocs: getExternalDocs(schema.externalDocs),
|
|
1900
2168
|
...extras
|
|
1901
2169
|
});
|
|
1902
2170
|
}
|
|
@@ -2361,13 +2629,15 @@ const annotationKeys = /* @__PURE__ */ new Set([
|
|
|
2361
2629
|
]);
|
|
2362
2630
|
/**
|
|
2363
2631
|
* Moves `allOf` members that hold only annotations or `if`/`then`/`else` onto the parent, so they do
|
|
2364
|
-
* not become `unknown`. The parent's own values win
|
|
2632
|
+
* not become `unknown`. The parent's own values win. The parser reads their `if`/`then`/`else` into `conditionals`.
|
|
2365
2633
|
*/
|
|
2634
|
+
function isAnnotationMember(member) {
|
|
2635
|
+
return !!member && typeof member === "object" && !isReference(member) && Object.keys(member).every((key) => annotationKeys.has(key));
|
|
2636
|
+
}
|
|
2366
2637
|
function mergeAnnotations(schema) {
|
|
2367
2638
|
const members = schema.allOf;
|
|
2368
|
-
const
|
|
2369
|
-
const
|
|
2370
|
-
const rest = members.filter((member) => !isAnnotation(member));
|
|
2639
|
+
const annotations = members.filter(isAnnotationMember);
|
|
2640
|
+
const rest = members.filter((member) => !isAnnotationMember(member));
|
|
2371
2641
|
return annotations.length && rest.length ? {
|
|
2372
2642
|
...Object.assign({}, ...annotations),
|
|
2373
2643
|
...schema,
|
|
@@ -2400,7 +2670,8 @@ function convertAllOf({ schema: original, name, nullable, defaultValue, parse, r
|
|
|
2400
2670
|
default: mergedDefault,
|
|
2401
2671
|
examples: extractExamples(schema) ?? memberNode.examples,
|
|
2402
2672
|
pattern: schema.pattern ?? ("pattern" in memberNode ? memberNode.pattern : void 0),
|
|
2403
|
-
format: schema.format ?? memberNode.format
|
|
2673
|
+
format: schema.format ?? memberNode.format,
|
|
2674
|
+
externalDocs: getExternalDocs(schema.externalDocs) ?? memberNode.externalDocs
|
|
2404
2675
|
});
|
|
2405
2676
|
}
|
|
2406
2677
|
const { members: discriminatedAllOf, discriminantValues } = extractDiscriminatedAllOfMembers({
|
|
@@ -2475,7 +2746,7 @@ function convertUnion(context) {
|
|
|
2475
2746
|
};
|
|
2476
2747
|
const discriminator = isDiscriminator(schema) ? schema.discriminator : void 0;
|
|
2477
2748
|
const declaredMembers = [...schema.oneOf ?? [], ...schema.anyOf ?? []];
|
|
2478
|
-
const defaultRef = getDefaultMappingRef(discriminator);
|
|
2749
|
+
const defaultRef = getDefaultMappingRef(typeof schema.discriminator === "object" ? schema.discriminator : void 0);
|
|
2479
2750
|
const unionMembers = resolveUnionMembers(defaultRef && !declaredMembers.some((member) => isReference(member) && member.$ref === defaultRef) ? [...declaredMembers, { $ref: defaultRef }] : declaredMembers, schema.properties ?? {});
|
|
2480
2751
|
const strategy = schema.oneOf ? "one" : "any";
|
|
2481
2752
|
const explicitDiscriminatorPropertyName = discriminator?.propertyName;
|
|
@@ -2587,11 +2858,18 @@ function getPrimitiveType(type) {
|
|
|
2587
2858
|
}
|
|
2588
2859
|
/** Shared by number, integer and bigint nodes; the exclusive bounds keep only the OAS 3.1 numeric form. */
|
|
2589
2860
|
function getNumericConstraints(schema) {
|
|
2861
|
+
const exclusiveMinimum = typeof schema.exclusiveMinimum === "number" ? schema.exclusiveMinimum : void 0;
|
|
2862
|
+
const exclusiveMaximum = typeof schema.exclusiveMaximum === "number" ? schema.exclusiveMaximum : void 0;
|
|
2863
|
+
const hasExclusive = exclusiveMinimum !== void 0 || exclusiveMaximum !== void 0;
|
|
2590
2864
|
return {
|
|
2591
2865
|
min: schema.minimum,
|
|
2592
2866
|
max: schema.maximum,
|
|
2593
|
-
|
|
2594
|
-
|
|
2867
|
+
...hasExclusive && { exclusive: {
|
|
2868
|
+
...exclusiveMinimum !== void 0 && { min: exclusiveMinimum },
|
|
2869
|
+
...exclusiveMaximum !== void 0 && { max: exclusiveMaximum }
|
|
2870
|
+
} },
|
|
2871
|
+
exclusiveMinimum,
|
|
2872
|
+
exclusiveMaximum,
|
|
2595
2873
|
multipleOf: schema.multipleOf
|
|
2596
2874
|
};
|
|
2597
2875
|
}
|
|
@@ -2600,11 +2878,11 @@ function getNumericConstraints(schema) {
|
|
|
2600
2878
|
*/
|
|
2601
2879
|
function isWithinBounds({ value, schema }) {
|
|
2602
2880
|
if (typeof value !== "number") return true;
|
|
2603
|
-
const { min, max,
|
|
2881
|
+
const { min, max, exclusive, multipleOf } = getNumericConstraints(schema);
|
|
2604
2882
|
if (min !== void 0 && value < min) return false;
|
|
2605
2883
|
if (max !== void 0 && value > max) return false;
|
|
2606
|
-
if (
|
|
2607
|
-
if (
|
|
2884
|
+
if (exclusive?.min !== void 0 && value <= exclusive.min) return false;
|
|
2885
|
+
if (exclusive?.max !== void 0 && value >= exclusive.max) return false;
|
|
2608
2886
|
if (multipleOf !== void 0 && Math.abs(value / multipleOf - Math.round(value / multipleOf)) > 1e-9) return false;
|
|
2609
2887
|
return true;
|
|
2610
2888
|
}
|
|
@@ -2762,6 +3040,15 @@ function convertFormattedEnum(context) {
|
|
|
2762
3040
|
}))
|
|
2763
3041
|
});
|
|
2764
3042
|
}
|
|
3043
|
+
function getStringContent({ schema, parse }) {
|
|
3044
|
+
const { contentMediaType: mediaType, contentEncoding: encoding, contentSchema } = schema;
|
|
3045
|
+
if (mediaType === void 0 && encoding === void 0 && !contentSchema) return {};
|
|
3046
|
+
return { content: {
|
|
3047
|
+
...mediaType !== void 0 && { mediaType },
|
|
3048
|
+
...encoding !== void 0 && { encoding },
|
|
3049
|
+
...contentSchema && { schema: parse({ schema: contentSchema }) }
|
|
3050
|
+
} };
|
|
3051
|
+
}
|
|
2765
3052
|
/**
|
|
2766
3053
|
* Converts a `type: 'string'` schema into a `StringSchemaNode`.
|
|
2767
3054
|
*/
|
|
@@ -2772,7 +3059,8 @@ function convertString(context) {
|
|
|
2772
3059
|
primitive: "string",
|
|
2773
3060
|
min: schema.minLength,
|
|
2774
3061
|
max: schema.maxLength,
|
|
2775
|
-
pattern: schema.pattern
|
|
3062
|
+
pattern: schema.pattern,
|
|
3063
|
+
...getStringContent(context)
|
|
2776
3064
|
});
|
|
2777
3065
|
}
|
|
2778
3066
|
/**
|
|
@@ -2786,6 +3074,15 @@ function convertNumeric(context, type) {
|
|
|
2786
3074
|
});
|
|
2787
3075
|
}
|
|
2788
3076
|
// src/emit/converters/structural.ts
|
|
3077
|
+
function getContains(schema, parse) {
|
|
3078
|
+
const { contains, minContains, maxContains } = schema;
|
|
3079
|
+
if (!contains || typeof contains !== "object") return {};
|
|
3080
|
+
return { contains: {
|
|
3081
|
+
schema: parse({ schema: contains }),
|
|
3082
|
+
...typeof minContains === "number" && { min: minContains },
|
|
3083
|
+
...typeof maxContains === "number" && { max: maxContains }
|
|
3084
|
+
} };
|
|
3085
|
+
}
|
|
2789
3086
|
/**
|
|
2790
3087
|
* Resolves a `true` or empty-object map schema (`additionalProperties`/`patternProperties`) to
|
|
2791
3088
|
* `options.unknownType`, otherwise parses it as a regular schema.
|
|
@@ -2838,7 +3135,7 @@ function convertObject({ schema, name, nullable, defaultValue, options, parse, r
|
|
|
2838
3135
|
required
|
|
2839
3136
|
});
|
|
2840
3137
|
}) : [];
|
|
2841
|
-
const additionalProperties = schema.additionalProperties;
|
|
3138
|
+
const additionalProperties = schema.additionalProperties ?? schema.unevaluatedProperties;
|
|
2842
3139
|
const additionalPropertiesNode = (() => {
|
|
2843
3140
|
if (additionalProperties === true) return true;
|
|
2844
3141
|
if (additionalProperties) return resolveMapSchema(additionalProperties, {
|
|
@@ -2868,6 +3165,8 @@ function convertObject({ schema, name, nullable, defaultValue, options, parse, r
|
|
|
2868
3165
|
additionalProperties: additionalPropertiesNode,
|
|
2869
3166
|
patternProperties,
|
|
2870
3167
|
propertyNames,
|
|
3168
|
+
min: schema.minProperties,
|
|
3169
|
+
max: schema.maxProperties,
|
|
2871
3170
|
minProperties: schema.minProperties,
|
|
2872
3171
|
maxProperties: schema.maxProperties
|
|
2873
3172
|
});
|
|
@@ -2898,7 +3197,8 @@ function convertObject({ schema, name, nullable, defaultValue, options, parse, r
|
|
|
2898
3197
|
*/
|
|
2899
3198
|
function convertTuple({ schema, name, nullable, defaultValue, options, parse }) {
|
|
2900
3199
|
const tupleItems = (schema.prefixItems ?? []).map((item) => parse({ schema: item }));
|
|
2901
|
-
const
|
|
3200
|
+
const tail = schema.items ?? schema.unevaluatedItems;
|
|
3201
|
+
const rest = tail === false ? void 0 : !tail || tail === true ? ast.factory.createSchema({ type: options.unknownType }) : parse({ schema: tail });
|
|
2902
3202
|
return createNode({
|
|
2903
3203
|
schema,
|
|
2904
3204
|
name,
|
|
@@ -2910,7 +3210,8 @@ function convertTuple({ schema, name, nullable, defaultValue, options, parse })
|
|
|
2910
3210
|
items: tupleItems,
|
|
2911
3211
|
rest,
|
|
2912
3212
|
min: schema.minItems,
|
|
2913
|
-
max: schema.maxItems
|
|
3213
|
+
max: schema.maxItems,
|
|
3214
|
+
...getContains(schema, parse)
|
|
2914
3215
|
});
|
|
2915
3216
|
}
|
|
2916
3217
|
/**
|
|
@@ -2934,7 +3235,8 @@ function convertArray({ schema, name, nullable, defaultValue, options, parse })
|
|
|
2934
3235
|
items,
|
|
2935
3236
|
min: schema.minItems,
|
|
2936
3237
|
max: schema.maxItems,
|
|
2937
|
-
unique: schema.uniqueItems ?? void 0
|
|
3238
|
+
unique: schema.uniqueItems ?? void 0,
|
|
3239
|
+
...getContains(schema, parse)
|
|
2938
3240
|
});
|
|
2939
3241
|
}
|
|
2940
3242
|
// src/emit/parseSchema.ts
|
|
@@ -3062,6 +3364,20 @@ const schemaRules = [
|
|
|
3062
3364
|
];
|
|
3063
3365
|
// src/parser.ts
|
|
3064
3366
|
/**
|
|
3367
|
+
* `unevaluated*` also sees what composition siblings evaluate, so with such a sibling it is dropped to keep the schema open.
|
|
3368
|
+
*/
|
|
3369
|
+
function hasUnevaluatedSiblings(schema) {
|
|
3370
|
+
if (schema.unevaluatedProperties === void 0 && schema.unevaluatedItems === void 0) return false;
|
|
3371
|
+
return [
|
|
3372
|
+
schema.allOf,
|
|
3373
|
+
schema.anyOf,
|
|
3374
|
+
schema.oneOf,
|
|
3375
|
+
schema.if,
|
|
3376
|
+
schema.dependentSchemas,
|
|
3377
|
+
schema.$ref
|
|
3378
|
+
].some((value) => value !== void 0);
|
|
3379
|
+
}
|
|
3380
|
+
/**
|
|
3065
3381
|
* Creates the schema converter bound to one OpenAPI document: `parseSchema` dispatches each
|
|
3066
3382
|
* schema through the ordered `schemaRules` table, with the parser options merged once.
|
|
3067
3383
|
*
|
|
@@ -3079,6 +3395,13 @@ function createSchemaParser(ctx) {
|
|
|
3079
3395
|
schema: flattenedSchema,
|
|
3080
3396
|
name
|
|
3081
3397
|
});
|
|
3398
|
+
if (hasUnevaluatedSiblings(schema)) {
|
|
3399
|
+
const { unevaluatedProperties: _properties, unevaluatedItems: _items, ...open } = schema;
|
|
3400
|
+
return parseSchema({
|
|
3401
|
+
schema: open,
|
|
3402
|
+
name
|
|
3403
|
+
});
|
|
3404
|
+
}
|
|
3082
3405
|
const nullable = isNullable(schema) || void 0;
|
|
3083
3406
|
const context = {
|
|
3084
3407
|
schema,
|
|
@@ -3092,8 +3415,62 @@ function createSchemaParser(ctx) {
|
|
|
3092
3415
|
refs,
|
|
3093
3416
|
renames
|
|
3094
3417
|
};
|
|
3095
|
-
|
|
3096
|
-
return createNode(context, { type: options.emptySchemaType });
|
|
3418
|
+
const rule = schemaRules.find((entry) => entry.match(context));
|
|
3419
|
+
return withConditionals(rule ? rule.convert(context) : createNode(context, { type: options.emptySchemaType }), schema);
|
|
3420
|
+
}
|
|
3421
|
+
function requireKeys(keys) {
|
|
3422
|
+
const unknown = ast.factory.createSchema({ type: ast.schemaTypes.unknown });
|
|
3423
|
+
return ast.factory.createSchema({
|
|
3424
|
+
type: ast.schemaTypes.object,
|
|
3425
|
+
primitive: "object",
|
|
3426
|
+
properties: keys.map((name) => ast.factory.createProperty({
|
|
3427
|
+
name,
|
|
3428
|
+
required: true,
|
|
3429
|
+
schema: unknown
|
|
3430
|
+
}))
|
|
3431
|
+
});
|
|
3432
|
+
}
|
|
3433
|
+
/**
|
|
3434
|
+
* Adds `if`/`then`/`else`, `dependentRequired` and `dependentSchemas` to the node as `conditionals`.
|
|
3435
|
+
*/
|
|
3436
|
+
function withConditionals(node, schema) {
|
|
3437
|
+
const conditionals = [schema, ...Array.isArray(schema.allOf) ? schema.allOf.filter(isAnnotationMember) : []].flatMap(toConditionals);
|
|
3438
|
+
return conditionals.length ? {
|
|
3439
|
+
...node,
|
|
3440
|
+
conditionals
|
|
3441
|
+
} : node;
|
|
3442
|
+
}
|
|
3443
|
+
function toConditionals(schema) {
|
|
3444
|
+
const branch = (value) => {
|
|
3445
|
+
if (!value || typeof value !== "object") return void 0;
|
|
3446
|
+
const { required, type, ...rest } = value;
|
|
3447
|
+
if (Array.isArray(required) && required.length && (type === void 0 || type === "object") && !Object.keys(rest).length) return requireKeys(required);
|
|
3448
|
+
return parseSchema({ schema: value });
|
|
3449
|
+
};
|
|
3450
|
+
const entries = (value) => value && typeof value === "object" ? Object.entries(value) : [];
|
|
3451
|
+
const conditionals = [];
|
|
3452
|
+
const condition = branch(schema.if);
|
|
3453
|
+
if (condition) {
|
|
3454
|
+
const thenNode = branch(schema.then);
|
|
3455
|
+
const elseNode = branch(schema.else);
|
|
3456
|
+
conditionals.push({
|
|
3457
|
+
if: condition,
|
|
3458
|
+
...thenNode && { then: thenNode },
|
|
3459
|
+
...elseNode && { else: elseNode }
|
|
3460
|
+
});
|
|
3461
|
+
}
|
|
3462
|
+
for (const [key, required] of entries(schema.dependentRequired)) if (Array.isArray(required) && required.length && required.every((name) => typeof name === "string")) conditionals.push({
|
|
3463
|
+
if: requireKeys([key]),
|
|
3464
|
+
then: requireKeys(required)
|
|
3465
|
+
});
|
|
3466
|
+
for (const [key, dependent] of entries(schema.dependentSchemas)) {
|
|
3467
|
+
const thenNode = branch(dependent);
|
|
3468
|
+
if (thenNode) conditionals.push({
|
|
3469
|
+
if: requireKeys([key]),
|
|
3470
|
+
then: thenNode
|
|
3471
|
+
});
|
|
3472
|
+
}
|
|
3473
|
+
return conditionals;
|
|
3097
3474
|
}
|
|
3098
3475
|
return parseSchema;
|
|
3099
3476
|
}
|
|
@@ -3433,6 +3810,7 @@ const adapterOas = defineExtension({
|
|
|
3433
3810
|
schemaNodes.push(promotedEnums ? refPromotedEnums(node, promotedEnums) : node);
|
|
3434
3811
|
}
|
|
3435
3812
|
const operations = promotedEnums ? operationNodes.map((node) => refPromotedEnums(node, promotedEnums)) : operationNodes;
|
|
3813
|
+
const authSchemes = toAuthSchemes(document.components?.securitySchemes, refs);
|
|
3436
3814
|
return ast.factory.createInput({
|
|
3437
3815
|
schemas: schemaNodes,
|
|
3438
3816
|
operations,
|
|
@@ -3440,23 +3818,25 @@ const adapterOas = defineExtension({
|
|
|
3440
3818
|
title: document.info?.title,
|
|
3441
3819
|
description: document.info?.description,
|
|
3442
3820
|
version: document.info?.version,
|
|
3821
|
+
summary: document.info?.summary,
|
|
3822
|
+
termsOfService: document.info?.termsOfService,
|
|
3823
|
+
contact: pickStrings(document.info?.contact, [
|
|
3824
|
+
"name",
|
|
3825
|
+
"url",
|
|
3826
|
+
"email"
|
|
3827
|
+
]),
|
|
3828
|
+
license: typeof document.info?.license?.name === "string" ? {
|
|
3829
|
+
...pickStrings(document.info.license, ["identifier", "url"]),
|
|
3830
|
+
name: document.info.license.name
|
|
3831
|
+
} : void 0,
|
|
3832
|
+
externalDocs: getExternalDocs(document.externalDocs),
|
|
3443
3833
|
baseURL: resolveBaseUrl({
|
|
3444
3834
|
document,
|
|
3445
3835
|
server
|
|
3446
3836
|
}),
|
|
3447
3837
|
servers: toInputServers(document.servers ?? []),
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
return scheme?.type ? [{
|
|
3451
|
-
name,
|
|
3452
|
-
type: scheme.type,
|
|
3453
|
-
description: scheme.description,
|
|
3454
|
-
scheme: scheme.scheme,
|
|
3455
|
-
bearerFormat: scheme.bearerFormat,
|
|
3456
|
-
in: scheme.in,
|
|
3457
|
-
parameterName: scheme.name
|
|
3458
|
-
}] : [];
|
|
3459
|
-
}),
|
|
3838
|
+
...document.tags?.length && { tags: toInputTags(document.tags) },
|
|
3839
|
+
...authSchemes.length && { auth: authSchemes },
|
|
3460
3840
|
extensions: pickExtensions(document)
|
|
3461
3841
|
}
|
|
3462
3842
|
});
|