@redocly/openapi-core 1.0.0-beta.105 → 1.0.0-beta.106
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/README.md +4 -4
- package/__tests__/utils.ts +5 -5
- package/lib/benchmark/benches/recommended-oas3.bench.js +1 -1
- package/lib/benchmark/utils.d.ts +2 -2
- package/lib/benchmark/utils.js +2 -2
- package/lib/bundle.d.ts +2 -2
- package/lib/bundle.js +2 -2
- package/lib/config/all.d.ts +2 -2
- package/lib/config/all.js +1 -1
- package/lib/config/builtIn.d.ts +2 -2
- package/lib/config/builtIn.js +2 -2
- package/lib/config/config-resolvers.d.ts +5 -5
- package/lib/config/config-resolvers.js +39 -36
- package/lib/config/config.d.ts +5 -5
- package/lib/config/config.js +4 -4
- package/lib/config/load.js +4 -4
- package/lib/config/minimal.d.ts +2 -2
- package/lib/config/minimal.js +1 -1
- package/lib/config/recommended.d.ts +2 -2
- package/lib/config/recommended.js +1 -1
- package/lib/config/rules.d.ts +2 -2
- package/lib/config/rules.js +1 -1
- package/lib/config/types.d.ts +23 -19
- package/lib/config/utils.d.ts +5 -5
- package/lib/config/utils.js +43 -26
- package/lib/decorators/common/remove-x-internal.js +2 -2
- package/lib/format/format.js +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +2 -2
- package/lib/js-yaml/index.js +1 -6
- package/lib/lint.d.ts +2 -2
- package/lib/lint.js +16 -6
- package/lib/redocly/registry-api.d.ts +1 -1
- package/lib/redocly/registry-api.js +2 -2
- package/lib/rules/common/info-license-url.d.ts +1 -1
- package/lib/rules/common/info-license-url.js +5 -10
- package/lib/rules/common/info-license.d.ts +2 -0
- package/lib/rules/common/info-license.js +17 -0
- package/lib/rules/common/no-enum-type-mismatch.js +1 -3
- package/lib/rules/common/operation-operationId.js +1 -1
- package/lib/rules/common/path-not-include-query.js +1 -1
- package/lib/rules/common/paths-kebab-case.js +4 -1
- package/lib/rules/common/spec.js +1 -1
- package/lib/rules/oas2/index.js +4 -4
- package/lib/rules/oas2/remove-unused-components.js +3 -3
- package/lib/rules/oas3/index.js +4 -4
- package/lib/rules/oas3/no-empty-servers.js +1 -1
- package/lib/rules/oas3/remove-unused-components.js +2 -2
- package/lib/rules/other/stats.js +43 -14
- package/lib/rules/utils.d.ts +1 -1
- package/lib/rules/utils.js +4 -1
- package/lib/types/index.d.ts +2 -2
- package/lib/types/redocly-yaml.js +8 -7
- package/package.json +1 -1
- package/src/__tests__/__snapshots__/bundle.test.ts.snap +141 -0
- package/src/__tests__/bundle.test.ts +68 -34
- package/src/__tests__/codeframes.test.ts +13 -14
- package/src/__tests__/js-yaml.test.ts +6 -4
- package/src/__tests__/lint.test.ts +74 -6
- package/src/__tests__/login.test.ts +2 -2
- package/src/__tests__/normalizeVisitors.test.ts +4 -4
- package/src/__tests__/ref-utils.test.ts +13 -13
- package/src/__tests__/resolve-http.test.ts +1 -1
- package/src/__tests__/resolve.test.ts +14 -11
- package/src/__tests__/walk.test.ts +48 -56
- package/src/benchmark/benches/lint-with-many-rules.bench.ts +1 -1
- package/src/benchmark/benches/lint-with-nested-rule.bench.ts +1 -1
- package/src/benchmark/benches/lint-with-no-rules.bench.ts +1 -1
- package/src/benchmark/benches/lint-with-top-level-rule-report.bench.ts +1 -1
- package/src/benchmark/benches/lint-with-top-level-rule.bench.ts +1 -1
- package/src/benchmark/benches/recommended-oas3.bench.ts +3 -3
- package/src/benchmark/benches/resolve-with-no-external.bench.ts +1 -1
- package/src/benchmark/benchmark.js +9 -5
- package/src/benchmark/utils.ts +5 -5
- package/src/bundle.ts +18 -17
- package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +1 -1
- package/src/config/__tests__/config-resolvers.test.ts +123 -121
- package/src/config/__tests__/config.test.ts +76 -76
- package/src/config/__tests__/fixtures/resolve-config/api/plugin.js +4 -2
- package/src/config/__tests__/fixtures/resolve-config/plugin.js +4 -1
- package/src/config/__tests__/resolve-plugins.test.ts +3 -3
- package/src/config/__tests__/utils.test.ts +83 -0
- package/src/config/all.ts +3 -4
- package/src/config/builtIn.ts +5 -5
- package/src/config/config-resolvers.ts +122 -83
- package/src/config/config.ts +5 -5
- package/src/config/load.ts +6 -6
- package/src/config/minimal.ts +3 -3
- package/src/config/recommended.ts +3 -3
- package/src/config/rules.ts +6 -6
- package/src/config/types.ts +28 -19
- package/src/config/utils.ts +70 -50
- package/src/decorators/__tests__/filter-out.test.ts +8 -4
- package/src/decorators/__tests__/remove-x-internal.test.ts +5 -5
- package/src/decorators/common/filters/filter-helper.ts +1 -1
- package/src/decorators/common/info-description-override.ts +1 -1
- package/src/decorators/common/operation-description-override.ts +1 -1
- package/src/decorators/common/remove-x-internal.ts +4 -4
- package/src/decorators/common/tag-description-override.ts +1 -1
- package/src/format/codeframes.ts +4 -4
- package/src/format/format.ts +10 -10
- package/src/index.ts +2 -3
- package/src/js-yaml/index.ts +3 -8
- package/src/lint.ts +22 -18
- package/src/oas-types.ts +1 -6
- package/src/redocly/__tests__/redocly-client.test.ts +25 -19
- package/src/redocly/index.ts +6 -4
- package/src/redocly/registry-api.ts +6 -6
- package/src/ref-utils.ts +2 -2
- package/src/resolve.ts +7 -4
- package/src/rules/__tests__/no-unresolved-refs.test.ts +4 -4
- package/src/rules/__tests__/utils.test.ts +122 -0
- package/src/rules/ajv.ts +3 -4
- package/src/rules/common/__tests__/info-description.test.ts +3 -3
- package/src/rules/common/__tests__/info-license.test.ts +2 -2
- package/src/rules/common/__tests__/license-url.test.ts +2 -2
- package/src/rules/common/__tests__/no-ambiguous-paths.test.ts +1 -1
- package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +8 -8
- package/src/rules/common/__tests__/no-identical-paths.test.ts +1 -1
- package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +3 -3
- package/src/rules/common/__tests__/operation-2xx-response.test.ts +3 -3
- package/src/rules/common/__tests__/operation-4xx-response.test.ts +3 -3
- package/src/rules/common/__tests__/operation-operationId-unique.test.ts +2 -2
- package/src/rules/common/__tests__/operation-operationId-url-safe.test.ts +1 -1
- package/src/rules/common/__tests__/operation-parameters-unique.test.ts +4 -4
- package/src/rules/common/__tests__/operation-security-defined.test.ts +2 -2
- package/src/rules/common/__tests__/operation-singular-tag.test.ts +2 -2
- package/src/rules/common/__tests__/path-http-verbs-order.test.ts +2 -2
- package/src/rules/common/__tests__/path-not-include-query.test.ts +2 -2
- package/src/rules/common/__tests__/path-params-defined.test.ts +3 -3
- package/src/rules/common/__tests__/paths-kebab-case.test.ts +15 -15
- package/src/rules/common/__tests__/scalar-property-missing-example.test.ts +8 -8
- package/src/rules/common/__tests__/spec.test.ts +2 -2
- package/src/rules/common/__tests__/tag-description.test.ts +2 -2
- package/src/rules/common/__tests__/tags-alphabetical.test.ts +2 -2
- package/src/rules/common/assertions/__tests__/asserts.test.ts +513 -130
- package/src/rules/common/assertions/index.ts +6 -6
- package/src/rules/common/info-license-url.ts +4 -9
- package/src/rules/common/info-license.ts +15 -0
- package/src/rules/common/no-ambiguous-paths.ts +1 -1
- package/src/rules/common/no-enum-type-mismatch.ts +12 -9
- package/src/rules/common/no-invalid-parameter-examples.ts +2 -2
- package/src/rules/common/no-invalid-schema-examples.ts +1 -1
- package/src/rules/common/operation-operationId.ts +1 -1
- package/src/rules/common/operation-parameters-unique.ts +2 -2
- package/src/rules/common/path-not-include-query.ts +1 -1
- package/src/rules/common/path-params-defined.ts +1 -1
- package/src/rules/common/paths-kebab-case.ts +4 -1
- package/src/rules/common/scalar-property-missing-example.ts +1 -1
- package/src/rules/common/spec.ts +10 -7
- package/src/rules/no-unresolved-refs.ts +1 -1
- package/src/rules/oas2/__tests__/boolean-parameter-prefixes.test.ts +3 -3
- package/src/rules/oas2/__tests__/spec/info.test.ts +12 -12
- package/src/rules/oas2/__tests__/spec/operation.test.ts +4 -4
- package/src/rules/oas2/__tests__/spec/paths.test.ts +10 -10
- package/src/rules/oas2/__tests__/spec/referenceableScalars.test.ts +6 -2
- package/src/rules/oas2/__tests__/spec/utils.ts +6 -6
- package/src/rules/oas2/index.ts +3 -3
- package/src/rules/oas2/remove-unused-components.ts +13 -8
- package/src/rules/oas3/__tests__/boolean-parameter-prefixes.test.ts +3 -3
- package/src/rules/oas3/__tests__/no-example-value-and-externalValue.test.ts +2 -2
- package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +8 -8
- package/src/rules/oas3/__tests__/no-server-example.com.test.ts +2 -2
- package/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts +3 -3
- package/src/rules/oas3/__tests__/no-unused-components.test.ts +1 -1
- package/src/rules/oas3/__tests__/spec/callbacks.test.ts +1 -1
- package/src/rules/oas3/__tests__/spec/info.test.ts +12 -12
- package/src/rules/oas3/__tests__/spec/operation.test.ts +8 -8
- package/src/rules/oas3/__tests__/spec/paths.test.ts +10 -10
- package/src/rules/oas3/__tests__/spec/referenceableScalars.test.ts +12 -12
- package/src/rules/oas3/__tests__/spec/servers.test.ts +15 -15
- package/src/rules/oas3/__tests__/spec/spec.test.ts +6 -6
- package/src/rules/oas3/__tests__/spec/utils.ts +6 -6
- package/src/rules/oas3/index.ts +3 -3
- package/src/rules/oas3/no-empty-servers.ts +1 -1
- package/src/rules/oas3/no-invalid-media-type-examples.ts +12 -4
- package/src/rules/oas3/no-servers-empty-enum.ts +9 -10
- package/src/rules/oas3/remove-unused-components.ts +18 -7
- package/src/rules/other/stats.ts +46 -17
- package/src/rules/utils.ts +5 -3
- package/src/types/index.ts +5 -5
- package/src/types/redocly-yaml.ts +8 -7
- package/src/typings/common.ts +9 -1
- package/src/typings/openapi.ts +1 -1
- package/src/visitors.ts +4 -4
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/rules/common/license-url.d.ts +0 -2
- package/lib/rules/common/license-url.js +0 -12
- package/src/rules/common/license-url.ts +0 -10
|
@@ -12,28 +12,30 @@ import {
|
|
|
12
12
|
transformConfig,
|
|
13
13
|
} from './utils';
|
|
14
14
|
import type {
|
|
15
|
-
|
|
15
|
+
StyleguideRawConfig,
|
|
16
|
+
ApiStyleguideRawConfig,
|
|
16
17
|
Plugin,
|
|
17
18
|
RawConfig,
|
|
18
19
|
ResolvedApi,
|
|
19
|
-
|
|
20
|
+
ResolvedStyleguideConfig,
|
|
20
21
|
RuleConfig,
|
|
22
|
+
DeprecatedInRawConfig,
|
|
21
23
|
} from './types';
|
|
22
24
|
import { isNotString, isString, notUndefined, parseYaml } from '../utils';
|
|
23
25
|
import { Config } from './config';
|
|
24
26
|
|
|
25
|
-
export async function resolveConfig(rawConfig: RawConfig, configPath?: string) {
|
|
26
|
-
if (rawConfig.
|
|
27
|
+
export async function resolveConfig(rawConfig: RawConfig, configPath?: string): Promise<Config> {
|
|
28
|
+
if (rawConfig.styleguide?.extends?.some(isNotString)) {
|
|
27
29
|
throw new Error(
|
|
28
|
-
`Error configuration format not detected in extends value must contain strings
|
|
30
|
+
`Error configuration format not detected in extends value must contain strings`
|
|
29
31
|
);
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
const resolver = new BaseResolver(getResolveConfig(rawConfig.resolve));
|
|
33
|
-
const configExtends = rawConfig?.
|
|
34
|
-
const recommendedFallback = !rawConfig?.
|
|
35
|
-
const
|
|
36
|
-
...rawConfig?.
|
|
35
|
+
const configExtends = rawConfig?.styleguide?.extends ?? ['recommended'];
|
|
36
|
+
const recommendedFallback = !rawConfig?.styleguide?.extends;
|
|
37
|
+
const styleguideConfig = {
|
|
38
|
+
...rawConfig?.styleguide,
|
|
37
39
|
extends: configExtends,
|
|
38
40
|
recommendedFallback,
|
|
39
41
|
};
|
|
@@ -41,14 +43,14 @@ export async function resolveConfig(rawConfig: RawConfig, configPath?: string) {
|
|
|
41
43
|
const apis = await resolveApis({
|
|
42
44
|
rawConfig: {
|
|
43
45
|
...rawConfig,
|
|
44
|
-
|
|
46
|
+
styleguide: styleguideConfig,
|
|
45
47
|
},
|
|
46
48
|
configPath,
|
|
47
49
|
resolver,
|
|
48
50
|
});
|
|
49
51
|
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
+
const styleguide = await resolveStyleguideConfig({
|
|
53
|
+
styleguideConfig,
|
|
52
54
|
configPath,
|
|
53
55
|
resolver,
|
|
54
56
|
});
|
|
@@ -57,15 +59,15 @@ export async function resolveConfig(rawConfig: RawConfig, configPath?: string) {
|
|
|
57
59
|
{
|
|
58
60
|
...rawConfig,
|
|
59
61
|
apis,
|
|
60
|
-
|
|
62
|
+
styleguide,
|
|
61
63
|
},
|
|
62
|
-
configPath
|
|
64
|
+
configPath
|
|
63
65
|
);
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
export function resolvePlugins(
|
|
67
69
|
plugins: (string | Plugin)[] | null,
|
|
68
|
-
configPath: string = ''
|
|
70
|
+
configPath: string = ''
|
|
69
71
|
): Plugin[] {
|
|
70
72
|
if (!plugins) return [];
|
|
71
73
|
|
|
@@ -95,9 +97,9 @@ export function resolvePlugins(
|
|
|
95
97
|
throw new Error(
|
|
96
98
|
red(
|
|
97
99
|
`Plugin "id" must be unique. Plugin ${blue(p.toString())} uses id "${blue(
|
|
98
|
-
id
|
|
99
|
-
)}" already seen in ${blue(pluginPath)}
|
|
100
|
-
)
|
|
100
|
+
id
|
|
101
|
+
)}" already seen in ${blue(pluginPath)}`
|
|
102
|
+
)
|
|
101
103
|
);
|
|
102
104
|
}
|
|
103
105
|
|
|
@@ -124,7 +126,7 @@ export function resolvePlugins(
|
|
|
124
126
|
if (pluginModule.preprocessors) {
|
|
125
127
|
if (!pluginModule.preprocessors.oas3 && !pluginModule.preprocessors.oas2) {
|
|
126
128
|
throw new Error(
|
|
127
|
-
`Plugin \`preprocessors\` must have \`oas3\` or \`oas2\` preprocessors "${p}
|
|
129
|
+
`Plugin \`preprocessors\` must have \`oas3\` or \`oas2\` preprocessors "${p}.`
|
|
128
130
|
);
|
|
129
131
|
}
|
|
130
132
|
plugin.preprocessors = {};
|
|
@@ -163,45 +165,48 @@ export async function resolveApis({
|
|
|
163
165
|
configPath?: string;
|
|
164
166
|
resolver?: BaseResolver;
|
|
165
167
|
}): Promise<Record<string, ResolvedApi>> {
|
|
166
|
-
const { apis = {},
|
|
168
|
+
const { apis = {}, styleguide: styleguideConfig = {} } = rawConfig;
|
|
167
169
|
let resolvedApis: Record<string, ResolvedApi> = {};
|
|
168
170
|
for (const [apiName, apiContent] of Object.entries(apis || {})) {
|
|
169
|
-
if (apiContent.
|
|
171
|
+
if (apiContent.styleguide?.extends?.some(isNotString)) {
|
|
170
172
|
throw new Error(
|
|
171
|
-
`Error configuration format not detected in extends value must contain strings
|
|
173
|
+
`Error configuration format not detected in extends value must contain strings`
|
|
172
174
|
);
|
|
173
175
|
}
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
176
|
+
const rawStyleguideConfig = getMergedRawStyleguideConfig(
|
|
177
|
+
styleguideConfig,
|
|
178
|
+
apiContent.styleguide
|
|
179
|
+
);
|
|
180
|
+
const resolvedApiConfig = await resolveStyleguideConfig({
|
|
181
|
+
styleguideConfig: rawStyleguideConfig,
|
|
177
182
|
configPath,
|
|
178
183
|
resolver,
|
|
179
184
|
});
|
|
180
|
-
resolvedApis[apiName] = { ...apiContent,
|
|
185
|
+
resolvedApis[apiName] = { ...apiContent, styleguide: resolvedApiConfig };
|
|
181
186
|
}
|
|
182
187
|
return resolvedApis;
|
|
183
188
|
}
|
|
184
189
|
|
|
185
|
-
async function
|
|
190
|
+
async function resolveAndMergeNestedStyleguideConfig(
|
|
186
191
|
{
|
|
187
|
-
|
|
192
|
+
styleguideConfig,
|
|
188
193
|
configPath = '',
|
|
189
194
|
resolver = new BaseResolver(),
|
|
190
195
|
}: {
|
|
191
|
-
|
|
196
|
+
styleguideConfig?: StyleguideRawConfig;
|
|
192
197
|
configPath?: string;
|
|
193
198
|
resolver?: BaseResolver;
|
|
194
199
|
},
|
|
195
200
|
parentConfigPaths: string[] = [],
|
|
196
|
-
extendPaths: string[] = []
|
|
197
|
-
): Promise<
|
|
201
|
+
extendPaths: string[] = []
|
|
202
|
+
): Promise<ResolvedStyleguideConfig> {
|
|
198
203
|
if (parentConfigPaths.includes(configPath)) {
|
|
199
204
|
throw new Error(`Circular dependency in config file: "${configPath}"`);
|
|
200
205
|
}
|
|
201
206
|
const plugins = getUniquePlugins(
|
|
202
|
-
resolvePlugins([...(
|
|
207
|
+
resolvePlugins([...(styleguideConfig?.plugins || []), defaultPlugin], configPath)
|
|
203
208
|
);
|
|
204
|
-
const pluginPaths =
|
|
209
|
+
const pluginPaths = styleguideConfig?.plugins
|
|
205
210
|
?.filter(isString)
|
|
206
211
|
.map((p) => path.resolve(path.dirname(configPath), p));
|
|
207
212
|
|
|
@@ -209,8 +214,8 @@ async function resolveAndMergeNestedLint(
|
|
|
209
214
|
? configPath
|
|
210
215
|
: configPath && path.resolve(configPath);
|
|
211
216
|
|
|
212
|
-
const extendConfigs:
|
|
213
|
-
|
|
217
|
+
const extendConfigs: ResolvedStyleguideConfig[] = await Promise.all(
|
|
218
|
+
styleguideConfig?.extends?.map(async (presetItem) => {
|
|
214
219
|
if (!isAbsoluteUrl(presetItem) && !path.extname(presetItem)) {
|
|
215
220
|
return resolvePreset(presetItem, plugins);
|
|
216
221
|
}
|
|
@@ -219,23 +224,23 @@ async function resolveAndMergeNestedLint(
|
|
|
219
224
|
: isAbsoluteUrl(configPath)
|
|
220
225
|
? new URL(presetItem, configPath).href
|
|
221
226
|
: path.resolve(path.dirname(configPath), presetItem);
|
|
222
|
-
const
|
|
223
|
-
return await
|
|
227
|
+
const extendedStyleguideConfig = await loadExtendStyleguideConfig(pathItem, resolver);
|
|
228
|
+
return await resolveAndMergeNestedStyleguideConfig(
|
|
224
229
|
{
|
|
225
|
-
|
|
230
|
+
styleguideConfig: extendedStyleguideConfig,
|
|
226
231
|
configPath: pathItem,
|
|
227
232
|
resolver: resolver,
|
|
228
233
|
},
|
|
229
234
|
[...parentConfigPaths, resolvedConfigPath],
|
|
230
|
-
extendPaths
|
|
235
|
+
extendPaths
|
|
231
236
|
);
|
|
232
|
-
}) || []
|
|
237
|
+
}) || []
|
|
233
238
|
);
|
|
234
239
|
|
|
235
|
-
const { plugins: mergedPlugins = [], ...
|
|
240
|
+
const { plugins: mergedPlugins = [], ...styleguide } = mergeExtends([
|
|
236
241
|
...extendConfigs,
|
|
237
242
|
{
|
|
238
|
-
...
|
|
243
|
+
...styleguideConfig,
|
|
239
244
|
plugins,
|
|
240
245
|
extends: undefined,
|
|
241
246
|
extendPaths: [...parentConfigPaths, resolvedConfigPath],
|
|
@@ -244,91 +249,125 @@ async function resolveAndMergeNestedLint(
|
|
|
244
249
|
]);
|
|
245
250
|
|
|
246
251
|
return {
|
|
247
|
-
...
|
|
248
|
-
extendPaths:
|
|
252
|
+
...styleguide,
|
|
253
|
+
extendPaths: styleguide.extendPaths?.filter((path) => path && !isAbsoluteUrl(path)),
|
|
249
254
|
plugins: getUniquePlugins(mergedPlugins),
|
|
250
|
-
recommendedFallback:
|
|
251
|
-
doNotResolveExamples:
|
|
255
|
+
recommendedFallback: styleguideConfig?.recommendedFallback,
|
|
256
|
+
doNotResolveExamples: styleguideConfig?.doNotResolveExamples,
|
|
252
257
|
};
|
|
253
258
|
}
|
|
254
259
|
|
|
255
|
-
export async function
|
|
256
|
-
|
|
257
|
-
|
|
260
|
+
export async function resolveStyleguideConfig(
|
|
261
|
+
opts: {
|
|
262
|
+
styleguideConfig?: StyleguideRawConfig;
|
|
258
263
|
configPath?: string;
|
|
259
264
|
resolver?: BaseResolver;
|
|
260
265
|
},
|
|
261
266
|
parentConfigPaths: string[] = [],
|
|
262
|
-
extendPaths: string[] = []
|
|
263
|
-
): Promise<
|
|
264
|
-
const
|
|
267
|
+
extendPaths: string[] = []
|
|
268
|
+
): Promise<ResolvedStyleguideConfig> {
|
|
269
|
+
const resolvedStyleguideConfig = await resolveAndMergeNestedStyleguideConfig(
|
|
270
|
+
opts,
|
|
271
|
+
parentConfigPaths,
|
|
272
|
+
extendPaths
|
|
273
|
+
);
|
|
265
274
|
|
|
266
275
|
return {
|
|
267
|
-
...
|
|
268
|
-
rules:
|
|
276
|
+
...resolvedStyleguideConfig,
|
|
277
|
+
rules:
|
|
278
|
+
resolvedStyleguideConfig.rules &&
|
|
279
|
+
groupStyleguideAssertionRules(resolvedStyleguideConfig.rules),
|
|
269
280
|
};
|
|
270
281
|
}
|
|
271
282
|
|
|
272
|
-
export function resolvePreset(presetName: string, plugins: Plugin[]):
|
|
283
|
+
export function resolvePreset(presetName: string, plugins: Plugin[]): ResolvedStyleguideConfig {
|
|
273
284
|
const { pluginId, configName } = parsePresetName(presetName);
|
|
274
285
|
const plugin = plugins.find((p) => p.id === pluginId);
|
|
275
286
|
if (!plugin) {
|
|
276
287
|
throw new Error(`Invalid config ${red(presetName)}: plugin ${pluginId} is not included.`);
|
|
277
288
|
}
|
|
278
289
|
|
|
279
|
-
const preset = plugin.configs?.[configName]! as
|
|
290
|
+
const preset = plugin.configs?.[configName]! as ResolvedStyleguideConfig;
|
|
280
291
|
if (!preset) {
|
|
281
292
|
throw new Error(
|
|
282
293
|
pluginId
|
|
283
294
|
? `Invalid config ${red(
|
|
284
|
-
presetName
|
|
295
|
+
presetName
|
|
285
296
|
)}: plugin ${pluginId} doesn't export config with name ${configName}.`
|
|
286
|
-
: `Invalid config ${red(presetName)}: there is no such built-in config
|
|
297
|
+
: `Invalid config ${red(presetName)}: there is no such built-in config.`
|
|
287
298
|
);
|
|
288
299
|
}
|
|
289
300
|
return preset;
|
|
290
301
|
}
|
|
291
302
|
|
|
292
|
-
async function
|
|
303
|
+
async function loadExtendStyleguideConfig(
|
|
293
304
|
filePath: string,
|
|
294
|
-
resolver: BaseResolver
|
|
295
|
-
): Promise<
|
|
305
|
+
resolver: BaseResolver
|
|
306
|
+
): Promise<StyleguideRawConfig> {
|
|
296
307
|
try {
|
|
297
308
|
const fileSource = await resolver.loadExternalRef(filePath);
|
|
298
|
-
const rawConfig = transformConfig(
|
|
299
|
-
|
|
300
|
-
|
|
309
|
+
const rawConfig = transformConfig(
|
|
310
|
+
parseYaml(fileSource.body) as RawConfig & DeprecatedInRawConfig
|
|
311
|
+
);
|
|
312
|
+
if (!rawConfig.styleguide) {
|
|
313
|
+
throw new Error(`Styleguide configuration format not detected: "${filePath}"`);
|
|
301
314
|
}
|
|
302
315
|
|
|
303
|
-
return rawConfig.
|
|
316
|
+
return rawConfig.styleguide;
|
|
304
317
|
} catch (error) {
|
|
305
318
|
throw new Error(`Failed to load "${filePath}": ${error.message}`);
|
|
306
319
|
}
|
|
307
320
|
}
|
|
308
321
|
|
|
309
|
-
function
|
|
322
|
+
function getMergedRawStyleguideConfig(
|
|
323
|
+
rootStyleguideConfig: StyleguideRawConfig,
|
|
324
|
+
apiStyleguideConfig?: ApiStyleguideRawConfig
|
|
325
|
+
) {
|
|
310
326
|
const resultLint = {
|
|
311
|
-
...
|
|
312
|
-
...
|
|
313
|
-
rules: { ...
|
|
314
|
-
oas2Rules: { ...
|
|
315
|
-
oas3_0Rules: { ...
|
|
316
|
-
oas3_1Rules: { ...
|
|
317
|
-
preprocessors: {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
327
|
+
...rootStyleguideConfig,
|
|
328
|
+
...apiStyleguideConfig,
|
|
329
|
+
rules: { ...rootStyleguideConfig?.rules, ...apiStyleguideConfig?.rules },
|
|
330
|
+
oas2Rules: { ...rootStyleguideConfig?.oas2Rules, ...apiStyleguideConfig?.oas2Rules },
|
|
331
|
+
oas3_0Rules: { ...rootStyleguideConfig?.oas3_0Rules, ...apiStyleguideConfig?.oas3_0Rules },
|
|
332
|
+
oas3_1Rules: { ...rootStyleguideConfig?.oas3_1Rules, ...apiStyleguideConfig?.oas3_1Rules },
|
|
333
|
+
preprocessors: {
|
|
334
|
+
...rootStyleguideConfig?.preprocessors,
|
|
335
|
+
...apiStyleguideConfig?.preprocessors,
|
|
336
|
+
},
|
|
337
|
+
oas2Preprocessors: {
|
|
338
|
+
...rootStyleguideConfig?.oas2Preprocessors,
|
|
339
|
+
...apiStyleguideConfig?.oas2Preprocessors,
|
|
340
|
+
},
|
|
341
|
+
oas3_0Preprocessors: {
|
|
342
|
+
...rootStyleguideConfig?.oas3_0Preprocessors,
|
|
343
|
+
...apiStyleguideConfig?.oas3_0Preprocessors,
|
|
344
|
+
},
|
|
345
|
+
oas3_1Preprocessors: {
|
|
346
|
+
...rootStyleguideConfig?.oas3_1Preprocessors,
|
|
347
|
+
...apiStyleguideConfig?.oas3_1Preprocessors,
|
|
348
|
+
},
|
|
349
|
+
decorators: { ...rootStyleguideConfig?.decorators, ...apiStyleguideConfig?.decorators },
|
|
350
|
+
oas2Decorators: {
|
|
351
|
+
...rootStyleguideConfig?.oas2Decorators,
|
|
352
|
+
...apiStyleguideConfig?.oas2Decorators,
|
|
353
|
+
},
|
|
354
|
+
oas3_0Decorators: {
|
|
355
|
+
...rootStyleguideConfig?.oas3_0Decorators,
|
|
356
|
+
...apiStyleguideConfig?.oas3_0Decorators,
|
|
357
|
+
},
|
|
358
|
+
oas3_1Decorators: {
|
|
359
|
+
...rootStyleguideConfig?.oas3_1Decorators,
|
|
360
|
+
...apiStyleguideConfig?.oas3_1Decorators,
|
|
361
|
+
},
|
|
362
|
+
recommendedFallback: apiStyleguideConfig?.extends
|
|
363
|
+
? false
|
|
364
|
+
: rootStyleguideConfig.recommendedFallback,
|
|
326
365
|
};
|
|
327
366
|
return resultLint;
|
|
328
367
|
}
|
|
329
368
|
|
|
330
|
-
function
|
|
331
|
-
rules: Record<string, RuleConfig> | undefined
|
|
369
|
+
function groupStyleguideAssertionRules(
|
|
370
|
+
rules: Record<string, RuleConfig> | undefined
|
|
332
371
|
): Record<string, RuleConfig> | undefined {
|
|
333
372
|
if (!rules) {
|
|
334
373
|
return rules;
|
package/src/config/config.ts
CHANGED
|
@@ -14,7 +14,7 @@ import type {
|
|
|
14
14
|
ResolveConfig,
|
|
15
15
|
ResolvedApi,
|
|
16
16
|
ResolvedConfig,
|
|
17
|
-
|
|
17
|
+
ResolvedStyleguideConfig,
|
|
18
18
|
RuleConfig,
|
|
19
19
|
} from './types';
|
|
20
20
|
import { getResolveConfig } from './utils';
|
|
@@ -59,7 +59,7 @@ function getIgnoreFilePath(configFile?: string): string | undefined {
|
|
|
59
59
|
export const DOMAINS = getDomains();
|
|
60
60
|
export const AVAILABLE_REGIONS = Object.keys(DOMAINS) as Region[];
|
|
61
61
|
|
|
62
|
-
export class
|
|
62
|
+
export class StyleguideConfig {
|
|
63
63
|
plugins: Plugin[];
|
|
64
64
|
ignore: Record<string, Record<string, Set<string>>> = {};
|
|
65
65
|
doNotResolveExamples: boolean;
|
|
@@ -75,7 +75,7 @@ export class LintConfig {
|
|
|
75
75
|
extendPaths: string[];
|
|
76
76
|
pluginPaths: string[];
|
|
77
77
|
|
|
78
|
-
constructor(public rawConfig:
|
|
78
|
+
constructor(public rawConfig: ResolvedStyleguideConfig, public configFile?: string) {
|
|
79
79
|
this.plugins = rawConfig.plugins || [];
|
|
80
80
|
this.doNotResolveExamples = !!rawConfig.doNotResolveExamples;
|
|
81
81
|
|
|
@@ -297,7 +297,7 @@ export class LintConfig {
|
|
|
297
297
|
|
|
298
298
|
export class Config {
|
|
299
299
|
apis: Record<string, ResolvedApi>;
|
|
300
|
-
|
|
300
|
+
styleguide: StyleguideConfig;
|
|
301
301
|
resolve: ResolveConfig;
|
|
302
302
|
licenseKey?: string;
|
|
303
303
|
region?: Region;
|
|
@@ -306,7 +306,7 @@ export class Config {
|
|
|
306
306
|
organization?: string;
|
|
307
307
|
constructor(public rawConfig: ResolvedConfig, public configFile?: string) {
|
|
308
308
|
this.apis = rawConfig.apis || {};
|
|
309
|
-
this.
|
|
309
|
+
this.styleguide = new StyleguideConfig(rawConfig.styleguide || {}, configFile);
|
|
310
310
|
this['features.openapi'] = rawConfig['features.openapi'] || {};
|
|
311
311
|
this['features.mockServer'] = rawConfig['features.mockServer'] || {};
|
|
312
312
|
this.resolve = getResolveConfig(rawConfig?.resolve);
|
package/src/config/load.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { Config, DOMAINS } from './config';
|
|
|
6
6
|
import { transformConfig } from './utils';
|
|
7
7
|
import { resolveConfig } from './config-resolvers';
|
|
8
8
|
|
|
9
|
-
import type { RawConfig, Region } from './types';
|
|
9
|
+
import type { DeprecatedInRawConfig, RawConfig, Region } from './types';
|
|
10
10
|
|
|
11
11
|
async function addConfigMetadata({
|
|
12
12
|
rawConfig,
|
|
@@ -18,11 +18,11 @@ async function addConfigMetadata({
|
|
|
18
18
|
configPath?: string;
|
|
19
19
|
}): Promise<Config> {
|
|
20
20
|
if (customExtends !== undefined) {
|
|
21
|
-
rawConfig.
|
|
22
|
-
rawConfig.
|
|
21
|
+
rawConfig.styleguide = rawConfig.styleguide || {};
|
|
22
|
+
rawConfig.styleguide.extends = customExtends;
|
|
23
23
|
} else if (isEmptyObject(rawConfig)) {
|
|
24
24
|
// TODO: check if we can add recommended here. add message here?
|
|
25
|
-
// rawConfig.
|
|
25
|
+
// rawConfig.styleguide = { extends: ['recommended'], recommendedFallback: true };
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
const redoclyClient = new RedoclyClient();
|
|
@@ -93,10 +93,10 @@ export function findConfig(dir?: string): string | undefined {
|
|
|
93
93
|
return existingConfigFiles[0];
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
export async function getConfig(configPath: string | undefined = findConfig()) {
|
|
96
|
+
export async function getConfig(configPath: string | undefined = findConfig()): Promise<RawConfig> {
|
|
97
97
|
if (!configPath || !doesYamlFileExist(configPath)) return {};
|
|
98
98
|
try {
|
|
99
|
-
const rawConfig = (
|
|
99
|
+
const rawConfig = (await loadYaml<RawConfig & DeprecatedInRawConfig>(configPath)) || {};
|
|
100
100
|
return transformConfig(rawConfig);
|
|
101
101
|
} catch (e) {
|
|
102
102
|
throw new Error(`Error parsing config file at '${configPath}': ${e.message}`);
|
package/src/config/minimal.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PluginStyleguideConfig } from './types';
|
|
2
2
|
|
|
3
3
|
export default {
|
|
4
4
|
rules: {
|
|
@@ -18,7 +18,7 @@ export default {
|
|
|
18
18
|
'operation-description': 'off',
|
|
19
19
|
'operation-2xx-response': 'warn',
|
|
20
20
|
'operation-4xx-response': 'off',
|
|
21
|
-
|
|
21
|
+
assertions: 'warn',
|
|
22
22
|
'operation-operationId': 'warn',
|
|
23
23
|
'operation-summary': 'warn',
|
|
24
24
|
'operation-operationId-unique': 'warn',
|
|
@@ -55,4 +55,4 @@ export default {
|
|
|
55
55
|
'no-undefined-server-variable': 'warn',
|
|
56
56
|
'no-servers-empty-enum': 'error',
|
|
57
57
|
},
|
|
58
|
-
} as
|
|
58
|
+
} as PluginStyleguideConfig;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PluginStyleguideConfig } from './types';
|
|
2
2
|
|
|
3
3
|
export default {
|
|
4
4
|
rules: {
|
|
@@ -17,7 +17,7 @@ export default {
|
|
|
17
17
|
'path-parameters-defined': 'error',
|
|
18
18
|
'operation-description': 'off',
|
|
19
19
|
'operation-2xx-response': 'warn',
|
|
20
|
-
|
|
20
|
+
assertions: 'warn',
|
|
21
21
|
'operation-4xx-response': 'warn',
|
|
22
22
|
'operation-operationId': 'warn',
|
|
23
23
|
'operation-summary': 'error',
|
|
@@ -55,4 +55,4 @@ export default {
|
|
|
55
55
|
'no-undefined-server-variable': 'error',
|
|
56
56
|
'no-servers-empty-enum': 'error',
|
|
57
57
|
},
|
|
58
|
-
} as
|
|
58
|
+
} as PluginStyleguideConfig;
|
package/src/config/rules.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { RuleSet, OasVersion } from '../oas-types';
|
|
2
|
-
import {
|
|
2
|
+
import { StyleguideConfig } from './config';
|
|
3
3
|
import { notUndefined } from '../utils';
|
|
4
4
|
|
|
5
5
|
export function initRules<T extends Function, P extends RuleSet<T>>(
|
|
6
6
|
rules: P[],
|
|
7
|
-
config:
|
|
7
|
+
config: StyleguideConfig,
|
|
8
8
|
type: 'rules' | 'preprocessors' | 'decorators',
|
|
9
|
-
oasVersion: OasVersion
|
|
9
|
+
oasVersion: OasVersion
|
|
10
10
|
) {
|
|
11
11
|
return rules
|
|
12
12
|
.flatMap((ruleset) =>
|
|
@@ -31,7 +31,7 @@ export function initRules<T extends Function, P extends RuleSet<T>>(
|
|
|
31
31
|
severity: ruleSettings.severity,
|
|
32
32
|
ruleId,
|
|
33
33
|
visitor: visitor,
|
|
34
|
-
}))
|
|
34
|
+
}));
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
return {
|
|
@@ -39,8 +39,8 @@ export function initRules<T extends Function, P extends RuleSet<T>>(
|
|
|
39
39
|
ruleId,
|
|
40
40
|
visitor: visitors, // note: actually it is only one visitor object
|
|
41
41
|
};
|
|
42
|
-
})
|
|
42
|
+
})
|
|
43
43
|
)
|
|
44
|
-
.flatMap(visitor => visitor)
|
|
44
|
+
.flatMap((visitor) => visitor)
|
|
45
45
|
.filter(notUndefined);
|
|
46
46
|
}
|
package/src/config/types.ts
CHANGED
|
@@ -29,7 +29,7 @@ export type PreprocessorConfig =
|
|
|
29
29
|
|
|
30
30
|
export type DecoratorConfig = PreprocessorConfig;
|
|
31
31
|
|
|
32
|
-
export type
|
|
32
|
+
export type StyleguideRawConfig = {
|
|
33
33
|
plugins?: (string | Plugin)[];
|
|
34
34
|
extends?: string[];
|
|
35
35
|
doNotResolveExamples?: boolean;
|
|
@@ -51,7 +51,9 @@ export type LintRawConfig = {
|
|
|
51
51
|
oas3_1Decorators?: Record<string, DecoratorConfig>;
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
-
export type
|
|
54
|
+
export type ApiStyleguideRawConfig = Omit<StyleguideRawConfig, 'plugins'>;
|
|
55
|
+
|
|
56
|
+
export type ResolvedStyleguideConfig = PluginStyleguideConfig & {
|
|
55
57
|
plugins?: Plugin[];
|
|
56
58
|
recommendedFallback?: boolean;
|
|
57
59
|
extends?: void | never;
|
|
@@ -71,7 +73,7 @@ export type DecoratorsConfig = {
|
|
|
71
73
|
|
|
72
74
|
export type TypesExtensionFn = (
|
|
73
75
|
types: Record<string, NodeType>,
|
|
74
|
-
oasVersion: OasVersion
|
|
76
|
+
oasVersion: OasVersion
|
|
75
77
|
) => Record<string, NodeType>;
|
|
76
78
|
|
|
77
79
|
export type TypeExtensionsConfig = Partial<Record<OasMajorVersion, TypesExtensionFn>>;
|
|
@@ -83,14 +85,14 @@ export type CustomRulesConfig = {
|
|
|
83
85
|
|
|
84
86
|
export type Plugin = {
|
|
85
87
|
id: string;
|
|
86
|
-
configs?: Record<string,
|
|
88
|
+
configs?: Record<string, PluginStyleguideConfig>;
|
|
87
89
|
rules?: CustomRulesConfig;
|
|
88
90
|
preprocessors?: PreprocessorsConfig;
|
|
89
91
|
decorators?: DecoratorsConfig;
|
|
90
92
|
typeExtension?: TypeExtensionsConfig;
|
|
91
93
|
};
|
|
92
94
|
|
|
93
|
-
export type
|
|
95
|
+
export type PluginStyleguideConfig = Omit<StyleguideRawConfig, 'plugins' | 'extends'>;
|
|
94
96
|
|
|
95
97
|
export type ResolveHeader =
|
|
96
98
|
| {
|
|
@@ -123,35 +125,42 @@ export type Region = 'us' | 'eu';
|
|
|
123
125
|
|
|
124
126
|
export type AccessTokens = { [region in Region]?: string };
|
|
125
127
|
|
|
126
|
-
export type
|
|
128
|
+
export type DeprecatedInRawConfig = {
|
|
127
129
|
apiDefinitions?: Record<string, string>;
|
|
128
|
-
lint?:
|
|
129
|
-
resolve?: RawResolveConfig;
|
|
130
|
-
region?: Region;
|
|
130
|
+
lint?: StyleguideRawConfig;
|
|
131
131
|
referenceDocs?: Record<string, any>;
|
|
132
|
+
apis?: Record<string, Api & DeprecatedInApi>;
|
|
132
133
|
};
|
|
133
134
|
|
|
134
135
|
export type Api = {
|
|
135
136
|
root: string;
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
137
|
+
styleguide?: ApiStyleguideRawConfig;
|
|
138
|
+
} & FeaturesConfig;
|
|
139
|
+
|
|
140
|
+
export type DeprecatedInApi = {
|
|
141
|
+
lint?: ApiStyleguideRawConfig;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export type ResolvedApi = Omit<Api, 'styleguide'> & {
|
|
145
|
+
styleguide: ResolvedStyleguideConfig;
|
|
139
146
|
};
|
|
140
|
-
export type ResolvedApi = Omit<Api, 'lint'> & { lint: Omit<ResolvedLintConfig, 'plugins'>};
|
|
141
147
|
|
|
142
148
|
export type RawConfig = {
|
|
143
149
|
apis?: Record<string, Api>;
|
|
144
|
-
|
|
150
|
+
styleguide?: StyleguideRawConfig;
|
|
145
151
|
resolve?: RawResolveConfig;
|
|
146
152
|
region?: Region;
|
|
147
|
-
'features.openapi'?: Record<string, any>;
|
|
148
|
-
'features.mockServer'?: Record<string, any>;
|
|
149
153
|
organization?: string;
|
|
154
|
+
} & FeaturesConfig;
|
|
155
|
+
|
|
156
|
+
export type ResolvedConfig = Omit<RawConfig, 'apis' | 'styleguide'> & {
|
|
157
|
+
apis: Record<string, ResolvedApi>;
|
|
158
|
+
styleguide: ResolvedStyleguideConfig;
|
|
150
159
|
};
|
|
151
160
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
161
|
+
type FeaturesConfig = {
|
|
162
|
+
'features.openapi'?: Record<string, any>;
|
|
163
|
+
'features.mockServer'?: Record<string, any>;
|
|
155
164
|
};
|
|
156
165
|
|
|
157
166
|
export type RulesFields =
|