@kubb/adapter-oas 5.14.4 → 5.14.6
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 +79 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +79 -14
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { defineExtension } from "@kubb/core";
|
|
2
2
|
import { Diagnostics, ast, childName, enumPrimitive, enumPropName, extractRefName, macroDiscriminatorEnum, macroEnumName, macroSimplifyUnion, mergeAdjacentObjectsLazy } from "@kubb/kit";
|
|
3
|
+
import { join } from "node:path";
|
|
3
4
|
import { access, readFile } from "node:fs/promises";
|
|
4
5
|
import { upgrade } from "@scalar/openapi-upgrader";
|
|
5
6
|
import { bundle } from "api-ref-bundler";
|
|
@@ -20,7 +21,7 @@ var compatibility = {
|
|
|
20
21
|
};
|
|
21
22
|
//#endregion
|
|
22
23
|
//#region package.json
|
|
23
|
-
var version = "5.14.
|
|
24
|
+
var version = "5.14.6";
|
|
24
25
|
//#endregion
|
|
25
26
|
//#region src/constants.ts
|
|
26
27
|
/**
|
|
@@ -698,6 +699,30 @@ function inlinePathRefs(node, resolve, visiting = []) {
|
|
|
698
699
|
for (const [key, value] of Object.entries(node)) node[key] = inlinePathRefs(value, resolve, visiting);
|
|
699
700
|
return node;
|
|
700
701
|
}
|
|
702
|
+
const namedEntryKeys = /* @__PURE__ */ new Set([
|
|
703
|
+
"properties",
|
|
704
|
+
"patternProperties",
|
|
705
|
+
"headers",
|
|
706
|
+
"schemas",
|
|
707
|
+
"responses",
|
|
708
|
+
"parameters",
|
|
709
|
+
"requestBodies",
|
|
710
|
+
"examples",
|
|
711
|
+
"links",
|
|
712
|
+
"callbacks",
|
|
713
|
+
"securitySchemes",
|
|
714
|
+
"securityDefinitions",
|
|
715
|
+
"pathItems",
|
|
716
|
+
"definitions",
|
|
717
|
+
"$defs"
|
|
718
|
+
]);
|
|
719
|
+
/**
|
|
720
|
+
* True when `path` runs through an `x-` vendor extension. Kubb never reads an extension, so a `$ref`
|
|
721
|
+
* Kubb cannot read inside one cannot change the output.
|
|
722
|
+
*/
|
|
723
|
+
function isExtensionPath(path) {
|
|
724
|
+
return path.some((token, index) => String(token).startsWith("x-") && !namedEntryKeys.has(String(path[index - 1])));
|
|
725
|
+
}
|
|
701
726
|
/**
|
|
702
727
|
* Bundles a multi-file OpenAPI document into a single document via `api-ref-bundler`.
|
|
703
728
|
*
|
|
@@ -711,33 +736,55 @@ function inlinePathRefs(node, resolve, visiting = []) {
|
|
|
711
736
|
* all-internal document it is a no-op that still walks the whole tree to confirm that, which
|
|
712
737
|
* costs real time on a large spec.
|
|
713
738
|
*
|
|
739
|
+
* `document` stands in for the file at `pathOrUrl`, such as inline input. Every other file or URL
|
|
740
|
+
* read, including one that fails, lands in `sources`. A `$ref` that cannot be read reports
|
|
741
|
+
* `KUBB_REF_NOT_FOUND` at the key that holds it, as a warning when it sits inside an `x-` extension.
|
|
742
|
+
*
|
|
714
743
|
* @example Local file
|
|
715
744
|
* `const document = await bundleDocument('./openapi.yaml')`
|
|
716
745
|
*
|
|
717
746
|
* @example Remote URL
|
|
718
747
|
* `const document = await bundleDocument('https://example.com/openapi.yaml')`
|
|
719
748
|
*/
|
|
720
|
-
async function bundleDocument(pathOrUrl) {
|
|
749
|
+
async function bundleDocument(pathOrUrl, { document, sources = [] } = {}) {
|
|
721
750
|
const cache = /* @__PURE__ */ new Map();
|
|
751
|
+
const toKey = (sourcePath) => urlRegExp.test(sourcePath) ? new URL(sourcePath).href : sourcePath;
|
|
722
752
|
const resolver = (sourcePath) => {
|
|
723
|
-
|
|
753
|
+
if (document && sourcePath === pathOrUrl) return Promise.resolve(document);
|
|
754
|
+
const key = toKey(sourcePath);
|
|
724
755
|
const cached = cache.get(key);
|
|
725
756
|
if (cached) return cached;
|
|
757
|
+
sources.push(key);
|
|
726
758
|
const result = resolveSource(sourcePath);
|
|
727
759
|
cache.set(key, result);
|
|
728
760
|
return result;
|
|
729
761
|
};
|
|
730
762
|
const root = await resolver(pathOrUrl);
|
|
731
763
|
if (typeof root === "object" && root !== null && !hasExternalRef(root)) return root;
|
|
732
|
-
return await bundle(pathOrUrl, resolver)
|
|
764
|
+
return await bundle(pathOrUrl, resolver, { hooks: { onError: (message, { path, state }) => {
|
|
765
|
+
const pointer = toKey(state.baseFile) === toKey(pathOrUrl) ? `#/${path.map((token) => escapePointerToken(String(token))).join("/")}` : void 0;
|
|
766
|
+
const diagnostic = {
|
|
767
|
+
code: Diagnostics.code.refNotFound,
|
|
768
|
+
severity: isExtensionPath(path) ? "warning" : "error",
|
|
769
|
+
message: `Could not bundle an external \`$ref\`. ${message}.`,
|
|
770
|
+
help: "Check that the file or URL the `$ref` points at exists and is readable, or fix the `$ref`.",
|
|
771
|
+
...pointer && { location: {
|
|
772
|
+
kind: "schema",
|
|
773
|
+
pointer
|
|
774
|
+
} }
|
|
775
|
+
};
|
|
776
|
+
if (!Diagnostics.report(diagnostic) && diagnostic.severity === "error") throw new Diagnostics.Error(diagnostic);
|
|
777
|
+
} } });
|
|
733
778
|
}
|
|
779
|
+
const inlineInputName = "<inline input>";
|
|
734
780
|
/**
|
|
735
781
|
* Creates a `Document` from an `AdapterSource`.
|
|
736
782
|
*
|
|
737
783
|
* - `{ type: 'path' }` bundles an absolute file path (core resolves `input`) or remote URL via
|
|
738
784
|
* `api-ref-bundler`, hoisting external file schemas into named `components.schemas` entries so
|
|
739
785
|
* generators can emit named types and imports.
|
|
740
|
-
* - `{ type: 'data' }` parses an inline string (YAML/JSON) or raw object
|
|
786
|
+
* - `{ type: 'data' }` parses an inline string (YAML/JSON) or raw object, then bundles its
|
|
787
|
+
* external `$ref`s from `root` when it has any. Each file or URL read lands in `sources`.
|
|
741
788
|
*
|
|
742
789
|
* Swagger 2.0 and OpenAPI 3.0 documents are up-converted to OpenAPI 3.1 via `@scalar/openapi-upgrader`.
|
|
743
790
|
*
|
|
@@ -747,14 +794,20 @@ async function bundleDocument(pathOrUrl) {
|
|
|
747
794
|
* const document = await parseFromConfig({ type: 'data', data: '{"openapi":"3.0.0",...}' })
|
|
748
795
|
* ```
|
|
749
796
|
*/
|
|
750
|
-
async function parseFromConfig(source) {
|
|
797
|
+
async function parseFromConfig(source, sources = []) {
|
|
751
798
|
const raw = await (async () => {
|
|
752
|
-
if (source.type === "data")
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
799
|
+
if (source.type === "data") {
|
|
800
|
+
const data = typeof source.data === "string" ? parseYaml(source.data, {
|
|
801
|
+
origin: "the inline `input` string",
|
|
802
|
+
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."
|
|
803
|
+
}) : structuredClone(source.data);
|
|
804
|
+
return source.root && hasExternalRef(data) ? bundleDocument(join(source.root, inlineInputName), {
|
|
805
|
+
document: data,
|
|
806
|
+
sources
|
|
807
|
+
}) : data;
|
|
808
|
+
}
|
|
756
809
|
await assertInputExists(source.path);
|
|
757
|
-
return bundleDocument(source.path);
|
|
810
|
+
return bundleDocument(source.path, { sources });
|
|
758
811
|
})();
|
|
759
812
|
if (raw && typeof raw === "object") {
|
|
760
813
|
const document = raw;
|
|
@@ -2890,6 +2943,7 @@ const adapterOas = defineExtension({
|
|
|
2890
2943
|
}),
|
|
2891
2944
|
build({ validate, contentType, server, discriminator, enums, ...parserOptions }) {
|
|
2892
2945
|
let parsedDocument = null;
|
|
2946
|
+
let sources = [];
|
|
2893
2947
|
const pendingValidations = [];
|
|
2894
2948
|
const inputCache = /* @__PURE__ */ new WeakMap();
|
|
2895
2949
|
/**
|
|
@@ -3023,6 +3077,9 @@ const adapterOas = defineExtension({
|
|
|
3023
3077
|
get document() {
|
|
3024
3078
|
return parsedDocument;
|
|
3025
3079
|
},
|
|
3080
|
+
get sources() {
|
|
3081
|
+
return sources;
|
|
3082
|
+
},
|
|
3026
3083
|
locate,
|
|
3027
3084
|
async validate(input, options) {
|
|
3028
3085
|
const document = await parseFromConfig({
|
|
@@ -3038,9 +3095,14 @@ const adapterOas = defineExtension({
|
|
|
3038
3095
|
async parse(source, { signal } = {}) {
|
|
3039
3096
|
signal?.throwIfAborted();
|
|
3040
3097
|
const cached = inputCache.get(source);
|
|
3041
|
-
if (cached)
|
|
3098
|
+
if (cached) {
|
|
3099
|
+
sources = cached.sources;
|
|
3100
|
+
return cached.promise;
|
|
3101
|
+
}
|
|
3102
|
+
const read = [];
|
|
3103
|
+
sources = read;
|
|
3042
3104
|
const promise = (async () => {
|
|
3043
|
-
const document = await parseFromConfig(source);
|
|
3105
|
+
const document = await parseFromConfig(source, read);
|
|
3044
3106
|
signal?.throwIfAborted();
|
|
3045
3107
|
assertDocument(document);
|
|
3046
3108
|
if (validate) pendingValidations.push(validateDocumentInWorker(document));
|
|
@@ -3060,7 +3122,10 @@ const adapterOas = defineExtension({
|
|
|
3060
3122
|
})
|
|
3061
3123
|
});
|
|
3062
3124
|
})();
|
|
3063
|
-
inputCache.set(source,
|
|
3125
|
+
inputCache.set(source, {
|
|
3126
|
+
promise,
|
|
3127
|
+
sources: read
|
|
3128
|
+
});
|
|
3064
3129
|
return promise.catch((error) => {
|
|
3065
3130
|
if (signal?.aborted) inputCache.delete(source);
|
|
3066
3131
|
throw error;
|