@redocly/cli 1.12.2 → 1.14.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 +21 -0
- package/lib/__tests__/commands/join.test.js +5 -5
- package/lib/__tests__/commands/lint.test.js +2 -2
- package/lib/__tests__/commands/push.test.js +1 -1
- package/lib/cms/commands/push.js +1 -1
- package/lib/commands/join.js +14 -14
- package/lib/commands/lint.js +1 -1
- package/lib/commands/push.js +6 -6
- package/lib/commands/split/index.js +3 -3
- package/lib/index.js +2 -1
- package/lib/wrapper.js +1 -1
- package/package.json +2 -2
- package/src/__tests__/commands/join.test.ts +5 -5
- package/src/__tests__/commands/lint.test.ts +2 -2
- package/src/__tests__/commands/push.test.ts +1 -1
- package/src/cms/commands/push.ts +1 -1
- package/src/commands/join.ts +14 -18
- package/src/commands/lint.ts +1 -1
- package/src/commands/push.ts +6 -6
- package/src/commands/split/index.ts +4 -3
- package/src/index.ts +3 -1
- package/src/wrapper.ts +1 -1
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @redocly/cli
|
|
2
2
|
|
|
3
|
+
## 1.14.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Added the ability to exclude some operations or entire paths from the `security-defined` rule.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Improved error messages.
|
|
12
|
+
- Updated @redocly/openapi-core to v1.14.0.
|
|
13
|
+
|
|
14
|
+
## 1.13.0
|
|
15
|
+
|
|
16
|
+
### Minor Changes
|
|
17
|
+
|
|
18
|
+
- Added support for the linting command to output markdown format.
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Updated @redocly/openapi-core to v1.13.0.
|
|
23
|
+
|
|
3
24
|
## 1.12.2
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
|
@@ -22,7 +22,7 @@ describe('handleJoin', () => {
|
|
|
22
22
|
colloreteYellowMock.mockImplementation((string) => string);
|
|
23
23
|
it('should call exitWithError because only one entrypoint', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
24
|
yield (0, join_1.handleJoin)({ apis: ['first.yaml'] }, {}, 'cli-version');
|
|
25
|
-
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith(`At least 2 apis should be provided
|
|
25
|
+
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith(`At least 2 apis should be provided.`);
|
|
26
26
|
}));
|
|
27
27
|
it('should call exitWithError because passed all 3 options for tags', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
28
28
|
yield (0, join_1.handleJoin)({
|
|
@@ -31,7 +31,7 @@ describe('handleJoin', () => {
|
|
|
31
31
|
'without-x-tag-groups': true,
|
|
32
32
|
'prefix-tags-with-filename': true,
|
|
33
33
|
}, {}, 'cli-version');
|
|
34
|
-
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith(`You use prefix-tags-with-filename, prefix-tags-with-info-prop, without-x-tag-groups together.\nPlease choose only one
|
|
34
|
+
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith(`You use prefix-tags-with-filename, prefix-tags-with-info-prop, without-x-tag-groups together.\nPlease choose only one!`);
|
|
35
35
|
}));
|
|
36
36
|
it('should call exitWithError because passed all 2 options for tags', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
37
37
|
yield (0, join_1.handleJoin)({
|
|
@@ -39,13 +39,13 @@ describe('handleJoin', () => {
|
|
|
39
39
|
'without-x-tag-groups': true,
|
|
40
40
|
'prefix-tags-with-filename': true,
|
|
41
41
|
}, {}, 'cli-version');
|
|
42
|
-
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith(`You use prefix-tags-with-filename, without-x-tag-groups together.\nPlease choose only one
|
|
42
|
+
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith(`You use prefix-tags-with-filename, without-x-tag-groups together.\nPlease choose only one!`);
|
|
43
43
|
}));
|
|
44
44
|
it('should call exitWithError because Only OpenAPI 3.0 and OpenAPI 3.1 are supported', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
45
45
|
yield (0, join_1.handleJoin)({
|
|
46
46
|
apis: ['first.yaml', 'second.yaml'],
|
|
47
47
|
}, config_1.ConfigFixture, 'cli-version');
|
|
48
|
-
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith('Only OpenAPI 3.0 and OpenAPI 3.1 are supported: undefined
|
|
48
|
+
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith('Only OpenAPI 3.0 and OpenAPI 3.1 are supported: undefined.');
|
|
49
49
|
}));
|
|
50
50
|
it('should call exitWithError if mixing OpenAPI 3.0 and 3.1', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
51
51
|
openapi_core_1.detectSpec
|
|
@@ -54,7 +54,7 @@ describe('handleJoin', () => {
|
|
|
54
54
|
yield (0, join_1.handleJoin)({
|
|
55
55
|
apis: ['first.yaml', 'second.yaml'],
|
|
56
56
|
}, config_1.ConfigFixture, 'cli-version');
|
|
57
|
-
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith('All APIs must use the same OpenAPI version: undefined
|
|
57
|
+
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith('All APIs must use the same OpenAPI version: undefined.');
|
|
58
58
|
}));
|
|
59
59
|
it('should call writeToFileByExtension function', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
60
60
|
openapi_core_1.detectSpec.mockReturnValue('oas3_0');
|
|
@@ -48,7 +48,7 @@ describe('handleLint', () => {
|
|
|
48
48
|
describe('loadConfig and getEnrtypoints stage', () => {
|
|
49
49
|
it('should fail if config file does not exist', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
50
50
|
yield (0, wrapper_1.commandWrapper)(lint_1.handleLint)(Object.assign(Object.assign({}, argvMock), { config: 'config.yaml' }));
|
|
51
|
-
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith('Please
|
|
51
|
+
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith('Please provide a valid path to the configuration file.');
|
|
52
52
|
}));
|
|
53
53
|
it('should call loadConfigAndHandleErrors and getFallbackApisOrExit', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
54
54
|
yield (0, wrapper_1.commandWrapper)(lint_1.handleLint)(argvMock);
|
|
@@ -78,7 +78,7 @@ describe('handleLint', () => {
|
|
|
78
78
|
it('should fail if apis not provided', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
79
79
|
yield (0, wrapper_1.commandWrapper)(lint_1.handleLint)(Object.assign(Object.assign({}, argvMock), { apis: [] }));
|
|
80
80
|
expect(miscellaneous_1.getFallbackApisOrExit).toHaveBeenCalledTimes(1);
|
|
81
|
-
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith('No APIs were provided');
|
|
81
|
+
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith('No APIs were provided.');
|
|
82
82
|
}));
|
|
83
83
|
});
|
|
84
84
|
describe('loop through entrypoints and lint stage', () => {
|
|
@@ -186,7 +186,7 @@ describe('push', () => {
|
|
|
186
186
|
'job-id': '123',
|
|
187
187
|
'batch-size': 2,
|
|
188
188
|
}, mockConfig);
|
|
189
|
-
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith(`Destination argument value is not valid, please use the right format: ${(0, colorette_1.yellow)('<api-name@api-version>')}
|
|
189
|
+
expect(miscellaneous_1.exitWithError).toHaveBeenCalledWith(`Destination argument value is not valid, please use the right format: ${(0, colorette_1.yellow)('<api-name@api-version>')}.`);
|
|
190
190
|
}));
|
|
191
191
|
it('push should work and encode name with spaces', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
192
192
|
const encodeURIComponentSpy = jest.spyOn(global, 'encodeURIComponent');
|
package/lib/cms/commands/push.js
CHANGED
|
@@ -25,7 +25,7 @@ function handlePush(argv, config) {
|
|
|
25
25
|
const { organization, project: projectId, 'mount-path': mountPath, verbose } = argv;
|
|
26
26
|
const orgId = organization || config.organization;
|
|
27
27
|
if (!argv.message || !argv.author || !argv.branch) {
|
|
28
|
-
(0, miscellaneous_1.exitWithError)('Error: message, author and branch are required for push to the CMS');
|
|
28
|
+
(0, miscellaneous_1.exitWithError)('Error: message, author and branch are required for push to the CMS.');
|
|
29
29
|
}
|
|
30
30
|
if (!orgId) {
|
|
31
31
|
return (0, miscellaneous_1.exitWithError)(`No organization provided, please use --organization option or specify the 'organization' field in the config file.`);
|
package/lib/commands/join.js
CHANGED
|
@@ -26,7 +26,7 @@ function handleJoin(argv, config, packageVersion) {
|
|
|
26
26
|
return __awaiter(this, void 0, void 0, function* () {
|
|
27
27
|
const startedAt = perf_hooks_1.performance.now();
|
|
28
28
|
if (argv.apis.length < 2) {
|
|
29
|
-
return (0, miscellaneous_1.exitWithError)(`At least 2 apis should be provided
|
|
29
|
+
return (0, miscellaneous_1.exitWithError)(`At least 2 apis should be provided.`);
|
|
30
30
|
}
|
|
31
31
|
const fileExtension = (0, miscellaneous_1.getAndValidateFileExtension)(argv.output || argv.apis[0]);
|
|
32
32
|
const { 'prefix-components-with-info-prop': prefixComponentsWithInfoProp, 'prefix-tags-with-filename': prefixTagsWithFilename, 'prefix-tags-with-info-prop': prefixTagsWithInfoProp, 'without-x-tag-groups': withoutXTagGroups, output: specFilename = `openapi.${fileExtension}`, } = argv;
|
|
@@ -36,7 +36,7 @@ function handleJoin(argv, config, packageVersion) {
|
|
|
36
36
|
withoutXTagGroups && 'without-x-tag-groups',
|
|
37
37
|
].filter(Boolean);
|
|
38
38
|
if (usedTagsOptions.length > 1) {
|
|
39
|
-
return (0, miscellaneous_1.exitWithError)(`You use ${(0, colorette_1.yellow)(usedTagsOptions.join(', '))} together.\nPlease choose only one
|
|
39
|
+
return (0, miscellaneous_1.exitWithError)(`You use ${(0, colorette_1.yellow)(usedTagsOptions.join(', '))} together.\nPlease choose only one!`);
|
|
40
40
|
}
|
|
41
41
|
const apis = yield (0, miscellaneous_1.getFallbackApisOrExit)(argv.apis, config);
|
|
42
42
|
const externalRefResolver = new openapi_core_1.BaseResolver(config.resolve);
|
|
@@ -67,7 +67,7 @@ function handleJoin(argv, config, packageVersion) {
|
|
|
67
67
|
totals: fileTotals,
|
|
68
68
|
version: packageVersion,
|
|
69
69
|
});
|
|
70
|
-
(0, miscellaneous_1.exitWithError)(`❌ Errors encountered while bundling ${(0, colorette_1.blue)(document.source.absoluteRef)}: join will not proceed
|
|
70
|
+
(0, miscellaneous_1.exitWithError)(`❌ Errors encountered while bundling ${(0, colorette_1.blue)(document.source.absoluteRef)}: join will not proceed.`);
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
let oasVersion = null;
|
|
@@ -75,15 +75,15 @@ function handleJoin(argv, config, packageVersion) {
|
|
|
75
75
|
try {
|
|
76
76
|
const version = (0, openapi_core_1.detectSpec)(document.parsed);
|
|
77
77
|
if (version !== openapi_core_1.SpecVersion.OAS3_0 && version !== openapi_core_1.SpecVersion.OAS3_1) {
|
|
78
|
-
return (0, miscellaneous_1.exitWithError)(`Only OpenAPI 3.0 and OpenAPI 3.1 are supported: ${(0, colorette_1.blue)(document.source.absoluteRef)}
|
|
78
|
+
return (0, miscellaneous_1.exitWithError)(`Only OpenAPI 3.0 and OpenAPI 3.1 are supported: ${(0, colorette_1.blue)(document.source.absoluteRef)}.`);
|
|
79
79
|
}
|
|
80
80
|
oasVersion = oasVersion !== null && oasVersion !== void 0 ? oasVersion : version;
|
|
81
81
|
if (oasVersion !== version) {
|
|
82
|
-
return (0, miscellaneous_1.exitWithError)(`All APIs must use the same OpenAPI version: ${(0, colorette_1.blue)(document.source.absoluteRef)}
|
|
82
|
+
return (0, miscellaneous_1.exitWithError)(`All APIs must use the same OpenAPI version: ${(0, colorette_1.blue)(document.source.absoluteRef)}.`);
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
catch (e) {
|
|
86
|
-
return (0, miscellaneous_1.exitWithError)(`${e.message}: ${(0, colorette_1.blue)(document.source.absoluteRef)}
|
|
86
|
+
return (0, miscellaneous_1.exitWithError)(`${e.message}: ${(0, colorette_1.blue)(document.source.absoluteRef)}.`);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
const joinedDef = {};
|
|
@@ -276,7 +276,7 @@ function handleJoin(argv, config, packageVersion) {
|
|
|
276
276
|
for (const pathServer of joinedDef.paths[path].servers) {
|
|
277
277
|
if (pathServer.url === server.url) {
|
|
278
278
|
if (!isServersEqual(pathServer, server)) {
|
|
279
|
-
(0, miscellaneous_1.exitWithError)(`Different server values for (${server.url}) in ${path}
|
|
279
|
+
(0, miscellaneous_1.exitWithError)(`Different server values for (${server.url}) in ${path}.`);
|
|
280
280
|
}
|
|
281
281
|
isFoundServer = true;
|
|
282
282
|
}
|
|
@@ -307,7 +307,7 @@ function handleJoin(argv, config, packageVersion) {
|
|
|
307
307
|
if (!(0, openapi_core_1.isRef)(pathParameter) && !(0, openapi_core_1.isRef)(parameter)) {
|
|
308
308
|
if (pathParameter.name === parameter.name && pathParameter.in === parameter.in) {
|
|
309
309
|
if (!isEqual(pathParameter.schema, parameter.schema)) {
|
|
310
|
-
(0, miscellaneous_1.exitWithError)(`Different parameter schemas for (${parameter.name}) in ${path}
|
|
310
|
+
(0, miscellaneous_1.exitWithError)(`Different parameter schemas for (${parameter.name}) in ${path}.`);
|
|
311
311
|
}
|
|
312
312
|
isFoundParameter = true;
|
|
313
313
|
}
|
|
@@ -441,9 +441,9 @@ function handleJoin(argv, config, packageVersion) {
|
|
|
441
441
|
const openapi = firstApi.parsed;
|
|
442
442
|
const componentsPrefix = getInfoPrefix(openapi.info, prefixComponentsWithInfoProp, types_1.COMPONENTS);
|
|
443
443
|
if (!openapi.openapi)
|
|
444
|
-
(0, miscellaneous_1.exitWithError)('Version of specification is not found
|
|
444
|
+
(0, miscellaneous_1.exitWithError)('Version of specification is not found.');
|
|
445
445
|
if (!openapi.info)
|
|
446
|
-
(0, miscellaneous_1.exitWithError)('Info section is not found in specification.
|
|
446
|
+
(0, miscellaneous_1.exitWithError)('Info section is not found in specification.');
|
|
447
447
|
if ((_a = openapi.info) === null || _a === void 0 ? void 0 : _a.description) {
|
|
448
448
|
openapi.info.description = addComponentsPrefix(openapi.info.description, componentsPrefix);
|
|
449
449
|
}
|
|
@@ -542,13 +542,13 @@ function getInfoPrefix(info, prefixArg, type) {
|
|
|
542
542
|
if (!prefixArg)
|
|
543
543
|
return '';
|
|
544
544
|
if (!info)
|
|
545
|
-
(0, miscellaneous_1.exitWithError)('Info section is not found in specification.
|
|
545
|
+
(0, miscellaneous_1.exitWithError)('Info section is not found in specification.');
|
|
546
546
|
if (!info[prefixArg])
|
|
547
|
-
(0, miscellaneous_1.exitWithError)(`${(0, colorette_1.yellow)(`prefix-${type}-with-info-prop`)} argument value is not found in info section
|
|
547
|
+
(0, miscellaneous_1.exitWithError)(`${(0, colorette_1.yellow)(`prefix-${type}-with-info-prop`)} argument value is not found in info section.`);
|
|
548
548
|
if (!(0, js_utils_1.isString)(info[prefixArg]))
|
|
549
|
-
(0, miscellaneous_1.exitWithError)(`${(0, colorette_1.yellow)(`prefix-${type}-with-info-prop`)} argument value should be string
|
|
549
|
+
(0, miscellaneous_1.exitWithError)(`${(0, colorette_1.yellow)(`prefix-${type}-with-info-prop`)} argument value should be string.`);
|
|
550
550
|
if (info[prefixArg].length > 50)
|
|
551
|
-
(0, miscellaneous_1.exitWithError)(`${(0, colorette_1.yellow)(`prefix-${type}-with-info-prop`)} argument value length should not exceed 50 characters
|
|
551
|
+
(0, miscellaneous_1.exitWithError)(`${(0, colorette_1.yellow)(`prefix-${type}-with-info-prop`)} argument value length should not exceed 50 characters.`);
|
|
552
552
|
return info[prefixArg].replaceAll(/\s/g, '_');
|
|
553
553
|
}
|
|
554
554
|
function replace$Refs(obj, componentsPrefix) {
|
package/lib/commands/lint.js
CHANGED
|
@@ -20,7 +20,7 @@ function handleLint(argv, config, version) {
|
|
|
20
20
|
return __awaiter(this, void 0, void 0, function* () {
|
|
21
21
|
const apis = yield (0, miscellaneous_1.getFallbackApisOrExit)(argv.apis, config);
|
|
22
22
|
if (!apis.length) {
|
|
23
|
-
(0, miscellaneous_1.exitWithError)('No APIs were provided');
|
|
23
|
+
(0, miscellaneous_1.exitWithError)('No APIs were provided.');
|
|
24
24
|
}
|
|
25
25
|
if (argv['generate-ignore-file']) {
|
|
26
26
|
config.styleguide.ignore = {}; // clear ignore
|
package/lib/commands/push.js
CHANGED
|
@@ -53,7 +53,7 @@ function handlePush(argv, config) {
|
|
|
53
53
|
const jobId = argv['job-id'];
|
|
54
54
|
const batchSize = argv['batch-size'];
|
|
55
55
|
if (destination && !exports.DESTINATION_REGEX.test(destination)) {
|
|
56
|
-
(0, miscellaneous_1.exitWithError)(`Destination argument value is not valid, please use the right format: ${(0, colorette_1.yellow)('<api-name@api-version>')}
|
|
56
|
+
(0, miscellaneous_1.exitWithError)(`Destination argument value is not valid, please use the right format: ${(0, colorette_1.yellow)('<api-name@api-version>')}.`);
|
|
57
57
|
}
|
|
58
58
|
const destinationProps = getDestinationProps(destination, config.organization);
|
|
59
59
|
const organizationId = argv.organization || destinationProps.organizationId;
|
|
@@ -108,7 +108,7 @@ function handlePush(argv, config) {
|
|
|
108
108
|
const uploadResponse = yield uploadFileToS3(signedUploadUrl, file.contents || file.filePath);
|
|
109
109
|
const fileCounter = `(${++uploaded}/${filesToUpload.files.length})`;
|
|
110
110
|
if (!uploadResponse.ok) {
|
|
111
|
-
(0, miscellaneous_1.exitWithError)(`✗ ${fileCounter}\nFile upload failed
|
|
111
|
+
(0, miscellaneous_1.exitWithError)(`✗ ${fileCounter}\nFile upload failed.`);
|
|
112
112
|
}
|
|
113
113
|
process.stdout.write((0, colorette_1.green)(`✓ ${fileCounter}\n`));
|
|
114
114
|
}
|
|
@@ -128,14 +128,14 @@ function handlePush(argv, config) {
|
|
|
128
128
|
}
|
|
129
129
|
catch (error) {
|
|
130
130
|
if (error.message === 'ORGANIZATION_NOT_FOUND') {
|
|
131
|
-
(0, miscellaneous_1.exitWithError)(`Organization ${(0, colorette_1.blue)(organizationId)} not found
|
|
131
|
+
(0, miscellaneous_1.exitWithError)(`Organization ${(0, colorette_1.blue)(organizationId)} not found.`);
|
|
132
132
|
}
|
|
133
133
|
if (error.message === 'API_VERSION_NOT_FOUND') {
|
|
134
|
-
(0, miscellaneous_1.exitWithError)(`The definition version ${(0, colorette_1.blue)(`${name}@${version}`)} does not exist in organization ${(0, colorette_1.blue)(organizationId)}!\n${(0, colorette_1.yellow)('Suggestion:')} please use ${(0, colorette_1.blue)('-u')} or ${(0, colorette_1.blue)('--upsert')} to create definition
|
|
134
|
+
(0, miscellaneous_1.exitWithError)(`The definition version ${(0, colorette_1.blue)(`${name}@${version}`)} does not exist in organization ${(0, colorette_1.blue)(organizationId)}!\n${(0, colorette_1.yellow)('Suggestion:')} please use ${(0, colorette_1.blue)('-u')} or ${(0, colorette_1.blue)('--upsert')} to create definition.`);
|
|
135
135
|
}
|
|
136
136
|
throw error;
|
|
137
137
|
}
|
|
138
|
-
process.stdout.write(`Definition: ${(0, colorette_1.blue)(api)} is successfully pushed to Redocly API Registry
|
|
138
|
+
process.stdout.write(`Definition: ${(0, colorette_1.blue)(api)} is successfully pushed to Redocly API Registry.\n`);
|
|
139
139
|
}
|
|
140
140
|
(0, miscellaneous_1.printExecutionTime)('push', startedAt, api || `apis in organization ${organizationId}`);
|
|
141
141
|
});
|
|
@@ -171,7 +171,7 @@ function collectFilesToUpload(api, config) {
|
|
|
171
171
|
process.stdout.write(`Created a bundle for ${(0, colorette_1.blue)(api)} ${fileTotals.warnings > 0 ? 'with warnings' : ''}\n`);
|
|
172
172
|
}
|
|
173
173
|
else {
|
|
174
|
-
(0, miscellaneous_1.exitWithError)(`Failed to create a bundle for ${(0, colorette_1.blue)(api)}
|
|
174
|
+
(0, miscellaneous_1.exitWithError)(`Failed to create a bundle for ${(0, colorette_1.blue)(api)}.`);
|
|
175
175
|
}
|
|
176
176
|
const fileExt = path.extname(apiPath).split('.').pop();
|
|
177
177
|
files.push(getFileEntry(apiPath, (0, miscellaneous_1.dumpBundle)(openapiBundle.parsed, fileExt)));
|
|
@@ -61,12 +61,12 @@ function loadFile(fileName) {
|
|
|
61
61
|
}
|
|
62
62
|
function validateDefinitionFileName(fileName) {
|
|
63
63
|
if (!fs.existsSync(fileName))
|
|
64
|
-
(0, miscellaneous_1.exitWithError)(`File ${(0, colorette_1.blue)(fileName)} does not exist
|
|
64
|
+
(0, miscellaneous_1.exitWithError)(`File ${(0, colorette_1.blue)(fileName)} does not exist.`);
|
|
65
65
|
const file = loadFile(fileName);
|
|
66
66
|
if (file.swagger)
|
|
67
|
-
(0, miscellaneous_1.exitWithError)('OpenAPI 2 is not supported by this command');
|
|
67
|
+
(0, miscellaneous_1.exitWithError)('OpenAPI 2 is not supported by this command.');
|
|
68
68
|
if (!file.openapi)
|
|
69
|
-
(0, miscellaneous_1.exitWithError)('File does not conform to the OpenAPI Specification. OpenAPI version is not specified');
|
|
69
|
+
(0, miscellaneous_1.exitWithError)('File does not conform to the OpenAPI Specification. OpenAPI version is not specified.');
|
|
70
70
|
return true;
|
|
71
71
|
}
|
|
72
72
|
function traverseDirectoryDeep(directory, callback, componentsFiles) {
|
package/lib/index.js
CHANGED
|
@@ -364,6 +364,7 @@ yargs
|
|
|
364
364
|
'checkstyle',
|
|
365
365
|
'codeclimate',
|
|
366
366
|
'summary',
|
|
367
|
+
'markdown',
|
|
367
368
|
'github-actions',
|
|
368
369
|
],
|
|
369
370
|
default: 'codeframe',
|
|
@@ -636,7 +637,7 @@ yargs
|
|
|
636
637
|
},
|
|
637
638
|
t: {
|
|
638
639
|
alias: 'template',
|
|
639
|
-
describe: 'Path to handlebars page template, see https://
|
|
640
|
+
describe: 'Path to handlebars page template, see https://github.com/Redocly/redocly-cli/blob/main/packages/cli/src/commands/build-docs/template.hbs for the example.',
|
|
640
641
|
type: 'string',
|
|
641
642
|
},
|
|
642
643
|
templateOptions: {
|
package/lib/wrapper.js
CHANGED
|
@@ -21,7 +21,7 @@ function commandWrapper(commandHandler) {
|
|
|
21
21
|
let telemetry;
|
|
22
22
|
try {
|
|
23
23
|
if (argv.config && !(0, openapi_core_1.doesYamlFileExist)(argv.config)) {
|
|
24
|
-
(0, miscellaneous_1.exitWithError)('Please
|
|
24
|
+
(0, miscellaneous_1.exitWithError)('Please provide a valid path to the configuration file.');
|
|
25
25
|
}
|
|
26
26
|
const config = (yield (0, miscellaneous_1.loadConfigAndHandleErrors)({
|
|
27
27
|
configPath: argv.config,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"Roman Hotsiy <roman@redoc.ly> (https://redoc.ly/)"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@redocly/openapi-core": "1.
|
|
39
|
+
"@redocly/openapi-core": "1.14.0",
|
|
40
40
|
"abort-controller": "^3.0.0",
|
|
41
41
|
"chokidar": "^3.5.1",
|
|
42
42
|
"colorette": "^1.2.0",
|
|
@@ -15,7 +15,7 @@ describe('handleJoin', () => {
|
|
|
15
15
|
|
|
16
16
|
it('should call exitWithError because only one entrypoint', async () => {
|
|
17
17
|
await handleJoin({ apis: ['first.yaml'] }, {} as any, 'cli-version');
|
|
18
|
-
expect(exitWithError).toHaveBeenCalledWith(`At least 2 apis should be provided
|
|
18
|
+
expect(exitWithError).toHaveBeenCalledWith(`At least 2 apis should be provided.`);
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
it('should call exitWithError because passed all 3 options for tags', async () => {
|
|
@@ -31,7 +31,7 @@ describe('handleJoin', () => {
|
|
|
31
31
|
);
|
|
32
32
|
|
|
33
33
|
expect(exitWithError).toHaveBeenCalledWith(
|
|
34
|
-
`You use prefix-tags-with-filename, prefix-tags-with-info-prop, without-x-tag-groups together.\nPlease choose only one
|
|
34
|
+
`You use prefix-tags-with-filename, prefix-tags-with-info-prop, without-x-tag-groups together.\nPlease choose only one!`
|
|
35
35
|
);
|
|
36
36
|
});
|
|
37
37
|
|
|
@@ -47,7 +47,7 @@ describe('handleJoin', () => {
|
|
|
47
47
|
);
|
|
48
48
|
|
|
49
49
|
expect(exitWithError).toHaveBeenCalledWith(
|
|
50
|
-
`You use prefix-tags-with-filename, without-x-tag-groups together.\nPlease choose only one
|
|
50
|
+
`You use prefix-tags-with-filename, without-x-tag-groups together.\nPlease choose only one!`
|
|
51
51
|
);
|
|
52
52
|
});
|
|
53
53
|
|
|
@@ -60,7 +60,7 @@ describe('handleJoin', () => {
|
|
|
60
60
|
'cli-version'
|
|
61
61
|
);
|
|
62
62
|
expect(exitWithError).toHaveBeenCalledWith(
|
|
63
|
-
'Only OpenAPI 3.0 and OpenAPI 3.1 are supported: undefined
|
|
63
|
+
'Only OpenAPI 3.0 and OpenAPI 3.1 are supported: undefined.'
|
|
64
64
|
);
|
|
65
65
|
});
|
|
66
66
|
|
|
@@ -77,7 +77,7 @@ describe('handleJoin', () => {
|
|
|
77
77
|
);
|
|
78
78
|
|
|
79
79
|
expect(exitWithError).toHaveBeenCalledWith(
|
|
80
|
-
'All APIs must use the same OpenAPI version: undefined
|
|
80
|
+
'All APIs must use the same OpenAPI version: undefined.'
|
|
81
81
|
);
|
|
82
82
|
});
|
|
83
83
|
|
|
@@ -62,7 +62,7 @@ describe('handleLint', () => {
|
|
|
62
62
|
it('should fail if config file does not exist', async () => {
|
|
63
63
|
await commandWrapper(handleLint)({ ...argvMock, config: 'config.yaml' });
|
|
64
64
|
expect(exitWithError).toHaveBeenCalledWith(
|
|
65
|
-
'Please
|
|
65
|
+
'Please provide a valid path to the configuration file.'
|
|
66
66
|
);
|
|
67
67
|
});
|
|
68
68
|
|
|
@@ -102,7 +102,7 @@ describe('handleLint', () => {
|
|
|
102
102
|
it('should fail if apis not provided', async () => {
|
|
103
103
|
await commandWrapper(handleLint)({ ...argvMock, apis: [] });
|
|
104
104
|
expect(getFallbackApisOrExit).toHaveBeenCalledTimes(1);
|
|
105
|
-
expect(exitWithError).toHaveBeenCalledWith('No APIs were provided');
|
|
105
|
+
expect(exitWithError).toHaveBeenCalledWith('No APIs were provided.');
|
|
106
106
|
});
|
|
107
107
|
});
|
|
108
108
|
|
package/src/cms/commands/push.ts
CHANGED
|
@@ -51,7 +51,7 @@ export async function handlePush(
|
|
|
51
51
|
const orgId = organization || config.organization;
|
|
52
52
|
|
|
53
53
|
if (!argv.message || !argv.author || !argv.branch) {
|
|
54
|
-
exitWithError('Error: message, author and branch are required for push to the CMS');
|
|
54
|
+
exitWithError('Error: message, author and branch are required for push to the CMS.');
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
if (!orgId) {
|
package/src/commands/join.ts
CHANGED
|
@@ -68,7 +68,7 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
68
68
|
const startedAt = performance.now();
|
|
69
69
|
|
|
70
70
|
if (argv.apis.length < 2) {
|
|
71
|
-
return exitWithError(`At least 2 apis should be provided
|
|
71
|
+
return exitWithError(`At least 2 apis should be provided.`);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
const fileExtension = getAndValidateFileExtension(argv.output || argv.apis[0]);
|
|
@@ -89,7 +89,7 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
89
89
|
|
|
90
90
|
if (usedTagsOptions.length > 1) {
|
|
91
91
|
return exitWithError(
|
|
92
|
-
`You use ${yellow(usedTagsOptions.join(', '))} together.\nPlease choose only one
|
|
92
|
+
`You use ${yellow(usedTagsOptions.join(', '))} together.\nPlease choose only one!`
|
|
93
93
|
);
|
|
94
94
|
}
|
|
95
95
|
|
|
@@ -137,7 +137,7 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
137
137
|
exitWithError(
|
|
138
138
|
`❌ Errors encountered while bundling ${blue(
|
|
139
139
|
document.source.absoluteRef
|
|
140
|
-
)}: join will not proceed
|
|
140
|
+
)}: join will not proceed.`
|
|
141
141
|
);
|
|
142
142
|
}
|
|
143
143
|
}
|
|
@@ -148,20 +148,18 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
148
148
|
const version = detectSpec(document.parsed);
|
|
149
149
|
if (version !== SpecVersion.OAS3_0 && version !== SpecVersion.OAS3_1) {
|
|
150
150
|
return exitWithError(
|
|
151
|
-
`Only OpenAPI 3.0 and OpenAPI 3.1 are supported: ${blue(
|
|
152
|
-
document.source.absoluteRef
|
|
153
|
-
)} \n\n`
|
|
151
|
+
`Only OpenAPI 3.0 and OpenAPI 3.1 are supported: ${blue(document.source.absoluteRef)}.`
|
|
154
152
|
);
|
|
155
153
|
}
|
|
156
154
|
|
|
157
155
|
oasVersion = oasVersion ?? version;
|
|
158
156
|
if (oasVersion !== version) {
|
|
159
157
|
return exitWithError(
|
|
160
|
-
`All APIs must use the same OpenAPI version: ${blue(document.source.absoluteRef)}
|
|
158
|
+
`All APIs must use the same OpenAPI version: ${blue(document.source.absoluteRef)}.`
|
|
161
159
|
);
|
|
162
160
|
}
|
|
163
161
|
} catch (e) {
|
|
164
|
-
return exitWithError(`${e.message}: ${blue(document.source.absoluteRef)}
|
|
162
|
+
return exitWithError(`${e.message}: ${blue(document.source.absoluteRef)}.`);
|
|
165
163
|
}
|
|
166
164
|
}
|
|
167
165
|
|
|
@@ -417,7 +415,7 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
417
415
|
for (const pathServer of joinedDef.paths[path].servers) {
|
|
418
416
|
if (pathServer.url === server.url) {
|
|
419
417
|
if (!isServersEqual(pathServer, server)) {
|
|
420
|
-
exitWithError(`Different server values for (${server.url}) in ${path}
|
|
418
|
+
exitWithError(`Different server values for (${server.url}) in ${path}.`);
|
|
421
419
|
}
|
|
422
420
|
isFoundServer = true;
|
|
423
421
|
}
|
|
@@ -452,7 +450,7 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
452
450
|
if (!isRef(pathParameter) && !isRef(parameter)) {
|
|
453
451
|
if (pathParameter.name === parameter.name && pathParameter.in === parameter.in) {
|
|
454
452
|
if (!isEqual(pathParameter.schema, parameter.schema)) {
|
|
455
|
-
exitWithError(`Different parameter schemas for (${parameter.name}) in ${path}
|
|
453
|
+
exitWithError(`Different parameter schemas for (${parameter.name}) in ${path}.`);
|
|
456
454
|
}
|
|
457
455
|
isFoundParameter = true;
|
|
458
456
|
}
|
|
@@ -627,8 +625,8 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
627
625
|
const firstApi = documents[0];
|
|
628
626
|
const openapi = firstApi.parsed;
|
|
629
627
|
const componentsPrefix = getInfoPrefix(openapi.info, prefixComponentsWithInfoProp, COMPONENTS);
|
|
630
|
-
if (!openapi.openapi) exitWithError('Version of specification is not found
|
|
631
|
-
if (!openapi.info) exitWithError('Info section is not found in specification.
|
|
628
|
+
if (!openapi.openapi) exitWithError('Version of specification is not found.');
|
|
629
|
+
if (!openapi.info) exitWithError('Info section is not found in specification.');
|
|
632
630
|
if (openapi.info?.description) {
|
|
633
631
|
openapi.info.description = addComponentsPrefix(openapi.info.description, componentsPrefix);
|
|
634
632
|
}
|
|
@@ -749,20 +747,18 @@ function addSecurityPrefix(security: any, componentsPrefix: string) {
|
|
|
749
747
|
|
|
750
748
|
function getInfoPrefix(info: any, prefixArg: string | undefined, type: string) {
|
|
751
749
|
if (!prefixArg) return '';
|
|
752
|
-
if (!info) exitWithError('Info section is not found in specification.
|
|
750
|
+
if (!info) exitWithError('Info section is not found in specification.');
|
|
753
751
|
if (!info[prefixArg])
|
|
754
752
|
exitWithError(
|
|
755
|
-
`${yellow(`prefix-${type}-with-info-prop`)} argument value is not found in info section
|
|
753
|
+
`${yellow(`prefix-${type}-with-info-prop`)} argument value is not found in info section.`
|
|
756
754
|
);
|
|
757
755
|
if (!isString(info[prefixArg]))
|
|
758
|
-
exitWithError(
|
|
759
|
-
`${yellow(`prefix-${type}-with-info-prop`)} argument value should be string. \n\n`
|
|
760
|
-
);
|
|
756
|
+
exitWithError(`${yellow(`prefix-${type}-with-info-prop`)} argument value should be string.`);
|
|
761
757
|
if (info[prefixArg].length > 50)
|
|
762
758
|
exitWithError(
|
|
763
759
|
`${yellow(
|
|
764
760
|
`prefix-${type}-with-info-prop`
|
|
765
|
-
)} argument value length should not exceed 50 characters
|
|
761
|
+
)} argument value length should not exceed 50 characters.`
|
|
766
762
|
);
|
|
767
763
|
return info[prefixArg].replaceAll(/\s/g, '_');
|
|
768
764
|
}
|
package/src/commands/lint.ts
CHANGED
|
@@ -41,7 +41,7 @@ export async function handleLint(argv: LintOptions, config: Config, version: str
|
|
|
41
41
|
const apis = await getFallbackApisOrExit(argv.apis, config);
|
|
42
42
|
|
|
43
43
|
if (!apis.length) {
|
|
44
|
-
exitWithError('No APIs were provided');
|
|
44
|
+
exitWithError('No APIs were provided.');
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
if (argv['generate-ignore-file']) {
|
package/src/commands/push.ts
CHANGED
|
@@ -76,7 +76,7 @@ export async function handlePush(argv: PushOptions, config: Config): Promise<voi
|
|
|
76
76
|
exitWithError(
|
|
77
77
|
`Destination argument value is not valid, please use the right format: ${yellow(
|
|
78
78
|
'<api-name@api-version>'
|
|
79
|
-
)}
|
|
79
|
+
)}.`
|
|
80
80
|
);
|
|
81
81
|
}
|
|
82
82
|
|
|
@@ -176,7 +176,7 @@ export async function handlePush(argv: PushOptions, config: Config): Promise<voi
|
|
|
176
176
|
const fileCounter = `(${++uploaded}/${filesToUpload.files.length})`;
|
|
177
177
|
|
|
178
178
|
if (!uploadResponse.ok) {
|
|
179
|
-
exitWithError(`✗ ${fileCounter}\nFile upload failed
|
|
179
|
+
exitWithError(`✗ ${fileCounter}\nFile upload failed.`);
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
process.stdout.write(green(`✓ ${fileCounter}\n`));
|
|
@@ -198,7 +198,7 @@ export async function handlePush(argv: PushOptions, config: Config): Promise<voi
|
|
|
198
198
|
});
|
|
199
199
|
} catch (error) {
|
|
200
200
|
if (error.message === 'ORGANIZATION_NOT_FOUND') {
|
|
201
|
-
exitWithError(`Organization ${blue(organizationId)} not found
|
|
201
|
+
exitWithError(`Organization ${blue(organizationId)} not found.`);
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
if (error.message === 'API_VERSION_NOT_FOUND') {
|
|
@@ -207,7 +207,7 @@ export async function handlePush(argv: PushOptions, config: Config): Promise<voi
|
|
|
207
207
|
`${name}@${version}`
|
|
208
208
|
)} does not exist in organization ${blue(organizationId)}!\n${yellow(
|
|
209
209
|
'Suggestion:'
|
|
210
|
-
)} please use ${blue('-u')} or ${blue('--upsert')} to create definition
|
|
210
|
+
)} please use ${blue('-u')} or ${blue('--upsert')} to create definition.`
|
|
211
211
|
);
|
|
212
212
|
}
|
|
213
213
|
|
|
@@ -215,7 +215,7 @@ export async function handlePush(argv: PushOptions, config: Config): Promise<voi
|
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
process.stdout.write(
|
|
218
|
-
`Definition: ${blue(api!)} is successfully pushed to Redocly API Registry
|
|
218
|
+
`Definition: ${blue(api!)} is successfully pushed to Redocly API Registry.\n`
|
|
219
219
|
);
|
|
220
220
|
}
|
|
221
221
|
printExecutionTime('push', startedAt, api || `apis in organization ${organizationId}`);
|
|
@@ -254,7 +254,7 @@ async function collectFilesToUpload(api: string, config: Config) {
|
|
|
254
254
|
`Created a bundle for ${blue(api)} ${fileTotals.warnings > 0 ? 'with warnings' : ''}\n`
|
|
255
255
|
);
|
|
256
256
|
} else {
|
|
257
|
-
exitWithError(`Failed to create a bundle for ${blue(api)}
|
|
257
|
+
exitWithError(`Failed to create a bundle for ${blue(api)}.`);
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
const fileExt = path.extname(apiPath).split('.').pop();
|
|
@@ -111,12 +111,13 @@ function loadFile(fileName: string) {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
function validateDefinitionFileName(fileName: string) {
|
|
114
|
-
if (!fs.existsSync(fileName)) exitWithError(`File ${blue(fileName)} does not exist
|
|
114
|
+
if (!fs.existsSync(fileName)) exitWithError(`File ${blue(fileName)} does not exist.`);
|
|
115
115
|
const file = loadFile(fileName);
|
|
116
|
-
if ((file as Oas2Definition).swagger)
|
|
116
|
+
if ((file as Oas2Definition).swagger)
|
|
117
|
+
exitWithError('OpenAPI 2 is not supported by this command.');
|
|
117
118
|
if (!(file as Oas3Definition | Oas3_1Definition).openapi)
|
|
118
119
|
exitWithError(
|
|
119
|
-
'File does not conform to the OpenAPI Specification. OpenAPI version is not specified'
|
|
120
|
+
'File does not conform to the OpenAPI Specification. OpenAPI version is not specified.'
|
|
120
121
|
);
|
|
121
122
|
return true;
|
|
122
123
|
}
|
package/src/index.ts
CHANGED
|
@@ -408,6 +408,7 @@ yargs
|
|
|
408
408
|
'checkstyle',
|
|
409
409
|
'codeclimate',
|
|
410
410
|
'summary',
|
|
411
|
+
'markdown',
|
|
411
412
|
'github-actions',
|
|
412
413
|
] as ReadonlyArray<OutputFormat>,
|
|
413
414
|
default: 'codeframe' as OutputFormat,
|
|
@@ -725,7 +726,8 @@ yargs
|
|
|
725
726
|
},
|
|
726
727
|
t: {
|
|
727
728
|
alias: 'template',
|
|
728
|
-
describe:
|
|
729
|
+
describe:
|
|
730
|
+
'Path to handlebars page template, see https://github.com/Redocly/redocly-cli/blob/main/packages/cli/src/commands/build-docs/template.hbs for the example.',
|
|
729
731
|
type: 'string',
|
|
730
732
|
},
|
|
731
733
|
templateOptions: {
|
package/src/wrapper.ts
CHANGED
|
@@ -19,7 +19,7 @@ export function commandWrapper<T extends CommandOptions>(
|
|
|
19
19
|
let telemetry;
|
|
20
20
|
try {
|
|
21
21
|
if (argv.config && !doesYamlFileExist(argv.config)) {
|
|
22
|
-
exitWithError('Please
|
|
22
|
+
exitWithError('Please provide a valid path to the configuration file.');
|
|
23
23
|
}
|
|
24
24
|
const config: Config = (await loadConfigAndHandleErrors({
|
|
25
25
|
configPath: argv.config,
|