@redocly/openapi-core 1.18.0 → 1.19.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 +20 -0
- package/lib/benchmark/benches/lint-with-many-rules.bench.js +2 -2
- package/lib/benchmark/benches/lint-with-nested-rule.bench.js +2 -2
- package/lib/benchmark/benches/lint-with-no-rules.bench.js +2 -2
- package/lib/benchmark/benches/lint-with-top-level-rule-report.bench.js +2 -2
- package/lib/benchmark/benches/lint-with-top-level-rule.bench.js +2 -2
- package/lib/benchmark/benches/recommended-oas3.bench.js +2 -2
- package/lib/benchmark/benches/resolve-with-no-external.bench.js +2 -2
- package/lib/benchmark/utils.js +7 -4
- package/lib/bundle.d.ts +3 -3
- package/lib/bundle.js +128 -122
- package/lib/config/all.js +9 -0
- package/lib/config/builtIn.js +7 -1
- package/lib/config/config-resolvers.js +179 -138
- package/lib/config/config.d.ts +2 -2
- package/lib/config/config.js +53 -34
- package/lib/config/load.d.ts +1 -2
- package/lib/config/load.js +105 -117
- package/lib/config/minimal.js +9 -0
- package/lib/config/recommended-strict.js +9 -0
- package/lib/config/recommended.js +9 -0
- package/lib/config/rules.d.ts +3 -3
- package/lib/config/rules.js +1 -2
- package/lib/config/types.d.ts +9 -3
- package/lib/config/utils.js +70 -49
- package/lib/decorators/async3/index.d.ts +1 -0
- package/lib/decorators/async3/index.js +4 -0
- package/lib/decorators/common/filters/filter-helper.js +2 -3
- package/lib/decorators/common/filters/filter-in.js +1 -1
- package/lib/decorators/common/filters/filter-out.js +1 -1
- package/lib/decorators/common/info-override.js +1 -12
- package/lib/decorators/common/media-type-examples-override.js +8 -2
- package/lib/decorators/common/remove-x-internal.js +4 -5
- package/lib/decorators/oas2/remove-unused-components.js +1 -2
- package/lib/decorators/oas3/remove-unused-components.js +1 -2
- package/lib/env.d.ts +0 -1
- package/lib/env.js +1 -1
- package/lib/format/codeframes.js +10 -8
- package/lib/format/format.js +23 -15
- package/lib/index.d.ts +2 -1
- package/lib/index.js +6 -4
- package/lib/js-yaml/index.js +1 -1
- package/lib/lint.d.ts +2 -0
- package/lib/lint.js +92 -99
- package/lib/oas-types.d.ts +9 -5
- package/lib/oas-types.js +22 -12
- package/lib/redocly/domains.js +6 -6
- package/lib/redocly/index.js +60 -73
- package/lib/redocly/registry-api.js +64 -82
- package/lib/ref-utils.js +13 -13
- package/lib/resolve.js +186 -205
- package/lib/rules/ajv.js +10 -8
- package/lib/rules/async3/channels-kebab-case.d.ts +2 -0
- package/lib/rules/async3/channels-kebab-case.js +19 -0
- package/lib/rules/async3/index.d.ts +3 -0
- package/lib/rules/async3/index.js +22 -0
- package/lib/rules/async3/no-channel-trailing-slash.d.ts +2 -0
- package/lib/rules/async3/no-channel-trailing-slash.js +16 -0
- package/lib/rules/common/assertions/asserts.js +5 -5
- package/lib/rules/common/assertions/index.d.ts +5 -4
- package/lib/rules/common/assertions/utils.js +43 -28
- package/lib/rules/common/no-invalid-parameter-examples.js +1 -2
- package/lib/rules/common/no-invalid-schema-examples.js +1 -2
- package/lib/rules/common/no-required-schema-properties-undefined.js +1 -2
- package/lib/rules/common/operation-tag-defined.js +1 -2
- package/lib/rules/common/path-http-verbs-order.js +1 -1
- package/lib/rules/common/path-segment-plural.js +2 -1
- package/lib/rules/common/required-string-property-missing-min-length.js +2 -2
- package/lib/rules/common/response-contains-header.js +2 -2
- package/lib/rules/common/security-defined.js +3 -7
- package/lib/rules/common/spec.d.ts +2 -2
- package/lib/rules/common/spec.js +6 -7
- package/lib/rules/no-unresolved-refs.js +3 -4
- package/lib/rules/oas2/response-contains-property.js +1 -2
- package/lib/rules/oas3/array-parameter-serialization.js +1 -2
- package/lib/rules/oas3/component-name-unique.js +2 -4
- package/lib/rules/oas3/no-invalid-media-type-examples.js +1 -2
- package/lib/rules/oas3/no-server-variables-empty-enum.js +1 -2
- package/lib/rules/oas3/no-undefined-server-variable.js +2 -3
- package/lib/rules/oas3/no-unused-components.js +1 -2
- package/lib/rules/oas3/response-contains-property.js +1 -2
- package/lib/rules/utils.js +14 -12
- package/lib/types/arazzo.d.ts +1299 -73
- package/lib/types/arazzo.js +41 -36
- package/lib/types/asyncapi2.d.ts +17 -0
- package/lib/types/{asyncapi.js → asyncapi2.js} +71 -93
- package/lib/types/asyncapi3.d.ts +2 -0
- package/lib/types/asyncapi3.js +347 -0
- package/lib/types/index.js +19 -10
- package/lib/types/json-schema-adapter.js +4 -18
- package/lib/types/oas2.js +6 -6
- package/lib/types/oas3.js +10 -10
- package/lib/types/oas3_1.js +15 -9
- package/lib/types/redocly-yaml.d.ts +3 -1
- package/lib/types/redocly-yaml.js +131 -35
- package/lib/typings/arazzo.d.ts +28 -1
- package/lib/typings/asyncapi3.d.ts +53 -0
- package/lib/typings/asyncapi3.js +2 -0
- package/lib/utils.d.ts +12 -7
- package/lib/utils.js +91 -77
- package/lib/visitors.d.ts +11 -0
- package/lib/visitors.js +21 -8
- package/lib/walk.js +30 -23
- package/package.json +3 -3
- package/src/__tests__/bundle.test.ts +142 -0
- package/src/__tests__/lint.test.ts +0 -50
- package/src/bundle.ts +19 -6
- package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +22 -0
- package/src/config/__tests__/__snapshots__/config.test.ts.snap +24 -0
- package/src/config/__tests__/config.test.ts +11 -0
- package/src/config/all.ts +9 -0
- package/src/config/builtIn.ts +6 -0
- package/src/config/config-resolvers.ts +15 -2
- package/src/config/config.ts +24 -5
- package/src/config/load.ts +1 -2
- package/src/config/minimal.ts +9 -0
- package/src/config/recommended-strict.ts +9 -0
- package/src/config/recommended.ts +9 -0
- package/src/config/rules.ts +12 -4
- package/src/config/types.ts +15 -2
- package/src/config/utils.ts +15 -0
- package/src/decorators/async3/index.ts +1 -0
- package/src/decorators/common/remove-x-internal.ts +2 -2
- package/src/index.ts +2 -1
- package/src/lint.ts +26 -3
- package/src/oas-types.ts +31 -13
- package/src/rules/arazzo/index.ts +1 -1
- package/src/rules/async2/index.ts +5 -5
- package/src/rules/async3/__tests__/channels-kebab-case.test.ts +141 -0
- package/src/rules/async3/__tests__/no-channel-trailing-slash.test.ts +96 -0
- package/src/rules/async3/channels-kebab-case.ts +19 -0
- package/src/rules/async3/index.ts +23 -0
- package/src/rules/async3/no-channel-trailing-slash.ts +16 -0
- package/src/rules/common/__tests__/spec.test.ts +47 -0
- package/src/rules/common/assertions/index.ts +13 -4
- package/src/rules/common/no-invalid-schema-examples.ts +3 -2
- package/src/rules/common/path-segment-plural.ts +3 -2
- package/src/rules/common/spec.ts +2 -2
- package/src/rules/oas2/index.ts +4 -4
- package/src/rules/oas3/index.ts +39 -37
- package/src/types/arazzo.ts +28 -23
- package/src/types/{asyncapi.ts → asyncapi2.ts} +58 -76
- package/src/types/asyncapi3.ts +381 -0
- package/src/types/oas3_1.ts +3 -2
- package/src/types/redocly-yaml.ts +14 -0
- package/src/typings/arazzo.ts +41 -1
- package/src/typings/asyncapi3.ts +61 -0
- package/src/utils.ts +46 -11
- package/src/visitors.ts +18 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/types/asyncapi.d.ts +0 -2
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { outdent } from 'outdent';
|
|
2
|
+
import { lintDocument } from '../../../lint';
|
|
3
|
+
import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../../../__tests__/utils';
|
|
4
|
+
import { BaseResolver } from '../../../resolve';
|
|
5
|
+
|
|
6
|
+
describe('no-channel-trailing-slash', () => {
|
|
7
|
+
it.only('should report on trailing slash in a channel path', async () => {
|
|
8
|
+
const document = parseYamlToDocument(
|
|
9
|
+
outdent`
|
|
10
|
+
asyncapi: '3.0.0'
|
|
11
|
+
info:
|
|
12
|
+
title: Excellent API
|
|
13
|
+
version: 1.0.0
|
|
14
|
+
channels:
|
|
15
|
+
channel1:
|
|
16
|
+
address: /trailing/
|
|
17
|
+
payload:
|
|
18
|
+
type: object
|
|
19
|
+
`,
|
|
20
|
+
'asyncapi.yaml'
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const results = await lintDocument({
|
|
24
|
+
externalRefResolver: new BaseResolver(),
|
|
25
|
+
document,
|
|
26
|
+
config: await makeConfig({ 'no-channel-trailing-slash': 'error' }),
|
|
27
|
+
});
|
|
28
|
+
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
|
|
29
|
+
[
|
|
30
|
+
{
|
|
31
|
+
"location": [
|
|
32
|
+
{
|
|
33
|
+
"pointer": "#/channels/channel1",
|
|
34
|
+
"reportOnKey": true,
|
|
35
|
+
"source": "asyncapi.yaml",
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
"message": "\`/trailing/\` should not have a trailing slash.",
|
|
39
|
+
"ruleId": "no-channel-trailing-slash",
|
|
40
|
+
"severity": "error",
|
|
41
|
+
"suggest": [],
|
|
42
|
+
},
|
|
43
|
+
]
|
|
44
|
+
`);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should not report on if no trailing slash in path', async () => {
|
|
48
|
+
const document = parseYamlToDocument(
|
|
49
|
+
outdent`
|
|
50
|
+
asyncapi: '3.0.0'
|
|
51
|
+
info:
|
|
52
|
+
title: Excellent API
|
|
53
|
+
version: 1.0.0
|
|
54
|
+
channels:
|
|
55
|
+
channel1:
|
|
56
|
+
address: /expected
|
|
57
|
+
payload:
|
|
58
|
+
type: object
|
|
59
|
+
`,
|
|
60
|
+
'asyncapi.yaml'
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const results = await lintDocument({
|
|
64
|
+
externalRefResolver: new BaseResolver(),
|
|
65
|
+
document,
|
|
66
|
+
config: await makeConfig({ 'no-channel-trailing-slash': 'error' }),
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`[]`);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should not report on trailing slash in path if the path is root', async () => {
|
|
73
|
+
const document = parseYamlToDocument(
|
|
74
|
+
outdent`
|
|
75
|
+
asyncapi: '3.0.0'
|
|
76
|
+
info:
|
|
77
|
+
title: Excellent API
|
|
78
|
+
version: 1.0.0
|
|
79
|
+
channels:
|
|
80
|
+
channel1:
|
|
81
|
+
address: /
|
|
82
|
+
payload:
|
|
83
|
+
type: object
|
|
84
|
+
`,
|
|
85
|
+
'foobar.yaml'
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const results = await lintDocument({
|
|
89
|
+
externalRefResolver: new BaseResolver(),
|
|
90
|
+
document,
|
|
91
|
+
config: await makeConfig({ 'no-channel-trailing-slash': 'error' }),
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`[]`);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Channel } from '../../typings/asyncapi3';
|
|
2
|
+
import { Async3Rule } from '../../visitors';
|
|
3
|
+
import { UserContext } from '../../walk';
|
|
4
|
+
|
|
5
|
+
export const ChannelsKebabCase: Async3Rule = () => {
|
|
6
|
+
return {
|
|
7
|
+
Channel(channel: Channel, { report }: UserContext) {
|
|
8
|
+
const segments = (channel.address || '')
|
|
9
|
+
.split(/[/.:]/) // split on / or : as likely channel namespacers
|
|
10
|
+
.filter((s) => s !== ''); // filter out empty segments
|
|
11
|
+
if (!segments.every((segment) => /^{.+}$/.test(segment) || /^[a-z0-9-.]+$/.test(segment))) {
|
|
12
|
+
report({
|
|
13
|
+
message: `\`${channel.address}\` does not use kebab-case.`,
|
|
14
|
+
location: { reportOnKey: true },
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Async3Rule } from '../../visitors';
|
|
2
|
+
import { Assertions } from '../common/assertions';
|
|
3
|
+
import { Spec } from '../common/spec';
|
|
4
|
+
import { InfoContact } from '../common/info-contact';
|
|
5
|
+
import { OperationOperationId } from '../common/operation-operationId';
|
|
6
|
+
import { TagDescription } from '../common/tag-description';
|
|
7
|
+
import { TagsAlphabetical } from '../common/tags-alphabetical';
|
|
8
|
+
import { ChannelsKebabCase } from './channels-kebab-case';
|
|
9
|
+
import { NoChannelTrailingSlash } from './no-channel-trailing-slash';
|
|
10
|
+
import type { Async3RuleSet } from '../../oas-types';
|
|
11
|
+
|
|
12
|
+
export const rules: Async3RuleSet<'built-in'> = {
|
|
13
|
+
spec: Spec as Async3Rule,
|
|
14
|
+
assertions: Assertions as Async3Rule,
|
|
15
|
+
'info-contact': InfoContact as Async3Rule,
|
|
16
|
+
'operation-operationId': OperationOperationId as Async3Rule,
|
|
17
|
+
'channels-kebab-case': ChannelsKebabCase,
|
|
18
|
+
'no-channel-trailing-slash': NoChannelTrailingSlash,
|
|
19
|
+
'tag-description': TagDescription as Async3Rule,
|
|
20
|
+
'tags-alphabetical': TagsAlphabetical as Async3Rule,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const preprocessors = {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Async3Rule } from '../../visitors';
|
|
2
|
+
import { UserContext } from '../../walk';
|
|
3
|
+
import { Channel } from '../../typings/asyncapi3';
|
|
4
|
+
|
|
5
|
+
export const NoChannelTrailingSlash: Async3Rule = () => {
|
|
6
|
+
return {
|
|
7
|
+
Channel(channel: Channel, { report, location }: UserContext) {
|
|
8
|
+
if ((channel.address as string).endsWith('/') && channel.address !== '/') {
|
|
9
|
+
report({
|
|
10
|
+
message: `\`${channel.address}\` should not have a trailing slash.`,
|
|
11
|
+
location: location.key(),
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -607,4 +607,51 @@ describe('Oas3.1 spec', () => {
|
|
|
607
607
|
]
|
|
608
608
|
`);
|
|
609
609
|
});
|
|
610
|
+
|
|
611
|
+
it('should flag invalid dependentSchemas', async () => {
|
|
612
|
+
const document = parseYamlToDocument(
|
|
613
|
+
outdent`
|
|
614
|
+
openapi: 3.1.0
|
|
615
|
+
info:
|
|
616
|
+
version: 1.0.0
|
|
617
|
+
title: Example.com
|
|
618
|
+
description: info,
|
|
619
|
+
license:
|
|
620
|
+
name: Apache 2.0
|
|
621
|
+
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
|
|
622
|
+
components:
|
|
623
|
+
schemas:
|
|
624
|
+
withInvalidDependentSchemas:
|
|
625
|
+
dependentSchemas:
|
|
626
|
+
- invalid1
|
|
627
|
+
- invalid2
|
|
628
|
+
`,
|
|
629
|
+
'foobar.yaml'
|
|
630
|
+
);
|
|
631
|
+
|
|
632
|
+
const results = await lintDocument({
|
|
633
|
+
externalRefResolver: new BaseResolver(),
|
|
634
|
+
document,
|
|
635
|
+
config: await makeConfig({ spec: 'error' }),
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
|
|
639
|
+
[
|
|
640
|
+
{
|
|
641
|
+
"from": undefined,
|
|
642
|
+
"location": [
|
|
643
|
+
{
|
|
644
|
+
"pointer": "#/components/schemas/withInvalidDependentSchemas/dependentSchemas",
|
|
645
|
+
"reportOnKey": false,
|
|
646
|
+
"source": "foobar.yaml",
|
|
647
|
+
},
|
|
648
|
+
],
|
|
649
|
+
"message": "Expected type \`SchemaMap\` (object) but got \`array\`",
|
|
650
|
+
"ruleId": "spec",
|
|
651
|
+
"severity": "error",
|
|
652
|
+
"suggest": [],
|
|
653
|
+
},
|
|
654
|
+
]
|
|
655
|
+
`);
|
|
656
|
+
});
|
|
610
657
|
});
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import { asserts
|
|
1
|
+
import { asserts } from './asserts';
|
|
2
2
|
import { buildSubjectVisitor, buildVisitorObject } from './utils';
|
|
3
|
-
import { Oas2Visitor, Oas3Visitor } from '../../../visitors';
|
|
4
|
-
import { RuleSeverity } from '../../../config';
|
|
5
3
|
import { isString } from '../../../utils';
|
|
6
4
|
|
|
5
|
+
import type { AssertionFn } from './asserts';
|
|
6
|
+
import type {
|
|
7
|
+
ArazzoVisitor,
|
|
8
|
+
Async2Visitor,
|
|
9
|
+
Async3Visitor,
|
|
10
|
+
Oas2Visitor,
|
|
11
|
+
Oas3Visitor,
|
|
12
|
+
} from '../../../visitors';
|
|
13
|
+
import type { RuleSeverity } from '../../../config';
|
|
14
|
+
|
|
7
15
|
export type AssertionLocators = {
|
|
8
16
|
filterInParentKeys?: (string | number)[];
|
|
9
17
|
filterOutParentKeys?: (string | number)[];
|
|
@@ -28,7 +36,8 @@ export type RawAssertion = AssertionDefinition & {
|
|
|
28
36
|
export type Assertion = RawAssertion & { assertionId: string };
|
|
29
37
|
|
|
30
38
|
export const Assertions = (opts: Record<string, Assertion>) => {
|
|
31
|
-
const visitors: (Oas2Visitor | Oas3Visitor)[] =
|
|
39
|
+
const visitors: (Oas2Visitor | Oas3Visitor | Async2Visitor | Async3Visitor | ArazzoVisitor)[] =
|
|
40
|
+
[];
|
|
32
41
|
|
|
33
42
|
// As 'Assertions' has an array of asserts,
|
|
34
43
|
// that array spreads into an 'opts' object on init rules phase here
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { UserContext } from '../../walk';
|
|
2
|
-
import { Oas3_1Schema } from '../../typings/openapi';
|
|
3
1
|
import { getAdditionalPropertiesOption, validateExample } from '../utils';
|
|
4
2
|
|
|
3
|
+
import type { UserContext } from '../../walk';
|
|
4
|
+
import type { Oas3_1Schema } from '../../typings/openapi';
|
|
5
|
+
|
|
5
6
|
export const NoInvalidSchemaExamples: any = (opts: any) => {
|
|
6
7
|
const allowAdditionalProperties = getAdditionalPropertiesOption(opts) ?? false;
|
|
7
8
|
return {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import * as pluralize from 'pluralize';
|
|
1
2
|
import { Oas3Rule, Oas2Rule } from '../../visitors';
|
|
2
3
|
import { UserContext } from '../../walk';
|
|
3
|
-
import { isPathParameter
|
|
4
|
+
import { isPathParameter } from '../../utils';
|
|
4
5
|
|
|
5
6
|
export const PathSegmentPlural: Oas3Rule | Oas2Rule = (opts) => {
|
|
6
7
|
const { ignoreLastPathSegment, exceptions } = opts;
|
|
@@ -17,7 +18,7 @@ export const PathSegmentPlural: Oas3Rule | Oas2Rule = (opts) => {
|
|
|
17
18
|
|
|
18
19
|
for (const pathSegment of pathSegments) {
|
|
19
20
|
if (exceptions && exceptions.includes(pathSegment)) continue;
|
|
20
|
-
if (!isPathParameter(pathSegment) && isSingular(pathSegment)) {
|
|
21
|
+
if (!isPathParameter(pathSegment) && pluralize.isSingular(pathSegment)) {
|
|
21
22
|
report({
|
|
22
23
|
message: `path segment \`${pathSegment}\` should be plural.`,
|
|
23
24
|
location: location.key(),
|
package/src/rules/common/spec.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { Oas3Rule, Oas2Rule, Async2Rule, ArazzoRule } from '../../visitors';
|
|
1
|
+
import type { Oas3Rule, Oas2Rule, Async2Rule, Async3Rule, ArazzoRule } from '../../visitors';
|
|
2
2
|
import { isNamedType, SpecExtension } from '../../types';
|
|
3
3
|
import { oasTypeOf, matchesJsonSchemaType, getSuggest, validateSchemaEnumType } from '../utils';
|
|
4
4
|
import { isRef } from '../../ref-utils';
|
|
5
5
|
import { isPlainObject } from '../../utils';
|
|
6
6
|
import { UserContext } from '../../walk';
|
|
7
7
|
|
|
8
|
-
export const Spec: Oas3Rule | Oas2Rule | Async2Rule | ArazzoRule = () => {
|
|
8
|
+
export const Spec: Oas3Rule | Oas2Rule | Async2Rule | Async3Rule | ArazzoRule = () => {
|
|
9
9
|
return {
|
|
10
10
|
any(
|
|
11
11
|
node: any,
|
package/src/rules/oas2/index.ts
CHANGED
|
@@ -86,10 +86,10 @@ export const rules: Oas2RuleSet<'built-in'> = {
|
|
|
86
86
|
'path-segment-plural': PathSegmentPlural as Oas2Rule,
|
|
87
87
|
'response-contains-header': ResponseContainsHeader as Oas2Rule,
|
|
88
88
|
'response-contains-property': ResponseContainsProperty as Oas2Rule,
|
|
89
|
-
'scalar-property-missing-example': ScalarPropertyMissingExample,
|
|
90
|
-
'required-string-property-missing-min-length': RequiredStringPropertyMissingMinLength,
|
|
91
|
-
'spec-strict-refs': SpecStrictRefs,
|
|
92
|
-
'no-required-schema-properties-undefined': NoRequiredSchemaPropertiesUndefined,
|
|
89
|
+
'scalar-property-missing-example': ScalarPropertyMissingExample as Oas2Rule,
|
|
90
|
+
'required-string-property-missing-min-length': RequiredStringPropertyMissingMinLength as Oas2Rule,
|
|
91
|
+
'spec-strict-refs': SpecStrictRefs as Oas2Rule,
|
|
92
|
+
'no-required-schema-properties-undefined': NoRequiredSchemaPropertiesUndefined as Oas2Rule,
|
|
93
93
|
};
|
|
94
94
|
|
|
95
95
|
export const preprocessors = {};
|
package/src/rules/oas3/index.ts
CHANGED
|
@@ -55,63 +55,65 @@ import { ComponentNameUnique } from './component-name-unique';
|
|
|
55
55
|
import { ArrayParameterSerialization } from './array-parameter-serialization';
|
|
56
56
|
import { NoRequiredSchemaPropertiesUndefined } from '../common/no-required-schema-properties-undefined';
|
|
57
57
|
|
|
58
|
+
import type { Oas3Rule } from '../../visitors';
|
|
59
|
+
|
|
58
60
|
export const rules: Oas3RuleSet<'built-in'> = {
|
|
59
|
-
spec: Spec,
|
|
60
|
-
'info-contact': InfoContact,
|
|
61
|
-
'info-license': InfoLicense,
|
|
62
|
-
'info-license-url': InfoLicenseUrl,
|
|
63
|
-
'operation-2xx-response': Operation2xxResponse,
|
|
64
|
-
'operation-4xx-response': Operation4xxResponse,
|
|
61
|
+
spec: Spec as Oas3Rule,
|
|
62
|
+
'info-contact': InfoContact as Oas3Rule,
|
|
63
|
+
'info-license': InfoLicense as Oas3Rule,
|
|
64
|
+
'info-license-url': InfoLicenseUrl as Oas3Rule,
|
|
65
|
+
'operation-2xx-response': Operation2xxResponse as Oas3Rule,
|
|
66
|
+
'operation-4xx-response': Operation4xxResponse as Oas3Rule,
|
|
65
67
|
'operation-4xx-problem-details-rfc7807': Operation4xxProblemDetailsRfc7807,
|
|
66
|
-
assertions: Assertions,
|
|
67
|
-
'operation-operationId-unique': OperationIdUnique,
|
|
68
|
-
'operation-parameters-unique': OperationParametersUnique,
|
|
69
|
-
'operation-tag-defined': OperationTagDefined,
|
|
68
|
+
assertions: Assertions as Oas3Rule,
|
|
69
|
+
'operation-operationId-unique': OperationIdUnique as Oas3Rule,
|
|
70
|
+
'operation-parameters-unique': OperationParametersUnique as Oas3Rule,
|
|
71
|
+
'operation-tag-defined': OperationTagDefined as Oas3Rule,
|
|
70
72
|
'no-example-value-and-externalValue': NoExampleValueAndExternalValue,
|
|
71
|
-
'no-enum-type-mismatch': NoEnumTypeMismatch,
|
|
72
|
-
'no-path-trailing-slash': NoPathTrailingSlash,
|
|
73
|
+
'no-enum-type-mismatch': NoEnumTypeMismatch as Oas3Rule,
|
|
74
|
+
'no-path-trailing-slash': NoPathTrailingSlash as Oas3Rule,
|
|
73
75
|
'no-empty-servers': NoEmptyServers,
|
|
74
|
-
'path-declaration-must-exist': PathDeclarationMustExist,
|
|
75
|
-
'operation-operationId-url-safe': OperationIdUrlSafe,
|
|
76
|
-
'operation-operationId': OperationOperationId,
|
|
77
|
-
'operation-summary': OperationSummary,
|
|
78
|
-
'tags-alphabetical': TagsAlphabetical,
|
|
76
|
+
'path-declaration-must-exist': PathDeclarationMustExist as Oas3Rule,
|
|
77
|
+
'operation-operationId-url-safe': OperationIdUrlSafe as Oas3Rule,
|
|
78
|
+
'operation-operationId': OperationOperationId as Oas3Rule,
|
|
79
|
+
'operation-summary': OperationSummary as Oas3Rule,
|
|
80
|
+
'tags-alphabetical': TagsAlphabetical as Oas3Rule,
|
|
79
81
|
'no-server-example.com': NoServerExample,
|
|
80
82
|
'no-server-trailing-slash': NoServerTrailingSlash,
|
|
81
|
-
'tag-description': TagDescription,
|
|
82
|
-
'operation-description': OperationDescription,
|
|
83
|
+
'tag-description': TagDescription as Oas3Rule,
|
|
84
|
+
'operation-description': OperationDescription as Oas3Rule,
|
|
83
85
|
'no-unused-components': NoUnusedComponents,
|
|
84
|
-
'path-not-include-query': PathNotIncludeQuery,
|
|
85
|
-
'path-parameters-defined': PathParamsDefined,
|
|
86
|
-
'path-params-defined': PathParamsDefined,
|
|
87
|
-
'parameter-description': ParameterDescription,
|
|
88
|
-
'operation-singular-tag': OperationSingularTag,
|
|
89
|
-
'security-defined': SecurityDefined,
|
|
86
|
+
'path-not-include-query': PathNotIncludeQuery as Oas3Rule,
|
|
87
|
+
'path-parameters-defined': PathParamsDefined as Oas3Rule,
|
|
88
|
+
'path-params-defined': PathParamsDefined as Oas3Rule,
|
|
89
|
+
'parameter-description': ParameterDescription as Oas3Rule,
|
|
90
|
+
'operation-singular-tag': OperationSingularTag as Oas3Rule,
|
|
91
|
+
'security-defined': SecurityDefined as Oas3Rule,
|
|
90
92
|
'no-unresolved-refs': NoUnresolvedRefs,
|
|
91
|
-
'paths-kebab-case': PathsKebabCase,
|
|
93
|
+
'paths-kebab-case': PathsKebabCase as Oas3Rule,
|
|
92
94
|
'boolean-parameter-prefixes': BooleanParameterPrefixes,
|
|
93
|
-
'path-http-verbs-order': PathHttpVerbsOrder,
|
|
95
|
+
'path-http-verbs-order': PathHttpVerbsOrder as Oas3Rule,
|
|
94
96
|
'no-invalid-media-type-examples': ValidContentExamples,
|
|
95
|
-
'no-identical-paths': NoIdenticalPaths,
|
|
96
|
-
'no-ambiguous-paths': NoAmbiguousPaths,
|
|
97
|
+
'no-identical-paths': NoIdenticalPaths as Oas3Rule,
|
|
98
|
+
'no-ambiguous-paths': NoAmbiguousPaths as Oas3Rule,
|
|
97
99
|
'no-undefined-server-variable': NoUndefinedServerVariable,
|
|
98
100
|
'no-server-variables-empty-enum': NoServerVariablesEmptyEnum,
|
|
99
|
-
'no-http-verbs-in-paths': NoHttpVerbsInPaths,
|
|
100
|
-
'path-excludes-patterns': PathExcludesPatterns,
|
|
101
|
+
'no-http-verbs-in-paths': NoHttpVerbsInPaths as Oas3Rule,
|
|
102
|
+
'path-excludes-patterns': PathExcludesPatterns as Oas3Rule,
|
|
101
103
|
'request-mime-type': RequestMimeType,
|
|
102
104
|
'response-mime-type': ResponseMimeType,
|
|
103
|
-
'path-segment-plural': PathSegmentPlural,
|
|
105
|
+
'path-segment-plural': PathSegmentPlural as Oas3Rule,
|
|
104
106
|
'no-invalid-schema-examples': NoInvalidSchemaExamples,
|
|
105
107
|
'no-invalid-parameter-examples': NoInvalidParameterExamples,
|
|
106
|
-
'response-contains-header': ResponseContainsHeader,
|
|
108
|
+
'response-contains-header': ResponseContainsHeader as Oas3Rule,
|
|
107
109
|
'response-contains-property': ResponseContainsProperty,
|
|
108
|
-
'scalar-property-missing-example': ScalarPropertyMissingExample,
|
|
110
|
+
'scalar-property-missing-example': ScalarPropertyMissingExample as Oas3Rule,
|
|
109
111
|
'spec-components-invalid-map-name': SpecComponentsInvalidMapName,
|
|
110
112
|
'required-string-property-missing-min-length': RequiredStringPropertyMissingMinLength,
|
|
111
|
-
'spec-strict-refs': SpecStrictRefs,
|
|
112
|
-
'component-name-unique': ComponentNameUnique,
|
|
113
|
+
'spec-strict-refs': SpecStrictRefs as Oas3Rule,
|
|
114
|
+
'component-name-unique': ComponentNameUnique as Oas3Rule,
|
|
113
115
|
'array-parameter-serialization': ArrayParameterSerialization,
|
|
114
|
-
'no-required-schema-properties-undefined': NoRequiredSchemaPropertiesUndefined,
|
|
116
|
+
'no-required-schema-properties-undefined': NoRequiredSchemaPropertiesUndefined as Oas3Rule,
|
|
115
117
|
};
|
|
116
118
|
|
|
117
119
|
export const preprocessors = {};
|
package/src/types/arazzo.ts
CHANGED
|
@@ -4,11 +4,11 @@ import { getNodeTypesFromJSONSchema } from './json-schema-adapter';
|
|
|
4
4
|
|
|
5
5
|
export const ARAZZO_ROOT_TYPE = 'Root';
|
|
6
6
|
|
|
7
|
-
const operationMethod = {
|
|
7
|
+
export const operationMethod = {
|
|
8
8
|
type: 'string',
|
|
9
9
|
enum: ['get', 'post', 'put', 'delete', 'patch'],
|
|
10
10
|
} as const;
|
|
11
|
-
const expectSchema = {
|
|
11
|
+
export const expectSchema = {
|
|
12
12
|
type: 'object',
|
|
13
13
|
properties: {
|
|
14
14
|
statusCode: { type: 'number' },
|
|
@@ -58,7 +58,7 @@ const arazzoSourceDescriptionSchema = {
|
|
|
58
58
|
additionalProperties: false,
|
|
59
59
|
required: ['name', 'type', 'url'],
|
|
60
60
|
} as const;
|
|
61
|
-
const sourceDescriptionSchema = {
|
|
61
|
+
export const sourceDescriptionSchema = {
|
|
62
62
|
type: 'object',
|
|
63
63
|
oneOf: [
|
|
64
64
|
openAPISourceDescriptionSchema,
|
|
@@ -81,7 +81,7 @@ const extendedOperation = {
|
|
|
81
81
|
additionalProperties: false,
|
|
82
82
|
required: ['path', 'method'],
|
|
83
83
|
} as const;
|
|
84
|
-
const parameter = {
|
|
84
|
+
export const parameter = {
|
|
85
85
|
type: 'object',
|
|
86
86
|
oneOf: [
|
|
87
87
|
{
|
|
@@ -96,17 +96,6 @@ const parameter = {
|
|
|
96
96
|
required: ['name', 'value'],
|
|
97
97
|
additionalProperties: false,
|
|
98
98
|
},
|
|
99
|
-
{
|
|
100
|
-
type: 'object',
|
|
101
|
-
properties: {
|
|
102
|
-
$ref: { type: 'string' },
|
|
103
|
-
value: {
|
|
104
|
-
oneOf: [{ type: 'string' }, { type: 'number' }, { type: 'boolean' }],
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
required: ['$ref'],
|
|
108
|
-
additionalProperties: false,
|
|
109
|
-
},
|
|
110
99
|
{
|
|
111
100
|
type: 'object',
|
|
112
101
|
properties: {
|
|
@@ -124,7 +113,7 @@ const parameters = {
|
|
|
124
113
|
type: 'array',
|
|
125
114
|
items: parameter,
|
|
126
115
|
} as const;
|
|
127
|
-
const infoObject = {
|
|
116
|
+
export const infoObject = {
|
|
128
117
|
type: 'object',
|
|
129
118
|
properties: {
|
|
130
119
|
title: { type: 'string' },
|
|
@@ -135,7 +124,7 @@ const infoObject = {
|
|
|
135
124
|
additionalProperties: false,
|
|
136
125
|
required: ['title', 'version'],
|
|
137
126
|
} as const;
|
|
138
|
-
const replacement = {
|
|
127
|
+
export const replacement = {
|
|
139
128
|
type: 'object',
|
|
140
129
|
properties: {
|
|
141
130
|
target: { type: 'string' },
|
|
@@ -150,7 +139,7 @@ const replacement = {
|
|
|
150
139
|
},
|
|
151
140
|
},
|
|
152
141
|
} as const;
|
|
153
|
-
const requestBody = {
|
|
142
|
+
export const requestBody = {
|
|
154
143
|
type: 'object',
|
|
155
144
|
properties: {
|
|
156
145
|
contentType: { type: 'string' },
|
|
@@ -172,7 +161,7 @@ const requestBody = {
|
|
|
172
161
|
additionalProperties: false,
|
|
173
162
|
required: ['payload'],
|
|
174
163
|
} as const;
|
|
175
|
-
const criteriaObject = {
|
|
164
|
+
export const criteriaObject = {
|
|
176
165
|
type: 'object',
|
|
177
166
|
properties: {
|
|
178
167
|
condition: { type: 'string' },
|
|
@@ -204,7 +193,7 @@ const criteriaObjects = {
|
|
|
204
193
|
type: 'array',
|
|
205
194
|
items: criteriaObject,
|
|
206
195
|
} as const;
|
|
207
|
-
const inherit = {
|
|
196
|
+
export const inherit = {
|
|
208
197
|
type: 'string',
|
|
209
198
|
enum: ['auto', 'none'],
|
|
210
199
|
} as const;
|
|
@@ -242,7 +231,7 @@ const onFailureList = {
|
|
|
242
231
|
type: 'array',
|
|
243
232
|
items: onFailureObject,
|
|
244
233
|
} as const;
|
|
245
|
-
const step = {
|
|
234
|
+
export const step = {
|
|
246
235
|
type: 'object',
|
|
247
236
|
properties: {
|
|
248
237
|
stepId: { type: 'string' },
|
|
@@ -257,7 +246,23 @@ const step = {
|
|
|
257
246
|
outputs: {
|
|
258
247
|
type: 'object',
|
|
259
248
|
additionalProperties: {
|
|
260
|
-
|
|
249
|
+
oneOf: [
|
|
250
|
+
{
|
|
251
|
+
type: 'string',
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
type: 'object',
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
type: 'array',
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
type: 'boolean',
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
type: 'number',
|
|
264
|
+
},
|
|
265
|
+
],
|
|
261
266
|
},
|
|
262
267
|
},
|
|
263
268
|
'x-inherit': inherit,
|
|
@@ -301,7 +306,7 @@ const JSONSchema = {
|
|
|
301
306
|
required: ['type'],
|
|
302
307
|
additionalProperties: true,
|
|
303
308
|
} as const;
|
|
304
|
-
const workflow = {
|
|
309
|
+
export const workflow = {
|
|
305
310
|
type: 'object',
|
|
306
311
|
properties: {
|
|
307
312
|
workflowId: { type: 'string' },
|