@redocly/openapi-core 1.0.0-beta.108 → 1.0.0-beta.109

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.
Files changed (132) hide show
  1. package/lib/benchmark/benches/resolve-with-no-external.bench.js +1 -1
  2. package/lib/bundle.d.ts +1 -1
  3. package/lib/bundle.js +4 -4
  4. package/lib/config/all.js +3 -1
  5. package/lib/config/config-resolvers.js +1 -1
  6. package/lib/config/minimal.js +3 -1
  7. package/lib/config/recommended.js +3 -1
  8. package/lib/config/rules.js +1 -1
  9. package/lib/config/types.d.ts +7 -0
  10. package/lib/config/utils.d.ts +2 -2
  11. package/lib/config/utils.js +42 -4
  12. package/lib/decorators/common/registry-dependencies.js +1 -1
  13. package/lib/format/format.d.ts +1 -1
  14. package/lib/format/format.js +22 -1
  15. package/lib/lint.js +2 -2
  16. package/lib/redocly/registry-api.d.ts +0 -1
  17. package/lib/redocly/registry-api.js +5 -4
  18. package/lib/resolve.js +3 -1
  19. package/lib/rules/common/no-ambiguous-paths.js +1 -1
  20. package/lib/rules/common/no-identical-paths.js +1 -1
  21. package/lib/rules/common/operation-2xx-response.js +1 -1
  22. package/lib/rules/common/operation-4xx-response.js +1 -1
  23. package/lib/rules/common/operation-operationId.js +1 -1
  24. package/lib/rules/common/operation-tag-defined.js +1 -1
  25. package/lib/rules/common/path-not-include-query.js +1 -1
  26. package/lib/rules/common/security-defined.d.ts +2 -0
  27. package/lib/rules/common/{operation-security-defined.js → security-defined.js} +18 -4
  28. package/lib/rules/common/spec.js +12 -1
  29. package/lib/rules/common/tags-alphabetical.js +1 -1
  30. package/lib/rules/oas2/index.d.ts +1 -1
  31. package/lib/rules/oas2/index.js +2 -2
  32. package/lib/rules/oas2/remove-unused-components.js +1 -1
  33. package/lib/rules/oas2/request-mime-type.js +1 -1
  34. package/lib/rules/oas2/response-mime-type.js +1 -1
  35. package/lib/rules/oas3/index.js +6 -2
  36. package/lib/rules/oas3/no-empty-servers.js +1 -1
  37. package/lib/rules/oas3/no-server-variables-empty-enum.js +1 -1
  38. package/lib/rules/oas3/no-unused-components.js +1 -1
  39. package/lib/rules/oas3/operation-4xx-problem-details-rfc7807.d.ts +5 -0
  40. package/lib/rules/oas3/operation-4xx-problem-details-rfc7807.js +36 -0
  41. package/lib/rules/oas3/remove-unused-components.js +1 -1
  42. package/lib/rules/oas3/request-mime-type.js +1 -1
  43. package/lib/rules/oas3/response-mime-type.js +1 -1
  44. package/lib/rules/oas3/spec-components-invalid-map-name.d.ts +2 -0
  45. package/lib/rules/oas3/spec-components-invalid-map-name.js +46 -0
  46. package/lib/rules/other/stats.d.ts +2 -2
  47. package/lib/rules/other/stats.js +2 -2
  48. package/lib/types/oas2.js +5 -5
  49. package/lib/types/oas3.js +27 -20
  50. package/lib/types/oas3_1.js +3 -3
  51. package/lib/types/redocly-yaml.js +46 -55
  52. package/lib/utils.d.ts +3 -3
  53. package/lib/utils.js +5 -5
  54. package/lib/visitors.d.ts +11 -11
  55. package/lib/visitors.js +13 -1
  56. package/package.json +1 -1
  57. package/src/__tests__/__snapshots__/bundle.test.ts.snap +3 -3
  58. package/src/__tests__/fixtures/extension.js +3 -3
  59. package/src/__tests__/format.test.ts +76 -0
  60. package/src/__tests__/lint.test.ts +106 -131
  61. package/src/__tests__/resolve-http.test.ts +1 -1
  62. package/src/__tests__/resolve.test.ts +9 -9
  63. package/src/__tests__/walk.test.ts +78 -10
  64. package/src/benchmark/benches/resolve-with-no-external.bench.ts +1 -1
  65. package/src/bundle.ts +4 -4
  66. package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +6 -2
  67. package/src/config/__tests__/fixtures/plugin-config.yaml +2 -3
  68. package/src/config/__tests__/fixtures/resolve-config/api/nested-config.yaml +11 -12
  69. package/src/config/__tests__/fixtures/resolve-config/local-config-with-circular.yaml +7 -8
  70. package/src/config/__tests__/fixtures/resolve-config/local-config-with-file.yaml +18 -19
  71. package/src/config/__tests__/fixtures/resolve-config/local-config.yaml +9 -10
  72. package/src/config/__tests__/fixtures/resolve-remote-configs/nested-remote-config.yaml +3 -4
  73. package/src/config/__tests__/fixtures/resolve-remote-configs/remote-config.yaml +4 -5
  74. package/src/config/__tests__/load.test.ts +12 -15
  75. package/src/config/__tests__/utils.test.ts +64 -4
  76. package/src/config/all.ts +3 -1
  77. package/src/config/config-resolvers.ts +2 -2
  78. package/src/config/load.ts +3 -2
  79. package/src/config/minimal.ts +3 -1
  80. package/src/config/recommended.ts +3 -1
  81. package/src/config/rules.ts +2 -2
  82. package/src/config/types.ts +11 -0
  83. package/src/config/utils.ts +102 -13
  84. package/src/decorators/common/registry-dependencies.ts +1 -1
  85. package/src/format/format.ts +32 -2
  86. package/src/lint.ts +2 -2
  87. package/src/redocly/registry-api.ts +5 -4
  88. package/src/resolve.ts +3 -1
  89. package/src/rules/__tests__/utils.test.ts +1 -1
  90. package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +1 -0
  91. package/src/rules/common/__tests__/operation-2xx-response.test.ts +1 -1
  92. package/src/rules/common/__tests__/operation-4xx-response.test.ts +26 -3
  93. package/src/rules/common/__tests__/security-defined.test.ts +175 -0
  94. package/src/rules/common/__tests__/spec.test.ts +79 -0
  95. package/src/rules/common/assertions/__tests__/utils.test.ts +2 -2
  96. package/src/rules/common/no-ambiguous-paths.ts +1 -1
  97. package/src/rules/common/no-identical-paths.ts +1 -1
  98. package/src/rules/common/operation-2xx-response.ts +1 -1
  99. package/src/rules/common/operation-4xx-response.ts +1 -1
  100. package/src/rules/common/operation-operationId.ts +1 -1
  101. package/src/rules/common/operation-tag-defined.ts +1 -1
  102. package/src/rules/common/path-not-include-query.ts +1 -1
  103. package/src/rules/common/{operation-security-defined.ts → security-defined.ts} +19 -4
  104. package/src/rules/common/spec.ts +15 -1
  105. package/src/rules/common/tags-alphabetical.ts +1 -1
  106. package/src/rules/oas2/index.ts +2 -2
  107. package/src/rules/oas2/remove-unused-components.ts +1 -1
  108. package/src/rules/oas2/request-mime-type.ts +1 -1
  109. package/src/rules/oas2/response-mime-type.ts +1 -1
  110. package/src/rules/oas3/__tests__/operation-4xx-problem-details-rfc7807.test.ts +145 -0
  111. package/src/rules/oas3/__tests__/spec/spec.test.ts +10 -0
  112. package/src/rules/oas3/__tests__/spec-components-invalid-map-name.test.ts +217 -0
  113. package/src/rules/oas3/index.ts +6 -2
  114. package/src/rules/oas3/no-empty-servers.ts +1 -1
  115. package/src/rules/oas3/no-server-variables-empty-enum.ts +1 -1
  116. package/src/rules/oas3/no-unused-components.ts +1 -1
  117. package/src/rules/oas3/operation-4xx-problem-details-rfc7807.ts +36 -0
  118. package/src/rules/oas3/remove-unused-components.ts +1 -1
  119. package/src/rules/oas3/request-mime-type.ts +1 -1
  120. package/src/rules/oas3/response-mime-type.ts +1 -1
  121. package/src/rules/oas3/spec-components-invalid-map-name.ts +53 -0
  122. package/src/rules/other/stats.ts +2 -2
  123. package/src/types/index.ts +2 -2
  124. package/src/types/oas2.ts +5 -5
  125. package/src/types/oas3.ts +27 -20
  126. package/src/types/oas3_1.ts +3 -3
  127. package/src/types/redocly-yaml.ts +52 -40
  128. package/src/utils.ts +11 -7
  129. package/src/visitors.ts +29 -13
  130. package/tsconfig.tsbuildinfo +1 -1
  131. package/lib/rules/common/operation-security-defined.d.ts +0 -2
  132. package/src/rules/common/__tests__/operation-security-defined.test.ts +0 -69
package/lib/utils.d.ts CHANGED
@@ -14,7 +14,7 @@ export declare function pushStack<T, P extends Stack<T> = Stack<T>>(head: P, val
14
14
  export declare function popStack<T, P extends Stack<T>>(head: P): StackFrame<T> | null;
15
15
  export declare type BundleOutputFormat = 'json' | 'yml' | 'yaml';
16
16
  export declare function loadYaml<T>(filename: string): Promise<T>;
17
- export declare function notUndefined<T>(x: T | undefined): x is T;
17
+ export declare function isDefined<T>(x: T | undefined): x is T;
18
18
  export declare function isPlainObject(value: any): value is object;
19
19
  export declare function isEmptyObject(value: any): value is object;
20
20
  export declare function isEmptyArray(value: any): boolean;
@@ -41,8 +41,8 @@ export declare function assignExisting<T>(target: Record<string, T>, obj: Record
41
41
  export declare function getMatchingStatusCodeRange(code: number | string): string;
42
42
  export declare function isCustomRuleId(id: string): boolean;
43
43
  export declare function doesYamlFileExist(filePath: string): boolean;
44
- export declare function showWarningForDeprecatedField(deprecatedField: string, updatedField: string): void;
45
- export declare function showErrorForDeprecatedField(deprecatedField: string, updatedField: string): void;
44
+ export declare function showWarningForDeprecatedField(deprecatedField: string, updatedField?: string): void;
45
+ export declare function showErrorForDeprecatedField(deprecatedField: string, updatedField?: string): void;
46
46
  export declare type Falsy = undefined | null | false | '' | 0;
47
47
  export declare function isTruthy<Truthy>(value: Truthy | Falsy): value is Truthy;
48
48
  export declare function identity<T>(value: T): T;
package/lib/utils.js CHANGED
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.identity = exports.isTruthy = exports.showErrorForDeprecatedField = exports.showWarningForDeprecatedField = exports.doesYamlFileExist = exports.isCustomRuleId = exports.getMatchingStatusCodeRange = exports.assignExisting = exports.isNotString = exports.isString = exports.isNotEmptyObject = exports.slash = exports.isPathParameter = exports.readFileAsStringSync = exports.isSingular = exports.validateMimeTypeOAS3 = exports.validateMimeType = exports.splitCamelCaseIntoWords = exports.omitObjectProps = exports.pickObjectProps = exports.readFileFromUrl = exports.isEmptyArray = exports.isEmptyObject = exports.isPlainObject = exports.notUndefined = exports.loadYaml = exports.popStack = exports.pushStack = exports.stringifyYaml = exports.parseYaml = void 0;
12
+ exports.identity = exports.isTruthy = exports.showErrorForDeprecatedField = exports.showWarningForDeprecatedField = exports.doesYamlFileExist = exports.isCustomRuleId = exports.getMatchingStatusCodeRange = exports.assignExisting = exports.isNotString = exports.isString = exports.isNotEmptyObject = exports.slash = exports.isPathParameter = exports.readFileAsStringSync = exports.isSingular = exports.validateMimeTypeOAS3 = exports.validateMimeType = exports.splitCamelCaseIntoWords = exports.omitObjectProps = exports.pickObjectProps = exports.readFileFromUrl = exports.isEmptyArray = exports.isEmptyObject = exports.isPlainObject = exports.isDefined = exports.loadYaml = exports.popStack = exports.pushStack = exports.stringifyYaml = exports.parseYaml = void 0;
13
13
  const fs = require("fs");
14
14
  const path_1 = require("path");
15
15
  const minimatch = require("minimatch");
@@ -37,10 +37,10 @@ function loadYaml(filename) {
37
37
  });
38
38
  }
39
39
  exports.loadYaml = loadYaml;
40
- function notUndefined(x) {
40
+ function isDefined(x) {
41
41
  return x !== undefined;
42
42
  }
43
- exports.notUndefined = notUndefined;
43
+ exports.isDefined = isDefined;
44
44
  function isPlainObject(value) {
45
45
  return value !== null && typeof value === 'object' && !Array.isArray(value);
46
46
  }
@@ -190,11 +190,11 @@ function doesYamlFileExist(filePath) {
190
190
  }
191
191
  exports.doesYamlFileExist = doesYamlFileExist;
192
192
  function showWarningForDeprecatedField(deprecatedField, updatedField) {
193
- logger_1.logger.warn(`The ${logger_1.colorize.red(deprecatedField)} field is deprecated. Use ${logger_1.colorize.green(updatedField)} instead. Read more about this change: https://redocly.com/docs/api-registry/guides/migration-guide-config-file/#changed-properties\n`);
193
+ logger_1.logger.warn(`The '${logger_1.colorize.red(deprecatedField)}' field is deprecated. ${updatedField ? `Use ${logger_1.colorize.green(updatedField)} instead. ` : ''}Read more about this change: https://redocly.com/docs/api-registry/guides/migration-guide-config-file/#changed-properties\n`);
194
194
  }
195
195
  exports.showWarningForDeprecatedField = showWarningForDeprecatedField;
196
196
  function showErrorForDeprecatedField(deprecatedField, updatedField) {
197
- throw new Error(`Do not use '${deprecatedField}' field. Use '${updatedField}' instead.\n`);
197
+ throw new Error(`Do not use '${deprecatedField}' field. ${updatedField ? `Use '${updatedField}' instead. ` : ''}\n`);
198
198
  }
199
199
  exports.showErrorForDeprecatedField = showErrorForDeprecatedField;
200
200
  function isTruthy(value) {
package/lib/visitors.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import type { Oas3Definition, Oas3ExternalDocs, Oas3Info, Oas3Contact, Oas3Components, Oas3License, Oas3Schema, Oas3Header, Oas3Parameter, Oas3Operation, Oas3PathItem, Oas3ServerVariable, Oas3Server, Oas3MediaType, Oas3Response, Oas3Example, Oas3RequestBody, Oas3Tag, OasRef, Oas3SecurityScheme, Oas3SecurityRequirement, Oas3Encoding, Oas3Link, Oas3Xml, Oas3Discriminator, Oas3Callback } from './typings/openapi';
2
- import { Oas2Definition, Oas2Tag, Oas2ExternalDocs, Oas2SecurityRequirement, Oas2Info, Oas2Contact, Oas2License, Oas2PathItem, Oas2Operation, Oas2Header, Oas2Response, Oas2Schema, Oas2Xml, Oas2Parameter, Oas2SecurityScheme } from './typings/swagger';
3
- import { NormalizedNodeType } from './types';
4
- import { Stack } from './utils';
5
- import { UserContext, ResolveResult, ProblemSeverity } from './walk';
6
- import { Location } from './ref-utils';
2
+ import type { Oas2Definition, Oas2Tag, Oas2ExternalDocs, Oas2SecurityRequirement, Oas2Info, Oas2Contact, Oas2License, Oas2PathItem, Oas2Operation, Oas2Header, Oas2Response, Oas2Schema, Oas2Xml, Oas2Parameter, Oas2SecurityScheme } from './typings/swagger';
3
+ import type { NormalizedNodeType } from './types';
4
+ import type { Stack } from './utils';
5
+ import type { UserContext, ResolveResult, ProblemSeverity } from './walk';
6
+ import type { Location } from './ref-utils';
7
7
  export declare type VisitFunction<T> = (node: T, ctx: UserContext & {
8
8
  ignoreNextVisitorsOnNode: () => void;
9
9
  }, parents?: any, context?: any) => void;
@@ -61,7 +61,7 @@ export declare type BaseVisitor = {
61
61
  } | VisitRefFunction;
62
62
  };
63
63
  declare type Oas3FlatVisitor = {
64
- DefinitionRoot?: VisitFunctionOrObject<Oas3Definition>;
64
+ Root?: VisitFunctionOrObject<Oas3Definition>;
65
65
  Tag?: VisitFunctionOrObject<Oas3Tag>;
66
66
  ExternalDocs?: VisitFunctionOrObject<Oas3ExternalDocs>;
67
67
  Server?: VisitFunctionOrObject<Oas3Server>;
@@ -70,13 +70,13 @@ declare type Oas3FlatVisitor = {
70
70
  Info?: VisitFunctionOrObject<Oas3Info>;
71
71
  Contact?: VisitFunctionOrObject<Oas3Contact>;
72
72
  License?: VisitFunctionOrObject<Oas3License>;
73
- PathMap?: VisitFunctionOrObject<Record<string, Oas3PathItem>>;
73
+ PathsMap?: VisitFunctionOrObject<Record<string, Oas3PathItem>>;
74
74
  PathItem?: VisitFunctionOrObject<Oas3PathItem>;
75
75
  Callback?: VisitFunctionOrObject<Record<string, Oas3PathItem>>;
76
76
  Parameter?: VisitFunctionOrObject<Oas3Parameter>;
77
77
  Operation?: VisitFunctionOrObject<Oas3Operation>;
78
78
  RequestBody?: VisitFunctionOrObject<Oas3RequestBody>;
79
- MediaTypeMap?: VisitFunctionOrObject<Record<string, Oas3MediaType>>;
79
+ MediaTypesMap?: VisitFunctionOrObject<Record<string, Oas3MediaType>>;
80
80
  MediaType?: VisitFunctionOrObject<Oas3MediaType>;
81
81
  Example?: VisitFunctionOrObject<Oas3Example>;
82
82
  Encoding?: VisitFunctionOrObject<Oas3Encoding>;
@@ -107,14 +107,14 @@ declare type Oas3FlatVisitor = {
107
107
  SecurityScheme?: VisitFunctionOrObject<Oas3SecurityScheme>;
108
108
  };
109
109
  declare type Oas2FlatVisitor = {
110
- DefinitionRoot?: VisitFunctionOrObject<Oas2Definition>;
110
+ Root?: VisitFunctionOrObject<Oas2Definition>;
111
111
  Tag?: VisitFunctionOrObject<Oas2Tag>;
112
112
  ExternalDocs?: VisitFunctionOrObject<Oas2ExternalDocs>;
113
113
  SecurityRequirement?: VisitFunctionOrObject<Oas2SecurityRequirement>;
114
114
  Info?: VisitFunctionOrObject<Oas2Info>;
115
115
  Contact?: VisitFunctionOrObject<Oas2Contact>;
116
116
  License?: VisitFunctionOrObject<Oas2License>;
117
- PathMap?: VisitFunctionOrObject<Record<string, Oas2PathItem>>;
117
+ PathsMap?: VisitFunctionOrObject<Record<string, Oas2PathItem>>;
118
118
  PathItem?: VisitFunctionOrObject<Oas2PathItem>;
119
119
  Parameter?: VisitFunctionOrObject<any>;
120
120
  Operation?: VisitFunctionOrObject<Oas2Operation>;
@@ -140,7 +140,7 @@ export declare type Oas3Visitor = BaseVisitor & Oas3NestedVisitor & Record<strin
140
140
  export declare type Oas2Visitor = BaseVisitor & Oas2NestedVisitor & Record<string, VisitFunction<any> | NestedVisitObject<any, Oas2NestedVisitor>>;
141
141
  export declare type Oas3TransformVisitor = BaseVisitor & Oas3FlatVisitor & Record<string, VisitFunction<any> | VisitObject<any>>;
142
142
  export declare type Oas2TransformVisitor = BaseVisitor & Oas2FlatVisitor & Record<string, VisitFunction<any> | VisitObject<any>>;
143
- export declare type NestedVisitor<T> = Exclude<T, 'any' | 'ref' | 'DefinitionRoot'>;
143
+ export declare type NestedVisitor<T> = Exclude<T, 'any' | 'ref' | 'Root'>;
144
144
  export declare type NormalizedOasVisitors<T extends BaseVisitor> = {
145
145
  [V in keyof T]-?: {
146
146
  enter: Array<NormalizeVisitor<T[V]>>;
package/lib/visitors.js CHANGED
@@ -1,6 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.normalizeVisitors = void 0;
4
+ const legacyTypesMap = {
5
+ Root: 'DefinitionRoot',
6
+ ServerVariablesMap: 'ServerVariableMap',
7
+ PathsMap: 'PathMap',
8
+ CallbacksMap: 'CallbackMap',
9
+ MediaTypesMap: 'MediaTypeMap',
10
+ ExamplesMap: 'ExampleMap',
11
+ EncodingsMap: 'EncodingMap',
12
+ HeadersMap: 'HeaderMap',
13
+ LinksMap: 'LinkMap',
14
+ };
4
15
  function normalizeVisitors(visitorsConfig, types) {
5
16
  const normalizedVisitors = {};
6
17
  normalizedVisitors.any = {
@@ -89,7 +100,8 @@ function normalizeVisitors(visitorsConfig, types) {
89
100
  }
90
101
  }
91
102
  for (const typeName of visitorKeys) {
92
- const typeVisitor = visitor[typeName];
103
+ const typeVisitor = (visitor[typeName] ||
104
+ visitor[legacyTypesMap[typeName]]);
93
105
  const normalizedTypeVisitor = normalizedVisitors[typeName];
94
106
  if (!typeVisitor)
95
107
  continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/openapi-core",
3
- "version": "1.0.0-beta.108",
3
+ "version": "1.0.0-beta.109",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "engines": {
@@ -47,7 +47,7 @@ rootType:
47
47
  description:
48
48
  type: string
49
49
  variables:
50
- name: ServerVariableMap
50
+ name: ServerVariablesMap
51
51
  properties: {}
52
52
  required:
53
53
  - url
@@ -94,7 +94,7 @@ rootType:
94
94
  name: ExternalDocs
95
95
  paths:
96
96
  properties: {}
97
- name: PathMap
97
+ name: PathsMap
98
98
  components:
99
99
  properties:
100
100
  parameters:
@@ -132,7 +132,7 @@ rootType:
132
132
  - openapi
133
133
  - paths
134
134
  - info
135
- name: DefinitionRoot
135
+ name: Root
136
136
  refTypes: {}
137
137
  visitorsData:
138
138
  registry-dependencies:
@@ -9,10 +9,10 @@ function oas3_0(types) {
9
9
  parameters: listOf('Parameter'),
10
10
  },
11
11
  },
12
- DefinitionRoot: {
13
- ...types.DefinitionRoot,
12
+ Root: {
13
+ ...types.Root,
14
14
  properties: {
15
- ...types.DefinitionRoot.properties,
15
+ ...types.Root.properties,
16
16
  'x-webhooks': 'XWebHooks',
17
17
  },
18
18
  },
@@ -0,0 +1,76 @@
1
+ import { outdent } from 'outdent';
2
+
3
+ import { formatProblems, getTotals } from '../format/format';
4
+
5
+ describe('format', () => {
6
+ function replaceColors(log: string) {
7
+ return log
8
+ .replace(/\x1b\[33m(.*?)\x1b\[39m/g, '<o>$1</o>') // orange
9
+ .replace(/\x1b\[31m(.*?)\x1b\[39m/g, '<r>$1</r>'); // red
10
+ }
11
+
12
+ const problems = [
13
+ {
14
+ ruleId: 'spec',
15
+ location: [],
16
+ severity: 'error' as const,
17
+ message: 'message',
18
+ suggest: [],
19
+ },
20
+ {
21
+ ruleId: 'spec',
22
+ location: [],
23
+ severity: 'error' as const,
24
+ message: 'message 2',
25
+ suggest: [],
26
+ },
27
+ {
28
+ ruleId: 'other-rule',
29
+ location: [],
30
+ severity: 'warn' as const,
31
+ message: 'message',
32
+ suggest: [],
33
+ },
34
+ ];
35
+
36
+ let output = '';
37
+ beforeEach(() => {
38
+ output = '';
39
+ jest.spyOn(process.stderr, 'write').mockImplementation((str: string | Uint8Array) => {
40
+ output += str;
41
+ return true;
42
+ });
43
+ });
44
+
45
+ it('should correctly format summary output', () => {
46
+ formatProblems(problems, {
47
+ format: 'summary',
48
+ version: '1.0.0',
49
+ totals: getTotals(problems),
50
+ color: false,
51
+ });
52
+
53
+ expect(output).toMatchInlineSnapshot(`
54
+ "error spec: 2
55
+ warning other-rule: 1
56
+
57
+ "
58
+ `);
59
+ });
60
+
61
+ it('should correctly format summary output in color mode', () => {
62
+ formatProblems(problems, {
63
+ format: 'summary',
64
+ version: '1.0.0',
65
+ totals: getTotals(problems),
66
+ color: true,
67
+ });
68
+
69
+ expect(replaceColors(output)).toMatchInlineSnapshot(`
70
+ "<r>error </r> spec: 2
71
+ <o>warning</o> other-rule: 1
72
+
73
+ "
74
+ `);
75
+ });
76
+ });
@@ -12,16 +12,16 @@ describe('lint', () => {
12
12
  const results = await lintFromString({
13
13
  absoluteRef: '/test/spec.yaml',
14
14
  source: outdent`
15
- openapi: 3.0.0
16
- info:
17
- title: Test API
18
- version: "1.0"
19
- description: Test
20
- license: Fail
15
+ openapi: 3.0.0
16
+ info:
17
+ title: Test API
18
+ version: "1.0"
19
+ description: Test
20
+ license: Fail
21
21
 
22
- servers:
23
- - url: http://example.com
24
- paths: {}
22
+ servers:
23
+ - url: http://example.com
24
+ paths: {}
25
25
  `,
26
26
  config: await loadConfig(),
27
27
  });
@@ -29,6 +29,7 @@ describe('lint', () => {
29
29
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
30
30
  Array [
31
31
  Object {
32
+ "from": undefined,
32
33
  "location": Array [
33
34
  Object {
34
35
  "pointer": "#/info/license",
@@ -48,8 +49,7 @@ describe('lint', () => {
48
49
  it('lintConfig should work', async () => {
49
50
  const document = parseYamlToDocument(
50
51
  outdent`
51
- apis: error string
52
- styleguide:
52
+ apis: error string
53
53
  plugins:
54
54
  - './local-plugin.js'
55
55
  extends:
@@ -60,16 +60,16 @@ describe('lint', () => {
60
60
  no-invalid-media-type-examples: error
61
61
  path-http-verbs-order: error
62
62
  boolean-parameter-prefixes: off
63
- features.openapi:
64
- showConsole: true
65
- layout:
66
- scope: section
67
- routingStrategy: browser
68
- theme:
69
- rightPanel:
70
- backgroundColor: '#263238'
71
- links:
72
- color: '#6CC496'
63
+ features.openapi:
64
+ showConsole: true
65
+ layout:
66
+ scope: section
67
+ routingStrategy: browser
68
+ theme:
69
+ rightPanel:
70
+ backgroundColor: '#263238'
71
+ links:
72
+ color: '#6CC496'
73
73
  `,
74
74
  ''
75
75
  );
@@ -78,6 +78,7 @@ describe('lint', () => {
78
78
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
79
79
  Array [
80
80
  Object {
81
+ "from": undefined,
81
82
  "location": Array [
82
83
  Object {
83
84
  "pointer": "#/apis",
@@ -91,6 +92,7 @@ describe('lint', () => {
91
92
  "suggest": Array [],
92
93
  },
93
94
  Object {
95
+ "from": undefined,
94
96
  "location": Array [
95
97
  Object {
96
98
  "pointer": "#/features.openapi/layout",
@@ -110,10 +112,9 @@ describe('lint', () => {
110
112
  it('lintConfig should detect wrong fields and suggest correct ones', async () => {
111
113
  const document = parseYamlToDocument(
112
114
  outdent`
113
- api:
114
- name@version:
115
- root: ./file.yaml
116
- syleguide:
115
+ api:
116
+ name@version:
117
+ root: ./file.yaml
117
118
  rules:
118
119
  operation-2xx-response: warn
119
120
  `,
@@ -124,6 +125,7 @@ describe('lint', () => {
124
125
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
125
126
  Array [
126
127
  Object {
128
+ "from": undefined,
127
129
  "location": Array [
128
130
  Object {
129
131
  "pointer": "#/api",
@@ -138,21 +140,6 @@ describe('lint', () => {
138
140
  "apis",
139
141
  ],
140
142
  },
141
- Object {
142
- "location": Array [
143
- Object {
144
- "pointer": "#/syleguide",
145
- "reportOnKey": true,
146
- "source": "",
147
- },
148
- ],
149
- "message": "Property \`syleguide\` is not expected here.",
150
- "ruleId": "configuration spec",
151
- "severity": "error",
152
- "suggest": Array [
153
- "styleguide",
154
- ],
155
- },
156
143
  ]
157
144
  `);
158
145
  });
@@ -160,13 +147,13 @@ describe('lint', () => {
160
147
  it('lintConfig should work with legacy fields', async () => {
161
148
  const document = parseYamlToDocument(
162
149
  outdent`
163
- apiDefinitions:
164
- entry: ./file.yaml
165
- lint:
150
+ apis:
151
+ entry:
152
+ root: ./file.yaml
166
153
  rules:
167
154
  operation-2xx-response: warn
168
- referenceDocs:
169
- showConsole: true
155
+ referenceDocs:
156
+ showConsole: true
170
157
  `,
171
158
  ''
172
159
  );
@@ -175,16 +162,16 @@ describe('lint', () => {
175
162
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`Array []`);
176
163
  });
177
164
 
178
- it("'plugins' shouldn't be allowed in 'apis' -> 'styleguide' field", async () => {
165
+ it("'plugins' shouldn't be allowed in 'apis'", async () => {
179
166
  const document = parseYamlToDocument(
180
167
  outdent`
181
- apis:
182
- styleguide:
183
- plugins:
168
+ apis:
169
+ main:
170
+ root: ./main.yaml
171
+ plugins:
184
172
  - './local-plugin.js'
185
- styleguide:
186
173
  plugins:
187
- - './local-plugin.js'
174
+ - './local-plugin.js'
188
175
  `,
189
176
  ''
190
177
  );
@@ -193,22 +180,10 @@ describe('lint', () => {
193
180
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
194
181
  Array [
195
182
  Object {
183
+ "from": undefined,
196
184
  "location": Array [
197
185
  Object {
198
- "pointer": "#/apis/styleguide",
199
- "reportOnKey": true,
200
- "source": "",
201
- },
202
- ],
203
- "message": "The field \`root\` must be present on this level.",
204
- "ruleId": "configuration spec",
205
- "severity": "error",
206
- "suggest": Array [],
207
- },
208
- Object {
209
- "location": Array [
210
- Object {
211
- "pointer": "#/apis/styleguide/plugins",
186
+ "pointer": "#/apis/main/plugins",
212
187
  "reportOnKey": true,
213
188
  "source": "",
214
189
  },
@@ -225,31 +200,31 @@ describe('lint', () => {
225
200
  it("'const' can have any type", async () => {
226
201
  const document = parseYamlToDocument(
227
202
  outdent`
228
- openapi: "3.1.0"
229
- info:
230
- version: 1.0.0
231
- title: Swagger Petstore
232
- description: Information about Petstore
233
- license:
234
- name: MIT
235
- url: https://opensource.org/licenses/MIT
236
- servers:
237
- - url: http://petstore.swagger.io/v1
238
- paths:
239
- /pets:
240
- get:
241
- summary: List all pets
242
- operationId: listPets
243
- tags:
244
- - pets
245
- responses:
246
- 200:
247
- description: An paged array of pets
248
- content:
249
- application/json:
250
- schema:
251
- type: string
252
- const: ABC
203
+ openapi: "3.1.0"
204
+ info:
205
+ version: 1.0.0
206
+ title: Swagger Petstore
207
+ description: Information about Petstore
208
+ license:
209
+ name: MIT
210
+ url: https://opensource.org/licenses/MIT
211
+ servers:
212
+ - url: http://petstore.swagger.io/v1
213
+ paths:
214
+ /pets:
215
+ get:
216
+ summary: List all pets
217
+ operationId: listPets
218
+ tags:
219
+ - pets
220
+ responses:
221
+ 200:
222
+ description: An paged array of pets
223
+ content:
224
+ application/json:
225
+ schema:
226
+ type: string
227
+ const: ABC
253
228
  `,
254
229
  'foobar.yaml'
255
230
  );
@@ -266,8 +241,8 @@ describe('lint', () => {
266
241
  it('detect OpenAPI should throw an error when version is not string', () => {
267
242
  const testDocument = parseYamlToDocument(
268
243
  outdent`
269
- openapi: 3.0
270
- `,
244
+ openapi: 3.0
245
+ `,
271
246
  ''
272
247
  );
273
248
  expect(() => detectOpenAPI(testDocument.parsed)).toThrow(
@@ -278,28 +253,28 @@ describe('lint', () => {
278
253
  it("spec rule shouldn't throw an error for named callback", async () => {
279
254
  const document = parseYamlToDocument(
280
255
  outdent`
281
- openapi: 3.1.0
282
- info:
283
- title: Callback test
284
- version: 'alpha'
285
- components:
286
- callbacks:
287
- resultCallback:
288
- '{$url}':
289
- post:
290
- requestBody:
291
- description: Callback payload
292
- content:
293
- 'application/json':
294
- schema:
295
- type: object
296
- properties:
297
- test:
298
- type: string
299
- responses:
300
- '200':
301
- description: callback successfully processed
302
- `,
256
+ openapi: 3.1.0
257
+ info:
258
+ title: Callback test
259
+ version: 'alpha'
260
+ components:
261
+ callbacks:
262
+ resultCallback:
263
+ '{$url}':
264
+ post:
265
+ requestBody:
266
+ description: Callback payload
267
+ content:
268
+ 'application/json':
269
+ schema:
270
+ type: object
271
+ properties:
272
+ test:
273
+ type: string
274
+ responses:
275
+ '200':
276
+ description: callback successfully processed
277
+ `,
303
278
  'foobar.yaml'
304
279
  );
305
280
 
@@ -316,23 +291,23 @@ describe('lint', () => {
316
291
  const absoluteRef = path.join(__dirname, 'fixtures/openapi.yaml');
317
292
  const document = parseYamlToDocument(
318
293
  outdent`
319
- openapi: 3.0.0
320
- info:
321
- version: 1.0.0
322
- title: Example OpenAPI 3 definition.
323
- description: Information about API
324
- license:
325
- name: MIT
326
- url: 'https://opensource.org/licenses/MIT'
327
- servers:
328
- - url: 'https://redocly.com/v1'
329
- paths:
330
- '/pets/{petId}':
331
- post:
332
- responses:
333
- '201':
334
- summary: Exist
335
- description: example description
294
+ openapi: 3.0.0
295
+ info:
296
+ version: 1.0.0
297
+ title: Example OpenAPI 3 definition.
298
+ description: Information about API
299
+ license:
300
+ name: MIT
301
+ url: 'https://opensource.org/licenses/MIT'
302
+ servers:
303
+ - url: 'https://redocly.com/v1'
304
+ paths:
305
+ '/pets/{petId}':
306
+ post:
307
+ responses:
308
+ '201':
309
+ summary: Exist
310
+ description: example description
336
311
  `,
337
312
  absoluteRef
338
313
  );
@@ -43,7 +43,7 @@ describe('Resolve http-headers', () => {
43
43
  ],
44
44
  },
45
45
  }),
46
- rootType: normalizeTypes(Oas3Types).DefinitionRoot,
46
+ rootType: normalizeTypes(Oas3Types).Root,
47
47
  });
48
48
 
49
49
  expect(fetchMock).toBeCalledTimes(3);