@redocly/openapi-core 1.0.0-beta.104 → 1.0.0-beta.107
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 +8 -6
- 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 +6 -5
- package/lib/config/config.js +27 -20
- package/lib/config/load.js +6 -7
- package/lib/config/minimal.d.ts +2 -2
- package/lib/config/minimal.js +3 -2
- package/lib/config/recommended.d.ts +2 -2
- package/lib/config/recommended.js +3 -2
- 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 +2 -2
- package/lib/index.js +3 -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/ajv.d.ts +1 -1
- package/lib/rules/ajv.js +6 -6
- 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/no-invalid-parameter-examples.js +3 -3
- package/lib/rules/common/no-invalid-schema-examples.js +3 -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/no-invalid-media-type-examples.js +2 -2
- package/lib/rules/oas3/remove-unused-components.js +2 -2
- package/lib/rules/other/stats.js +43 -14
- package/lib/rules/utils.d.ts +3 -2
- package/lib/rules/utils.js +19 -4
- package/lib/types/index.d.ts +2 -2
- package/lib/types/redocly-yaml.js +8 -7
- package/lib/utils.d.ts +5 -2
- package/lib/utils.js +20 -2
- package/lib/walk.d.ts +2 -1
- package/lib/walk.js +6 -3
- package/package.json +2 -2
- 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__/fixtures/.redocly.lint-ignore.yaml +5 -0
- package/src/__tests__/js-yaml.test.ts +6 -4
- package/src/__tests__/lint.test.ts +127 -12
- 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__/utils.test.ts +42 -1
- 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 +3 -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__/load.test.ts +2 -2
- 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 +36 -32
- package/src/config/load.ts +13 -16
- package/src/config/minimal.ts +5 -4
- package/src/config/recommended.ts +5 -4
- package/src/config/rules.ts +6 -6
- package/src/config/types.ts +28 -19
- package/src/config/utils.ts +74 -54
- 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 +3 -4
- 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 +160 -0
- package/src/rules/ajv.ts +7 -8
- 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 +4 -4
- package/src/rules/common/no-invalid-schema-examples.ts +4 -4
- 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 +13 -13
- 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 +14 -6
- 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 +19 -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/utils.ts +31 -8
- package/src/visitors.ts +4 -4
- package/src/walk.ts +15 -11
- 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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { parseYaml, stringifyYaml } from '../js-yaml';
|
|
4
|
-
import { slash } from '../utils';
|
|
4
|
+
import { slash, doesYamlFileExist } from '../utils';
|
|
5
5
|
import { NormalizedProblem } from '../walk';
|
|
6
6
|
import { OasVersion, OasMajorVersion, Oas2RuleSet, Oas3RuleSet } from '../oas-types';
|
|
7
7
|
|
|
@@ -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';
|
|
@@ -46,10 +46,20 @@ function getDomains() {
|
|
|
46
46
|
return domains;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
function getIgnoreFilePath(configFile?: string): string | undefined {
|
|
50
|
+
if (configFile) {
|
|
51
|
+
return doesYamlFileExist(configFile)
|
|
52
|
+
? path.join(path.dirname(configFile), IGNORE_FILE)
|
|
53
|
+
: path.join(configFile, IGNORE_FILE);
|
|
54
|
+
} else {
|
|
55
|
+
return typeof process === 'undefined' ? undefined : path.join(process.cwd(), IGNORE_FILE);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
49
59
|
export const DOMAINS = getDomains();
|
|
50
60
|
export const AVAILABLE_REGIONS = Object.keys(DOMAINS) as Region[];
|
|
51
61
|
|
|
52
|
-
export class
|
|
62
|
+
export class StyleguideConfig {
|
|
53
63
|
plugins: Plugin[];
|
|
54
64
|
ignore: Record<string, Record<string, Set<string>>> = {};
|
|
55
65
|
doNotResolveExamples: boolean;
|
|
@@ -65,11 +75,11 @@ export class LintConfig {
|
|
|
65
75
|
extendPaths: string[];
|
|
66
76
|
pluginPaths: string[];
|
|
67
77
|
|
|
68
|
-
constructor(public rawConfig:
|
|
78
|
+
constructor(public rawConfig: ResolvedStyleguideConfig, public configFile?: string) {
|
|
69
79
|
this.plugins = rawConfig.plugins || [];
|
|
70
80
|
this.doNotResolveExamples = !!rawConfig.doNotResolveExamples;
|
|
71
81
|
|
|
72
|
-
this.recommendedFallback = rawConfig.recommendedFallback || false
|
|
82
|
+
this.recommendedFallback = rawConfig.recommendedFallback || false;
|
|
73
83
|
|
|
74
84
|
this.rules = {
|
|
75
85
|
[OasVersion.Version2]: { ...rawConfig.rules, ...rawConfig.oas2Rules },
|
|
@@ -91,29 +101,25 @@ export class LintConfig {
|
|
|
91
101
|
|
|
92
102
|
this.extendPaths = rawConfig.extendPaths || [];
|
|
93
103
|
this.pluginPaths = rawConfig.pluginPaths || [];
|
|
104
|
+
this.resolveIgnore(getIgnoreFilePath(configFile));
|
|
105
|
+
}
|
|
94
106
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
: (typeof process !== 'undefined' && process.cwd()) || '';
|
|
98
|
-
const ignoreFile = path.join(dir, IGNORE_FILE);
|
|
107
|
+
resolveIgnore(ignoreFile?: string) {
|
|
108
|
+
if (!ignoreFile || !doesYamlFileExist(ignoreFile)) return;
|
|
99
109
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
this.ignore[path.resolve(path.dirname(ignoreFile), fileName)] = this.ignore[fileName];
|
|
112
|
-
for (const ruleId of Object.keys(this.ignore[fileName])) {
|
|
113
|
-
this.ignore[fileName][ruleId] = new Set(this.ignore[fileName][ruleId]);
|
|
114
|
-
}
|
|
115
|
-
delete this.ignore[fileName];
|
|
110
|
+
this.ignore =
|
|
111
|
+
(parseYaml(fs.readFileSync(ignoreFile, 'utf-8')) as Record<
|
|
112
|
+
string,
|
|
113
|
+
Record<string, Set<string>>
|
|
114
|
+
>) || {};
|
|
115
|
+
|
|
116
|
+
// resolve ignore paths
|
|
117
|
+
for (const fileName of Object.keys(this.ignore)) {
|
|
118
|
+
this.ignore[path.resolve(path.dirname(ignoreFile), fileName)] = this.ignore[fileName];
|
|
119
|
+
for (const ruleId of Object.keys(this.ignore[fileName])) {
|
|
120
|
+
this.ignore[fileName][ruleId] = new Set(this.ignore[fileName][ruleId]);
|
|
116
121
|
}
|
|
122
|
+
delete this.ignore[fileName];
|
|
117
123
|
}
|
|
118
124
|
}
|
|
119
125
|
|
|
@@ -224,15 +230,13 @@ export class LintConfig {
|
|
|
224
230
|
|
|
225
231
|
for (const usedVersion of Array.from(this._usedVersions)) {
|
|
226
232
|
rules.push(
|
|
227
|
-
...Object.keys(this.rules[usedVersion]).filter((name) => !this._usedRules.has(name))
|
|
233
|
+
...Object.keys(this.rules[usedVersion]).filter((name) => !this._usedRules.has(name))
|
|
228
234
|
);
|
|
229
235
|
decorators.push(
|
|
230
|
-
...Object.keys(this.decorators[usedVersion]).filter((name) => !this._usedRules.has(name))
|
|
236
|
+
...Object.keys(this.decorators[usedVersion]).filter((name) => !this._usedRules.has(name))
|
|
231
237
|
);
|
|
232
238
|
preprocessors.push(
|
|
233
|
-
...Object.keys(this.preprocessors[usedVersion]).filter(
|
|
234
|
-
(name) => !this._usedRules.has(name),
|
|
235
|
-
),
|
|
239
|
+
...Object.keys(this.preprocessors[usedVersion]).filter((name) => !this._usedRules.has(name))
|
|
236
240
|
);
|
|
237
241
|
}
|
|
238
242
|
|
|
@@ -293,7 +297,7 @@ export class LintConfig {
|
|
|
293
297
|
|
|
294
298
|
export class Config {
|
|
295
299
|
apis: Record<string, ResolvedApi>;
|
|
296
|
-
|
|
300
|
+
styleguide: StyleguideConfig;
|
|
297
301
|
resolve: ResolveConfig;
|
|
298
302
|
licenseKey?: string;
|
|
299
303
|
region?: Region;
|
|
@@ -302,7 +306,7 @@ export class Config {
|
|
|
302
306
|
organization?: string;
|
|
303
307
|
constructor(public rawConfig: ResolvedConfig, public configFile?: string) {
|
|
304
308
|
this.apis = rawConfig.apis || {};
|
|
305
|
-
this.
|
|
309
|
+
this.styleguide = new StyleguideConfig(rawConfig.styleguide || {}, configFile);
|
|
306
310
|
this['features.openapi'] = rawConfig['features.openapi'] || {};
|
|
307
311
|
this['features.mockServer'] = rawConfig['features.mockServer'] || {};
|
|
308
312
|
this.resolve = getResolveConfig(rawConfig?.resolve);
|
package/src/config/load.ts
CHANGED
|
@@ -1,29 +1,28 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { RedoclyClient } from '../redocly';
|
|
4
|
-
import { isEmptyObject, loadYaml } from '../utils';
|
|
4
|
+
import { isEmptyObject, loadYaml, doesYamlFileExist } from '../utils';
|
|
5
5
|
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,
|
|
13
13
|
customExtends,
|
|
14
|
-
configPath
|
|
14
|
+
configPath,
|
|
15
15
|
}: {
|
|
16
16
|
rawConfig: RawConfig;
|
|
17
17
|
customExtends?: string[];
|
|
18
18
|
configPath?: string;
|
|
19
|
-
|
|
20
19
|
}): Promise<Config> {
|
|
21
20
|
if (customExtends !== undefined) {
|
|
22
|
-
rawConfig.
|
|
23
|
-
rawConfig.
|
|
21
|
+
rawConfig.styleguide = rawConfig.styleguide || {};
|
|
22
|
+
rawConfig.styleguide.extends = customExtends;
|
|
24
23
|
} else if (isEmptyObject(rawConfig)) {
|
|
25
24
|
// TODO: check if we can add recommended here. add message here?
|
|
26
|
-
// rawConfig.
|
|
25
|
+
// rawConfig.styleguide = { extends: ['recommended'], recommendedFallback: true };
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
const redoclyClient = new RedoclyClient();
|
|
@@ -53,7 +52,7 @@ async function addConfigMetadata({
|
|
|
53
52
|
value: item.token,
|
|
54
53
|
},
|
|
55
54
|
]
|
|
56
|
-
: [])
|
|
55
|
+
: [])
|
|
57
56
|
);
|
|
58
57
|
}
|
|
59
58
|
}
|
|
@@ -64,27 +63,25 @@ async function addConfigMetadata({
|
|
|
64
63
|
export async function loadConfig(
|
|
65
64
|
configPath: string | undefined = findConfig(),
|
|
66
65
|
customExtends?: string[],
|
|
67
|
-
processRawConfig?: (rawConfig: RawConfig) => void | Promise<void
|
|
66
|
+
processRawConfig?: (rawConfig: RawConfig) => void | Promise<void>
|
|
68
67
|
): Promise<Config> {
|
|
69
68
|
const rawConfig = await getConfig(configPath);
|
|
70
|
-
|
|
71
69
|
if (typeof processRawConfig === 'function') {
|
|
72
70
|
await processRawConfig(rawConfig);
|
|
73
71
|
}
|
|
74
|
-
|
|
75
72
|
return await addConfigMetadata({
|
|
76
73
|
rawConfig,
|
|
77
74
|
customExtends,
|
|
78
75
|
configPath,
|
|
79
76
|
});
|
|
80
|
-
}
|
|
77
|
+
}
|
|
81
78
|
|
|
82
79
|
export const CONFIG_FILE_NAMES = ['redocly.yaml', 'redocly.yml', '.redocly.yaml', '.redocly.yml'];
|
|
83
80
|
|
|
84
81
|
export function findConfig(dir?: string): string | undefined {
|
|
85
82
|
if (!fs.hasOwnProperty('existsSync')) return;
|
|
86
83
|
const existingConfigFiles = CONFIG_FILE_NAMES.map((name) =>
|
|
87
|
-
dir ? path.resolve(dir, name) : name
|
|
84
|
+
dir ? path.resolve(dir, name) : name
|
|
88
85
|
).filter(fs.existsSync);
|
|
89
86
|
if (existingConfigFiles.length > 1) {
|
|
90
87
|
throw new Error(`
|
|
@@ -96,10 +93,10 @@ export function findConfig(dir?: string): string | undefined {
|
|
|
96
93
|
return existingConfigFiles[0];
|
|
97
94
|
}
|
|
98
95
|
|
|
99
|
-
export async function getConfig(configPath: string | undefined = findConfig()) {
|
|
100
|
-
if (!configPath) return {};
|
|
96
|
+
export async function getConfig(configPath: string | undefined = findConfig()): Promise<RawConfig> {
|
|
97
|
+
if (!configPath || !doesYamlFileExist(configPath)) return {};
|
|
101
98
|
try {
|
|
102
|
-
const rawConfig = (
|
|
99
|
+
const rawConfig = (await loadYaml<RawConfig & DeprecatedInRawConfig>(configPath)) || {};
|
|
103
100
|
return transformConfig(rawConfig);
|
|
104
101
|
} catch (e) {
|
|
105
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',
|
|
@@ -36,7 +36,7 @@ export default {
|
|
|
36
36
|
oas3_0Rules: {
|
|
37
37
|
'no-invalid-media-type-examples': {
|
|
38
38
|
severity: 'warn',
|
|
39
|
-
|
|
39
|
+
allowAdditionalProperties: false,
|
|
40
40
|
},
|
|
41
41
|
'no-server-example.com': 'warn',
|
|
42
42
|
'no-server-trailing-slash': 'error',
|
|
@@ -47,6 +47,7 @@ export default {
|
|
|
47
47
|
'no-servers-empty-enum': 'error',
|
|
48
48
|
},
|
|
49
49
|
oas3_1Rules: {
|
|
50
|
+
'no-invalid-media-type-examples': 'warn',
|
|
50
51
|
'no-server-example.com': 'warn',
|
|
51
52
|
'no-server-trailing-slash': 'error',
|
|
52
53
|
'no-empty-servers': 'warn',
|
|
@@ -55,4 +56,4 @@ export default {
|
|
|
55
56
|
'no-undefined-server-variable': 'warn',
|
|
56
57
|
'no-servers-empty-enum': 'error',
|
|
57
58
|
},
|
|
58
|
-
} as
|
|
59
|
+
} 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',
|
|
@@ -36,7 +36,7 @@ export default {
|
|
|
36
36
|
oas3_0Rules: {
|
|
37
37
|
'no-invalid-media-type-examples': {
|
|
38
38
|
severity: 'warn',
|
|
39
|
-
|
|
39
|
+
allowAdditionalProperties: false,
|
|
40
40
|
},
|
|
41
41
|
'no-server-example.com': 'warn',
|
|
42
42
|
'no-server-trailing-slash': 'error',
|
|
@@ -47,6 +47,7 @@ export default {
|
|
|
47
47
|
'no-servers-empty-enum': 'error',
|
|
48
48
|
},
|
|
49
49
|
oas3_1Rules: {
|
|
50
|
+
'no-invalid-media-type-examples': 'warn',
|
|
50
51
|
'no-server-example.com': 'warn',
|
|
51
52
|
'no-server-trailing-slash': 'error',
|
|
52
53
|
'no-empty-servers': 'error',
|
|
@@ -55,4 +56,4 @@ export default {
|
|
|
55
56
|
'no-undefined-server-variable': 'error',
|
|
56
57
|
'no-servers-empty-enum': 'error',
|
|
57
58
|
},
|
|
58
|
-
} as
|
|
59
|
+
} as PluginStyleguideConfig;
|