@redocly/openapi-core 1.14.0 → 1.16.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 +16 -0
- package/lib/bundle.js +2 -2
- package/lib/config/config.d.ts +0 -6
- package/lib/config/config.js +1 -19
- package/lib/config/load.js +2 -2
- package/lib/decorators/common/registry-dependencies.js +2 -2
- package/lib/index.d.ts +3 -2
- package/lib/index.js +17 -2
- package/lib/redocly/domains.d.ts +14 -0
- package/lib/redocly/domains.js +41 -0
- package/lib/redocly/index.d.ts +1 -2
- package/lib/redocly/index.js +14 -24
- package/lib/redocly/registry-api.d.ts +2 -2
- package/lib/redocly/registry-api.js +9 -9
- package/lib/rules/common/no-invalid-parameter-examples.js +1 -1
- package/lib/rules/common/no-invalid-schema-examples.js +1 -1
- package/lib/rules/oas3/no-invalid-media-type-examples.js +1 -1
- package/lib/types/redocly-yaml.d.ts +0 -1
- package/lib/types/redocly-yaml.js +3 -7
- package/lib/utils.d.ts +2 -0
- package/lib/utils.js +7 -1
- package/package.json +5 -3
- package/src/__tests__/lint.test.ts +15 -36
- package/src/bundle.ts +1 -1
- package/src/config/__tests__/load.test.ts +13 -13
- package/src/config/config.ts +1 -23
- package/src/config/load.ts +2 -1
- package/src/decorators/common/registry-dependencies.ts +1 -1
- package/src/index.ts +4 -1
- package/src/redocly/__tests__/domains.test.ts +52 -0
- package/src/redocly/__tests__/redocly-client.test.ts +5 -3
- package/src/redocly/domains.ts +48 -0
- package/src/redocly/index.ts +14 -24
- package/src/redocly/registry-api.ts +25 -31
- package/src/rules/common/__tests__/no-invalid-parameter-examples.test.ts +53 -0
- package/src/rules/common/__tests__/no-invalid-schema-examples.test.ts +51 -0
- package/src/rules/common/no-invalid-parameter-examples.ts +1 -1
- package/src/rules/common/no-invalid-schema-examples.ts +1 -1
- package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +52 -0
- package/src/rules/oas3/no-invalid-media-type-examples.ts +1 -1
- package/src/types/redocly-yaml.ts +3 -13
- package/src/utils.ts +7 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -369,26 +369,8 @@ describe('lint', () => {
|
|
|
369
369
|
min: 3
|
|
370
370
|
theme:
|
|
371
371
|
openapi:
|
|
372
|
-
showConsole: true
|
|
373
|
-
layout:
|
|
374
|
-
scope: section
|
|
375
|
-
routingStrategy: browser
|
|
376
|
-
theme:
|
|
377
|
-
rightPanel:
|
|
378
|
-
backgroundColor: '#263238'
|
|
379
|
-
links:
|
|
380
|
-
color: '#6CC496'
|
|
381
|
-
theme:
|
|
382
|
-
openapi:
|
|
383
|
-
showConsole: true
|
|
384
|
-
layout:
|
|
385
|
-
scope: section
|
|
386
|
-
routingStrategy: browser
|
|
387
|
-
theme:
|
|
388
|
-
rightPanel:
|
|
389
|
-
backgroundColor: '#263238'
|
|
390
|
-
links:
|
|
391
|
-
color: '#6CC496'
|
|
372
|
+
showConsole: true # Not expected anymore
|
|
373
|
+
layout: wrong-option
|
|
392
374
|
`,
|
|
393
375
|
''
|
|
394
376
|
);
|
|
@@ -414,12 +396,12 @@ describe('lint', () => {
|
|
|
414
396
|
"from": undefined,
|
|
415
397
|
"location": [
|
|
416
398
|
{
|
|
417
|
-
"pointer": "#/theme/openapi/
|
|
418
|
-
"reportOnKey":
|
|
399
|
+
"pointer": "#/theme/openapi/showConsole",
|
|
400
|
+
"reportOnKey": true,
|
|
419
401
|
"source": "",
|
|
420
402
|
},
|
|
421
403
|
],
|
|
422
|
-
"message": "\`
|
|
404
|
+
"message": "Property \`showConsole\` is not expected here.",
|
|
423
405
|
"ruleId": "configuration spec",
|
|
424
406
|
"severity": "error",
|
|
425
407
|
"suggest": [],
|
|
@@ -428,18 +410,15 @@ describe('lint', () => {
|
|
|
428
410
|
"from": undefined,
|
|
429
411
|
"location": [
|
|
430
412
|
{
|
|
431
|
-
"pointer": "#/theme/openapi/
|
|
432
|
-
"reportOnKey":
|
|
413
|
+
"pointer": "#/theme/openapi/layout",
|
|
414
|
+
"reportOnKey": false,
|
|
433
415
|
"source": "",
|
|
434
416
|
},
|
|
435
417
|
],
|
|
436
|
-
"message": "
|
|
418
|
+
"message": "\`layout\` can be one of the following only: "stacked", "three-panel".",
|
|
437
419
|
"ruleId": "configuration spec",
|
|
438
420
|
"severity": "error",
|
|
439
|
-
"suggest": [
|
|
440
|
-
"schema",
|
|
441
|
-
"shape",
|
|
442
|
-
],
|
|
421
|
+
"suggest": [],
|
|
443
422
|
},
|
|
444
423
|
]
|
|
445
424
|
`);
|
|
@@ -806,12 +785,12 @@ describe('lint', () => {
|
|
|
806
785
|
"from": undefined,
|
|
807
786
|
"location": [
|
|
808
787
|
{
|
|
809
|
-
"pointer": "#/apis/with-theme/theme/
|
|
810
|
-
"reportOnKey":
|
|
788
|
+
"pointer": "#/apis/with-theme/theme/not-expected",
|
|
789
|
+
"reportOnKey": true,
|
|
811
790
|
"source": "",
|
|
812
791
|
},
|
|
813
792
|
],
|
|
814
|
-
"message": "
|
|
793
|
+
"message": "Property \`not-expected\` is not expected here.",
|
|
815
794
|
"ruleId": "configuration spec",
|
|
816
795
|
"severity": "error",
|
|
817
796
|
"suggest": [],
|
|
@@ -820,12 +799,12 @@ describe('lint', () => {
|
|
|
820
799
|
"from": undefined,
|
|
821
800
|
"location": [
|
|
822
801
|
{
|
|
823
|
-
"pointer": "#/apis/with-theme/theme/
|
|
824
|
-
"reportOnKey":
|
|
802
|
+
"pointer": "#/apis/with-theme/theme/openapi",
|
|
803
|
+
"reportOnKey": false,
|
|
825
804
|
"source": "",
|
|
826
805
|
},
|
|
827
806
|
],
|
|
828
|
-
"message": "
|
|
807
|
+
"message": "Expected type \`rootRedoclyConfigSchema.apis_additionalProperties.theme.openapi\` (object) but got \`string\`",
|
|
829
808
|
"ruleId": "configuration spec",
|
|
830
809
|
"severity": "error",
|
|
831
810
|
"suggest": [],
|
package/src/bundle.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { isAbsoluteUrl, isRef, Location, refBaseName } from './ref-utils';
|
|
|
14
14
|
import { initRules } from './config/rules';
|
|
15
15
|
import { reportUnresolvedRef } from './rules/no-unresolved-refs';
|
|
16
16
|
import { isPlainObject, isTruthy } from './utils';
|
|
17
|
-
import { isRedoclyRegistryURL } from './redocly';
|
|
17
|
+
import { isRedoclyRegistryURL } from './redocly/domains';
|
|
18
18
|
import { RemoveUnusedComponents as RemoveUnusedComponentsOas2 } from './decorators/oas2/remove-unused-components';
|
|
19
19
|
import { RemoveUnusedComponents as RemoveUnusedComponentsOas3 } from './decorators/oas3/remove-unused-components';
|
|
20
20
|
import { ConfigTypes } from './types/redocly-yaml';
|
|
@@ -149,19 +149,6 @@ describe('getConfig', () => {
|
|
|
149
149
|
"severity": "warn",
|
|
150
150
|
"suggest": [],
|
|
151
151
|
},
|
|
152
|
-
{
|
|
153
|
-
"location": [
|
|
154
|
-
{
|
|
155
|
-
"pointer": "#/theme",
|
|
156
|
-
"reportOnKey": false,
|
|
157
|
-
"source": "fixtures/resolve-refs-in-config/config-with-refs.yaml",
|
|
158
|
-
},
|
|
159
|
-
],
|
|
160
|
-
"message": "Can't resolve $ref: ENOENT: no such file or directory 'fixtures/resolve-refs-in-config/wrong-ref.yaml'",
|
|
161
|
-
"ruleId": "configuration no-unresolved-refs",
|
|
162
|
-
"severity": "warn",
|
|
163
|
-
"suggest": [],
|
|
164
|
-
},
|
|
165
152
|
{
|
|
166
153
|
"from": {
|
|
167
154
|
"pointer": "#/rules",
|
|
@@ -179,6 +166,19 @@ describe('getConfig', () => {
|
|
|
179
166
|
"severity": "warn",
|
|
180
167
|
"suggest": [],
|
|
181
168
|
},
|
|
169
|
+
{
|
|
170
|
+
"location": [
|
|
171
|
+
{
|
|
172
|
+
"pointer": "#/theme",
|
|
173
|
+
"reportOnKey": false,
|
|
174
|
+
"source": "fixtures/resolve-refs-in-config/config-with-refs.yaml",
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
"message": "Can't resolve $ref: ENOENT: no such file or directory 'fixtures/resolve-refs-in-config/wrong-ref.yaml'",
|
|
178
|
+
"ruleId": "configuration no-unresolved-refs",
|
|
179
|
+
"severity": "warn",
|
|
180
|
+
"suggest": [],
|
|
181
|
+
},
|
|
182
182
|
]
|
|
183
183
|
`);
|
|
184
184
|
});
|
package/src/config/config.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
Oas3RuleSet,
|
|
11
11
|
Async2RuleSet,
|
|
12
12
|
} from '../oas-types';
|
|
13
|
-
import { isBrowser
|
|
13
|
+
import { isBrowser } from '../env';
|
|
14
14
|
|
|
15
15
|
import type { NodeType } from '../types';
|
|
16
16
|
import type {
|
|
@@ -35,25 +35,6 @@ const IGNORE_BANNER =
|
|
|
35
35
|
`# This file instructs Redocly's linter to ignore the rules contained for specific parts of your API.\n` +
|
|
36
36
|
`# See https://redoc.ly/docs/cli/ for more information.\n`;
|
|
37
37
|
|
|
38
|
-
export const DEFAULT_REGION = 'us';
|
|
39
|
-
|
|
40
|
-
function getDomains() {
|
|
41
|
-
const domains: { [region in Region]: string } = {
|
|
42
|
-
us: 'redocly.com',
|
|
43
|
-
eu: 'eu.redocly.com',
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// FIXME: temporary fix for our lab environments
|
|
47
|
-
const domain = env.REDOCLY_DOMAIN;
|
|
48
|
-
if (domain?.endsWith('.redocly.host')) {
|
|
49
|
-
domains[domain.split('.')[0] as Region] = domain;
|
|
50
|
-
}
|
|
51
|
-
if (domain === 'redoc.online') {
|
|
52
|
-
domains[domain as Region] = domain;
|
|
53
|
-
}
|
|
54
|
-
return domains;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
38
|
function getIgnoreFilePath(configFile?: string): string | undefined {
|
|
58
39
|
if (configFile) {
|
|
59
40
|
return doesYamlFileExist(configFile)
|
|
@@ -64,9 +45,6 @@ function getIgnoreFilePath(configFile?: string): string | undefined {
|
|
|
64
45
|
}
|
|
65
46
|
}
|
|
66
47
|
|
|
67
|
-
export const DOMAINS = getDomains();
|
|
68
|
-
export const AVAILABLE_REGIONS = Object.keys(DOMAINS) as Region[];
|
|
69
|
-
|
|
70
48
|
export class StyleguideConfig {
|
|
71
49
|
plugins: Plugin[];
|
|
72
50
|
ignore: Record<string, Record<string, Set<string>>> = {};
|
package/src/config/load.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as path from 'path';
|
|
|
3
3
|
import { RedoclyClient } from '../redocly';
|
|
4
4
|
import { isEmptyObject } from '../utils';
|
|
5
5
|
import { parseYaml } from '../js-yaml';
|
|
6
|
-
import { Config
|
|
6
|
+
import { Config } from './config';
|
|
7
7
|
import { ConfigValidationError, transformConfig } from './utils';
|
|
8
8
|
import { resolveConfig, resolveConfigFileAndRefs } from './config-resolvers';
|
|
9
9
|
import { bundleConfig } from '../bundle';
|
|
@@ -14,6 +14,7 @@ import type { Document } from '../resolve';
|
|
|
14
14
|
import type { RegionalToken, RegionalTokenWithValidity } from '../redocly/redocly-client-types';
|
|
15
15
|
import type { RawConfig, RawUniversalConfig, Region } from './types';
|
|
16
16
|
import type { ResolvedRefMap } from '../resolve';
|
|
17
|
+
import { DOMAINS } from '../redocly/domains';
|
|
17
18
|
|
|
18
19
|
async function addConfigMetadata({
|
|
19
20
|
rawConfig,
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ export {
|
|
|
4
4
|
slash,
|
|
5
5
|
doesYamlFileExist,
|
|
6
6
|
isTruthy,
|
|
7
|
+
getProxyAgent,
|
|
7
8
|
pause,
|
|
8
9
|
} from './utils';
|
|
9
10
|
export { Oas3_1Types } from './types/oas3_1';
|
|
@@ -48,7 +49,9 @@ export {
|
|
|
48
49
|
ResolvedApi,
|
|
49
50
|
} from './config';
|
|
50
51
|
|
|
51
|
-
export { RedoclyClient
|
|
52
|
+
export { RedoclyClient } from './redocly';
|
|
53
|
+
|
|
54
|
+
export * from './redocly/domains';
|
|
52
55
|
|
|
53
56
|
export {
|
|
54
57
|
Source,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { RedoclyClient } from '../../index';
|
|
2
|
+
import { setRedoclyDomain, getRedoclyDomain, getDomains, AVAILABLE_REGIONS } from '../domains';
|
|
3
|
+
|
|
4
|
+
describe('domains', () => {
|
|
5
|
+
const REDOCLY_DOMAIN_US = 'redocly.com';
|
|
6
|
+
const TEST_DOMAIN = 'redoclyDomain.com';
|
|
7
|
+
const TEST_LAB_DOMAIN = 'lab.redocly.host';
|
|
8
|
+
const TEST_REDOC_ONLINE_DOMAIN = 'redoc.online';
|
|
9
|
+
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
delete process.env.REDOCLY_DOMAIN;
|
|
12
|
+
setRedoclyDomain('');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should resolve the US domain by default', () => {
|
|
16
|
+
expect(getRedoclyDomain()).toBe(REDOCLY_DOMAIN_US);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should resolve the US and EU regions by default', () => {
|
|
20
|
+
expect(AVAILABLE_REGIONS).toStrictEqual(['us', 'eu']);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should resolve the specified domain if used with setter', () => {
|
|
24
|
+
setRedoclyDomain(TEST_DOMAIN);
|
|
25
|
+
expect(getRedoclyDomain()).toBe(TEST_DOMAIN);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should resolve the specified domain provided in environmental variable, after initializing RedoclyClient', () => {
|
|
29
|
+
process.env.REDOCLY_DOMAIN = TEST_DOMAIN;
|
|
30
|
+
const client = new RedoclyClient();
|
|
31
|
+
expect(getRedoclyDomain()).toBe(TEST_DOMAIN);
|
|
32
|
+
expect(client.domain).toBe(TEST_DOMAIN);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should return correct object when redocly domain is set to lab env', () => {
|
|
36
|
+
setRedoclyDomain(TEST_LAB_DOMAIN);
|
|
37
|
+
const domains = getDomains();
|
|
38
|
+
expect(domains).toEqual({ us: 'redocly.com', eu: 'eu.redocly.com', lab: 'lab.redocly.host' });
|
|
39
|
+
expect(getRedoclyDomain()).toBe(TEST_LAB_DOMAIN);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should return correct object when redocly domain is set to redoc.online env', () => {
|
|
43
|
+
setRedoclyDomain(TEST_REDOC_ONLINE_DOMAIN);
|
|
44
|
+
const domains = getDomains();
|
|
45
|
+
expect(domains).toEqual({
|
|
46
|
+
us: 'redocly.com',
|
|
47
|
+
eu: 'eu.redocly.com',
|
|
48
|
+
'redoc.online': 'redoc.online',
|
|
49
|
+
});
|
|
50
|
+
expect(getRedoclyDomain()).toBe(TEST_REDOC_ONLINE_DOMAIN);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { setRedoclyDomain } from '../domains';
|
|
1
2
|
import { RedoclyClient } from '../index';
|
|
2
3
|
|
|
3
4
|
jest.mock('node-fetch', () => ({
|
|
@@ -16,6 +17,7 @@ describe('RedoclyClient', () => {
|
|
|
16
17
|
|
|
17
18
|
afterEach(() => {
|
|
18
19
|
delete process.env.REDOCLY_DOMAIN;
|
|
20
|
+
setRedoclyDomain('');
|
|
19
21
|
});
|
|
20
22
|
|
|
21
23
|
it('should resolve the US domain by default', () => {
|
|
@@ -40,19 +42,19 @@ describe('RedoclyClient', () => {
|
|
|
40
42
|
});
|
|
41
43
|
|
|
42
44
|
it('should resolve domain by EU region prioritizing flag over env variable', () => {
|
|
43
|
-
|
|
45
|
+
setRedoclyDomain(testRedoclyDomain);
|
|
44
46
|
const client = new RedoclyClient('eu');
|
|
45
47
|
expect(client.domain).toBe(REDOCLY_DOMAIN_EU);
|
|
46
48
|
});
|
|
47
49
|
|
|
48
50
|
it('should resolve domain by US region prioritizing flag over env variable', () => {
|
|
49
|
-
|
|
51
|
+
setRedoclyDomain(testRedoclyDomain);
|
|
50
52
|
const client = new RedoclyClient('us');
|
|
51
53
|
expect(client.domain).toBe(REDOCLY_DOMAIN_US);
|
|
52
54
|
});
|
|
53
55
|
|
|
54
56
|
it('should resolve domain by US region when REDOCLY_DOMAIN consists EU domain', () => {
|
|
55
|
-
|
|
57
|
+
setRedoclyDomain(REDOCLY_DOMAIN_EU);
|
|
56
58
|
const client = new RedoclyClient();
|
|
57
59
|
expect(client.getRegion()).toBe('eu');
|
|
58
60
|
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Region } from '../config/types';
|
|
2
|
+
|
|
3
|
+
let redoclyDomain = 'redocly.com';
|
|
4
|
+
|
|
5
|
+
export const DEFAULT_REGION = 'us';
|
|
6
|
+
|
|
7
|
+
export const DOMAINS = getDomains();
|
|
8
|
+
export const AVAILABLE_REGIONS = Object.keys(DOMAINS) as Region[];
|
|
9
|
+
|
|
10
|
+
export function getDomains() {
|
|
11
|
+
const domains: { [region in Region]: string } = {
|
|
12
|
+
us: 'redocly.com',
|
|
13
|
+
eu: 'eu.redocly.com',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// FIXME: temporary fix for our lab environments
|
|
17
|
+
const domain = redoclyDomain;
|
|
18
|
+
if (domain?.endsWith('.redocly.host')) {
|
|
19
|
+
domains[domain.split('.')[0] as Region] = domain;
|
|
20
|
+
}
|
|
21
|
+
if (domain === 'redoc.online') {
|
|
22
|
+
domains[domain as Region] = domain;
|
|
23
|
+
}
|
|
24
|
+
return domains;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function setRedoclyDomain(domain: string) {
|
|
28
|
+
redoclyDomain = domain;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function getRedoclyDomain(): string {
|
|
32
|
+
return redoclyDomain;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function isRedoclyRegistryURL(link: string): boolean {
|
|
36
|
+
const domain = getRedoclyDomain() || DOMAINS[DEFAULT_REGION];
|
|
37
|
+
|
|
38
|
+
const legacyDomain = domain === 'redocly.com' ? 'redoc.ly' : domain;
|
|
39
|
+
|
|
40
|
+
if (
|
|
41
|
+
!link.startsWith(`https://api.${domain}/registry/`) &&
|
|
42
|
+
!link.startsWith(`https://api.${legacyDomain}/registry/`)
|
|
43
|
+
) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return true;
|
|
48
|
+
}
|
package/src/redocly/index.ts
CHANGED
|
@@ -2,13 +2,19 @@ import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'fs';
|
|
|
2
2
|
import { resolve } from 'path';
|
|
3
3
|
import { homedir } from 'os';
|
|
4
4
|
import { RegistryApi } from './registry-api';
|
|
5
|
-
import { DEFAULT_REGION, DOMAINS, AVAILABLE_REGIONS } from '../config/config';
|
|
6
5
|
import { env } from '../env';
|
|
7
6
|
import { RegionalToken, RegionalTokenWithValidity } from './redocly-client-types';
|
|
8
7
|
import { isNotEmptyObject } from '../utils';
|
|
9
8
|
import { colorize } from '../logger';
|
|
10
9
|
|
|
11
10
|
import type { AccessTokens, Region } from '../config/types';
|
|
11
|
+
import {
|
|
12
|
+
AVAILABLE_REGIONS,
|
|
13
|
+
DEFAULT_REGION,
|
|
14
|
+
DOMAINS,
|
|
15
|
+
getRedoclyDomain,
|
|
16
|
+
setRedoclyDomain,
|
|
17
|
+
} from './domains';
|
|
12
18
|
|
|
13
19
|
export const TOKEN_FILENAME = '.redocly-config.json';
|
|
14
20
|
|
|
@@ -23,7 +29,7 @@ export class RedoclyClient {
|
|
|
23
29
|
this.loadTokens();
|
|
24
30
|
this.domain = region ? DOMAINS[region] : env.REDOCLY_DOMAIN || DOMAINS[DEFAULT_REGION];
|
|
25
31
|
|
|
26
|
-
|
|
32
|
+
setRedoclyDomain(this.domain);
|
|
27
33
|
this.registryApi = new RegistryApi(this.accessTokens, this.region);
|
|
28
34
|
}
|
|
29
35
|
|
|
@@ -36,9 +42,9 @@ export class RedoclyClient {
|
|
|
36
42
|
);
|
|
37
43
|
}
|
|
38
44
|
|
|
39
|
-
if (
|
|
45
|
+
if (getRedoclyDomain()) {
|
|
40
46
|
return (AVAILABLE_REGIONS.find(
|
|
41
|
-
(region) => DOMAINS[region as Region] ===
|
|
47
|
+
(region) => DOMAINS[region as Region] === getRedoclyDomain()
|
|
42
48
|
) || DEFAULT_REGION) as Region;
|
|
43
49
|
}
|
|
44
50
|
return region || DEFAULT_REGION;
|
|
@@ -96,7 +102,7 @@ export class RedoclyClient {
|
|
|
96
102
|
const allTokens = this.getAllTokens();
|
|
97
103
|
|
|
98
104
|
const verifiedTokens = await Promise.allSettled(
|
|
99
|
-
allTokens.map(({ token
|
|
105
|
+
allTokens.map(({ token }) => this.verifyToken(token))
|
|
100
106
|
);
|
|
101
107
|
|
|
102
108
|
return allTokens
|
|
@@ -120,7 +126,7 @@ export class RedoclyClient {
|
|
|
120
126
|
}
|
|
121
127
|
|
|
122
128
|
try {
|
|
123
|
-
await this.verifyToken(accessToken
|
|
129
|
+
await this.verifyToken(accessToken);
|
|
124
130
|
|
|
125
131
|
return true;
|
|
126
132
|
} catch (err) {
|
|
@@ -138,17 +144,16 @@ export class RedoclyClient {
|
|
|
138
144
|
|
|
139
145
|
async verifyToken(
|
|
140
146
|
accessToken: string,
|
|
141
|
-
region: Region,
|
|
142
147
|
verbose: boolean = false
|
|
143
148
|
): Promise<{ viewerId: string; organizations: string[] }> {
|
|
144
|
-
return this.registryApi.authStatus(accessToken,
|
|
149
|
+
return this.registryApi.authStatus(accessToken, verbose);
|
|
145
150
|
}
|
|
146
151
|
|
|
147
152
|
async login(accessToken: string, verbose: boolean = false) {
|
|
148
153
|
const credentialsPath = resolve(homedir(), TOKEN_FILENAME);
|
|
149
154
|
|
|
150
155
|
try {
|
|
151
|
-
await this.verifyToken(accessToken,
|
|
156
|
+
await this.verifyToken(accessToken, verbose);
|
|
152
157
|
} catch (err) {
|
|
153
158
|
throw new Error('Authorization failed. Please check if you entered a valid API key.');
|
|
154
159
|
}
|
|
@@ -170,18 +175,3 @@ export class RedoclyClient {
|
|
|
170
175
|
}
|
|
171
176
|
}
|
|
172
177
|
}
|
|
173
|
-
|
|
174
|
-
export function isRedoclyRegistryURL(link: string): boolean {
|
|
175
|
-
const domain = env.REDOCLY_DOMAIN || DOMAINS[DEFAULT_REGION];
|
|
176
|
-
|
|
177
|
-
const legacyDomain = domain === 'redocly.com' ? 'redoc.ly' : domain;
|
|
178
|
-
|
|
179
|
-
if (
|
|
180
|
-
!link.startsWith(`https://api.${domain}/registry/`) &&
|
|
181
|
-
!link.startsWith(`https://api.${legacyDomain}/registry/`)
|
|
182
|
-
) {
|
|
183
|
-
return false;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return true;
|
|
187
|
-
}
|
|
@@ -6,8 +6,8 @@ import type {
|
|
|
6
6
|
PushApiParams,
|
|
7
7
|
} from './registry-api-types';
|
|
8
8
|
import type { AccessTokens, Region } from '../config/types';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { getProxyAgent, isNotEmptyObject } from '../utils';
|
|
10
|
+
import { getRedoclyDomain } from './domains';
|
|
11
11
|
|
|
12
12
|
const version = require('../../package.json').version;
|
|
13
13
|
|
|
@@ -18,8 +18,8 @@ export class RegistryApi {
|
|
|
18
18
|
return isNotEmptyObject(this.accessTokens) && this.accessTokens[this.region];
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
getBaseUrl(
|
|
22
|
-
return `https://api.${
|
|
21
|
+
getBaseUrl() {
|
|
22
|
+
return `https://api.${getRedoclyDomain()}/registry`;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
setAccessTokens(accessTokens: AccessTokens) {
|
|
@@ -27,7 +27,7 @@ export class RegistryApi {
|
|
|
27
27
|
return this;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
private async request(path = '', options: RequestInit = {}
|
|
30
|
+
private async request(path = '', options: RequestInit = {}) {
|
|
31
31
|
const currentCommand =
|
|
32
32
|
typeof process !== 'undefined' ? process.env?.REDOCLY_CLI_COMMAND || '' : '';
|
|
33
33
|
const redoclyEnv = typeof process !== 'undefined' ? process.env?.REDOCLY_ENVIRONMENT || '' : '';
|
|
@@ -42,8 +42,8 @@ export class RegistryApi {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
const response = await fetch(
|
|
45
|
-
`${this.getBaseUrl(
|
|
46
|
-
Object.assign({}, options, { headers })
|
|
45
|
+
`${this.getBaseUrl()}${path}`,
|
|
46
|
+
Object.assign({}, options, { headers, agent: getProxyAgent() })
|
|
47
47
|
);
|
|
48
48
|
|
|
49
49
|
if (response.status === 401) {
|
|
@@ -60,11 +60,10 @@ export class RegistryApi {
|
|
|
60
60
|
|
|
61
61
|
async authStatus(
|
|
62
62
|
accessToken: string,
|
|
63
|
-
region: Region,
|
|
64
63
|
verbose = false
|
|
65
64
|
): Promise<{ viewerId: string; organizations: string[] }> {
|
|
66
65
|
try {
|
|
67
|
-
const response = await this.request('', { headers: { authorization: accessToken } }
|
|
66
|
+
const response = await this.request('', { headers: { authorization: accessToken } });
|
|
68
67
|
|
|
69
68
|
return await response.json();
|
|
70
69
|
} catch (error) {
|
|
@@ -97,8 +96,7 @@ export class RegistryApi {
|
|
|
97
96
|
filename,
|
|
98
97
|
isUpsert,
|
|
99
98
|
}),
|
|
100
|
-
}
|
|
101
|
-
this.region
|
|
99
|
+
}
|
|
102
100
|
);
|
|
103
101
|
|
|
104
102
|
if (response.ok) {
|
|
@@ -120,26 +118,22 @@ export class RegistryApi {
|
|
|
120
118
|
batchId,
|
|
121
119
|
batchSize,
|
|
122
120
|
}: PushApiParams) {
|
|
123
|
-
const response = await this.request(
|
|
124
|
-
|
|
125
|
-
{
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}),
|
|
140
|
-
},
|
|
141
|
-
this.region
|
|
142
|
-
);
|
|
121
|
+
const response = await this.request(`/${organizationId}/${name}/${version}`, {
|
|
122
|
+
method: 'PUT',
|
|
123
|
+
headers: {
|
|
124
|
+
'content-type': 'application/json',
|
|
125
|
+
authorization: this.accessToken,
|
|
126
|
+
} as HeadersInit,
|
|
127
|
+
body: JSON.stringify({
|
|
128
|
+
rootFilePath,
|
|
129
|
+
filePaths,
|
|
130
|
+
branch,
|
|
131
|
+
isUpsert,
|
|
132
|
+
isPublic,
|
|
133
|
+
batchId,
|
|
134
|
+
batchSize,
|
|
135
|
+
}),
|
|
136
|
+
});
|
|
143
137
|
|
|
144
138
|
if (response.ok) {
|
|
145
139
|
return;
|
|
@@ -0,0 +1,53 @@
|
|
|
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-invalid-parameter-examples', () => {
|
|
7
|
+
it('should report on invalid falsy example', async () => {
|
|
8
|
+
const document = parseYamlToDocument(
|
|
9
|
+
outdent`
|
|
10
|
+
openapi: 3.1.0
|
|
11
|
+
paths:
|
|
12
|
+
/results:
|
|
13
|
+
get:
|
|
14
|
+
parameters:
|
|
15
|
+
- name: username
|
|
16
|
+
in: query
|
|
17
|
+
schema:
|
|
18
|
+
type: string
|
|
19
|
+
maxLength: 15
|
|
20
|
+
example: false
|
|
21
|
+
`,
|
|
22
|
+
'foobar.yaml'
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
const results = await lintDocument({
|
|
26
|
+
externalRefResolver: new BaseResolver(),
|
|
27
|
+
document,
|
|
28
|
+
config: await makeConfig({ 'no-invalid-parameter-examples': 'error' }),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
|
|
32
|
+
[
|
|
33
|
+
{
|
|
34
|
+
"from": {
|
|
35
|
+
"pointer": "#/paths/~1results/get/parameters/0",
|
|
36
|
+
"source": "foobar.yaml",
|
|
37
|
+
},
|
|
38
|
+
"location": [
|
|
39
|
+
{
|
|
40
|
+
"pointer": "#/paths/~1results/get/parameters/0/example",
|
|
41
|
+
"reportOnKey": false,
|
|
42
|
+
"source": "foobar.yaml",
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
"message": "Example value must conform to the schema: type must be string.",
|
|
46
|
+
"ruleId": "no-invalid-parameter-examples",
|
|
47
|
+
"severity": "error",
|
|
48
|
+
"suggest": [],
|
|
49
|
+
},
|
|
50
|
+
]
|
|
51
|
+
`);
|
|
52
|
+
});
|
|
53
|
+
});
|