@scalar/openapi-parser 0.25.3 → 0.25.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/CHANGELOG.md +12 -0
- package/dist/configuration/index.js +24 -24
- package/dist/index.js +24 -45
- package/dist/lib/Validator/Validator.d.ts.map +1 -1
- package/dist/lib/Validator/Validator.js +125 -105
- package/dist/plugins/fetch-urls/fetch-urls.js +39 -38
- package/dist/plugins/fetch-urls/index.js +1 -6
- package/dist/plugins/read-files/index.js +1 -5
- package/dist/plugins/read-files/read-files.js +53 -51
- package/dist/schemas/v2.0/schema.js +1373 -1377
- package/dist/schemas/v3.0/schema.js +1411 -1415
- package/dist/schemas/v3.1/schema.js +1196 -1200
- package/dist/schemas/v3.2/schema.js +1417 -1421
- package/dist/types/index.js +1 -1
- package/dist/utils/betterAjvErrors/helpers.js +138 -112
- package/dist/utils/betterAjvErrors/index.js +11 -15
- package/dist/utils/betterAjvErrors/utils.js +17 -30
- package/dist/utils/betterAjvErrors/validation-errors/additional-prop.js +14 -18
- package/dist/utils/betterAjvErrors/validation-errors/base.js +20 -21
- package/dist/utils/betterAjvErrors/validation-errors/default.js +14 -18
- package/dist/utils/betterAjvErrors/validation-errors/enum.js +33 -37
- package/dist/utils/betterAjvErrors/validation-errors/index.js +6 -15
- package/dist/utils/betterAjvErrors/validation-errors/pattern.js +14 -18
- package/dist/utils/betterAjvErrors/validation-errors/required.js +13 -17
- package/dist/utils/betterAjvErrors/validation-errors/unevaluated-prop.js +14 -18
- package/dist/utils/dereference.js +22 -18
- package/dist/utils/details.js +28 -29
- package/dist/utils/filter.js +13 -14
- package/dist/utils/get-entrypoint.js +5 -6
- package/dist/utils/get-list-of-references.js +20 -16
- package/dist/utils/get-segments-from-path.js +13 -9
- package/dist/utils/is-filesystem.js +8 -6
- package/dist/utils/is-json.js +8 -11
- package/dist/utils/is-yaml.js +15 -17
- package/dist/utils/join/index.js +1 -5
- package/dist/utils/join/join.js +267 -153
- package/dist/utils/join/merge-objects.js +35 -18
- package/dist/utils/load/index.js +1 -5
- package/dist/utils/load/load.js +114 -90
- package/dist/utils/make-filesystem.js +20 -21
- package/dist/utils/normalize.js +32 -29
- package/dist/utils/openapi/actions/details.js +9 -10
- package/dist/utils/openapi/actions/files.js +7 -8
- package/dist/utils/openapi/actions/get.js +9 -10
- package/dist/utils/openapi/actions/toJson.js +9 -10
- package/dist/utils/openapi/actions/toYaml.js +9 -10
- package/dist/utils/openapi/commands/dereferenceCommand.js +25 -26
- package/dist/utils/openapi/commands/filterCommand.js +24 -25
- package/dist/utils/openapi/commands/loadCommand.js +40 -41
- package/dist/utils/openapi/commands/upgradeCommand.js +27 -28
- package/dist/utils/openapi/commands/validateCommand.js +31 -32
- package/dist/utils/openapi/openapi.js +16 -14
- package/dist/utils/openapi/openapi.test-d.js +13 -13
- package/dist/utils/openapi/utils/queueTask.js +8 -9
- package/dist/utils/openapi/utils/workThroughQueue.js +64 -50
- package/dist/utils/resolve-references.js +168 -110
- package/dist/utils/to-json.js +1 -5
- package/dist/utils/to-yaml.js +2 -6
- package/dist/utils/transform/sanitize.js +22 -22
- package/dist/utils/transform/utils/addInfoObject.js +9 -14
- package/dist/utils/transform/utils/addLatestOpenApiVersion.js +4 -9
- package/dist/utils/transform/utils/addMissingTags.js +26 -27
- package/dist/utils/transform/utils/normalizeSecuritySchemes.js +39 -37
- package/dist/utils/transform/utils/rejectSwaggerDocuments.js +5 -9
- package/dist/utils/transform-errors.js +62 -55
- package/dist/utils/traverse.js +21 -22
- package/dist/utils/unescape-json-pointer.js +8 -6
- package/dist/utils/upgrade.js +19 -22
- package/dist/utils/validate-path-parameters.d.ts +6 -0
- package/dist/utils/validate-path-parameters.d.ts.map +1 -0
- package/dist/utils/validate-path-parameters.js +91 -0
- package/dist/utils/validate.js +23 -19
- package/package.json +9 -14
- package/dist/configuration/index.js.map +0 -7
- package/dist/declarations.d.js +0 -1
- package/dist/declarations.d.js.map +0 -7
- package/dist/index.js.map +0 -7
- package/dist/lib/Validator/Validator.js.map +0 -7
- package/dist/plugins/fetch-urls/fetch-urls.js.map +0 -7
- package/dist/plugins/fetch-urls/index.js.map +0 -7
- package/dist/plugins/read-files/index.js.map +0 -7
- package/dist/plugins/read-files/read-files.js.map +0 -7
- package/dist/schemas/v2.0/schema.js.map +0 -7
- package/dist/schemas/v3.0/schema.js.map +0 -7
- package/dist/schemas/v3.1/schema.js.map +0 -7
- package/dist/schemas/v3.2/schema.js.map +0 -7
- package/dist/types/index.js.map +0 -7
- package/dist/utils/betterAjvErrors/helpers.js.map +0 -7
- package/dist/utils/betterAjvErrors/index.js.map +0 -7
- package/dist/utils/betterAjvErrors/utils.js.map +0 -7
- package/dist/utils/betterAjvErrors/validation-errors/additional-prop.js.map +0 -7
- package/dist/utils/betterAjvErrors/validation-errors/base.js.map +0 -7
- package/dist/utils/betterAjvErrors/validation-errors/default.js.map +0 -7
- package/dist/utils/betterAjvErrors/validation-errors/enum.js.map +0 -7
- package/dist/utils/betterAjvErrors/validation-errors/index.js.map +0 -7
- package/dist/utils/betterAjvErrors/validation-errors/pattern.js.map +0 -7
- package/dist/utils/betterAjvErrors/validation-errors/required.js.map +0 -7
- package/dist/utils/betterAjvErrors/validation-errors/unevaluated-prop.js.map +0 -7
- package/dist/utils/dereference.js.map +0 -7
- package/dist/utils/details.js.map +0 -7
- package/dist/utils/filter.js.map +0 -7
- package/dist/utils/get-entrypoint.js.map +0 -7
- package/dist/utils/get-list-of-references.js.map +0 -7
- package/dist/utils/get-segments-from-path.js.map +0 -7
- package/dist/utils/is-filesystem.js.map +0 -7
- package/dist/utils/is-json.js.map +0 -7
- package/dist/utils/is-yaml.js.map +0 -7
- package/dist/utils/join/index.js.map +0 -7
- package/dist/utils/join/join.js.map +0 -7
- package/dist/utils/join/merge-objects.js.map +0 -7
- package/dist/utils/load/index.js.map +0 -7
- package/dist/utils/load/load.js.map +0 -7
- package/dist/utils/make-filesystem.js.map +0 -7
- package/dist/utils/normalize.js.map +0 -7
- package/dist/utils/openapi/actions/details.js.map +0 -7
- package/dist/utils/openapi/actions/files.js.map +0 -7
- package/dist/utils/openapi/actions/get.js.map +0 -7
- package/dist/utils/openapi/actions/toJson.js.map +0 -7
- package/dist/utils/openapi/actions/toYaml.js.map +0 -7
- package/dist/utils/openapi/commands/dereferenceCommand.js.map +0 -7
- package/dist/utils/openapi/commands/filterCommand.js.map +0 -7
- package/dist/utils/openapi/commands/loadCommand.js.map +0 -7
- package/dist/utils/openapi/commands/upgradeCommand.js.map +0 -7
- package/dist/utils/openapi/commands/validateCommand.js.map +0 -7
- package/dist/utils/openapi/openapi.js.map +0 -7
- package/dist/utils/openapi/openapi.test-d.js.map +0 -7
- package/dist/utils/openapi/utils/queueTask.js.map +0 -7
- package/dist/utils/openapi/utils/workThroughQueue.js.map +0 -7
- package/dist/utils/resolve-references.js.map +0 -7
- package/dist/utils/to-json.js.map +0 -7
- package/dist/utils/to-yaml.js.map +0 -7
- package/dist/utils/transform/sanitize.js.map +0 -7
- package/dist/utils/transform/utils/addInfoObject.js.map +0 -7
- package/dist/utils/transform/utils/addLatestOpenApiVersion.js.map +0 -7
- package/dist/utils/transform/utils/addMissingTags.js.map +0 -7
- package/dist/utils/transform/utils/normalizeSecuritySchemes.js.map +0 -7
- package/dist/utils/transform/utils/rejectSwaggerDocuments.js.map +0 -7
- package/dist/utils/transform-errors.js.map +0 -7
- package/dist/utils/traverse.js.map +0 -7
- package/dist/utils/unescape-json-pointer.js.map +0 -7
- package/dist/utils/upgrade.js.map +0 -7
- package/dist/utils/validate.js.map +0 -7
|
@@ -1,29 +1,28 @@
|
|
|
1
|
-
import { details } from
|
|
2
|
-
import { files } from
|
|
3
|
-
import { get } from
|
|
4
|
-
import { toJson } from
|
|
5
|
-
import { toYaml } from
|
|
6
|
-
import { queueTask } from
|
|
7
|
-
import { dereferenceCommand } from
|
|
8
|
-
import { filterCommand } from
|
|
9
|
-
import { validateCommand } from
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
import { details } from '../actions/details.js';
|
|
2
|
+
import { files } from '../actions/files.js';
|
|
3
|
+
import { get } from '../actions/get.js';
|
|
4
|
+
import { toJson } from '../actions/toJson.js';
|
|
5
|
+
import { toYaml } from '../actions/toYaml.js';
|
|
6
|
+
import { queueTask } from '../utils/queueTask.js';
|
|
7
|
+
import { dereferenceCommand } from './dereferenceCommand.js';
|
|
8
|
+
import { filterCommand } from './filterCommand.js';
|
|
9
|
+
import { validateCommand } from './validateCommand.js';
|
|
10
|
+
/**
|
|
11
|
+
* Upgrade the given OpenAPI document
|
|
12
|
+
*/
|
|
13
|
+
export function upgradeCommand(previousQueue) {
|
|
14
|
+
const task = {
|
|
15
|
+
name: 'upgrade',
|
|
16
|
+
};
|
|
17
|
+
const queue = queueTask(previousQueue, task);
|
|
18
|
+
return {
|
|
19
|
+
dereference: (dereferenceOptions) => dereferenceCommand(queue, dereferenceOptions),
|
|
20
|
+
details: () => details(queue),
|
|
21
|
+
files: () => files(queue),
|
|
22
|
+
filter: (callback) => filterCommand(queue, callback),
|
|
23
|
+
get: () => get(queue),
|
|
24
|
+
toJson: () => toJson(queue),
|
|
25
|
+
toYaml: () => toYaml(queue),
|
|
26
|
+
validate: (validateOptions) => validateCommand(queue, validateOptions),
|
|
27
|
+
};
|
|
25
28
|
}
|
|
26
|
-
export {
|
|
27
|
-
upgradeCommand
|
|
28
|
-
};
|
|
29
|
-
//# sourceMappingURL=upgradeCommand.js.map
|
|
@@ -1,33 +1,32 @@
|
|
|
1
|
-
import { details } from
|
|
2
|
-
import { files } from
|
|
3
|
-
import { get } from
|
|
4
|
-
import { toJson } from
|
|
5
|
-
import { toYaml } from
|
|
6
|
-
import { queueTask } from
|
|
7
|
-
import { dereferenceCommand } from
|
|
8
|
-
import { filterCommand } from
|
|
9
|
-
import { upgradeCommand } from
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
1
|
+
import { details } from '../actions/details.js';
|
|
2
|
+
import { files } from '../actions/files.js';
|
|
3
|
+
import { get } from '../actions/get.js';
|
|
4
|
+
import { toJson } from '../actions/toJson.js';
|
|
5
|
+
import { toYaml } from '../actions/toYaml.js';
|
|
6
|
+
import { queueTask } from '../utils/queueTask.js';
|
|
7
|
+
import { dereferenceCommand } from './dereferenceCommand.js';
|
|
8
|
+
import { filterCommand } from './filterCommand.js';
|
|
9
|
+
import { upgradeCommand } from './upgradeCommand.js';
|
|
10
|
+
/**
|
|
11
|
+
* Validate the given OpenAPI document
|
|
12
|
+
*/
|
|
13
|
+
export function validateCommand(previousQueue, options) {
|
|
14
|
+
const task = {
|
|
15
|
+
name: 'validate',
|
|
16
|
+
options: {
|
|
17
|
+
throwOnError: previousQueue.options?.throwOnError,
|
|
18
|
+
...(options ?? {}),
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
const queue = queueTask(previousQueue, task);
|
|
22
|
+
return {
|
|
23
|
+
dereference: (dereferenceOptions) => dereferenceCommand(queue, dereferenceOptions),
|
|
24
|
+
details: () => details(queue),
|
|
25
|
+
files: () => files(queue),
|
|
26
|
+
filter: (callback) => filterCommand(queue, callback),
|
|
27
|
+
get: () => get(queue),
|
|
28
|
+
toJson: () => toJson(queue),
|
|
29
|
+
toYaml: () => toYaml(queue),
|
|
30
|
+
upgrade: () => upgradeCommand(queue),
|
|
31
|
+
};
|
|
29
32
|
}
|
|
30
|
-
export {
|
|
31
|
-
validateCommand
|
|
32
|
-
};
|
|
33
|
-
//# sourceMappingURL=validateCommand.js.map
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import { loadCommand } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { loadCommand } from './commands/loadCommand.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a fluent OpenAPI pipeline
|
|
4
|
+
*
|
|
5
|
+
* @deprecated We are about to drop the pipeline syntax. Use the individual utilities instead.
|
|
6
|
+
*/
|
|
7
|
+
export function openapi(globalOptions) {
|
|
8
|
+
// Create a new queue
|
|
9
|
+
const queue = {
|
|
10
|
+
input: null,
|
|
11
|
+
options: globalOptions,
|
|
12
|
+
tasks: [],
|
|
13
|
+
};
|
|
14
|
+
return {
|
|
15
|
+
load: (input, options) => loadCommand(queue, input, options),
|
|
16
|
+
};
|
|
11
17
|
}
|
|
12
|
-
export {
|
|
13
|
-
openapi
|
|
14
|
-
};
|
|
15
|
-
//# sourceMappingURL=openapi.js.map
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { describe, expectTypeOf, it } from
|
|
2
|
-
import { openapi } from
|
|
3
|
-
describe(
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { describe, expectTypeOf, it } from 'vitest';
|
|
2
|
+
import { openapi } from './openapi.js';
|
|
3
|
+
describe('openapi', () => {
|
|
4
|
+
it('returns the correct type for load()', async () => {
|
|
5
|
+
const result = await openapi().load({}).get();
|
|
6
|
+
expectTypeOf(result.filesystem).toMatchTypeOf();
|
|
7
|
+
// @ts-expect-error `valid` should be undefined
|
|
8
|
+
expectTypeOf(result.valid).toMatchTypeOf();
|
|
9
|
+
});
|
|
10
|
+
it('returns the correct type for validate()', async () => {
|
|
11
|
+
const result = await openapi().load({}).validate().get();
|
|
12
|
+
expectTypeOf(result.valid).toMatchTypeOf();
|
|
13
|
+
});
|
|
13
14
|
});
|
|
14
|
-
//# sourceMappingURL=openapi.test-d.js.map
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Add a new task to the existing queue
|
|
3
|
+
*/
|
|
4
|
+
export function queueTask(queue, task) {
|
|
5
|
+
return {
|
|
6
|
+
...queue,
|
|
7
|
+
tasks: [...queue.tasks, task],
|
|
8
|
+
};
|
|
6
9
|
}
|
|
7
|
-
export {
|
|
8
|
-
queueTask
|
|
9
|
-
};
|
|
10
|
-
//# sourceMappingURL=queueTask.js.map
|
|
@@ -1,52 +1,66 @@
|
|
|
1
|
-
import { dereference } from
|
|
2
|
-
import { filter } from
|
|
3
|
-
import { load } from
|
|
4
|
-
import { upgrade } from
|
|
5
|
-
import { validate } from
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
1
|
+
import { dereference } from '../../../utils/dereference.js';
|
|
2
|
+
import { filter } from '../../../utils/filter.js';
|
|
3
|
+
import { load } from '../../../utils/load/load.js';
|
|
4
|
+
import { upgrade } from '../../../utils/upgrade.js';
|
|
5
|
+
import { validate } from '../../../utils/validate.js';
|
|
6
|
+
/**
|
|
7
|
+
* Takes a queue of tasks and works through them
|
|
8
|
+
*/
|
|
9
|
+
export async function workThroughQueue(queue) {
|
|
10
|
+
const { input } = {
|
|
11
|
+
...queue,
|
|
12
|
+
};
|
|
13
|
+
let result = {};
|
|
14
|
+
// Work through the whole queue
|
|
15
|
+
for (const task of queue.tasks) {
|
|
16
|
+
const name = task.name;
|
|
17
|
+
const options = 'options' in task ? task.options : undefined;
|
|
18
|
+
// Use the result of the previous task, or fall back to the original input
|
|
19
|
+
const currentSpecification = result.specification
|
|
20
|
+
? result.specification
|
|
21
|
+
: typeof input === 'object'
|
|
22
|
+
? // Detach from the original object
|
|
23
|
+
structuredClone(input)
|
|
24
|
+
: input;
|
|
25
|
+
// load
|
|
26
|
+
if (name === 'load') {
|
|
27
|
+
result = {
|
|
28
|
+
...result,
|
|
29
|
+
...(await load(input, options)),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
// validate
|
|
33
|
+
else if (name === 'filter') {
|
|
34
|
+
result = {
|
|
35
|
+
...result,
|
|
36
|
+
...filter(currentSpecification, options),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
// dereference
|
|
40
|
+
else if (name === 'dereference') {
|
|
41
|
+
result = {
|
|
42
|
+
...result,
|
|
43
|
+
...dereference(currentSpecification, options),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// upgrade
|
|
47
|
+
else if (name === 'upgrade') {
|
|
48
|
+
result = {
|
|
49
|
+
...result,
|
|
50
|
+
...upgrade(currentSpecification),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// validate
|
|
54
|
+
else if (name === 'validate') {
|
|
55
|
+
result = {
|
|
56
|
+
...result,
|
|
57
|
+
...(await validate(currentSpecification, options)),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// Make TS complain when we forgot to handle a command.
|
|
61
|
+
else {
|
|
62
|
+
name;
|
|
63
|
+
}
|
|
45
64
|
}
|
|
46
|
-
|
|
47
|
-
return result;
|
|
65
|
+
return result;
|
|
48
66
|
}
|
|
49
|
-
export {
|
|
50
|
-
workThroughQueue
|
|
51
|
-
};
|
|
52
|
-
//# sourceMappingURL=workThroughQueue.js.map
|
|
@@ -1,124 +1,182 @@
|
|
|
1
|
-
import { isObject } from
|
|
2
|
-
import { ERRORS } from
|
|
3
|
-
import { getEntrypoint } from
|
|
4
|
-
import { getSegmentsFromPath } from
|
|
5
|
-
import { makeFilesystem } from
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
import { isObject } from '@scalar/helpers/object/is-object';
|
|
2
|
+
import { ERRORS } from '../configuration/index.js';
|
|
3
|
+
import { getEntrypoint } from './get-entrypoint.js';
|
|
4
|
+
import { getSegmentsFromPath } from './get-segments-from-path.js';
|
|
5
|
+
import { makeFilesystem } from './make-filesystem.js';
|
|
6
|
+
/**
|
|
7
|
+
* Takes a specification and resolves all references.
|
|
8
|
+
*/
|
|
9
|
+
export function resolveReferences(
|
|
10
|
+
// Just a specification, or a set of files.
|
|
11
|
+
input,
|
|
12
|
+
// Additional options to control the behaviour
|
|
13
|
+
options,
|
|
14
|
+
// Fallback to the entrypoint
|
|
15
|
+
file,
|
|
16
|
+
// Errors that occurred during the process
|
|
17
|
+
errors = []) {
|
|
18
|
+
// Detach from input
|
|
19
|
+
const clonedInput = structuredClone(input);
|
|
20
|
+
// Make it a filesystem, even if it's just one file
|
|
21
|
+
const filesystem = makeFilesystem(clonedInput);
|
|
22
|
+
// Get the main file
|
|
23
|
+
const entrypoint = getEntrypoint(filesystem);
|
|
24
|
+
const finalInput = file?.specification ?? entrypoint.specification;
|
|
25
|
+
// Does it look like an OpenAPI document?
|
|
26
|
+
if (!isObject(finalInput)) {
|
|
27
|
+
if (options?.throwOnError) {
|
|
28
|
+
throw new Error(ERRORS.NO_CONTENT);
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
valid: false,
|
|
32
|
+
errors,
|
|
33
|
+
schema: finalInput,
|
|
34
|
+
};
|
|
14
35
|
}
|
|
36
|
+
// Recursively resolve all references
|
|
37
|
+
dereference(finalInput, filesystem, file ?? entrypoint, new WeakSet(), errors, options);
|
|
38
|
+
// Remove duplicates (according to message) from errors
|
|
39
|
+
errors = errors.filter((error, index, self) => index === self.findIndex((t) => t.message === error.message && t.code === error.code));
|
|
40
|
+
// Return the resolved specification
|
|
15
41
|
return {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
42
|
+
valid: errors.length === 0,
|
|
43
|
+
errors,
|
|
44
|
+
schema: finalInput,
|
|
19
45
|
};
|
|
20
|
-
}
|
|
21
|
-
dereference(finalInput, filesystem, file ?? entrypoint, /* @__PURE__ */ new WeakSet(), errors, options);
|
|
22
|
-
errors = errors.filter(
|
|
23
|
-
(error, index, self) => index === self.findIndex((t) => t.message === error.message && t.code === error.code)
|
|
24
|
-
);
|
|
25
|
-
return {
|
|
26
|
-
valid: errors.length === 0,
|
|
27
|
-
errors,
|
|
28
|
-
schema: finalInput
|
|
29
|
-
};
|
|
30
46
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
while (schema.$ref !== void 0) {
|
|
42
|
-
const selfReferenceDetected = processedRefs.has(schema.$ref);
|
|
43
|
-
if (selfReferenceDetected) {
|
|
44
|
-
errors.push({
|
|
45
|
-
code: "SELF_REFERENCE",
|
|
46
|
-
message: ERRORS.SELF_REFERENCE.replace("%s", schema.$ref)
|
|
47
|
-
});
|
|
48
|
-
delete schema.$ref;
|
|
49
|
-
break;
|
|
47
|
+
/**
|
|
48
|
+
* Resolves the circular reference to an object and deletes the $ref properties (in-place).
|
|
49
|
+
*/
|
|
50
|
+
function dereference(schema, filesystem, entrypoint,
|
|
51
|
+
// references to resolved object
|
|
52
|
+
resolvedSchemas,
|
|
53
|
+
// error output
|
|
54
|
+
errors, options) {
|
|
55
|
+
if (schema === null || resolvedSchemas.has(schema)) {
|
|
56
|
+
return;
|
|
50
57
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
58
|
+
resolvedSchemas.add(schema);
|
|
59
|
+
function resolveExternal(externalFile) {
|
|
60
|
+
dereference(externalFile.specification, filesystem, externalFile, resolvedSchemas, errors, options);
|
|
61
|
+
return externalFile;
|
|
55
62
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Track seen $ref paths to detect self-referencing schemas.
|
|
65
|
+
*
|
|
66
|
+
* This only tracks $refs within the current while loop (one resolution chain).
|
|
67
|
+
* Each schema object gets its own fresh processedRefs when dereference() is called.
|
|
68
|
+
*
|
|
69
|
+
* This catches invalid cases like:
|
|
70
|
+
* Test: { $ref: '#/components/schemas/Test' }
|
|
71
|
+
*
|
|
72
|
+
* But allows valid recursive schemas where the $ref is nested:
|
|
73
|
+
* Person: { type: 'object', properties: { friend: { $ref: '#/components/schemas/Person' } } }
|
|
74
|
+
*/
|
|
75
|
+
const processedRefs = new Set();
|
|
76
|
+
while (schema.$ref !== undefined) {
|
|
77
|
+
const selfReferenceDetected = processedRefs.has(schema.$ref);
|
|
78
|
+
if (selfReferenceDetected) {
|
|
79
|
+
errors.push({
|
|
80
|
+
code: 'SELF_REFERENCE',
|
|
81
|
+
message: ERRORS.SELF_REFERENCE.replace('%s', schema.$ref),
|
|
82
|
+
});
|
|
83
|
+
delete schema.$ref;
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
processedRefs.add(schema.$ref);
|
|
87
|
+
// Find the referenced content
|
|
88
|
+
const resolved = resolveUri(schema.$ref, options, entrypoint, filesystem, resolveExternal, errors);
|
|
89
|
+
// invalid
|
|
90
|
+
if (typeof resolved !== 'object' || resolved === null) {
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
const dereferencedRef = schema.$ref;
|
|
94
|
+
// Get rid of the reference
|
|
95
|
+
delete schema.$ref;
|
|
96
|
+
for (const key of Object.keys(resolved)) {
|
|
97
|
+
if (schema[key] === undefined) {
|
|
98
|
+
schema[key] = resolved[key];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (dereferencedRef) {
|
|
102
|
+
options?.onDereference?.({ schema, ref: dereferencedRef });
|
|
103
|
+
}
|
|
62
104
|
}
|
|
63
|
-
|
|
64
|
-
|
|
105
|
+
// Iterate over the whole object
|
|
106
|
+
for (const value of Object.values(schema)) {
|
|
107
|
+
if (typeof value === 'object' && value !== null) {
|
|
108
|
+
dereference(value, filesystem, entrypoint, resolvedSchemas, errors, options);
|
|
109
|
+
}
|
|
65
110
|
}
|
|
66
|
-
}
|
|
67
|
-
for (const value of Object.values(schema)) {
|
|
68
|
-
if (typeof value === "object" && value !== null) {
|
|
69
|
-
dereference(value, filesystem, entrypoint, resolvedSchemas, errors, options);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
111
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
112
|
+
/**
|
|
113
|
+
* Resolves a URI to a part of the specification
|
|
114
|
+
*
|
|
115
|
+
* The output is not necessarily dereferenced
|
|
116
|
+
*/
|
|
117
|
+
function resolveUri(
|
|
118
|
+
// 'foobar.json#/foo/bar'
|
|
119
|
+
uri, options,
|
|
120
|
+
// { filename: './foobar.json '}
|
|
121
|
+
file,
|
|
122
|
+
// [ { filename: './foobar.json '} ]
|
|
123
|
+
filesystem,
|
|
124
|
+
// a function to resolve references in external file
|
|
125
|
+
resolve, errors) {
|
|
126
|
+
// Ignore invalid URIs
|
|
127
|
+
if (typeof uri !== 'string') {
|
|
128
|
+
if (options?.throwOnError) {
|
|
129
|
+
throw new Error(ERRORS.INVALID_REFERENCE.replace('%s', uri));
|
|
130
|
+
}
|
|
131
|
+
errors.push({
|
|
132
|
+
code: 'INVALID_REFERENCE',
|
|
133
|
+
message: ERRORS.INVALID_REFERENCE.replace('%s', uri),
|
|
134
|
+
});
|
|
135
|
+
return undefined;
|
|
77
136
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
137
|
+
// Understand the URI
|
|
138
|
+
const [prefix, path] = uri.split('#', 2);
|
|
139
|
+
/** Check whether the file is pointing to itself */
|
|
140
|
+
const isDifferentFile = prefix !== file.filename;
|
|
141
|
+
// External references
|
|
142
|
+
if (prefix && isDifferentFile) {
|
|
143
|
+
const externalReference = filesystem.find((entry) => {
|
|
144
|
+
return entry.filename === prefix;
|
|
145
|
+
});
|
|
146
|
+
if (!externalReference) {
|
|
147
|
+
if (options?.throwOnError) {
|
|
148
|
+
throw new Error(ERRORS.EXTERNAL_REFERENCE_NOT_FOUND.replace('%s', prefix));
|
|
149
|
+
}
|
|
150
|
+
errors.push({
|
|
151
|
+
code: 'EXTERNAL_REFERENCE_NOT_FOUND',
|
|
152
|
+
message: ERRORS.EXTERNAL_REFERENCE_NOT_FOUND.replace('%s', prefix),
|
|
153
|
+
});
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
// $ref: 'other-file.yaml'
|
|
157
|
+
if (path === undefined) {
|
|
158
|
+
return externalReference.specification;
|
|
159
|
+
}
|
|
160
|
+
// $ref: 'other-file.yaml#/foo/bar'
|
|
161
|
+
// resolve refs first before accessing properties directly
|
|
162
|
+
return resolveUri(`#${path}`, options, resolve(externalReference), filesystem, resolve, errors);
|
|
99
163
|
}
|
|
100
|
-
|
|
101
|
-
|
|
164
|
+
// Pointers
|
|
165
|
+
const segments = getSegmentsFromPath(path);
|
|
166
|
+
// Try to find the URI
|
|
167
|
+
try {
|
|
168
|
+
return segments.reduce((acc, key) => {
|
|
169
|
+
return acc[key];
|
|
170
|
+
}, file.specification);
|
|
102
171
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (options?.throwOnError) {
|
|
112
|
-
throw new Error(ERRORS.INVALID_REFERENCE.replace("%s", uri));
|
|
172
|
+
catch (_error) {
|
|
173
|
+
if (options?.throwOnError) {
|
|
174
|
+
throw new Error(ERRORS.INVALID_REFERENCE.replace('%s', uri));
|
|
175
|
+
}
|
|
176
|
+
errors.push({
|
|
177
|
+
code: 'INVALID_REFERENCE',
|
|
178
|
+
message: ERRORS.INVALID_REFERENCE.replace('%s', uri),
|
|
179
|
+
});
|
|
113
180
|
}
|
|
114
|
-
|
|
115
|
-
code: "INVALID_REFERENCE",
|
|
116
|
-
message: ERRORS.INVALID_REFERENCE.replace("%s", uri)
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
return void 0;
|
|
181
|
+
return undefined;
|
|
120
182
|
}
|
|
121
|
-
export {
|
|
122
|
-
resolveReferences
|
|
123
|
-
};
|
|
124
|
-
//# sourceMappingURL=resolve-references.js.map
|
package/dist/utils/to-json.js
CHANGED
package/dist/utils/to-yaml.js
CHANGED