@redocly/openapi-core 1.0.0-beta.94 → 1.0.0-beta.97

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 (123) hide show
  1. package/README.md +1 -1
  2. package/__tests__/bundle.test.ts +6 -6
  3. package/__tests__/fixtures/extension.js +1 -1
  4. package/__tests__/login.test.ts +2 -2
  5. package/__tests__/ref-utils.test.ts +1 -1
  6. package/__tests__/utils.ts +30 -18
  7. package/lib/benchmark/benches/recommended-oas3.bench.js +2 -3
  8. package/lib/benchmark/utils.d.ts +2 -1
  9. package/lib/benchmark/utils.js +10 -7
  10. package/lib/bundle.d.ts +2 -2
  11. package/lib/config/all.d.ts +2 -2
  12. package/lib/config/builtIn.d.ts +1 -1
  13. package/lib/config/config-resolvers.d.ts +16 -0
  14. package/lib/config/config-resolvers.js +242 -0
  15. package/lib/config/config.d.ts +18 -130
  16. package/lib/config/config.js +34 -245
  17. package/lib/config/index.d.ts +7 -0
  18. package/lib/config/index.js +19 -0
  19. package/lib/config/load.d.ts +2 -1
  20. package/lib/config/load.js +20 -13
  21. package/lib/config/minimal.d.ts +2 -2
  22. package/lib/config/recommended.d.ts +2 -2
  23. package/lib/config/types.d.ts +113 -0
  24. package/lib/config/types.js +2 -0
  25. package/lib/config/utils.d.ts +13 -0
  26. package/lib/config/utils.js +160 -0
  27. package/lib/format/format.d.ts +1 -1
  28. package/lib/format/format.js +30 -1
  29. package/lib/index.d.ts +1 -2
  30. package/lib/index.js +5 -6
  31. package/lib/lint.d.ts +1 -1
  32. package/lib/lint.js +5 -7
  33. package/lib/redocly/index.d.ts +1 -1
  34. package/lib/redocly/index.js +10 -26
  35. package/lib/redocly/redocly-client-types.d.ts +1 -1
  36. package/lib/redocly/registry-api-types.d.ts +1 -0
  37. package/lib/redocly/registry-api.d.ts +2 -2
  38. package/lib/redocly/registry-api.js +2 -1
  39. package/lib/resolve.d.ts +1 -1
  40. package/lib/resolve.js +1 -2
  41. package/lib/rules/common/assertions/index.js +1 -1
  42. package/lib/rules/common/assertions/utils.d.ts +1 -1
  43. package/lib/rules/common/assertions/utils.js +6 -2
  44. package/lib/utils.d.ts +4 -2
  45. package/lib/utils.js +20 -3
  46. package/package.json +9 -6
  47. package/src/__tests__/lint.test.ts +1 -1
  48. package/src/benchmark/benches/recommended-oas3.bench.ts +2 -3
  49. package/src/benchmark/benchmark.js +1 -1
  50. package/src/benchmark/utils.ts +13 -8
  51. package/src/bundle.ts +2 -1
  52. package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +157 -0
  53. package/src/config/__tests__/config-resolvers.test.ts +429 -0
  54. package/src/config/__tests__/config.test.ts +17 -29
  55. package/src/config/__tests__/fixtures/plugin.js +1 -1
  56. package/src/config/__tests__/fixtures/resolve-config/api/nested-config.yaml +12 -0
  57. package/src/config/__tests__/fixtures/resolve-config/api/plugin.js +67 -0
  58. package/src/config/__tests__/fixtures/resolve-config/local-config-with-circular.yaml +8 -0
  59. package/src/config/__tests__/fixtures/resolve-config/local-config-with-file.yaml +19 -0
  60. package/src/config/__tests__/fixtures/resolve-config/local-config.yaml +10 -0
  61. package/src/config/__tests__/fixtures/resolve-config/plugin.js +66 -0
  62. package/src/config/__tests__/fixtures/resolve-remote-configs/nested-remote-config.yaml +4 -0
  63. package/src/config/__tests__/fixtures/resolve-remote-configs/remote-config.yaml +5 -0
  64. package/src/config/__tests__/load.test.ts +8 -1
  65. package/src/config/all.ts +3 -2
  66. package/src/config/builtIn.ts +2 -1
  67. package/src/config/config-resolvers.ts +359 -0
  68. package/src/config/config.ts +60 -468
  69. package/src/config/index.ts +7 -0
  70. package/src/config/load.ts +37 -31
  71. package/src/config/minimal.ts +2 -2
  72. package/src/config/recommended.ts +2 -2
  73. package/src/config/types.ts +168 -0
  74. package/src/config/utils.ts +208 -0
  75. package/src/decorators/__tests__/remove-x-internal.test.ts +5 -5
  76. package/src/format/format.ts +38 -7
  77. package/src/index.ts +6 -2
  78. package/src/lint.ts +4 -5
  79. package/src/redocly/__tests__/redocly-client.test.ts +7 -0
  80. package/src/redocly/index.ts +14 -41
  81. package/src/redocly/redocly-client-types.ts +1 -1
  82. package/src/redocly/registry-api-types.ts +1 -0
  83. package/src/redocly/registry-api.ts +5 -1
  84. package/src/resolve.ts +2 -4
  85. package/src/rules/__tests__/no-unresolved-refs.test.ts +4 -4
  86. package/src/rules/common/__tests__/info-description.test.ts +3 -3
  87. package/src/rules/common/__tests__/info-license.test.ts +2 -2
  88. package/src/rules/common/__tests__/license-url.test.ts +2 -2
  89. package/src/rules/common/__tests__/no-ambiguous-paths.test.ts +1 -1
  90. package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +5 -5
  91. package/src/rules/common/__tests__/no-identical-paths.test.ts +1 -1
  92. package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +3 -3
  93. package/src/rules/common/__tests__/operation-2xx-response.test.ts +3 -3
  94. package/src/rules/common/__tests__/operation-4xx-response.test.ts +3 -3
  95. package/src/rules/common/__tests__/operation-operationId-unique.test.ts +2 -2
  96. package/src/rules/common/__tests__/operation-operationId-url-safe.test.ts +1 -1
  97. package/src/rules/common/__tests__/operation-parameters-unique.test.ts +4 -4
  98. package/src/rules/common/__tests__/operation-security-defined.test.ts +2 -2
  99. package/src/rules/common/__tests__/operation-singular-tag.test.ts +2 -2
  100. package/src/rules/common/__tests__/path-http-verbs-order.test.ts +2 -2
  101. package/src/rules/common/__tests__/path-not-include-query.test.ts +2 -2
  102. package/src/rules/common/__tests__/path-params-defined.test.ts +3 -3
  103. package/src/rules/common/__tests__/paths-kebab-case.test.ts +3 -3
  104. package/src/rules/common/__tests__/spec.test.ts +1 -1
  105. package/src/rules/common/__tests__/tag-description.test.ts +2 -2
  106. package/src/rules/common/__tests__/tags-alphabetical.test.ts +2 -2
  107. package/src/rules/common/assertions/index.ts +1 -1
  108. package/src/rules/common/assertions/utils.ts +5 -2
  109. package/src/rules/oas2/__tests__/boolean-parameter-prefixes.test.ts +3 -3
  110. package/src/rules/oas2/__tests__/spec/referenceableScalars.test.ts +1 -1
  111. package/src/rules/oas2/__tests__/spec/utils.ts +10 -7
  112. package/src/rules/oas3/__tests__/boolean-parameter-prefixes.test.ts +3 -3
  113. package/src/rules/oas3/__tests__/no-empty-enum-servers.com.test.ts +6 -6
  114. package/src/rules/oas3/__tests__/no-example-value-and-externalValue.test.ts +2 -2
  115. package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +8 -8
  116. package/src/rules/oas3/__tests__/no-server-example.com.test.ts +2 -2
  117. package/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts +3 -3
  118. package/src/rules/oas3/__tests__/no-unused-components.test.ts +1 -1
  119. package/src/rules/oas3/__tests__/spec/referenceableScalars.test.ts +23 -14
  120. package/src/rules/oas3/__tests__/spec/spec.test.ts +4 -4
  121. package/src/rules/oas3/__tests__/spec/utils.ts +10 -7
  122. package/src/utils.ts +21 -4
  123. package/tsconfig.tsbuildinfo +1 -1
@@ -1,4 +1,4 @@
1
- import { LintRawConfig } from './config';
1
+ import type { PluginLintConfig } from './types';
2
2
 
3
3
  export default {
4
4
  rules: {
@@ -55,4 +55,4 @@ export default {
55
55
  'no-undefined-server-variable': 'warn',
56
56
  'no-servers-empty-enum': 'error',
57
57
  },
58
- } as LintRawConfig;
58
+ } as PluginLintConfig;
@@ -1,4 +1,4 @@
1
- import { LintRawConfig } from './config';
1
+ import type { PluginLintConfig } from './types';
2
2
 
3
3
  export default {
4
4
  rules: {
@@ -55,4 +55,4 @@ export default {
55
55
  'no-undefined-server-variable': 'error',
56
56
  'no-servers-empty-enum': 'error',
57
57
  },
58
- } as LintRawConfig;
58
+ } as PluginLintConfig;
@@ -0,0 +1,168 @@
1
+ import type { ProblemSeverity } from '../walk';
2
+ import type {
3
+ Oas3PreprocessorsSet,
4
+ OasMajorVersion,
5
+ Oas3DecoratorsSet,
6
+ Oas2RuleSet,
7
+ Oas2PreprocessorsSet,
8
+ Oas2DecoratorsSet,
9
+ Oas3RuleSet,
10
+ OasVersion,
11
+ } from '../oas-types';
12
+ import type { NodeType } from '../types';
13
+
14
+ export type RuleConfig =
15
+ | ProblemSeverity
16
+ | 'off'
17
+ | ({
18
+ severity?: ProblemSeverity;
19
+ } & Record<string, any>);
20
+
21
+ export type PreprocessorConfig =
22
+ | ProblemSeverity
23
+ | 'off'
24
+ | 'on'
25
+ | ({
26
+ severity?: ProblemSeverity;
27
+ } & Record<string, any>);
28
+
29
+ export type DecoratorConfig = PreprocessorConfig;
30
+
31
+ export type LintRawConfig = {
32
+ plugins?: (string | Plugin)[];
33
+ extends?: string[];
34
+ doNotResolveExamples?: boolean;
35
+ recommendedFallback?: boolean;
36
+
37
+ rules?: Record<string, RuleConfig>;
38
+ oas2Rules?: Record<string, RuleConfig>;
39
+ oas3_0Rules?: Record<string, RuleConfig>;
40
+ oas3_1Rules?: Record<string, RuleConfig>;
41
+
42
+ preprocessors?: Record<string, PreprocessorConfig>;
43
+ oas2Preprocessors?: Record<string, PreprocessorConfig>;
44
+ oas3_0Preprocessors?: Record<string, PreprocessorConfig>;
45
+ oas3_1Preprocessors?: Record<string, PreprocessorConfig>;
46
+
47
+ decorators?: Record<string, DecoratorConfig>;
48
+ oas2Decorators?: Record<string, DecoratorConfig>;
49
+ oas3_0Decorators?: Record<string, DecoratorConfig>;
50
+ oas3_1Decorators?: Record<string, DecoratorConfig>;
51
+ };
52
+
53
+ export type ResolvedLintConfig = PluginLintConfig & {
54
+ plugins?: Plugin[];
55
+ recommendedFallback?: boolean;
56
+ extends?: void | never;
57
+ extendPaths?: string[];
58
+ pluginPaths?: string[];
59
+ };
60
+
61
+ export type PreprocessorsConfig = {
62
+ oas3?: Oas3PreprocessorsSet;
63
+ oas2?: Oas2PreprocessorsSet;
64
+ };
65
+
66
+ export type DecoratorsConfig = {
67
+ oas3?: Oas3DecoratorsSet;
68
+ oas2?: Oas2DecoratorsSet;
69
+ };
70
+
71
+ export type TypesExtensionFn = (
72
+ types: Record<string, NodeType>,
73
+ oasVersion: OasVersion,
74
+ ) => Record<string, NodeType>;
75
+
76
+ export type TypeExtensionsConfig = Partial<Record<OasMajorVersion, TypesExtensionFn>>;
77
+
78
+ export type CustomRulesConfig = {
79
+ oas3?: Oas3RuleSet;
80
+ oas2?: Oas2RuleSet;
81
+ };
82
+
83
+ export type Plugin = {
84
+ id: string;
85
+ configs?: Record<string, PluginLintConfig>;
86
+ rules?: CustomRulesConfig;
87
+ preprocessors?: PreprocessorsConfig;
88
+ decorators?: DecoratorsConfig;
89
+ typeExtension?: TypeExtensionsConfig;
90
+ };
91
+
92
+ export type PluginLintConfig = Omit<LintRawConfig, 'plugins' | 'extends'>;
93
+
94
+ export type ResolveHeader =
95
+ | {
96
+ name: string;
97
+ envVariable?: undefined;
98
+ value: string;
99
+ matches: string;
100
+ }
101
+ | {
102
+ name: string;
103
+ value?: undefined;
104
+ envVariable: string;
105
+ matches: string;
106
+ };
107
+
108
+ export type RawResolveConfig = {
109
+ http?: Partial<HttpResolveConfig>;
110
+ };
111
+
112
+ export type HttpResolveConfig = {
113
+ headers: ResolveHeader[];
114
+ customFetch?: Function;
115
+ };
116
+
117
+ export type ResolveConfig = {
118
+ http: HttpResolveConfig;
119
+ };
120
+
121
+ export type Region = 'us' | 'eu';
122
+
123
+ export type AccessTokens = { [region in Region]?: string };
124
+
125
+ export type DeprecatedRawConfig = {
126
+ apiDefinitions?: Record<string, string>;
127
+ lint?: LintRawConfig;
128
+ resolve?: RawResolveConfig;
129
+ region?: Region;
130
+ referenceDocs?: Record<string, any>;
131
+ };
132
+
133
+ export type Api = {
134
+ root: string;
135
+ lint?: Omit<LintRawConfig, 'plugins'>;
136
+ 'features.openapi'?: Record<string, any>;
137
+ 'features.mockServer'?: Record<string, any>;
138
+ };
139
+ export type ResolvedApi = Omit<Api, 'lint'> & { lint: Omit<ResolvedLintConfig, 'plugins'>};
140
+
141
+ export type RawConfig = {
142
+ apis?: Record<string, Api>;
143
+ lint?: LintRawConfig;
144
+ resolve?: RawResolveConfig;
145
+ region?: Region;
146
+ 'features.openapi'?: Record<string, any>;
147
+ 'features.mockServer'?: Record<string, any>;
148
+ organization?: string;
149
+ };
150
+
151
+ export type ResolvedConfig = Omit<RawConfig, 'lint' | 'apis'> & {
152
+ lint: ResolvedLintConfig;
153
+ apis: Record<string,ResolvedApi>
154
+ };
155
+
156
+ export type RulesFields =
157
+ | 'rules'
158
+ | 'oas2Rules'
159
+ | 'oas3_0Rules'
160
+ | 'oas3_1Rules'
161
+ | 'preprocessors'
162
+ | 'oas2Preprocessors'
163
+ | 'oas3_0Preprocessors'
164
+ | 'oas3_1Preprocessors'
165
+ | 'decorators'
166
+ | 'oas2Decorators'
167
+ | 'oas3_0Decorators'
168
+ | 'oas3_1Decorators';
@@ -0,0 +1,208 @@
1
+ import { green, yellow } from 'colorette';
2
+ import { assignExisting } from '../utils';
3
+ import { Config } from './config';
4
+
5
+ import type {
6
+ Api,
7
+ DeprecatedRawConfig,
8
+ Plugin,
9
+ RawConfig,
10
+ RawResolveConfig,
11
+ ResolveConfig,
12
+ ResolvedLintConfig,
13
+ RulesFields,
14
+ } from './types';
15
+
16
+ export function parsePresetName(presetName: string): { pluginId: string; configName: string } {
17
+ if (presetName.indexOf('/') > -1) {
18
+ const [pluginId, configName] = presetName.split('/');
19
+ return { pluginId, configName };
20
+ } else {
21
+ return { pluginId: '', configName: presetName };
22
+ }
23
+ }
24
+
25
+ export function transformApiDefinitionsToApis(
26
+ apiDefinitions: Record<string, string> = {},
27
+ ): Record<string, Api> {
28
+ let apis: Record<string, Api> = {};
29
+ for (const [apiName, apiPath] of Object.entries(apiDefinitions)) {
30
+ apis[apiName] = { root: apiPath };
31
+ }
32
+ return apis;
33
+ }
34
+
35
+ export function prefixRules<T extends Record<string, any>>(rules: T, prefix: string) {
36
+ if (!prefix) return rules;
37
+
38
+ const res: any = {};
39
+ for (const name of Object.keys(rules)) {
40
+ res[`${prefix}/${name}`] = rules[name];
41
+ }
42
+
43
+ return res;
44
+ }
45
+
46
+ export function mergeExtends(rulesConfList: ResolvedLintConfig[]) {
47
+ const result: Omit<ResolvedLintConfig, RulesFields> &
48
+ Required<Pick<ResolvedLintConfig, RulesFields>> = {
49
+ rules: {},
50
+ oas2Rules: {},
51
+ oas3_0Rules: {},
52
+ oas3_1Rules: {},
53
+
54
+ preprocessors: {},
55
+ oas2Preprocessors: {},
56
+ oas3_0Preprocessors: {},
57
+ oas3_1Preprocessors: {},
58
+
59
+ decorators: {},
60
+ oas2Decorators: {},
61
+ oas3_0Decorators: {},
62
+ oas3_1Decorators: {},
63
+
64
+ plugins: [],
65
+ pluginPaths: [],
66
+ extendPaths: [],
67
+ };
68
+
69
+ for (let rulesConf of rulesConfList) {
70
+ if (rulesConf.extends) {
71
+ throw new Error(
72
+ `\`extends\` is not supported in shared configs yet: ${JSON.stringify(
73
+ rulesConf,
74
+ null,
75
+ 2,
76
+ )}.`,
77
+ );
78
+ }
79
+
80
+ Object.assign(result.rules, rulesConf.rules);
81
+ Object.assign(result.oas2Rules, rulesConf.oas2Rules);
82
+ assignExisting(result.oas2Rules, rulesConf.rules || {});
83
+ Object.assign(result.oas3_0Rules, rulesConf.oas3_0Rules);
84
+ assignExisting(result.oas3_0Rules, rulesConf.rules || {});
85
+ Object.assign(result.oas3_1Rules, rulesConf.oas3_1Rules);
86
+ assignExisting(result.oas3_1Rules, rulesConf.rules || {});
87
+
88
+ Object.assign(result.preprocessors, rulesConf.preprocessors);
89
+ Object.assign(result.oas2Preprocessors, rulesConf.oas2Preprocessors);
90
+ assignExisting(result.oas2Preprocessors, rulesConf.preprocessors || {});
91
+ Object.assign(result.oas3_0Preprocessors, rulesConf.oas3_0Preprocessors);
92
+ assignExisting(result.oas3_0Preprocessors, rulesConf.preprocessors || {});
93
+ Object.assign(result.oas3_1Preprocessors, rulesConf.oas3_1Preprocessors);
94
+ assignExisting(result.oas3_1Preprocessors, rulesConf.preprocessors || {});
95
+
96
+ Object.assign(result.decorators, rulesConf.decorators);
97
+ Object.assign(result.oas2Decorators, rulesConf.oas2Decorators);
98
+ assignExisting(result.oas2Decorators, rulesConf.decorators || {});
99
+ Object.assign(result.oas3_0Decorators, rulesConf.oas3_0Decorators);
100
+ assignExisting(result.oas3_0Decorators, rulesConf.decorators || {});
101
+ Object.assign(result.oas3_1Decorators, rulesConf.oas3_1Decorators);
102
+ assignExisting(result.oas3_1Decorators, rulesConf.decorators || {});
103
+
104
+ result.plugins!.push(...(rulesConf.plugins || []));
105
+ result.pluginPaths!.push(...(rulesConf.pluginPaths || []));
106
+ result.extendPaths!.push(...new Set(rulesConf.extendPaths));
107
+ }
108
+
109
+ return result;
110
+ }
111
+
112
+ export function getMergedConfig(config: Config, entrypointAlias?: string): Config {
113
+ const extendPaths = [
114
+ ...Object.values(config.apis).map((api) => api?.lint?.extendPaths),
115
+ config.rawConfig?.lint?.extendPaths,
116
+ ]
117
+ .flat()
118
+ .filter(Boolean) as string[];
119
+
120
+ const pluginPaths = [
121
+ ...Object.values(config.apis).map((api) => api?.lint?.pluginPaths),
122
+ config.rawConfig?.lint?.pluginPaths,
123
+ ]
124
+ .flat()
125
+ .filter(Boolean) as string[];
126
+
127
+ return entrypointAlias
128
+ ? new Config(
129
+ {
130
+ ...config.rawConfig,
131
+ lint: {
132
+ ...(config.apis[entrypointAlias]
133
+ ? config.apis[entrypointAlias].lint
134
+ : config.rawConfig.lint),
135
+ extendPaths,
136
+ pluginPaths,
137
+ },
138
+ 'features.openapi': {
139
+ ...config['features.openapi'],
140
+ ...config.apis[entrypointAlias]?.['features.openapi'],
141
+ },
142
+ 'features.mockServer': {
143
+ ...config['features.mockServer'],
144
+ ...config.apis[entrypointAlias]?.['features.mockServer'],
145
+ },
146
+ // TODO: merge everything else here
147
+ },
148
+ config.configFile,
149
+ )
150
+ : config;
151
+ }
152
+
153
+ export function transformConfig(rawConfig: DeprecatedRawConfig | RawConfig): RawConfig {
154
+ if ((rawConfig as RawConfig).apis && (rawConfig as DeprecatedRawConfig).apiDefinitions) {
155
+ throw new Error("Do not use 'apiDefinitions' field. Use 'apis' instead.\n");
156
+ }
157
+ if (
158
+ (rawConfig as RawConfig)['features.openapi'] &&
159
+ (rawConfig as DeprecatedRawConfig).referenceDocs
160
+ ) {
161
+ throw new Error("Do not use 'referenceDocs' field. Use 'features.openapi' instead.\n");
162
+ }
163
+ const { apiDefinitions, referenceDocs, ...rest } = rawConfig as DeprecatedRawConfig & RawConfig;
164
+ if (apiDefinitions) {
165
+ process.stderr.write(
166
+ `The ${yellow('apiDefinitions')} field is deprecated. Use ${green(
167
+ 'apis',
168
+ )} instead. Read more about this change: https://redocly.com/docs/api-registry/guides/migration-guide-config-file/#changed-properties\n`,
169
+ );
170
+ }
171
+ if (referenceDocs) {
172
+ process.stderr.write(
173
+ `The ${yellow('referenceDocs')} field is deprecated. Use ${green(
174
+ 'features.openapi',
175
+ )} instead. Read more about this change: https://redocly.com/docs/api-registry/guides/migration-guide-config-file/#changed-properties\n`,
176
+ );
177
+ }
178
+ return {
179
+ 'features.openapi': referenceDocs,
180
+ apis: transformApiDefinitionsToApis(apiDefinitions),
181
+ ...rest,
182
+ };
183
+ }
184
+
185
+ export function getResolveConfig(resolve?: RawResolveConfig): ResolveConfig {
186
+ return {
187
+ http: {
188
+ headers: resolve?.http?.headers ?? [],
189
+ customFetch: undefined,
190
+ },
191
+ };
192
+ }
193
+
194
+ export function getUniquePlugins(plugins: Plugin[]): Plugin[] {
195
+ const seen = new Set();
196
+ const results = [];
197
+ for (const p of plugins) {
198
+ if (!seen.has(p.id)) {
199
+ results.push(p);
200
+ seen.add(p.id);
201
+ } else if (p.id) {
202
+ process.stderr.write(
203
+ `Duplicate plugin id "${yellow(p.id)}".\n`,
204
+ );
205
+ }
206
+ }
207
+ return results;
208
+ }
@@ -25,7 +25,7 @@ describe('oas3 remove-x-internal', () => {
25
25
  const { bundle: res } = await bundleDocument({
26
26
  document: testDocument,
27
27
  externalRefResolver: new BaseResolver(),
28
- config: makeConfig({}, { 'remove-x-internal': { internalFlagProperty: 'removeit' } }),
28
+ config: await makeConfig({}, { 'remove-x-internal': { internalFlagProperty: 'removeit' } }),
29
29
  });
30
30
  expect(res.parsed).toMatchInlineSnapshot(`
31
31
  openapi: 3.0.0
@@ -92,7 +92,7 @@ describe('oas3 remove-x-internal', () => {
92
92
  const { bundle: res } = await bundleDocument({
93
93
  document: testDoc,
94
94
  externalRefResolver: new BaseResolver(),
95
- config: makeConfig({}, { 'remove-x-internal': 'on' }),
95
+ config: await makeConfig({}, { 'remove-x-internal': 'on' }),
96
96
  });
97
97
  expect(res.parsed).toMatchInlineSnapshot(`
98
98
  openapi: 3.1.0
@@ -165,7 +165,7 @@ describe('oas3 remove-x-internal', () => {
165
165
  const { bundle: res } = await bundleDocument({
166
166
  document: testDoc,
167
167
  externalRefResolver: new BaseResolver(),
168
- config: makeConfig({}, { 'remove-x-internal': 'on' }),
168
+ config: await makeConfig({}, { 'remove-x-internal': 'on' }),
169
169
  });
170
170
 
171
171
  expect(res.parsed).toMatchInlineSnapshot(`
@@ -239,7 +239,7 @@ describe('oas3 remove-x-internal', () => {
239
239
  const { bundle: res } = await bundleDocument({
240
240
  document: testDoc,
241
241
  externalRefResolver: new BaseResolver(),
242
- config: makeConfig({}, { 'remove-x-internal': 'on' }),
242
+ config: await makeConfig({}, { 'remove-x-internal': 'on' }),
243
243
  });
244
244
  expect(res.parsed).toMatchInlineSnapshot(`
245
245
  openapi: 3.0.1
@@ -302,7 +302,7 @@ describe('oas2 remove-x-internal', () => {
302
302
  const { bundle: res } = await bundleDocument({
303
303
  document: testDoc,
304
304
  externalRefResolver: new BaseResolver(),
305
- config: makeConfig({}, { 'remove-x-internal': 'on' }),
305
+ config: await makeConfig({}, { 'remove-x-internal': 'on' }),
306
306
  });
307
307
  expect(res.parsed).toMatchInlineSnapshot(`
308
308
  swagger: '2.0'
@@ -14,12 +14,13 @@ const coreVersion = require('../../package.json').version;
14
14
 
15
15
  import { NormalizedProblem, ProblemSeverity, LineColLocationObject, LocationObject } from '../walk';
16
16
  import { getCodeframe, getLineColLocation } from './codeframes';
17
+ import { env } from "../config";
17
18
 
18
19
  export type Totals = {
19
- errors: number;
20
- warnings: number;
21
- ignored: number;
22
- }
20
+ errors: number;
21
+ warnings: number;
22
+ ignored: number;
23
+ };
23
24
 
24
25
  const ERROR_MESSAGE = {
25
26
  INVALID_SEVERITY_LEVEL: 'Invalid severity level; accepted values: error or warn',
@@ -40,13 +41,18 @@ const SEVERITY_NAMES = {
40
41
  error: 'Error',
41
42
  };
42
43
 
44
+ const CODECLIMATE_SEVERITY_MAPPING = {
45
+ error: 'critical',
46
+ warn: 'minor',
47
+ };
48
+
43
49
  const MAX_SUGGEST = 5;
44
50
 
45
51
  function severityToNumber(severity: ProblemSeverity) {
46
52
  return severity === 'error' ? 1 : 2;
47
53
  }
48
54
 
49
- export type OutputFormat = 'codeframe' | 'stylish' | 'json' | 'checkstyle';
55
+ export type OutputFormat = 'codeframe' | 'stylish' | 'json' | 'checkstyle' | 'codeclimate';
50
56
 
51
57
  export function getTotals(problems: (NormalizedProblem & { ignored?: boolean })[]): Totals {
52
58
  let errors = 0;
@@ -76,7 +82,7 @@ export function formatProblems(
76
82
  cwd?: string;
77
83
  format?: OutputFormat;
78
84
  color?: boolean;
79
- totals: Totals
85
+ totals: Totals;
80
86
  version: string;
81
87
  },
82
88
  ) {
@@ -142,6 +148,9 @@ export function formatProblems(
142
148
  process.stdout.write(`</checkstyle>\n`);
143
149
  break;
144
150
  }
151
+ case 'codeclimate':
152
+ outputForCodeClimate();
153
+ break;
145
154
  }
146
155
 
147
156
  if (totalProblems - ignoredProblems > maxProblems) {
@@ -152,6 +161,25 @@ export function formatProblems(
152
161
  );
153
162
  }
154
163
 
164
+ function outputForCodeClimate() {
165
+ const issues = problems.map((p) => {
166
+ const location = p.location[0]; // TODO: support multiple location
167
+ const lineCol = getLineColLocation(location);
168
+ return {
169
+ description: p.message,
170
+ location: {
171
+ path: path.relative(cwd, location.source.absoluteRef),
172
+ lines: {
173
+ begin: lineCol.start.line,
174
+ },
175
+ },
176
+ severity: CODECLIMATE_SEVERITY_MAPPING[p.severity],
177
+ fingerprint: `${p.ruleId}${p.location.length > 0 ? '-' + p.location[0].pointer : ''}`,
178
+ };
179
+ });
180
+ process.stdout.write(JSON.stringify(issues, null, 2));
181
+ }
182
+
155
183
  function outputJSON() {
156
184
  const resultObject = {
157
185
  totals,
@@ -175,7 +203,7 @@ export function formatProblems(
175
203
  : undefined,
176
204
  };
177
205
 
178
- if (process.env.FORMAT_JSON_WITH_CODEFRAMES) {
206
+ if (env.FORMAT_JSON_WITH_CODEFRAMES) {
179
207
  const location = p.location[0]; // TODO: support multiple locations
180
208
  const loc = getLineColLocation(location);
181
209
  (problem as any).codeframe = getCodeframe(loc, color);
@@ -214,6 +242,9 @@ export function formatProblems(
214
242
 
215
243
  function formatStylish(problem: OnlyLineColProblem, locationPad: number, ruleIdPad: number) {
216
244
  const color = COLORS[problem.severity];
245
+ if (!SEVERITY_NAMES[problem.severity]) {
246
+ return 'Error not found severity. Please check your config file. Allowed values: \`warn,error,off\`'
247
+ }
217
248
  const severityName = color(SEVERITY_NAMES[problem.severity].toLowerCase().padEnd(7));
218
249
  const { start } = problem.location[0];
219
250
  return ` ${`${start.line}:${start.col}`.padEnd(
package/src/index.ts CHANGED
@@ -29,9 +29,13 @@ export {
29
29
  Region,
30
30
  getMergedConfig,
31
31
  transformConfig,
32
- } from './config/config';
32
+ loadConfig,
33
+ getConfig,
34
+ findConfig,
35
+ CONFIG_FILE_NAMES,
36
+ } from './config';
37
+
33
38
 
34
- export { loadConfig, getConfig, findConfig, CONFIG_FILE_NAMES } from './config/load';
35
39
  export { RedoclyClient, isRedoclyRegistryURL } from './redocly';
36
40
 
37
41
  export {
package/src/lint.ts CHANGED
@@ -7,14 +7,13 @@ import { Oas3Types } from './types/oas3';
7
7
  import { Oas2Types } from './types/oas2';
8
8
  import { NodeType } from './types';
9
9
  import { ProblemSeverity, WalkContext, walkDocument } from './walk';
10
- import { LintConfig, Config } from './config/config';
10
+ import { LintConfig, Config, initRules, defaultPlugin, resolvePlugins } from './config';
11
11
  import { normalizeTypes } from './types';
12
- import { initRules } from './config/rules';
13
12
  import { releaseAjvInstance } from './rules/ajv';
14
13
  import { detectOpenAPI, Oas3RuleSet, OasMajorVersion, OasVersion, openAPIMajor } from './oas-types';
15
14
  import { ConfigTypes } from './types/redocly-yaml';
16
15
  import { OasSpec } from './rules/common/spec';
17
- import { defaultPlugin } from './config/builtIn';
16
+
18
17
 
19
18
  export async function lint(opts: {
20
19
  ref: string;
@@ -104,9 +103,9 @@ export async function lintConfig(opts: {
104
103
  oasVersion: OasVersion.Version3_0,
105
104
  visitorsData: {},
106
105
  };
106
+ const plugins = resolvePlugins([defaultPlugin]);
107
107
  const config = new LintConfig({
108
- plugins: [defaultPlugin],
109
- extends: [],
108
+ plugins,
110
109
  rules: { spec: 'error' },
111
110
  });
112
111
 
@@ -1,5 +1,12 @@
1
1
  import { RedoclyClient } from '../index';
2
2
 
3
+ jest.mock('node-fetch', () => ({
4
+ default: jest.fn(() => ({
5
+ ok: true,
6
+ json: jest.fn().mockResolvedValue({}),
7
+ })),
8
+ }));
9
+
3
10
  describe('RedoclyClient', () => {
4
11
  const REDOCLY_DOMAIN_US = 'redocly.com';
5
12
  const REDOCLY_DOMAIN_EU = 'eu.redocly.com';