@redocly/openapi-core 1.0.0-beta.62 → 1.0.0-beta.66
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__/lint.test.ts +17 -0
- package/__tests__/resolve.test.ts +10 -2
- package/__tests__/utils.ts +3 -5
- package/lib/benchmark/utils.js +2 -2
- package/lib/config/all.js +8 -1
- package/lib/config/config.d.ts +1 -0
- package/lib/config/config.js +4 -4
- package/lib/index.d.ts +2 -1
- package/lib/index.js +5 -1
- package/lib/js-yaml/index.d.ts +3 -0
- package/lib/js-yaml/index.js +19 -0
- package/lib/oas-types.js +3 -0
- package/lib/resolve.d.ts +1 -1
- package/lib/resolve.js +3 -4
- package/lib/rules/builtin.d.ts +6 -0
- package/lib/rules/common/info-description-override.d.ts +2 -0
- package/lib/rules/common/info-description-override.js +24 -0
- package/lib/rules/common/info-license-url.js +1 -0
- package/lib/rules/common/no-http-verbs-in-paths.d.ts +2 -0
- package/lib/rules/common/no-http-verbs-in-paths.js +33 -0
- package/lib/rules/common/operation-description-override.d.ts +2 -0
- package/lib/rules/common/operation-description-override.js +29 -0
- package/lib/rules/common/path-excludes-patterns.d.ts +2 -0
- package/lib/rules/common/path-excludes-patterns.js +22 -0
- package/lib/rules/common/path-segment-plural.d.ts +2 -0
- package/lib/rules/common/path-segment-plural.js +32 -0
- package/lib/rules/common/tag-description-override.d.ts +2 -0
- package/lib/rules/common/tag-description-override.js +25 -0
- package/lib/rules/oas2/index.d.ts +8 -0
- package/lib/rules/oas2/index.js +16 -0
- package/lib/rules/oas2/request-mime-type.d.ts +2 -0
- package/lib/rules/oas2/request-mime-type.js +17 -0
- package/lib/rules/oas2/response-mime-type.d.ts +2 -0
- package/lib/rules/oas2/response-mime-type.js +17 -0
- package/lib/rules/oas3/index.d.ts +3 -0
- package/lib/rules/oas3/index.js +17 -1
- package/lib/rules/oas3/request-mime-type.d.ts +2 -0
- package/lib/rules/oas3/request-mime-type.js +31 -0
- package/lib/rules/oas3/response-mime-type.d.ts +2 -0
- package/lib/rules/oas3/response-mime-type.js +31 -0
- package/lib/types/oas3_1.js +6 -0
- package/lib/types/redocly-yaml.js +332 -21
- package/lib/utils.d.ts +15 -1
- package/lib/utils.js +82 -3
- package/package.json +6 -4
- package/src/__tests__/js-yaml.test.ts +47 -0
- package/src/__tests__/lint.test.ts +13 -0
- package/src/__tests__/utils.test.ts +74 -0
- package/src/benchmark/utils.ts +2 -2
- package/src/config/all.ts +8 -1
- package/src/config/config.ts +6 -5
- package/src/index.ts +3 -1
- package/src/js-yaml/index.ts +19 -0
- package/src/oas-types.ts +4 -0
- package/src/resolve.ts +5 -5
- package/src/rules/__tests__/no-unresolved-refs.test.ts +2 -2
- package/src/rules/common/__tests__/info-license.test.ts +1 -1
- package/src/rules/common/info-description-override.ts +24 -0
- package/src/rules/common/info-license-url.ts +1 -0
- package/src/rules/common/no-http-verbs-in-paths.ts +36 -0
- package/src/rules/common/operation-description-override.ts +30 -0
- package/src/rules/common/path-excludes-patterns.ts +23 -0
- package/src/rules/common/path-segment-plural.ts +31 -0
- package/src/rules/common/tag-description-override.ts +25 -0
- package/src/rules/oas2/index.ts +16 -0
- package/src/rules/oas2/request-mime-type.ts +17 -0
- package/src/rules/oas2/response-mime-type.ts +17 -0
- package/src/rules/oas3/index.ts +18 -3
- package/src/rules/oas3/request-mime-type.ts +31 -0
- package/src/rules/oas3/response-mime-type.ts +31 -0
- package/src/rules/utils.ts +1 -1
- package/src/types/oas3_1.ts +7 -0
- package/src/types/redocly-yaml.ts +434 -22
- package/src/typings/swagger.ts +0 -1
- package/src/utils.ts +101 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import outdent from 'outdent';
|
|
2
|
+
import { detectOpenAPI } from '../src/oas-types';
|
|
3
|
+
import { parseYamlToDocument } from './utils';
|
|
4
|
+
|
|
5
|
+
describe.only('lint', () => {
|
|
6
|
+
it('detect OpenAPI should throw an error when version is not string', () => {
|
|
7
|
+
|
|
8
|
+
const testDocument = parseYamlToDocument(
|
|
9
|
+
outdent`
|
|
10
|
+
openapi: 3.0
|
|
11
|
+
`,
|
|
12
|
+
'',
|
|
13
|
+
);
|
|
14
|
+
expect(() => detectOpenAPI(testDocument.parsed))
|
|
15
|
+
.toThrow(`Invalid OpenAPI version: should be a string but got "number"`)
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -192,7 +192,7 @@ describe('collect refs', () => {
|
|
|
192
192
|
|
|
193
193
|
expect(resolvedRefs).toBeDefined();
|
|
194
194
|
|
|
195
|
-
expect(Array.from(resolvedRefs.keys()).map((ref) => ref.substring(cwd.length + 1)))
|
|
195
|
+
expect(Array.from(resolvedRefs.keys()).map((ref) => ref.substring(cwd.length + 1)).sort())
|
|
196
196
|
.toMatchInlineSnapshot(`
|
|
197
197
|
Array [
|
|
198
198
|
"openapi-with-back.yaml::./schemas/type-a.yaml#/",
|
|
@@ -201,7 +201,15 @@ describe('collect refs', () => {
|
|
|
201
201
|
]
|
|
202
202
|
`);
|
|
203
203
|
|
|
204
|
-
expect(
|
|
204
|
+
expect(
|
|
205
|
+
Array.from(resolvedRefs.values())
|
|
206
|
+
.map((val) => val.node)
|
|
207
|
+
.sort((firstEl, secondEl) => {
|
|
208
|
+
const getKey = (el: any): string => el?.allOf?.type || el?.type || '';
|
|
209
|
+
|
|
210
|
+
return getKey(firstEl).localeCompare(getKey(secondEl));
|
|
211
|
+
})
|
|
212
|
+
).toMatchInlineSnapshot(`
|
|
205
213
|
Array [
|
|
206
214
|
Object {
|
|
207
215
|
"allOf": Array [
|
package/__tests__/utils.ts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import * as yaml from 'js-yaml';
|
|
2
1
|
import * as path from 'path';
|
|
3
2
|
|
|
4
|
-
import { Document, Source } from '../src
|
|
5
|
-
import { NormalizedProblem } from '../src/walk';
|
|
3
|
+
import { Document, Source, NormalizedProblem, parseYaml, stringifyYaml } from '../src';
|
|
6
4
|
import { RuleConfig, LintConfig, Plugin } from '../src/config/config';
|
|
7
5
|
import { Oas3RuleSet } from '../src/oas-types';
|
|
8
6
|
|
|
9
7
|
export function parseYamlToDocument(body: string, absoluteRef: string = ''): Document {
|
|
10
8
|
return {
|
|
11
9
|
source: new Source(absoluteRef, body),
|
|
12
|
-
parsed:
|
|
10
|
+
parsed: parseYaml(body, { filename: absoluteRef }),
|
|
13
11
|
};
|
|
14
12
|
}
|
|
15
13
|
|
|
@@ -41,7 +39,7 @@ export const yamlSerializer = {
|
|
|
41
39
|
return true;
|
|
42
40
|
},
|
|
43
41
|
print: (val: any) => {
|
|
44
|
-
return
|
|
42
|
+
return stringifyYaml(val);
|
|
45
43
|
},
|
|
46
44
|
};
|
|
47
45
|
|
package/lib/benchmark/utils.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.makeConfigForRuleset = exports.parseYamlToDocument = void 0;
|
|
4
|
-
const
|
|
4
|
+
const js_yaml_1 = require("../js-yaml");
|
|
5
5
|
const resolve_1 = require("../resolve");
|
|
6
6
|
const config_1 = require("../config/config");
|
|
7
7
|
function parseYamlToDocument(body, absoluteRef = '') {
|
|
8
8
|
return {
|
|
9
9
|
source: new resolve_1.Source(absoluteRef, body),
|
|
10
|
-
parsed:
|
|
10
|
+
parsed: js_yaml_1.parseYaml(body, { filename: absoluteRef }),
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
13
|
exports.parseYamlToDocument = parseYamlToDocument;
|
package/lib/config/all.js
CHANGED
|
@@ -12,6 +12,7 @@ exports.default = {
|
|
|
12
12
|
'no-identical-paths': 'error',
|
|
13
13
|
'no-ambiguous-paths': 'error',
|
|
14
14
|
'no-path-trailing-slash': 'error',
|
|
15
|
+
'path-segment-plural': 'error',
|
|
15
16
|
'path-declaration-must-exist': 'error',
|
|
16
17
|
'path-not-include-query': 'error',
|
|
17
18
|
'path-parameters-defined': 'error',
|
|
@@ -29,6 +30,12 @@ exports.default = {
|
|
|
29
30
|
'no-enum-type-mismatch': 'error',
|
|
30
31
|
'boolean-parameter-prefixes': 'error',
|
|
31
32
|
'paths-kebab-case': 'error',
|
|
33
|
+
'no-http-verbs-in-paths': 'error',
|
|
34
|
+
'path-excludes-patterns': {
|
|
35
|
+
severity: 'error',
|
|
36
|
+
patterns: [],
|
|
37
|
+
},
|
|
38
|
+
'request-mime-type': 'error',
|
|
32
39
|
spec: 'error',
|
|
33
40
|
},
|
|
34
41
|
oas3_0Rules: {
|
|
@@ -49,5 +56,5 @@ exports.default = {
|
|
|
49
56
|
'no-unused-components': 'error',
|
|
50
57
|
'no-undefined-server-variable': 'error',
|
|
51
58
|
'no-servers-empty-enum': 'error',
|
|
52
|
-
}
|
|
59
|
+
},
|
|
53
60
|
};
|
package/lib/config/config.d.ts
CHANGED
package/lib/config/config.js
CHANGED
|
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Config = exports.LintConfig = exports.IGNORE_FILE = void 0;
|
|
4
4
|
const fs = require("fs");
|
|
5
5
|
const path = require("path");
|
|
6
|
-
const yaml = require("js-yaml");
|
|
7
6
|
const path_1 = require("path");
|
|
8
7
|
const colorette_1 = require("colorette");
|
|
8
|
+
const js_yaml_1 = require("../js-yaml");
|
|
9
9
|
const utils_1 = require("../utils");
|
|
10
10
|
const oas_types_1 = require("../oas-types");
|
|
11
11
|
const recommended_1 = require("./recommended");
|
|
@@ -57,7 +57,7 @@ class LintConfig {
|
|
|
57
57
|
if (fs.hasOwnProperty('existsSync') && fs.existsSync(ignoreFile)) {
|
|
58
58
|
// TODO: parse errors
|
|
59
59
|
this.ignore =
|
|
60
|
-
|
|
60
|
+
js_yaml_1.parseYaml(fs.readFileSync(ignoreFile, 'utf-8')) || {};
|
|
61
61
|
// resolve ignore paths
|
|
62
62
|
for (const fileName of Object.keys(this.ignore)) {
|
|
63
63
|
this.ignore[path.resolve(path_1.dirname(ignoreFile), fileName)] = this.ignore[fileName];
|
|
@@ -73,12 +73,12 @@ class LintConfig {
|
|
|
73
73
|
const ignoreFile = path.join(dir, exports.IGNORE_FILE);
|
|
74
74
|
const mapped = {};
|
|
75
75
|
for (const absFileName of Object.keys(this.ignore)) {
|
|
76
|
-
const ignoredRules = (mapped[path.relative(dir, absFileName)] = this.ignore[absFileName]);
|
|
76
|
+
const ignoredRules = (mapped[utils_1.slash(path.relative(dir, absFileName))] = this.ignore[absFileName]);
|
|
77
77
|
for (const ruleId of Object.keys(ignoredRules)) {
|
|
78
78
|
ignoredRules[ruleId] = Array.from(ignoredRules[ruleId]);
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
-
fs.writeFileSync(ignoreFile, IGNORE_BANNER +
|
|
81
|
+
fs.writeFileSync(ignoreFile, IGNORE_BANNER + js_yaml_1.stringifyYaml(mapped));
|
|
82
82
|
}
|
|
83
83
|
addIgnore(problem) {
|
|
84
84
|
const ignore = this.ignore;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { BundleOutputFormat, readFileFromUrl } from './utils';
|
|
1
|
+
export { BundleOutputFormat, readFileFromUrl, slash } from './utils';
|
|
2
2
|
export { Oas3_1Types } from './types/oas3_1';
|
|
3
3
|
export { Oas3Types } from './types/oas3';
|
|
4
4
|
export { Oas2Types } from './types/oas2';
|
|
@@ -12,6 +12,7 @@ export { Config, LintConfig, RawConfig, IGNORE_FILE } from './config/config';
|
|
|
12
12
|
export { loadConfig } from './config/load';
|
|
13
13
|
export { RedoclyClient } from './redocly';
|
|
14
14
|
export { Source, BaseResolver, Document, resolveDocument, ResolveError, YamlParseError, makeDocumentFromString, } from './resolve';
|
|
15
|
+
export { parseYaml, stringifyYaml } from './js-yaml';
|
|
15
16
|
export { unescapePointer } from './ref-utils';
|
|
16
17
|
export { detectOpenAPI, OasMajorVersion, openAPIMajor, OasVersion } from './oas-types';
|
|
17
18
|
export { normalizeVisitors } from './visitors';
|
package/lib/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
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.unescapePointer = 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.readFileFromUrl = void 0;
|
|
3
|
+
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.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;
|
|
4
4
|
var utils_1 = require("./utils");
|
|
5
5
|
Object.defineProperty(exports, "readFileFromUrl", { enumerable: true, get: function () { return utils_1.readFileFromUrl; } });
|
|
6
|
+
Object.defineProperty(exports, "slash", { enumerable: true, get: function () { return utils_1.slash; } });
|
|
6
7
|
var oas3_1_1 = require("./types/oas3_1");
|
|
7
8
|
Object.defineProperty(exports, "Oas3_1Types", { enumerable: true, get: function () { return oas3_1_1.Oas3_1Types; } });
|
|
8
9
|
var oas3_1 = require("./types/oas3");
|
|
@@ -30,6 +31,9 @@ Object.defineProperty(exports, "resolveDocument", { enumerable: true, get: funct
|
|
|
30
31
|
Object.defineProperty(exports, "ResolveError", { enumerable: true, get: function () { return resolve_1.ResolveError; } });
|
|
31
32
|
Object.defineProperty(exports, "YamlParseError", { enumerable: true, get: function () { return resolve_1.YamlParseError; } });
|
|
32
33
|
Object.defineProperty(exports, "makeDocumentFromString", { enumerable: true, get: function () { return resolve_1.makeDocumentFromString; } });
|
|
34
|
+
var js_yaml_1 = require("./js-yaml");
|
|
35
|
+
Object.defineProperty(exports, "parseYaml", { enumerable: true, get: function () { return js_yaml_1.parseYaml; } });
|
|
36
|
+
Object.defineProperty(exports, "stringifyYaml", { enumerable: true, get: function () { return js_yaml_1.stringifyYaml; } });
|
|
33
37
|
var ref_utils_1 = require("./ref-utils");
|
|
34
38
|
Object.defineProperty(exports, "unescapePointer", { enumerable: true, get: function () { return ref_utils_1.unescapePointer; } });
|
|
35
39
|
var oas_types_1 = require("./oas-types");
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.stringifyYaml = exports.parseYaml = void 0;
|
|
4
|
+
// TODO: add a type for "types" https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/js-yaml/index.d.ts
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
const js_yaml_1 = require("js-yaml");
|
|
7
|
+
const DEFAULT_SCHEMA_WITHOUT_TIMESTAMP = js_yaml_1.JSON_SCHEMA.extend({
|
|
8
|
+
implicit: [js_yaml_1.types.merge],
|
|
9
|
+
explicit: [
|
|
10
|
+
js_yaml_1.types.binary,
|
|
11
|
+
js_yaml_1.types.omap,
|
|
12
|
+
js_yaml_1.types.pairs,
|
|
13
|
+
js_yaml_1.types.set,
|
|
14
|
+
],
|
|
15
|
+
});
|
|
16
|
+
const parseYaml = (str, opts) => js_yaml_1.load(str, Object.assign({ schema: DEFAULT_SCHEMA_WITHOUT_TIMESTAMP }, opts));
|
|
17
|
+
exports.parseYaml = parseYaml;
|
|
18
|
+
const stringifyYaml = (obj, opts) => js_yaml_1.dump(obj, Object.assign({ schema: DEFAULT_SCHEMA_WITHOUT_TIMESTAMP }, opts));
|
|
19
|
+
exports.stringifyYaml = stringifyYaml;
|
package/lib/oas-types.js
CHANGED
|
@@ -19,6 +19,9 @@ function detectOpenAPI(root) {
|
|
|
19
19
|
if (!(root.openapi || root.swagger)) {
|
|
20
20
|
throw new Error('This doesn’t look like an OpenAPI document.\n');
|
|
21
21
|
}
|
|
22
|
+
if (root.openapi && typeof root.openapi !== 'string') {
|
|
23
|
+
throw new Error(`Invalid OpenAPI version: should be a string but got "${typeof root.openapi}"`);
|
|
24
|
+
}
|
|
22
25
|
if (root.openapi && root.openapi.startsWith('3.0')) {
|
|
23
26
|
return OasVersion.Version3_0;
|
|
24
27
|
}
|
package/lib/resolve.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export declare type Document = {
|
|
|
29
29
|
};
|
|
30
30
|
export declare function makeDocumentFromString(sourceString: string, absoluteRef: string): {
|
|
31
31
|
source: Source;
|
|
32
|
-
parsed:
|
|
32
|
+
parsed: unknown;
|
|
33
33
|
};
|
|
34
34
|
export declare class BaseResolver {
|
|
35
35
|
private config;
|
package/lib/resolve.js
CHANGED
|
@@ -13,7 +13,6 @@ exports.resolveDocument = exports.BaseResolver = exports.makeDocumentFromString
|
|
|
13
13
|
const fs = require("fs");
|
|
14
14
|
const path = require("path");
|
|
15
15
|
const url = require("url");
|
|
16
|
-
const yaml = require("js-yaml");
|
|
17
16
|
const ref_utils_1 = require("./ref-utils");
|
|
18
17
|
const types_1 = require("./types");
|
|
19
18
|
const utils_1 = require("./utils");
|
|
@@ -56,7 +55,7 @@ class ResolveError extends Error {
|
|
|
56
55
|
}
|
|
57
56
|
}
|
|
58
57
|
exports.ResolveError = ResolveError;
|
|
59
|
-
const jsYamlErrorLineColRegexp =
|
|
58
|
+
const jsYamlErrorLineColRegexp = /\((\d+):(\d+)\)$/;
|
|
60
59
|
class YamlParseError extends Error {
|
|
61
60
|
constructor(originalError, source) {
|
|
62
61
|
super(originalError.message.split('\n')[0]);
|
|
@@ -75,7 +74,7 @@ function makeDocumentFromString(sourceString, absoluteRef) {
|
|
|
75
74
|
try {
|
|
76
75
|
return {
|
|
77
76
|
source,
|
|
78
|
-
parsed:
|
|
77
|
+
parsed: utils_1.parseYaml(sourceString, { filename: absoluteRef }),
|
|
79
78
|
};
|
|
80
79
|
}
|
|
81
80
|
catch (e) {
|
|
@@ -128,7 +127,7 @@ class BaseResolver {
|
|
|
128
127
|
try {
|
|
129
128
|
return {
|
|
130
129
|
source,
|
|
131
|
-
parsed:
|
|
130
|
+
parsed: utils_1.parseYaml(source.body, { filename: source.absoluteRef }),
|
|
132
131
|
};
|
|
133
132
|
}
|
|
134
133
|
catch (e) {
|
package/lib/rules/builtin.d.ts
CHANGED
|
@@ -7,8 +7,14 @@ export declare const preprocessors: {
|
|
|
7
7
|
export declare const decorators: {
|
|
8
8
|
oas3: {
|
|
9
9
|
'registry-dependencies': import("../visitors").Oas3Decorator;
|
|
10
|
+
'operation-description-override': import("../visitors").Oas3Decorator;
|
|
11
|
+
'tag-description-override': import("../visitors").Oas3Decorator;
|
|
12
|
+
'info-description-override': import("../visitors").Oas3Decorator;
|
|
10
13
|
};
|
|
11
14
|
oas2: {
|
|
12
15
|
'registry-dependencies': import("../visitors").Oas2Decorator;
|
|
16
|
+
'operation-description-override': import("../visitors").Oas2Decorator;
|
|
17
|
+
'tag-description-override': import("../visitors").Oas2Decorator;
|
|
18
|
+
'info-description-override': import("../visitors").Oas2Decorator;
|
|
13
19
|
};
|
|
14
20
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InfoDescriptionOverride = void 0;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const InfoDescriptionOverride = ({ filePath }) => {
|
|
6
|
+
return {
|
|
7
|
+
Info: {
|
|
8
|
+
leave(info, { report, location }) {
|
|
9
|
+
if (!filePath)
|
|
10
|
+
throw new Error(`Parameter "filePath" is not provided for "info-description-override" rule`);
|
|
11
|
+
try {
|
|
12
|
+
info.description = utils_1.readFileAsStringSync(filePath);
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
report({
|
|
16
|
+
message: `Failed to read markdown override file for "info.description".\n${e.message}`,
|
|
17
|
+
location: location.child('description'),
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
exports.InfoDescriptionOverride = InfoDescriptionOverride;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NoHttpVerbsInPaths = void 0;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const httpMethods = ['get', 'head', 'post', 'put', 'patch', 'delete', 'options', 'trace'];
|
|
6
|
+
const NoHttpVerbsInPaths = ({ splitIntoWords }) => {
|
|
7
|
+
return {
|
|
8
|
+
PathItem(_path, { key, report, location }) {
|
|
9
|
+
const pathKey = key.toString();
|
|
10
|
+
if (!pathKey.startsWith('/'))
|
|
11
|
+
return;
|
|
12
|
+
const pathSegments = pathKey.split('/');
|
|
13
|
+
for (const pathSegment of pathSegments) {
|
|
14
|
+
if (!pathSegment || utils_1.isPathParameter(pathSegment))
|
|
15
|
+
continue;
|
|
16
|
+
const isHttpMethodIncluded = (method) => {
|
|
17
|
+
return splitIntoWords
|
|
18
|
+
? utils_1.splitCamelCaseIntoWords(pathSegment).has(method)
|
|
19
|
+
: pathSegment.toLocaleLowerCase().includes(method);
|
|
20
|
+
};
|
|
21
|
+
for (const method of httpMethods) {
|
|
22
|
+
if (isHttpMethodIncluded(method)) {
|
|
23
|
+
report({
|
|
24
|
+
message: `path \`${pathKey}\` should not contain http verb ${method}`,
|
|
25
|
+
location: location.key(),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
exports.NoHttpVerbsInPaths = NoHttpVerbsInPaths;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OperationDescriptionOverride = void 0;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const OperationDescriptionOverride = ({ operationIds }) => {
|
|
6
|
+
return {
|
|
7
|
+
Operation: {
|
|
8
|
+
leave(operation, { report, location }) {
|
|
9
|
+
if (!operation.operationId)
|
|
10
|
+
return;
|
|
11
|
+
if (!operationIds)
|
|
12
|
+
throw new Error(`Parameter "operationIds" is not provided for "operation-description-override" rule`);
|
|
13
|
+
const operationId = operation.operationId;
|
|
14
|
+
if (operationIds[operationId]) {
|
|
15
|
+
try {
|
|
16
|
+
operation.description = utils_1.readFileAsStringSync(operationIds[operationId]);
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
report({
|
|
20
|
+
message: `Failed to read markdown override file for operation "${operationId}".\n${e.message}`,
|
|
21
|
+
location: location.child('operationId').key(),
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
exports.OperationDescriptionOverride = OperationDescriptionOverride;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PathExcludesPatterns = void 0;
|
|
4
|
+
const PathExcludesPatterns = ({ patterns }) => {
|
|
5
|
+
return {
|
|
6
|
+
PathItem(_path, { report, key, location }) {
|
|
7
|
+
if (!patterns)
|
|
8
|
+
throw new Error(`Parameter "patterns" is not provided for "path-excludes-patterns" rule`);
|
|
9
|
+
const pathKey = key.toString();
|
|
10
|
+
if (pathKey.startsWith('/')) {
|
|
11
|
+
const matches = patterns.filter((pattern) => pathKey.match(pattern));
|
|
12
|
+
for (const match of matches) {
|
|
13
|
+
report({
|
|
14
|
+
message: `path \`${pathKey}\` should not match regex pattern: \`${match}\``,
|
|
15
|
+
location: location.key(),
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
exports.PathExcludesPatterns = PathExcludesPatterns;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PathSegmentPlural = void 0;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const PathSegmentPlural = (opts) => {
|
|
6
|
+
const { ignoreLastPathSegment, exceptions } = opts;
|
|
7
|
+
return {
|
|
8
|
+
PathItem: {
|
|
9
|
+
leave(_path, { report, key, location }) {
|
|
10
|
+
const pathKey = key.toString();
|
|
11
|
+
if (pathKey.startsWith('/')) {
|
|
12
|
+
const pathSegments = pathKey.split('/');
|
|
13
|
+
pathSegments.shift();
|
|
14
|
+
if (ignoreLastPathSegment && pathSegments.length > 1) {
|
|
15
|
+
pathSegments.pop();
|
|
16
|
+
}
|
|
17
|
+
for (const pathSegment of pathSegments) {
|
|
18
|
+
if (exceptions && exceptions.includes(pathSegment))
|
|
19
|
+
continue;
|
|
20
|
+
if (!utils_1.isPathParameter(pathSegment) && utils_1.isSingular(pathSegment)) {
|
|
21
|
+
report({
|
|
22
|
+
message: `path segment \`${pathSegment}\` should be plural.`,
|
|
23
|
+
location: location.key(),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
exports.PathSegmentPlural = PathSegmentPlural;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TagDescriptionOverride = void 0;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const TagDescriptionOverride = ({ tagNames }) => {
|
|
6
|
+
return {
|
|
7
|
+
Tag: {
|
|
8
|
+
leave(tag, { report }) {
|
|
9
|
+
if (!tagNames)
|
|
10
|
+
throw new Error(`Parameter "tagNames" is not provided for "tag-description-override" rule`);
|
|
11
|
+
if (tagNames[tag.name]) {
|
|
12
|
+
try {
|
|
13
|
+
tag.description = utils_1.readFileAsStringSync(tagNames[tag.name]);
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
report({
|
|
17
|
+
message: `Failed to read markdown override file for tag "${tag.name}".\n${e.message}`,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
exports.TagDescriptionOverride = TagDescriptionOverride;
|
|
@@ -30,8 +30,16 @@ export declare const rules: {
|
|
|
30
30
|
'no-identical-paths': Oas2Rule;
|
|
31
31
|
'no-ambiguous-paths': Oas2Rule;
|
|
32
32
|
'path-http-verbs-order': Oas2Rule;
|
|
33
|
+
'no-http-verbs-in-paths': Oas2Rule;
|
|
34
|
+
'path-excludes-patterns': Oas2Rule;
|
|
35
|
+
'request-mime-type': Oas2Rule;
|
|
36
|
+
'response-mime-type': Oas2Rule;
|
|
37
|
+
'path-segment-plural': Oas2Rule;
|
|
33
38
|
};
|
|
34
39
|
export declare const preprocessors: {};
|
|
35
40
|
export declare const decorators: {
|
|
36
41
|
'registry-dependencies': Oas2Decorator;
|
|
42
|
+
'operation-description-override': Oas2Decorator;
|
|
43
|
+
'tag-description-override': Oas2Decorator;
|
|
44
|
+
'info-description-override': Oas2Decorator;
|
|
37
45
|
};
|
package/lib/rules/oas2/index.js
CHANGED
|
@@ -31,6 +31,14 @@ const no_identical_paths_1 = require("../common/no-identical-paths");
|
|
|
31
31
|
const operation_operationId_1 = require("../common/operation-operationId");
|
|
32
32
|
const operation_summary_1 = require("../common/operation-summary");
|
|
33
33
|
const no_ambiguous_paths_1 = require("../common/no-ambiguous-paths");
|
|
34
|
+
const no_http_verbs_in_paths_1 = require("../common/no-http-verbs-in-paths");
|
|
35
|
+
const path_excludes_patterns_1 = require("../common/path-excludes-patterns");
|
|
36
|
+
const request_mime_type_1 = require("./request-mime-type");
|
|
37
|
+
const response_mime_type_1 = require("./response-mime-type");
|
|
38
|
+
const path_segment_plural_1 = require("../common/path-segment-plural");
|
|
39
|
+
const operation_description_override_1 = require("../common/operation-description-override");
|
|
40
|
+
const tag_description_override_1 = require("../common/tag-description-override");
|
|
41
|
+
const info_description_override_1 = require("../common/info-description-override");
|
|
34
42
|
exports.rules = {
|
|
35
43
|
spec: spec_1.OasSpec,
|
|
36
44
|
'info-description': info_description_1.InfoDescription,
|
|
@@ -62,8 +70,16 @@ exports.rules = {
|
|
|
62
70
|
'no-identical-paths': no_identical_paths_1.NoIdenticalPaths,
|
|
63
71
|
'no-ambiguous-paths': no_ambiguous_paths_1.NoAmbiguousPaths,
|
|
64
72
|
'path-http-verbs-order': path_http_verbs_order_1.PathHttpVerbsOrder,
|
|
73
|
+
'no-http-verbs-in-paths': no_http_verbs_in_paths_1.NoHttpVerbsInPaths,
|
|
74
|
+
'path-excludes-patterns': path_excludes_patterns_1.PathExcludesPatterns,
|
|
75
|
+
'request-mime-type': request_mime_type_1.RequestMimeType,
|
|
76
|
+
'response-mime-type': response_mime_type_1.ResponseMimeType,
|
|
77
|
+
'path-segment-plural': path_segment_plural_1.PathSegmentPlural,
|
|
65
78
|
};
|
|
66
79
|
exports.preprocessors = {};
|
|
67
80
|
exports.decorators = {
|
|
68
81
|
'registry-dependencies': registry_dependencies_1.RegistryDependencies,
|
|
82
|
+
'operation-description-override': operation_description_override_1.OperationDescriptionOverride,
|
|
83
|
+
'tag-description-override': tag_description_override_1.TagDescriptionOverride,
|
|
84
|
+
'info-description-override': info_description_override_1.InfoDescriptionOverride,
|
|
69
85
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RequestMimeType = void 0;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const RequestMimeType = ({ allowedValues }) => {
|
|
6
|
+
return {
|
|
7
|
+
DefinitionRoot(root, ctx) {
|
|
8
|
+
utils_1.validateMimeType({ type: 'consumes', value: root }, ctx, allowedValues);
|
|
9
|
+
},
|
|
10
|
+
Operation: {
|
|
11
|
+
leave(operation, ctx) {
|
|
12
|
+
utils_1.validateMimeType({ type: 'consumes', value: operation }, ctx, allowedValues);
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
exports.RequestMimeType = RequestMimeType;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ResponseMimeType = void 0;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const ResponseMimeType = ({ allowedValues }) => {
|
|
6
|
+
return {
|
|
7
|
+
DefinitionRoot(root, ctx) {
|
|
8
|
+
utils_1.validateMimeType({ type: 'produces', value: root }, ctx, allowedValues);
|
|
9
|
+
},
|
|
10
|
+
Operation: {
|
|
11
|
+
leave(operation, ctx) {
|
|
12
|
+
utils_1.validateMimeType({ type: 'produces', value: operation }, ctx, allowedValues);
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
exports.ResponseMimeType = ResponseMimeType;
|
|
@@ -4,4 +4,7 @@ export declare const rules: Oas3RuleSet;
|
|
|
4
4
|
export declare const preprocessors: {};
|
|
5
5
|
export declare const decorators: {
|
|
6
6
|
'registry-dependencies': Oas3Decorator;
|
|
7
|
+
'operation-description-override': Oas3Decorator;
|
|
8
|
+
'tag-description-override': Oas3Decorator;
|
|
9
|
+
'info-description-override': Oas3Decorator;
|
|
7
10
|
};
|