@kubb/adapter-oas 5.14.3 → 5.14.5
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 +55 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +55 -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.5";
|
|
24
25
|
//#endregion
|
|
25
26
|
//#region src/constants.ts
|
|
26
27
|
/**
|
|
@@ -711,33 +712,55 @@ function inlinePathRefs(node, resolve, visiting = []) {
|
|
|
711
712
|
* all-internal document it is a no-op that still walks the whole tree to confirm that, which
|
|
712
713
|
* costs real time on a large spec.
|
|
713
714
|
*
|
|
715
|
+
* `document` stands in for the file at `pathOrUrl`, such as inline input. Every other file or URL
|
|
716
|
+
* read, including one that fails, lands in `sources`. A `$ref` that cannot be read reports
|
|
717
|
+
* `KUBB_REF_NOT_FOUND` at the key that holds it.
|
|
718
|
+
*
|
|
714
719
|
* @example Local file
|
|
715
720
|
* `const document = await bundleDocument('./openapi.yaml')`
|
|
716
721
|
*
|
|
717
722
|
* @example Remote URL
|
|
718
723
|
* `const document = await bundleDocument('https://example.com/openapi.yaml')`
|
|
719
724
|
*/
|
|
720
|
-
async function bundleDocument(pathOrUrl) {
|
|
725
|
+
async function bundleDocument(pathOrUrl, { document, sources = [] } = {}) {
|
|
721
726
|
const cache = /* @__PURE__ */ new Map();
|
|
727
|
+
const toKey = (sourcePath) => urlRegExp.test(sourcePath) ? new URL(sourcePath).href : sourcePath;
|
|
722
728
|
const resolver = (sourcePath) => {
|
|
723
|
-
|
|
729
|
+
if (document && sourcePath === pathOrUrl) return Promise.resolve(document);
|
|
730
|
+
const key = toKey(sourcePath);
|
|
724
731
|
const cached = cache.get(key);
|
|
725
732
|
if (cached) return cached;
|
|
733
|
+
sources.push(key);
|
|
726
734
|
const result = resolveSource(sourcePath);
|
|
727
735
|
cache.set(key, result);
|
|
728
736
|
return result;
|
|
729
737
|
};
|
|
730
738
|
const root = await resolver(pathOrUrl);
|
|
731
739
|
if (typeof root === "object" && root !== null && !hasExternalRef(root)) return root;
|
|
732
|
-
return await bundle(pathOrUrl, resolver)
|
|
740
|
+
return await bundle(pathOrUrl, resolver, { hooks: { onError: (message, { path, state }) => {
|
|
741
|
+
const pointer = toKey(state.baseFile) === toKey(pathOrUrl) ? `#/${path.map((token) => escapePointerToken(String(token))).join("/")}` : void 0;
|
|
742
|
+
const diagnostic = {
|
|
743
|
+
code: Diagnostics.code.refNotFound,
|
|
744
|
+
severity: "error",
|
|
745
|
+
message: `Could not bundle an external \`$ref\`. ${message}.`,
|
|
746
|
+
help: "Check that the file or URL the `$ref` points at exists and is readable, or fix the `$ref`.",
|
|
747
|
+
...pointer && { location: {
|
|
748
|
+
kind: "schema",
|
|
749
|
+
pointer
|
|
750
|
+
} }
|
|
751
|
+
};
|
|
752
|
+
if (!Diagnostics.report(diagnostic)) throw new Diagnostics.Error(diagnostic);
|
|
753
|
+
} } });
|
|
733
754
|
}
|
|
755
|
+
const inlineInputName = "<inline input>";
|
|
734
756
|
/**
|
|
735
757
|
* Creates a `Document` from an `AdapterSource`.
|
|
736
758
|
*
|
|
737
759
|
* - `{ type: 'path' }` bundles an absolute file path (core resolves `input`) or remote URL via
|
|
738
760
|
* `api-ref-bundler`, hoisting external file schemas into named `components.schemas` entries so
|
|
739
761
|
* generators can emit named types and imports.
|
|
740
|
-
* - `{ type: 'data' }` parses an inline string (YAML/JSON) or raw object
|
|
762
|
+
* - `{ type: 'data' }` parses an inline string (YAML/JSON) or raw object, then bundles its
|
|
763
|
+
* external `$ref`s from `root` when it has any. Each file or URL read lands in `sources`.
|
|
741
764
|
*
|
|
742
765
|
* Swagger 2.0 and OpenAPI 3.0 documents are up-converted to OpenAPI 3.1 via `@scalar/openapi-upgrader`.
|
|
743
766
|
*
|
|
@@ -747,14 +770,20 @@ async function bundleDocument(pathOrUrl) {
|
|
|
747
770
|
* const document = await parseFromConfig({ type: 'data', data: '{"openapi":"3.0.0",...}' })
|
|
748
771
|
* ```
|
|
749
772
|
*/
|
|
750
|
-
async function parseFromConfig(source) {
|
|
773
|
+
async function parseFromConfig(source, sources = []) {
|
|
751
774
|
const raw = await (async () => {
|
|
752
|
-
if (source.type === "data")
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
775
|
+
if (source.type === "data") {
|
|
776
|
+
const data = typeof source.data === "string" ? parseYaml(source.data, {
|
|
777
|
+
origin: "the inline `input` string",
|
|
778
|
+
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."
|
|
779
|
+
}) : structuredClone(source.data);
|
|
780
|
+
return source.root && hasExternalRef(data) ? bundleDocument(join(source.root, inlineInputName), {
|
|
781
|
+
document: data,
|
|
782
|
+
sources
|
|
783
|
+
}) : data;
|
|
784
|
+
}
|
|
756
785
|
await assertInputExists(source.path);
|
|
757
|
-
return bundleDocument(source.path);
|
|
786
|
+
return bundleDocument(source.path, { sources });
|
|
758
787
|
})();
|
|
759
788
|
if (raw && typeof raw === "object") {
|
|
760
789
|
const document = raw;
|
|
@@ -2890,6 +2919,7 @@ const adapterOas = defineExtension({
|
|
|
2890
2919
|
}),
|
|
2891
2920
|
build({ validate, contentType, server, discriminator, enums, ...parserOptions }) {
|
|
2892
2921
|
let parsedDocument = null;
|
|
2922
|
+
let sources = [];
|
|
2893
2923
|
const pendingValidations = [];
|
|
2894
2924
|
const inputCache = /* @__PURE__ */ new WeakMap();
|
|
2895
2925
|
/**
|
|
@@ -3023,6 +3053,9 @@ const adapterOas = defineExtension({
|
|
|
3023
3053
|
get document() {
|
|
3024
3054
|
return parsedDocument;
|
|
3025
3055
|
},
|
|
3056
|
+
get sources() {
|
|
3057
|
+
return sources;
|
|
3058
|
+
},
|
|
3026
3059
|
locate,
|
|
3027
3060
|
async validate(input, options) {
|
|
3028
3061
|
const document = await parseFromConfig({
|
|
@@ -3038,9 +3071,14 @@ const adapterOas = defineExtension({
|
|
|
3038
3071
|
async parse(source, { signal } = {}) {
|
|
3039
3072
|
signal?.throwIfAborted();
|
|
3040
3073
|
const cached = inputCache.get(source);
|
|
3041
|
-
if (cached)
|
|
3074
|
+
if (cached) {
|
|
3075
|
+
sources = cached.sources;
|
|
3076
|
+
return cached.promise;
|
|
3077
|
+
}
|
|
3078
|
+
const read = [];
|
|
3079
|
+
sources = read;
|
|
3042
3080
|
const promise = (async () => {
|
|
3043
|
-
const document = await parseFromConfig(source);
|
|
3081
|
+
const document = await parseFromConfig(source, read);
|
|
3044
3082
|
signal?.throwIfAborted();
|
|
3045
3083
|
assertDocument(document);
|
|
3046
3084
|
if (validate) pendingValidations.push(validateDocumentInWorker(document));
|
|
@@ -3060,7 +3098,10 @@ const adapterOas = defineExtension({
|
|
|
3060
3098
|
})
|
|
3061
3099
|
});
|
|
3062
3100
|
})();
|
|
3063
|
-
inputCache.set(source,
|
|
3101
|
+
inputCache.set(source, {
|
|
3102
|
+
promise,
|
|
3103
|
+
sources: read
|
|
3104
|
+
});
|
|
3064
3105
|
return promise.catch((error) => {
|
|
3065
3106
|
if (signal?.aborted) inputCache.delete(source);
|
|
3066
3107
|
throw error;
|