@redocly/cli 1.0.0-beta.116 → 1.0.0-beta.118
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/lib/__mocks__/@redocly/openapi-core.d.ts +1 -0
- package/lib/__mocks__/@redocly/openapi-core.js +2 -1
- package/lib/__mocks__/utils.d.ts +11 -0
- package/lib/__mocks__/utils.js +3 -1
- package/lib/__tests__/commands/lint.test.js +4 -4
- package/lib/__tests__/commands/push.test.js +1 -1
- package/lib/__tests__/utils.test.js +98 -0
- package/lib/commands/build-docs/index.js +5 -3
- package/lib/commands/build-docs/utils.d.ts +1 -2
- package/lib/commands/build-docs/utils.js +3 -6
- package/lib/commands/bundle.js +10 -7
- package/lib/commands/join.js +1 -1
- package/lib/commands/lint.js +1 -1
- package/lib/commands/login.js +1 -1
- package/lib/commands/preview-docs/index.js +1 -1
- package/lib/commands/push.js +1 -1
- package/lib/commands/stats.js +1 -1
- package/lib/types.d.ts +2 -1
- package/lib/utils.d.ts +10 -3
- package/lib/utils.js +37 -13
- package/package.json +2 -2
- package/src/__mocks__/@redocly/openapi-core.ts +1 -0
- package/src/__mocks__/utils.ts +3 -0
- package/src/__tests__/commands/lint.test.ts +5 -5
- package/src/__tests__/commands/push.test.ts +3 -3
- package/src/__tests__/utils.test.ts +129 -1
- package/src/commands/build-docs/index.ts +12 -5
- package/src/commands/build-docs/utils.ts +2 -6
- package/src/commands/bundle.ts +8 -11
- package/src/commands/join.ts +2 -2
- package/src/commands/lint.ts +2 -2
- package/src/commands/login.ts +3 -3
- package/src/commands/preview-docs/index.ts +2 -3
- package/src/commands/push.ts +2 -2
- package/src/commands/stats.ts +2 -3
- package/src/types.ts +3 -1
- package/src/utils.ts +65 -19
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -52,6 +52,7 @@ export declare const bundleDocument: jest.Mock<Promise<{
|
|
|
52
52
|
problems: {};
|
|
53
53
|
}>, []>;
|
|
54
54
|
export declare const detectOpenAPI: jest.Mock<any, any>;
|
|
55
|
+
export declare const isAbsoluteUrl: jest.Mock<any, any>;
|
|
55
56
|
export declare class BaseResolver {
|
|
56
57
|
cache: Map<string, Promise<ResolveError | Document>>;
|
|
57
58
|
getFiles: jest.Mock<any, any>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Oas3Operations = exports.OasVersion = exports.BaseResolver = exports.detectOpenAPI = 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;
|
|
3
|
+
exports.Oas3Operations = exports.OasVersion = exports.BaseResolver = exports.isAbsoluteUrl = exports.detectOpenAPI = 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 = {
|
|
@@ -29,6 +29,7 @@ exports.findConfig = jest.fn();
|
|
|
29
29
|
exports.doesYamlFileExist = jest.fn();
|
|
30
30
|
exports.bundleDocument = jest.fn(() => Promise.resolve({ problems: {} }));
|
|
31
31
|
exports.detectOpenAPI = jest.fn();
|
|
32
|
+
exports.isAbsoluteUrl = jest.fn();
|
|
32
33
|
class BaseResolver {
|
|
33
34
|
constructor() {
|
|
34
35
|
this.cache = new Map();
|
package/lib/__mocks__/utils.d.ts
CHANGED
|
@@ -14,3 +14,14 @@ export declare const getOutputFileName: jest.Mock<{
|
|
|
14
14
|
export declare const handleError: jest.Mock<any, any>;
|
|
15
15
|
export declare const exitWithError: jest.Mock<any, any>;
|
|
16
16
|
export declare const writeYaml: jest.Mock<any, any>;
|
|
17
|
+
export declare const loadConfigAndHandleErrors: jest.Mock<{
|
|
18
|
+
configFile: null;
|
|
19
|
+
styleguide: {
|
|
20
|
+
addIgnore: jest.Mock<any, any>;
|
|
21
|
+
skipRules: jest.Mock<any, any>;
|
|
22
|
+
skipPreprocessors: jest.Mock<any, any>;
|
|
23
|
+
saveIgnore: jest.Mock<any, any>;
|
|
24
|
+
skipDecorators: jest.Mock<any, any>;
|
|
25
|
+
ignore: null;
|
|
26
|
+
};
|
|
27
|
+
}, []>;
|
package/lib/__mocks__/utils.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.writeYaml = exports.exitWithError = exports.handleError = exports.getOutputFileName = exports.printLintTotals = exports.printUnusedWarnings = exports.printExecutionTime = exports.getExecutionTime = exports.pluralize = exports.slash = exports.dumpBundle = exports.getFallbackApisOrExit = void 0;
|
|
3
|
+
exports.loadConfigAndHandleErrors = exports.writeYaml = exports.exitWithError = exports.handleError = exports.getOutputFileName = exports.printLintTotals = exports.printUnusedWarnings = exports.printExecutionTime = exports.getExecutionTime = exports.pluralize = exports.slash = exports.dumpBundle = exports.getFallbackApisOrExit = void 0;
|
|
4
|
+
const config_1 = require("../__tests__/fixtures/config");
|
|
4
5
|
exports.getFallbackApisOrExit = jest.fn((entrypoints) => entrypoints.map((path) => ({ path })));
|
|
5
6
|
exports.dumpBundle = jest.fn(() => '');
|
|
6
7
|
exports.slash = jest.fn();
|
|
@@ -13,3 +14,4 @@ exports.getOutputFileName = jest.fn(() => ({ outputFile: 'test.yaml', ext: 'yaml
|
|
|
13
14
|
exports.handleError = jest.fn();
|
|
14
15
|
exports.exitWithError = jest.fn();
|
|
15
16
|
exports.writeYaml = jest.fn();
|
|
17
|
+
exports.loadConfigAndHandleErrors = jest.fn(() => config_1.ConfigFixture);
|
|
@@ -45,11 +45,11 @@ describe('handleLint', () => {
|
|
|
45
45
|
it('should fail if config file does not exist', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
46
46
|
yield lint_1.handleLint(Object.assign(Object.assign({}, argvMock), { config: 'config.yaml' }), versionMock);
|
|
47
47
|
expect(utils_1.exitWithError).toHaveBeenCalledWith('Please, provide valid path to the configuration file');
|
|
48
|
-
expect(
|
|
48
|
+
expect(utils_1.loadConfigAndHandleErrors).toHaveBeenCalledTimes(0);
|
|
49
49
|
}));
|
|
50
|
-
it('should call
|
|
50
|
+
it('should call loadConfigAndHandleErrors and getFallbackApisOrExit', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
51
51
|
yield lint_1.handleLint(argvMock, versionMock);
|
|
52
|
-
expect(
|
|
52
|
+
expect(utils_1.loadConfigAndHandleErrors).toHaveBeenCalledWith({
|
|
53
53
|
configPath: undefined,
|
|
54
54
|
customExtends: undefined,
|
|
55
55
|
processRawConfig: undefined,
|
|
@@ -58,7 +58,7 @@ describe('handleLint', () => {
|
|
|
58
58
|
}));
|
|
59
59
|
it('should call loadConfig with args if such exist', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
60
60
|
yield lint_1.handleLint(Object.assign(Object.assign({}, argvMock), { config: 'redocly.yaml', extends: ['some/path'] }), versionMock);
|
|
61
|
-
expect(
|
|
61
|
+
expect(utils_1.loadConfigAndHandleErrors).toHaveBeenCalledWith({
|
|
62
62
|
configPath: 'redocly.yaml',
|
|
63
63
|
customExtends: ['some/path'],
|
|
64
64
|
processRawConfig: undefined,
|
|
@@ -79,7 +79,7 @@ describe('push', () => {
|
|
|
79
79
|
expect(utils_1.exitWithError).toBeCalledTimes(1);
|
|
80
80
|
}));
|
|
81
81
|
it('push with --files', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
82
|
-
|
|
82
|
+
utils_1.loadConfigAndHandleErrors.mockImplementation(({ files }) => {
|
|
83
83
|
return Object.assign(Object.assign({}, config_1.ConfigFixture), { files });
|
|
84
84
|
});
|
|
85
85
|
//@ts-ignore
|
|
@@ -10,9 +10,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
const utils_1 = require("../utils");
|
|
13
|
+
const openapi_core_1 = require("@redocly/openapi-core");
|
|
13
14
|
const colorette_1 = require("colorette");
|
|
15
|
+
const fs_1 = require("fs");
|
|
16
|
+
const path = require("path");
|
|
14
17
|
jest.mock('os');
|
|
15
18
|
jest.mock('colorette');
|
|
19
|
+
jest.mock('fs');
|
|
16
20
|
describe('isSubdir', () => {
|
|
17
21
|
it('can correctly determine if subdir', () => {
|
|
18
22
|
[
|
|
@@ -52,6 +56,7 @@ describe('pathToFilename', () => {
|
|
|
52
56
|
});
|
|
53
57
|
describe('getFallbackApisOrExit', () => {
|
|
54
58
|
it('should find alias by filename', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
59
|
+
fs_1.existsSync.mockImplementationOnce(() => true);
|
|
55
60
|
const entry = yield utils_1.getFallbackApisOrExit(['./test.yaml'], {
|
|
56
61
|
apis: {
|
|
57
62
|
main: {
|
|
@@ -98,3 +103,96 @@ describe('printConfigLintTotals', () => {
|
|
|
98
103
|
expect(redColoretteMocks).toHaveBeenCalledTimes(0);
|
|
99
104
|
});
|
|
100
105
|
});
|
|
106
|
+
describe('getFallbackApisOrExit', () => {
|
|
107
|
+
const redColoretteMocks = colorette_1.red;
|
|
108
|
+
const yellowColoretteMocks = colorette_1.yellow;
|
|
109
|
+
const apis = {
|
|
110
|
+
main: {
|
|
111
|
+
root: 'someFile.yaml',
|
|
112
|
+
styleguide: {},
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
const config = { apis };
|
|
116
|
+
beforeEach(() => {
|
|
117
|
+
yellowColoretteMocks.mockImplementation((text) => text);
|
|
118
|
+
redColoretteMocks.mockImplementation((text) => text);
|
|
119
|
+
jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
120
|
+
jest.spyOn(process, 'exit').mockImplementation();
|
|
121
|
+
});
|
|
122
|
+
it('should exit with error because no path provided', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
123
|
+
const apisConfig = {
|
|
124
|
+
apis: {},
|
|
125
|
+
};
|
|
126
|
+
yield utils_1.getFallbackApisOrExit([''], apisConfig);
|
|
127
|
+
expect(process.exit).toHaveBeenCalledWith(1);
|
|
128
|
+
}));
|
|
129
|
+
it('should error if file from config do not exist', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
130
|
+
fs_1.existsSync.mockImplementationOnce(() => false);
|
|
131
|
+
yield utils_1.getFallbackApisOrExit(undefined, config);
|
|
132
|
+
expect(process.stderr.write).toHaveBeenCalledWith('\n someFile.yaml does not exist or is invalid. Please provide a valid path. \n\n');
|
|
133
|
+
expect(process.exit).toHaveBeenCalledWith(1);
|
|
134
|
+
}));
|
|
135
|
+
it('should return valid array with results if such file exist', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
136
|
+
fs_1.existsSync.mockImplementationOnce(() => true);
|
|
137
|
+
jest.spyOn(path, 'resolve').mockImplementationOnce((_, path) => path);
|
|
138
|
+
const result = yield utils_1.getFallbackApisOrExit(undefined, config);
|
|
139
|
+
expect(process.stderr.write).toHaveBeenCalledTimes(0);
|
|
140
|
+
expect(process.exit).toHaveBeenCalledTimes(0);
|
|
141
|
+
expect(result).toStrictEqual([
|
|
142
|
+
{
|
|
143
|
+
alias: 'main',
|
|
144
|
+
path: 'someFile.yaml',
|
|
145
|
+
},
|
|
146
|
+
]);
|
|
147
|
+
}));
|
|
148
|
+
it('should exit with error in case if invalid path provided as args', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
149
|
+
const apisConfig = {
|
|
150
|
+
apis: {},
|
|
151
|
+
};
|
|
152
|
+
fs_1.existsSync.mockImplementationOnce(() => false);
|
|
153
|
+
yield utils_1.getFallbackApisOrExit(['someFile.yaml'], apisConfig);
|
|
154
|
+
expect(process.stderr.write).toHaveBeenCalledWith('\n someFile.yaml does not exist or is invalid. Please provide a valid path. \n\n');
|
|
155
|
+
expect(process.exit).toHaveBeenCalledWith(1);
|
|
156
|
+
}));
|
|
157
|
+
it('should exit with error in case if invalid 2 path provided as args', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
158
|
+
const apisConfig = {
|
|
159
|
+
apis: {},
|
|
160
|
+
};
|
|
161
|
+
fs_1.existsSync.mockImplementationOnce(() => false);
|
|
162
|
+
yield utils_1.getFallbackApisOrExit(['someFile.yaml', 'someFile2.yaml'], apisConfig);
|
|
163
|
+
expect(process.stderr.write).lastCalledWith('\n someFile2.yaml does not exist or is invalid. Please provide a valid path. \n\n');
|
|
164
|
+
expect(process.exit).toHaveBeenCalledWith(1);
|
|
165
|
+
}));
|
|
166
|
+
it('should exit with error if only one file exist ', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
167
|
+
const apisStub = Object.assign(Object.assign({}, apis), { notExist: {
|
|
168
|
+
root: 'notExist.yaml',
|
|
169
|
+
styleguide: {},
|
|
170
|
+
} });
|
|
171
|
+
const configStub = { apis: apisStub };
|
|
172
|
+
fs_1.existsSync.mockImplementationOnce((path) => path === 'someFile.yaml');
|
|
173
|
+
yield utils_1.getFallbackApisOrExit(undefined, configStub);
|
|
174
|
+
expect(process.stderr.write).toBeCalledWith('\n notExist.yaml does not exist or is invalid. Please provide a valid path. \n\n');
|
|
175
|
+
expect(process.exit).toHaveBeenCalledWith(1);
|
|
176
|
+
}));
|
|
177
|
+
it('should work ok if it is url passed', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
178
|
+
fs_1.existsSync.mockImplementationOnce(() => false);
|
|
179
|
+
openapi_core_1.isAbsoluteUrl.mockImplementation(() => true);
|
|
180
|
+
const apisConfig = {
|
|
181
|
+
apis: {
|
|
182
|
+
main: {
|
|
183
|
+
root: 'https://someLinkt/petstore.yaml?main',
|
|
184
|
+
styleguide: {},
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
const result = yield utils_1.getFallbackApisOrExit(undefined, apisConfig);
|
|
189
|
+
expect(process.stderr.write).toHaveBeenCalledTimes(0);
|
|
190
|
+
expect(process.exit).toHaveBeenCalledTimes(0);
|
|
191
|
+
expect(result).toStrictEqual([
|
|
192
|
+
{
|
|
193
|
+
alias: 'main',
|
|
194
|
+
path: 'https://someLinkt/petstore.yaml?main',
|
|
195
|
+
},
|
|
196
|
+
]);
|
|
197
|
+
}));
|
|
198
|
+
});
|
|
@@ -15,12 +15,12 @@ const path_1 = require("path");
|
|
|
15
15
|
const fs_1 = require("fs");
|
|
16
16
|
const perf_hooks_1 = require("perf_hooks");
|
|
17
17
|
const utils_1 = require("./utils");
|
|
18
|
-
const utils_2 = require("../../utils");
|
|
19
18
|
const openapi_core_1 = require("@redocly/openapi-core");
|
|
19
|
+
const utils_2 = require("../../utils");
|
|
20
20
|
const handlerBuildCommand = (argv) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
21
|
var _a;
|
|
22
22
|
const startedAt = perf_hooks_1.performance.now();
|
|
23
|
-
const configFromFile = yield
|
|
23
|
+
const configFromFile = yield utils_2.loadConfigAndHandleErrors({ configPath: argv.config });
|
|
24
24
|
const config = openapi_core_1.getMergedConfig(configFromFile, argv.api);
|
|
25
25
|
const apis = yield utils_2.getFallbackApisOrExit(argv.api ? [argv.api] : [], config);
|
|
26
26
|
const { path: pathToApi } = apis[0];
|
|
@@ -36,7 +36,9 @@ const handlerBuildCommand = (argv) => __awaiter(void 0, void 0, void 0, function
|
|
|
36
36
|
const redocCurrentVersion = require('../../../package.json').dependencies.redoc.substring(1); // remove ~
|
|
37
37
|
try {
|
|
38
38
|
const elapsed = utils_2.getExecutionTime(startedAt);
|
|
39
|
-
const api = yield redoc_1.loadAndBundleSpec(
|
|
39
|
+
const api = yield redoc_1.loadAndBundleSpec(openapi_core_1.isAbsoluteUrl(pathToApi)
|
|
40
|
+
? pathToApi
|
|
41
|
+
: path_1.resolve(argv.config ? path_1.dirname(argv.config) : '', pathToApi));
|
|
40
42
|
const pageHTML = yield utils_1.getPageHTML(api, pathToApi, Object.assign(Object.assign({}, options), { redocCurrentVersion }));
|
|
41
43
|
fs_1.mkdirSync(path_1.dirname(options.output), { recursive: true });
|
|
42
44
|
fs_1.writeFileSync(options.output, pageHTML);
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import { Config } from '@redocly/openapi-core';
|
|
1
2
|
import type { BuildDocsOptions } from './types';
|
|
2
|
-
import type { Config } from '@redocly/openapi-core';
|
|
3
3
|
export declare function getObjectOrJSON(openapiOptions: string | Record<string, unknown>, config: Config): JSON | Record<string, unknown> | Config;
|
|
4
4
|
export declare function getPageHTML(api: any, pathToApi: string, { cdn, title, disableGoogleFont, templateFileName, templateOptions, redocOptions, redocCurrentVersion, }: BuildDocsOptions): Promise<string>;
|
|
5
|
-
export declare function isURL(str: string): boolean;
|
|
6
5
|
export declare function sanitizeJSONString(str: string): string;
|
|
7
6
|
export declare function escapeClosingScriptTag(str: string): string;
|
|
8
7
|
export declare function escapeUnicode(str: string): string;
|
|
@@ -9,9 +9,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.escapeUnicode = exports.escapeClosingScriptTag = exports.sanitizeJSONString = exports.
|
|
12
|
+
exports.escapeUnicode = exports.escapeClosingScriptTag = exports.sanitizeJSONString = exports.getPageHTML = exports.getObjectOrJSON = void 0;
|
|
13
13
|
const React = require("react");
|
|
14
14
|
const redoc_1 = require("redoc");
|
|
15
|
+
const openapi_core_1 = require("@redocly/openapi-core");
|
|
15
16
|
const server_1 = require("react-dom/server");
|
|
16
17
|
const styled_components_1 = require("styled-components");
|
|
17
18
|
const handlebars_1 = require("handlebars");
|
|
@@ -51,7 +52,7 @@ exports.getObjectOrJSON = getObjectOrJSON;
|
|
|
51
52
|
function getPageHTML(api, pathToApi, { cdn, title, disableGoogleFont, templateFileName, templateOptions, redocOptions = {}, redocCurrentVersion, }) {
|
|
52
53
|
return __awaiter(this, void 0, void 0, function* () {
|
|
53
54
|
process.stderr.write('Prerendering docs');
|
|
54
|
-
const apiUrl = redocOptions.specUrl || (
|
|
55
|
+
const apiUrl = redocOptions.specUrl || (openapi_core_1.isAbsoluteUrl(pathToApi) ? pathToApi : undefined);
|
|
55
56
|
const store = yield redoc_1.createStore(api, apiUrl, redocOptions);
|
|
56
57
|
const sheet = new styled_components_1.ServerStyleSheet();
|
|
57
58
|
const html = server_1.renderToString(sheet.collectStyles(React.createElement(redoc_1.Redoc, { store })));
|
|
@@ -80,10 +81,6 @@ function getPageHTML(api, pathToApi, { cdn, title, disableGoogleFont, templateFi
|
|
|
80
81
|
});
|
|
81
82
|
}
|
|
82
83
|
exports.getPageHTML = getPageHTML;
|
|
83
|
-
function isURL(str) {
|
|
84
|
-
return /^(https?:)\/\//m.test(str);
|
|
85
|
-
}
|
|
86
|
-
exports.isURL = isURL;
|
|
87
84
|
function sanitizeJSONString(str) {
|
|
88
85
|
return escapeClosingScriptTag(escapeUnicode(str));
|
|
89
86
|
}
|
package/lib/commands/bundle.js
CHANGED
|
@@ -27,11 +27,14 @@ const perf_hooks_1 = require("perf_hooks");
|
|
|
27
27
|
const colorette_1 = require("colorette");
|
|
28
28
|
const fs_1 = require("fs");
|
|
29
29
|
function handleBundle(argv, version) {
|
|
30
|
-
var _a, _b, _c, _d;
|
|
30
|
+
var _a, _b, _c, _d, _e;
|
|
31
31
|
return __awaiter(this, void 0, void 0, function* () {
|
|
32
|
-
const config = yield
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
const config = yield utils_1.loadConfigAndHandleErrors({
|
|
33
|
+
configPath: argv.config,
|
|
34
|
+
customExtends: argv.extends,
|
|
35
|
+
});
|
|
36
|
+
const removeUnusedComponents = argv['remove-unused-components'] ||
|
|
37
|
+
((_c = (_b = (_a = config.rawConfig) === null || _a === void 0 ? void 0 : _a.styleguide) === null || _b === void 0 ? void 0 : _b.decorators) === null || _c === void 0 ? void 0 : _c.hasOwnProperty('remove-unused-components'));
|
|
35
38
|
const apis = yield utils_1.getFallbackApisOrExit(argv.apis, config);
|
|
36
39
|
const totals = { errors: 0, warnings: 0, ignored: 0 };
|
|
37
40
|
const maxProblems = argv['max-problems'];
|
|
@@ -64,13 +67,13 @@ function handleBundle(argv, version) {
|
|
|
64
67
|
utils_1.printLintTotals(fileLintTotals, 2);
|
|
65
68
|
}
|
|
66
69
|
process.stderr.write(colorette_1.gray(`bundling ${path}...\n`));
|
|
67
|
-
const
|
|
70
|
+
const _f = yield openapi_core_1.bundle({
|
|
68
71
|
config: resolvedConfig,
|
|
69
72
|
ref: path,
|
|
70
73
|
dereference: argv.dereferenced,
|
|
71
74
|
removeUnusedComponents,
|
|
72
75
|
keepUrlRefs: argv['keep-url-references'],
|
|
73
|
-
}), { bundle: result, problems } =
|
|
76
|
+
}), { bundle: result, problems } = _f, meta = __rest(_f, ["bundle", "problems"]);
|
|
74
77
|
const fileTotals = openapi_core_1.getTotals(problems);
|
|
75
78
|
const { outputFile, ext } = utils_1.getOutputFileName(path, apis.length, argv.output, argv.ext);
|
|
76
79
|
if (fileTotals.errors === 0 || argv.force) {
|
|
@@ -112,7 +115,7 @@ function handleBundle(argv, version) {
|
|
|
112
115
|
else {
|
|
113
116
|
process.stderr.write(`📦 Created a bundle for ${colorette_1.blue(path)} at ${colorette_1.blue(outputFile)} ${colorette_1.green(elapsed)}.\n`);
|
|
114
117
|
}
|
|
115
|
-
const removedCount = (
|
|
118
|
+
const removedCount = (_e = (_d = meta.visitorsData) === null || _d === void 0 ? void 0 : _d['remove-unused-components']) === null || _e === void 0 ? void 0 : _e.removedCount;
|
|
116
119
|
if (removedCount) {
|
|
117
120
|
process.stderr.write(colorette_1.gray(`🧹 Removed ${removedCount} unused components.\n`));
|
|
118
121
|
}
|
package/lib/commands/join.js
CHANGED
|
@@ -37,7 +37,7 @@ function handleJoin(argv, packageVersion) {
|
|
|
37
37
|
if (usedTagsOptions.length > 1) {
|
|
38
38
|
return utils_1.exitWithError(`You use ${colorette_1.yellow(usedTagsOptions.join(', '))} together.\nPlease choose only one! \n\n`);
|
|
39
39
|
}
|
|
40
|
-
const config = yield
|
|
40
|
+
const config = yield utils_1.loadConfigAndHandleErrors();
|
|
41
41
|
const apis = yield utils_1.getFallbackApisOrExit(argv.apis, config);
|
|
42
42
|
const externalRefResolver = new openapi_core_1.BaseResolver(config.resolve);
|
|
43
43
|
const documents = yield Promise.all(apis.map(({ path }) => externalRefResolver.resolveDocument(null, path, true)));
|
package/lib/commands/lint.js
CHANGED
|
@@ -19,7 +19,7 @@ function handleLint(argv, version) {
|
|
|
19
19
|
if (argv.config && !openapi_core_1.doesYamlFileExist(argv.config)) {
|
|
20
20
|
return utils_1.exitWithError('Please, provide valid path to the configuration file');
|
|
21
21
|
}
|
|
22
|
-
const config = yield
|
|
22
|
+
const config = yield utils_1.loadConfigAndHandleErrors({
|
|
23
23
|
configPath: argv.config,
|
|
24
24
|
customExtends: argv.extends,
|
|
25
25
|
processRawConfig: lintConfigCallback(argv, version),
|
package/lib/commands/login.js
CHANGED
|
@@ -19,7 +19,7 @@ function promptClientToken(domain) {
|
|
|
19
19
|
exports.promptClientToken = promptClientToken;
|
|
20
20
|
function handleLogin(argv) {
|
|
21
21
|
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
-
const region = argv.region || (yield
|
|
22
|
+
const region = argv.region || (yield utils_1.loadConfigAndHandleErrors()).region;
|
|
23
23
|
const client = new openapi_core_1.RedoclyClient(region);
|
|
24
24
|
const clientToken = yield promptClientToken(client.domain);
|
|
25
25
|
process.stdout.write(colorette_1.gray('\n Logging in...\n'));
|
|
@@ -94,7 +94,7 @@ function previewDocs(argv) {
|
|
|
94
94
|
});
|
|
95
95
|
function reloadConfig() {
|
|
96
96
|
return __awaiter(this, void 0, void 0, function* () {
|
|
97
|
-
const config = yield
|
|
97
|
+
const config = yield utils_1.loadConfigAndHandleErrors({ configPath: argv.config });
|
|
98
98
|
const redoclyClient = new openapi_core_1.RedoclyClient();
|
|
99
99
|
isAuthorizedWithRedocly = yield redoclyClient.isAuthorizedWithRedocly();
|
|
100
100
|
const resolvedConfig = openapi_core_1.getMergedConfig(config, argv.api);
|
package/lib/commands/push.js
CHANGED
|
@@ -33,7 +33,7 @@ const login_1 = require("./login");
|
|
|
33
33
|
const DEFAULT_VERSION = 'latest';
|
|
34
34
|
function handlePush(argv) {
|
|
35
35
|
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
-
const config = yield
|
|
36
|
+
const config = yield utils_1.loadConfigAndHandleErrors({ region: argv.region, files: argv.files });
|
|
37
37
|
const client = new openapi_core_1.RedoclyClient(config.region);
|
|
38
38
|
const isAuthorized = yield client.isAuthorizedWithRedoclyByRegion();
|
|
39
39
|
if (!isAuthorized) {
|
package/lib/commands/stats.js
CHANGED
|
@@ -54,7 +54,7 @@ function printStats(statsAccumulator, api, format) {
|
|
|
54
54
|
}
|
|
55
55
|
function handleStats(argv) {
|
|
56
56
|
return __awaiter(this, void 0, void 0, function* () {
|
|
57
|
-
const config = yield
|
|
57
|
+
const config = yield utils_1.loadConfigAndHandleErrors({ configPath: argv.config });
|
|
58
58
|
const [{ path }] = yield utils_1.getFallbackApisOrExit(argv.api ? [argv.api] : [], config);
|
|
59
59
|
const externalRefResolver = new openapi_core_1.BaseResolver(config.resolve);
|
|
60
60
|
const { bundle: document } = yield openapi_core_1.bundle({ config, ref: path });
|
package/lib/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BundleOutputFormat, OutputFormat, Region } from '@redocly/openapi-core';
|
|
1
|
+
import type { BundleOutputFormat, OutputFormat, Region, Config } from '@redocly/openapi-core';
|
|
2
2
|
export declare type Totals = {
|
|
3
3
|
errors: number;
|
|
4
4
|
warnings: number;
|
|
@@ -23,3 +23,4 @@ export declare type Skips = {
|
|
|
23
23
|
'skip-decorator'?: string[];
|
|
24
24
|
'skip-preprocessor'?: string[];
|
|
25
25
|
};
|
|
26
|
+
export declare type ConfigApis = Pick<Config, 'apis' | 'configFile'>;
|
package/lib/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { BundleOutputFormat,
|
|
2
|
-
import { Totals, Entrypoint } from './types';
|
|
3
|
-
export declare function getFallbackApisOrExit(argsApis: string[] | undefined, config:
|
|
1
|
+
import { BundleOutputFormat, StyleguideConfig, RawConfig, Region, Config } from '@redocly/openapi-core';
|
|
2
|
+
import { Totals, Entrypoint, ConfigApis } from './types';
|
|
3
|
+
export declare function getFallbackApisOrExit(argsApis: string[] | undefined, config: ConfigApis): Promise<Entrypoint[]>;
|
|
4
4
|
export declare function getExecutionTime(startedAt: number): string;
|
|
5
5
|
export declare function printExecutionTime(commandName: string, startedAt: number, api: string): void;
|
|
6
6
|
export declare function pathToFilename(path: string, pathSeparator: string): string;
|
|
@@ -28,3 +28,10 @@ export declare function exitWithError(message: string): void;
|
|
|
28
28
|
* Checks if dir is subdir of parent
|
|
29
29
|
*/
|
|
30
30
|
export declare function isSubdir(parent: string, dir: string): boolean;
|
|
31
|
+
export declare function loadConfigAndHandleErrors(options?: {
|
|
32
|
+
configPath?: string;
|
|
33
|
+
customExtends?: string[];
|
|
34
|
+
processRawConfig?: (rawConfig: RawConfig) => void | Promise<void>;
|
|
35
|
+
files?: string[];
|
|
36
|
+
region?: Region;
|
|
37
|
+
}): Promise<Config>;
|
package/lib/utils.js
CHANGED
|
@@ -9,13 +9,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.isSubdir = exports.exitWithError = exports.printUnusedWarnings = exports.getOutputFileName = exports.printConfigLintTotals = exports.printLintTotals = exports.handleError = exports.pluralize = exports.writeYaml = exports.readYaml = exports.promptUser = exports.saveBundle = exports.dumpBundle = exports.CircularJSONNotSupportedError = exports.escapeLanguageName = exports.pathToFilename = exports.printExecutionTime = exports.getExecutionTime = exports.getFallbackApisOrExit = void 0;
|
|
12
|
+
exports.loadConfigAndHandleErrors = exports.isSubdir = exports.exitWithError = exports.printUnusedWarnings = exports.getOutputFileName = exports.printConfigLintTotals = exports.printLintTotals = exports.handleError = exports.pluralize = exports.writeYaml = exports.readYaml = exports.promptUser = exports.saveBundle = exports.dumpBundle = exports.CircularJSONNotSupportedError = exports.escapeLanguageName = exports.pathToFilename = exports.printExecutionTime = exports.getExecutionTime = exports.getFallbackApisOrExit = void 0;
|
|
13
13
|
const path_1 = require("path");
|
|
14
14
|
const colorette_1 = require("colorette");
|
|
15
15
|
const perf_hooks_1 = require("perf_hooks");
|
|
16
16
|
const glob = require("glob-promise");
|
|
17
17
|
const fs = require("fs");
|
|
18
|
-
const path = require("path");
|
|
19
18
|
const readline = require("readline");
|
|
20
19
|
const stream_1 = require("stream");
|
|
21
20
|
const openapi_core_1 = require("@redocly/openapi-core");
|
|
@@ -25,13 +24,13 @@ function getFallbackApisOrExit(argsApis, config) {
|
|
|
25
24
|
const { apis } = config;
|
|
26
25
|
const shouldFallbackToAllDefinitions = !isNotEmptyArray(argsApis) && apis && Object.keys(apis).length > 0;
|
|
27
26
|
const res = shouldFallbackToAllDefinitions
|
|
28
|
-
?
|
|
29
|
-
path: path_1.resolve(getConfigDirectory(config), root),
|
|
30
|
-
alias,
|
|
31
|
-
}))
|
|
27
|
+
? fallbackToAllDefinitions(apis, config)
|
|
32
28
|
: yield expandGlobsInEntrypoints(argsApis, config);
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
const filteredInvalidEntrypoints = res.filter(({ path }) => !isApiPathValid(path));
|
|
30
|
+
if (isNotEmptyArray(filteredInvalidEntrypoints)) {
|
|
31
|
+
for (const { path } of filteredInvalidEntrypoints) {
|
|
32
|
+
process.stderr.write(colorette_1.yellow(`\n ${path_1.relative(process.cwd(), path)} ${colorette_1.red(`does not exist or is invalid. Please provide a valid path. \n\n`)}`));
|
|
33
|
+
}
|
|
35
34
|
process.exit(1);
|
|
36
35
|
}
|
|
37
36
|
return res;
|
|
@@ -44,6 +43,19 @@ function getConfigDirectory(config) {
|
|
|
44
43
|
function isNotEmptyArray(args) {
|
|
45
44
|
return Array.isArray(args) && !!args.length;
|
|
46
45
|
}
|
|
46
|
+
function isApiPathValid(apiPath) {
|
|
47
|
+
if (!apiPath.trim()) {
|
|
48
|
+
exitWithError('Path cannot be empty.');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
return fs.existsSync(apiPath) || openapi_core_1.isAbsoluteUrl(apiPath) ? apiPath : undefined;
|
|
52
|
+
}
|
|
53
|
+
function fallbackToAllDefinitions(apis, config) {
|
|
54
|
+
return Object.entries(apis).map(([alias, { root }]) => ({
|
|
55
|
+
path: openapi_core_1.isAbsoluteUrl(root) ? root : path_1.resolve(getConfigDirectory(config), root),
|
|
56
|
+
alias,
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
47
59
|
function getAliasOrPath(config, aliasOrPath) {
|
|
48
60
|
var _a, _b, _c;
|
|
49
61
|
return config.apis[aliasOrPath]
|
|
@@ -52,14 +64,14 @@ function getAliasOrPath(config, aliasOrPath) {
|
|
|
52
64
|
path: aliasOrPath,
|
|
53
65
|
// find alias by path, take the first match
|
|
54
66
|
alias: (_c = (_b = Object.entries(config.apis).find(([_alias, api]) => {
|
|
55
|
-
return
|
|
67
|
+
return path_1.resolve(api.root) === path_1.resolve(aliasOrPath);
|
|
56
68
|
})) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : undefined,
|
|
57
69
|
};
|
|
58
70
|
}
|
|
59
71
|
function expandGlobsInEntrypoints(args, config) {
|
|
60
72
|
return __awaiter(this, void 0, void 0, function* () {
|
|
61
73
|
return (yield Promise.all(args.map((aliasOrPath) => __awaiter(this, void 0, void 0, function* () {
|
|
62
|
-
return glob.hasMagic(aliasOrPath)
|
|
74
|
+
return glob.hasMagic(aliasOrPath) && !openapi_core_1.isAbsoluteUrl(aliasOrPath)
|
|
63
75
|
? (yield glob(aliasOrPath)).map((g) => getAliasOrPath(config, g))
|
|
64
76
|
: getAliasOrPath(config, aliasOrPath);
|
|
65
77
|
})))).flat();
|
|
@@ -118,7 +130,7 @@ function dumpBundle(obj, format, dereference) {
|
|
|
118
130
|
}
|
|
119
131
|
exports.dumpBundle = dumpBundle;
|
|
120
132
|
function saveBundle(filename, output) {
|
|
121
|
-
fs.mkdirSync(
|
|
133
|
+
fs.mkdirSync(path_1.dirname(filename), { recursive: true });
|
|
122
134
|
fs.writeFileSync(filename, output);
|
|
123
135
|
}
|
|
124
136
|
exports.saveBundle = saveBundle;
|
|
@@ -277,7 +289,19 @@ exports.exitWithError = exitWithError;
|
|
|
277
289
|
* Checks if dir is subdir of parent
|
|
278
290
|
*/
|
|
279
291
|
function isSubdir(parent, dir) {
|
|
280
|
-
const
|
|
281
|
-
return !!
|
|
292
|
+
const relativePath = path_1.relative(parent, dir);
|
|
293
|
+
return !!relativePath && !/^..($|\/)/.test(relativePath) && !path_1.isAbsolute(relativePath);
|
|
282
294
|
}
|
|
283
295
|
exports.isSubdir = isSubdir;
|
|
296
|
+
function loadConfigAndHandleErrors(options = {}) {
|
|
297
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
298
|
+
try {
|
|
299
|
+
return yield openapi_core_1.loadConfig(options);
|
|
300
|
+
}
|
|
301
|
+
catch (e) {
|
|
302
|
+
exitWithError(e.message);
|
|
303
|
+
return new openapi_core_1.Config({ apis: {}, styleguide: {} });
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
exports.loadConfigAndHandleErrors = loadConfigAndHandleErrors;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/cli",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.118",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"Roman Hotsiy <roman@redoc.ly> (https://redoc.ly/)"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@redocly/openapi-core": "1.0.0-beta.
|
|
36
|
+
"@redocly/openapi-core": "1.0.0-beta.118",
|
|
37
37
|
"assert-node-version": "^1.0.3",
|
|
38
38
|
"chokidar": "^3.5.1",
|
|
39
39
|
"colorette": "^1.2.0",
|
|
@@ -29,6 +29,7 @@ export const findConfig = jest.fn();
|
|
|
29
29
|
export const doesYamlFileExist = jest.fn();
|
|
30
30
|
export const bundleDocument = jest.fn(() => Promise.resolve({ problems: {} }));
|
|
31
31
|
export const detectOpenAPI = jest.fn();
|
|
32
|
+
export const isAbsoluteUrl = jest.fn();
|
|
32
33
|
|
|
33
34
|
export class BaseResolver {
|
|
34
35
|
cache = new Map<string, Promise<Document | ResolveError>>();
|
package/src/__mocks__/utils.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ConfigFixture } from '../__tests__/fixtures/config';
|
|
2
|
+
|
|
1
3
|
export const getFallbackApisOrExit = jest.fn((entrypoints) =>
|
|
2
4
|
entrypoints.map((path: string) => ({ path }))
|
|
3
5
|
);
|
|
@@ -12,3 +14,4 @@ export const getOutputFileName = jest.fn(() => ({ outputFile: 'test.yaml', ext:
|
|
|
12
14
|
export const handleError = jest.fn();
|
|
13
15
|
export const exitWithError = jest.fn();
|
|
14
16
|
export const writeYaml = jest.fn();
|
|
17
|
+
export const loadConfigAndHandleErrors = jest.fn(() => ConfigFixture);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { handleLint, LintOptions } from '../../commands/lint';
|
|
2
2
|
import {
|
|
3
|
-
loadConfig,
|
|
4
3
|
getMergedConfig,
|
|
5
4
|
lint,
|
|
6
5
|
getTotals,
|
|
@@ -13,6 +12,7 @@ import {
|
|
|
13
12
|
printUnusedWarnings,
|
|
14
13
|
handleError,
|
|
15
14
|
exitWithError,
|
|
15
|
+
loadConfigAndHandleErrors,
|
|
16
16
|
} from '../../utils';
|
|
17
17
|
import { ConfigFixture } from '../fixtures/config';
|
|
18
18
|
import { performance } from 'perf_hooks';
|
|
@@ -58,12 +58,12 @@ describe('handleLint', () => {
|
|
|
58
58
|
expect(exitWithError).toHaveBeenCalledWith(
|
|
59
59
|
'Please, provide valid path to the configuration file'
|
|
60
60
|
);
|
|
61
|
-
expect(
|
|
61
|
+
expect(loadConfigAndHandleErrors).toHaveBeenCalledTimes(0);
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
-
it('should call
|
|
64
|
+
it('should call loadConfigAndHandleErrors and getFallbackApisOrExit', async () => {
|
|
65
65
|
await handleLint(argvMock, versionMock);
|
|
66
|
-
expect(
|
|
66
|
+
expect(loadConfigAndHandleErrors).toHaveBeenCalledWith({
|
|
67
67
|
configPath: undefined,
|
|
68
68
|
customExtends: undefined,
|
|
69
69
|
processRawConfig: undefined,
|
|
@@ -76,7 +76,7 @@ describe('handleLint', () => {
|
|
|
76
76
|
{ ...argvMock, config: 'redocly.yaml', extends: ['some/path'] },
|
|
77
77
|
versionMock
|
|
78
78
|
);
|
|
79
|
-
expect(
|
|
79
|
+
expect(loadConfigAndHandleErrors).toHaveBeenCalledWith({
|
|
80
80
|
configPath: 'redocly.yaml',
|
|
81
81
|
customExtends: ['some/path'],
|
|
82
82
|
processRawConfig: undefined,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
|
-
import { Config, getMergedConfig
|
|
3
|
-
import { exitWithError } from '../../utils';
|
|
2
|
+
import { Config, getMergedConfig } from '@redocly/openapi-core';
|
|
3
|
+
import { exitWithError, loadConfigAndHandleErrors } from '../../utils';
|
|
4
4
|
import { getApiRoot, getDestinationProps, handlePush, transformPush } from '../../commands/push';
|
|
5
5
|
import { ConfigFixture } from '../fixtures/config';
|
|
6
6
|
|
|
@@ -79,7 +79,7 @@ describe('push', () => {
|
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
it('push with --files', async () => {
|
|
82
|
-
(
|
|
82
|
+
(loadConfigAndHandleErrors as jest.Mock).mockImplementation(({ files }) => {
|
|
83
83
|
return { ...ConfigFixture, files };
|
|
84
84
|
});
|
|
85
85
|
|