@scalar/openapi-parser 0.4.0 → 0.5.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/CHANGELOG.md +12 -0
- package/dist/configuration.d.ts +3907 -0
- package/dist/index.d.ts +29 -5877
- package/dist/lib/Validator/Validator.d.ts +33 -0
- package/dist/pipeline.d.ts +445 -0
- package/dist/schemas/v2.0/schema.json.js +1623 -0
- package/dist/schemas/v3.0/schema.json.js +1673 -0
- package/dist/schemas/v3.1/schema.json.js +1452 -0
- package/dist/src/configuration.js +22 -0
- package/dist/src/index.js +27 -0
- package/dist/src/lib/Validator/Validator.js +94 -0
- package/dist/src/pipeline.js +131 -0
- package/dist/src/polyfills/path.js +83 -0
- package/dist/src/utils/betterAjvErrors/helpers.js +89 -0
- package/dist/src/utils/betterAjvErrors/index.js +15 -0
- package/dist/src/utils/betterAjvErrors/utils.js +17 -0
- package/dist/src/utils/betterAjvErrors/validation-errors/additional-prop.js +18 -0
- package/dist/src/utils/betterAjvErrors/validation-errors/base.js +23 -0
- package/dist/src/utils/betterAjvErrors/validation-errors/default.js +18 -0
- package/dist/src/utils/betterAjvErrors/validation-errors/enum.js +41 -0
- package/dist/src/utils/betterAjvErrors/validation-errors/pattern.js +18 -0
- package/dist/src/utils/betterAjvErrors/validation-errors/required.js +17 -0
- package/dist/src/utils/betterAjvErrors/validation-errors/unevaluated-prop.js +18 -0
- package/dist/src/utils/dereference.js +18 -0
- package/dist/src/utils/details.js +22 -0
- package/dist/src/utils/escapeJsonPointer.js +5 -0
- package/dist/src/utils/filter.js +12 -0
- package/dist/src/utils/getEntrypoint.js +5 -0
- package/dist/src/utils/getListOfReferences.js +17 -0
- package/dist/src/utils/getSegmentsFromPath.js +10 -0
- package/dist/src/utils/isFilesystem.js +5 -0
- package/dist/src/utils/isJson.js +10 -0
- package/dist/src/utils/isObject.js +3 -0
- package/dist/src/utils/isYaml.js +16 -0
- package/dist/src/utils/load/load.js +46 -0
- package/dist/src/utils/load/plugins/fetchUrlsPlugin.js +38 -0
- package/dist/src/utils/load/plugins/readFilesPlugin.js +50 -0
- package/dist/src/utils/makeFilesystem.js +22 -0
- package/dist/src/utils/normalize.js +18 -0
- package/dist/src/utils/resolveReferences.js +106 -0
- package/dist/src/utils/toJson.js +3 -0
- package/dist/src/utils/toYaml.js +5 -0
- package/dist/src/utils/transformErrors.js +19 -0
- package/dist/src/utils/traverse.js +20 -0
- package/dist/src/utils/unescapeJsonPointer.js +5 -0
- package/dist/src/utils/upgrade.js +17 -0
- package/dist/src/utils/upgradeFromThreeToThreeOne.js +71 -0
- package/dist/src/utils/upgradeFromTwoToThree.js +5 -0
- package/dist/src/utils/validate.js +15 -0
- package/dist/types/index.d.ts +42 -0
- package/dist/types/openapi.d.ts +747 -0
- package/dist/utils/dereference.d.ts +8 -0
- package/dist/utils/details.d.ts +12 -0
- package/dist/utils/escapeJsonPointer.d.ts +8 -0
- package/dist/utils/filter.d.ts +8 -0
- package/dist/utils/getEntrypoint.d.ts +8 -0
- package/dist/utils/getListOfReferences.d.ts +10 -0
- package/dist/utils/getSegmentsFromPath.d.ts +6 -0
- package/dist/utils/isFilesystem.d.ts +6 -0
- package/dist/utils/isJson.d.ts +3 -0
- package/dist/utils/isObject.d.ts +6 -0
- package/dist/utils/isYaml.d.ts +3 -0
- package/dist/utils/load/load.d.ts +16 -0
- package/dist/utils/load/plugins/fetchUrlsPlugin.d.ts +10 -0
- package/dist/utils/load/plugins/readFilesPlugin.d.ts +5 -0
- package/dist/utils/normalize.d.ts +9 -0
- package/dist/utils/resolveReferences.d.ts +14 -0
- package/dist/utils/toJson.d.ts +5 -0
- package/dist/utils/toYaml.d.ts +5 -0
- package/dist/utils/transformErrors.d.ts +8 -0
- package/dist/utils/traverse.d.ts +8 -0
- package/dist/utils/unescapeJsonPointer.d.ts +9 -0
- package/dist/utils/upgrade.d.ts +8 -0
- package/dist/utils/upgradeFromThreeToThreeOne.d.ts +10 -0
- package/dist/utils/upgradeFromTwoToThree.d.ts +10 -0
- package/dist/utils/validate.d.ts +8 -0
- package/dist/webpack-stats.json +1 -1
- package/package.json +12 -8
- package/dist/index.js +0 -16818
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { OpenApiVersions } from '../configuration.js';
|
|
2
|
+
|
|
3
|
+
function details(specification) {
|
|
4
|
+
for (const version of new Set(OpenApiVersions)) {
|
|
5
|
+
const specificationType = version === "2.0" ? "swagger" : "openapi";
|
|
6
|
+
const value = specification[specificationType];
|
|
7
|
+
if (typeof value === "string" && value.startsWith(version)) {
|
|
8
|
+
return {
|
|
9
|
+
version,
|
|
10
|
+
specificationType,
|
|
11
|
+
specificationVersion: value
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
version: void 0,
|
|
17
|
+
specificationType: void 0,
|
|
18
|
+
specificationVersion: void 0
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { details };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getEntrypoint } from './getEntrypoint.js';
|
|
2
|
+
import { makeFilesystem } from './makeFilesystem.js';
|
|
3
|
+
import { traverse } from './traverse.js';
|
|
4
|
+
|
|
5
|
+
function filter(specification, callback) {
|
|
6
|
+
const filesystem = makeFilesystem(specification);
|
|
7
|
+
return traverse(getEntrypoint(filesystem).specification, (schema) => {
|
|
8
|
+
return callback(schema) ? schema : void 0;
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { filter };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { traverse } from './traverse.js';
|
|
2
|
+
|
|
3
|
+
function getListOfReferences(specification) {
|
|
4
|
+
const references = [];
|
|
5
|
+
if (!specification || typeof specification !== "object") {
|
|
6
|
+
return references;
|
|
7
|
+
}
|
|
8
|
+
traverse(specification, (value) => {
|
|
9
|
+
if (value.$ref && typeof value.$ref === "string" && !value.$ref.startsWith("#")) {
|
|
10
|
+
references.push(value.$ref.split("#")[0]);
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
13
|
+
});
|
|
14
|
+
return [...new Set(references)];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { getListOfReferences };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { parse } from 'yaml';
|
|
2
|
+
|
|
3
|
+
function isYaml(value) {
|
|
4
|
+
if (!value.includes("\n")) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
try {
|
|
8
|
+
parse(value);
|
|
9
|
+
return true;
|
|
10
|
+
} catch (error) {
|
|
11
|
+
console.log("ADSAS", error);
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { isYaml };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { getListOfReferences } from '../getListOfReferences.js';
|
|
2
|
+
import { makeFilesystem } from '../makeFilesystem.js';
|
|
3
|
+
import { normalize } from '../normalize.js';
|
|
4
|
+
|
|
5
|
+
async function load(value, options) {
|
|
6
|
+
if (options?.filesystem && options?.filesystem.find((entry) => entry.filename === value)) {
|
|
7
|
+
return options.filesystem;
|
|
8
|
+
}
|
|
9
|
+
const plugin = options?.plugins?.find((plugin2) => plugin2.check(value));
|
|
10
|
+
const content = normalize(plugin ? await plugin.get(value) : value);
|
|
11
|
+
if (content === void 0) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
let filesystem = makeFilesystem(content, {
|
|
15
|
+
filename: options?.filename ?? null
|
|
16
|
+
});
|
|
17
|
+
const listOfReferences = getListOfReferences(content);
|
|
18
|
+
if (listOfReferences.length === 0) {
|
|
19
|
+
return filesystem;
|
|
20
|
+
}
|
|
21
|
+
for (const reference of listOfReferences) {
|
|
22
|
+
const plugin2 = options?.plugins?.find((plugin3) => plugin3.check(reference));
|
|
23
|
+
const target = plugin2.check(reference) && plugin2.resolvePath ? plugin2.resolvePath(value, reference) : reference;
|
|
24
|
+
if (filesystem.find((entry) => entry.filename === reference)) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const referencedFiles = await load(target, {
|
|
28
|
+
...options,
|
|
29
|
+
// Make the filename the exact same value as the $ref
|
|
30
|
+
// TODO: This leads to problems, if there are multiple references with the same file name but in different folders
|
|
31
|
+
filename: reference
|
|
32
|
+
});
|
|
33
|
+
filesystem = [
|
|
34
|
+
...filesystem,
|
|
35
|
+
...referencedFiles.map((file) => {
|
|
36
|
+
return {
|
|
37
|
+
...file,
|
|
38
|
+
isEntrypoint: false
|
|
39
|
+
};
|
|
40
|
+
})
|
|
41
|
+
];
|
|
42
|
+
}
|
|
43
|
+
return filesystem;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { load };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const fetchUrlsPluginDefaultConfiguration = {
|
|
2
|
+
limit: 20
|
|
3
|
+
};
|
|
4
|
+
const fetchUrlsPlugin = (customConfiguration) => {
|
|
5
|
+
let numberOfRequests = 0;
|
|
6
|
+
const configuration = {
|
|
7
|
+
...fetchUrlsPluginDefaultConfiguration,
|
|
8
|
+
...customConfiguration
|
|
9
|
+
};
|
|
10
|
+
return {
|
|
11
|
+
check(value) {
|
|
12
|
+
if (typeof value !== "string") {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
if (!value.startsWith("http://") && !value.startsWith("https://")) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
return true;
|
|
19
|
+
},
|
|
20
|
+
async get(value) {
|
|
21
|
+
if (configuration?.limit !== false && numberOfRequests >= configuration?.limit) {
|
|
22
|
+
console.warn(
|
|
23
|
+
`[fetchUrlsPlugin] Maximum number of requests reeached (${configuration?.limit}), skipping request`
|
|
24
|
+
);
|
|
25
|
+
return void 0;
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
numberOfRequests++;
|
|
29
|
+
const response = await fetch(value);
|
|
30
|
+
return await response.text();
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error("[fetchUrlsPlugin]", error.message, `(${value})`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export { fetchUrlsPlugin, fetchUrlsPluginDefaultConfiguration };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { ERRORS } from '../../../configuration.js';
|
|
3
|
+
import { dirname, join } from '../../../polyfills/path.js';
|
|
4
|
+
import { isJson } from '../../isJson.js';
|
|
5
|
+
import { isYaml } from '../../isYaml.js';
|
|
6
|
+
|
|
7
|
+
const readFilesPlugin = () => {
|
|
8
|
+
return {
|
|
9
|
+
check(value) {
|
|
10
|
+
if (typeof value !== "string") {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
if (value.startsWith("http://") || value.startsWith("https://")) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
if (value.includes("\n")) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
if (isJson(value)) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
if (isYaml(value)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
},
|
|
27
|
+
async get(value) {
|
|
28
|
+
if (!fs.existsSync(value)) {
|
|
29
|
+
throw new Error(ERRORS.FILE_DOES_NOT_EXIST.replace("%s", value));
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
return fs.readFileSync(value, "utf-8");
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error("[readFilesPlugin]", error);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
resolvePath(value, reference) {
|
|
38
|
+
const dir = dirname(value);
|
|
39
|
+
return join(dir, reference);
|
|
40
|
+
},
|
|
41
|
+
getDir(value) {
|
|
42
|
+
return dirname(value);
|
|
43
|
+
},
|
|
44
|
+
getFilename(value) {
|
|
45
|
+
return value.split("/").pop();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export { readFilesPlugin };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { getListOfReferences } from './getListOfReferences.js';
|
|
2
|
+
import { isFilesystem } from './isFilesystem.js';
|
|
3
|
+
import { normalize } from './normalize.js';
|
|
4
|
+
|
|
5
|
+
function makeFilesystem(value, overwrites = {}) {
|
|
6
|
+
if (isFilesystem(value)) {
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
const specification = normalize(value);
|
|
10
|
+
return [
|
|
11
|
+
{
|
|
12
|
+
isEntrypoint: true,
|
|
13
|
+
specification,
|
|
14
|
+
filename: null,
|
|
15
|
+
dir: "./",
|
|
16
|
+
references: getListOfReferences(specification),
|
|
17
|
+
...overwrites
|
|
18
|
+
}
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { makeFilesystem };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { parse } from 'yaml';
|
|
2
|
+
import { isFilesystem } from './isFilesystem.js';
|
|
3
|
+
|
|
4
|
+
function normalize(specification) {
|
|
5
|
+
if (isFilesystem(specification)) {
|
|
6
|
+
return specification;
|
|
7
|
+
}
|
|
8
|
+
if (typeof specification === "string") {
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(specification);
|
|
11
|
+
} catch (error) {
|
|
12
|
+
return parse(specification);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return specification;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { normalize };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { ERRORS } from '../configuration.js';
|
|
2
|
+
import { getEntrypoint } from './getEntrypoint.js';
|
|
3
|
+
import { getSegmentsFromPath } from './getSegmentsFromPath.js';
|
|
4
|
+
import { makeFilesystem } from './makeFilesystem.js';
|
|
5
|
+
|
|
6
|
+
function resolveReferences(input, file, errors) {
|
|
7
|
+
if (errors === void 0) {
|
|
8
|
+
errors = [];
|
|
9
|
+
}
|
|
10
|
+
const clonedInput = structuredClone(input);
|
|
11
|
+
const filesystem = makeFilesystem(clonedInput);
|
|
12
|
+
const entrypoint = getEntrypoint(filesystem);
|
|
13
|
+
resolve(
|
|
14
|
+
file?.specification ?? entrypoint.specification,
|
|
15
|
+
filesystem,
|
|
16
|
+
file ?? entrypoint
|
|
17
|
+
);
|
|
18
|
+
resolve(
|
|
19
|
+
file?.specification ?? entrypoint.specification,
|
|
20
|
+
filesystem,
|
|
21
|
+
file ?? entrypoint
|
|
22
|
+
);
|
|
23
|
+
errors = errors.filter(
|
|
24
|
+
(error, index, self) => index === self.findIndex(
|
|
25
|
+
(t) => t.message === error.message && t.code === error.code
|
|
26
|
+
)
|
|
27
|
+
);
|
|
28
|
+
return {
|
|
29
|
+
valid: errors.length === 0,
|
|
30
|
+
errors,
|
|
31
|
+
schema: (file ?? getEntrypoint(filesystem)).specification
|
|
32
|
+
};
|
|
33
|
+
function resolve(schema, filesystem2, file2) {
|
|
34
|
+
let result;
|
|
35
|
+
Object.entries(schema ?? {}).forEach(([_, value]) => {
|
|
36
|
+
if (schema.$ref !== void 0) {
|
|
37
|
+
const target = resolveUri(schema.$ref, file2, filesystem2, errors);
|
|
38
|
+
if (target === void 0) {
|
|
39
|
+
return void 0;
|
|
40
|
+
}
|
|
41
|
+
delete schema.$ref;
|
|
42
|
+
if (typeof target === "object") {
|
|
43
|
+
Object.keys(target).forEach((key) => {
|
|
44
|
+
if (schema[key] === void 0) {
|
|
45
|
+
schema[key] = target[key];
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (typeof value === "object" && !isCircular(value)) {
|
|
51
|
+
result = resolve(value, filesystem2, file2);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
errors: result?.errors ?? []
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function isCircular(schema) {
|
|
60
|
+
try {
|
|
61
|
+
JSON.stringify(schema);
|
|
62
|
+
return false;
|
|
63
|
+
} catch (error) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function resolveUri(uri, file, filesystem, errors) {
|
|
68
|
+
if (typeof uri !== "string") {
|
|
69
|
+
errors.push({
|
|
70
|
+
code: "INVALID_REFERENCE",
|
|
71
|
+
message: ERRORS.INVALID_REFERENCE.replace("%s", uri)
|
|
72
|
+
});
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const [prefix, path] = uri.split("#", 2);
|
|
76
|
+
if (prefix) {
|
|
77
|
+
const externalReference = filesystem.find((entry) => {
|
|
78
|
+
return entry.filename === prefix;
|
|
79
|
+
});
|
|
80
|
+
if (!externalReference) {
|
|
81
|
+
errors.push({
|
|
82
|
+
code: "EXTERNAL_REFERENCE_NOT_FOUND",
|
|
83
|
+
message: ERRORS.EXTERNAL_REFERENCE_NOT_FOUND.replace("%s", prefix)
|
|
84
|
+
});
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const result = resolveReferences(filesystem, externalReference, errors);
|
|
88
|
+
if (path === void 0) {
|
|
89
|
+
return result.schema;
|
|
90
|
+
}
|
|
91
|
+
return resolveUri(`#${path}`, externalReference, filesystem, errors);
|
|
92
|
+
}
|
|
93
|
+
const segments = getSegmentsFromPath(path);
|
|
94
|
+
try {
|
|
95
|
+
return segments.reduce((acc, key) => {
|
|
96
|
+
return acc[key];
|
|
97
|
+
}, file.specification);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
errors.push({
|
|
100
|
+
code: "INVALID_REFERENCE",
|
|
101
|
+
message: ERRORS.INVALID_REFERENCE.replace("%s", uri)
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export { resolveReferences };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { betterAjvErrors } from './betterAjvErrors/index.js';
|
|
2
|
+
|
|
3
|
+
function transformErrors(specification, errors) {
|
|
4
|
+
if (typeof errors === "string") {
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
message: errors
|
|
8
|
+
}
|
|
9
|
+
];
|
|
10
|
+
}
|
|
11
|
+
return betterAjvErrors(specification, null, errors, {
|
|
12
|
+
indent: 2
|
|
13
|
+
}).map((error) => {
|
|
14
|
+
error.message = error.message.trim();
|
|
15
|
+
return error;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { transformErrors };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
function traverse(specification, transform) {
|
|
2
|
+
const result = {};
|
|
3
|
+
for (const [key, value] of Object.entries(specification)) {
|
|
4
|
+
if (Array.isArray(value)) {
|
|
5
|
+
result[key] = value.map((item) => {
|
|
6
|
+
if (typeof item === "object" && item !== null) {
|
|
7
|
+
return traverse(item, transform);
|
|
8
|
+
}
|
|
9
|
+
return item;
|
|
10
|
+
});
|
|
11
|
+
} else if (typeof value === "object" && value !== null) {
|
|
12
|
+
result[key] = traverse(value, transform);
|
|
13
|
+
} else {
|
|
14
|
+
result[key] = value;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return transform(result);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { traverse };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { getEntrypoint } from './getEntrypoint.js';
|
|
2
|
+
import { isFilesystem } from './isFilesystem.js';
|
|
3
|
+
import { makeFilesystem } from './makeFilesystem.js';
|
|
4
|
+
import { upgradeFromThreeToThreeOne } from './upgradeFromThreeToThreeOne.js';
|
|
5
|
+
import { upgradeFromTwoToThree } from './upgradeFromTwoToThree.js';
|
|
6
|
+
|
|
7
|
+
function upgrade(specification, _options) {
|
|
8
|
+
const upgraders = [upgradeFromTwoToThree, upgradeFromThreeToThreeOne];
|
|
9
|
+
const wasFilesystem = isFilesystem(specification);
|
|
10
|
+
const result = upgraders.reduce(
|
|
11
|
+
(specification2, upgrader) => upgrader(specification2),
|
|
12
|
+
getEntrypoint(makeFilesystem(specification)).specification
|
|
13
|
+
);
|
|
14
|
+
return wasFilesystem ? makeFilesystem(result) : result;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { upgrade };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { traverse } from './traverse.js';
|
|
2
|
+
|
|
3
|
+
function upgradeFromThreeToThreeOne(specification) {
|
|
4
|
+
if (specification.openapi?.startsWith("3.0")) {
|
|
5
|
+
specification.openapi = "3.1.0";
|
|
6
|
+
} else {
|
|
7
|
+
return specification;
|
|
8
|
+
}
|
|
9
|
+
specification = traverse(specification, (schema) => {
|
|
10
|
+
if (schema.type !== "undefined" && schema.nullable === true) {
|
|
11
|
+
schema.type = ["null", schema.type];
|
|
12
|
+
delete schema.nullable;
|
|
13
|
+
}
|
|
14
|
+
return schema;
|
|
15
|
+
});
|
|
16
|
+
specification = traverse(specification, (schema) => {
|
|
17
|
+
if (schema.exclusiveMinimum === true) {
|
|
18
|
+
schema.exclusiveMinimum = schema.minimum;
|
|
19
|
+
delete schema.minimum;
|
|
20
|
+
} else if (schema.exclusiveMinimum === false) {
|
|
21
|
+
delete schema.exclusiveMinimum;
|
|
22
|
+
}
|
|
23
|
+
if (schema.exclusiveMaximum === true) {
|
|
24
|
+
schema.exclusiveMaximum = schema.maximum;
|
|
25
|
+
delete schema.maximum;
|
|
26
|
+
} else if (schema.exclusiveMaximum === false) {
|
|
27
|
+
delete schema.exclusiveMaximum;
|
|
28
|
+
}
|
|
29
|
+
return schema;
|
|
30
|
+
});
|
|
31
|
+
specification = traverse(specification, (schema) => {
|
|
32
|
+
if (schema.example !== void 0) {
|
|
33
|
+
schema.examples = {
|
|
34
|
+
default: schema.example
|
|
35
|
+
};
|
|
36
|
+
delete schema.example;
|
|
37
|
+
}
|
|
38
|
+
return schema;
|
|
39
|
+
});
|
|
40
|
+
specification = traverse(specification, (schema) => {
|
|
41
|
+
if (schema.type === "object" && schema.properties !== void 0) {
|
|
42
|
+
for (const [_, value] of Object.entries(schema.properties)) {
|
|
43
|
+
if (value !== void 0 && // @ts-ignore
|
|
44
|
+
value.type === "string" && // @ts-ignore
|
|
45
|
+
value.format === "binary") {
|
|
46
|
+
value.contentEncoding = "application/octet-stream";
|
|
47
|
+
delete value.format;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return schema;
|
|
52
|
+
});
|
|
53
|
+
specification = traverse(specification, (schema) => {
|
|
54
|
+
if (schema.type === "string" && schema.format === "binary") {
|
|
55
|
+
return void 0;
|
|
56
|
+
}
|
|
57
|
+
return schema;
|
|
58
|
+
});
|
|
59
|
+
specification = traverse(specification, (schema) => {
|
|
60
|
+
if (schema.type === "string" && schema.format === "base64") {
|
|
61
|
+
return {
|
|
62
|
+
type: "string",
|
|
63
|
+
contentEncoding: "base64"
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return schema;
|
|
67
|
+
});
|
|
68
|
+
return specification;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export { upgradeFromThreeToThreeOne };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { makeFilesystem } from './makeFilesystem.js';
|
|
2
|
+
import { Validator } from '../lib/Validator/Validator.js';
|
|
3
|
+
|
|
4
|
+
async function validate(value) {
|
|
5
|
+
const filesystem = makeFilesystem(value);
|
|
6
|
+
const validator = new Validator();
|
|
7
|
+
const result = await validator.validate(filesystem);
|
|
8
|
+
return {
|
|
9
|
+
...result,
|
|
10
|
+
specification: validator.specification,
|
|
11
|
+
version: validator.version
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { validate };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ERRORS } from '../configuration.js';
|
|
2
|
+
import { OpenAPI } from './openapi.js';
|
|
3
|
+
export { OpenAPIV2, OpenAPIV3, OpenAPIV3_1 } from './openapi.js';
|
|
4
|
+
|
|
5
|
+
type AnyObject = Record<string, any>;
|
|
6
|
+
type ValidateResult = {
|
|
7
|
+
valid: boolean;
|
|
8
|
+
specification?: OpenAPI.Document;
|
|
9
|
+
version?: string;
|
|
10
|
+
errors?: ErrorObject[];
|
|
11
|
+
schema?: OpenAPI.Document;
|
|
12
|
+
};
|
|
13
|
+
type ErrorObject = {
|
|
14
|
+
message: string;
|
|
15
|
+
code?: keyof typeof ERRORS | string;
|
|
16
|
+
};
|
|
17
|
+
type ResolveResult = {
|
|
18
|
+
version: string | undefined;
|
|
19
|
+
specification?: OpenAPI.Document;
|
|
20
|
+
schema?: OpenAPI.Document;
|
|
21
|
+
errors?: ErrorObject[];
|
|
22
|
+
};
|
|
23
|
+
type AjvOptions = {
|
|
24
|
+
strict?: boolean | 'log';
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Not literally a filesystem, but a list of files with their content.
|
|
28
|
+
* This is an abstraction layer to handle multiple files in the browser (without access to the hard disk).
|
|
29
|
+
*/
|
|
30
|
+
type Filesystem = FilesystemEntry[];
|
|
31
|
+
/**
|
|
32
|
+
* Holds all information about a single file (doesn’t have to be a literal file, see Filesystem).
|
|
33
|
+
*/
|
|
34
|
+
type FilesystemEntry = {
|
|
35
|
+
dir: string;
|
|
36
|
+
isEntrypoint: boolean;
|
|
37
|
+
references: string[];
|
|
38
|
+
filename: string;
|
|
39
|
+
specification: AnyObject;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { type AjvOptions, type AnyObject, type ErrorObject, type Filesystem, type FilesystemEntry, OpenAPI, type ResolveResult, type ValidateResult };
|