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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +1 -1
  2. package/__tests__/bundle.test.ts +6 -6
  3. package/__tests__/fixtures/extension.js +1 -1
  4. package/__tests__/login.test.ts +2 -2
  5. package/__tests__/ref-utils.test.ts +1 -1
  6. package/__tests__/utils.ts +30 -18
  7. package/lib/benchmark/benches/recommended-oas3.bench.js +2 -3
  8. package/lib/benchmark/utils.d.ts +2 -1
  9. package/lib/benchmark/utils.js +10 -7
  10. package/lib/bundle.d.ts +2 -2
  11. package/lib/config/all.d.ts +2 -2
  12. package/lib/config/builtIn.d.ts +1 -1
  13. package/lib/config/config-resolvers.d.ts +16 -0
  14. package/lib/config/config-resolvers.js +242 -0
  15. package/lib/config/config.d.ts +18 -130
  16. package/lib/config/config.js +34 -245
  17. package/lib/config/index.d.ts +7 -0
  18. package/lib/config/index.js +19 -0
  19. package/lib/config/load.d.ts +2 -1
  20. package/lib/config/load.js +20 -13
  21. package/lib/config/minimal.d.ts +2 -2
  22. package/lib/config/recommended.d.ts +2 -2
  23. package/lib/config/types.d.ts +113 -0
  24. package/lib/config/types.js +2 -0
  25. package/lib/config/utils.d.ts +13 -0
  26. package/lib/config/utils.js +160 -0
  27. package/lib/format/format.d.ts +1 -1
  28. package/lib/format/format.js +30 -1
  29. package/lib/index.d.ts +1 -2
  30. package/lib/index.js +5 -6
  31. package/lib/lint.d.ts +1 -1
  32. package/lib/lint.js +5 -7
  33. package/lib/redocly/index.d.ts +1 -1
  34. package/lib/redocly/index.js +10 -26
  35. package/lib/redocly/redocly-client-types.d.ts +1 -1
  36. package/lib/redocly/registry-api-types.d.ts +1 -0
  37. package/lib/redocly/registry-api.d.ts +2 -2
  38. package/lib/redocly/registry-api.js +2 -1
  39. package/lib/resolve.d.ts +1 -1
  40. package/lib/resolve.js +1 -2
  41. package/lib/rules/common/assertions/index.js +1 -1
  42. package/lib/rules/common/assertions/utils.d.ts +1 -1
  43. package/lib/rules/common/assertions/utils.js +6 -2
  44. package/lib/utils.d.ts +4 -2
  45. package/lib/utils.js +20 -3
  46. package/package.json +9 -6
  47. package/src/__tests__/lint.test.ts +1 -1
  48. package/src/benchmark/benches/recommended-oas3.bench.ts +2 -3
  49. package/src/benchmark/benchmark.js +1 -1
  50. package/src/benchmark/utils.ts +13 -8
  51. package/src/bundle.ts +2 -1
  52. package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +157 -0
  53. package/src/config/__tests__/config-resolvers.test.ts +429 -0
  54. package/src/config/__tests__/config.test.ts +17 -29
  55. package/src/config/__tests__/fixtures/plugin.js +1 -1
  56. package/src/config/__tests__/fixtures/resolve-config/api/nested-config.yaml +12 -0
  57. package/src/config/__tests__/fixtures/resolve-config/api/plugin.js +67 -0
  58. package/src/config/__tests__/fixtures/resolve-config/local-config-with-circular.yaml +8 -0
  59. package/src/config/__tests__/fixtures/resolve-config/local-config-with-file.yaml +19 -0
  60. package/src/config/__tests__/fixtures/resolve-config/local-config.yaml +10 -0
  61. package/src/config/__tests__/fixtures/resolve-config/plugin.js +66 -0
  62. package/src/config/__tests__/fixtures/resolve-remote-configs/nested-remote-config.yaml +4 -0
  63. package/src/config/__tests__/fixtures/resolve-remote-configs/remote-config.yaml +5 -0
  64. package/src/config/__tests__/load.test.ts +8 -1
  65. package/src/config/all.ts +3 -2
  66. package/src/config/builtIn.ts +2 -1
  67. package/src/config/config-resolvers.ts +359 -0
  68. package/src/config/config.ts +60 -468
  69. package/src/config/index.ts +7 -0
  70. package/src/config/load.ts +37 -31
  71. package/src/config/minimal.ts +2 -2
  72. package/src/config/recommended.ts +2 -2
  73. package/src/config/types.ts +168 -0
  74. package/src/config/utils.ts +208 -0
  75. package/src/decorators/__tests__/remove-x-internal.test.ts +5 -5
  76. package/src/format/format.ts +38 -7
  77. package/src/index.ts +6 -2
  78. package/src/lint.ts +4 -5
  79. package/src/redocly/__tests__/redocly-client.test.ts +7 -0
  80. package/src/redocly/index.ts +14 -41
  81. package/src/redocly/redocly-client-types.ts +1 -1
  82. package/src/redocly/registry-api-types.ts +1 -0
  83. package/src/redocly/registry-api.ts +5 -1
  84. package/src/resolve.ts +2 -4
  85. package/src/rules/__tests__/no-unresolved-refs.test.ts +4 -4
  86. package/src/rules/common/__tests__/info-description.test.ts +3 -3
  87. package/src/rules/common/__tests__/info-license.test.ts +2 -2
  88. package/src/rules/common/__tests__/license-url.test.ts +2 -2
  89. package/src/rules/common/__tests__/no-ambiguous-paths.test.ts +1 -1
  90. package/src/rules/common/__tests__/no-enum-type-mismatch.test.ts +5 -5
  91. package/src/rules/common/__tests__/no-identical-paths.test.ts +1 -1
  92. package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +3 -3
  93. package/src/rules/common/__tests__/operation-2xx-response.test.ts +3 -3
  94. package/src/rules/common/__tests__/operation-4xx-response.test.ts +3 -3
  95. package/src/rules/common/__tests__/operation-operationId-unique.test.ts +2 -2
  96. package/src/rules/common/__tests__/operation-operationId-url-safe.test.ts +1 -1
  97. package/src/rules/common/__tests__/operation-parameters-unique.test.ts +4 -4
  98. package/src/rules/common/__tests__/operation-security-defined.test.ts +2 -2
  99. package/src/rules/common/__tests__/operation-singular-tag.test.ts +2 -2
  100. package/src/rules/common/__tests__/path-http-verbs-order.test.ts +2 -2
  101. package/src/rules/common/__tests__/path-not-include-query.test.ts +2 -2
  102. package/src/rules/common/__tests__/path-params-defined.test.ts +3 -3
  103. package/src/rules/common/__tests__/paths-kebab-case.test.ts +3 -3
  104. package/src/rules/common/__tests__/spec.test.ts +1 -1
  105. package/src/rules/common/__tests__/tag-description.test.ts +2 -2
  106. package/src/rules/common/__tests__/tags-alphabetical.test.ts +2 -2
  107. package/src/rules/common/assertions/index.ts +1 -1
  108. package/src/rules/common/assertions/utils.ts +5 -2
  109. package/src/rules/oas2/__tests__/boolean-parameter-prefixes.test.ts +3 -3
  110. package/src/rules/oas2/__tests__/spec/referenceableScalars.test.ts +1 -1
  111. package/src/rules/oas2/__tests__/spec/utils.ts +10 -7
  112. package/src/rules/oas3/__tests__/boolean-parameter-prefixes.test.ts +3 -3
  113. package/src/rules/oas3/__tests__/no-empty-enum-servers.com.test.ts +6 -6
  114. package/src/rules/oas3/__tests__/no-example-value-and-externalValue.test.ts +2 -2
  115. package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +8 -8
  116. package/src/rules/oas3/__tests__/no-server-example.com.test.ts +2 -2
  117. package/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts +3 -3
  118. package/src/rules/oas3/__tests__/no-unused-components.test.ts +1 -1
  119. package/src/rules/oas3/__tests__/spec/referenceableScalars.test.ts +23 -14
  120. package/src/rules/oas3/__tests__/spec/spec.test.ts +4 -4
  121. package/src/rules/oas3/__tests__/spec/utils.ts +10 -7
  122. package/src/utils.ts +21 -4
  123. package/tsconfig.tsbuildinfo +1 -1
@@ -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;
@@ -5,6 +5,7 @@ const path = require("path");
5
5
  const colorette_1 = require("colorette");
6
6
  const coreVersion = require('../../package.json').version;
7
7
  const codeframes_1 = require("./codeframes");
8
+ const config_1 = require("../config");
8
9
  const ERROR_MESSAGE = {
9
10
  INVALID_SEVERITY_LEVEL: 'Invalid severity level; accepted values: error or warn',
10
11
  };
@@ -20,6 +21,10 @@ const SEVERITY_NAMES = {
20
21
  warn: 'Warning',
21
22
  error: 'Error',
22
23
  };
24
+ const CODECLIMATE_SEVERITY_MAPPING = {
25
+ error: 'critical',
26
+ warn: 'minor',
27
+ };
23
28
  const MAX_SUGGEST = 5;
24
29
  function severityToNumber(severity) {
25
30
  return severity === 'error' ? 1 : 2;
@@ -90,10 +95,31 @@ function formatProblems(problems, opts) {
90
95
  process.stdout.write(`</checkstyle>\n`);
91
96
  break;
92
97
  }
98
+ case 'codeclimate':
99
+ outputForCodeClimate();
100
+ break;
93
101
  }
94
102
  if (totalProblems - ignoredProblems > maxProblems) {
95
103
  process.stderr.write(`< ... ${totalProblems - maxProblems} more problems hidden > ${colorette_1.gray('increase with `--max-problems N`')}\n`);
96
104
  }
105
+ function outputForCodeClimate() {
106
+ const issues = problems.map((p) => {
107
+ const location = p.location[0]; // TODO: support multiple location
108
+ const lineCol = codeframes_1.getLineColLocation(location);
109
+ return {
110
+ description: p.message,
111
+ location: {
112
+ path: path.relative(cwd, location.source.absoluteRef),
113
+ lines: {
114
+ begin: lineCol.start.line,
115
+ },
116
+ },
117
+ severity: CODECLIMATE_SEVERITY_MAPPING[p.severity],
118
+ fingerprint: `${p.ruleId}${p.location.length > 0 ? '-' + p.location[0].pointer : ''}`,
119
+ };
120
+ });
121
+ process.stdout.write(JSON.stringify(issues, null, 2));
122
+ }
97
123
  function outputJSON() {
98
124
  const resultObject = {
99
125
  totals,
@@ -106,7 +132,7 @@ function formatProblems(problems, opts) {
106
132
  ? Object.assign(Object.assign({}, p.from), { source: {
107
133
  ref: path.relative(cwd, ((_a = p.from) === null || _a === void 0 ? void 0 : _a.source.absoluteRef) || cwd),
108
134
  } }) : undefined });
109
- if (process.env.FORMAT_JSON_WITH_CODEFRAMES) {
135
+ if (config_1.env.FORMAT_JSON_WITH_CODEFRAMES) {
110
136
  const location = p.location[0]; // TODO: support multiple locations
111
137
  const loc = codeframes_1.getLineColLocation(location);
112
138
  problem.codeframe = codeframes_1.getCodeframe(loc, color);
@@ -140,6 +166,9 @@ function formatProblems(problems, opts) {
140
166
  }
141
167
  function formatStylish(problem, locationPad, ruleIdPad) {
142
168
  const color = COLORS[problem.severity];
169
+ if (!SEVERITY_NAMES[problem.severity]) {
170
+ return 'Error not found severity. Please check your config file. Allowed values: \`warn,error,off\`';
171
+ }
143
172
  const severityName = color(SEVERITY_NAMES[problem.severity].toLowerCase().padEnd(7));
144
173
  const { start } = problem.location[0];
145
174
  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;
@@ -18,27 +18,21 @@ const registry_api_1 = require("./registry-api");
18
18
  const config_1 = require("../config/config");
19
19
  const utils_1 = require("../utils");
20
20
  const TOKEN_FILENAME = '.redocly-config.json';
21
- let REDOCLY_DOMAIN; // workaround for the isRedoclyRegistryURL, see more below
22
21
  class RedoclyClient {
23
22
  constructor(region) {
24
23
  this.accessTokens = {};
25
24
  this.region = this.loadRegion(region);
26
25
  this.loadTokens();
27
- this.domain = region ? config_1.DOMAINS[region] : process.env.REDOCLY_DOMAIN || config_1.DOMAINS[config_1.DEFAULT_REGION];
28
- /*
29
- * We can't use process.env here because it is replaced by a const in some client-side bundles,
30
- * which breaks assignment.
31
- */
32
- REDOCLY_DOMAIN = this.domain; // isRedoclyRegistryURL depends on the value to be set
26
+ this.domain = region ? config_1.DOMAINS[region] : config_1.env.REDOCLY_DOMAIN || config_1.DOMAINS[config_1.DEFAULT_REGION];
27
+ config_1.env.REDOCLY_DOMAIN = this.domain; // isRedoclyRegistryURL depends on the value to be set
33
28
  this.registryApi = new registry_api_1.RegistryApi(this.accessTokens, this.region);
34
29
  }
35
30
  loadRegion(region) {
36
31
  if (region && !config_1.DOMAINS[region]) {
37
- process.stdout.write(colorette_1.red(`Invalid argument: region in config file.\nGiven: ${colorette_1.green(region)}, choices: "us", "eu".\n`));
38
- process.exit(1);
32
+ throw new Error(`Invalid argument: region in config file.\nGiven: ${colorette_1.green(region)}, choices: "us", "eu".`);
39
33
  }
40
- if (process.env.REDOCLY_DOMAIN) {
41
- return (config_1.AVAILABLE_REGIONS.find((region) => config_1.DOMAINS[region] === process.env.REDOCLY_DOMAIN) || config_1.DEFAULT_REGION);
34
+ if (config_1.env.REDOCLY_DOMAIN) {
35
+ return (config_1.AVAILABLE_REGIONS.find((region) => config_1.DOMAINS[region] === config_1.env.REDOCLY_DOMAIN) || config_1.DEFAULT_REGION);
42
36
  }
43
37
  return region || config_1.DEFAULT_REGION;
44
38
  }
@@ -54,13 +48,7 @@ class RedoclyClient {
54
48
  }
55
49
  getAuthorizationHeader() {
56
50
  return __awaiter(this, void 0, void 0, function* () {
57
- const token = this.accessTokens[this.region];
58
- // print this only if there is token but invalid
59
- if (token && !this.isAuthorizedWithRedoclyByRegion()) {
60
- process.stderr.write(`${colorette_1.yellow('Warning:')} invalid Redocly API key. Use "npx @redocly/openapi-cli login" to provide your API key\n`);
61
- return undefined;
62
- }
63
- return token;
51
+ return this.accessTokens[this.region];
64
52
  });
65
53
  }
66
54
  // </backward compatibility: portal>
@@ -76,8 +64,8 @@ class RedoclyClient {
76
64
  [this.region]: credentials.token,
77
65
  })));
78
66
  }
79
- if (process.env.REDOCLY_AUTHORIZATION) {
80
- this.setAccessTokens(Object.assign(Object.assign({}, this.accessTokens), { [this.region]: process.env.REDOCLY_AUTHORIZATION }));
67
+ if (config_1.env.REDOCLY_AUTHORIZATION) {
68
+ this.setAccessTokens(Object.assign(Object.assign({}, this.accessTokens), { [this.region]: config_1.env.REDOCLY_AUTHORIZATION }));
81
69
  }
82
70
  }
83
71
  getAllTokens() {
@@ -133,19 +121,16 @@ class RedoclyClient {
133
121
  login(accessToken, verbose = false) {
134
122
  return __awaiter(this, void 0, void 0, function* () {
135
123
  const credentialsPath = path_1.resolve(os_1.homedir(), TOKEN_FILENAME);
136
- process.stdout.write(colorette_1.gray('\n Logging in...\n'));
137
124
  try {
138
125
  yield this.verifyToken(accessToken, this.region, verbose);
139
126
  }
140
127
  catch (err) {
141
- process.stdout.write(colorette_1.red('Authorization failed. Please check if you entered a valid API key.\n'));
142
- process.exit(1);
128
+ throw new Error('Authorization failed. Please check if you entered a valid API key.');
143
129
  }
144
130
  const credentials = Object.assign(Object.assign({}, this.readCredentialsFile(credentialsPath)), { [this.region]: accessToken, token: accessToken });
145
131
  this.accessTokens = credentials;
146
132
  this.registryApi.setAccessTokens(credentials);
147
133
  fs_1.writeFileSync(credentialsPath, JSON.stringify(credentials, null, 2));
148
- process.stdout.write(colorette_1.green(' Authorization confirmed. ✅\n\n'));
149
134
  });
150
135
  }
151
136
  logout() {
@@ -153,12 +138,11 @@ class RedoclyClient {
153
138
  if (fs_1.existsSync(credentialsPath)) {
154
139
  fs_1.unlinkSync(credentialsPath);
155
140
  }
156
- process.stdout.write('Logged out from the Redocly account. ✋\n');
157
141
  }
158
142
  }
159
143
  exports.RedoclyClient = RedoclyClient;
160
144
  function isRedoclyRegistryURL(link) {
161
- const domain = REDOCLY_DOMAIN || process.env.REDOCLY_DOMAIN || config_1.DOMAINS[config_1.DEFAULT_REGION];
145
+ const domain = config_1.env.REDOCLY_DOMAIN || config_1.DOMAINS[config_1.DEFAULT_REGION];
162
146
  const legacyDomain = domain === 'redocly.com' ? 'redoc.ly' : domain;
163
147
  if (!link.startsWith(`https://api.${domain}/registry/`) &&
164
148
  !link.startsWith(`https://api.${legacyDomain}/registry/`)) {
@@ -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;
@@ -14,6 +14,7 @@ export declare namespace RegistryApiTypes {
14
14
  filePaths: string[];
15
15
  branch?: string;
16
16
  isUpsert?: boolean;
17
+ isPublic?: boolean;
17
18
  }
18
19
  export interface PrepareFileuploadOKResponse {
19
20
  filePath: 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;
@@ -13,5 +13,5 @@ export declare class RegistryApi {
13
13
  organizations: string[];
14
14
  }>;
15
15
  prepareFileUpload({ organizationId, name, version, filesHash, filename, isUpsert, }: RegistryApiTypes.PrepareFileuploadParams): Promise<RegistryApiTypes.PrepareFileuploadOKResponse>;
16
- pushApi({ organizationId, name, version, rootFilePath, filePaths, branch, isUpsert, }: RegistryApiTypes.PushApiParams): Promise<void>;
16
+ pushApi({ organizationId, name, version, rootFilePath, filePaths, branch, isUpsert, isPublic, }: RegistryApiTypes.PushApiParams): Promise<void>;
17
17
  }
@@ -80,7 +80,7 @@ class RegistryApi {
80
80
  throw new Error('Could not prepare file upload');
81
81
  });
82
82
  }
83
- pushApi({ organizationId, name, version, rootFilePath, filePaths, branch, isUpsert, }) {
83
+ pushApi({ organizationId, name, version, rootFilePath, filePaths, branch, isUpsert, isPublic, }) {
84
84
  return __awaiter(this, void 0, void 0, function* () {
85
85
  const response = yield this.request(`/${organizationId}/${name}/${version}`, {
86
86
  method: 'PUT',
@@ -93,6 +93,7 @@ class RegistryApi {
93
93
  filePaths,
94
94
  branch,
95
95
  isUpsert,
96
+ isPublic,
96
97
  }),
97
98
  }, this.region);
98
99
  if (response.ok) {
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
  }
@@ -7,7 +7,7 @@ const Assertions = (opts) => {
7
7
  let visitors = [];
8
8
  // As 'Assertions' has an array of asserts,
9
9
  // that array spreads into an 'opts' object on init rules phase here
10
- // https://github.com/Redocly/openapi-cli/blob/master/packages/core/src/config/config.ts#L311
10
+ // https://github.com/Redocly/redocly-cli/blob/master/packages/core/src/config/config.ts#L311
11
11
  // that is why we need to iterate through 'opts' values;
12
12
  // before - filter only object 'opts' values
13
13
  const assertions = Object.values(opts).filter((opt) => typeof opt === 'object' && opt !== null);