@scalar/openapi-parser 0.4.1 → 0.6.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 +17 -0
- package/README.md +6 -6
- package/dist/configuration.d.ts +3907 -0
- package/dist/index.d.ts +29 -5889
- package/dist/lib/Validator/Validator.d.ts +33 -0
- package/dist/pipeline.d.ts +388 -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 +121 -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 +17 -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 +17 -0
- package/dist/src/utils/load/load.js +59 -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 +20 -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 +19 -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/src/utils/workThroughQueue.js +24 -0
- package/dist/types/index.d.ts +57 -0
- package/dist/types/openapi-types.d.ts +747 -0
- package/dist/utils/dereference.d.ts +8 -0
- package/dist/utils/details.d.ts +8 -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 +17 -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 +14 -9
- package/dist/index.js +0 -5521
|
@@ -0,0 +1,17 @@
|
|
|
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 {
|
|
8
|
+
specification: traverse(
|
|
9
|
+
getEntrypoint(filesystem).specification,
|
|
10
|
+
(schema) => {
|
|
11
|
+
return callback(schema) ? schema : void 0;
|
|
12
|
+
}
|
|
13
|
+
)
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
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,17 @@
|
|
|
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
|
+
maxAliasCount: 1e4
|
|
10
|
+
});
|
|
11
|
+
return true;
|
|
12
|
+
} catch (error) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { isYaml };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { getEntrypoint } from '../getEntrypoint.js';
|
|
2
|
+
import { getListOfReferences } from '../getListOfReferences.js';
|
|
3
|
+
import { makeFilesystem } from '../makeFilesystem.js';
|
|
4
|
+
import { normalize } from '../normalize.js';
|
|
5
|
+
|
|
6
|
+
async function load(value, options) {
|
|
7
|
+
if (options?.filesystem && options?.filesystem.find((entry) => entry.filename === value)) {
|
|
8
|
+
return {
|
|
9
|
+
filesystem: options.filesystem
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
const plugin = options?.plugins?.find((plugin2) => plugin2.check(value));
|
|
13
|
+
const content = normalize(plugin ? await plugin.get(value) : value);
|
|
14
|
+
if (content === void 0) {
|
|
15
|
+
return {
|
|
16
|
+
filesystem: []
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
let filesystem = makeFilesystem(content, {
|
|
20
|
+
filename: options?.filename ?? null
|
|
21
|
+
});
|
|
22
|
+
const newEntry = options?.filename ? filesystem.find((entry) => entry.filename === options?.filename) : getEntrypoint(filesystem);
|
|
23
|
+
const listOfReferences = newEntry.references ?? getListOfReferences(content);
|
|
24
|
+
if (listOfReferences.length === 0) {
|
|
25
|
+
return {
|
|
26
|
+
filesystem
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
for (const reference of listOfReferences) {
|
|
30
|
+
const plugin2 = options?.plugins?.find((plugin3) => plugin3.check(reference));
|
|
31
|
+
if (!plugin2) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const target = plugin2.check(reference) && plugin2.resolvePath ? plugin2.resolvePath(value, reference) : reference;
|
|
35
|
+
if (filesystem.find((entry) => entry.filename === reference)) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const { filesystem: referencedFiles } = await load(target, {
|
|
39
|
+
...options,
|
|
40
|
+
// Make the filename the exact same value as the $ref
|
|
41
|
+
// TODO: This leads to problems, if there are multiple references with the same file name but in different folders
|
|
42
|
+
filename: reference
|
|
43
|
+
});
|
|
44
|
+
filesystem = [
|
|
45
|
+
...filesystem,
|
|
46
|
+
...referencedFiles.map((file) => {
|
|
47
|
+
return {
|
|
48
|
+
...file,
|
|
49
|
+
isEntrypoint: false
|
|
50
|
+
};
|
|
51
|
+
})
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
filesystem
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
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 (configuration?.fetch ? configuration.fetch(value) : 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,20 @@
|
|
|
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
|
+
maxAliasCount: 1e4
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return specification;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
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,19 @@
|
|
|
1
|
+
import { getEntrypoint } from './getEntrypoint.js';
|
|
2
|
+
import { makeFilesystem } from './makeFilesystem.js';
|
|
3
|
+
import { upgradeFromThreeToThreeOne } from './upgradeFromThreeToThreeOne.js';
|
|
4
|
+
import { upgradeFromTwoToThree } from './upgradeFromTwoToThree.js';
|
|
5
|
+
|
|
6
|
+
function upgrade(specification, _options) {
|
|
7
|
+
const upgraders = [upgradeFromTwoToThree, upgradeFromThreeToThreeOne];
|
|
8
|
+
const result = upgraders.reduce(
|
|
9
|
+
(specification2, upgrader) => upgrader(specification2),
|
|
10
|
+
getEntrypoint(makeFilesystem(specification)).specification
|
|
11
|
+
);
|
|
12
|
+
return {
|
|
13
|
+
specification: result,
|
|
14
|
+
// TODO: Make dynamic
|
|
15
|
+
version: "3.1"
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
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,24 @@
|
|
|
1
|
+
async function workThroughQueue(queue) {
|
|
2
|
+
let specification = queue.specification;
|
|
3
|
+
let result;
|
|
4
|
+
for (const { action, options } of queue.tasks) {
|
|
5
|
+
if (typeof action !== "function") {
|
|
6
|
+
console.warn("[queue] The given action is not a function:", action);
|
|
7
|
+
continue;
|
|
8
|
+
}
|
|
9
|
+
if (action.constructor.name === "AsyncFunction") {
|
|
10
|
+
result = {
|
|
11
|
+
...result,
|
|
12
|
+
...await action(result?.filesystem ?? specification, options)
|
|
13
|
+
};
|
|
14
|
+
} else {
|
|
15
|
+
result = {
|
|
16
|
+
...result,
|
|
17
|
+
...action(result?.filesystem ?? specification, options)
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { workThroughQueue };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { OpenApiVersion, ERRORS } from '../configuration.js';
|
|
2
|
+
import { OpenAPI } from './openapi-types.js';
|
|
3
|
+
export { OpenAPIV2, OpenAPIV3, OpenAPIV3_1 } from './openapi-types.js';
|
|
4
|
+
|
|
5
|
+
type AnyObject = Record<string, any>;
|
|
6
|
+
type LoadResult = {
|
|
7
|
+
filesystem: Filesystem;
|
|
8
|
+
};
|
|
9
|
+
type ValidateResult = {
|
|
10
|
+
valid: boolean;
|
|
11
|
+
specification?: OpenAPI.Document;
|
|
12
|
+
version?: string;
|
|
13
|
+
errors?: ErrorObject[];
|
|
14
|
+
schema?: OpenAPI.Document;
|
|
15
|
+
};
|
|
16
|
+
type UpgradeResult = {
|
|
17
|
+
specification: OpenAPI.Document;
|
|
18
|
+
version: string;
|
|
19
|
+
};
|
|
20
|
+
type FilterResult = {
|
|
21
|
+
specification: OpenAPI.Document;
|
|
22
|
+
};
|
|
23
|
+
type DetailsResult = {
|
|
24
|
+
version: OpenApiVersion;
|
|
25
|
+
specificationType: string;
|
|
26
|
+
specificationVersion: string;
|
|
27
|
+
};
|
|
28
|
+
type DereferenceResult = {
|
|
29
|
+
version: string | undefined;
|
|
30
|
+
specification?: OpenAPI.Document;
|
|
31
|
+
schema?: OpenAPI.Document;
|
|
32
|
+
errors?: ErrorObject[];
|
|
33
|
+
};
|
|
34
|
+
type ErrorObject = {
|
|
35
|
+
message: string;
|
|
36
|
+
code?: keyof typeof ERRORS | string;
|
|
37
|
+
};
|
|
38
|
+
type AjvOptions = {
|
|
39
|
+
strict?: boolean | 'log';
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Not literally a filesystem, but a list of files with their content.
|
|
43
|
+
* This is an abstraction layer to handle multiple files in the browser (without access to the hard disk).
|
|
44
|
+
*/
|
|
45
|
+
type Filesystem = FilesystemEntry[];
|
|
46
|
+
/**
|
|
47
|
+
* Holds all information about a single file (doesn’t have to be a literal file, see Filesystem).
|
|
48
|
+
*/
|
|
49
|
+
type FilesystemEntry = {
|
|
50
|
+
dir: string;
|
|
51
|
+
isEntrypoint: boolean;
|
|
52
|
+
references: string[];
|
|
53
|
+
filename: string;
|
|
54
|
+
specification: AnyObject;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export { type AjvOptions, type AnyObject, type DereferenceResult, type DetailsResult, type ErrorObject, type Filesystem, type FilesystemEntry, type FilterResult, type LoadResult, OpenAPI, type UpgradeResult, type ValidateResult };
|