@redocly/openapi-core 1.0.0-beta.105 → 1.0.0-beta.108
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/lint-with-top-level-rule-report.bench.js +0 -1
- 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 +7 -4
- package/lib/config/all.d.ts +2 -2
- package/lib/config/all.js +3 -3
- 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 +70 -49
- package/lib/config/config.d.ts +8 -10
- package/lib/config/config.js +10 -7
- package/lib/config/load.d.ts +7 -0
- package/lib/config/load.js +18 -10
- package/lib/config/minimal.d.ts +2 -2
- package/lib/config/minimal.js +5 -4
- package/lib/config/recommended.d.ts +2 -2
- package/lib/config/recommended.js +5 -4
- package/lib/config/rules.d.ts +3 -3
- 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 +48 -31
- package/lib/decorators/common/registry-dependencies.js +1 -1
- package/lib/decorators/common/remove-x-internal.js +2 -2
- package/lib/env.d.ts +3 -0
- package/lib/env.js +8 -0
- package/lib/format/codeframes.js +16 -10
- package/lib/format/format.js +29 -27
- package/lib/index.d.ts +5 -5
- package/lib/index.js +4 -2
- package/lib/js-yaml/index.js +2 -6
- package/lib/lint.d.ts +2 -2
- package/lib/lint.js +16 -6
- package/lib/logger.d.ts +10 -0
- package/lib/logger.js +31 -0
- package/lib/output.d.ts +3 -0
- package/lib/output.js +9 -0
- package/lib/redocly/index.js +10 -9
- package/lib/redocly/registry-api-types.d.ts +28 -30
- package/lib/redocly/registry-api.d.ts +4 -3
- package/lib/redocly/registry-api.js +9 -4
- package/lib/ref-utils.js +2 -1
- package/lib/resolve.d.ts +1 -1
- package/lib/resolve.js +1 -1
- package/lib/rules/ajv.d.ts +1 -1
- package/lib/rules/ajv.js +7 -7
- package/lib/rules/common/assertions/asserts.js +4 -4
- package/lib/rules/common/assertions/index.js +1 -1
- 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/operation-security-defined.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 +3 -3
- package/lib/rules/oas2/index.js +4 -4
- package/lib/rules/oas2/remove-unused-components.js +5 -5
- package/lib/rules/oas3/index.js +6 -6
- 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/no-server-variables-empty-enum.d.ts +2 -0
- package/lib/rules/oas3/{no-servers-empty-enum.js → no-server-variables-empty-enum.js} +4 -4
- package/lib/rules/oas3/no-unused-components.js +1 -1
- package/lib/rules/oas3/remove-unused-components.js +5 -5
- package/lib/rules/other/stats.js +43 -14
- package/lib/rules/utils.d.ts +3 -2
- package/lib/rules/utils.js +20 -5
- package/lib/types/index.d.ts +2 -2
- package/lib/types/redocly-yaml.js +9 -8
- package/lib/utils.d.ts +5 -0
- package/lib/utils.js +22 -5
- package/lib/visitors.d.ts +1 -1
- package/lib/visitors.js +2 -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__/js-yaml.test.ts +6 -4
- package/src/__tests__/lint.test.ts +74 -6
- package/src/__tests__/logger-browser.test.ts +53 -0
- package/src/__tests__/logger.test.ts +47 -0
- package/src/__tests__/login.test.ts +2 -2
- package/src/__tests__/normalizeVisitors.test.ts +4 -4
- package/src/__tests__/output-browser.test.ts +18 -0
- package/src/__tests__/output.test.ts +15 -0
- 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-browser.test.ts +11 -0
- package/src/__tests__/utils.test.ts +7 -0
- 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 -2
- 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 +24 -20
- package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +7 -5
- package/src/config/__tests__/config-resolvers.test.ts +123 -121
- package/src/config/__tests__/config.test.ts +111 -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 +79 -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 +5 -6
- package/src/config/builtIn.ts +5 -5
- package/src/config/config-resolvers.ts +161 -96
- package/src/config/config.ts +15 -13
- package/src/config/load.ts +34 -11
- package/src/config/minimal.ts +7 -6
- package/src/config/recommended.ts +7 -6
- package/src/config/rules.ts +6 -6
- package/src/config/types.ts +28 -19
- package/src/config/utils.ts +78 -57
- 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/registry-dependencies.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/env.ts +5 -0
- package/src/format/codeframes.ts +18 -12
- package/src/format/format.ts +37 -42
- package/src/index.ts +8 -7
- package/src/js-yaml/index.ts +4 -8
- package/src/lint.ts +22 -18
- package/src/logger.ts +34 -0
- package/src/oas-types.ts +1 -6
- package/src/output.ts +7 -0
- package/src/redocly/__tests__/redocly-client.test.ts +25 -19
- package/src/redocly/index.ts +12 -7
- package/src/redocly/registry-api-types.ts +27 -29
- package/src/redocly/registry-api.ts +22 -12
- package/src/ref-utils.ts +4 -3
- package/src/resolve.ts +11 -8
- 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/asserts.ts +4 -4
- package/src/rules/common/assertions/index.ts +7 -7
- 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/operation-security-defined.ts +1 -1
- 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 +12 -9
- 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 +14 -9
- package/src/rules/oas3/__tests__/boolean-parameter-prefixes.test.ts +3 -3
- package/src/rules/oas3/__tests__/no-empty-enum-servers.com.test.ts +16 -16
- 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 +5 -5
- 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 → no-server-variables-empty-enum.ts} +10 -11
- package/src/rules/oas3/no-unused-components.ts +1 -1
- package/src/rules/oas3/remove-unused-components.ts +21 -10
- package/src/rules/other/stats.ts +46 -17
- package/src/rules/utils.ts +20 -4
- package/src/types/index.ts +5 -5
- package/src/types/redocly-yaml.ts +9 -8
- package/src/typings/common.ts +9 -1
- package/src/typings/openapi.ts +1 -1
- package/src/utils.ts +26 -3
- package/src/visitors.ts +9 -9
- 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/lib/rules/oas3/no-servers-empty-enum.d.ts +0 -2
- package/src/rules/common/license-url.ts +0 -10
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
|
-
import { blue, red } from 'colorette';
|
|
3
2
|
import { isAbsoluteUrl } from '../ref-utils';
|
|
4
3
|
import { BaseResolver } from '../resolve';
|
|
5
4
|
import { defaultPlugin } from './builtIn';
|
|
@@ -12,28 +11,32 @@ import {
|
|
|
12
11
|
transformConfig,
|
|
13
12
|
} from './utils';
|
|
14
13
|
import type {
|
|
15
|
-
|
|
14
|
+
StyleguideRawConfig,
|
|
15
|
+
ApiStyleguideRawConfig,
|
|
16
16
|
Plugin,
|
|
17
17
|
RawConfig,
|
|
18
18
|
ResolvedApi,
|
|
19
|
-
|
|
19
|
+
ResolvedStyleguideConfig,
|
|
20
20
|
RuleConfig,
|
|
21
|
+
DeprecatedInRawConfig,
|
|
21
22
|
} from './types';
|
|
23
|
+
import { isBrowser } from '../env';
|
|
22
24
|
import { isNotString, isString, notUndefined, parseYaml } from '../utils';
|
|
23
25
|
import { Config } from './config';
|
|
26
|
+
import { colorize, logger } from '../logger';
|
|
24
27
|
|
|
25
|
-
export async function resolveConfig(rawConfig: RawConfig, configPath?: string) {
|
|
26
|
-
if (rawConfig.
|
|
28
|
+
export async function resolveConfig(rawConfig: RawConfig, configPath?: string): Promise<Config> {
|
|
29
|
+
if (rawConfig.styleguide?.extends?.some(isNotString)) {
|
|
27
30
|
throw new Error(
|
|
28
|
-
`Error configuration format not detected in extends value must contain strings
|
|
31
|
+
`Error configuration format not detected in extends value must contain strings`
|
|
29
32
|
);
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
const resolver = new BaseResolver(getResolveConfig(rawConfig.resolve));
|
|
33
|
-
const configExtends = rawConfig?.
|
|
34
|
-
const recommendedFallback = !rawConfig?.
|
|
35
|
-
const
|
|
36
|
-
...rawConfig?.
|
|
36
|
+
const configExtends = rawConfig?.styleguide?.extends ?? ['recommended'];
|
|
37
|
+
const recommendedFallback = !rawConfig?.styleguide?.extends;
|
|
38
|
+
const styleguideConfig = {
|
|
39
|
+
...rawConfig?.styleguide,
|
|
37
40
|
extends: configExtends,
|
|
38
41
|
recommendedFallback,
|
|
39
42
|
};
|
|
@@ -41,14 +44,14 @@ export async function resolveConfig(rawConfig: RawConfig, configPath?: string) {
|
|
|
41
44
|
const apis = await resolveApis({
|
|
42
45
|
rawConfig: {
|
|
43
46
|
...rawConfig,
|
|
44
|
-
|
|
47
|
+
styleguide: styleguideConfig,
|
|
45
48
|
},
|
|
46
49
|
configPath,
|
|
47
50
|
resolver,
|
|
48
51
|
});
|
|
49
52
|
|
|
50
|
-
const
|
|
51
|
-
|
|
53
|
+
const styleguide = await resolveStyleguideConfig({
|
|
54
|
+
styleguideConfig,
|
|
52
55
|
configPath,
|
|
53
56
|
resolver,
|
|
54
57
|
});
|
|
@@ -57,47 +60,70 @@ export async function resolveConfig(rawConfig: RawConfig, configPath?: string) {
|
|
|
57
60
|
{
|
|
58
61
|
...rawConfig,
|
|
59
62
|
apis,
|
|
60
|
-
|
|
63
|
+
styleguide,
|
|
61
64
|
},
|
|
62
|
-
configPath
|
|
65
|
+
configPath
|
|
63
66
|
);
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
export function resolvePlugins(
|
|
67
70
|
plugins: (string | Plugin)[] | null,
|
|
68
|
-
configPath: string = ''
|
|
71
|
+
configPath: string = ''
|
|
69
72
|
): Plugin[] {
|
|
70
73
|
if (!plugins) return [];
|
|
71
74
|
|
|
72
|
-
//
|
|
73
|
-
const requireFunc =
|
|
75
|
+
// TODO: implement or reuse Resolver approach so it will work in node and browser envs
|
|
76
|
+
const requireFunc = (plugin: string | Plugin): Plugin | undefined => {
|
|
77
|
+
if (isBrowser && isString(plugin)) {
|
|
78
|
+
logger.error(`Cannot load ${plugin}. Plugins aren't supported in browser yet.`);
|
|
79
|
+
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (isString(plugin)) {
|
|
84
|
+
const absoltePluginPath = path.resolve(path.dirname(configPath), plugin);
|
|
85
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
86
|
+
// @ts-ignore
|
|
87
|
+
return typeof __webpack_require__ === 'function'
|
|
88
|
+
? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
89
|
+
// @ts-ignore
|
|
90
|
+
__non_webpack_require__(absoltePluginPath)
|
|
91
|
+
: require(absoltePluginPath);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return plugin;
|
|
95
|
+
};
|
|
74
96
|
|
|
75
97
|
const seenPluginIds = new Map<string, string>();
|
|
76
98
|
|
|
77
99
|
return plugins
|
|
78
100
|
.map((p) => {
|
|
79
101
|
if (isString(p) && isAbsoluteUrl(p)) {
|
|
80
|
-
throw new Error(red(`We don't support remote plugins yet.`));
|
|
102
|
+
throw new Error(colorize.red(`We don't support remote plugins yet.`));
|
|
81
103
|
}
|
|
82
104
|
|
|
83
105
|
// TODO: resolve npm packages similar to eslint
|
|
84
|
-
const pluginModule =
|
|
85
|
-
|
|
86
|
-
|
|
106
|
+
const pluginModule = requireFunc(p);
|
|
107
|
+
|
|
108
|
+
if (!pluginModule) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
87
111
|
|
|
88
112
|
const id = pluginModule.id;
|
|
89
113
|
if (typeof id !== 'string') {
|
|
90
|
-
throw new Error(
|
|
114
|
+
throw new Error(
|
|
115
|
+
colorize.red(`Plugin must define \`id\` property in ${colorize.blue(p.toString())}.`)
|
|
116
|
+
);
|
|
91
117
|
}
|
|
92
118
|
|
|
93
119
|
if (seenPluginIds.has(id)) {
|
|
94
120
|
const pluginPath = seenPluginIds.get(id)!;
|
|
95
121
|
throw new Error(
|
|
96
|
-
red(
|
|
97
|
-
`Plugin "id" must be unique. Plugin ${
|
|
98
|
-
|
|
99
|
-
)}" already seen in ${blue(pluginPath)}
|
|
100
|
-
)
|
|
122
|
+
colorize.red(
|
|
123
|
+
`Plugin "id" must be unique. Plugin ${colorize.blue(
|
|
124
|
+
p.toString()
|
|
125
|
+
)} uses id "${colorize.blue(id)}" already seen in ${colorize.blue(pluginPath)}`
|
|
126
|
+
)
|
|
101
127
|
);
|
|
102
128
|
}
|
|
103
129
|
|
|
@@ -124,7 +150,7 @@ export function resolvePlugins(
|
|
|
124
150
|
if (pluginModule.preprocessors) {
|
|
125
151
|
if (!pluginModule.preprocessors.oas3 && !pluginModule.preprocessors.oas2) {
|
|
126
152
|
throw new Error(
|
|
127
|
-
`Plugin \`preprocessors\` must have \`oas3\` or \`oas2\` preprocessors "${p}
|
|
153
|
+
`Plugin \`preprocessors\` must have \`oas3\` or \`oas2\` preprocessors "${p}.`
|
|
128
154
|
);
|
|
129
155
|
}
|
|
130
156
|
plugin.preprocessors = {};
|
|
@@ -163,45 +189,48 @@ export async function resolveApis({
|
|
|
163
189
|
configPath?: string;
|
|
164
190
|
resolver?: BaseResolver;
|
|
165
191
|
}): Promise<Record<string, ResolvedApi>> {
|
|
166
|
-
const { apis = {},
|
|
167
|
-
|
|
192
|
+
const { apis = {}, styleguide: styleguideConfig = {} } = rawConfig;
|
|
193
|
+
const resolvedApis: Record<string, ResolvedApi> = {};
|
|
168
194
|
for (const [apiName, apiContent] of Object.entries(apis || {})) {
|
|
169
|
-
if (apiContent.
|
|
195
|
+
if (apiContent.styleguide?.extends?.some(isNotString)) {
|
|
170
196
|
throw new Error(
|
|
171
|
-
`Error configuration format not detected in extends value must contain strings
|
|
197
|
+
`Error configuration format not detected in extends value must contain strings`
|
|
172
198
|
);
|
|
173
199
|
}
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
200
|
+
const rawStyleguideConfig = getMergedRawStyleguideConfig(
|
|
201
|
+
styleguideConfig,
|
|
202
|
+
apiContent.styleguide
|
|
203
|
+
);
|
|
204
|
+
const resolvedApiConfig = await resolveStyleguideConfig({
|
|
205
|
+
styleguideConfig: rawStyleguideConfig,
|
|
177
206
|
configPath,
|
|
178
207
|
resolver,
|
|
179
208
|
});
|
|
180
|
-
resolvedApis[apiName] = { ...apiContent,
|
|
209
|
+
resolvedApis[apiName] = { ...apiContent, styleguide: resolvedApiConfig };
|
|
181
210
|
}
|
|
182
211
|
return resolvedApis;
|
|
183
212
|
}
|
|
184
213
|
|
|
185
|
-
async function
|
|
214
|
+
async function resolveAndMergeNestedStyleguideConfig(
|
|
186
215
|
{
|
|
187
|
-
|
|
216
|
+
styleguideConfig,
|
|
188
217
|
configPath = '',
|
|
189
218
|
resolver = new BaseResolver(),
|
|
190
219
|
}: {
|
|
191
|
-
|
|
220
|
+
styleguideConfig?: StyleguideRawConfig;
|
|
192
221
|
configPath?: string;
|
|
193
222
|
resolver?: BaseResolver;
|
|
194
223
|
},
|
|
195
224
|
parentConfigPaths: string[] = [],
|
|
196
|
-
extendPaths: string[] = []
|
|
197
|
-
): Promise<
|
|
225
|
+
extendPaths: string[] = []
|
|
226
|
+
): Promise<ResolvedStyleguideConfig> {
|
|
198
227
|
if (parentConfigPaths.includes(configPath)) {
|
|
199
228
|
throw new Error(`Circular dependency in config file: "${configPath}"`);
|
|
200
229
|
}
|
|
201
230
|
const plugins = getUniquePlugins(
|
|
202
|
-
resolvePlugins([...(
|
|
231
|
+
resolvePlugins([...(styleguideConfig?.plugins || []), defaultPlugin], configPath)
|
|
203
232
|
);
|
|
204
|
-
const pluginPaths =
|
|
233
|
+
const pluginPaths = styleguideConfig?.plugins
|
|
205
234
|
?.filter(isString)
|
|
206
235
|
.map((p) => path.resolve(path.dirname(configPath), p));
|
|
207
236
|
|
|
@@ -209,8 +238,8 @@ async function resolveAndMergeNestedLint(
|
|
|
209
238
|
? configPath
|
|
210
239
|
: configPath && path.resolve(configPath);
|
|
211
240
|
|
|
212
|
-
const extendConfigs:
|
|
213
|
-
|
|
241
|
+
const extendConfigs: ResolvedStyleguideConfig[] = await Promise.all(
|
|
242
|
+
styleguideConfig?.extends?.map(async (presetItem) => {
|
|
214
243
|
if (!isAbsoluteUrl(presetItem) && !path.extname(presetItem)) {
|
|
215
244
|
return resolvePreset(presetItem, plugins);
|
|
216
245
|
}
|
|
@@ -219,23 +248,23 @@ async function resolveAndMergeNestedLint(
|
|
|
219
248
|
: isAbsoluteUrl(configPath)
|
|
220
249
|
? new URL(presetItem, configPath).href
|
|
221
250
|
: path.resolve(path.dirname(configPath), presetItem);
|
|
222
|
-
const
|
|
223
|
-
return await
|
|
251
|
+
const extendedStyleguideConfig = await loadExtendStyleguideConfig(pathItem, resolver);
|
|
252
|
+
return await resolveAndMergeNestedStyleguideConfig(
|
|
224
253
|
{
|
|
225
|
-
|
|
254
|
+
styleguideConfig: extendedStyleguideConfig,
|
|
226
255
|
configPath: pathItem,
|
|
227
256
|
resolver: resolver,
|
|
228
257
|
},
|
|
229
258
|
[...parentConfigPaths, resolvedConfigPath],
|
|
230
|
-
extendPaths
|
|
259
|
+
extendPaths
|
|
231
260
|
);
|
|
232
|
-
}) || []
|
|
261
|
+
}) || []
|
|
233
262
|
);
|
|
234
263
|
|
|
235
|
-
const { plugins: mergedPlugins = [], ...
|
|
264
|
+
const { plugins: mergedPlugins = [], ...styleguide } = mergeExtends([
|
|
236
265
|
...extendConfigs,
|
|
237
266
|
{
|
|
238
|
-
...
|
|
267
|
+
...styleguideConfig,
|
|
239
268
|
plugins,
|
|
240
269
|
extends: undefined,
|
|
241
270
|
extendPaths: [...parentConfigPaths, resolvedConfigPath],
|
|
@@ -244,91 +273,127 @@ async function resolveAndMergeNestedLint(
|
|
|
244
273
|
]);
|
|
245
274
|
|
|
246
275
|
return {
|
|
247
|
-
...
|
|
248
|
-
extendPaths:
|
|
276
|
+
...styleguide,
|
|
277
|
+
extendPaths: styleguide.extendPaths?.filter((path) => path && !isAbsoluteUrl(path)),
|
|
249
278
|
plugins: getUniquePlugins(mergedPlugins),
|
|
250
|
-
recommendedFallback:
|
|
251
|
-
doNotResolveExamples:
|
|
279
|
+
recommendedFallback: styleguideConfig?.recommendedFallback,
|
|
280
|
+
doNotResolveExamples: styleguideConfig?.doNotResolveExamples,
|
|
252
281
|
};
|
|
253
282
|
}
|
|
254
283
|
|
|
255
|
-
export async function
|
|
256
|
-
|
|
257
|
-
|
|
284
|
+
export async function resolveStyleguideConfig(
|
|
285
|
+
opts: {
|
|
286
|
+
styleguideConfig?: StyleguideRawConfig;
|
|
258
287
|
configPath?: string;
|
|
259
288
|
resolver?: BaseResolver;
|
|
260
289
|
},
|
|
261
290
|
parentConfigPaths: string[] = [],
|
|
262
|
-
extendPaths: string[] = []
|
|
263
|
-
): Promise<
|
|
264
|
-
const
|
|
291
|
+
extendPaths: string[] = []
|
|
292
|
+
): Promise<ResolvedStyleguideConfig> {
|
|
293
|
+
const resolvedStyleguideConfig = await resolveAndMergeNestedStyleguideConfig(
|
|
294
|
+
opts,
|
|
295
|
+
parentConfigPaths,
|
|
296
|
+
extendPaths
|
|
297
|
+
);
|
|
265
298
|
|
|
266
299
|
return {
|
|
267
|
-
...
|
|
268
|
-
rules:
|
|
300
|
+
...resolvedStyleguideConfig,
|
|
301
|
+
rules:
|
|
302
|
+
resolvedStyleguideConfig.rules &&
|
|
303
|
+
groupStyleguideAssertionRules(resolvedStyleguideConfig.rules),
|
|
269
304
|
};
|
|
270
305
|
}
|
|
271
306
|
|
|
272
|
-
export function resolvePreset(presetName: string, plugins: Plugin[]):
|
|
307
|
+
export function resolvePreset(presetName: string, plugins: Plugin[]): ResolvedStyleguideConfig {
|
|
273
308
|
const { pluginId, configName } = parsePresetName(presetName);
|
|
274
309
|
const plugin = plugins.find((p) => p.id === pluginId);
|
|
275
310
|
if (!plugin) {
|
|
276
|
-
throw new Error(
|
|
311
|
+
throw new Error(
|
|
312
|
+
`Invalid config ${colorize.red(presetName)}: plugin ${pluginId} is not included.`
|
|
313
|
+
);
|
|
277
314
|
}
|
|
278
315
|
|
|
279
|
-
const preset = plugin.configs?.[configName]
|
|
316
|
+
const preset = plugin.configs?.[configName];
|
|
280
317
|
if (!preset) {
|
|
281
318
|
throw new Error(
|
|
282
319
|
pluginId
|
|
283
|
-
? `Invalid config ${red(
|
|
284
|
-
presetName
|
|
320
|
+
? `Invalid config ${colorize.red(
|
|
321
|
+
presetName
|
|
285
322
|
)}: plugin ${pluginId} doesn't export config with name ${configName}.`
|
|
286
|
-
: `Invalid config ${red(presetName)}: there is no such built-in config
|
|
323
|
+
: `Invalid config ${colorize.red(presetName)}: there is no such built-in config.`
|
|
287
324
|
);
|
|
288
325
|
}
|
|
289
326
|
return preset;
|
|
290
327
|
}
|
|
291
328
|
|
|
292
|
-
async function
|
|
329
|
+
async function loadExtendStyleguideConfig(
|
|
293
330
|
filePath: string,
|
|
294
|
-
resolver: BaseResolver
|
|
295
|
-
): Promise<
|
|
331
|
+
resolver: BaseResolver
|
|
332
|
+
): Promise<StyleguideRawConfig> {
|
|
296
333
|
try {
|
|
297
334
|
const fileSource = await resolver.loadExternalRef(filePath);
|
|
298
|
-
const rawConfig = transformConfig(
|
|
299
|
-
|
|
300
|
-
|
|
335
|
+
const rawConfig = transformConfig(
|
|
336
|
+
parseYaml(fileSource.body) as RawConfig & DeprecatedInRawConfig
|
|
337
|
+
);
|
|
338
|
+
if (!rawConfig.styleguide) {
|
|
339
|
+
throw new Error(`Styleguide configuration format not detected: "${filePath}"`);
|
|
301
340
|
}
|
|
302
341
|
|
|
303
|
-
return rawConfig.
|
|
342
|
+
return rawConfig.styleguide;
|
|
304
343
|
} catch (error) {
|
|
305
344
|
throw new Error(`Failed to load "${filePath}": ${error.message}`);
|
|
306
345
|
}
|
|
307
346
|
}
|
|
308
347
|
|
|
309
|
-
function
|
|
348
|
+
function getMergedRawStyleguideConfig(
|
|
349
|
+
rootStyleguideConfig: StyleguideRawConfig,
|
|
350
|
+
apiStyleguideConfig?: ApiStyleguideRawConfig
|
|
351
|
+
) {
|
|
310
352
|
const resultLint = {
|
|
311
|
-
...
|
|
312
|
-
...
|
|
313
|
-
rules: { ...
|
|
314
|
-
oas2Rules: { ...
|
|
315
|
-
oas3_0Rules: { ...
|
|
316
|
-
oas3_1Rules: { ...
|
|
317
|
-
preprocessors: {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
353
|
+
...rootStyleguideConfig,
|
|
354
|
+
...apiStyleguideConfig,
|
|
355
|
+
rules: { ...rootStyleguideConfig?.rules, ...apiStyleguideConfig?.rules },
|
|
356
|
+
oas2Rules: { ...rootStyleguideConfig?.oas2Rules, ...apiStyleguideConfig?.oas2Rules },
|
|
357
|
+
oas3_0Rules: { ...rootStyleguideConfig?.oas3_0Rules, ...apiStyleguideConfig?.oas3_0Rules },
|
|
358
|
+
oas3_1Rules: { ...rootStyleguideConfig?.oas3_1Rules, ...apiStyleguideConfig?.oas3_1Rules },
|
|
359
|
+
preprocessors: {
|
|
360
|
+
...rootStyleguideConfig?.preprocessors,
|
|
361
|
+
...apiStyleguideConfig?.preprocessors,
|
|
362
|
+
},
|
|
363
|
+
oas2Preprocessors: {
|
|
364
|
+
...rootStyleguideConfig?.oas2Preprocessors,
|
|
365
|
+
...apiStyleguideConfig?.oas2Preprocessors,
|
|
366
|
+
},
|
|
367
|
+
oas3_0Preprocessors: {
|
|
368
|
+
...rootStyleguideConfig?.oas3_0Preprocessors,
|
|
369
|
+
...apiStyleguideConfig?.oas3_0Preprocessors,
|
|
370
|
+
},
|
|
371
|
+
oas3_1Preprocessors: {
|
|
372
|
+
...rootStyleguideConfig?.oas3_1Preprocessors,
|
|
373
|
+
...apiStyleguideConfig?.oas3_1Preprocessors,
|
|
374
|
+
},
|
|
375
|
+
decorators: { ...rootStyleguideConfig?.decorators, ...apiStyleguideConfig?.decorators },
|
|
376
|
+
oas2Decorators: {
|
|
377
|
+
...rootStyleguideConfig?.oas2Decorators,
|
|
378
|
+
...apiStyleguideConfig?.oas2Decorators,
|
|
379
|
+
},
|
|
380
|
+
oas3_0Decorators: {
|
|
381
|
+
...rootStyleguideConfig?.oas3_0Decorators,
|
|
382
|
+
...apiStyleguideConfig?.oas3_0Decorators,
|
|
383
|
+
},
|
|
384
|
+
oas3_1Decorators: {
|
|
385
|
+
...rootStyleguideConfig?.oas3_1Decorators,
|
|
386
|
+
...apiStyleguideConfig?.oas3_1Decorators,
|
|
387
|
+
},
|
|
388
|
+
recommendedFallback: apiStyleguideConfig?.extends
|
|
389
|
+
? false
|
|
390
|
+
: rootStyleguideConfig.recommendedFallback,
|
|
326
391
|
};
|
|
327
392
|
return resultLint;
|
|
328
393
|
}
|
|
329
394
|
|
|
330
|
-
function
|
|
331
|
-
rules: Record<string, RuleConfig> | undefined
|
|
395
|
+
function groupStyleguideAssertionRules(
|
|
396
|
+
rules: Record<string, RuleConfig> | undefined
|
|
332
397
|
): Record<string, RuleConfig> | undefined {
|
|
333
398
|
if (!rules) {
|
|
334
399
|
return rules;
|
package/src/config/config.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { parseYaml, stringifyYaml } from '../js-yaml';
|
|
|
4
4
|
import { slash, doesYamlFileExist } from '../utils';
|
|
5
5
|
import { NormalizedProblem } from '../walk';
|
|
6
6
|
import { OasVersion, OasMajorVersion, Oas2RuleSet, Oas3RuleSet } from '../oas-types';
|
|
7
|
+
import { env } from '../env';
|
|
7
8
|
|
|
8
9
|
import type { NodeType } from '../types';
|
|
9
10
|
import type {
|
|
@@ -14,14 +15,11 @@ import type {
|
|
|
14
15
|
ResolveConfig,
|
|
15
16
|
ResolvedApi,
|
|
16
17
|
ResolvedConfig,
|
|
17
|
-
|
|
18
|
+
ResolvedStyleguideConfig,
|
|
18
19
|
RuleConfig,
|
|
19
20
|
} from './types';
|
|
20
21
|
import { getResolveConfig } from './utils';
|
|
21
22
|
|
|
22
|
-
// Alias environment here so this file can work in browser environments too.
|
|
23
|
-
export const env = typeof process !== 'undefined' ? process.env || {} : {};
|
|
24
|
-
|
|
25
23
|
export const IGNORE_FILE = '.redocly.lint-ignore.yaml';
|
|
26
24
|
const IGNORE_BANNER =
|
|
27
25
|
`# This file instructs Redocly's linter to ignore the rules contained for specific parts of your API.\n` +
|
|
@@ -59,7 +57,7 @@ function getIgnoreFilePath(configFile?: string): string | undefined {
|
|
|
59
57
|
export const DOMAINS = getDomains();
|
|
60
58
|
export const AVAILABLE_REGIONS = Object.keys(DOMAINS) as Region[];
|
|
61
59
|
|
|
62
|
-
export class
|
|
60
|
+
export class StyleguideConfig {
|
|
63
61
|
plugins: Plugin[];
|
|
64
62
|
ignore: Record<string, Record<string, Set<string>>> = {};
|
|
65
63
|
doNotResolveExamples: boolean;
|
|
@@ -75,7 +73,7 @@ export class LintConfig {
|
|
|
75
73
|
extendPaths: string[];
|
|
76
74
|
pluginPaths: string[];
|
|
77
75
|
|
|
78
|
-
constructor(public rawConfig:
|
|
76
|
+
constructor(public rawConfig: ResolvedStyleguideConfig, public configFile?: string) {
|
|
79
77
|
this.plugins = rawConfig.plugins || [];
|
|
80
78
|
this.doNotResolveExamples = !!rawConfig.doNotResolveExamples;
|
|
81
79
|
|
|
@@ -172,9 +170,11 @@ export class LintConfig {
|
|
|
172
170
|
case OasVersion.Version3_1:
|
|
173
171
|
if (!plugin.typeExtension.oas3) continue;
|
|
174
172
|
extendedTypes = plugin.typeExtension.oas3(extendedTypes, version);
|
|
173
|
+
break;
|
|
175
174
|
case OasVersion.Version2:
|
|
176
175
|
if (!plugin.typeExtension.oas2) continue;
|
|
177
176
|
extendedTypes = plugin.typeExtension.oas2(extendedTypes, version);
|
|
177
|
+
break;
|
|
178
178
|
default:
|
|
179
179
|
throw new Error('Not implemented');
|
|
180
180
|
}
|
|
@@ -192,7 +192,7 @@ export class LintConfig {
|
|
|
192
192
|
severity: settings,
|
|
193
193
|
};
|
|
194
194
|
} else {
|
|
195
|
-
return { severity: 'error'
|
|
195
|
+
return { severity: 'error', ...settings };
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
198
|
|
|
@@ -203,10 +203,10 @@ export class LintConfig {
|
|
|
203
203
|
const settings = this.preprocessors[oasVersion][ruleId] || 'off';
|
|
204
204
|
if (typeof settings === 'string') {
|
|
205
205
|
return {
|
|
206
|
-
severity: settings === 'on' ?
|
|
206
|
+
severity: settings === 'on' ? 'error' : settings,
|
|
207
207
|
};
|
|
208
208
|
} else {
|
|
209
|
-
return { severity: 'error'
|
|
209
|
+
return { severity: 'error', ...settings };
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
|
|
@@ -216,10 +216,10 @@ export class LintConfig {
|
|
|
216
216
|
const settings = this.decorators[oasVersion][ruleId] || 'off';
|
|
217
217
|
if (typeof settings === 'string') {
|
|
218
218
|
return {
|
|
219
|
-
severity: settings === 'on' ?
|
|
219
|
+
severity: settings === 'on' ? 'error' : settings,
|
|
220
220
|
};
|
|
221
221
|
} else {
|
|
222
|
-
return { severity: 'error'
|
|
222
|
+
return { severity: 'error', ...settings };
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
225
|
|
|
@@ -250,12 +250,14 @@ export class LintConfig {
|
|
|
250
250
|
getRulesForOasVersion(version: OasMajorVersion) {
|
|
251
251
|
switch (version) {
|
|
252
252
|
case OasMajorVersion.Version3:
|
|
253
|
+
// eslint-disable-next-line no-case-declarations
|
|
253
254
|
const oas3Rules: Oas3RuleSet[] = []; // default ruleset
|
|
254
255
|
this.plugins.forEach((p) => p.preprocessors?.oas3 && oas3Rules.push(p.preprocessors.oas3));
|
|
255
256
|
this.plugins.forEach((p) => p.rules?.oas3 && oas3Rules.push(p.rules.oas3));
|
|
256
257
|
this.plugins.forEach((p) => p.decorators?.oas3 && oas3Rules.push(p.decorators.oas3));
|
|
257
258
|
return oas3Rules;
|
|
258
259
|
case OasMajorVersion.Version2:
|
|
260
|
+
// eslint-disable-next-line no-case-declarations
|
|
259
261
|
const oas2Rules: Oas2RuleSet[] = []; // default ruleset
|
|
260
262
|
this.plugins.forEach((p) => p.preprocessors?.oas2 && oas2Rules.push(p.preprocessors.oas2));
|
|
261
263
|
this.plugins.forEach((p) => p.rules?.oas2 && oas2Rules.push(p.rules.oas2));
|
|
@@ -297,7 +299,7 @@ export class LintConfig {
|
|
|
297
299
|
|
|
298
300
|
export class Config {
|
|
299
301
|
apis: Record<string, ResolvedApi>;
|
|
300
|
-
|
|
302
|
+
styleguide: StyleguideConfig;
|
|
301
303
|
resolve: ResolveConfig;
|
|
302
304
|
licenseKey?: string;
|
|
303
305
|
region?: Region;
|
|
@@ -306,7 +308,7 @@ export class Config {
|
|
|
306
308
|
organization?: string;
|
|
307
309
|
constructor(public rawConfig: ResolvedConfig, public configFile?: string) {
|
|
308
310
|
this.apis = rawConfig.apis || {};
|
|
309
|
-
this.
|
|
311
|
+
this.styleguide = new StyleguideConfig(rawConfig.styleguide || {}, configFile);
|
|
310
312
|
this['features.openapi'] = rawConfig['features.openapi'] || {};
|
|
311
313
|
this['features.mockServer'] = rawConfig['features.mockServer'] || {};
|
|
312
314
|
this.resolve = getResolveConfig(rawConfig?.resolve);
|
package/src/config/load.ts
CHANGED
|
@@ -2,33 +2,34 @@ import * as fs from 'fs';
|
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { RedoclyClient } from '../redocly';
|
|
4
4
|
import { isEmptyObject, loadYaml, doesYamlFileExist } from '../utils';
|
|
5
|
+
import { parseYaml } from '../js-yaml';
|
|
5
6
|
import { Config, DOMAINS } from './config';
|
|
6
7
|
import { transformConfig } from './utils';
|
|
7
8
|
import { resolveConfig } from './config-resolvers';
|
|
8
9
|
|
|
9
|
-
import type { RawConfig, Region } from './types';
|
|
10
|
+
import type { DeprecatedInRawConfig, RawConfig, Region } from './types';
|
|
11
|
+
import { RegionalTokenWithValidity } from '../redocly/redocly-client-types';
|
|
10
12
|
|
|
11
13
|
async function addConfigMetadata({
|
|
12
14
|
rawConfig,
|
|
13
15
|
customExtends,
|
|
14
16
|
configPath,
|
|
17
|
+
tokens,
|
|
15
18
|
}: {
|
|
16
19
|
rawConfig: RawConfig;
|
|
17
20
|
customExtends?: string[];
|
|
18
21
|
configPath?: string;
|
|
22
|
+
tokens?: RegionalTokenWithValidity[];
|
|
19
23
|
}): Promise<Config> {
|
|
20
24
|
if (customExtends !== undefined) {
|
|
21
|
-
rawConfig.
|
|
22
|
-
rawConfig.
|
|
25
|
+
rawConfig.styleguide = rawConfig.styleguide || {};
|
|
26
|
+
rawConfig.styleguide.extends = customExtends;
|
|
23
27
|
} else if (isEmptyObject(rawConfig)) {
|
|
24
28
|
// TODO: check if we can add recommended here. add message here?
|
|
25
|
-
// rawConfig.
|
|
29
|
+
// rawConfig.styleguide = { extends: ['recommended'], recommendedFallback: true };
|
|
26
30
|
}
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
const tokens = await redoclyClient.getTokens();
|
|
30
|
-
|
|
31
|
-
if (tokens.length) {
|
|
32
|
+
if (tokens?.length) {
|
|
32
33
|
if (!rawConfig.resolve) rawConfig.resolve = {};
|
|
33
34
|
if (!rawConfig.resolve.http) rawConfig.resolve.http = {};
|
|
34
35
|
rawConfig.resolve.http.headers = [...(rawConfig.resolve.http.headers ?? [])];
|
|
@@ -69,10 +70,15 @@ export async function loadConfig(
|
|
|
69
70
|
if (typeof processRawConfig === 'function') {
|
|
70
71
|
await processRawConfig(rawConfig);
|
|
71
72
|
}
|
|
72
|
-
|
|
73
|
+
|
|
74
|
+
const redoclyClient = new RedoclyClient();
|
|
75
|
+
const tokens = await redoclyClient.getTokens();
|
|
76
|
+
|
|
77
|
+
return addConfigMetadata({
|
|
73
78
|
rawConfig,
|
|
74
79
|
customExtends,
|
|
75
80
|
configPath,
|
|
81
|
+
tokens,
|
|
76
82
|
});
|
|
77
83
|
}
|
|
78
84
|
|
|
@@ -93,12 +99,29 @@ export function findConfig(dir?: string): string | undefined {
|
|
|
93
99
|
return existingConfigFiles[0];
|
|
94
100
|
}
|
|
95
101
|
|
|
96
|
-
export async function getConfig(configPath: string | undefined = findConfig()) {
|
|
102
|
+
export async function getConfig(configPath: string | undefined = findConfig()): Promise<RawConfig> {
|
|
97
103
|
if (!configPath || !doesYamlFileExist(configPath)) return {};
|
|
98
104
|
try {
|
|
99
|
-
const rawConfig = (
|
|
105
|
+
const rawConfig = (await loadYaml<RawConfig & DeprecatedInRawConfig>(configPath)) || {};
|
|
100
106
|
return transformConfig(rawConfig);
|
|
101
107
|
} catch (e) {
|
|
102
108
|
throw new Error(`Error parsing config file at '${configPath}': ${e.message}`);
|
|
103
109
|
}
|
|
104
110
|
}
|
|
111
|
+
|
|
112
|
+
type CreateConfigOptions = {
|
|
113
|
+
extends?: string[];
|
|
114
|
+
tokens?: RegionalTokenWithValidity[];
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export async function createConfig(
|
|
118
|
+
config: string | RawConfig,
|
|
119
|
+
options?: CreateConfigOptions
|
|
120
|
+
): Promise<Config> {
|
|
121
|
+
return addConfigMetadata({
|
|
122
|
+
rawConfig: transformConfig(
|
|
123
|
+
typeof config === 'string' ? (parseYaml(config) as RawConfig) : config
|
|
124
|
+
),
|
|
125
|
+
...options,
|
|
126
|
+
});
|
|
127
|
+
}
|