@redocly/cli 1.0.2 → 1.2.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 +27 -0
- package/README.md +3 -3
- package/lib/__mocks__/@redocly/openapi-core.d.ts +7 -6
- package/lib/__mocks__/@redocly/openapi-core.js +9 -8
- package/lib/__tests__/commands/build-docs.test.js +0 -3
- package/lib/__tests__/commands/join.test.js +22 -6
- package/lib/__tests__/utils.test.js +3 -2
- package/lib/assert-node-version.js +10 -4
- package/lib/commands/join.js +27 -22
- package/lib/commands/preview-docs/index.js +1 -12
- package/lib/commands/preview-docs/preview-server/preview-server.js +2 -2
- package/lib/commands/stats.js +3 -4
- package/lib/index.js +8 -5
- package/lib/utils.js +6 -7
- package/package.json +16 -16
- package/src/__mocks__/@redocly/openapi-core.ts +8 -6
- package/src/__tests__/commands/build-docs.test.ts +0 -4
- package/src/__tests__/commands/join.test.ts +39 -7
- package/src/__tests__/utils.test.ts +3 -2
- package/src/assert-node-version.ts +15 -4
- package/src/commands/join.ts +41 -25
- package/src/commands/preview-docs/index.ts +2 -20
- package/src/commands/preview-docs/preview-server/preview-server.ts +2 -2
- package/src/commands/stats.ts +5 -12
- package/src/index.ts +9 -5
- package/src/utils.ts +6 -7
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @redocly/cli
|
|
2
2
|
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Added support for linting AsyncAPI v2 files, so that a wider range of API descriptions can use the Redocly linting workflow.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Renamed API definition to API description for consistency.
|
|
12
|
+
- Updated @redocly/openapi-core to v1.2.0.
|
|
13
|
+
|
|
14
|
+
## 1.1.0
|
|
15
|
+
|
|
16
|
+
### Minor Changes
|
|
17
|
+
|
|
18
|
+
- Added `ignoreCase` option for `tags-alphabetical` rule.
|
|
19
|
+
- Added `join` support for OAS 3.1 definitions.
|
|
20
|
+
- Added support for Redoc v2.1.2, and aligned the dependencies for both projects.
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Fixed an issue where the `--remove-unused-components` option removed used components that were referenced as child objects.
|
|
25
|
+
- Updated Redocly config validation.
|
|
26
|
+
- Fixed the location pointer when reporting on the `no-path-trailing-slash` rule.
|
|
27
|
+
- Updated minimum required version of Node.js to v14 and removed deprecated packages.
|
|
28
|
+
- Updated @redocly/openapi-core to v1.1.0.
|
|
29
|
+
|
|
3
30
|
## 1.0.2
|
|
4
31
|
|
|
5
32
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -30,8 +30,8 @@ redocly lint path-to-root-file.yaml
|
|
|
30
30
|
|
|
31
31
|
### Docker
|
|
32
32
|
|
|
33
|
-
To give the Docker container access to the OpenAPI
|
|
34
|
-
mount the containing directory as a volume. Assuming the
|
|
33
|
+
To give the Docker container access to the OpenAPI description files, you need to
|
|
34
|
+
mount the containing directory as a volume. Assuming the API description is rooted
|
|
35
35
|
in the current working directory, you need the following command:
|
|
36
36
|
|
|
37
37
|
```
|
|
@@ -93,7 +93,7 @@ This tool [collects data](./docs/usage-data.md) to help Redocly improve our prod
|
|
|
93
93
|
|
|
94
94
|
## Credits
|
|
95
95
|
|
|
96
|
-
Thanks to [graphql-js](https://github.com/graphql/graphql-js) and [eslint](https://github.com/eslint/eslint) for inspiration of the
|
|
96
|
+
Thanks to [graphql-js](https://github.com/graphql/graphql-js) and [eslint](https://github.com/eslint/eslint) for inspiration of the API description traversal approach and to [Swagger](https://github.com/swagger-api/swagger-editor), [Spectral](https://github.com/stoplightio/spectral), and [OAS-Kit](https://github.com/Mermade/oas-kit) for inspiring the recommended ruleset.
|
|
97
97
|
|
|
98
98
|
## Development
|
|
99
99
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="jest" />
|
|
2
|
-
import { Document } from '@redocly/openapi-core';
|
|
2
|
+
import type { Document } from '@redocly/openapi-core';
|
|
3
3
|
export declare const __redoclyClient: {
|
|
4
4
|
isAuthorizedWithRedocly: jest.Mock<any, any>;
|
|
5
5
|
isAuthorizedWithRedoclyByRegion: jest.Mock<any, any>;
|
|
@@ -61,7 +61,7 @@ export declare const doesYamlFileExist: jest.Mock<any, any>;
|
|
|
61
61
|
export declare const bundleDocument: jest.Mock<Promise<{
|
|
62
62
|
problems: {};
|
|
63
63
|
}>, []>;
|
|
64
|
-
export declare const
|
|
64
|
+
export declare const detectSpec: jest.Mock<any, any>;
|
|
65
65
|
export declare const isAbsoluteUrl: jest.Mock<any, any>;
|
|
66
66
|
export declare class BaseResolver {
|
|
67
67
|
cache: Map<string, Promise<Document | ResolveError>>;
|
|
@@ -79,10 +79,11 @@ export declare class YamlParseError extends Error {
|
|
|
79
79
|
originalError: Error;
|
|
80
80
|
constructor(originalError: Error);
|
|
81
81
|
}
|
|
82
|
-
export declare enum
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
export declare enum SpecVersion {
|
|
83
|
+
OAS2 = "oas2",
|
|
84
|
+
OAS3_0 = "oas3_0",
|
|
85
|
+
OAS3_1 = "oas3_1",
|
|
86
|
+
Async2 = "async2"
|
|
86
87
|
}
|
|
87
88
|
export declare enum Oas3Operations {
|
|
88
89
|
get = "get",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Oas3Operations = exports.
|
|
3
|
+
exports.Oas3Operations = exports.SpecVersion = exports.YamlParseError = exports.ResolveError = exports.BaseResolver = exports.isAbsoluteUrl = exports.detectSpec = exports.bundleDocument = exports.doesYamlFileExist = exports.findConfig = exports.slash = exports.formatProblems = exports.getTotals = exports.bundle = exports.lint = exports.getMergedConfig = exports.loadConfig = exports.RedoclyClient = exports.__redoclyClient = void 0;
|
|
4
4
|
const config_1 = require("./../../__tests__/fixtures/config");
|
|
5
5
|
const documents_1 = require("../documents");
|
|
6
6
|
exports.__redoclyClient = {
|
|
@@ -28,7 +28,7 @@ exports.slash = jest.fn();
|
|
|
28
28
|
exports.findConfig = jest.fn();
|
|
29
29
|
exports.doesYamlFileExist = jest.fn();
|
|
30
30
|
exports.bundleDocument = jest.fn(() => Promise.resolve({ problems: {} }));
|
|
31
|
-
exports.
|
|
31
|
+
exports.detectSpec = jest.fn();
|
|
32
32
|
exports.isAbsoluteUrl = jest.fn();
|
|
33
33
|
class BaseResolver {
|
|
34
34
|
constructor() {
|
|
@@ -60,12 +60,13 @@ class YamlParseError extends Error {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
exports.YamlParseError = YamlParseError;
|
|
63
|
-
var
|
|
64
|
-
(function (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
var SpecVersion;
|
|
64
|
+
(function (SpecVersion) {
|
|
65
|
+
SpecVersion["OAS2"] = "oas2";
|
|
66
|
+
SpecVersion["OAS3_0"] = "oas3_0";
|
|
67
|
+
SpecVersion["OAS3_1"] = "oas3_1";
|
|
68
|
+
SpecVersion["Async2"] = "async2";
|
|
69
|
+
})(SpecVersion = exports.SpecVersion || (exports.SpecVersion = {}));
|
|
69
70
|
var Oas3Operations;
|
|
70
71
|
(function (Oas3Operations) {
|
|
71
72
|
Oas3Operations["get"] = "get";
|
|
@@ -31,9 +31,6 @@ jest.mock('react-dom/server', () => ({
|
|
|
31
31
|
jest.mock('handlebars', () => ({
|
|
32
32
|
compile: jest.fn(() => jest.fn(() => '<html></html>')),
|
|
33
33
|
}));
|
|
34
|
-
jest.mock('mkdirp', () => ({
|
|
35
|
-
sync: jest.fn(),
|
|
36
|
-
}));
|
|
37
34
|
describe('build-docs', () => {
|
|
38
35
|
it('should return correct html and call function for ssr', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
39
36
|
const result = yield utils_1.getPageHTML({}, '../some-path/openapi.yaml', Object.assign(Object.assign({}, config), { redocCurrentVersion: '2.0.0' }));
|
|
@@ -41,21 +41,37 @@ describe('handleJoin fails', () => {
|
|
|
41
41
|
}, {}, 'cli-version');
|
|
42
42
|
expect(utils_1.exitWithError).toHaveBeenCalledWith(`You use prefix-tags-with-filename, without-x-tag-groups together.\nPlease choose only one! \n\n`);
|
|
43
43
|
}));
|
|
44
|
-
it('should call exitWithError because Only OpenAPI 3
|
|
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 join_1.handleJoin({
|
|
46
46
|
apis: ['first.yaml', 'second.yaml'],
|
|
47
47
|
}, config_1.ConfigFixture, 'cli-version');
|
|
48
|
-
expect(utils_1.exitWithError).toHaveBeenCalledWith('Only OpenAPI 3
|
|
48
|
+
expect(utils_1.exitWithError).toHaveBeenCalledWith('Only OpenAPI 3.0 and OpenAPI 3.1 are supported: undefined \n\n');
|
|
49
|
+
}));
|
|
50
|
+
it('should call exitWithError if mixing OpenAPI 3.0 and 3.1', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
51
|
+
openapi_core_1.detectSpec
|
|
52
|
+
.mockImplementationOnce(() => 'oas3_0')
|
|
53
|
+
.mockImplementationOnce(() => 'oas3_1');
|
|
54
|
+
yield join_1.handleJoin({
|
|
55
|
+
apis: ['first.yaml', 'second.yaml'],
|
|
56
|
+
}, config_1.ConfigFixture, 'cli-version');
|
|
57
|
+
expect(utils_1.exitWithError).toHaveBeenCalledWith('All APIs must use the same OpenAPI version: undefined \n\n');
|
|
49
58
|
}));
|
|
50
59
|
it('should call writeYaml function', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
51
|
-
openapi_core_1.
|
|
60
|
+
openapi_core_1.detectSpec.mockReturnValue('oas3_0');
|
|
61
|
+
yield join_1.handleJoin({
|
|
62
|
+
apis: ['first.yaml', 'second.yaml'],
|
|
63
|
+
}, config_1.ConfigFixture, 'cli-version');
|
|
64
|
+
expect(utils_1.writeYaml).toHaveBeenCalledWith(expect.any(Object), 'openapi.yaml', expect.any(Boolean));
|
|
65
|
+
}));
|
|
66
|
+
it('should call writeYaml function for OpenAPI 3.1', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
67
|
+
openapi_core_1.detectSpec.mockReturnValue('oas3_1');
|
|
52
68
|
yield join_1.handleJoin({
|
|
53
69
|
apis: ['first.yaml', 'second.yaml'],
|
|
54
70
|
}, config_1.ConfigFixture, 'cli-version');
|
|
55
71
|
expect(utils_1.writeYaml).toHaveBeenCalledWith(expect.any(Object), 'openapi.yaml', expect.any(Boolean));
|
|
56
72
|
}));
|
|
57
73
|
it('should call writeYaml function with custom output file', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
58
|
-
openapi_core_1.
|
|
74
|
+
openapi_core_1.detectSpec.mockReturnValue('oas3_0');
|
|
59
75
|
yield join_1.handleJoin({
|
|
60
76
|
apis: ['first.yaml', 'second.yaml'],
|
|
61
77
|
output: 'output.yml',
|
|
@@ -63,7 +79,7 @@ describe('handleJoin fails', () => {
|
|
|
63
79
|
expect(utils_1.writeYaml).toHaveBeenCalledWith(expect.any(Object), 'output.yml', expect.any(Boolean));
|
|
64
80
|
}));
|
|
65
81
|
it('should call skipDecorators and skipPreprocessors', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
66
|
-
openapi_core_1.
|
|
82
|
+
openapi_core_1.detectSpec.mockReturnValue('oas3_0');
|
|
67
83
|
yield join_1.handleJoin({
|
|
68
84
|
apis: ['first.yaml', 'second.yaml'],
|
|
69
85
|
}, config_1.ConfigFixture, 'cli-version');
|
|
@@ -72,7 +88,7 @@ describe('handleJoin fails', () => {
|
|
|
72
88
|
expect(config.styleguide.skipPreprocessors).toHaveBeenCalled();
|
|
73
89
|
}));
|
|
74
90
|
it('should not call skipDecorators and skipPreprocessors', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
75
|
-
openapi_core_1.
|
|
91
|
+
openapi_core_1.detectSpec.mockReturnValue('oas3_0');
|
|
76
92
|
yield join_1.handleJoin({
|
|
77
93
|
apis: ['first.yaml', 'second.yaml'],
|
|
78
94
|
decorate: true,
|
|
@@ -338,13 +338,13 @@ describe('handleErrors', () => {
|
|
|
338
338
|
const resolveError = new openapi_core_1.ResolveError(new Error('File not found'));
|
|
339
339
|
expect(() => utils_1.handleError(resolveError, ref)).toThrowError(utils_1.HandledError);
|
|
340
340
|
expect(redColoretteMocks).toHaveBeenCalledTimes(1);
|
|
341
|
-
expect(process.stderr.write).toHaveBeenCalledWith(`Failed to resolve
|
|
341
|
+
expect(process.stderr.write).toHaveBeenCalledWith(`Failed to resolve API description at openapi/test.yaml:\n\n - File not found.\n\n`);
|
|
342
342
|
});
|
|
343
343
|
it('should handle YamlParseError', () => {
|
|
344
344
|
const yamlParseError = new openapi_core_1.YamlParseError(new Error('Invalid yaml'), {});
|
|
345
345
|
expect(() => utils_1.handleError(yamlParseError, ref)).toThrowError(utils_1.HandledError);
|
|
346
346
|
expect(redColoretteMocks).toHaveBeenCalledTimes(1);
|
|
347
|
-
expect(process.stderr.write).toHaveBeenCalledWith(`Failed to parse
|
|
347
|
+
expect(process.stderr.write).toHaveBeenCalledWith(`Failed to parse API description at openapi/test.yaml:\n\n - Invalid yaml.\n\n`);
|
|
348
348
|
});
|
|
349
349
|
it('should handle CircularJSONNotSupportedError', () => {
|
|
350
350
|
const circularError = new utils_1.CircularJSONNotSupportedError(new Error('Circular json'));
|
|
@@ -376,6 +376,7 @@ describe('checkIfRulesetExist', () => {
|
|
|
376
376
|
oas2: {},
|
|
377
377
|
oas3_0: {},
|
|
378
378
|
oas3_1: {},
|
|
379
|
+
async2: {},
|
|
379
380
|
};
|
|
380
381
|
expect(() => utils_1.checkIfRulesetExist(rules)).toThrowError('⚠️ No rules were configured. Learn how to configure rules: https://redocly.com/docs/cli/rules/');
|
|
381
382
|
});
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const semver = require("semver");
|
|
3
4
|
const path = require("path");
|
|
4
|
-
const
|
|
5
|
+
const process = require("process");
|
|
6
|
+
const colorette_1 = require("colorette");
|
|
5
7
|
try {
|
|
6
|
-
require(
|
|
8
|
+
const { engines } = require(path.join(__dirname, '../package.json'));
|
|
9
|
+
const version = engines.node;
|
|
10
|
+
if (!semver.satisfies(process.version, version)) {
|
|
11
|
+
process.stderr.write(colorette_1.yellow(`\n⚠️ Warning: failed to satisfy expected node version. Expected: "${version}", Current "${process.version}"\n\n`));
|
|
12
|
+
}
|
|
7
13
|
}
|
|
8
|
-
catch (
|
|
9
|
-
|
|
14
|
+
catch (e) {
|
|
15
|
+
// Do nothing
|
|
10
16
|
}
|
package/lib/commands/join.js
CHANGED
|
@@ -73,11 +73,16 @@ function handleJoin(argv, config, packageVersion) {
|
|
|
73
73
|
utils_1.exitWithError(`❌ Errors encountered while bundling ${colorette_1.blue(document.source.absoluteRef)}: join will not proceed.\n`);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
+
let oasVersion = null;
|
|
76
77
|
for (const document of documents) {
|
|
77
78
|
try {
|
|
78
|
-
const version = openapi_core_1.
|
|
79
|
-
if (version !== openapi_core_1.
|
|
80
|
-
return utils_1.exitWithError(`Only OpenAPI 3
|
|
79
|
+
const version = openapi_core_1.detectSpec(document.parsed);
|
|
80
|
+
if (version !== openapi_core_1.SpecVersion.OAS3_0 && version !== openapi_core_1.SpecVersion.OAS3_1) {
|
|
81
|
+
return utils_1.exitWithError(`Only OpenAPI 3.0 and OpenAPI 3.1 are supported: ${colorette_1.blue(document.source.absoluteRef)} \n\n`);
|
|
82
|
+
}
|
|
83
|
+
oasVersion = oasVersion !== null && oasVersion !== void 0 ? oasVersion : version;
|
|
84
|
+
if (oasVersion !== version) {
|
|
85
|
+
return utils_1.exitWithError(`All APIs must use the same OpenAPI version: ${colorette_1.blue(document.source.absoluteRef)} \n\n`);
|
|
81
86
|
}
|
|
82
87
|
}
|
|
83
88
|
catch (e) {
|
|
@@ -94,7 +99,7 @@ function handleJoin(argv, config, packageVersion) {
|
|
|
94
99
|
tags: {},
|
|
95
100
|
paths: {},
|
|
96
101
|
components: {},
|
|
97
|
-
|
|
102
|
+
webhooks: {},
|
|
98
103
|
};
|
|
99
104
|
addInfoSectionAndSpecVersion(documents, prefixComponentsWithInfoProp);
|
|
100
105
|
for (const document of documents) {
|
|
@@ -125,7 +130,7 @@ function handleJoin(argv, config, packageVersion) {
|
|
|
125
130
|
collectExternalDocs(openapi, context);
|
|
126
131
|
collectPaths(openapi, context);
|
|
127
132
|
collectComponents(openapi, context);
|
|
128
|
-
|
|
133
|
+
collectWebhooks(oasVersion, openapi, context);
|
|
129
134
|
if (componentsPrefix) {
|
|
130
135
|
replace$Refs(openapi, componentsPrefix);
|
|
131
136
|
}
|
|
@@ -411,28 +416,28 @@ function handleJoin(argv, config, packageVersion) {
|
|
|
411
416
|
}
|
|
412
417
|
}
|
|
413
418
|
}
|
|
414
|
-
function
|
|
415
|
-
const
|
|
416
|
-
const
|
|
417
|
-
if (
|
|
418
|
-
if (!joinedDef.hasOwnProperty(
|
|
419
|
-
joinedDef[
|
|
420
|
-
}
|
|
421
|
-
for (const webhook of Object.keys(
|
|
422
|
-
joinedDef[
|
|
423
|
-
if (!potentialConflicts.
|
|
424
|
-
potentialConflicts.
|
|
419
|
+
function collectWebhooks(oasVersion, openapi, { apiFilename, api, potentialConflicts, tagsPrefix, componentsPrefix }) {
|
|
420
|
+
const webhooks = oasVersion === openapi_core_1.SpecVersion.OAS3_1 ? 'webhooks' : 'x-webhooks';
|
|
421
|
+
const openapiWebhooks = openapi[webhooks];
|
|
422
|
+
if (openapiWebhooks) {
|
|
423
|
+
if (!joinedDef.hasOwnProperty(webhooks)) {
|
|
424
|
+
joinedDef[webhooks] = {};
|
|
425
|
+
}
|
|
426
|
+
for (const webhook of Object.keys(openapiWebhooks)) {
|
|
427
|
+
joinedDef[webhooks][webhook] = openapiWebhooks[webhook];
|
|
428
|
+
if (!potentialConflicts.webhooks.hasOwnProperty(webhook)) {
|
|
429
|
+
potentialConflicts.webhooks[webhook] = {};
|
|
425
430
|
}
|
|
426
|
-
for (const operation of Object.keys(
|
|
427
|
-
potentialConflicts.
|
|
428
|
-
...(potentialConflicts.
|
|
431
|
+
for (const operation of Object.keys(openapiWebhooks[webhook])) {
|
|
432
|
+
potentialConflicts.webhooks[webhook][operation] = [
|
|
433
|
+
...(potentialConflicts.webhooks[webhook][operation] || []),
|
|
429
434
|
api,
|
|
430
435
|
];
|
|
431
436
|
}
|
|
432
|
-
for (const operationKey of Object.keys(joinedDef[
|
|
433
|
-
const { tags } = joinedDef[
|
|
437
|
+
for (const operationKey of Object.keys(joinedDef[webhooks][webhook])) {
|
|
438
|
+
const { tags } = joinedDef[webhooks][webhook][operationKey];
|
|
434
439
|
if (tags) {
|
|
435
|
-
joinedDef[
|
|
440
|
+
joinedDef[webhooks][webhook][operationKey].tags = tags.map((tag) => addPrefix(tag, tagsPrefix));
|
|
436
441
|
populateTags({
|
|
437
442
|
api,
|
|
438
443
|
apiFilename,
|
|
@@ -51,7 +51,7 @@ function previewDocs(argv, configFromFile) {
|
|
|
51
51
|
return openapiBundle.parsed;
|
|
52
52
|
}
|
|
53
53
|
catch (e) {
|
|
54
|
-
handleError(e, api.path);
|
|
54
|
+
utils_1.handleError(e, api.path);
|
|
55
55
|
}
|
|
56
56
|
});
|
|
57
57
|
}
|
|
@@ -138,14 +138,3 @@ function debounce(func, wait, immediate) {
|
|
|
138
138
|
};
|
|
139
139
|
}
|
|
140
140
|
exports.debounce = debounce;
|
|
141
|
-
function handleError(e, ref) {
|
|
142
|
-
if (e instanceof openapi_core_1.ResolveError) {
|
|
143
|
-
process.stderr.write(`Failed to resolve api definition at ${ref}:\n\n - ${e.message}.\n\n`);
|
|
144
|
-
}
|
|
145
|
-
else if (e instanceof openapi_core_1.YamlParseError) {
|
|
146
|
-
process.stderr.write(`Failed to parse api definition at ${ref}:\n\n - ${e.message}.\n\n`);
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
process.stderr.write(`Something went wrong when processing ${ref}:\n\n - ${e.message}.\n\n`);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
@@ -11,7 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
const handlebars_1 = require("handlebars");
|
|
13
13
|
const colorette = require("colorette");
|
|
14
|
-
const
|
|
14
|
+
const get_port_please_1 = require("get-port-please");
|
|
15
15
|
const fs_1 = require("fs");
|
|
16
16
|
const path = require("path");
|
|
17
17
|
const server_1 = require("./server");
|
|
@@ -113,7 +113,7 @@ function startPreviewServer(port, host, { getBundle, getOptions, useRedocPro, })
|
|
|
113
113
|
}
|
|
114
114
|
console.timeEnd(colorette.dim(`GET ${request.url}`));
|
|
115
115
|
});
|
|
116
|
-
const wsPort = yield
|
|
116
|
+
const wsPort = yield get_port_please_1.getPort({ portRange: [32201, 32301] });
|
|
117
117
|
const server = server_1.startHttpServer(port, host, handler);
|
|
118
118
|
server.on('listening', () => {
|
|
119
119
|
process.stdout.write(`\n 🔎 Preview server running at ${colorette.blue(`http://${host}:${port}\n`)}`);
|
package/lib/commands/stats.js
CHANGED
|
@@ -58,13 +58,12 @@ function handleStats(argv, config) {
|
|
|
58
58
|
const externalRefResolver = new openapi_core_1.BaseResolver(config.resolve);
|
|
59
59
|
const { bundle: document } = yield openapi_core_1.bundle({ config, ref: path });
|
|
60
60
|
const lintConfig = config.styleguide;
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
const types = openapi_core_1.normalizeTypes(lintConfig.extendTypes(oasMajorVersion === openapi_core_1.OasMajorVersion.Version3 ? openapi_core_1.Oas3Types : openapi_core_1.Oas2Types, oasVersion), lintConfig);
|
|
61
|
+
const specVersion = openapi_core_1.detectSpec(document.parsed);
|
|
62
|
+
const types = openapi_core_1.normalizeTypes(lintConfig.extendTypes(openapi_core_1.getTypes(specVersion), specVersion), lintConfig);
|
|
64
63
|
const startedAt = perf_hooks_1.performance.now();
|
|
65
64
|
const ctx = {
|
|
66
65
|
problems: [],
|
|
67
|
-
oasVersion:
|
|
66
|
+
oasVersion: specVersion,
|
|
68
67
|
visitorsData: {},
|
|
69
68
|
};
|
|
70
69
|
const resolvedRefMap = yield openapi_core_1.resolveDocument({
|
package/lib/index.js
CHANGED
|
@@ -26,6 +26,9 @@ const build_docs_1 = require("./commands/build-docs");
|
|
|
26
26
|
const update_version_notifier_1 = require("./update-version-notifier");
|
|
27
27
|
const wrapper_1 = require("./wrapper");
|
|
28
28
|
const update_version_notifier_2 = require("./update-version-notifier");
|
|
29
|
+
if (!('replaceAll' in String.prototype)) {
|
|
30
|
+
require('core-js/actual/string/replace-all');
|
|
31
|
+
}
|
|
29
32
|
update_version_notifier_1.cacheLatestVersion();
|
|
30
33
|
yargs
|
|
31
34
|
.version('version', 'Show version number.', update_version_notifier_2.version)
|
|
@@ -42,9 +45,9 @@ yargs
|
|
|
42
45
|
process.env.REDOCLY_CLI_COMMAND = 'stats';
|
|
43
46
|
wrapper_1.commandWrapper(stats_1.handleStats)(argv);
|
|
44
47
|
})
|
|
45
|
-
.command('split [api]', 'Split an API
|
|
48
|
+
.command('split [api]', 'Split an API description into a multi-file structure.', (yargs) => yargs
|
|
46
49
|
.positional('api', {
|
|
47
|
-
description: 'API
|
|
50
|
+
description: 'API description file that you want to split',
|
|
48
51
|
type: 'string',
|
|
49
52
|
})
|
|
50
53
|
.option({
|
|
@@ -113,7 +116,7 @@ yargs
|
|
|
113
116
|
process.env.REDOCLY_CLI_COMMAND = 'join';
|
|
114
117
|
wrapper_1.commandWrapper(join_1.handleJoin)(argv);
|
|
115
118
|
})
|
|
116
|
-
.command('push [api] [maybeDestination] [maybeBranchName]', 'Push an API
|
|
119
|
+
.command('push [api] [maybeDestination] [maybeBranchName]', 'Push an API description to the Redocly API registry.', (yargs) => yargs
|
|
117
120
|
.usage('push [api]')
|
|
118
121
|
.positional('api', { type: 'string' })
|
|
119
122
|
.positional('maybeDestination', { type: 'string' })
|
|
@@ -164,7 +167,7 @@ yargs
|
|
|
164
167
|
type: 'string',
|
|
165
168
|
},
|
|
166
169
|
public: {
|
|
167
|
-
description: 'Make the API
|
|
170
|
+
description: 'Make the API description available to the public',
|
|
168
171
|
type: 'boolean',
|
|
169
172
|
},
|
|
170
173
|
files: {
|
|
@@ -282,7 +285,7 @@ yargs
|
|
|
282
285
|
type: 'string',
|
|
283
286
|
},
|
|
284
287
|
lint: {
|
|
285
|
-
description: 'Lint API
|
|
288
|
+
description: 'Lint API descriptions',
|
|
286
289
|
type: 'boolean',
|
|
287
290
|
default: false,
|
|
288
291
|
},
|
package/lib/utils.js
CHANGED
|
@@ -25,7 +25,7 @@ const fetch_with_timeout_1 = require("./fetch-with-timeout");
|
|
|
25
25
|
const path_1 = require("path");
|
|
26
26
|
const colorette_1 = require("colorette");
|
|
27
27
|
const perf_hooks_1 = require("perf_hooks");
|
|
28
|
-
const glob = require("glob
|
|
28
|
+
const glob = require("glob");
|
|
29
29
|
const fs = require("fs");
|
|
30
30
|
const readline = require("readline");
|
|
31
31
|
const stream_1 = require("stream");
|
|
@@ -87,7 +87,7 @@ function expandGlobsInEntrypoints(args, config) {
|
|
|
87
87
|
return __awaiter(this, void 0, void 0, function* () {
|
|
88
88
|
return (yield Promise.all(args.map((aliasOrPath) => __awaiter(this, void 0, void 0, function* () {
|
|
89
89
|
return glob.hasMagic(aliasOrPath) && !openapi_core_1.isAbsoluteUrl(aliasOrPath)
|
|
90
|
-
? (yield glob(aliasOrPath)).map((g) => getAliasOrPath(config, g))
|
|
90
|
+
? (yield glob.__promisify__(aliasOrPath)).map((g) => getAliasOrPath(config, g))
|
|
91
91
|
: getAliasOrPath(config, aliasOrPath);
|
|
92
92
|
})))).flat();
|
|
93
93
|
});
|
|
@@ -222,10 +222,9 @@ function handleError(e, ref) {
|
|
|
222
222
|
throw e;
|
|
223
223
|
}
|
|
224
224
|
case openapi_core_1.ResolveError:
|
|
225
|
-
return exitWithError(`Failed to resolve
|
|
225
|
+
return exitWithError(`Failed to resolve API description at ${ref}:\n\n - ${e.message}.`);
|
|
226
226
|
case openapi_core_1.YamlParseError:
|
|
227
|
-
return exitWithError(`Failed to parse
|
|
228
|
-
// TODO: codeframe
|
|
227
|
+
return exitWithError(`Failed to parse API description at ${ref}:\n\n - ${e.message}.`);
|
|
229
228
|
case CircularJSONNotSupportedError: {
|
|
230
229
|
return exitWithError(`Detected circular reference which can't be converted to JSON.\n` +
|
|
231
230
|
`Try to use ${colorette_1.blue('yaml')} output or remove ${colorette_1.blue('--dereferenced')}.`);
|
|
@@ -251,11 +250,11 @@ function printLintTotals(totals, definitionsCount) {
|
|
|
251
250
|
: ''}.\n${ignored}`));
|
|
252
251
|
}
|
|
253
252
|
else if (totals.warnings > 0) {
|
|
254
|
-
process.stderr.write(colorette_1.green(`Woohoo! Your
|
|
253
|
+
process.stderr.write(colorette_1.green(`Woohoo! Your API ${pluralize('description is', definitionsCount)} valid. 🎉\n`));
|
|
255
254
|
process.stderr.write(colorette_1.yellow(`You have ${totals.warnings} ${pluralize('warning', totals.warnings)}.\n${ignored}`));
|
|
256
255
|
}
|
|
257
256
|
else {
|
|
258
|
-
process.stderr.write(colorette_1.green(`Woohoo! Your
|
|
257
|
+
process.stderr.write(colorette_1.green(`Woohoo! Your API ${pluralize('description is', definitionsCount)} valid. 🎉\n${ignored}`));
|
|
259
258
|
}
|
|
260
259
|
if (totals.errors > 0) {
|
|
261
260
|
process.stderr.write(colorette_1.gray(`run \`redocly lint --generate-ignore-file\` to add all problems to the ignore file.\n`));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/cli",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"redocly": "bin/cli.js"
|
|
9
9
|
},
|
|
10
10
|
"engines": {
|
|
11
|
-
"node": ">=
|
|
11
|
+
"node": ">=14.0.0"
|
|
12
12
|
},
|
|
13
13
|
"engineStrict": true,
|
|
14
14
|
"scripts": {
|
|
@@ -28,36 +28,36 @@
|
|
|
28
28
|
"Swagger",
|
|
29
29
|
"OpenAPI linter",
|
|
30
30
|
"Swagger linter",
|
|
31
|
+
"AsyncAPI linter",
|
|
31
32
|
"oas"
|
|
32
33
|
],
|
|
33
34
|
"contributors": [
|
|
34
35
|
"Roman Hotsiy <roman@redoc.ly> (https://redoc.ly/)"
|
|
35
36
|
],
|
|
36
37
|
"dependencies": {
|
|
37
|
-
"@redocly/openapi-core": "1.0
|
|
38
|
-
"assert-node-version": "^1.0.3",
|
|
38
|
+
"@redocly/openapi-core": "1.2.0",
|
|
39
39
|
"chokidar": "^3.5.1",
|
|
40
40
|
"colorette": "^1.2.0",
|
|
41
|
+
"core-js": "^3.32.1",
|
|
42
|
+
"get-port-please": "^3.0.1",
|
|
41
43
|
"glob": "^7.1.6",
|
|
42
|
-
"glob-promise": "^3.4.0",
|
|
43
44
|
"handlebars": "^4.7.6",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
45
|
+
"mobx": "^6.0.4",
|
|
46
|
+
"react": "^17.0.0 || ^18.2.0",
|
|
47
|
+
"react-dom": "^17.0.0 || ^18.2.0",
|
|
48
|
+
"redoc": "~2.1.2",
|
|
46
49
|
"semver": "^7.5.2",
|
|
47
50
|
"simple-websocket": "^9.0.0",
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"react": "^17.0.0",
|
|
51
|
-
"react-dom": "^17.0.0",
|
|
52
|
-
"styled-components": "^5.1.1"
|
|
51
|
+
"styled-components": "^6.0.7",
|
|
52
|
+
"yargs": "17.0.1"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@types/configstore": "^5.0.1",
|
|
56
|
-
"@types/
|
|
57
|
-
"@types/react
|
|
58
|
-
"@types/
|
|
59
|
-
"@types/yargs": "17.0.5",
|
|
56
|
+
"@types/glob": "^8.1.0",
|
|
57
|
+
"@types/react": "^17.0.0 || ^18.2.21",
|
|
58
|
+
"@types/react-dom": "^17.0.0 || ^18.2.7",
|
|
60
59
|
"@types/semver": "^7.5.0",
|
|
60
|
+
"@types/yargs": "17.0.5",
|
|
61
61
|
"typescript": "^4.0.3"
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ConfigFixture } from './../../__tests__/fixtures/config';
|
|
2
|
-
import { Document } from '@redocly/openapi-core';
|
|
3
2
|
import { firstDocument, secondDocument } from '../documents';
|
|
4
3
|
|
|
4
|
+
import type { Document } from '@redocly/openapi-core';
|
|
5
|
+
|
|
5
6
|
export const __redoclyClient = {
|
|
6
7
|
isAuthorizedWithRedocly: jest.fn().mockResolvedValue(true),
|
|
7
8
|
isAuthorizedWithRedoclyByRegion: jest.fn().mockResolvedValue(true),
|
|
@@ -28,7 +29,7 @@ export const slash = jest.fn();
|
|
|
28
29
|
export const findConfig = jest.fn();
|
|
29
30
|
export const doesYamlFileExist = jest.fn();
|
|
30
31
|
export const bundleDocument = jest.fn(() => Promise.resolve({ problems: {} }));
|
|
31
|
-
export const
|
|
32
|
+
export const detectSpec = jest.fn();
|
|
32
33
|
export const isAbsoluteUrl = jest.fn();
|
|
33
34
|
|
|
34
35
|
export class BaseResolver {
|
|
@@ -62,10 +63,11 @@ export class YamlParseError extends Error {
|
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
export enum
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
export enum SpecVersion {
|
|
67
|
+
OAS2 = 'oas2',
|
|
68
|
+
OAS3_0 = 'oas3_0',
|
|
69
|
+
OAS3_1 = 'oas3_1',
|
|
70
|
+
Async2 = 'async2',
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
export enum Oas3Operations {
|
|
@@ -26,10 +26,6 @@ jest.mock('handlebars', () => ({
|
|
|
26
26
|
compile: jest.fn(() => jest.fn(() => '<html></html>')),
|
|
27
27
|
}));
|
|
28
28
|
|
|
29
|
-
jest.mock('mkdirp', () => ({
|
|
30
|
-
sync: jest.fn(),
|
|
31
|
-
}));
|
|
32
|
-
|
|
33
29
|
describe('build-docs', () => {
|
|
34
30
|
it('should return correct html and call function for ssr', async () => {
|
|
35
31
|
const result = await getPageHTML({}, '../some-path/openapi.yaml', {
|