@redocly/cli 1.10.5 → 1.11.0
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/CHANGELOG.md +20 -0
- package/lib/__tests__/commands/bundle.test.js +3 -32
- package/lib/__tests__/commands/join.test.js +0 -11
- package/lib/commands/bundle.d.ts +1 -4
- package/lib/commands/bundle.js +2 -32
- package/lib/commands/join.d.ts +0 -3
- package/lib/commands/join.js +13 -36
- package/lib/commands/lint.js +3 -1
- package/lib/index.js +73 -26
- package/lib/types.d.ts +5 -1
- package/lib/utils/getCommandNameFromArgs.d.ts +2 -0
- package/lib/utils/getCommandNameFromArgs.js +8 -0
- package/lib/utils/miscellaneous.d.ts +1 -1
- package/lib/utils/miscellaneous.js +4 -1
- package/lib/wrapper.d.ts +1 -1
- package/lib/wrapper.js +3 -1
- package/package.json +2 -2
- package/src/__tests__/commands/bundle.test.ts +4 -37
- package/src/__tests__/commands/join.test.ts +0 -17
- package/src/commands/bundle.ts +3 -53
- package/src/commands/join.ts +13 -49
- package/src/commands/lint.ts +5 -1
- package/src/index.ts +96 -26
- package/src/types.ts +6 -0
- package/src/utils/getCommandNameFromArgs.ts +5 -0
- package/src/utils/miscellaneous.ts +3 -1
- package/src/wrapper.ts +4 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { bundle, getTotals, getMergedConfig } from '@redocly/openapi-core';
|
|
2
2
|
|
|
3
3
|
import { BundleOptions, handleBundle } from '../../commands/bundle';
|
|
4
4
|
import { handleError } from '../../utils/miscellaneous';
|
|
@@ -25,21 +25,18 @@ describe('bundle', () => {
|
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
afterEach(() => {
|
|
28
|
-
(lint as jest.Mock).mockClear();
|
|
29
28
|
(bundle as jest.Mock).mockClear();
|
|
30
29
|
(getTotals as jest.Mock).mockReset();
|
|
31
30
|
});
|
|
32
31
|
|
|
33
|
-
it('bundles definitions
|
|
32
|
+
it('bundles definitions', async () => {
|
|
34
33
|
const apis = ['foo.yaml', 'bar.yaml'];
|
|
35
34
|
|
|
36
35
|
await commandWrapper(handleBundle)({
|
|
37
36
|
apis,
|
|
38
37
|
ext: 'yaml',
|
|
39
|
-
format: 'codeframe',
|
|
40
38
|
} as Arguments<BundleOptions>);
|
|
41
39
|
|
|
42
|
-
expect(lint).toBeCalledTimes(0);
|
|
43
40
|
expect(bundle).toBeCalledTimes(apis.length);
|
|
44
41
|
});
|
|
45
42
|
|
|
@@ -49,48 +46,25 @@ describe('bundle', () => {
|
|
|
49
46
|
await commandWrapper(handleBundle)({
|
|
50
47
|
apis,
|
|
51
48
|
ext: 'yaml',
|
|
52
|
-
format: 'codeframe',
|
|
53
49
|
} as Arguments<BundleOptions>);
|
|
54
50
|
|
|
55
51
|
await exitCb?.();
|
|
56
52
|
expect(processExitMock).toHaveBeenCalledWith(0);
|
|
57
53
|
});
|
|
58
54
|
|
|
59
|
-
it('bundles definitions w/
|
|
60
|
-
const apis = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
|
|
61
|
-
|
|
62
|
-
(getTotals as jest.Mock).mockReturnValue({
|
|
63
|
-
errors: 0,
|
|
64
|
-
warnings: 0,
|
|
65
|
-
ignored: 0,
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
await commandWrapper(handleBundle)({
|
|
69
|
-
apis,
|
|
70
|
-
ext: 'yaml',
|
|
71
|
-
format: 'codeframe',
|
|
72
|
-
lint: true,
|
|
73
|
-
} as Arguments<BundleOptions>);
|
|
74
|
-
|
|
75
|
-
expect(lint).toBeCalledTimes(apis.length);
|
|
76
|
-
expect(bundle).toBeCalledTimes(apis.length);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('exits with code 0 when bundles definitions w/linting w/o errors', async () => {
|
|
55
|
+
it('exits with code 0 when bundles definitions w/o errors', async () => {
|
|
80
56
|
const apis = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
|
|
81
57
|
|
|
82
58
|
await commandWrapper(handleBundle)({
|
|
83
59
|
apis,
|
|
84
60
|
ext: 'yaml',
|
|
85
|
-
format: 'codeframe',
|
|
86
|
-
lint: true,
|
|
87
61
|
} as Arguments<BundleOptions>);
|
|
88
62
|
|
|
89
63
|
await exitCb?.();
|
|
90
64
|
expect(processExitMock).toHaveBeenCalledWith(0);
|
|
91
65
|
});
|
|
92
66
|
|
|
93
|
-
it('exits with code 1 when bundles definitions w/
|
|
67
|
+
it('exits with code 1 when bundles definitions w/errors', async () => {
|
|
94
68
|
const apis = ['foo.yaml'];
|
|
95
69
|
|
|
96
70
|
(getTotals as jest.Mock).mockReturnValue({
|
|
@@ -102,11 +76,8 @@ describe('bundle', () => {
|
|
|
102
76
|
await commandWrapper(handleBundle)({
|
|
103
77
|
apis,
|
|
104
78
|
ext: 'yaml',
|
|
105
|
-
format: 'codeframe',
|
|
106
|
-
lint: true,
|
|
107
79
|
} as Arguments<BundleOptions>);
|
|
108
80
|
|
|
109
|
-
expect(lint).toBeCalledTimes(apis.length);
|
|
110
81
|
await exitCb?.();
|
|
111
82
|
expect(processExitMock).toHaveBeenCalledWith(1);
|
|
112
83
|
});
|
|
@@ -121,8 +92,6 @@ describe('bundle', () => {
|
|
|
121
92
|
await commandWrapper(handleBundle)({
|
|
122
93
|
apis,
|
|
123
94
|
ext: 'json',
|
|
124
|
-
format: 'codeframe',
|
|
125
|
-
lint: false,
|
|
126
95
|
} as Arguments<BundleOptions>);
|
|
127
96
|
|
|
128
97
|
expect(handleError).toHaveBeenCalledTimes(1);
|
|
@@ -141,8 +110,6 @@ describe('bundle', () => {
|
|
|
141
110
|
await commandWrapper(handleBundle)({
|
|
142
111
|
apis,
|
|
143
112
|
ext: 'yaml',
|
|
144
|
-
format: 'codeframe',
|
|
145
|
-
lint: false,
|
|
146
113
|
} as Arguments<BundleOptions>);
|
|
147
114
|
|
|
148
115
|
expect(handleError).toHaveBeenCalledTimes(0);
|
|
@@ -165,23 +165,6 @@ describe('handleJoin', () => {
|
|
|
165
165
|
expect(config.styleguide.skipPreprocessors).toHaveBeenCalled();
|
|
166
166
|
});
|
|
167
167
|
|
|
168
|
-
it('should not call skipDecorators and skipPreprocessors', async () => {
|
|
169
|
-
(detectSpec as jest.Mock).mockReturnValue('oas3_0');
|
|
170
|
-
await handleJoin(
|
|
171
|
-
{
|
|
172
|
-
apis: ['first.yaml', 'second.yaml'],
|
|
173
|
-
decorate: true,
|
|
174
|
-
preprocess: true,
|
|
175
|
-
},
|
|
176
|
-
ConfigFixture as any,
|
|
177
|
-
'cli-version'
|
|
178
|
-
);
|
|
179
|
-
|
|
180
|
-
const config = loadConfig();
|
|
181
|
-
expect(config.styleguide.skipDecorators).not.toHaveBeenCalled();
|
|
182
|
-
expect(config.styleguide.skipPreprocessors).not.toHaveBeenCalled();
|
|
183
|
-
});
|
|
184
|
-
|
|
185
168
|
it('should handle join with prefix-components-with-info-prop and null values', async () => {
|
|
186
169
|
(detectSpec as jest.Mock).mockReturnValue('oas3_0');
|
|
187
170
|
|
package/src/commands/bundle.ts
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
formatProblems,
|
|
3
|
-
getTotals,
|
|
4
|
-
getMergedConfig,
|
|
5
|
-
lint,
|
|
6
|
-
bundle,
|
|
7
|
-
Config,
|
|
8
|
-
OutputFormat,
|
|
9
|
-
} from '@redocly/openapi-core';
|
|
1
|
+
import { formatProblems, getTotals, getMergedConfig, bundle, Config } from '@redocly/openapi-core';
|
|
10
2
|
import {
|
|
11
3
|
dumpBundle,
|
|
12
4
|
getExecutionTime,
|
|
@@ -15,8 +7,6 @@ import {
|
|
|
15
7
|
handleError,
|
|
16
8
|
printUnusedWarnings,
|
|
17
9
|
saveBundle,
|
|
18
|
-
printLintTotals,
|
|
19
|
-
checkIfRulesetExist,
|
|
20
10
|
sortTopLevelKeysForOas,
|
|
21
11
|
} from '../utils/miscellaneous';
|
|
22
12
|
import type { OutputExtensions, Skips, Totals } from '../types';
|
|
@@ -27,15 +17,12 @@ import { checkForDeprecatedOptions } from '../utils/miscellaneous';
|
|
|
27
17
|
|
|
28
18
|
export type BundleOptions = {
|
|
29
19
|
apis?: string[];
|
|
30
|
-
'max-problems'?: number;
|
|
31
20
|
extends?: string[];
|
|
32
21
|
config?: string;
|
|
33
|
-
format?: OutputFormat;
|
|
34
22
|
output?: string;
|
|
35
23
|
ext: OutputExtensions;
|
|
36
24
|
dereferenced?: boolean;
|
|
37
25
|
force?: boolean;
|
|
38
|
-
lint?: boolean;
|
|
39
26
|
metafile?: string;
|
|
40
27
|
'remove-unused-components'?: boolean;
|
|
41
28
|
'keep-url-references'?: boolean;
|
|
@@ -47,14 +34,7 @@ export async function handleBundle(argv: BundleOptions, config: Config, version:
|
|
|
47
34
|
config.rawConfig?.styleguide?.decorators?.hasOwnProperty('remove-unused-components');
|
|
48
35
|
const apis = await getFallbackApisOrExit(argv.apis, config);
|
|
49
36
|
const totals: Totals = { errors: 0, warnings: 0, ignored: 0 };
|
|
50
|
-
const
|
|
51
|
-
const deprecatedOptions: Array<keyof BundleOptions> = [
|
|
52
|
-
'lint',
|
|
53
|
-
'format',
|
|
54
|
-
'skip-rule',
|
|
55
|
-
'extends',
|
|
56
|
-
'max-problems',
|
|
57
|
-
];
|
|
37
|
+
const deprecatedOptions: Array<keyof BundleOptions> = [];
|
|
58
38
|
|
|
59
39
|
checkForDeprecatedOptions(argv, deprecatedOptions);
|
|
60
40
|
|
|
@@ -64,38 +44,9 @@ export async function handleBundle(argv: BundleOptions, config: Config, version:
|
|
|
64
44
|
const resolvedConfig = getMergedConfig(config, alias);
|
|
65
45
|
const { styleguide } = resolvedConfig;
|
|
66
46
|
|
|
67
|
-
styleguide.skipRules(argv['skip-rule']);
|
|
68
47
|
styleguide.skipPreprocessors(argv['skip-preprocessor']);
|
|
69
48
|
styleguide.skipDecorators(argv['skip-decorator']);
|
|
70
49
|
|
|
71
|
-
if (argv.lint) {
|
|
72
|
-
checkIfRulesetExist(styleguide.rules);
|
|
73
|
-
if (config.styleguide.recommendedFallback) {
|
|
74
|
-
process.stderr.write(
|
|
75
|
-
`No configurations were provided -- using built in ${blue(
|
|
76
|
-
'recommended'
|
|
77
|
-
)} configuration by default.\n\n`
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
const results = await lint({
|
|
81
|
-
ref: path,
|
|
82
|
-
config: resolvedConfig,
|
|
83
|
-
});
|
|
84
|
-
const fileLintTotals = getTotals(results);
|
|
85
|
-
|
|
86
|
-
totals.errors += fileLintTotals.errors;
|
|
87
|
-
totals.warnings += fileLintTotals.warnings;
|
|
88
|
-
totals.ignored += fileLintTotals.ignored;
|
|
89
|
-
|
|
90
|
-
formatProblems(results, {
|
|
91
|
-
format: argv.format || 'codeframe',
|
|
92
|
-
totals: fileLintTotals,
|
|
93
|
-
version,
|
|
94
|
-
maxProblems: maxProblems,
|
|
95
|
-
});
|
|
96
|
-
printLintTotals(fileLintTotals, 2);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
50
|
process.stderr.write(gray(`bundling ${path}...\n`));
|
|
100
51
|
|
|
101
52
|
const {
|
|
@@ -132,8 +83,7 @@ export async function handleBundle(argv: BundleOptions, config: Config, version:
|
|
|
132
83
|
totals.ignored += fileTotals.ignored;
|
|
133
84
|
|
|
134
85
|
formatProblems(problems, {
|
|
135
|
-
format:
|
|
136
|
-
maxProblems: maxProblems,
|
|
86
|
+
format: 'codeframe',
|
|
137
87
|
totals: fileTotals,
|
|
138
88
|
version,
|
|
139
89
|
});
|
package/src/commands/join.ts
CHANGED
|
@@ -6,10 +6,8 @@ import {
|
|
|
6
6
|
Config,
|
|
7
7
|
SpecVersion,
|
|
8
8
|
BaseResolver,
|
|
9
|
-
StyleguideConfig,
|
|
10
9
|
formatProblems,
|
|
11
10
|
getTotals,
|
|
12
|
-
lintDocument,
|
|
13
11
|
detectSpec,
|
|
14
12
|
bundleDocument,
|
|
15
13
|
isRef,
|
|
@@ -17,13 +15,10 @@ import {
|
|
|
17
15
|
import {
|
|
18
16
|
getFallbackApisOrExit,
|
|
19
17
|
printExecutionTime,
|
|
20
|
-
handleError,
|
|
21
|
-
printLintTotals,
|
|
22
18
|
exitWithError,
|
|
23
19
|
sortTopLevelKeysForOas,
|
|
24
20
|
getAndValidateFileExtension,
|
|
25
21
|
writeToFileByExtension,
|
|
26
|
-
checkForDeprecatedOptions,
|
|
27
22
|
} from '../utils/miscellaneous';
|
|
28
23
|
import { isObject, isString, keysOf } from '../utils/js-utils';
|
|
29
24
|
import { COMPONENTS, OPENAPI3_METHOD } from './split/types';
|
|
@@ -60,9 +55,6 @@ type JoinDocumentContext = {
|
|
|
60
55
|
|
|
61
56
|
export type JoinOptions = {
|
|
62
57
|
apis: string[];
|
|
63
|
-
lint?: boolean;
|
|
64
|
-
decorate?: boolean;
|
|
65
|
-
preprocess?: boolean;
|
|
66
58
|
'prefix-tags-with-info-prop'?: string;
|
|
67
59
|
'prefix-tags-with-filename'?: boolean;
|
|
68
60
|
'prefix-components-with-info-prop'?: string;
|
|
@@ -79,8 +71,6 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
79
71
|
return exitWithError(`At least 2 apis should be provided. \n\n`);
|
|
80
72
|
}
|
|
81
73
|
|
|
82
|
-
checkForDeprecatedOptions(argv, ['lint'] as Array<keyof JoinOptions>);
|
|
83
|
-
|
|
84
74
|
const fileExtension = getAndValidateFileExtension(argv.output || argv.apis[0]);
|
|
85
75
|
|
|
86
76
|
const {
|
|
@@ -111,23 +101,19 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
111
101
|
)
|
|
112
102
|
);
|
|
113
103
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
config.styleguide.skipDecorators(Array.from(decorators));
|
|
121
|
-
}
|
|
104
|
+
const decorators = new Set([
|
|
105
|
+
...Object.keys(config.styleguide.decorators.oas3_0),
|
|
106
|
+
...Object.keys(config.styleguide.decorators.oas3_1),
|
|
107
|
+
...Object.keys(config.styleguide.decorators.oas2),
|
|
108
|
+
]);
|
|
109
|
+
config.styleguide.skipDecorators(Array.from(decorators));
|
|
122
110
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
config.styleguide.skipPreprocessors(Array.from(preprocessors));
|
|
130
|
-
}
|
|
111
|
+
const preprocessors = new Set([
|
|
112
|
+
...Object.keys(config.styleguide.preprocessors.oas3_0),
|
|
113
|
+
...Object.keys(config.styleguide.preprocessors.oas3_1),
|
|
114
|
+
...Object.keys(config.styleguide.preprocessors.oas2),
|
|
115
|
+
]);
|
|
116
|
+
config.styleguide.skipPreprocessors(Array.from(preprocessors));
|
|
131
117
|
|
|
132
118
|
const bundleResults = await Promise.all(
|
|
133
119
|
documents.map((document) =>
|
|
@@ -146,7 +132,7 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
146
132
|
if (fileTotals.errors) {
|
|
147
133
|
formatProblems(problems, {
|
|
148
134
|
totals: fileTotals,
|
|
149
|
-
version:
|
|
135
|
+
version: packageVersion,
|
|
150
136
|
});
|
|
151
137
|
exitWithError(
|
|
152
138
|
`❌ Errors encountered while bundling ${blue(
|
|
@@ -179,12 +165,6 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
179
165
|
}
|
|
180
166
|
}
|
|
181
167
|
|
|
182
|
-
if (argv.lint) {
|
|
183
|
-
for (const document of documents) {
|
|
184
|
-
await validateApi(document, config.styleguide, externalRefResolver, packageVersion);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
168
|
const joinedDef: any = {};
|
|
189
169
|
const potentialConflicts = {
|
|
190
170
|
tags: {},
|
|
@@ -787,22 +767,6 @@ function getInfoPrefix(info: any, prefixArg: string | undefined, type: string) {
|
|
|
787
767
|
return info[prefixArg].replaceAll(/\s/g, '_');
|
|
788
768
|
}
|
|
789
769
|
|
|
790
|
-
async function validateApi(
|
|
791
|
-
document: Document,
|
|
792
|
-
config: StyleguideConfig,
|
|
793
|
-
externalRefResolver: BaseResolver,
|
|
794
|
-
packageVersion: string
|
|
795
|
-
) {
|
|
796
|
-
try {
|
|
797
|
-
const results = await lintDocument({ document, config, externalRefResolver });
|
|
798
|
-
const fileTotals = getTotals(results);
|
|
799
|
-
formatProblems(results, { format: 'stylish', totals: fileTotals, version: packageVersion });
|
|
800
|
-
printLintTotals(fileTotals, 2);
|
|
801
|
-
} catch (err) {
|
|
802
|
-
handleError(err, document.parsed);
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
|
|
806
770
|
function replace$Refs(obj: unknown, componentsPrefix: string) {
|
|
807
771
|
crawl(obj, (node: Record<string, unknown>) => {
|
|
808
772
|
if (node.$ref && typeof node.$ref === 'string' && startsWithComponents(node.$ref)) {
|
package/src/commands/lint.ts
CHANGED
|
@@ -24,6 +24,8 @@ import { performance } from 'perf_hooks';
|
|
|
24
24
|
import type { OutputFormat, ProblemSeverity, Document, RuleSeverity } from '@redocly/openapi-core';
|
|
25
25
|
import type { ResolvedRefMap } from '@redocly/openapi-core/lib/resolve';
|
|
26
26
|
import type { CommandOptions, Skips, Totals } from '../types';
|
|
27
|
+
import { getCommandNameFromArgs } from '../utils/getCommandNameFromArgs';
|
|
28
|
+
import { Arguments } from 'yargs';
|
|
27
29
|
|
|
28
30
|
export type LintOptions = {
|
|
29
31
|
apis?: string[];
|
|
@@ -144,7 +146,9 @@ export function lintConfigCallback(
|
|
|
144
146
|
version,
|
|
145
147
|
});
|
|
146
148
|
|
|
147
|
-
|
|
149
|
+
const command = argv ? getCommandNameFromArgs(argv as unknown as Arguments) : undefined;
|
|
150
|
+
|
|
151
|
+
printConfigLintTotals(fileTotals, command);
|
|
148
152
|
|
|
149
153
|
if (fileTotals.errors > 0) {
|
|
150
154
|
throw new ConfigValidationError();
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import './utils/assert-node-version';
|
|
4
4
|
import * as yargs from 'yargs';
|
|
5
|
+
import * as colors from 'colorette';
|
|
5
6
|
import { outputExtensions, PushArguments, regionChoices } from './types';
|
|
6
7
|
import { RedoclyClient } from '@redocly/openapi-core';
|
|
7
8
|
import { previewDocs } from './commands/preview-docs';
|
|
@@ -104,9 +105,6 @@ yargs
|
|
|
104
105
|
demandOption: true,
|
|
105
106
|
})
|
|
106
107
|
.option({
|
|
107
|
-
lint: { description: 'Lint descriptions', type: 'boolean', default: false, hidden: true },
|
|
108
|
-
decorate: { description: 'Run decorators', type: 'boolean', default: false },
|
|
109
|
-
preprocess: { description: 'Run preprocessors', type: 'boolean', default: false },
|
|
110
108
|
'prefix-tags-with-info-prop': {
|
|
111
109
|
description: 'Prefix tags with property value from info object.',
|
|
112
110
|
requiresArg: true,
|
|
@@ -141,8 +139,47 @@ yargs
|
|
|
141
139
|
choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
|
|
142
140
|
default: 'warn' as RuleSeverity,
|
|
143
141
|
},
|
|
142
|
+
lint: {
|
|
143
|
+
hidden: true,
|
|
144
|
+
deprecated: true,
|
|
145
|
+
},
|
|
146
|
+
decorate: {
|
|
147
|
+
hidden: true,
|
|
148
|
+
deprecated: true,
|
|
149
|
+
},
|
|
150
|
+
preprocess: {
|
|
151
|
+
hidden: true,
|
|
152
|
+
deprecated: true,
|
|
153
|
+
},
|
|
144
154
|
}),
|
|
145
155
|
(argv) => {
|
|
156
|
+
const DEPRECATED_OPTIONS = ['lint', 'preprocess', 'decorate'];
|
|
157
|
+
const DECORATORS_DOCUMENTATION_LINK = 'https://redocly.com/docs/cli/decorators/#decorators';
|
|
158
|
+
const JOIN_COMMAND_DOCUMENTATION_LINK = 'https://redocly.com/docs/cli/commands/join/#join';
|
|
159
|
+
|
|
160
|
+
DEPRECATED_OPTIONS.forEach((option) => {
|
|
161
|
+
if (argv[option]) {
|
|
162
|
+
process.stdout.write(
|
|
163
|
+
`${colors.red(
|
|
164
|
+
`Option --${option} is no longer supported. Please review join command documentation ${JOIN_COMMAND_DOCUMENTATION_LINK}.`
|
|
165
|
+
)}`
|
|
166
|
+
);
|
|
167
|
+
process.stdout.write('\n\n');
|
|
168
|
+
|
|
169
|
+
if (['preprocess', 'decorate'].includes(option)) {
|
|
170
|
+
process.stdout.write(
|
|
171
|
+
`${colors.red(
|
|
172
|
+
`If you are looking for decorators, please review the decorators documentation ${DECORATORS_DOCUMENTATION_LINK}.`
|
|
173
|
+
)}`
|
|
174
|
+
);
|
|
175
|
+
process.stdout.write('\n\n');
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
yargs.showHelp();
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
146
183
|
process.env.REDOCLY_CLI_COMMAND = 'join';
|
|
147
184
|
commandWrapper(handleJoin)(argv);
|
|
148
185
|
}
|
|
@@ -360,6 +397,7 @@ yargs
|
|
|
360
397
|
'checkstyle',
|
|
361
398
|
'codeclimate',
|
|
362
399
|
'summary',
|
|
400
|
+
'github-actions',
|
|
363
401
|
] as ReadonlyArray<OutputFormat>,
|
|
364
402
|
default: 'codeframe' as OutputFormat,
|
|
365
403
|
},
|
|
@@ -415,28 +453,11 @@ yargs
|
|
|
415
453
|
description: 'Output file.',
|
|
416
454
|
alias: 'o',
|
|
417
455
|
},
|
|
418
|
-
format: {
|
|
419
|
-
description: 'Use a specific output format.',
|
|
420
|
-
choices: ['stylish', 'codeframe', 'json', 'checkstyle'] as ReadonlyArray<OutputFormat>,
|
|
421
|
-
hidden: true,
|
|
422
|
-
},
|
|
423
|
-
'max-problems': {
|
|
424
|
-
requiresArg: true,
|
|
425
|
-
description: 'Reduce output to a maximum of N problems.',
|
|
426
|
-
type: 'number',
|
|
427
|
-
hidden: true,
|
|
428
|
-
},
|
|
429
456
|
ext: {
|
|
430
457
|
description: 'Bundle file extension.',
|
|
431
458
|
requiresArg: true,
|
|
432
459
|
choices: outputExtensions,
|
|
433
460
|
},
|
|
434
|
-
'skip-rule': {
|
|
435
|
-
description: 'Ignore certain rules.',
|
|
436
|
-
array: true,
|
|
437
|
-
type: 'string',
|
|
438
|
-
hidden: true,
|
|
439
|
-
},
|
|
440
461
|
'skip-preprocessor': {
|
|
441
462
|
description: 'Ignore certain preprocessors.',
|
|
442
463
|
array: true,
|
|
@@ -461,12 +482,6 @@ yargs
|
|
|
461
482
|
description: 'Path to the config file.',
|
|
462
483
|
type: 'string',
|
|
463
484
|
},
|
|
464
|
-
lint: {
|
|
465
|
-
description: 'Lint API descriptions',
|
|
466
|
-
type: 'boolean',
|
|
467
|
-
default: false,
|
|
468
|
-
hidden: true,
|
|
469
|
-
},
|
|
470
485
|
metafile: {
|
|
471
486
|
description: 'Produce metadata about the bundle',
|
|
472
487
|
type: 'string',
|
|
@@ -493,12 +508,67 @@ yargs
|
|
|
493
508
|
choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
|
|
494
509
|
default: 'warn' as RuleSeverity,
|
|
495
510
|
},
|
|
511
|
+
format: {
|
|
512
|
+
hidden: true,
|
|
513
|
+
deprecated: true,
|
|
514
|
+
},
|
|
515
|
+
lint: {
|
|
516
|
+
hidden: true,
|
|
517
|
+
deprecated: true,
|
|
518
|
+
},
|
|
519
|
+
'skip-rule': {
|
|
520
|
+
hidden: true,
|
|
521
|
+
deprecated: true,
|
|
522
|
+
array: true,
|
|
523
|
+
type: 'string',
|
|
524
|
+
},
|
|
525
|
+
'max-problems': {
|
|
526
|
+
hidden: true,
|
|
527
|
+
deprecated: true,
|
|
528
|
+
},
|
|
496
529
|
}),
|
|
497
530
|
(argv) => {
|
|
531
|
+
const DEPRECATED_OPTIONS = ['lint', 'format', 'skip-rule', 'max-problems'];
|
|
532
|
+
const LINT_AND_BUNDLE_DOCUMENTATION_LINK =
|
|
533
|
+
'https://redocly.com/docs/cli/guides/lint-and-bundle/#lint-and-bundle-api-descriptions-with-redocly-cli';
|
|
534
|
+
|
|
535
|
+
DEPRECATED_OPTIONS.forEach((option) => {
|
|
536
|
+
if (argv[option]) {
|
|
537
|
+
process.stdout.write(
|
|
538
|
+
`${colors.red(
|
|
539
|
+
`Option --${option} is no longer supported. Please use separate commands, as described in the ${LINT_AND_BUNDLE_DOCUMENTATION_LINK}.`
|
|
540
|
+
)}`
|
|
541
|
+
);
|
|
542
|
+
process.stdout.write('\n\n');
|
|
543
|
+
yargs.showHelp();
|
|
544
|
+
process.exit(1);
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
|
|
498
548
|
process.env.REDOCLY_CLI_COMMAND = 'bundle';
|
|
499
549
|
commandWrapper(handleBundle)(argv);
|
|
500
550
|
}
|
|
501
551
|
)
|
|
552
|
+
.command(
|
|
553
|
+
'check-config',
|
|
554
|
+
'Lint the Redocly configuration file.',
|
|
555
|
+
async (yargs) =>
|
|
556
|
+
yargs.option({
|
|
557
|
+
config: {
|
|
558
|
+
description: 'Path to the config file.',
|
|
559
|
+
type: 'string',
|
|
560
|
+
},
|
|
561
|
+
'lint-config': {
|
|
562
|
+
description: 'Severity level for config file linting.',
|
|
563
|
+
choices: ['warn', 'error'] as ReadonlyArray<RuleSeverity>,
|
|
564
|
+
default: 'error' as RuleSeverity,
|
|
565
|
+
},
|
|
566
|
+
}),
|
|
567
|
+
(argv) => {
|
|
568
|
+
process.env.REDOCLY_CLI_COMMAND = 'check-config';
|
|
569
|
+
commandWrapper()(argv);
|
|
570
|
+
}
|
|
571
|
+
)
|
|
502
572
|
.command(
|
|
503
573
|
'login',
|
|
504
574
|
'Login to the Redocly API registry with an access token.',
|
package/src/types.ts
CHANGED
|
@@ -38,8 +38,14 @@ export type CommandOptions =
|
|
|
38
38
|
| PreviewDocsOptions
|
|
39
39
|
| BuildDocsArgv
|
|
40
40
|
| PushStatusOptions
|
|
41
|
+
| VerifyConfigOptions
|
|
41
42
|
| PreviewProjectOptions;
|
|
42
43
|
|
|
44
|
+
export type VerifyConfigOptions = {
|
|
45
|
+
config?: string;
|
|
46
|
+
'lint-config'?: 'warning' | 'error' | 'off';
|
|
47
|
+
};
|
|
48
|
+
|
|
43
49
|
export type Skips = {
|
|
44
50
|
'skip-rule'?: string[];
|
|
45
51
|
'skip-decorator'?: string[];
|
|
@@ -352,7 +352,7 @@ export function printLintTotals(totals: Totals, definitionsCount: number) {
|
|
|
352
352
|
process.stderr.write('\n');
|
|
353
353
|
}
|
|
354
354
|
|
|
355
|
-
export function printConfigLintTotals(totals: Totals): void {
|
|
355
|
+
export function printConfigLintTotals(totals: Totals, command?: string | number): void {
|
|
356
356
|
if (totals.errors > 0) {
|
|
357
357
|
process.stderr.write(
|
|
358
358
|
red(`❌ Your config has ${totals.errors} ${pluralize('error', totals.errors)}.`)
|
|
@@ -361,6 +361,8 @@ export function printConfigLintTotals(totals: Totals): void {
|
|
|
361
361
|
process.stderr.write(
|
|
362
362
|
yellow(`⚠️ Your config has ${totals.warnings} ${pluralize('warning', totals.warnings)}.\n`)
|
|
363
363
|
);
|
|
364
|
+
} else if (command === 'check-config') {
|
|
365
|
+
process.stderr.write(green('✅ Your config is valid.\n'));
|
|
364
366
|
}
|
|
365
367
|
}
|
|
366
368
|
|
package/src/wrapper.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { lintConfigCallback } from './commands/lint';
|
|
|
11
11
|
import type { CommandOptions } from './types';
|
|
12
12
|
|
|
13
13
|
export function commandWrapper<T extends CommandOptions>(
|
|
14
|
-
commandHandler
|
|
14
|
+
commandHandler?: (argv: T, config: Config, version: string) => Promise<void>
|
|
15
15
|
) {
|
|
16
16
|
return async (argv: Arguments<T>) => {
|
|
17
17
|
let code: ExitCode = 2;
|
|
@@ -31,7 +31,9 @@ export function commandWrapper<T extends CommandOptions>(
|
|
|
31
31
|
telemetry = config.telemetry;
|
|
32
32
|
hasConfig = !config.styleguide.recommendedFallback;
|
|
33
33
|
code = 1;
|
|
34
|
-
|
|
34
|
+
if (typeof commandHandler === 'function') {
|
|
35
|
+
await commandHandler(argv, config, version);
|
|
36
|
+
}
|
|
35
37
|
code = 0;
|
|
36
38
|
} catch (err) {
|
|
37
39
|
// Do nothing
|