@redocly/openapi-core 1.0.0-beta.105 → 1.0.0-beta.106
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/README.md +4 -4
- package/__tests__/utils.ts +5 -5
- package/lib/benchmark/benches/recommended-oas3.bench.js +1 -1
- package/lib/benchmark/utils.d.ts +2 -2
- package/lib/benchmark/utils.js +2 -2
- package/lib/bundle.d.ts +2 -2
- package/lib/bundle.js +2 -2
- package/lib/config/all.d.ts +2 -2
- package/lib/config/all.js +1 -1
- package/lib/config/builtIn.d.ts +2 -2
- package/lib/config/builtIn.js +2 -2
- package/lib/config/config-resolvers.d.ts +5 -5
- package/lib/config/config-resolvers.js +39 -36
- package/lib/config/config.d.ts +5 -5
- package/lib/config/config.js +4 -4
- package/lib/config/load.js +4 -4
- package/lib/config/minimal.d.ts +2 -2
- package/lib/config/minimal.js +1 -1
- package/lib/config/recommended.d.ts +2 -2
- package/lib/config/recommended.js +1 -1
- package/lib/config/rules.d.ts +2 -2
- package/lib/config/rules.js +1 -1
- package/lib/config/types.d.ts +23 -19
- package/lib/config/utils.d.ts +5 -5
- package/lib/config/utils.js +43 -26
- package/lib/decorators/common/remove-x-internal.js +2 -2
- package/lib/format/format.js +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +2 -2
- package/lib/js-yaml/index.js +1 -6
- package/lib/lint.d.ts +2 -2
- package/lib/lint.js +16 -6
- package/lib/redocly/registry-api.d.ts +1 -1
- package/lib/redocly/registry-api.js +2 -2
- package/lib/rules/common/info-license-url.d.ts +1 -1
- package/lib/rules/common/info-license-url.js +5 -10
- package/lib/rules/common/info-license.d.ts +2 -0
- package/lib/rules/common/info-license.js +17 -0
- package/lib/rules/common/no-enum-type-mismatch.js +1 -3
- package/lib/rules/common/operation-operationId.js +1 -1
- package/lib/rules/common/path-not-include-query.js +1 -1
- package/lib/rules/common/paths-kebab-case.js +4 -1
- package/lib/rules/common/spec.js +1 -1
- package/lib/rules/oas2/index.js +4 -4
- package/lib/rules/oas2/remove-unused-components.js +3 -3
- package/lib/rules/oas3/index.js +4 -4
- package/lib/rules/oas3/no-empty-servers.js +1 -1
- package/lib/rules/oas3/remove-unused-components.js +2 -2
- package/lib/rules/other/stats.js +43 -14
- package/lib/rules/utils.d.ts +1 -1
- package/lib/rules/utils.js +4 -1
- package/lib/types/index.d.ts +2 -2
- package/lib/types/redocly-yaml.js +8 -7
- package/package.json +1 -1
- package/src/__tests__/__snapshots__/bundle.test.ts.snap +141 -0
- package/src/__tests__/bundle.test.ts +68 -34
- package/src/__tests__/codeframes.test.ts +13 -14
- package/src/__tests__/js-yaml.test.ts +6 -4
- package/src/__tests__/lint.test.ts +74 -6
- package/src/__tests__/login.test.ts +2 -2
- package/src/__tests__/normalizeVisitors.test.ts +4 -4
- package/src/__tests__/ref-utils.test.ts +13 -13
- package/src/__tests__/resolve-http.test.ts +1 -1
- package/src/__tests__/resolve.test.ts +14 -11
- package/src/__tests__/walk.test.ts +48 -56
- package/src/benchmark/benches/lint-with-many-rules.bench.ts +1 -1
- package/src/benchmark/benches/lint-with-nested-rule.bench.ts +1 -1
- package/src/benchmark/benches/lint-with-no-rules.bench.ts +1 -1
- package/src/benchmark/benches/lint-with-top-level-rule-report.bench.ts +1 -1
- package/src/benchmark/benches/lint-with-top-level-rule.bench.ts +1 -1
- package/src/benchmark/benches/recommended-oas3.bench.ts +3 -3
- package/src/benchmark/benches/resolve-with-no-external.bench.ts +1 -1
- package/src/benchmark/benchmark.js +9 -5
- package/src/benchmark/utils.ts +5 -5
- package/src/bundle.ts +18 -17
- package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +1 -1
- package/src/config/__tests__/config-resolvers.test.ts +123 -121
- package/src/config/__tests__/config.test.ts +76 -76
- package/src/config/__tests__/fixtures/resolve-config/api/plugin.js +4 -2
- package/src/config/__tests__/fixtures/resolve-config/plugin.js +4 -1
- package/src/config/__tests__/resolve-plugins.test.ts +3 -3
- package/src/config/__tests__/utils.test.ts +83 -0
- package/src/config/all.ts +3 -4
- package/src/config/builtIn.ts +5 -5
- package/src/config/config-resolvers.ts +122 -83
- package/src/config/config.ts +5 -5
- package/src/config/load.ts +6 -6
- package/src/config/minimal.ts +3 -3
- package/src/config/recommended.ts +3 -3
- package/src/config/rules.ts +6 -6
- package/src/config/types.ts +28 -19
- package/src/config/utils.ts +70 -50
- package/src/decorators/__tests__/filter-out.test.ts +8 -4
- package/src/decorators/__tests__/remove-x-internal.test.ts +5 -5
- package/src/decorators/common/filters/filter-helper.ts +1 -1
- package/src/decorators/common/info-description-override.ts +1 -1
- package/src/decorators/common/operation-description-override.ts +1 -1
- package/src/decorators/common/remove-x-internal.ts +4 -4
- package/src/decorators/common/tag-description-override.ts +1 -1
- package/src/format/codeframes.ts +4 -4
- package/src/format/format.ts +10 -10
- package/src/index.ts +2 -3
- package/src/js-yaml/index.ts +3 -8
- package/src/lint.ts +22 -18
- package/src/oas-types.ts +1 -6
- package/src/redocly/__tests__/redocly-client.test.ts +25 -19
- package/src/redocly/index.ts +6 -4
- package/src/redocly/registry-api.ts +6 -6
- package/src/ref-utils.ts +2 -2
- package/src/resolve.ts +7 -4
- package/src/rules/__tests__/no-unresolved-refs.test.ts +4 -4
- package/src/rules/__tests__/utils.test.ts +122 -0
- package/src/rules/ajv.ts +3 -4
- package/src/rules/common/__tests__/info-description.test.ts +3 -3
- package/src/rules/common/__tests__/info-license.test.ts +2 -2
- package/src/rules/common/__tests__/license-url.test.ts +2 -2
- package/src/rules/common/__tests__/no-ambiguous-paths.test.ts +1 -1
- package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +8 -8
- package/src/rules/common/__tests__/no-identical-paths.test.ts +1 -1
- package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +3 -3
- package/src/rules/common/__tests__/operation-2xx-response.test.ts +3 -3
- package/src/rules/common/__tests__/operation-4xx-response.test.ts +3 -3
- package/src/rules/common/__tests__/operation-operationId-unique.test.ts +2 -2
- package/src/rules/common/__tests__/operation-operationId-url-safe.test.ts +1 -1
- package/src/rules/common/__tests__/operation-parameters-unique.test.ts +4 -4
- package/src/rules/common/__tests__/operation-security-defined.test.ts +2 -2
- package/src/rules/common/__tests__/operation-singular-tag.test.ts +2 -2
- package/src/rules/common/__tests__/path-http-verbs-order.test.ts +2 -2
- package/src/rules/common/__tests__/path-not-include-query.test.ts +2 -2
- package/src/rules/common/__tests__/path-params-defined.test.ts +3 -3
- package/src/rules/common/__tests__/paths-kebab-case.test.ts +15 -15
- package/src/rules/common/__tests__/scalar-property-missing-example.test.ts +8 -8
- package/src/rules/common/__tests__/spec.test.ts +2 -2
- package/src/rules/common/__tests__/tag-description.test.ts +2 -2
- package/src/rules/common/__tests__/tags-alphabetical.test.ts +2 -2
- package/src/rules/common/assertions/__tests__/asserts.test.ts +513 -130
- package/src/rules/common/assertions/index.ts +6 -6
- package/src/rules/common/info-license-url.ts +4 -9
- package/src/rules/common/info-license.ts +15 -0
- package/src/rules/common/no-ambiguous-paths.ts +1 -1
- package/src/rules/common/no-enum-type-mismatch.ts +12 -9
- package/src/rules/common/no-invalid-parameter-examples.ts +2 -2
- package/src/rules/common/no-invalid-schema-examples.ts +1 -1
- package/src/rules/common/operation-operationId.ts +1 -1
- package/src/rules/common/operation-parameters-unique.ts +2 -2
- package/src/rules/common/path-not-include-query.ts +1 -1
- package/src/rules/common/path-params-defined.ts +1 -1
- package/src/rules/common/paths-kebab-case.ts +4 -1
- package/src/rules/common/scalar-property-missing-example.ts +1 -1
- package/src/rules/common/spec.ts +10 -7
- package/src/rules/no-unresolved-refs.ts +1 -1
- package/src/rules/oas2/__tests__/boolean-parameter-prefixes.test.ts +3 -3
- package/src/rules/oas2/__tests__/spec/info.test.ts +12 -12
- package/src/rules/oas2/__tests__/spec/operation.test.ts +4 -4
- package/src/rules/oas2/__tests__/spec/paths.test.ts +10 -10
- package/src/rules/oas2/__tests__/spec/referenceableScalars.test.ts +6 -2
- package/src/rules/oas2/__tests__/spec/utils.ts +6 -6
- package/src/rules/oas2/index.ts +3 -3
- package/src/rules/oas2/remove-unused-components.ts +13 -8
- package/src/rules/oas3/__tests__/boolean-parameter-prefixes.test.ts +3 -3
- package/src/rules/oas3/__tests__/no-example-value-and-externalValue.test.ts +2 -2
- package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +8 -8
- package/src/rules/oas3/__tests__/no-server-example.com.test.ts +2 -2
- package/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts +3 -3
- package/src/rules/oas3/__tests__/no-unused-components.test.ts +1 -1
- package/src/rules/oas3/__tests__/spec/callbacks.test.ts +1 -1
- package/src/rules/oas3/__tests__/spec/info.test.ts +12 -12
- package/src/rules/oas3/__tests__/spec/operation.test.ts +8 -8
- package/src/rules/oas3/__tests__/spec/paths.test.ts +10 -10
- package/src/rules/oas3/__tests__/spec/referenceableScalars.test.ts +12 -12
- package/src/rules/oas3/__tests__/spec/servers.test.ts +15 -15
- package/src/rules/oas3/__tests__/spec/spec.test.ts +6 -6
- package/src/rules/oas3/__tests__/spec/utils.ts +6 -6
- package/src/rules/oas3/index.ts +3 -3
- package/src/rules/oas3/no-empty-servers.ts +1 -1
- package/src/rules/oas3/no-invalid-media-type-examples.ts +12 -4
- package/src/rules/oas3/no-servers-empty-enum.ts +9 -10
- package/src/rules/oas3/remove-unused-components.ts +18 -7
- package/src/rules/other/stats.ts +46 -17
- package/src/rules/utils.ts +5 -3
- package/src/types/index.ts +5 -5
- package/src/types/redocly-yaml.ts +8 -7
- package/src/typings/common.ts +9 -1
- package/src/typings/openapi.ts +1 -1
- package/src/visitors.ts +4 -4
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/rules/common/license-url.d.ts +0 -2
- package/lib/rules/common/license-url.js +0 -12
- package/src/rules/common/license-url.ts +0 -10
|
@@ -59,55 +59,57 @@ describe('RedoclyClient', () => {
|
|
|
59
59
|
|
|
60
60
|
it('should resolve all tokens', async () => {
|
|
61
61
|
let spy = jest.spyOn(RedoclyClient.prototype, 'readCredentialsFile').mockImplementation(() => {
|
|
62
|
-
return { token:
|
|
62
|
+
return { token: 'accessToken', us: 'accessToken', eu: 'eu-accessToken' };
|
|
63
63
|
});
|
|
64
64
|
const client = new RedoclyClient();
|
|
65
65
|
const tokens = client.getAllTokens();
|
|
66
66
|
expect(tokens).toStrictEqual([
|
|
67
67
|
{ region: 'us', token: 'accessToken' },
|
|
68
|
-
{ region: 'eu', token: 'eu-accessToken' }
|
|
68
|
+
{ region: 'eu', token: 'eu-accessToken' },
|
|
69
69
|
]);
|
|
70
70
|
spy.mockRestore();
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
it('should resolve valid tokens data', async () => {
|
|
74
74
|
let spy = jest.spyOn(RedoclyClient.prototype, 'readCredentialsFile').mockImplementation(() => {
|
|
75
|
-
return { us:
|
|
75
|
+
return { us: 'accessToken', eu: 'eu-accessToken' };
|
|
76
76
|
});
|
|
77
77
|
const client = new RedoclyClient();
|
|
78
78
|
const tokens = await client.getValidTokens();
|
|
79
79
|
expect(tokens).toStrictEqual([
|
|
80
80
|
{ region: 'us', token: 'accessToken', valid: true },
|
|
81
|
-
{ region: 'eu', token: 'eu-accessToken', valid: true }
|
|
81
|
+
{ region: 'eu', token: 'eu-accessToken', valid: true },
|
|
82
82
|
]);
|
|
83
83
|
spy.mockRestore();
|
|
84
84
|
});
|
|
85
85
|
|
|
86
86
|
it('should not call setAccessTokens by default', () => {
|
|
87
|
-
let spy = jest
|
|
87
|
+
let spy = jest
|
|
88
|
+
.spyOn(RedoclyClient.prototype, 'readCredentialsFile')
|
|
89
|
+
.mockImplementation(() => ({}));
|
|
88
90
|
jest.spyOn(RedoclyClient.prototype, 'setAccessTokens').mockImplementation();
|
|
89
91
|
const client = new RedoclyClient();
|
|
90
|
-
expect(client.setAccessTokens).not.toHaveBeenCalled()
|
|
92
|
+
expect(client.setAccessTokens).not.toHaveBeenCalled();
|
|
91
93
|
spy.mockRestore();
|
|
92
94
|
});
|
|
93
95
|
|
|
94
96
|
it('should set correct accessTokens - backward compatibility: default US region', () => {
|
|
95
|
-
let spy = jest
|
|
97
|
+
let spy = jest
|
|
98
|
+
.spyOn(RedoclyClient.prototype, 'readCredentialsFile')
|
|
99
|
+
.mockImplementation(() => ({ token: testToken }));
|
|
96
100
|
jest.spyOn(RedoclyClient.prototype, 'setAccessTokens').mockImplementation();
|
|
97
101
|
const client = new RedoclyClient();
|
|
98
|
-
expect(client.setAccessTokens).toBeCalledWith(
|
|
99
|
-
expect.objectContaining({ us: testToken })
|
|
100
|
-
);
|
|
102
|
+
expect(client.setAccessTokens).toBeCalledWith(expect.objectContaining({ us: testToken }));
|
|
101
103
|
spy.mockRestore();
|
|
102
104
|
});
|
|
103
105
|
|
|
104
106
|
it('should set correct accessTokens - backward compatibility: EU region', () => {
|
|
105
|
-
let spy = jest
|
|
107
|
+
let spy = jest
|
|
108
|
+
.spyOn(RedoclyClient.prototype, 'readCredentialsFile')
|
|
109
|
+
.mockImplementation(() => ({ token: testToken }));
|
|
106
110
|
jest.spyOn(RedoclyClient.prototype, 'setAccessTokens').mockImplementation();
|
|
107
111
|
const client = new RedoclyClient('eu');
|
|
108
|
-
expect(client.setAccessTokens).toBeCalledWith(
|
|
109
|
-
expect.objectContaining({ eu: testToken })
|
|
110
|
-
);
|
|
112
|
+
expect(client.setAccessTokens).toBeCalledWith(expect.objectContaining({ eu: testToken }));
|
|
111
113
|
spy.mockRestore();
|
|
112
114
|
});
|
|
113
115
|
|
|
@@ -116,25 +118,29 @@ describe('RedoclyClient', () => {
|
|
|
116
118
|
let spy = jest.spyOn(RedoclyClient.prototype, 'readCredentialsFile').mockImplementation();
|
|
117
119
|
jest.spyOn(RedoclyClient.prototype, 'setAccessTokens').mockImplementation();
|
|
118
120
|
const client = new RedoclyClient();
|
|
119
|
-
expect(client.setAccessTokens).toHaveBeenNthCalledWith(1, {
|
|
121
|
+
expect(client.setAccessTokens).toHaveBeenNthCalledWith(1, { us: REDOCLY_AUTHORIZATION_TOKEN });
|
|
120
122
|
spy.mockRestore();
|
|
121
123
|
});
|
|
122
124
|
|
|
123
125
|
it('should set correct accessTokens prioritizing REDOCLY_AUTHORIZATION env over token in file', () => {
|
|
124
126
|
process.env.REDOCLY_AUTHORIZATION = REDOCLY_AUTHORIZATION_TOKEN;
|
|
125
|
-
let spy = jest
|
|
127
|
+
let spy = jest
|
|
128
|
+
.spyOn(RedoclyClient.prototype, 'readCredentialsFile')
|
|
129
|
+
.mockImplementation(() => ({ token: testToken }));
|
|
126
130
|
jest.spyOn(RedoclyClient.prototype, 'setAccessTokens').mockImplementation();
|
|
127
131
|
const client = new RedoclyClient();
|
|
128
|
-
expect(client.setAccessTokens).toHaveBeenNthCalledWith(2, {
|
|
132
|
+
expect(client.setAccessTokens).toHaveBeenNthCalledWith(2, { us: REDOCLY_AUTHORIZATION_TOKEN });
|
|
129
133
|
spy.mockRestore();
|
|
130
134
|
});
|
|
131
135
|
|
|
132
136
|
it('should set correct accessTokens prioritizing REDOCLY_AUTHORIZATION env over EU token', () => {
|
|
133
137
|
process.env.REDOCLY_AUTHORIZATION = REDOCLY_AUTHORIZATION_TOKEN;
|
|
134
|
-
let spy = jest
|
|
138
|
+
let spy = jest
|
|
139
|
+
.spyOn(RedoclyClient.prototype, 'readCredentialsFile')
|
|
140
|
+
.mockImplementation(() => ({ us: testToken }));
|
|
135
141
|
jest.spyOn(RedoclyClient.prototype, 'setAccessTokens').mockImplementation();
|
|
136
142
|
const client = new RedoclyClient('eu');
|
|
137
|
-
expect(client.setAccessTokens).toHaveBeenNthCalledWith(2, {
|
|
143
|
+
expect(client.setAccessTokens).toHaveBeenNthCalledWith(2, { eu: REDOCLY_AUTHORIZATION_TOKEN });
|
|
138
144
|
spy.mockRestore();
|
|
139
145
|
});
|
|
140
146
|
});
|
package/src/redocly/index.ts
CHANGED
|
@@ -28,12 +28,14 @@ export class RedoclyClient {
|
|
|
28
28
|
|
|
29
29
|
loadRegion(region?: Region) {
|
|
30
30
|
if (region && !DOMAINS[region]) {
|
|
31
|
-
throw new Error(
|
|
31
|
+
throw new Error(
|
|
32
|
+
`Invalid argument: region in config file.\nGiven: ${green(region)}, choices: "us", "eu".`
|
|
33
|
+
);
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
if (env.REDOCLY_DOMAIN) {
|
|
35
37
|
return (AVAILABLE_REGIONS.find(
|
|
36
|
-
(region) => DOMAINS[region as Region] === env.REDOCLY_DOMAIN
|
|
38
|
+
(region) => DOMAINS[region as Region] === env.REDOCLY_DOMAIN
|
|
37
39
|
) || DEFAULT_REGION) as Region;
|
|
38
40
|
}
|
|
39
41
|
return region || DEFAULT_REGION;
|
|
@@ -91,7 +93,7 @@ export class RedoclyClient {
|
|
|
91
93
|
const allTokens = this.getAllTokens();
|
|
92
94
|
|
|
93
95
|
const verifiedTokens = await Promise.allSettled(
|
|
94
|
-
allTokens.map(({ token, region }) => this.verifyToken(token, region))
|
|
96
|
+
allTokens.map(({ token, region }) => this.verifyToken(token, region))
|
|
95
97
|
);
|
|
96
98
|
|
|
97
99
|
return allTokens
|
|
@@ -134,7 +136,7 @@ export class RedoclyClient {
|
|
|
134
136
|
async verifyToken(
|
|
135
137
|
accessToken: string,
|
|
136
138
|
region: Region,
|
|
137
|
-
verbose: boolean = false
|
|
139
|
+
verbose: boolean = false
|
|
138
140
|
): Promise<{ viewerId: string; organizations: string[] }> {
|
|
139
141
|
return this.registryApi.authStatus(accessToken, region, verbose);
|
|
140
142
|
}
|
|
@@ -31,7 +31,7 @@ export class RegistryApi {
|
|
|
31
31
|
|
|
32
32
|
const response = await fetch(
|
|
33
33
|
`${this.getBaseUrl(region)}${path}`,
|
|
34
|
-
Object.assign({}, options, { headers })
|
|
34
|
+
Object.assign({}, options, { headers })
|
|
35
35
|
);
|
|
36
36
|
|
|
37
37
|
if (response.status === 401) {
|
|
@@ -49,7 +49,7 @@ export class RegistryApi {
|
|
|
49
49
|
async authStatus(
|
|
50
50
|
accessToken: string,
|
|
51
51
|
region: Region,
|
|
52
|
-
verbose = false
|
|
52
|
+
verbose = false
|
|
53
53
|
): Promise<{ viewerId: string; organizations: string[] }> {
|
|
54
54
|
try {
|
|
55
55
|
const response = await this.request('', { headers: { authorization: accessToken } }, region);
|
|
@@ -86,7 +86,7 @@ export class RegistryApi {
|
|
|
86
86
|
isUpsert,
|
|
87
87
|
}),
|
|
88
88
|
},
|
|
89
|
-
this.region
|
|
89
|
+
this.region
|
|
90
90
|
);
|
|
91
91
|
|
|
92
92
|
if (response.ok) {
|
|
@@ -106,7 +106,7 @@ export class RegistryApi {
|
|
|
106
106
|
isUpsert,
|
|
107
107
|
isPublic,
|
|
108
108
|
batchId,
|
|
109
|
-
batchSize
|
|
109
|
+
batchSize,
|
|
110
110
|
}: RegistryApiTypes.PushApiParams) {
|
|
111
111
|
const response = await this.request(
|
|
112
112
|
`/${organizationId}/${name}/${version}`,
|
|
@@ -123,10 +123,10 @@ export class RegistryApi {
|
|
|
123
123
|
isUpsert,
|
|
124
124
|
isPublic,
|
|
125
125
|
batchId,
|
|
126
|
-
batchSize
|
|
126
|
+
batchSize,
|
|
127
127
|
}),
|
|
128
128
|
},
|
|
129
|
-
this.region
|
|
129
|
+
this.region
|
|
130
130
|
);
|
|
131
131
|
|
|
132
132
|
if (response.ok) {
|
package/src/ref-utils.ts
CHANGED
|
@@ -18,8 +18,8 @@ export class Location {
|
|
|
18
18
|
this.source,
|
|
19
19
|
joinPointer(
|
|
20
20
|
this.pointer,
|
|
21
|
-
(Array.isArray(components) ? components : [components]).map(escapePointer).join('/')
|
|
22
|
-
)
|
|
21
|
+
(Array.isArray(components) ? components : [components]).map(escapePointer).join('/')
|
|
22
|
+
)
|
|
23
23
|
);
|
|
24
24
|
}
|
|
25
25
|
|
package/src/resolve.ts
CHANGED
|
@@ -232,7 +232,7 @@ export async function resolveDocument(opts: {
|
|
|
232
232
|
rootNode: any,
|
|
233
233
|
rootNodeDocument: Document,
|
|
234
234
|
rootNodePointer: string,
|
|
235
|
-
type: any
|
|
235
|
+
type: any
|
|
236
236
|
) {
|
|
237
237
|
const rootNodeDocAbsoluteRef = rootNodeDocument.source.absoluteRef;
|
|
238
238
|
|
|
@@ -295,7 +295,7 @@ export async function resolveDocument(opts: {
|
|
|
295
295
|
resolvedRef.node,
|
|
296
296
|
resolvedRef.document,
|
|
297
297
|
resolvedRef.nodePointer!,
|
|
298
|
-
type
|
|
298
|
+
type
|
|
299
299
|
);
|
|
300
300
|
}
|
|
301
301
|
});
|
|
@@ -306,7 +306,7 @@ export async function resolveDocument(opts: {
|
|
|
306
306
|
async function followRef(
|
|
307
307
|
document: Document,
|
|
308
308
|
ref: OasRef,
|
|
309
|
-
refStack: RefFrame
|
|
309
|
+
refStack: RefFrame
|
|
310
310
|
): Promise<ResolvedRef> {
|
|
311
311
|
if (hasRef(refStack.prev, ref)) {
|
|
312
312
|
throw new Error('Self-referencing circular pointer');
|
|
@@ -316,7 +316,10 @@ export async function resolveDocument(opts: {
|
|
|
316
316
|
let targetDoc: Document;
|
|
317
317
|
try {
|
|
318
318
|
targetDoc = isRemote
|
|
319
|
-
? ((await externalRefResolver.resolveDocument(
|
|
319
|
+
? ((await externalRefResolver.resolveDocument(
|
|
320
|
+
document.source.absoluteRef,
|
|
321
|
+
uri!
|
|
322
|
+
)) as Document)
|
|
320
323
|
: document;
|
|
321
324
|
} catch (error) {
|
|
322
325
|
const resolvedRef = {
|
|
@@ -15,7 +15,7 @@ describe('oas3 boolean-parameter-prefixes', () => {
|
|
|
15
15
|
requestBody:
|
|
16
16
|
$ref: 'invalid.yaml'
|
|
17
17
|
`,
|
|
18
|
-
path.join(__dirname, 'foobar.yaml')
|
|
18
|
+
path.join(__dirname, 'foobar.yaml')
|
|
19
19
|
);
|
|
20
20
|
|
|
21
21
|
const results = await lintDocument({
|
|
@@ -55,7 +55,7 @@ describe('oas3 boolean-parameter-prefixes', () => {
|
|
|
55
55
|
requestBody:
|
|
56
56
|
$ref: 'fixtures/invalid-yaml.yaml'
|
|
57
57
|
`,
|
|
58
|
-
path.join(__dirname, 'foobar.yaml')
|
|
58
|
+
path.join(__dirname, 'foobar.yaml')
|
|
59
59
|
);
|
|
60
60
|
|
|
61
61
|
const results = await lintDocument({
|
|
@@ -112,7 +112,7 @@ describe('oas3 boolean-parameter-prefixes', () => {
|
|
|
112
112
|
requestBody:
|
|
113
113
|
$ref: 'fixtures/ref.yaml'
|
|
114
114
|
`,
|
|
115
|
-
path.join(__dirname, 'foobar.yaml')
|
|
115
|
+
path.join(__dirname, 'foobar.yaml')
|
|
116
116
|
);
|
|
117
117
|
|
|
118
118
|
const results = await lintDocument({
|
|
@@ -136,7 +136,7 @@ describe('oas3 boolean-parameter-prefixes', () => {
|
|
|
136
136
|
requestBody:
|
|
137
137
|
$ref: '#/components/requestBodies/a'
|
|
138
138
|
`,
|
|
139
|
-
path.join(__dirname, 'foobar.yaml')
|
|
139
|
+
path.join(__dirname, 'foobar.yaml')
|
|
140
140
|
);
|
|
141
141
|
|
|
142
142
|
const results = await lintDocument({
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { fieldNonEmpty, matchesJsonSchemaType, missingRequiredField, oasTypeOf } from '../utils';
|
|
2
|
+
|
|
3
|
+
describe('field-non-empty', () => {
|
|
4
|
+
it('should match expected message', () => {
|
|
5
|
+
const message = fieldNonEmpty('Car', 'color');
|
|
6
|
+
expect(message).toBe('Car object `color` must be non-empty string.');
|
|
7
|
+
});
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
describe('matches-json-schema-type', () => {
|
|
11
|
+
it('should report true on a null value with nullable type', () => {
|
|
12
|
+
const results = matchesJsonSchemaType(null, 'string', true);
|
|
13
|
+
expect(results).toBe(true);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('should report true on a value and type integer', () => {
|
|
17
|
+
const results = matchesJsonSchemaType(123, 'integer', false);
|
|
18
|
+
expect(results).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should report false when the value is not integer and type is integer', () => {
|
|
22
|
+
const results = matchesJsonSchemaType(3.14, 'integer', false);
|
|
23
|
+
expect(results).toBe(false);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should report true when the value is a number and type is number', () => {
|
|
27
|
+
const results = matchesJsonSchemaType(3.14, 'number', false);
|
|
28
|
+
expect(results).toBe(true);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should report true when the value is an integer and type is number', () => {
|
|
32
|
+
const results = matchesJsonSchemaType(3, 'number', false);
|
|
33
|
+
expect(results).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should report true when the value is true and type is boolean', () => {
|
|
37
|
+
const results = matchesJsonSchemaType(true, 'boolean', false);
|
|
38
|
+
expect(results).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should report true when the value is false and type is boolean', () => {
|
|
42
|
+
const results = matchesJsonSchemaType(false, 'boolean', false);
|
|
43
|
+
expect(results).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should report true when the value is a string and type is boolean', () => {
|
|
47
|
+
const results = matchesJsonSchemaType('test', 'boolean', false);
|
|
48
|
+
expect(results).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should report true on an array value with array type', () => {
|
|
52
|
+
const results = matchesJsonSchemaType(['foo', 'bar'], 'array', false);
|
|
53
|
+
expect(results).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('should report false on an array value with object type', () => {
|
|
57
|
+
const results = matchesJsonSchemaType(['foo', 'bar'], 'object', false);
|
|
58
|
+
expect(results).toBe(false);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should report true on an object value with object type', () => {
|
|
62
|
+
const car = { type: 'Fiat', model: '500', color: 'white' };
|
|
63
|
+
const results = matchesJsonSchemaType(car, 'object', true);
|
|
64
|
+
expect(results).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should report false on an object value with array type', () => {
|
|
68
|
+
const car = { type: 'Fiat', model: '500', color: 'white' };
|
|
69
|
+
const results = matchesJsonSchemaType(car, 'array', true);
|
|
70
|
+
expect(results).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe('missing-required-field', () => {
|
|
75
|
+
it('should match expected message for missing required field', () => {
|
|
76
|
+
const message = missingRequiredField('Car', 'color');
|
|
77
|
+
expect(message).toBe('Car object should contain `color` field.');
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('oas-type-of', () => {
|
|
82
|
+
it('should report the correct oas type for a string', () => {
|
|
83
|
+
const results = oasTypeOf('word');
|
|
84
|
+
expect(results).toBe('string');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should report the correct oas type for an integer', () => {
|
|
88
|
+
const results = oasTypeOf(123);
|
|
89
|
+
expect(results).toBe('integer');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should report the correct oas type for a number', () => {
|
|
93
|
+
const results = oasTypeOf(3.14);
|
|
94
|
+
expect(results).toBe('number');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should report the correct oas type for a null value', () => {
|
|
98
|
+
const results = oasTypeOf(null);
|
|
99
|
+
expect(results).toBe('null');
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should report the correct oas type for a true boolean', () => {
|
|
103
|
+
const results = oasTypeOf(true);
|
|
104
|
+
expect(results).toBe('boolean');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('should report the correct oas type for a false boolean', () => {
|
|
108
|
+
const results = oasTypeOf(false);
|
|
109
|
+
expect(results).toBe('boolean');
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('should report the correct oas type for an array', () => {
|
|
113
|
+
const results = oasTypeOf(['foo', 'bar']);
|
|
114
|
+
expect(results).toBe('array');
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should report the correct oas type for an object', () => {
|
|
118
|
+
const car = { type: 'Fiat', model: '500', color: 'white' };
|
|
119
|
+
const results = oasTypeOf(car);
|
|
120
|
+
expect(results).toBe('object');
|
|
121
|
+
});
|
|
122
|
+
});
|
package/src/rules/ajv.ts
CHANGED
|
@@ -36,7 +36,7 @@ function getAjvValidator(
|
|
|
36
36
|
schema: any,
|
|
37
37
|
loc: Location,
|
|
38
38
|
resolve: ResolveFn,
|
|
39
|
-
disallowAdditionalProperties: boolean
|
|
39
|
+
disallowAdditionalProperties: boolean
|
|
40
40
|
): ValidateFunction | undefined {
|
|
41
41
|
const ajv = getAjv(resolve, disallowAdditionalProperties);
|
|
42
42
|
|
|
@@ -53,7 +53,7 @@ export function validateJsonSchema(
|
|
|
53
53
|
schemaLoc: Location,
|
|
54
54
|
instancePath: string,
|
|
55
55
|
resolve: ResolveFn,
|
|
56
|
-
disallowAdditionalProperties: boolean
|
|
56
|
+
disallowAdditionalProperties: boolean
|
|
57
57
|
): { valid: boolean; errors: (ErrorObject & { suggest?: string[] })[] } {
|
|
58
58
|
const validate = getAjvValidator(schema, schemaLoc, resolve, disallowAdditionalProperties);
|
|
59
59
|
if (!validate) return { valid: true, errors: [] }; // unresolved refs are reported
|
|
@@ -73,8 +73,7 @@ export function validateJsonSchema(
|
|
|
73
73
|
|
|
74
74
|
function beatifyErrorMessage(error: ErrorObject) {
|
|
75
75
|
let message = error.message;
|
|
76
|
-
let suggest =
|
|
77
|
-
error.keyword === 'enum' ? error.params.allowedValues : undefined;
|
|
76
|
+
let suggest = error.keyword === 'enum' ? error.params.allowedValues : undefined;
|
|
78
77
|
if (suggest) {
|
|
79
78
|
message += ` ${suggest.map((e: any) => `"${e}"`).join(', ')}`;
|
|
80
79
|
}
|
|
@@ -11,7 +11,7 @@ describe('Oas3 info-description', () => {
|
|
|
11
11
|
info:
|
|
12
12
|
version: '1.0'
|
|
13
13
|
`,
|
|
14
|
-
'foobar.yaml'
|
|
14
|
+
'foobar.yaml'
|
|
15
15
|
);
|
|
16
16
|
|
|
17
17
|
const results = await lintDocument({
|
|
@@ -49,7 +49,7 @@ describe('Oas3 info-description', () => {
|
|
|
49
49
|
version: '1.0'
|
|
50
50
|
description: ''
|
|
51
51
|
`,
|
|
52
|
-
'foobar.yaml'
|
|
52
|
+
'foobar.yaml'
|
|
53
53
|
);
|
|
54
54
|
|
|
55
55
|
const results = await lintDocument({
|
|
@@ -86,7 +86,7 @@ describe('Oas3 info-description', () => {
|
|
|
86
86
|
info:
|
|
87
87
|
description: test description
|
|
88
88
|
`,
|
|
89
|
-
'foobar.yaml'
|
|
89
|
+
'foobar.yaml'
|
|
90
90
|
);
|
|
91
91
|
|
|
92
92
|
const results = await lintDocument({
|
|
@@ -11,7 +11,7 @@ describe('Oas3 info-license', () => {
|
|
|
11
11
|
info:
|
|
12
12
|
version: '1.0'
|
|
13
13
|
`,
|
|
14
|
-
'foobar.yaml'
|
|
14
|
+
'foobar.yaml'
|
|
15
15
|
);
|
|
16
16
|
|
|
17
17
|
const results = await lintDocument({
|
|
@@ -48,7 +48,7 @@ describe('Oas3 info-license', () => {
|
|
|
48
48
|
name: MIT
|
|
49
49
|
url: google.com
|
|
50
50
|
`,
|
|
51
|
-
'foobar.yaml'
|
|
51
|
+
'foobar.yaml'
|
|
52
52
|
);
|
|
53
53
|
|
|
54
54
|
const results = await lintDocument({
|
|
@@ -12,7 +12,7 @@ describe('Oas3 license-url', () => {
|
|
|
12
12
|
license:
|
|
13
13
|
name: MIT
|
|
14
14
|
`,
|
|
15
|
-
'foobar.yaml'
|
|
15
|
+
'foobar.yaml'
|
|
16
16
|
);
|
|
17
17
|
|
|
18
18
|
const results = await lintDocument({
|
|
@@ -49,7 +49,7 @@ describe('Oas3 license-url', () => {
|
|
|
49
49
|
name: MIT
|
|
50
50
|
url: google.com
|
|
51
51
|
`,
|
|
52
|
-
'foobar.yaml'
|
|
52
|
+
'foobar.yaml'
|
|
53
53
|
);
|
|
54
54
|
|
|
55
55
|
const results = await lintDocument({
|
|
@@ -23,7 +23,7 @@ describe('Oas3 typed enum', () => {
|
|
|
23
23
|
- 2
|
|
24
24
|
- 3
|
|
25
25
|
`,
|
|
26
|
-
'foobar.yaml'
|
|
26
|
+
'foobar.yaml'
|
|
27
27
|
);
|
|
28
28
|
|
|
29
29
|
const results = await lintDocument({
|
|
@@ -56,7 +56,7 @@ describe('Oas3 typed enum', () => {
|
|
|
56
56
|
- C
|
|
57
57
|
- null
|
|
58
58
|
`,
|
|
59
|
-
'foobar.yaml'
|
|
59
|
+
'foobar.yaml'
|
|
60
60
|
);
|
|
61
61
|
|
|
62
62
|
const results = await lintDocument({
|
|
@@ -86,7 +86,7 @@ describe('Oas3 typed enum', () => {
|
|
|
86
86
|
- string
|
|
87
87
|
- 3
|
|
88
88
|
`,
|
|
89
|
-
'foobar.yaml'
|
|
89
|
+
'foobar.yaml'
|
|
90
90
|
);
|
|
91
91
|
|
|
92
92
|
const results = await lintDocument({
|
|
@@ -114,7 +114,7 @@ describe('Oas3 typed enum', () => {
|
|
|
114
114
|
`);
|
|
115
115
|
});
|
|
116
116
|
|
|
117
|
-
it(
|
|
117
|
+
it("should report on enum object, 'string' value in enum does not have allowed types", async () => {
|
|
118
118
|
const document = parseYamlToDocument(
|
|
119
119
|
outdent`
|
|
120
120
|
openapi: 3.1.0
|
|
@@ -134,7 +134,7 @@ describe('Oas3 typed enum', () => {
|
|
|
134
134
|
- string
|
|
135
135
|
- 3
|
|
136
136
|
`,
|
|
137
|
-
'foobar.yaml'
|
|
137
|
+
'foobar.yaml'
|
|
138
138
|
);
|
|
139
139
|
|
|
140
140
|
const results = await lintDocument({
|
|
@@ -153,7 +153,7 @@ describe('Oas3 typed enum', () => {
|
|
|
153
153
|
"source": "foobar.yaml",
|
|
154
154
|
},
|
|
155
155
|
],
|
|
156
|
-
"message": "Enum value \`string\` must be of
|
|
156
|
+
"message": "Enum value \`string\` must be of allowed types: \`integer,array\`.",
|
|
157
157
|
"ruleId": "no-enum-type-mismatch",
|
|
158
158
|
"severity": "error",
|
|
159
159
|
"suggest": Array [],
|
|
@@ -179,13 +179,13 @@ describe('Oas3 typed enum', () => {
|
|
|
179
179
|
application/json:
|
|
180
180
|
schema: null
|
|
181
181
|
`,
|
|
182
|
-
'foobar.yaml'
|
|
182
|
+
'foobar.yaml'
|
|
183
183
|
);
|
|
184
184
|
|
|
185
185
|
const results = await lintDocument({
|
|
186
186
|
externalRefResolver: new BaseResolver(),
|
|
187
187
|
document,
|
|
188
|
-
config: await makeConfig({
|
|
188
|
+
config: await makeConfig({ spec: 'error', 'no-enum-type-mismatch': 'error' }),
|
|
189
189
|
});
|
|
190
190
|
|
|
191
191
|
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
|
|
@@ -13,7 +13,7 @@ describe('no-path-trailing-slash', () => {
|
|
|
13
13
|
get:
|
|
14
14
|
summary: List all pets
|
|
15
15
|
`,
|
|
16
|
-
'foobar.yaml'
|
|
16
|
+
'foobar.yaml'
|
|
17
17
|
);
|
|
18
18
|
|
|
19
19
|
const results = await lintDocument({
|
|
@@ -50,7 +50,7 @@ describe('no-path-trailing-slash', () => {
|
|
|
50
50
|
get:
|
|
51
51
|
summary: List all pets
|
|
52
52
|
`,
|
|
53
|
-
'foobar.yaml'
|
|
53
|
+
'foobar.yaml'
|
|
54
54
|
);
|
|
55
55
|
|
|
56
56
|
const results = await lintDocument({
|
|
@@ -71,7 +71,7 @@ describe('no-path-trailing-slash', () => {
|
|
|
71
71
|
get:
|
|
72
72
|
summary: List all pets
|
|
73
73
|
`,
|
|
74
|
-
'foobar.yaml'
|
|
74
|
+
'foobar.yaml'
|
|
75
75
|
);
|
|
76
76
|
|
|
77
77
|
const results = await lintDocument({
|
|
@@ -15,7 +15,7 @@ describe('Oas3 operation-2xx-response', () => {
|
|
|
15
15
|
400:
|
|
16
16
|
description: bad response
|
|
17
17
|
`,
|
|
18
|
-
'foobar.yaml'
|
|
18
|
+
'foobar.yaml'
|
|
19
19
|
);
|
|
20
20
|
|
|
21
21
|
const results = await lintDocument({
|
|
@@ -54,7 +54,7 @@ describe('Oas3 operation-2xx-response', () => {
|
|
|
54
54
|
200:
|
|
55
55
|
description: ok
|
|
56
56
|
`,
|
|
57
|
-
'foobar.yaml'
|
|
57
|
+
'foobar.yaml'
|
|
58
58
|
);
|
|
59
59
|
|
|
60
60
|
const results = await lintDocument({
|
|
@@ -77,7 +77,7 @@ describe('Oas3 operation-2xx-response', () => {
|
|
|
77
77
|
default:
|
|
78
78
|
description: ok
|
|
79
79
|
`,
|
|
80
|
-
'foobar.yaml'
|
|
80
|
+
'foobar.yaml'
|
|
81
81
|
);
|
|
82
82
|
|
|
83
83
|
const results = await lintDocument({
|
|
@@ -15,7 +15,7 @@ describe('Oas3 operation-4xx-response', () => {
|
|
|
15
15
|
200:
|
|
16
16
|
description: ok response
|
|
17
17
|
`,
|
|
18
|
-
'foobar.yaml'
|
|
18
|
+
'foobar.yaml'
|
|
19
19
|
);
|
|
20
20
|
|
|
21
21
|
const results = await lintDocument({
|
|
@@ -54,7 +54,7 @@ describe('Oas3 operation-4xx-response', () => {
|
|
|
54
54
|
400:
|
|
55
55
|
description: error response
|
|
56
56
|
`,
|
|
57
|
-
'foobar.yaml'
|
|
57
|
+
'foobar.yaml'
|
|
58
58
|
);
|
|
59
59
|
|
|
60
60
|
const results = await lintDocument({
|
|
@@ -77,7 +77,7 @@ describe('Oas3 operation-4xx-response', () => {
|
|
|
77
77
|
default:
|
|
78
78
|
description: some default response
|
|
79
79
|
`,
|
|
80
|
-
'foobar.yaml'
|
|
80
|
+
'foobar.yaml'
|
|
81
81
|
);
|
|
82
82
|
|
|
83
83
|
const results = await lintDocument({
|