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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/__tests__/bundle.test.ts +6 -6
  2. package/__tests__/fixtures/extension.js +1 -1
  3. package/__tests__/login.test.ts +2 -2
  4. package/__tests__/ref-utils.test.ts +1 -1
  5. package/__tests__/utils.ts +30 -18
  6. package/lib/benchmark/benches/recommended-oas3.bench.js +2 -3
  7. package/lib/benchmark/utils.d.ts +2 -1
  8. package/lib/benchmark/utils.js +10 -7
  9. package/lib/bundle.d.ts +2 -2
  10. package/lib/config/all.d.ts +2 -2
  11. package/lib/config/builtIn.d.ts +1 -1
  12. package/lib/config/config-resolvers.d.ts +16 -0
  13. package/lib/config/config-resolvers.js +213 -0
  14. package/lib/config/config.d.ts +14 -129
  15. package/lib/config/config.js +17 -234
  16. package/lib/config/index.d.ts +7 -0
  17. package/lib/config/index.js +19 -0
  18. package/lib/config/load.d.ts +2 -1
  19. package/lib/config/load.js +20 -13
  20. package/lib/config/minimal.d.ts +2 -2
  21. package/lib/config/recommended.d.ts +2 -2
  22. package/lib/config/types.d.ts +113 -0
  23. package/lib/config/types.js +2 -0
  24. package/lib/config/utils.d.ts +13 -0
  25. package/lib/config/utils.js +160 -0
  26. package/lib/format/format.d.ts +1 -1
  27. package/lib/format/format.js +28 -0
  28. package/lib/index.d.ts +1 -2
  29. package/lib/index.js +5 -6
  30. package/lib/lint.d.ts +1 -1
  31. package/lib/lint.js +5 -7
  32. package/lib/redocly/index.d.ts +1 -1
  33. package/lib/redocly/redocly-client-types.d.ts +1 -1
  34. package/lib/redocly/registry-api.d.ts +1 -1
  35. package/lib/resolve.d.ts +1 -1
  36. package/lib/resolve.js +1 -2
  37. package/lib/rules/common/assertions/utils.d.ts +1 -1
  38. package/lib/rules/common/assertions/utils.js +6 -2
  39. package/lib/utils.d.ts +4 -1
  40. package/lib/utils.js +18 -1
  41. package/package.json +5 -2
  42. package/src/__tests__/lint.test.ts +1 -1
  43. package/src/benchmark/benches/recommended-oas3.bench.ts +2 -3
  44. package/src/benchmark/utils.ts +13 -8
  45. package/src/bundle.ts +2 -1
  46. package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +140 -0
  47. package/src/config/__tests__/config-resolvers.test.ts +398 -0
  48. package/src/config/__tests__/config.test.ts +17 -29
  49. package/src/config/__tests__/fixtures/plugin.js +1 -1
  50. package/src/config/__tests__/fixtures/resolve-config/api/nested-config.yaml +7 -0
  51. package/src/config/__tests__/fixtures/resolve-config/api/plugin.js +67 -0
  52. package/src/config/__tests__/fixtures/resolve-config/local-config-with-circular.yaml +8 -0
  53. package/src/config/__tests__/fixtures/resolve-config/local-config-with-file.yaml +12 -0
  54. package/src/config/__tests__/fixtures/resolve-config/local-config.yaml +10 -0
  55. package/src/config/__tests__/fixtures/resolve-config/plugin.js +66 -0
  56. package/src/config/__tests__/fixtures/resolve-remote-configs/nested-remote-config.yaml +4 -0
  57. package/src/config/__tests__/fixtures/resolve-remote-configs/remote-config.yaml +5 -0
  58. package/src/config/__tests__/load.test.ts +8 -1
  59. package/src/config/all.ts +3 -2
  60. package/src/config/builtIn.ts +2 -1
  61. package/src/config/config-resolvers.ts +304 -0
  62. package/src/config/config.ts +40 -457
  63. package/src/config/index.ts +7 -0
  64. package/src/config/load.ts +37 -31
  65. package/src/config/minimal.ts +2 -2
  66. package/src/config/recommended.ts +2 -2
  67. package/src/config/types.ts +168 -0
  68. package/src/config/utils.ts +208 -0
  69. package/src/decorators/__tests__/remove-x-internal.test.ts +5 -5
  70. package/src/format/format.ts +36 -6
  71. package/src/index.ts +6 -2
  72. package/src/lint.ts +4 -5
  73. package/src/redocly/__tests__/redocly-client.test.ts +7 -0
  74. package/src/redocly/index.ts +3 -1
  75. package/src/redocly/redocly-client-types.ts +1 -1
  76. package/src/redocly/registry-api.ts +3 -1
  77. package/src/resolve.ts +2 -4
  78. package/src/rules/__tests__/no-unresolved-refs.test.ts +4 -4
  79. package/src/rules/common/__tests__/info-description.test.ts +3 -3
  80. package/src/rules/common/__tests__/info-license.test.ts +2 -2
  81. package/src/rules/common/__tests__/license-url.test.ts +2 -2
  82. package/src/rules/common/__tests__/no-ambiguous-paths.test.ts +1 -1
  83. package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +5 -5
  84. package/src/rules/common/__tests__/no-identical-paths.test.ts +1 -1
  85. package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +3 -3
  86. package/src/rules/common/__tests__/operation-2xx-response.test.ts +3 -3
  87. package/src/rules/common/__tests__/operation-4xx-response.test.ts +3 -3
  88. package/src/rules/common/__tests__/operation-operationId-unique.test.ts +2 -2
  89. package/src/rules/common/__tests__/operation-operationId-url-safe.test.ts +1 -1
  90. package/src/rules/common/__tests__/operation-parameters-unique.test.ts +4 -4
  91. package/src/rules/common/__tests__/operation-security-defined.test.ts +2 -2
  92. package/src/rules/common/__tests__/operation-singular-tag.test.ts +2 -2
  93. package/src/rules/common/__tests__/path-http-verbs-order.test.ts +2 -2
  94. package/src/rules/common/__tests__/path-not-include-query.test.ts +2 -2
  95. package/src/rules/common/__tests__/path-params-defined.test.ts +3 -3
  96. package/src/rules/common/__tests__/paths-kebab-case.test.ts +3 -3
  97. package/src/rules/common/__tests__/spec.test.ts +1 -1
  98. package/src/rules/common/__tests__/tag-description.test.ts +2 -2
  99. package/src/rules/common/__tests__/tags-alphabetical.test.ts +2 -2
  100. package/src/rules/common/assertions/utils.ts +5 -2
  101. package/src/rules/oas2/__tests__/boolean-parameter-prefixes.test.ts +3 -3
  102. package/src/rules/oas2/__tests__/spec/referenceableScalars.test.ts +1 -1
  103. package/src/rules/oas2/__tests__/spec/utils.ts +10 -7
  104. package/src/rules/oas3/__tests__/boolean-parameter-prefixes.test.ts +3 -3
  105. package/src/rules/oas3/__tests__/no-empty-enum-servers.com.test.ts +6 -6
  106. package/src/rules/oas3/__tests__/no-example-value-and-externalValue.test.ts +2 -2
  107. package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +8 -8
  108. package/src/rules/oas3/__tests__/no-server-example.com.test.ts +2 -2
  109. package/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts +3 -3
  110. package/src/rules/oas3/__tests__/no-unused-components.test.ts +1 -1
  111. package/src/rules/oas3/__tests__/spec/referenceableScalars.test.ts +23 -14
  112. package/src/rules/oas3/__tests__/spec/spec.test.ts +4 -4
  113. package/src/rules/oas3/__tests__/spec/utils.ts +10 -7
  114. package/src/utils.ts +18 -2
  115. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,113 @@
1
+ import type { ProblemSeverity } from '../walk';
2
+ import type { Oas3PreprocessorsSet, OasMajorVersion, Oas3DecoratorsSet, Oas2RuleSet, Oas2PreprocessorsSet, Oas2DecoratorsSet, Oas3RuleSet, OasVersion } from '../oas-types';
3
+ import type { NodeType } from '../types';
4
+ export declare type RuleConfig = ProblemSeverity | 'off' | ({
5
+ severity?: ProblemSeverity;
6
+ } & Record<string, any>);
7
+ export declare type PreprocessorConfig = ProblemSeverity | 'off' | 'on' | ({
8
+ severity?: ProblemSeverity;
9
+ } & Record<string, any>);
10
+ export declare type DecoratorConfig = PreprocessorConfig;
11
+ export declare type LintRawConfig = {
12
+ plugins?: (string | Plugin)[];
13
+ extends?: string[];
14
+ doNotResolveExamples?: boolean;
15
+ recommendedFallback?: boolean;
16
+ rules?: Record<string, RuleConfig>;
17
+ oas2Rules?: Record<string, RuleConfig>;
18
+ oas3_0Rules?: Record<string, RuleConfig>;
19
+ oas3_1Rules?: Record<string, RuleConfig>;
20
+ preprocessors?: Record<string, PreprocessorConfig>;
21
+ oas2Preprocessors?: Record<string, PreprocessorConfig>;
22
+ oas3_0Preprocessors?: Record<string, PreprocessorConfig>;
23
+ oas3_1Preprocessors?: Record<string, PreprocessorConfig>;
24
+ decorators?: Record<string, DecoratorConfig>;
25
+ oas2Decorators?: Record<string, DecoratorConfig>;
26
+ oas3_0Decorators?: Record<string, DecoratorConfig>;
27
+ oas3_1Decorators?: Record<string, DecoratorConfig>;
28
+ };
29
+ export declare type ResolvedLintConfig = PluginLintConfig & {
30
+ plugins?: Plugin[];
31
+ recommendedFallback?: boolean;
32
+ extends?: void | never;
33
+ extendPaths?: string[];
34
+ pluginPaths?: string[];
35
+ };
36
+ export declare type PreprocessorsConfig = {
37
+ oas3?: Oas3PreprocessorsSet;
38
+ oas2?: Oas2PreprocessorsSet;
39
+ };
40
+ export declare type DecoratorsConfig = {
41
+ oas3?: Oas3DecoratorsSet;
42
+ oas2?: Oas2DecoratorsSet;
43
+ };
44
+ export declare type TypesExtensionFn = (types: Record<string, NodeType>, oasVersion: OasVersion) => Record<string, NodeType>;
45
+ export declare type TypeExtensionsConfig = Partial<Record<OasMajorVersion, TypesExtensionFn>>;
46
+ export declare type CustomRulesConfig = {
47
+ oas3?: Oas3RuleSet;
48
+ oas2?: Oas2RuleSet;
49
+ };
50
+ export declare type Plugin = {
51
+ id: string;
52
+ configs?: Record<string, PluginLintConfig>;
53
+ rules?: CustomRulesConfig;
54
+ preprocessors?: PreprocessorsConfig;
55
+ decorators?: DecoratorsConfig;
56
+ typeExtension?: TypeExtensionsConfig;
57
+ };
58
+ export declare type PluginLintConfig = Omit<LintRawConfig, 'plugins' | 'extends'>;
59
+ export declare type ResolveHeader = {
60
+ name: string;
61
+ envVariable?: undefined;
62
+ value: string;
63
+ matches: string;
64
+ } | {
65
+ name: string;
66
+ value?: undefined;
67
+ envVariable: string;
68
+ matches: string;
69
+ };
70
+ export declare type RawResolveConfig = {
71
+ http?: Partial<HttpResolveConfig>;
72
+ };
73
+ export declare type HttpResolveConfig = {
74
+ headers: ResolveHeader[];
75
+ customFetch?: Function;
76
+ };
77
+ export declare type ResolveConfig = {
78
+ http: HttpResolveConfig;
79
+ };
80
+ export declare type Region = 'us' | 'eu';
81
+ export declare type AccessTokens = {
82
+ [region in Region]?: string;
83
+ };
84
+ export declare type DeprecatedRawConfig = {
85
+ apiDefinitions?: Record<string, string>;
86
+ lint?: LintRawConfig;
87
+ resolve?: RawResolveConfig;
88
+ region?: Region;
89
+ referenceDocs?: Record<string, any>;
90
+ };
91
+ export declare type Api = {
92
+ root: string;
93
+ lint?: Omit<LintRawConfig, 'plugins'>;
94
+ 'features.openapi'?: Record<string, any>;
95
+ 'features.mockServer'?: Record<string, any>;
96
+ };
97
+ export declare type ResolvedApi = Omit<Api, 'lint'> & {
98
+ lint: Omit<ResolvedLintConfig, 'plugins'>;
99
+ };
100
+ export declare type RawConfig = {
101
+ apis?: Record<string, Api>;
102
+ lint?: LintRawConfig;
103
+ resolve?: RawResolveConfig;
104
+ region?: Region;
105
+ 'features.openapi'?: Record<string, any>;
106
+ 'features.mockServer'?: Record<string, any>;
107
+ organization?: string;
108
+ };
109
+ export declare type ResolvedConfig = Omit<RawConfig, 'lint' | 'apis'> & {
110
+ lint: ResolvedLintConfig;
111
+ apis: Record<string, ResolvedApi>;
112
+ };
113
+ export declare type RulesFields = 'rules' | 'oas2Rules' | 'oas3_0Rules' | 'oas3_1Rules' | 'preprocessors' | 'oas2Preprocessors' | 'oas3_0Preprocessors' | 'oas3_1Preprocessors' | 'decorators' | 'oas2Decorators' | 'oas3_0Decorators' | 'oas3_1Decorators';
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,13 @@
1
+ import { Config } from './config';
2
+ import type { Api, DeprecatedRawConfig, Plugin, RawConfig, RawResolveConfig, ResolveConfig, ResolvedLintConfig, RulesFields } from './types';
3
+ export declare function parsePresetName(presetName: string): {
4
+ pluginId: string;
5
+ configName: string;
6
+ };
7
+ export declare function transformApiDefinitionsToApis(apiDefinitions?: Record<string, string>): Record<string, Api>;
8
+ export declare function prefixRules<T extends Record<string, any>>(rules: T, prefix: string): any;
9
+ export declare function mergeExtends(rulesConfList: ResolvedLintConfig[]): Omit<ResolvedLintConfig, RulesFields> & Required<Pick<ResolvedLintConfig, RulesFields>>;
10
+ export declare function getMergedConfig(config: Config, entrypointAlias?: string): Config;
11
+ export declare function transformConfig(rawConfig: DeprecatedRawConfig | RawConfig): RawConfig;
12
+ export declare function getResolveConfig(resolve?: RawResolveConfig): ResolveConfig;
13
+ export declare function getUniquePlugins(plugins: Plugin[]): Plugin[];
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.getUniquePlugins = exports.getResolveConfig = exports.transformConfig = exports.getMergedConfig = exports.mergeExtends = exports.prefixRules = exports.transformApiDefinitionsToApis = exports.parsePresetName = void 0;
15
+ const colorette_1 = require("colorette");
16
+ const utils_1 = require("../utils");
17
+ const config_1 = require("./config");
18
+ function parsePresetName(presetName) {
19
+ if (presetName.indexOf('/') > -1) {
20
+ const [pluginId, configName] = presetName.split('/');
21
+ return { pluginId, configName };
22
+ }
23
+ else {
24
+ return { pluginId: '', configName: presetName };
25
+ }
26
+ }
27
+ exports.parsePresetName = parsePresetName;
28
+ function transformApiDefinitionsToApis(apiDefinitions = {}) {
29
+ let apis = {};
30
+ for (const [apiName, apiPath] of Object.entries(apiDefinitions)) {
31
+ apis[apiName] = { root: apiPath };
32
+ }
33
+ return apis;
34
+ }
35
+ exports.transformApiDefinitionsToApis = transformApiDefinitionsToApis;
36
+ function prefixRules(rules, prefix) {
37
+ if (!prefix)
38
+ return rules;
39
+ const res = {};
40
+ for (const name of Object.keys(rules)) {
41
+ res[`${prefix}/${name}`] = rules[name];
42
+ }
43
+ return res;
44
+ }
45
+ exports.prefixRules = prefixRules;
46
+ function mergeExtends(rulesConfList) {
47
+ const result = {
48
+ rules: {},
49
+ oas2Rules: {},
50
+ oas3_0Rules: {},
51
+ oas3_1Rules: {},
52
+ preprocessors: {},
53
+ oas2Preprocessors: {},
54
+ oas3_0Preprocessors: {},
55
+ oas3_1Preprocessors: {},
56
+ decorators: {},
57
+ oas2Decorators: {},
58
+ oas3_0Decorators: {},
59
+ oas3_1Decorators: {},
60
+ plugins: [],
61
+ pluginPaths: [],
62
+ extendPaths: [],
63
+ };
64
+ for (let rulesConf of rulesConfList) {
65
+ if (rulesConf.extends) {
66
+ throw new Error(`\`extends\` is not supported in shared configs yet: ${JSON.stringify(rulesConf, null, 2)}.`);
67
+ }
68
+ Object.assign(result.rules, rulesConf.rules);
69
+ Object.assign(result.oas2Rules, rulesConf.oas2Rules);
70
+ utils_1.assignExisting(result.oas2Rules, rulesConf.rules || {});
71
+ Object.assign(result.oas3_0Rules, rulesConf.oas3_0Rules);
72
+ utils_1.assignExisting(result.oas3_0Rules, rulesConf.rules || {});
73
+ Object.assign(result.oas3_1Rules, rulesConf.oas3_1Rules);
74
+ utils_1.assignExisting(result.oas3_1Rules, rulesConf.rules || {});
75
+ Object.assign(result.preprocessors, rulesConf.preprocessors);
76
+ Object.assign(result.oas2Preprocessors, rulesConf.oas2Preprocessors);
77
+ utils_1.assignExisting(result.oas2Preprocessors, rulesConf.preprocessors || {});
78
+ Object.assign(result.oas3_0Preprocessors, rulesConf.oas3_0Preprocessors);
79
+ utils_1.assignExisting(result.oas3_0Preprocessors, rulesConf.preprocessors || {});
80
+ Object.assign(result.oas3_1Preprocessors, rulesConf.oas3_1Preprocessors);
81
+ utils_1.assignExisting(result.oas3_1Preprocessors, rulesConf.preprocessors || {});
82
+ Object.assign(result.decorators, rulesConf.decorators);
83
+ Object.assign(result.oas2Decorators, rulesConf.oas2Decorators);
84
+ utils_1.assignExisting(result.oas2Decorators, rulesConf.decorators || {});
85
+ Object.assign(result.oas3_0Decorators, rulesConf.oas3_0Decorators);
86
+ utils_1.assignExisting(result.oas3_0Decorators, rulesConf.decorators || {});
87
+ Object.assign(result.oas3_1Decorators, rulesConf.oas3_1Decorators);
88
+ utils_1.assignExisting(result.oas3_1Decorators, rulesConf.decorators || {});
89
+ result.plugins.push(...(rulesConf.plugins || []));
90
+ result.pluginPaths.push(...(rulesConf.pluginPaths || []));
91
+ result.extendPaths.push(...new Set(rulesConf.extendPaths));
92
+ }
93
+ return result;
94
+ }
95
+ exports.mergeExtends = mergeExtends;
96
+ function getMergedConfig(config, entrypointAlias) {
97
+ var _a, _b, _c, _d, _e, _f;
98
+ const extendPaths = [
99
+ ...Object.values(config.apis).map((api) => { var _a; return (_a = api === null || api === void 0 ? void 0 : api.lint) === null || _a === void 0 ? void 0 : _a.extendPaths; }),
100
+ (_b = (_a = config.rawConfig) === null || _a === void 0 ? void 0 : _a.lint) === null || _b === void 0 ? void 0 : _b.extendPaths,
101
+ ]
102
+ .flat()
103
+ .filter(Boolean);
104
+ const pluginPaths = [
105
+ ...Object.values(config.apis).map((api) => { var _a; return (_a = api === null || api === void 0 ? void 0 : api.lint) === null || _a === void 0 ? void 0 : _a.pluginPaths; }),
106
+ (_d = (_c = config.rawConfig) === null || _c === void 0 ? void 0 : _c.lint) === null || _d === void 0 ? void 0 : _d.pluginPaths,
107
+ ]
108
+ .flat()
109
+ .filter(Boolean);
110
+ return entrypointAlias
111
+ ? new config_1.Config(Object.assign(Object.assign({}, config.rawConfig), { lint: Object.assign(Object.assign({}, (config.apis[entrypointAlias]
112
+ ? config.apis[entrypointAlias].lint
113
+ : config.rawConfig.lint)), { extendPaths,
114
+ pluginPaths }), 'features.openapi': Object.assign(Object.assign({}, config['features.openapi']), (_e = config.apis[entrypointAlias]) === null || _e === void 0 ? void 0 : _e['features.openapi']), 'features.mockServer': Object.assign(Object.assign({}, config['features.mockServer']), (_f = config.apis[entrypointAlias]) === null || _f === void 0 ? void 0 : _f['features.mockServer']) }), config.configFile)
115
+ : config;
116
+ }
117
+ exports.getMergedConfig = getMergedConfig;
118
+ function transformConfig(rawConfig) {
119
+ if (rawConfig.apis && rawConfig.apiDefinitions) {
120
+ throw new Error("Do not use 'apiDefinitions' field. Use 'apis' instead.\n");
121
+ }
122
+ if (rawConfig['features.openapi'] &&
123
+ rawConfig.referenceDocs) {
124
+ throw new Error("Do not use 'referenceDocs' field. Use 'features.openapi' instead.\n");
125
+ }
126
+ const _a = rawConfig, { apiDefinitions, referenceDocs } = _a, rest = __rest(_a, ["apiDefinitions", "referenceDocs"]);
127
+ if (apiDefinitions) {
128
+ process.stderr.write(`The ${colorette_1.yellow('apiDefinitions')} field is deprecated. Use ${colorette_1.green('apis')} instead. Read more about this change: https://redocly.com/docs/api-registry/guides/migration-guide-config-file/#changed-properties\n`);
129
+ }
130
+ if (referenceDocs) {
131
+ process.stderr.write(`The ${colorette_1.yellow('referenceDocs')} field is deprecated. Use ${colorette_1.green('features.openapi')} instead. Read more about this change: https://redocly.com/docs/api-registry/guides/migration-guide-config-file/#changed-properties\n`);
132
+ }
133
+ return Object.assign({ 'features.openapi': referenceDocs, apis: transformApiDefinitionsToApis(apiDefinitions) }, rest);
134
+ }
135
+ exports.transformConfig = transformConfig;
136
+ function getResolveConfig(resolve) {
137
+ var _a, _b;
138
+ return {
139
+ http: {
140
+ headers: (_b = (_a = resolve === null || resolve === void 0 ? void 0 : resolve.http) === null || _a === void 0 ? void 0 : _a.headers) !== null && _b !== void 0 ? _b : [],
141
+ customFetch: undefined,
142
+ },
143
+ };
144
+ }
145
+ exports.getResolveConfig = getResolveConfig;
146
+ function getUniquePlugins(plugins) {
147
+ const seen = new Set();
148
+ const results = [];
149
+ for (const p of plugins) {
150
+ if (!seen.has(p.id)) {
151
+ results.push(p);
152
+ seen.add(p.id);
153
+ }
154
+ else if (p.id) {
155
+ process.stderr.write(`Duplicate plugin id "${colorette_1.yellow(p.id)}".\n`);
156
+ }
157
+ }
158
+ return results;
159
+ }
160
+ exports.getUniquePlugins = getUniquePlugins;
@@ -4,7 +4,7 @@ export declare type Totals = {
4
4
  warnings: number;
5
5
  ignored: number;
6
6
  };
7
- export declare type OutputFormat = 'codeframe' | 'stylish' | 'json' | 'checkstyle';
7
+ export declare type OutputFormat = 'codeframe' | 'stylish' | 'json' | 'checkstyle' | 'codeclimate';
8
8
  export declare function getTotals(problems: (NormalizedProblem & {
9
9
  ignored?: boolean;
10
10
  })[]): Totals;
@@ -20,6 +20,10 @@ const SEVERITY_NAMES = {
20
20
  warn: 'Warning',
21
21
  error: 'Error',
22
22
  };
23
+ const CODECLIMATE_SEVERITY_MAPPING = {
24
+ error: 'critical',
25
+ warn: 'minor',
26
+ };
23
27
  const MAX_SUGGEST = 5;
24
28
  function severityToNumber(severity) {
25
29
  return severity === 'error' ? 1 : 2;
@@ -90,10 +94,31 @@ function formatProblems(problems, opts) {
90
94
  process.stdout.write(`</checkstyle>\n`);
91
95
  break;
92
96
  }
97
+ case 'codeclimate':
98
+ outputForCodeClimate();
99
+ break;
93
100
  }
94
101
  if (totalProblems - ignoredProblems > maxProblems) {
95
102
  process.stderr.write(`< ... ${totalProblems - maxProblems} more problems hidden > ${colorette_1.gray('increase with `--max-problems N`')}\n`);
96
103
  }
104
+ function outputForCodeClimate() {
105
+ const issues = problems.map((p) => {
106
+ const location = p.location[0]; // TODO: support multiple location
107
+ const lineCol = codeframes_1.getLineColLocation(location);
108
+ return {
109
+ description: p.message,
110
+ location: {
111
+ path: path.relative(cwd, location.source.absoluteRef),
112
+ lines: {
113
+ begin: lineCol.start.line,
114
+ },
115
+ },
116
+ severity: CODECLIMATE_SEVERITY_MAPPING[p.severity],
117
+ fingerprint: `${p.ruleId}${p.location.length > 0 ? '-' + p.location[0].pointer : ''}`,
118
+ };
119
+ });
120
+ process.stdout.write(JSON.stringify(issues, null, 2));
121
+ }
97
122
  function outputJSON() {
98
123
  const resultObject = {
99
124
  totals,
@@ -140,6 +165,9 @@ function formatProblems(problems, opts) {
140
165
  }
141
166
  function formatStylish(problem, locationPad, ruleIdPad) {
142
167
  const color = COLORS[problem.severity];
168
+ if (!SEVERITY_NAMES[problem.severity]) {
169
+ return 'Error not found severity. Please check your config file. Allowed values: \`warn,error,off\`';
170
+ }
143
171
  const severityName = color(SEVERITY_NAMES[problem.severity].toLowerCase().padEnd(7));
144
172
  const { start } = problem.location[0];
145
173
  return ` ${`${start.line}:${start.col}`.padEnd(locationPad)} ${severityName} ${problem.ruleId.padEnd(ruleIdPad)} ${problem.message}`;
package/lib/index.d.ts CHANGED
@@ -8,8 +8,7 @@ export { Oas2Definition } from './typings/swagger';
8
8
  export { StatsAccumulator, StatsName } from './typings/common';
9
9
  export { normalizeTypes } from './types';
10
10
  export { Stats } from './rules/other/stats';
11
- export { Config, LintConfig, RawConfig, IGNORE_FILE, Region, getMergedConfig, transformConfig, } from './config/config';
12
- export { loadConfig, getConfig, findConfig, CONFIG_FILE_NAMES } from './config/load';
11
+ export { Config, LintConfig, RawConfig, IGNORE_FILE, Region, getMergedConfig, transformConfig, loadConfig, getConfig, findConfig, CONFIG_FILE_NAMES, } from './config';
13
12
  export { RedoclyClient, isRedoclyRegistryURL } from './redocly';
14
13
  export { Source, BaseResolver, Document, resolveDocument, ResolveError, YamlParseError, makeDocumentFromString, } from './resolve';
15
14
  export { parseYaml, stringifyYaml } from './js-yaml';
package/lib/index.js CHANGED
@@ -16,17 +16,16 @@ var types_1 = require("./types");
16
16
  Object.defineProperty(exports, "normalizeTypes", { enumerable: true, get: function () { return types_1.normalizeTypes; } });
17
17
  var stats_1 = require("./rules/other/stats");
18
18
  Object.defineProperty(exports, "Stats", { enumerable: true, get: function () { return stats_1.Stats; } });
19
- var config_1 = require("./config/config");
19
+ var config_1 = require("./config");
20
20
  Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return config_1.Config; } });
21
21
  Object.defineProperty(exports, "LintConfig", { enumerable: true, get: function () { return config_1.LintConfig; } });
22
22
  Object.defineProperty(exports, "IGNORE_FILE", { enumerable: true, get: function () { return config_1.IGNORE_FILE; } });
23
23
  Object.defineProperty(exports, "getMergedConfig", { enumerable: true, get: function () { return config_1.getMergedConfig; } });
24
24
  Object.defineProperty(exports, "transformConfig", { enumerable: true, get: function () { return config_1.transformConfig; } });
25
- var load_1 = require("./config/load");
26
- Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return load_1.loadConfig; } });
27
- Object.defineProperty(exports, "getConfig", { enumerable: true, get: function () { return load_1.getConfig; } });
28
- Object.defineProperty(exports, "findConfig", { enumerable: true, get: function () { return load_1.findConfig; } });
29
- Object.defineProperty(exports, "CONFIG_FILE_NAMES", { enumerable: true, get: function () { return load_1.CONFIG_FILE_NAMES; } });
25
+ Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return config_1.loadConfig; } });
26
+ Object.defineProperty(exports, "getConfig", { enumerable: true, get: function () { return config_1.getConfig; } });
27
+ Object.defineProperty(exports, "findConfig", { enumerable: true, get: function () { return config_1.findConfig; } });
28
+ Object.defineProperty(exports, "CONFIG_FILE_NAMES", { enumerable: true, get: function () { return config_1.CONFIG_FILE_NAMES; } });
30
29
  var redocly_1 = require("./redocly");
31
30
  Object.defineProperty(exports, "RedoclyClient", { enumerable: true, get: function () { return redocly_1.RedoclyClient; } });
32
31
  Object.defineProperty(exports, "isRedoclyRegistryURL", { enumerable: true, get: function () { return redocly_1.isRedoclyRegistryURL; } });
package/lib/lint.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { BaseResolver, Document } from './resolve';
2
2
  import { NodeType } from './types';
3
- import { LintConfig, Config } from './config/config';
3
+ import { LintConfig, Config } from './config';
4
4
  export declare function lint(opts: {
5
5
  ref: string;
6
6
  config: Config;
package/lib/lint.js CHANGED
@@ -16,14 +16,12 @@ const oas3_1_1 = require("./types/oas3_1");
16
16
  const oas3_1 = require("./types/oas3");
17
17
  const oas2_1 = require("./types/oas2");
18
18
  const walk_1 = require("./walk");
19
- const config_1 = require("./config/config");
19
+ const config_1 = require("./config");
20
20
  const types_1 = require("./types");
21
- const rules_1 = require("./config/rules");
22
21
  const ajv_1 = require("./rules/ajv");
23
22
  const oas_types_1 = require("./oas-types");
24
23
  const redocly_yaml_1 = require("./types/redocly-yaml");
25
24
  const spec_1 = require("./rules/common/spec");
26
- const builtIn_1 = require("./config/builtIn");
27
25
  function lint(opts) {
28
26
  return __awaiter(this, void 0, void 0, function* () {
29
27
  const { ref, externalRefResolver = new resolve_1.BaseResolver(opts.config.resolve) } = opts;
@@ -53,8 +51,8 @@ function lintDocument(opts) {
53
51
  oasVersion: oasVersion,
54
52
  visitorsData: {},
55
53
  };
56
- const preprocessors = rules_1.initRules(rules, config, 'preprocessors', oasVersion);
57
- const regularRules = rules_1.initRules(rules, config, 'rules', oasVersion);
54
+ const preprocessors = config_1.initRules(rules, config, 'preprocessors', oasVersion);
55
+ const regularRules = config_1.initRules(rules, config, 'rules', oasVersion);
58
56
  const normalizedVisitors = visitors_1.normalizeVisitors([...preprocessors, ...regularRules], types);
59
57
  const resolvedRefMap = yield resolve_1.resolveDocument({
60
58
  rootDocument: document,
@@ -80,9 +78,9 @@ function lintConfig(opts) {
80
78
  oasVersion: oas_types_1.OasVersion.Version3_0,
81
79
  visitorsData: {},
82
80
  };
81
+ const plugins = config_1.resolvePlugins([config_1.defaultPlugin]);
83
82
  const config = new config_1.LintConfig({
84
- plugins: [builtIn_1.defaultPlugin],
85
- extends: [],
83
+ plugins,
86
84
  rules: { spec: 'error' },
87
85
  });
88
86
  const types = types_1.normalizeTypes(redocly_yaml_1.ConfigTypes, config);
@@ -1,6 +1,6 @@
1
1
  import { RegistryApi } from './registry-api';
2
- import { AccessTokens, Region } from '../config/config';
3
2
  import { RegionalToken, RegionalTokenWithValidity } from './redocly-client-types';
3
+ import type { AccessTokens, Region } from '../config/types';
4
4
  export declare class RedoclyClient {
5
5
  private accessTokens;
6
6
  private region;
@@ -1,4 +1,4 @@
1
- import { Region } from '../config/config';
1
+ import type { Region } from '../config/types';
2
2
  export interface RegionalToken {
3
3
  region: Region;
4
4
  token: string;
@@ -1,5 +1,5 @@
1
1
  import { RegistryApiTypes } from './registry-api-types';
2
- import { AccessTokens, Region } from '../config/config';
2
+ import type { AccessTokens, Region } from '../config/types';
3
3
  export declare class RegistryApi {
4
4
  private accessTokens;
5
5
  private region;
package/lib/resolve.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { YAMLNode, LoadOptions } from 'yaml-ast-parser';
2
2
  import { NormalizedNodeType } from './types';
3
- import { ResolveConfig } from './config/config';
3
+ import { ResolveConfig } from './config/types';
4
4
  export declare type CollectedRefs = Map<string, Document>;
5
5
  export declare class Source {
6
6
  absoluteRef: string;
package/lib/resolve.js CHANGED
@@ -12,7 +12,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.resolveDocument = exports.BaseResolver = exports.makeDocumentFromString = exports.makeRefId = exports.YamlParseError = exports.ResolveError = exports.Source = void 0;
13
13
  const fs = require("fs");
14
14
  const path = require("path");
15
- const url = require("url");
16
15
  const ref_utils_1 = require("./ref-utils");
17
16
  const types_1 = require("./types");
18
17
  const utils_1 = require("./utils");
@@ -99,7 +98,7 @@ class BaseResolver {
99
98
  return ref;
100
99
  }
101
100
  if (base && ref_utils_1.isAbsoluteUrl(base)) {
102
- return url.resolve(base, ref);
101
+ return new URL(ref, base).href;
103
102
  }
104
103
  return path.resolve(base ? path.dirname(base) : process.cwd(), ref);
105
104
  }
@@ -15,6 +15,6 @@ export declare type AssertToApply = {
15
15
  runsOnValues: boolean;
16
16
  };
17
17
  export declare function buildVisitorObject(subject: string, context: Record<string, any>[], subjectVisitor: any): Record<string, any>;
18
- export declare function buildSubjectVisitor(properties: string | string[], asserts: AssertToApply[], context?: Record<string, any>[]): (node: any, { report, location, key, type }: UserContext) => void;
18
+ export declare function buildSubjectVisitor(properties: string | string[], asserts: AssertToApply[], context?: Record<string, any>[]): (node: any, { report, location, key, type, resolve }: UserContext) => void;
19
19
  export declare function getIntersectionLength(keys: string[], properties: string[]): number;
20
20
  export declare function isOrdered(value: any[], options: OrderOptions | OrderDirection): boolean;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isOrdered = exports.getIntersectionLength = exports.buildSubjectVisitor = exports.buildVisitorObject = void 0;
4
+ const ref_utils_1 = require("../../../ref-utils");
4
5
  const asserts_1 = require("./asserts");
5
6
  function buildVisitorObject(subject, context, subjectVisitor) {
6
7
  if (!context) {
@@ -44,7 +45,8 @@ function buildVisitorObject(subject, context, subjectVisitor) {
44
45
  }
45
46
  exports.buildVisitorObject = buildVisitorObject;
46
47
  function buildSubjectVisitor(properties, asserts, context) {
47
- return function (node, { report, location, key, type }) {
48
+ return function (node, { report, location, key, type, resolve }) {
49
+ var _a;
48
50
  // We need to check context's last node if it has the same type as subject node;
49
51
  // if yes - that means we didn't create context's last node visitor,
50
52
  // so we need to handle 'matchParentKeys' and 'excludeParentKeys' conditions here;
@@ -67,7 +69,9 @@ function buildSubjectVisitor(properties, asserts, context) {
67
69
  for (const assert of asserts) {
68
70
  if (properties) {
69
71
  for (const property of properties) {
70
- runAssertion(node[property], assert, location.child(property), report);
72
+ // we can have resolvable scalar so need to resolve value here.
73
+ const value = ref_utils_1.isRef(node[property]) ? (_a = resolve(node[property])) === null || _a === void 0 ? void 0 : _a.node : node[property];
74
+ runAssertion(value, assert, location.child(property), report);
71
75
  }
72
76
  }
73
77
  else {
package/lib/utils.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { HttpResolveConfig } from './config/config';
2
1
  import { UserContext } from './walk';
2
+ import type { HttpResolveConfig } from './config';
3
3
  export { parseYaml, stringifyYaml } from './js-yaml';
4
4
  export declare type StackFrame<T> = {
5
5
  prev: StackFrame<T> | null;
@@ -36,3 +36,6 @@ export declare function isPathParameter(pathSegment: string): boolean;
36
36
  */
37
37
  export declare function slash(path: string): string;
38
38
  export declare function isNotEmptyObject(obj: any): boolean;
39
+ export declare function isString(value: unknown): value is string;
40
+ export declare function isNotString<T>(value: string | T): value is T;
41
+ export declare function assignExisting<T>(target: Record<string, T>, obj: Record<string, T>): void;
package/lib/utils.js CHANGED
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.isNotEmptyObject = exports.slash = exports.isPathParameter = exports.readFileAsStringSync = exports.isSingular = exports.validateMimeTypeOAS3 = exports.validateMimeType = exports.splitCamelCaseIntoWords = exports.omitObjectProps = exports.pickObjectProps = exports.match = exports.readFileFromUrl = exports.isEmptyArray = exports.isEmptyObject = exports.isPlainObject = exports.notUndefined = exports.loadYaml = exports.popStack = exports.pushStack = exports.stringifyYaml = exports.parseYaml = void 0;
12
+ exports.assignExisting = exports.isNotString = exports.isString = exports.isNotEmptyObject = exports.slash = exports.isPathParameter = exports.readFileAsStringSync = exports.isSingular = exports.validateMimeTypeOAS3 = exports.validateMimeType = exports.splitCamelCaseIntoWords = exports.omitObjectProps = exports.pickObjectProps = exports.match = exports.readFileFromUrl = exports.isEmptyArray = exports.isEmptyObject = exports.isPlainObject = exports.notUndefined = exports.loadYaml = exports.popStack = exports.pushStack = exports.stringifyYaml = exports.parseYaml = void 0;
13
13
  const fs = require("fs");
14
14
  const minimatch = require("minimatch");
15
15
  const node_fetch_1 = require("node-fetch");
@@ -156,3 +156,20 @@ function isNotEmptyObject(obj) {
156
156
  return !!obj && Object.keys(obj).length > 0;
157
157
  }
158
158
  exports.isNotEmptyObject = isNotEmptyObject;
159
+ // TODO: use it everywhere
160
+ function isString(value) {
161
+ return typeof value === 'string';
162
+ }
163
+ exports.isString = isString;
164
+ function isNotString(value) {
165
+ return !isString(value);
166
+ }
167
+ exports.isNotString = isNotString;
168
+ function assignExisting(target, obj) {
169
+ for (let k of Object.keys(obj)) {
170
+ if (target.hasOwnProperty(k)) {
171
+ target[k] = obj[k];
172
+ }
173
+ }
174
+ }
175
+ exports.assignExisting = assignExisting;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/openapi-core",
3
- "version": "1.0.0-beta.94",
3
+ "version": "1.0.0-beta.95",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "engines": {
@@ -13,7 +13,10 @@
13
13
  "url": "https://github.com/Redocly/openapi-cli.git"
14
14
  },
15
15
  "browser": {
16
- "fs": false
16
+ "fs": false,
17
+ "path": "path-browserify",
18
+ "os": false,
19
+ "node-fetch": false
17
20
  },
18
21
  "homepage": "https://github.com/Redocly/openapi-cli",
19
22
  "keywords": [
@@ -174,7 +174,7 @@ describe('lint', () => {
174
174
  const results = await lintDocument({
175
175
  externalRefResolver: new BaseResolver(),
176
176
  document,
177
- config: makeConfig({ spec: 'error' }),
177
+ config: await makeConfig({ spec: 'error' }),
178
178
  });
179
179
 
180
180
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`Array []`);
@@ -1,10 +1,9 @@
1
1
  import { readFileSync } from 'fs';
2
2
  import { join as pathJoin, resolve as pathResolve } from 'path';
3
3
  import { lintDocument } from '../../lint';
4
- import { LintConfig } from '../../config/config';
4
+ import { LintConfig, defaultPlugin, resolvePreset } from '../../config';
5
5
  import { BaseResolver } from '../../resolve';
6
6
  import { parseYamlToDocument } from '../utils';
7
- import { defaultPlugin } from '../../config/builtIn';
8
7
 
9
8
  export const name = 'Validate with recommended rules';
10
9
  export const count = 10;
@@ -18,6 +17,6 @@ export function measureAsync() {
18
17
  return lintDocument({
19
18
  externalRefResolver: new BaseResolver(),
20
19
  document: rebillyDocument,
21
- config: new LintConfig({ plugins: [defaultPlugin] }),
20
+ config: new LintConfig(resolvePreset('recommended', [defaultPlugin])),
22
21
  });
23
22
  }