@redocly/openapi-core 1.0.0-beta.49 → 1.0.0-beta.53
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__/normalizeVisitors.test.ts +1 -1
- package/__tests__/utils.ts +1 -1
- package/__tests__/walk.test.ts +77 -4
- package/lib/benchmark/benches/recommended-oas3.bench.js +2 -1
- package/lib/benchmark/utils.d.ts +1 -1
- package/lib/bundle.d.ts +1 -1
- package/lib/bundle.js +10 -10
- package/lib/config/builtIn.d.ts +2 -1
- package/lib/config/builtIn.js +9 -1
- package/lib/config/config.d.ts +5 -7
- package/lib/config/config.js +40 -100
- package/lib/config/load.d.ts +2 -0
- package/lib/config/load.js +65 -0
- package/lib/config/rules.d.ts +1 -1
- package/lib/format/codeframes.js +1 -1
- package/lib/index.d.ts +4 -3
- package/lib/index.js +13 -11
- package/lib/lint.d.ts +6 -19
- package/lib/lint.js +13 -43
- package/lib/oas-types.d.ts +19 -0
- package/lib/oas-types.js +42 -0
- package/lib/resolve.d.ts +6 -2
- package/lib/resolve.js +18 -5
- package/lib/rules/ajv.d.ts +3 -3
- package/lib/rules/ajv.js +21 -18
- package/lib/rules/common/info-contact.js +2 -1
- package/lib/rules/common/info-description.js +2 -1
- package/lib/rules/common/info-license-url.js +2 -1
- package/lib/rules/common/license-url.js +2 -1
- package/lib/rules/common/no-ambiguous-paths.js +2 -1
- package/lib/rules/common/no-enum-type-mismatch.js +2 -1
- package/lib/rules/common/no-identical-paths.js +2 -1
- package/lib/rules/common/no-path-trailing-slash.js +2 -1
- package/lib/rules/common/operation-2xx-response.js +2 -1
- package/lib/rules/common/operation-description.js +2 -1
- package/lib/rules/common/operation-operationId-unique.js +2 -1
- package/lib/rules/common/operation-operationId-url-safe.js +2 -1
- package/lib/rules/common/operation-operationId.js +9 -4
- package/lib/rules/common/operation-parameters-unique.js +2 -1
- package/lib/rules/common/operation-security-defined.js +2 -1
- package/lib/rules/common/operation-singular-tag.js +2 -1
- package/lib/rules/common/operation-summary.js +2 -1
- package/lib/rules/common/operation-tag-defined.js +2 -1
- package/lib/rules/common/parameter-description.js +2 -1
- package/lib/rules/common/path-declaration-must-exist.js +2 -1
- package/lib/rules/common/path-http-verbs-order.js +2 -1
- package/lib/rules/common/path-not-include-query.js +2 -1
- package/lib/rules/common/path-params-defined.js +3 -2
- package/lib/rules/common/paths-kebab-case.js +2 -1
- package/lib/rules/common/registry-dependencies.js +2 -1
- package/lib/rules/common/spec.js +5 -2
- package/lib/rules/common/tag-description.js +2 -1
- package/lib/rules/common/tags-alphabetical.js +2 -1
- package/lib/rules/no-unresolved-refs.js +2 -1
- package/lib/rules/oas2/boolean-parameter-prefixes.js +2 -1
- package/lib/rules/oas2/index.d.ts +1 -1
- package/lib/rules/oas2/index.js +1 -1
- package/lib/rules/oas3/boolean-parameter-prefixes.js +2 -1
- package/lib/rules/oas3/index.d.ts +2 -1
- package/lib/rules/oas3/index.js +2 -2
- package/lib/rules/oas3/no-empty-servers.js +2 -1
- package/lib/rules/oas3/no-example-value-and-externalValue.js +2 -1
- package/lib/rules/oas3/no-invalid-media-type-examples.js +20 -10
- package/lib/rules/oas3/no-server-example.com.js +2 -1
- package/lib/rules/oas3/no-server-trailing-slash.js +2 -1
- package/lib/rules/oas3/no-servers-empty-enum.js +2 -1
- package/lib/rules/oas3/no-undefined-server-variable.js +2 -1
- package/lib/rules/oas3/no-unused-components.js +2 -1
- package/lib/rules/other/stats.js +2 -1
- package/lib/types/oas2.js +1 -1
- package/lib/types/oas3.js +1 -1
- package/lib/types/oas3_1.js +1 -1
- package/lib/utils.d.ts +1 -1
- package/lib/visitors.d.ts +3 -1
- package/lib/visitors.js +4 -4
- package/lib/walk.d.ts +1 -1
- package/lib/walk.js +11 -2
- package/package.json +7 -7
- package/src/__tests__/lint.test.ts +44 -0
- package/src/benchmark/benches/recommended-oas3.bench.ts +2 -1
- package/src/benchmark/benchmark.js +3 -1
- package/src/benchmark/utils.ts +1 -1
- package/src/bundle.ts +2 -2
- package/src/config/__tests__/resolve-plugins.test.ts +1 -1
- package/src/config/builtIn.ts +11 -1
- package/src/config/config.ts +30 -78
- package/src/config/load.ts +60 -0
- package/src/config/rules.ts +1 -1
- package/src/format/codeframes.ts +1 -1
- package/src/index.ts +4 -3
- package/src/lint.ts +19 -56
- package/src/oas-types.ts +58 -0
- package/src/resolve.ts +17 -4
- package/src/rules/__tests__/config.ts +10 -0
- package/src/rules/__tests__/no-unresolved-refs.test.ts +9 -21
- package/src/rules/ajv.ts +27 -23
- package/src/rules/common/__tests__/info-description.test.ts +8 -16
- package/src/rules/common/__tests__/info-license.test.ts +3 -3
- package/src/rules/common/__tests__/license-url.test.ts +3 -3
- package/src/rules/common/__tests__/no-ambiguous-paths.test.ts +2 -2
- package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +50 -5
- package/src/rules/common/__tests__/no-identical-paths.test.ts +2 -2
- package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +4 -4
- package/src/rules/common/__tests__/operation-2xx-response.test.ts +4 -4
- package/src/rules/common/__tests__/operation-operationId-unique.test.ts +3 -3
- package/src/rules/common/__tests__/operation-operationId-url-safe.test.ts +2 -5
- package/src/rules/common/__tests__/operation-parameters-unique.test.ts +5 -17
- package/src/rules/common/__tests__/operation-security-defined.test.ts +3 -3
- package/src/rules/common/__tests__/operation-singular-tag.test.ts +3 -3
- package/src/rules/common/__tests__/path-http-verbs-order.test.ts +3 -3
- package/src/rules/common/__tests__/path-not-include-query.test.ts +3 -3
- package/src/rules/common/__tests__/path-params-defined.test.ts +4 -4
- package/src/rules/common/__tests__/paths-kebab-case.test.ts +3 -3
- package/src/rules/common/__tests__/tag-description.test.ts +3 -3
- package/src/rules/common/__tests__/tags-alphabetical.test.ts +3 -3
- package/src/rules/common/operation-operationId.ts +7 -3
- package/src/rules/common/spec.ts +4 -1
- package/src/rules/oas2/__tests__/boolean-parameter-prefixes.test.ts +7 -10
- package/src/rules/oas2/__tests__/spec/referenceableScalars.test.ts +3 -6
- package/src/rules/oas2/__tests__/spec/utils.ts +2 -0
- package/src/rules/oas2/index.ts +1 -10
- package/src/rules/oas3/__tests__/boolean-parameter-prefixes.test.ts +7 -10
- package/src/rules/oas3/__tests__/fixtures/common.yaml +11 -0
- package/src/rules/oas3/__tests__/no-empty-enum-servers.com.test.ts +7 -7
- package/src/rules/oas3/__tests__/no-example-value-and-externalValue.test.ts +3 -9
- package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +103 -29
- package/src/rules/oas3/__tests__/no-server-example.com.test.ts +3 -3
- package/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts +3 -3
- package/src/rules/oas3/__tests__/no-unused-components.test.ts +2 -2
- package/src/rules/oas3/__tests__/spec/spec.test.ts +3 -1
- package/src/rules/oas3/__tests__/spec/utils.ts +2 -0
- package/src/rules/oas3/index.ts +3 -4
- package/src/rules/oas3/no-invalid-media-type-examples.ts +27 -19
- package/src/visitors.ts +12 -8
- package/src/walk.ts +24 -8
- package/tsconfig.tsbuildinfo +1 -3084
package/__tests__/utils.ts
CHANGED
|
@@ -4,7 +4,7 @@ import * as path from 'path';
|
|
|
4
4
|
import { Document, Source } from '../src/resolve';
|
|
5
5
|
import { NormalizedProblem } from '../src/walk';
|
|
6
6
|
import { RuleConfig, LintConfig, Plugin } from '../src/config/config';
|
|
7
|
-
import { Oas3RuleSet } from '../src/
|
|
7
|
+
import { Oas3RuleSet } from '../src/oas-types';
|
|
8
8
|
|
|
9
9
|
export function parseYamlToDocument(body: string, absoluteRef: string = ''): Document {
|
|
10
10
|
return {
|
package/__tests__/walk.test.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import outdent from 'outdent';
|
|
2
|
+
import each from 'jest-each';
|
|
2
3
|
import * as path from 'path';
|
|
3
4
|
|
|
4
|
-
import { lintDocument
|
|
5
|
+
import { lintDocument } from '../src/lint';
|
|
5
6
|
|
|
6
7
|
import { parseYamlToDocument, replaceSourceWithRef, makeConfigForRuleset } from './utils';
|
|
7
8
|
import { BaseResolver, Document } from '../src/resolve';
|
|
8
9
|
import { listOf } from '../src/types';
|
|
10
|
+
import { Oas3RuleSet } from '../src/oas-types';
|
|
9
11
|
|
|
10
12
|
describe('walk order', () => {
|
|
11
13
|
it('should run visitors', async () => {
|
|
@@ -1245,7 +1247,10 @@ describe('context.resolve', () => {
|
|
|
1245
1247
|
});
|
|
1246
1248
|
|
|
1247
1249
|
describe('type extensions', () => {
|
|
1248
|
-
|
|
1250
|
+
each([
|
|
1251
|
+
['3.0.0', 'oas3_0'],
|
|
1252
|
+
['3.1.0', 'oas3_1'],
|
|
1253
|
+
]).it('should correctly visit OpenAPI %s extended types', async (openapi, oas) => {
|
|
1249
1254
|
const calls: string[] = [];
|
|
1250
1255
|
|
|
1251
1256
|
const testRuleSet: Oas3RuleSet = {
|
|
@@ -1273,7 +1278,7 @@ describe('type extensions', () => {
|
|
|
1273
1278
|
|
|
1274
1279
|
const document = parseYamlToDocument(
|
|
1275
1280
|
outdent`
|
|
1276
|
-
openapi:
|
|
1281
|
+
openapi: ${openapi}
|
|
1277
1282
|
x-webhooks:
|
|
1278
1283
|
name: test
|
|
1279
1284
|
parameters:
|
|
@@ -1288,7 +1293,7 @@ describe('type extensions', () => {
|
|
|
1288
1293
|
config: makeConfigForRuleset(testRuleSet, {
|
|
1289
1294
|
typeExtension: {
|
|
1290
1295
|
oas3(types, version) {
|
|
1291
|
-
expect(version).toEqual(
|
|
1296
|
+
expect(version).toEqual(oas);
|
|
1292
1297
|
|
|
1293
1298
|
return {
|
|
1294
1299
|
...types,
|
|
@@ -1326,3 +1331,71 @@ describe('type extensions', () => {
|
|
|
1326
1331
|
`);
|
|
1327
1332
|
});
|
|
1328
1333
|
});
|
|
1334
|
+
|
|
1335
|
+
describe('ignoreNextRules', () => {
|
|
1336
|
+
it('should correctly skip top level', async () => {
|
|
1337
|
+
const calls: string[] = [];
|
|
1338
|
+
|
|
1339
|
+
const testRuleSet: Oas3RuleSet = {
|
|
1340
|
+
skip: jest.fn(() => {
|
|
1341
|
+
return {
|
|
1342
|
+
Operation: {
|
|
1343
|
+
enter: jest.fn((op, ctx) => {
|
|
1344
|
+
if (op.operationId === 'get') {
|
|
1345
|
+
ctx.ignoreNextVisitorsOnNode();
|
|
1346
|
+
calls.push(`enter and skip operation ${op.operationId}`);
|
|
1347
|
+
} else {
|
|
1348
|
+
calls.push(`enter and not skip operation ${op.operationId}`);
|
|
1349
|
+
}
|
|
1350
|
+
}),
|
|
1351
|
+
leave: jest.fn((op) => {
|
|
1352
|
+
if (op.operationId === 'get') {
|
|
1353
|
+
calls.push(`leave skipped operation ${op.operationId}`);
|
|
1354
|
+
} else {
|
|
1355
|
+
calls.push(`leave not skipped operation ${op.operationId}`);
|
|
1356
|
+
}
|
|
1357
|
+
}),
|
|
1358
|
+
},
|
|
1359
|
+
};
|
|
1360
|
+
}),
|
|
1361
|
+
test: jest.fn(() => {
|
|
1362
|
+
return {
|
|
1363
|
+
Operation: {
|
|
1364
|
+
enter: jest.fn((op) => calls.push(`enter operation ${op.operationId}`)),
|
|
1365
|
+
leave: jest.fn((op) => calls.push(`leave operation ${op.operationId}`)),
|
|
1366
|
+
},
|
|
1367
|
+
};
|
|
1368
|
+
}),
|
|
1369
|
+
};
|
|
1370
|
+
|
|
1371
|
+
const document = parseYamlToDocument(
|
|
1372
|
+
outdent`
|
|
1373
|
+
openapi: 3.0.0
|
|
1374
|
+
paths:
|
|
1375
|
+
/pet:
|
|
1376
|
+
get:
|
|
1377
|
+
operationId: get
|
|
1378
|
+
put:
|
|
1379
|
+
operationId: put
|
|
1380
|
+
`,
|
|
1381
|
+
'',
|
|
1382
|
+
);
|
|
1383
|
+
|
|
1384
|
+
await lintDocument({
|
|
1385
|
+
externalRefResolver: new BaseResolver(),
|
|
1386
|
+
document,
|
|
1387
|
+
config: makeConfigForRuleset(testRuleSet),
|
|
1388
|
+
});
|
|
1389
|
+
|
|
1390
|
+
expect(calls).toMatchInlineSnapshot(`
|
|
1391
|
+
Array [
|
|
1392
|
+
"enter and skip operation get",
|
|
1393
|
+
"leave skipped operation get",
|
|
1394
|
+
"enter and not skip operation put",
|
|
1395
|
+
"enter operation put",
|
|
1396
|
+
"leave not skipped operation put",
|
|
1397
|
+
"leave operation put",
|
|
1398
|
+
]
|
|
1399
|
+
`);
|
|
1400
|
+
});
|
|
1401
|
+
});
|
|
@@ -7,6 +7,7 @@ const lint_1 = require("../../lint");
|
|
|
7
7
|
const config_1 = require("../../config/config");
|
|
8
8
|
const resolve_1 = require("../../resolve");
|
|
9
9
|
const utils_1 = require("../utils");
|
|
10
|
+
const builtIn_1 = require("../../config/builtIn");
|
|
10
11
|
exports.name = 'Validate with recommended rules';
|
|
11
12
|
exports.count = 10;
|
|
12
13
|
const rebillyDefinitionRef = path_1.resolve(path_1.join(__dirname, 'rebilly.yaml'));
|
|
@@ -15,7 +16,7 @@ function measureAsync() {
|
|
|
15
16
|
return lint_1.lintDocument({
|
|
16
17
|
externalRefResolver: new resolve_1.BaseResolver(),
|
|
17
18
|
document: rebillyDocument,
|
|
18
|
-
config: new config_1.LintConfig({}),
|
|
19
|
+
config: new config_1.LintConfig({ plugins: [builtIn_1.defaultPlugin] }),
|
|
19
20
|
});
|
|
20
21
|
}
|
|
21
22
|
exports.measureAsync = measureAsync;
|
package/lib/benchmark/utils.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Document } from '../resolve';
|
|
2
|
-
import { Oas3RuleSet } from '../
|
|
2
|
+
import { Oas3RuleSet } from '../oas-types';
|
|
3
3
|
import { LintConfig, Plugin } from '../config/config';
|
|
4
4
|
export declare function parseYamlToDocument(body: string, absoluteRef?: string): Document;
|
|
5
5
|
export declare function makeConfigForRuleset(rules: Oas3RuleSet, plugin?: Partial<Plugin>): LintConfig;
|
package/lib/bundle.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseResolver, Document } from './resolve';
|
|
2
2
|
import { Oas3Rule } from './visitors';
|
|
3
3
|
import { NodeType } from './types';
|
|
4
|
-
import { Config, LintConfig } from './config/config';
|
|
4
|
+
import type { Config, LintConfig } from './config/config';
|
|
5
5
|
export declare type Oas3RuleSet = Record<string, Oas3Rule>;
|
|
6
6
|
export declare enum OasVersion {
|
|
7
7
|
Version2 = "oas2",
|
package/lib/bundle.js
CHANGED
|
@@ -18,7 +18,7 @@ const oas2_1 = require("./types/oas2");
|
|
|
18
18
|
const oas3_1_1 = require("./types/oas3_1");
|
|
19
19
|
const types_1 = require("./types");
|
|
20
20
|
const walk_1 = require("./walk");
|
|
21
|
-
const
|
|
21
|
+
const oas_types_1 = require("./oas-types");
|
|
22
22
|
const ref_utils_1 = require("./ref-utils");
|
|
23
23
|
const rules_1 = require("./config/rules");
|
|
24
24
|
const no_unresolved_refs_1 = require("./rules/no-unresolved-refs");
|
|
@@ -46,10 +46,10 @@ exports.bundle = bundle;
|
|
|
46
46
|
function bundleDocument(opts) {
|
|
47
47
|
return __awaiter(this, void 0, void 0, function* () {
|
|
48
48
|
const { document, config, customTypes, externalRefResolver, dereference = false } = opts;
|
|
49
|
-
const oasVersion =
|
|
50
|
-
const oasMajorVersion =
|
|
49
|
+
const oasVersion = oas_types_1.detectOpenAPI(document.parsed);
|
|
50
|
+
const oasMajorVersion = oas_types_1.openAPIMajor(oasVersion);
|
|
51
51
|
const rules = config.getRulesForOasVersion(oasMajorVersion);
|
|
52
|
-
const types = types_1.normalizeTypes(config.extendTypes((customTypes !== null && customTypes !== void 0 ? customTypes : oasMajorVersion ===
|
|
52
|
+
const types = types_1.normalizeTypes(config.extendTypes((customTypes !== null && customTypes !== void 0 ? customTypes : oasMajorVersion === oas_types_1.OasMajorVersion.Version3) ? (oasVersion === OasVersion.Version3_1 ? oas3_1_1.Oas3_1Types : oas3_1.Oas3Types) : oas2_1.Oas2Types, oasVersion), config);
|
|
53
53
|
const preprocessors = rules_1.initRules(rules, config, 'preprocessors', oasVersion);
|
|
54
54
|
const decorators = rules_1.initRules(rules, config, 'decorators', oasVersion);
|
|
55
55
|
const ctx = {
|
|
@@ -87,7 +87,7 @@ function bundleDocument(opts) {
|
|
|
87
87
|
exports.bundleDocument = bundleDocument;
|
|
88
88
|
function mapTypeToComponent(typeName, version) {
|
|
89
89
|
switch (version) {
|
|
90
|
-
case
|
|
90
|
+
case oas_types_1.OasMajorVersion.Version3:
|
|
91
91
|
switch (typeName) {
|
|
92
92
|
case 'Schema':
|
|
93
93
|
return 'schemas';
|
|
@@ -110,7 +110,7 @@ function mapTypeToComponent(typeName, version) {
|
|
|
110
110
|
default:
|
|
111
111
|
return null;
|
|
112
112
|
}
|
|
113
|
-
case
|
|
113
|
+
case oas_types_1.OasMajorVersion.Version2:
|
|
114
114
|
switch (typeName) {
|
|
115
115
|
case 'Schema':
|
|
116
116
|
return 'definitions';
|
|
@@ -156,16 +156,16 @@ function makeBundleVisitor(version, dereference, rootDocument) {
|
|
|
156
156
|
},
|
|
157
157
|
DefinitionRoot: {
|
|
158
158
|
enter(root) {
|
|
159
|
-
if (version ===
|
|
159
|
+
if (version === oas_types_1.OasMajorVersion.Version3) {
|
|
160
160
|
components = root.components = root.components || {};
|
|
161
161
|
}
|
|
162
|
-
else if (version ===
|
|
162
|
+
else if (version === oas_types_1.OasMajorVersion.Version2) {
|
|
163
163
|
components = root;
|
|
164
164
|
}
|
|
165
165
|
},
|
|
166
166
|
},
|
|
167
167
|
};
|
|
168
|
-
if (version ===
|
|
168
|
+
if (version === oas_types_1.OasMajorVersion.Version3) {
|
|
169
169
|
visitor.DiscriminatorMapping = {
|
|
170
170
|
leave(mapping, ctx) {
|
|
171
171
|
for (const name of Object.keys(mapping)) {
|
|
@@ -200,7 +200,7 @@ function makeBundleVisitor(version, dereference, rootDocument) {
|
|
|
200
200
|
components[componentType] = components[componentType] || {};
|
|
201
201
|
const name = getComponentName(target, componentType, ctx);
|
|
202
202
|
components[componentType][name] = target.node;
|
|
203
|
-
if (version ===
|
|
203
|
+
if (version === oas_types_1.OasMajorVersion.Version3) {
|
|
204
204
|
return `#/components/${componentType}/${name}`;
|
|
205
205
|
}
|
|
206
206
|
else {
|
package/lib/config/builtIn.d.ts
CHANGED
package/lib/config/builtIn.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.builtInConfigs = void 0;
|
|
3
|
+
exports.defaultPlugin = exports.builtInConfigs = void 0;
|
|
4
4
|
const recommended_1 = require("./recommended");
|
|
5
5
|
const all_1 = require("./all");
|
|
6
6
|
const minimal_1 = require("./minimal");
|
|
7
|
+
const builtinRules = require("../rules/builtin");
|
|
7
8
|
exports.builtInConfigs = {
|
|
8
9
|
recommended: recommended_1.default,
|
|
9
10
|
minimal: minimal_1.default,
|
|
@@ -12,3 +13,10 @@ exports.builtInConfigs = {
|
|
|
12
13
|
decorators: { 'registry-dependencies': 'on' }
|
|
13
14
|
}
|
|
14
15
|
};
|
|
16
|
+
exports.defaultPlugin = {
|
|
17
|
+
id: '',
|
|
18
|
+
rules: builtinRules.rules,
|
|
19
|
+
preprocessors: builtinRules.preprocessors,
|
|
20
|
+
decorators: builtinRules.decorators,
|
|
21
|
+
configs: exports.builtInConfigs,
|
|
22
|
+
};
|
package/lib/config/config.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { OasVersion, Oas3PreprocessorsSet, OasMajorVersion, Oas3DecoratorsSet, Oas2RuleSet, Oas2PreprocessorsSet, Oas2DecoratorsSet } from '../
|
|
1
|
+
import { OasVersion, Oas3PreprocessorsSet, OasMajorVersion, Oas3DecoratorsSet, Oas2RuleSet, Oas2PreprocessorsSet, Oas2DecoratorsSet, Oas3RuleSet } from '../oas-types';
|
|
2
2
|
import { ProblemSeverity, NormalizedProblem } from '../walk';
|
|
3
|
-
import { Oas3RuleSet } from '../lint';
|
|
4
3
|
import { NodeType } from '../types';
|
|
5
4
|
export declare const IGNORE_FILE = ".redocly.lint-ignore.yaml";
|
|
6
5
|
export declare type RuleConfig = ProblemSeverity | 'off' | ({
|
|
@@ -95,16 +94,16 @@ export declare class LintConfig {
|
|
|
95
94
|
addProblemToIgnore(problem: NormalizedProblem): NormalizedProblem;
|
|
96
95
|
extendTypes(types: Record<string, NodeType>, version: OasVersion): Record<string, NodeType>;
|
|
97
96
|
getRuleSettings(ruleId: string, oasVersion: OasVersion): {
|
|
98
|
-
severity:
|
|
97
|
+
severity: ProblemSeverity | "off";
|
|
99
98
|
};
|
|
100
99
|
getPreprocessorSettings(ruleId: string, oasVersion: OasVersion): {
|
|
101
|
-
severity:
|
|
100
|
+
severity: ProblemSeverity | "off";
|
|
102
101
|
} | {
|
|
103
102
|
severity: ProblemSeverity;
|
|
104
103
|
options?: Record<string, any> | undefined;
|
|
105
104
|
};
|
|
106
105
|
getDecoratorSettings(ruleId: string, oasVersion: OasVersion): {
|
|
107
|
-
severity:
|
|
106
|
+
severity: ProblemSeverity | "off";
|
|
108
107
|
} | {
|
|
109
108
|
severity: ProblemSeverity;
|
|
110
109
|
options?: Record<string, any> | undefined;
|
|
@@ -114,7 +113,7 @@ export declare class LintConfig {
|
|
|
114
113
|
preprocessors: string[];
|
|
115
114
|
decorators: string[];
|
|
116
115
|
};
|
|
117
|
-
getRulesForOasVersion(version: OasMajorVersion):
|
|
116
|
+
getRulesForOasVersion(version: OasMajorVersion): Oas3RuleSet[] | Oas2RuleSet[];
|
|
118
117
|
skipRules(rules?: string[]): void;
|
|
119
118
|
skipPreprocessors(preprocessors?: string[]): void;
|
|
120
119
|
skipDecorators(decorators?: string[]): void;
|
|
@@ -128,4 +127,3 @@ export declare class Config {
|
|
|
128
127
|
resolve: ResolveConfig;
|
|
129
128
|
constructor(rawConfig: RawConfig, configFile?: string | undefined);
|
|
130
129
|
}
|
|
131
|
-
export declare function loadConfig(configPath?: string, customExtends?: string[]): Promise<Config>;
|
package/lib/config/config.js
CHANGED
|
@@ -1,26 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
3
|
+
exports.Config = exports.LintConfig = exports.IGNORE_FILE = void 0;
|
|
13
4
|
const fs = require("fs");
|
|
14
5
|
const path = require("path");
|
|
15
6
|
const yaml = require("js-yaml");
|
|
16
7
|
const path_1 = require("path");
|
|
17
8
|
const colorette_1 = require("colorette");
|
|
18
|
-
const builtIn_1 = require("./builtIn");
|
|
19
|
-
const builtinRules = require("../rules/builtin");
|
|
20
9
|
const utils_1 = require("../utils");
|
|
21
|
-
const
|
|
10
|
+
const oas_types_1 = require("../oas-types");
|
|
22
11
|
const recommended_1 = require("./recommended");
|
|
23
|
-
const redocly_1 = require("../redocly");
|
|
24
12
|
exports.IGNORE_FILE = '.redocly.lint-ignore.yaml';
|
|
25
13
|
const IGNORE_BANNER = `# This file instructs Redocly's linter to ignore the rules contained for specific parts of your API.\n` +
|
|
26
14
|
`# See https://redoc.ly/docs/cli/ for more information.\n`;
|
|
@@ -34,12 +22,6 @@ class LintConfig {
|
|
|
34
22
|
this.recommendedFallback = false;
|
|
35
23
|
this.plugins = rawConfig.plugins ? resolvePlugins(rawConfig.plugins, configFile) : [];
|
|
36
24
|
this.doNotResolveExamples = !!rawConfig.doNotResolveExamples;
|
|
37
|
-
this.plugins.push({
|
|
38
|
-
id: '',
|
|
39
|
-
rules: builtinRules.rules,
|
|
40
|
-
preprocessors: builtinRules.preprocessors,
|
|
41
|
-
decorators: builtinRules.decorators,
|
|
42
|
-
});
|
|
43
25
|
if (!rawConfig.extends) {
|
|
44
26
|
this.recommendedFallback = true;
|
|
45
27
|
}
|
|
@@ -55,21 +37,21 @@ class LintConfig {
|
|
|
55
37
|
}
|
|
56
38
|
const merged = mergeExtends(extendConfigs);
|
|
57
39
|
this.rules = {
|
|
58
|
-
[
|
|
59
|
-
[
|
|
60
|
-
[
|
|
40
|
+
[oas_types_1.OasVersion.Version2]: Object.assign(Object.assign({}, merged.rules), merged.oas2Rules),
|
|
41
|
+
[oas_types_1.OasVersion.Version3_0]: Object.assign(Object.assign({}, merged.rules), merged.oas3_0Rules),
|
|
42
|
+
[oas_types_1.OasVersion.Version3_1]: Object.assign(Object.assign({}, merged.rules), merged.oas3_1Rules),
|
|
61
43
|
};
|
|
62
44
|
this.preprocessors = {
|
|
63
|
-
[
|
|
64
|
-
[
|
|
65
|
-
[
|
|
45
|
+
[oas_types_1.OasVersion.Version2]: Object.assign(Object.assign({}, merged.preprocessors), merged.oas2Preprocessors),
|
|
46
|
+
[oas_types_1.OasVersion.Version3_0]: Object.assign(Object.assign({}, merged.preprocessors), merged.oas3_0Preprocessors),
|
|
47
|
+
[oas_types_1.OasVersion.Version3_1]: Object.assign(Object.assign({}, merged.preprocessors), merged.oas3_1Preprocessors),
|
|
66
48
|
};
|
|
67
49
|
this.decorators = {
|
|
68
|
-
[
|
|
69
|
-
[
|
|
70
|
-
[
|
|
50
|
+
[oas_types_1.OasVersion.Version2]: Object.assign(Object.assign({}, merged.decorators), merged.oas2Decorators),
|
|
51
|
+
[oas_types_1.OasVersion.Version3_0]: Object.assign(Object.assign({}, merged.decorators), merged.oas3_0Decorators),
|
|
52
|
+
[oas_types_1.OasVersion.Version3_1]: Object.assign(Object.assign({}, merged.decorators), merged.oas3_1Decorators),
|
|
71
53
|
};
|
|
72
|
-
const dir = this.configFile ? path.dirname(this.configFile) : process.cwd();
|
|
54
|
+
const dir = this.configFile ? path.dirname(this.configFile) : (typeof process !== 'undefined' && process.cwd() || '');
|
|
73
55
|
const ignoreFile = path.join(dir, exports.IGNORE_FILE);
|
|
74
56
|
/* no crash when using it on the client */
|
|
75
57
|
if (fs.hasOwnProperty('existsSync') && fs.existsSync(ignoreFile)) {
|
|
@@ -122,11 +104,12 @@ class LintConfig {
|
|
|
122
104
|
for (const plugin of this.plugins) {
|
|
123
105
|
if (plugin.typeExtension !== undefined) {
|
|
124
106
|
switch (version) {
|
|
125
|
-
case
|
|
107
|
+
case oas_types_1.OasVersion.Version3_0:
|
|
108
|
+
case oas_types_1.OasVersion.Version3_1:
|
|
126
109
|
if (!plugin.typeExtension.oas3)
|
|
127
110
|
continue;
|
|
128
111
|
extendedTypes = plugin.typeExtension.oas3(extendedTypes, version);
|
|
129
|
-
case
|
|
112
|
+
case oas_types_1.OasVersion.Version2:
|
|
130
113
|
if (!plugin.typeExtension.oas2)
|
|
131
114
|
continue;
|
|
132
115
|
extendedTypes = plugin.typeExtension.oas2(extendedTypes, version);
|
|
@@ -193,13 +176,13 @@ class LintConfig {
|
|
|
193
176
|
}
|
|
194
177
|
getRulesForOasVersion(version) {
|
|
195
178
|
switch (version) {
|
|
196
|
-
case
|
|
179
|
+
case oas_types_1.OasMajorVersion.Version3:
|
|
197
180
|
const oas3Rules = []; // default ruleset
|
|
198
181
|
this.plugins.forEach((p) => { var _a; return ((_a = p.preprocessors) === null || _a === void 0 ? void 0 : _a.oas3) && oas3Rules.push(p.preprocessors.oas3); });
|
|
199
182
|
this.plugins.forEach((p) => { var _a; return ((_a = p.rules) === null || _a === void 0 ? void 0 : _a.oas3) && oas3Rules.push(p.rules.oas3); });
|
|
200
183
|
this.plugins.forEach((p) => { var _a; return ((_a = p.decorators) === null || _a === void 0 ? void 0 : _a.oas3) && oas3Rules.push(p.decorators.oas3); });
|
|
201
184
|
return oas3Rules;
|
|
202
|
-
case
|
|
185
|
+
case oas_types_1.OasMajorVersion.Version2:
|
|
203
186
|
const oas2Rules = []; // default ruleset
|
|
204
187
|
this.plugins.forEach((p) => { var _a; return ((_a = p.preprocessors) === null || _a === void 0 ? void 0 : _a.oas2) && oas2Rules.push(p.preprocessors.oas2); });
|
|
205
188
|
this.plugins.forEach((p) => { var _a; return ((_a = p.rules) === null || _a === void 0 ? void 0 : _a.oas2) && oas2Rules.push(p.rules.oas2); });
|
|
@@ -209,7 +192,7 @@ class LintConfig {
|
|
|
209
192
|
}
|
|
210
193
|
skipRules(rules) {
|
|
211
194
|
for (const ruleId of rules || []) {
|
|
212
|
-
for (const version of Object.values(
|
|
195
|
+
for (const version of Object.values(oas_types_1.OasVersion)) {
|
|
213
196
|
if (this.rules[version][ruleId]) {
|
|
214
197
|
this.rules[version][ruleId] = 'off';
|
|
215
198
|
}
|
|
@@ -218,7 +201,7 @@ class LintConfig {
|
|
|
218
201
|
}
|
|
219
202
|
skipPreprocessors(preprocessors) {
|
|
220
203
|
for (const preprocessorId of preprocessors || []) {
|
|
221
|
-
for (const version of Object.values(
|
|
204
|
+
for (const version of Object.values(oas_types_1.OasVersion)) {
|
|
222
205
|
if (this.preprocessors[version][preprocessorId]) {
|
|
223
206
|
this.preprocessors[version][preprocessorId] = 'off';
|
|
224
207
|
}
|
|
@@ -227,7 +210,7 @@ class LintConfig {
|
|
|
227
210
|
}
|
|
228
211
|
skipDecorators(decorators) {
|
|
229
212
|
for (const decoratorId of decorators || []) {
|
|
230
|
-
for (const version of Object.values(
|
|
213
|
+
for (const version of Object.values(oas_types_1.OasVersion)) {
|
|
231
214
|
if (this.decorators[version][decoratorId]) {
|
|
232
215
|
this.decorators[version][decoratorId] = 'off';
|
|
233
216
|
}
|
|
@@ -253,77 +236,32 @@ class Config {
|
|
|
253
236
|
}
|
|
254
237
|
}
|
|
255
238
|
exports.Config = Config;
|
|
256
|
-
function loadConfig(configPath, customExtends) {
|
|
257
|
-
var _a;
|
|
258
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
259
|
-
if (configPath === undefined) {
|
|
260
|
-
configPath = findConfig();
|
|
261
|
-
}
|
|
262
|
-
let rawConfig = {};
|
|
263
|
-
// let resolvedPlugins: Plugin[] = [];
|
|
264
|
-
if (configPath !== undefined) {
|
|
265
|
-
try {
|
|
266
|
-
rawConfig = (yield utils_1.loadYaml(configPath));
|
|
267
|
-
}
|
|
268
|
-
catch (e) {
|
|
269
|
-
throw new Error(`Error parsing config file at \`${configPath}\`: ${e.message}`);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
if (customExtends !== undefined) {
|
|
273
|
-
rawConfig.lint = rawConfig.lint || {};
|
|
274
|
-
rawConfig.lint.extends = customExtends;
|
|
275
|
-
}
|
|
276
|
-
const redoclyClient = new redocly_1.RedoclyClient();
|
|
277
|
-
if (redoclyClient.hasToken()) {
|
|
278
|
-
if (!rawConfig.resolve)
|
|
279
|
-
rawConfig.resolve = {};
|
|
280
|
-
if (!rawConfig.resolve.http)
|
|
281
|
-
rawConfig.resolve.http = {};
|
|
282
|
-
rawConfig.resolve.http.headers = [
|
|
283
|
-
{
|
|
284
|
-
matches: `https://api.${process.env.REDOCLY_DOMAIN || 'redoc.ly'}/registry/**`,
|
|
285
|
-
name: 'Authorization',
|
|
286
|
-
envVariable: undefined,
|
|
287
|
-
value: (redoclyClient && (yield redoclyClient.getAuthorizationHeader())) || '',
|
|
288
|
-
},
|
|
289
|
-
...((_a = rawConfig.resolve.http.headers) !== null && _a !== void 0 ? _a : []),
|
|
290
|
-
];
|
|
291
|
-
}
|
|
292
|
-
return new Config(rawConfig, configPath);
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
exports.loadConfig = loadConfig;
|
|
296
|
-
function findConfig() {
|
|
297
|
-
if (fs.existsSync('.redocly.yaml')) {
|
|
298
|
-
return '.redocly.yaml';
|
|
299
|
-
}
|
|
300
|
-
else if (fs.existsSync('.redocly.yml')) {
|
|
301
|
-
return '.redocly.yml';
|
|
302
|
-
}
|
|
303
|
-
return undefined;
|
|
304
|
-
}
|
|
305
239
|
function resolvePresets(presets, plugins) {
|
|
306
240
|
return presets.map((presetName) => {
|
|
307
241
|
var _a;
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
if (!plugin) {
|
|
313
|
-
throw new Error(`Invalid config ${colorette_1.red(presetName)}: plugin ${pluginName} is not included.`);
|
|
314
|
-
}
|
|
315
|
-
preset = (_a = plugin.configs) === null || _a === void 0 ? void 0 : _a[configName];
|
|
316
|
-
if (!preset) {
|
|
317
|
-
throw new Error(`Invalid config ${colorette_1.red(presetName)}: plugin ${pluginName} doesn't export config with name ${configName}.`);
|
|
318
|
-
}
|
|
319
|
-
return preset;
|
|
242
|
+
const { pluginId, configName } = parsePresetName(presetName);
|
|
243
|
+
const plugin = plugins.find((p) => p.id === pluginId);
|
|
244
|
+
if (!plugin) {
|
|
245
|
+
throw new Error(`Invalid config ${colorette_1.red(presetName)}: plugin ${pluginId} is not included.`);
|
|
320
246
|
}
|
|
247
|
+
const preset = (_a = plugin.configs) === null || _a === void 0 ? void 0 : _a[configName];
|
|
321
248
|
if (!preset) {
|
|
322
|
-
throw new Error(
|
|
249
|
+
throw new Error(pluginId
|
|
250
|
+
? `Invalid config ${colorette_1.red(presetName)}: plugin ${pluginId} doesn't export config with name ${configName}.`
|
|
251
|
+
: `Invalid config ${colorette_1.red(presetName)}: there is no such built-in config.`);
|
|
323
252
|
}
|
|
324
253
|
return preset;
|
|
325
254
|
});
|
|
326
255
|
}
|
|
256
|
+
function parsePresetName(presetName) {
|
|
257
|
+
if (presetName.indexOf('/') > -1) {
|
|
258
|
+
const [pluginId, configName] = presetName.split('/');
|
|
259
|
+
return { pluginId, configName };
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
return { pluginId: '', configName: presetName };
|
|
263
|
+
}
|
|
264
|
+
}
|
|
327
265
|
function resolvePlugins(plugins, configPath = '') {
|
|
328
266
|
if (!plugins)
|
|
329
267
|
return [];
|
|
@@ -337,7 +275,7 @@ function resolvePlugins(plugins, configPath = '') {
|
|
|
337
275
|
? requireFunc(path.resolve(path.dirname(configPath), p))
|
|
338
276
|
: p;
|
|
339
277
|
const id = pluginModule.id;
|
|
340
|
-
if (
|
|
278
|
+
if (typeof id !== 'string') {
|
|
341
279
|
throw new Error(colorette_1.red(`Plugin must define \`id\` property in ${colorette_1.blue(p.toString())}.`));
|
|
342
280
|
}
|
|
343
281
|
if (seenPluginIds.has(id)) {
|
|
@@ -387,6 +325,8 @@ function resolvePlugins(plugins, configPath = '') {
|
|
|
387
325
|
.filter(utils_1.notUndefined);
|
|
388
326
|
}
|
|
389
327
|
function prefixRules(rules, prefix) {
|
|
328
|
+
if (!prefix)
|
|
329
|
+
return rules;
|
|
390
330
|
const res = {};
|
|
391
331
|
for (const name of Object.keys(rules)) {
|
|
392
332
|
res[`${prefix}/${name}`] = rules[name];
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.loadConfig = void 0;
|
|
13
|
+
const fs = require("fs");
|
|
14
|
+
const redocly_1 = require("../redocly");
|
|
15
|
+
const utils_1 = require("../utils");
|
|
16
|
+
const config_1 = require("./config");
|
|
17
|
+
const builtIn_1 = require("./builtIn");
|
|
18
|
+
function loadConfig(configPath, customExtends) {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
+
if (configPath === undefined) {
|
|
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
|
+
}
|
|
33
|
+
if (customExtends !== undefined) {
|
|
34
|
+
rawConfig.lint = rawConfig.lint || {};
|
|
35
|
+
rawConfig.lint.extends = customExtends;
|
|
36
|
+
}
|
|
37
|
+
const redoclyClient = new redocly_1.RedoclyClient();
|
|
38
|
+
if (redoclyClient.hasToken()) {
|
|
39
|
+
if (!rawConfig.resolve)
|
|
40
|
+
rawConfig.resolve = {};
|
|
41
|
+
if (!rawConfig.resolve.http)
|
|
42
|
+
rawConfig.resolve.http = {};
|
|
43
|
+
rawConfig.resolve.http.headers = [
|
|
44
|
+
{
|
|
45
|
+
matches: `https://api.${process.env.REDOCLY_DOMAIN || 'redoc.ly'}/registry/**`,
|
|
46
|
+
name: 'Authorization',
|
|
47
|
+
envVariable: undefined,
|
|
48
|
+
value: (redoclyClient && (yield redoclyClient.getAuthorizationHeader())) || '',
|
|
49
|
+
},
|
|
50
|
+
...((_a = rawConfig.resolve.http.headers) !== null && _a !== void 0 ? _a : []),
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
return new config_1.Config(Object.assign(Object.assign({}, rawConfig), { lint: Object.assign(Object.assign({}, rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.lint), { plugins: [...(((_b = rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.lint) === null || _b === void 0 ? void 0 : _b.plugins) || []), builtIn_1.defaultPlugin] }) }), configPath);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
exports.loadConfig = loadConfig;
|
|
57
|
+
function findConfig() {
|
|
58
|
+
if (fs.existsSync('.redocly.yaml')) {
|
|
59
|
+
return '.redocly.yaml';
|
|
60
|
+
}
|
|
61
|
+
else if (fs.existsSync('.redocly.yml')) {
|
|
62
|
+
return '.redocly.yml';
|
|
63
|
+
}
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
package/lib/config/rules.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RuleSet, OasVersion } from '../
|
|
1
|
+
import { RuleSet, OasVersion } from '../oas-types';
|
|
2
2
|
import { LintConfig } from './config';
|
|
3
3
|
export declare function initRules<T extends Function, P extends RuleSet<T>>(rules: P[], config: LintConfig, type: 'rules' | 'preprocessors' | 'decorators', oasVersion: OasVersion): {
|
|
4
4
|
severity: import("..").ProblemSeverity;
|
package/lib/format/codeframes.js
CHANGED
|
@@ -105,7 +105,7 @@ function getLineColLocation(location) {
|
|
|
105
105
|
if (location.pointer === undefined)
|
|
106
106
|
return location;
|
|
107
107
|
const { source, pointer, reportOnKey } = location;
|
|
108
|
-
const ast = source.getAst();
|
|
108
|
+
const ast = source.getAst(yamlAst.safeLoad);
|
|
109
109
|
const astNode = getAstNodeByPointer(ast, pointer, !!reportOnKey);
|
|
110
110
|
return Object.assign(Object.assign(Object.assign({}, location), { pointer: undefined }), positionsToLoc(source.body, (_a = astNode === null || astNode === void 0 ? void 0 : astNode.startPosition) !== null && _a !== void 0 ? _a : 1, (_b = astNode === null || astNode === void 0 ? void 0 : astNode.endPosition) !== null && _b !== void 0 ? _b : 1));
|
|
111
111
|
}
|