@redocly/openapi-core 1.0.0-beta.85 → 1.0.0-beta.88
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/__tests__/codeframes.test.ts +22 -0
- package/__tests__/utils.ts +2 -2
- package/__tests__/walk.test.ts +84 -0
- package/lib/bundle.js +1 -0
- package/lib/config/config.d.ts +46 -4
- package/lib/config/config.js +63 -5
- package/lib/config/load.d.ts +5 -2
- package/lib/config/load.js +34 -22
- package/lib/format/codeframes.js +5 -2
- package/lib/index.d.ts +4 -4
- package/lib/index.js +7 -1
- package/lib/redocly/index.js +11 -10
- package/lib/rules/common/spec.js +4 -4
- package/lib/rules/oas3/no-empty-servers.js +2 -1
- package/lib/types/oas2.js +1 -1
- package/lib/types/oas3.js +1 -0
- package/package.json +1 -1
- package/src/bundle.ts +1 -0
- package/src/config/__tests__/load.test.ts +65 -24
- package/src/config/config.ts +98 -13
- package/src/config/load.ts +29 -22
- package/src/format/codeframes.ts +4 -2
- package/src/index.ts +14 -4
- package/src/redocly/__tests__/redocly-client.test.ts +1 -1
- package/src/redocly/index.ts +15 -9
- package/src/rules/common/__tests__/spec.test.ts +62 -0
- package/src/rules/common/spec.ts +1 -1
- package/src/rules/oas3/__tests__/spec/spec.test.ts +4 -4
- package/src/rules/oas3/no-empty-servers.ts +2 -1
- package/src/types/oas2.ts +2 -1
- package/src/types/oas3.ts +1 -0
- package/src/utils.ts +0 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -85,6 +85,28 @@ describe('Location', () => {
|
|
|
85
85
|
expect(preciseLocation.end).toEqual({ line: 5, col: 28 });
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
+
it('should correctly fallback to the closest parent node if node value is null', () => {
|
|
89
|
+
const loc = {
|
|
90
|
+
reportOnKey: false,
|
|
91
|
+
pointer: '#/servers',
|
|
92
|
+
source: new Source(
|
|
93
|
+
'foobar.yaml',
|
|
94
|
+
outdent`
|
|
95
|
+
openapi: 3.0.2
|
|
96
|
+
servers:
|
|
97
|
+
info:
|
|
98
|
+
license:
|
|
99
|
+
name: MIT
|
|
100
|
+
url: https://google.com
|
|
101
|
+
`,
|
|
102
|
+
),
|
|
103
|
+
};
|
|
104
|
+
const preciseLocation = getLineColLocation(loc);
|
|
105
|
+
expect(preciseLocation.start).toEqual({ line: 2, col: 1 });
|
|
106
|
+
expect(preciseLocation.end).toEqual({ line: 2, col: 9 });
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
|
|
88
110
|
it('should return first line for empty doc', () => {
|
|
89
111
|
const loc = {
|
|
90
112
|
reportOnKey: false,
|
package/__tests__/utils.ts
CHANGED
|
@@ -44,7 +44,7 @@ export const yamlSerializer = {
|
|
|
44
44
|
},
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
-
export function makeConfigForRuleset(rules: Oas3RuleSet, plugin?: Partial<Plugin
|
|
47
|
+
export function makeConfigForRuleset(rules: Oas3RuleSet, plugin?: Partial<Plugin>, version: string = 'oas3') {
|
|
48
48
|
const rulesConf: Record<string, RuleConfig> = {};
|
|
49
49
|
const ruleId = 'test';
|
|
50
50
|
Object.keys(rules).forEach((name) => {
|
|
@@ -56,7 +56,7 @@ export function makeConfigForRuleset(rules: Oas3RuleSet, plugin?: Partial<Plugin
|
|
|
56
56
|
{
|
|
57
57
|
...plugin,
|
|
58
58
|
id: ruleId,
|
|
59
|
-
rules: {
|
|
59
|
+
rules: { [version]: rules },
|
|
60
60
|
},
|
|
61
61
|
],
|
|
62
62
|
extends: [],
|
package/__tests__/walk.test.ts
CHANGED
|
@@ -143,6 +143,90 @@ describe('walk order', () => {
|
|
|
143
143
|
`);
|
|
144
144
|
});
|
|
145
145
|
|
|
146
|
+
it('should run nested visitors correctly oas2', async () => {
|
|
147
|
+
const calls: string[] = [];
|
|
148
|
+
|
|
149
|
+
const testRuleSet: Oas3RuleSet = {
|
|
150
|
+
test: jest.fn(() => {
|
|
151
|
+
return {
|
|
152
|
+
Operation: {
|
|
153
|
+
enter: jest.fn((op) => calls.push(`enter operation: ${op.operationId}`)),
|
|
154
|
+
leave: jest.fn((op) => calls.push(`leave operation: ${op.operationId}`)),
|
|
155
|
+
Parameter: {
|
|
156
|
+
enter: jest.fn((param, _ctx, parents) =>
|
|
157
|
+
calls.push(
|
|
158
|
+
`enter operation ${parents.Operation.operationId} > param ${param.name}`,
|
|
159
|
+
),
|
|
160
|
+
),
|
|
161
|
+
leave: jest.fn((param, _ctx, parents) =>
|
|
162
|
+
calls.push(
|
|
163
|
+
`leave operation ${parents.Operation.operationId} > param ${param.name}`,
|
|
164
|
+
),
|
|
165
|
+
),
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
Parameter: {
|
|
169
|
+
enter: jest.fn((param) => calls.push(`enter param ${param.name}`)),
|
|
170
|
+
leave: jest.fn((param) => calls.push(`leave param ${param.name}`)),
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
}),
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const document = parseYamlToDocument(
|
|
177
|
+
outdent`
|
|
178
|
+
swagger: "2.0"
|
|
179
|
+
info:
|
|
180
|
+
contact: {}
|
|
181
|
+
license: {}
|
|
182
|
+
paths:
|
|
183
|
+
/pet:
|
|
184
|
+
parameters:
|
|
185
|
+
- name: path-param
|
|
186
|
+
get:
|
|
187
|
+
operationId: get
|
|
188
|
+
parameters:
|
|
189
|
+
- name: get_a
|
|
190
|
+
- name: get_b
|
|
191
|
+
post:
|
|
192
|
+
operationId: post
|
|
193
|
+
parameters:
|
|
194
|
+
- name: post_a
|
|
195
|
+
|
|
196
|
+
`,
|
|
197
|
+
'',
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
await lintDocument({
|
|
201
|
+
externalRefResolver: new BaseResolver(),
|
|
202
|
+
document,
|
|
203
|
+
config: makeConfigForRuleset(testRuleSet, undefined, 'oas2'),
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
expect(calls).toMatchInlineSnapshot(`
|
|
207
|
+
Array [
|
|
208
|
+
"enter param path-param",
|
|
209
|
+
"leave param path-param",
|
|
210
|
+
"enter operation: get",
|
|
211
|
+
"enter operation get > param get_a",
|
|
212
|
+
"enter param get_a",
|
|
213
|
+
"leave param get_a",
|
|
214
|
+
"leave operation get > param get_a",
|
|
215
|
+
"enter operation get > param get_b",
|
|
216
|
+
"enter param get_b",
|
|
217
|
+
"leave param get_b",
|
|
218
|
+
"leave operation get > param get_b",
|
|
219
|
+
"leave operation: get",
|
|
220
|
+
"enter operation: post",
|
|
221
|
+
"enter operation post > param post_a",
|
|
222
|
+
"enter param post_a",
|
|
223
|
+
"leave param post_a",
|
|
224
|
+
"leave operation post > param post_a",
|
|
225
|
+
"leave operation: post",
|
|
226
|
+
]
|
|
227
|
+
`);
|
|
228
|
+
});
|
|
229
|
+
|
|
146
230
|
it('should resolve refs', async () => {
|
|
147
231
|
const calls: string[] = [];
|
|
148
232
|
|
package/lib/bundle.js
CHANGED
|
@@ -161,6 +161,7 @@ function makeBundleVisitor(version, dereference, skipRedoclyRegistryRefs, rootDo
|
|
|
161
161
|
!dereference) {
|
|
162
162
|
return;
|
|
163
163
|
}
|
|
164
|
+
// do not bundle registry URL before push, otherwise we can't record dependencies
|
|
164
165
|
if (skipRedoclyRegistryRefs && redocly_1.isRedoclyRegistryURL(node.$ref)) {
|
|
165
166
|
return;
|
|
166
167
|
}
|
package/lib/config/config.d.ts
CHANGED
|
@@ -78,12 +78,27 @@ export declare const DOMAINS: {
|
|
|
78
78
|
[region in Region]: string;
|
|
79
79
|
};
|
|
80
80
|
export declare const AVAILABLE_REGIONS: Region[];
|
|
81
|
-
export declare type
|
|
82
|
-
referenceDocs?: any;
|
|
81
|
+
export declare type DeprecatedRawConfig = {
|
|
83
82
|
apiDefinitions?: Record<string, string>;
|
|
84
83
|
lint?: LintRawConfig;
|
|
85
84
|
resolve?: RawResolveConfig;
|
|
86
85
|
region?: Region;
|
|
86
|
+
referenceDocs?: any;
|
|
87
|
+
};
|
|
88
|
+
export declare type Api = {
|
|
89
|
+
root: string;
|
|
90
|
+
lint?: LintRawConfig;
|
|
91
|
+
'features.openapi'?: any;
|
|
92
|
+
'features.mockServer'?: any;
|
|
93
|
+
};
|
|
94
|
+
export declare type RawConfig = {
|
|
95
|
+
apis?: Record<string, Api>;
|
|
96
|
+
lint?: LintRawConfig;
|
|
97
|
+
resolve?: RawResolveConfig;
|
|
98
|
+
region?: Region;
|
|
99
|
+
'features.openapi'?: any;
|
|
100
|
+
'features.mockServer'?: any;
|
|
101
|
+
organization?: string;
|
|
87
102
|
};
|
|
88
103
|
export declare class LintConfig {
|
|
89
104
|
rawConfig: LintRawConfig;
|
|
@@ -124,11 +139,38 @@ export declare class LintConfig {
|
|
|
124
139
|
export declare class Config {
|
|
125
140
|
rawConfig: RawConfig;
|
|
126
141
|
configFile?: string | undefined;
|
|
127
|
-
|
|
128
|
-
apiDefinitions: Record<string, string>;
|
|
142
|
+
apis: Record<string, Api>;
|
|
129
143
|
lint: LintConfig;
|
|
130
144
|
resolve: ResolveConfig;
|
|
131
145
|
licenseKey?: string;
|
|
132
146
|
region?: Region;
|
|
147
|
+
'features.openapi': Record<string, any>;
|
|
148
|
+
'features.mockServer'?: Record<string, any>;
|
|
149
|
+
organization?: string;
|
|
133
150
|
constructor(rawConfig: RawConfig, configFile?: string | undefined);
|
|
134
151
|
}
|
|
152
|
+
export declare function getMergedConfig(config: Config, entrypointAlias?: string): Config;
|
|
153
|
+
export declare function getMergedLintConfig(config: Config, entrypointAlias?: string): {
|
|
154
|
+
rules: {
|
|
155
|
+
[x: string]: RuleConfig;
|
|
156
|
+
};
|
|
157
|
+
preprocessors: {
|
|
158
|
+
[x: string]: PreprocessorConfig;
|
|
159
|
+
};
|
|
160
|
+
decorators: {
|
|
161
|
+
[x: string]: PreprocessorConfig;
|
|
162
|
+
};
|
|
163
|
+
plugins?: (string | Plugin)[] | undefined;
|
|
164
|
+
extends?: string[] | undefined;
|
|
165
|
+
doNotResolveExamples?: boolean | undefined;
|
|
166
|
+
oas2Rules?: Record<string, RuleConfig> | undefined;
|
|
167
|
+
oas3_0Rules?: Record<string, RuleConfig> | undefined;
|
|
168
|
+
oas3_1Rules?: Record<string, RuleConfig> | undefined;
|
|
169
|
+
oas2Preprocessors?: Record<string, PreprocessorConfig> | undefined;
|
|
170
|
+
oas3_0Preprocessors?: Record<string, PreprocessorConfig> | undefined;
|
|
171
|
+
oas3_1Preprocessors?: Record<string, PreprocessorConfig> | undefined;
|
|
172
|
+
oas2Decorators?: Record<string, PreprocessorConfig> | undefined;
|
|
173
|
+
oas3_0Decorators?: Record<string, PreprocessorConfig> | undefined;
|
|
174
|
+
oas3_1Decorators?: Record<string, PreprocessorConfig> | undefined;
|
|
175
|
+
};
|
|
176
|
+
export declare function transformConfig(rawConfig: DeprecatedRawConfig | RawConfig): RawConfig;
|
package/lib/config/config.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
2
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Config = exports.LintConfig = exports.AVAILABLE_REGIONS = exports.DOMAINS = exports.DEFAULT_REGION = exports.IGNORE_FILE = void 0;
|
|
14
|
+
exports.transformConfig = exports.getMergedLintConfig = exports.getMergedConfig = exports.Config = exports.LintConfig = exports.AVAILABLE_REGIONS = exports.DOMAINS = exports.DEFAULT_REGION = exports.IGNORE_FILE = void 0;
|
|
4
15
|
const fs = require("fs");
|
|
5
16
|
const path = require("path");
|
|
6
17
|
const path_1 = require("path");
|
|
@@ -15,10 +26,9 @@ const IGNORE_BANNER = `# This file instructs Redocly's linter to ignore the rule
|
|
|
15
26
|
exports.DEFAULT_REGION = 'us';
|
|
16
27
|
const REDOCLY_DOMAIN = process.env.REDOCLY_DOMAIN;
|
|
17
28
|
exports.DOMAINS = {
|
|
18
|
-
us: '
|
|
29
|
+
us: 'redocly.com',
|
|
19
30
|
eu: 'eu.redocly.com',
|
|
20
31
|
};
|
|
21
|
-
exports.AVAILABLE_REGIONS = Object.keys(exports.DOMAINS);
|
|
22
32
|
// FIXME: temporary fix for our lab environments
|
|
23
33
|
if (REDOCLY_DOMAIN === null || REDOCLY_DOMAIN === void 0 ? void 0 : REDOCLY_DOMAIN.endsWith('.redocly.host')) {
|
|
24
34
|
exports.DOMAINS[REDOCLY_DOMAIN.split('.')[0]] = REDOCLY_DOMAIN;
|
|
@@ -26,6 +36,7 @@ if (REDOCLY_DOMAIN === null || REDOCLY_DOMAIN === void 0 ? void 0 : REDOCLY_DOMA
|
|
|
26
36
|
if (REDOCLY_DOMAIN === 'redoc.online') {
|
|
27
37
|
exports.DOMAINS[REDOCLY_DOMAIN] = REDOCLY_DOMAIN;
|
|
28
38
|
}
|
|
39
|
+
exports.AVAILABLE_REGIONS = Object.keys(exports.DOMAINS);
|
|
29
40
|
class LintConfig {
|
|
30
41
|
constructor(rawConfig, configFile) {
|
|
31
42
|
this.rawConfig = rawConfig;
|
|
@@ -238,9 +249,10 @@ class Config {
|
|
|
238
249
|
var _a, _b, _c;
|
|
239
250
|
this.rawConfig = rawConfig;
|
|
240
251
|
this.configFile = configFile;
|
|
241
|
-
this.
|
|
252
|
+
this.apis = rawConfig.apis || {};
|
|
242
253
|
this.lint = new LintConfig(rawConfig.lint || {}, configFile);
|
|
243
|
-
this.
|
|
254
|
+
this['features.openapi'] = rawConfig['features.openapi'] || {};
|
|
255
|
+
this['features.mockServer'] = rawConfig['features.mockServer'] || {};
|
|
244
256
|
this.resolve = {
|
|
245
257
|
http: {
|
|
246
258
|
headers: (_c = (_b = (_a = rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.resolve) === null || _a === void 0 ? void 0 : _a.http) === null || _b === void 0 ? void 0 : _b.headers) !== null && _c !== void 0 ? _c : [],
|
|
@@ -248,6 +260,7 @@ class Config {
|
|
|
248
260
|
},
|
|
249
261
|
};
|
|
250
262
|
this.region = rawConfig.region;
|
|
263
|
+
this.organization = rawConfig.organization;
|
|
251
264
|
}
|
|
252
265
|
}
|
|
253
266
|
exports.Config = Config;
|
|
@@ -398,3 +411,48 @@ function assignExisting(target, obj) {
|
|
|
398
411
|
}
|
|
399
412
|
}
|
|
400
413
|
}
|
|
414
|
+
function getMergedConfig(config, entrypointAlias) {
|
|
415
|
+
var _a, _b;
|
|
416
|
+
return entrypointAlias
|
|
417
|
+
? new Config(Object.assign(Object.assign({}, config.rawConfig), { lint: getMergedLintConfig(config, entrypointAlias), 'features.openapi': Object.assign(Object.assign({}, config['features.openapi']), (_a = config.apis[entrypointAlias]) === null || _a === void 0 ? void 0 : _a['features.openapi']), 'features.mockServer': Object.assign(Object.assign({}, config['features.mockServer']), (_b = config.apis[entrypointAlias]) === null || _b === void 0 ? void 0 : _b['features.mockServer']) }))
|
|
418
|
+
: config;
|
|
419
|
+
}
|
|
420
|
+
exports.getMergedConfig = getMergedConfig;
|
|
421
|
+
function getMergedLintConfig(config, entrypointAlias) {
|
|
422
|
+
var _a, _b, _c, _d;
|
|
423
|
+
const apiLint = entrypointAlias
|
|
424
|
+
? (_a = config.apis[entrypointAlias]) === null || _a === void 0 ? void 0 : _a.lint
|
|
425
|
+
: {};
|
|
426
|
+
const mergedLint = Object.assign(Object.assign(Object.assign({}, config.rawConfig.lint), apiLint), { rules: Object.assign(Object.assign({}, (_b = config.rawConfig.lint) === null || _b === void 0 ? void 0 : _b.rules), apiLint === null || apiLint === void 0 ? void 0 : apiLint.rules), preprocessors: Object.assign(Object.assign({}, (_c = config.rawConfig.lint) === null || _c === void 0 ? void 0 : _c.preprocessors), apiLint === null || apiLint === void 0 ? void 0 : apiLint.preprocessors), decorators: Object.assign(Object.assign({}, (_d = config.rawConfig.lint) === null || _d === void 0 ? void 0 : _d.decorators), apiLint === null || apiLint === void 0 ? void 0 : apiLint.decorators) });
|
|
427
|
+
return mergedLint;
|
|
428
|
+
}
|
|
429
|
+
exports.getMergedLintConfig = getMergedLintConfig;
|
|
430
|
+
function transformApiDefinitionsToApis(apiDefinitions = {}) {
|
|
431
|
+
let apis = {};
|
|
432
|
+
for (const [apiName, apiPath] of Object.entries(apiDefinitions)) {
|
|
433
|
+
apis[apiName] = { root: apiPath };
|
|
434
|
+
}
|
|
435
|
+
return apis;
|
|
436
|
+
}
|
|
437
|
+
function transformConfig(rawConfig) {
|
|
438
|
+
if (rawConfig.apis && rawConfig.apiDefinitions) {
|
|
439
|
+
throw new Error("Do not use 'apiDefinitions' field. Use 'apis' instead.\n");
|
|
440
|
+
}
|
|
441
|
+
if (rawConfig['features.openapi'] && rawConfig.referenceDocs) {
|
|
442
|
+
throw new Error("Do not use 'referenceDocs' field. Use 'features.openapi' instead.\n");
|
|
443
|
+
}
|
|
444
|
+
const _a = rawConfig, { apiDefinitions, referenceDocs } = _a, rest = __rest(_a, ["apiDefinitions", "referenceDocs"]);
|
|
445
|
+
// TODO: put links to the changelog and uncomment this after successful release of ReferenceDocs/Redoc, Portal and Workflows
|
|
446
|
+
// if (apiDefinitions) {
|
|
447
|
+
// process.stderr.write(
|
|
448
|
+
// `The ${yellow('apiDefinitions')} field is deprecated. Use ${green('apis')} instead, see changelog: <link>\n`
|
|
449
|
+
// );
|
|
450
|
+
// }
|
|
451
|
+
// if (referenceDocs) {
|
|
452
|
+
// process.stderr.write(
|
|
453
|
+
// `The ${yellow('referenceDocs')} field is deprecated. Use ${green('features.openapi')} instead, see changelog: <link>\n`
|
|
454
|
+
// );
|
|
455
|
+
// }
|
|
456
|
+
return Object.assign({ 'features.openapi': referenceDocs, apis: transformApiDefinitionsToApis(apiDefinitions) }, rest);
|
|
457
|
+
}
|
|
458
|
+
exports.transformConfig = transformConfig;
|
package/lib/config/load.d.ts
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
import { Config } from './config';
|
|
2
|
-
export declare function loadConfig(configPath?: string, customExtends?: string[]): Promise<Config>;
|
|
1
|
+
import { Config, RawConfig } from './config';
|
|
2
|
+
export declare function loadConfig(configPath?: string | undefined, customExtends?: string[]): Promise<Config>;
|
|
3
|
+
export declare const CONFIG_FILE_NAMES: string[];
|
|
4
|
+
export declare function findConfig(dir?: string): string | undefined;
|
|
5
|
+
export declare function getConfig(configPath?: string | undefined): Promise<RawConfig>;
|
package/lib/config/load.js
CHANGED
|
@@ -9,27 +9,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.loadConfig = void 0;
|
|
12
|
+
exports.getConfig = exports.findConfig = exports.CONFIG_FILE_NAMES = exports.loadConfig = void 0;
|
|
13
13
|
const fs = require("fs");
|
|
14
|
+
const path = require("path");
|
|
14
15
|
const redocly_1 = require("../redocly");
|
|
15
16
|
const utils_1 = require("../utils");
|
|
16
17
|
const config_1 = require("./config");
|
|
17
18
|
const builtIn_1 = require("./builtIn");
|
|
18
|
-
function loadConfig(configPath, customExtends) {
|
|
19
|
+
function loadConfig(configPath = findConfig(), customExtends) {
|
|
19
20
|
var _a, _b;
|
|
20
21
|
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
-
|
|
22
|
-
configPath = findConfig();
|
|
23
|
-
}
|
|
24
|
-
let rawConfig = {};
|
|
25
|
-
if (configPath !== undefined) {
|
|
26
|
-
try {
|
|
27
|
-
rawConfig = (yield utils_1.loadYaml(configPath));
|
|
28
|
-
}
|
|
29
|
-
catch (e) {
|
|
30
|
-
throw new Error(`Error parsing config file at \`${configPath}\`: ${e.message}`);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
22
|
+
const rawConfig = yield getConfig(configPath);
|
|
33
23
|
if (customExtends !== undefined) {
|
|
34
24
|
rawConfig.lint = rawConfig.lint || {};
|
|
35
25
|
rawConfig.lint.extends = customExtends;
|
|
@@ -52,7 +42,7 @@ function loadConfig(configPath, customExtends) {
|
|
|
52
42
|
},
|
|
53
43
|
//support redocly.com domain for future compatibility
|
|
54
44
|
...(item.region === 'us' ? [{
|
|
55
|
-
matches: `https://api.
|
|
45
|
+
matches: `https://api.redoc.ly/registry/**`,
|
|
56
46
|
name: 'Authorization',
|
|
57
47
|
envVariable: undefined,
|
|
58
48
|
value: item.token,
|
|
@@ -63,12 +53,34 @@ function loadConfig(configPath, customExtends) {
|
|
|
63
53
|
});
|
|
64
54
|
}
|
|
65
55
|
exports.loadConfig = loadConfig;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
56
|
+
exports.CONFIG_FILE_NAMES = ['redocly.yaml', 'redocly.yml', '.redocly.yaml', '.redocly.yml'];
|
|
57
|
+
function findConfig(dir) {
|
|
58
|
+
if (!fs.hasOwnProperty('existsSync'))
|
|
59
|
+
return;
|
|
60
|
+
const existingConfigFiles = exports.CONFIG_FILE_NAMES
|
|
61
|
+
.map(name => dir ? path.resolve(dir, name) : name)
|
|
62
|
+
.filter(fs.existsSync);
|
|
63
|
+
if (existingConfigFiles.length > 1) {
|
|
64
|
+
throw new Error(`
|
|
65
|
+
Multiple configuration files are not allowed.
|
|
66
|
+
Found the following files: ${existingConfigFiles.join(', ')}.
|
|
67
|
+
Please use 'redocly.yaml' instead.
|
|
68
|
+
`);
|
|
72
69
|
}
|
|
73
|
-
return
|
|
70
|
+
return existingConfigFiles[0];
|
|
71
|
+
}
|
|
72
|
+
exports.findConfig = findConfig;
|
|
73
|
+
function getConfig(configPath = findConfig()) {
|
|
74
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
75
|
+
if (!configPath)
|
|
76
|
+
return {};
|
|
77
|
+
try {
|
|
78
|
+
const rawConfig = (yield utils_1.loadYaml(configPath));
|
|
79
|
+
return config_1.transformConfig(rawConfig);
|
|
80
|
+
}
|
|
81
|
+
catch (e) {
|
|
82
|
+
throw new Error(`Error parsing config file at '${configPath}': ${e.message}`);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
74
85
|
}
|
|
86
|
+
exports.getConfig = getConfig;
|
package/lib/format/codeframes.js
CHANGED
|
@@ -142,9 +142,12 @@ function getAstNodeByPointer(root, pointer, reportOnKey) {
|
|
|
142
142
|
for (const key of pointerSegments) {
|
|
143
143
|
if (currentNode.kind === yamlAst.Kind.MAP) {
|
|
144
144
|
const mapping = currentNode.mappings.find((m) => m.key.value === key);
|
|
145
|
-
if (!
|
|
145
|
+
if (!mapping)
|
|
146
146
|
break;
|
|
147
|
-
currentNode = mapping
|
|
147
|
+
currentNode = mapping;
|
|
148
|
+
if (!(mapping === null || mapping === void 0 ? void 0 : mapping.value))
|
|
149
|
+
break; // If node has value - return value, if not - return node itself
|
|
150
|
+
currentNode = mapping.value;
|
|
148
151
|
}
|
|
149
152
|
else if (currentNode.kind === yamlAst.Kind.SEQ) {
|
|
150
153
|
const elem = currentNode.items[parseInt(key, 10)];
|
package/lib/index.d.ts
CHANGED
|
@@ -3,14 +3,14 @@ export { Oas3_1Types } from './types/oas3_1';
|
|
|
3
3
|
export { Oas3Types } from './types/oas3';
|
|
4
4
|
export { Oas2Types } from './types/oas2';
|
|
5
5
|
export { ConfigTypes } from './types/redocly-yaml';
|
|
6
|
-
export { Oas3Definition, Oas3_1Definition, Oas3Components, Oas3PathItem, Oas3Paths, Oas3ComponentName, Oas3Schema, Oas3_1Schema, Oas3Tag, Oas3_1Webhooks, Referenced } from './typings/openapi';
|
|
6
|
+
export { Oas3Definition, Oas3_1Definition, Oas3Components, Oas3PathItem, Oas3Paths, Oas3ComponentName, Oas3Schema, Oas3_1Schema, Oas3Tag, Oas3_1Webhooks, Referenced, } from './typings/openapi';
|
|
7
7
|
export { Oas2Definition } from './typings/swagger';
|
|
8
8
|
export { StatsAccumulator, StatsName } from './typings/common';
|
|
9
9
|
export { normalizeTypes } from './types';
|
|
10
10
|
export { Stats } from './rules/other/stats';
|
|
11
|
-
export { Config, LintConfig, RawConfig, IGNORE_FILE, Region } from './config/config';
|
|
12
|
-
export { loadConfig } from './config/load';
|
|
13
|
-
export { RedoclyClient } from './redocly';
|
|
11
|
+
export { Config, LintConfig, RawConfig, IGNORE_FILE, Region, getMergedConfig, transformConfig, } from './config/config';
|
|
12
|
+
export { loadConfig, getConfig, findConfig, CONFIG_FILE_NAMES } from './config/load';
|
|
13
|
+
export { RedoclyClient, isRedoclyRegistryURL } from './redocly';
|
|
14
14
|
export { Source, BaseResolver, Document, resolveDocument, ResolveError, YamlParseError, makeDocumentFromString, } from './resolve';
|
|
15
15
|
export { parseYaml, stringifyYaml } from './js-yaml';
|
|
16
16
|
export { unescapePointer, isRef } from './ref-utils';
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.mapTypeToComponent = exports.bundleDocument = exports.bundle = exports.lintConfig = exports.lintFromString = exports.lintDocument = exports.validate = exports.lint = exports.getTotals = exports.formatProblems = exports.getLineColLocation = exports.getAstNodeByPointer = exports.walkDocument = exports.normalizeVisitors = exports.OasVersion = exports.openAPIMajor = exports.OasMajorVersion = exports.detectOpenAPI = exports.isRef = exports.unescapePointer = exports.stringifyYaml = exports.parseYaml = exports.makeDocumentFromString = exports.YamlParseError = exports.ResolveError = exports.resolveDocument = exports.BaseResolver = exports.Source = exports.RedoclyClient = exports.loadConfig = exports.IGNORE_FILE = exports.LintConfig = exports.Config = exports.Stats = exports.normalizeTypes = exports.ConfigTypes = exports.Oas2Types = exports.Oas3Types = exports.Oas3_1Types = exports.slash = exports.readFileFromUrl = void 0;
|
|
3
|
+
exports.mapTypeToComponent = exports.bundleDocument = exports.bundle = exports.lintConfig = exports.lintFromString = exports.lintDocument = exports.validate = exports.lint = exports.getTotals = exports.formatProblems = exports.getLineColLocation = exports.getAstNodeByPointer = exports.walkDocument = exports.normalizeVisitors = exports.OasVersion = exports.openAPIMajor = exports.OasMajorVersion = exports.detectOpenAPI = exports.isRef = exports.unescapePointer = exports.stringifyYaml = exports.parseYaml = exports.makeDocumentFromString = exports.YamlParseError = exports.ResolveError = exports.resolveDocument = exports.BaseResolver = exports.Source = exports.isRedoclyRegistryURL = exports.RedoclyClient = exports.CONFIG_FILE_NAMES = exports.findConfig = exports.getConfig = exports.loadConfig = exports.transformConfig = exports.getMergedConfig = exports.IGNORE_FILE = exports.LintConfig = exports.Config = exports.Stats = exports.normalizeTypes = exports.ConfigTypes = exports.Oas2Types = exports.Oas3Types = exports.Oas3_1Types = exports.slash = exports.readFileFromUrl = void 0;
|
|
4
4
|
var utils_1 = require("./utils");
|
|
5
5
|
Object.defineProperty(exports, "readFileFromUrl", { enumerable: true, get: function () { return utils_1.readFileFromUrl; } });
|
|
6
6
|
Object.defineProperty(exports, "slash", { enumerable: true, get: function () { return utils_1.slash; } });
|
|
@@ -20,10 +20,16 @@ var config_1 = require("./config/config");
|
|
|
20
20
|
Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return config_1.Config; } });
|
|
21
21
|
Object.defineProperty(exports, "LintConfig", { enumerable: true, get: function () { return config_1.LintConfig; } });
|
|
22
22
|
Object.defineProperty(exports, "IGNORE_FILE", { enumerable: true, get: function () { return config_1.IGNORE_FILE; } });
|
|
23
|
+
Object.defineProperty(exports, "getMergedConfig", { enumerable: true, get: function () { return config_1.getMergedConfig; } });
|
|
24
|
+
Object.defineProperty(exports, "transformConfig", { enumerable: true, get: function () { return config_1.transformConfig; } });
|
|
23
25
|
var load_1 = require("./config/load");
|
|
24
26
|
Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return load_1.loadConfig; } });
|
|
27
|
+
Object.defineProperty(exports, "getConfig", { enumerable: true, get: function () { return load_1.getConfig; } });
|
|
28
|
+
Object.defineProperty(exports, "findConfig", { enumerable: true, get: function () { return load_1.findConfig; } });
|
|
29
|
+
Object.defineProperty(exports, "CONFIG_FILE_NAMES", { enumerable: true, get: function () { return load_1.CONFIG_FILE_NAMES; } });
|
|
25
30
|
var redocly_1 = require("./redocly");
|
|
26
31
|
Object.defineProperty(exports, "RedoclyClient", { enumerable: true, get: function () { return redocly_1.RedoclyClient; } });
|
|
32
|
+
Object.defineProperty(exports, "isRedoclyRegistryURL", { enumerable: true, get: function () { return redocly_1.isRedoclyRegistryURL; } });
|
|
27
33
|
var resolve_1 = require("./resolve");
|
|
28
34
|
Object.defineProperty(exports, "Source", { enumerable: true, get: function () { return resolve_1.Source; } });
|
|
29
35
|
Object.defineProperty(exports, "BaseResolver", { enumerable: true, get: function () { return resolve_1.BaseResolver; } });
|
package/lib/redocly/index.js
CHANGED
|
@@ -18,6 +18,7 @@ const registry_api_1 = require("./registry-api");
|
|
|
18
18
|
const config_1 = require("../config/config");
|
|
19
19
|
const utils_1 = require("../utils");
|
|
20
20
|
const TOKEN_FILENAME = '.redocly-config.json';
|
|
21
|
+
let REDOCLY_DOMAIN; // workaround for the isRedoclyRegistryURL, see more below
|
|
21
22
|
class RedoclyClient {
|
|
22
23
|
constructor(region) {
|
|
23
24
|
this.accessTokens = {};
|
|
@@ -26,6 +27,11 @@ class RedoclyClient {
|
|
|
26
27
|
this.domain = region
|
|
27
28
|
? config_1.DOMAINS[region]
|
|
28
29
|
: process.env.REDOCLY_DOMAIN || config_1.DOMAINS[config_1.DEFAULT_REGION];
|
|
30
|
+
/*
|
|
31
|
+
* We can't use process.env here because it is replaced by a const in some client-side bundles,
|
|
32
|
+
* which breaks assignment.
|
|
33
|
+
*/
|
|
34
|
+
REDOCLY_DOMAIN = this.domain; // isRedoclyRegistryURL depends on the value to be set
|
|
29
35
|
this.registryApi = new registry_api_1.RegistryApi(this.accessTokens, this.region);
|
|
30
36
|
}
|
|
31
37
|
loadRegion(region) {
|
|
@@ -143,17 +149,12 @@ class RedoclyClient {
|
|
|
143
149
|
}
|
|
144
150
|
exports.RedoclyClient = RedoclyClient;
|
|
145
151
|
function isRedoclyRegistryURL(link) {
|
|
146
|
-
const domain = process.env.REDOCLY_DOMAIN || config_1.DOMAINS[config_1.DEFAULT_REGION];
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const pathParts = registryPath.split('/');
|
|
151
|
-
// we can be sure, that there is job UUID present
|
|
152
|
-
// (org, definition, version, bundle, branch, job, "openapi.yaml" 🤦♂️)
|
|
153
|
-
// so skip this link.
|
|
154
|
-
// FIXME
|
|
155
|
-
if (pathParts.length === 7)
|
|
152
|
+
const domain = REDOCLY_DOMAIN || process.env.REDOCLY_DOMAIN || config_1.DOMAINS[config_1.DEFAULT_REGION];
|
|
153
|
+
const legacyDomain = domain === 'redocly.com' ? 'redoc.ly' : domain;
|
|
154
|
+
if (!link.startsWith(`https://api.${domain}/registry/`) &&
|
|
155
|
+
!link.startsWith(`https://api.${legacyDomain}/registry/`)) {
|
|
156
156
|
return false;
|
|
157
|
+
}
|
|
157
158
|
return true;
|
|
158
159
|
}
|
|
159
160
|
exports.isRedoclyRegistryURL = isRedoclyRegistryURL;
|
package/lib/rules/common/spec.js
CHANGED
|
@@ -8,7 +8,7 @@ const utils_2 = require("../../utils");
|
|
|
8
8
|
const OasSpec = () => {
|
|
9
9
|
return {
|
|
10
10
|
any(node, { report, type, location, key, resolve, ignoreNextVisitorsOnNode }) {
|
|
11
|
-
var _a, _b, _c;
|
|
11
|
+
var _a, _b, _c, _d;
|
|
12
12
|
const nodeType = utils_1.oasTypeOf(node);
|
|
13
13
|
if (type.items) {
|
|
14
14
|
if (nodeType !== 'array') {
|
|
@@ -59,7 +59,7 @@ const OasSpec = () => {
|
|
|
59
59
|
}
|
|
60
60
|
if (!hasProperty)
|
|
61
61
|
report({
|
|
62
|
-
message:
|
|
62
|
+
message: `Must contain at least one of the following fields: ${(_b = type.requiredOneOf) === null || _b === void 0 ? void 0 : _b.join(', ')}.`,
|
|
63
63
|
location: [{ reportOnKey: true }],
|
|
64
64
|
});
|
|
65
65
|
}
|
|
@@ -109,8 +109,8 @@ const OasSpec = () => {
|
|
|
109
109
|
location: propLocation,
|
|
110
110
|
});
|
|
111
111
|
}
|
|
112
|
-
else if (propValueType === 'array' && ((
|
|
113
|
-
const itemsType = (
|
|
112
|
+
else if (propValueType === 'array' && ((_c = propSchema.items) === null || _c === void 0 ? void 0 : _c.type)) {
|
|
113
|
+
const itemsType = (_d = propSchema.items) === null || _d === void 0 ? void 0 : _d.type;
|
|
114
114
|
for (let i = 0; i < propValue.length; i++) {
|
|
115
115
|
const item = propValue[i];
|
|
116
116
|
if (!utils_1.matchesJsonSchemaType(item, itemsType, false)) {
|
|
@@ -4,9 +4,10 @@ exports.NoEmptyServers = void 0;
|
|
|
4
4
|
const NoEmptyServers = () => {
|
|
5
5
|
return {
|
|
6
6
|
DefinitionRoot(root, { report, location }) {
|
|
7
|
-
if (!root.servers) {
|
|
7
|
+
if (!root.hasOwnProperty('servers')) {
|
|
8
8
|
report({
|
|
9
9
|
message: 'Servers must be present.',
|
|
10
|
+
location: location.child(['openapi']).key()
|
|
10
11
|
});
|
|
11
12
|
return;
|
|
12
13
|
}
|
package/lib/types/oas2.js
CHANGED
|
@@ -55,6 +55,7 @@ const PathMap = {
|
|
|
55
55
|
const PathItem = {
|
|
56
56
|
properties: {
|
|
57
57
|
$ref: { type: 'string' },
|
|
58
|
+
parameters: _1.listOf('Parameter'),
|
|
58
59
|
get: 'Operation',
|
|
59
60
|
put: 'Operation',
|
|
60
61
|
post: 'Operation',
|
|
@@ -62,7 +63,6 @@ const PathItem = {
|
|
|
62
63
|
options: 'Operation',
|
|
63
64
|
head: 'Operation',
|
|
64
65
|
patch: 'Operation',
|
|
65
|
-
parameters: _1.listOf('Parameter'),
|
|
66
66
|
},
|
|
67
67
|
};
|
|
68
68
|
const Operation = {
|
package/lib/types/oas3.js
CHANGED
package/package.json
CHANGED