@redocly/cli 1.0.0-beta.129 → 1.0.0-beta.130
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/__tests__/fetch-with-timeout.test.d.ts +1 -0
- package/lib/__tests__/fetch-with-timeout.test.js +38 -0
- package/lib/__tests__/utils.test.js +42 -11
- package/lib/__tests__/wrapper.test.js +10 -0
- package/lib/fetch-with-timeout.d.ts +2 -0
- package/lib/fetch-with-timeout.js +25 -0
- package/lib/update-version-notifier.js +2 -2
- package/lib/utils.d.ts +1 -0
- package/lib/utils.js +17 -8
- package/lib/wrapper.js +1 -1
- package/package.json +8 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const fetch_with_timeout_1 = require("../fetch-with-timeout");
|
|
13
|
+
const node_fetch_1 = require("node-fetch");
|
|
14
|
+
jest.mock('node-fetch');
|
|
15
|
+
describe('fetchWithTimeout', () => {
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
jest.clearAllMocks();
|
|
18
|
+
});
|
|
19
|
+
it('should use bare node-fetch if AbortController is not available', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
20
|
+
// @ts-ignore
|
|
21
|
+
global.AbortController = undefined;
|
|
22
|
+
// @ts-ignore
|
|
23
|
+
global.setTimeout = jest.fn();
|
|
24
|
+
yield fetch_with_timeout_1.default('url', { method: 'GET' });
|
|
25
|
+
expect(node_fetch_1.default).toHaveBeenCalledWith('url', { method: 'GET' });
|
|
26
|
+
expect(global.setTimeout).toHaveBeenCalledTimes(0);
|
|
27
|
+
}));
|
|
28
|
+
it('should call node-fetch with signal if AbortController is available', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
29
|
+
global.AbortController = jest.fn().mockImplementation(() => ({ signal: 'something' }));
|
|
30
|
+
// @ts-ignore
|
|
31
|
+
global.setTimeout = jest.fn();
|
|
32
|
+
global.clearTimeout = jest.fn();
|
|
33
|
+
yield fetch_with_timeout_1.default('url');
|
|
34
|
+
expect(global.setTimeout).toHaveBeenCalledTimes(1);
|
|
35
|
+
expect(node_fetch_1.default).toHaveBeenCalledWith('url', { signal: 'something' });
|
|
36
|
+
expect(global.clearTimeout).toHaveBeenCalledTimes(1);
|
|
37
|
+
}));
|
|
38
|
+
});
|
|
@@ -399,16 +399,23 @@ describe('cleanArgs', () => {
|
|
|
399
399
|
beforeEach(() => {
|
|
400
400
|
// @ts-ignore
|
|
401
401
|
openapi_core_1.isAbsoluteUrl = jest.requireActual('@redocly/openapi-core').isAbsoluteUrl;
|
|
402
|
+
// @ts-ignore
|
|
403
|
+
fs_1.existsSync = (value) => jest.requireActual('fs').existsSync(path.resolve(__dirname, value));
|
|
404
|
+
// @ts-ignore
|
|
405
|
+
fs_1.statSync = (value) => jest.requireActual('fs').statSync(path.resolve(__dirname, value));
|
|
406
|
+
});
|
|
407
|
+
afterEach(() => {
|
|
408
|
+
jest.clearAllMocks();
|
|
402
409
|
});
|
|
403
410
|
it('should remove potentially sensitive data from args', () => {
|
|
404
411
|
const testArgs = {
|
|
405
|
-
config: '
|
|
406
|
-
apis: ['main@v1', 'openapi.yaml', 'http://some.url/openapi.yaml'],
|
|
412
|
+
config: './fixtures/redocly.yaml',
|
|
413
|
+
apis: ['main@v1', 'fixtures/openapi.yaml', 'http://some.url/openapi.yaml'],
|
|
407
414
|
format: 'codeframe',
|
|
408
415
|
};
|
|
409
416
|
expect(utils_1.cleanArgs(testArgs)).toEqual({
|
|
410
|
-
config: '
|
|
411
|
-
apis: ['
|
|
417
|
+
config: 'file-yaml',
|
|
418
|
+
apis: ['api-name@api-version', 'file-yaml', 'http://url'],
|
|
412
419
|
format: 'codeframe',
|
|
413
420
|
});
|
|
414
421
|
});
|
|
@@ -417,22 +424,46 @@ describe('cleanArgs', () => {
|
|
|
417
424
|
destination: '@org/name@version',
|
|
418
425
|
};
|
|
419
426
|
expect(utils_1.cleanArgs(testArgs)).toEqual({
|
|
420
|
-
destination: '
|
|
427
|
+
destination: '@organization/api-name@api-version',
|
|
421
428
|
});
|
|
422
429
|
});
|
|
423
430
|
});
|
|
424
431
|
describe('cleanRawInput', () => {
|
|
425
|
-
|
|
432
|
+
beforeEach(() => {
|
|
426
433
|
// @ts-ignore
|
|
427
434
|
openapi_core_1.isAbsoluteUrl = jest.requireActual('@redocly/openapi-core').isAbsoluteUrl;
|
|
435
|
+
// @ts-ignore
|
|
436
|
+
fs_1.existsSync = (value) => jest.requireActual('fs').existsSync(path.resolve(__dirname, value));
|
|
437
|
+
// @ts-ignore
|
|
438
|
+
fs_1.statSync = (value) => jest.requireActual('fs').statSync(path.resolve(__dirname, value));
|
|
439
|
+
});
|
|
440
|
+
afterEach(() => {
|
|
441
|
+
jest.clearAllMocks();
|
|
442
|
+
});
|
|
443
|
+
it('should remove potentially sensitive data from raw CLI input', () => {
|
|
428
444
|
const rawInput = [
|
|
429
445
|
'redocly',
|
|
430
|
-
'
|
|
431
|
-
'
|
|
432
|
-
'openapi.yaml',
|
|
446
|
+
'bundle',
|
|
447
|
+
'api-name@api-version',
|
|
448
|
+
'./fixtures/openapi.yaml',
|
|
433
449
|
'http://some.url/openapi.yaml',
|
|
434
|
-
'--config=
|
|
450
|
+
'--config=fixtures/redocly.yaml',
|
|
451
|
+
'--output',
|
|
452
|
+
'fixtures',
|
|
453
|
+
];
|
|
454
|
+
expect(utils_1.cleanRawInput(rawInput)).toEqual('redocly bundle api-name@api-version file-yaml http://url --config=file-yaml --output folder');
|
|
455
|
+
});
|
|
456
|
+
it('should preserve safe data from raw CLI input', () => {
|
|
457
|
+
const rawInput = [
|
|
458
|
+
'redocly',
|
|
459
|
+
'lint',
|
|
460
|
+
'./fixtures/openapi.json',
|
|
461
|
+
'--format',
|
|
462
|
+
'stylish',
|
|
463
|
+
'--extends=minimal',
|
|
464
|
+
'--skip-rule',
|
|
465
|
+
'operation-4xx-response',
|
|
435
466
|
];
|
|
436
|
-
expect(utils_1.cleanRawInput(rawInput)).toEqual('redocly lint
|
|
467
|
+
expect(utils_1.cleanRawInput(rawInput)).toEqual('redocly lint file-json --format stylish --extends=minimal --skip-rule operation-4xx-response');
|
|
437
468
|
});
|
|
438
469
|
});
|
|
@@ -13,6 +13,7 @@ const utils_1 = require("../utils");
|
|
|
13
13
|
const process = require("process");
|
|
14
14
|
const wrapper_1 = require("../wrapper");
|
|
15
15
|
const lint_1 = require("../commands/lint");
|
|
16
|
+
const push_1 = require("../commands/push");
|
|
16
17
|
jest.mock('node-fetch');
|
|
17
18
|
jest.mock('../utils', () => ({
|
|
18
19
|
sendTelemetry: jest.fn(),
|
|
@@ -44,4 +45,13 @@ describe('commandWrapper', () => {
|
|
|
44
45
|
expect(lint_1.handleLint).toHaveBeenCalledTimes(1);
|
|
45
46
|
expect(utils_1.sendTelemetry).toHaveBeenCalledTimes(0);
|
|
46
47
|
}));
|
|
48
|
+
it('should pass files from arguments to config', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
49
|
+
const filesToPush = ['test1.yaml', 'test2.yaml'];
|
|
50
|
+
const loadConfigMock = utils_1.loadConfigAndHandleErrors;
|
|
51
|
+
const argv = {
|
|
52
|
+
files: filesToPush,
|
|
53
|
+
};
|
|
54
|
+
yield wrapper_1.commandWrapper(push_1.handlePush)(argv);
|
|
55
|
+
expect(loadConfigMock).toHaveBeenCalledWith(expect.objectContaining({ files: filesToPush }));
|
|
56
|
+
}));
|
|
47
57
|
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const node_fetch_1 = require("node-fetch");
|
|
13
|
+
const TIMEOUT = 3000;
|
|
14
|
+
exports.default = (url, options = {}) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
|
+
if (!global.AbortController) {
|
|
16
|
+
return node_fetch_1.default(url, options);
|
|
17
|
+
}
|
|
18
|
+
const controller = new AbortController();
|
|
19
|
+
const timeout = setTimeout(() => {
|
|
20
|
+
controller.abort();
|
|
21
|
+
}, TIMEOUT);
|
|
22
|
+
const res = yield node_fetch_1.default(url, Object.assign({ signal: controller.signal }, options));
|
|
23
|
+
clearTimeout(timeout);
|
|
24
|
+
return res;
|
|
25
|
+
});
|
|
@@ -15,7 +15,7 @@ const os_1 = require("os");
|
|
|
15
15
|
const path_1 = require("path");
|
|
16
16
|
const fs_1 = require("fs");
|
|
17
17
|
const semver_1 = require("semver");
|
|
18
|
-
const
|
|
18
|
+
const fetch_with_timeout_1 = require("./fetch-with-timeout");
|
|
19
19
|
const colorette_1 = require("colorette");
|
|
20
20
|
const utils_1 = require("./utils");
|
|
21
21
|
_a = require('../package.json'), exports.version = _a.version, exports.name = _a.name;
|
|
@@ -41,7 +41,7 @@ exports.notifyUpdateCliVersion = notifyUpdateCliVersion;
|
|
|
41
41
|
const isNewVersionAvailable = (current, latest) => semver_1.compare(current, latest) < 0;
|
|
42
42
|
const getLatestVersion = (packageName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
43
43
|
const latestUrl = `http://registry.npmjs.org/${packageName}/latest`;
|
|
44
|
-
const response = yield
|
|
44
|
+
const response = yield fetch_with_timeout_1.default(latestUrl);
|
|
45
45
|
const info = yield response.json();
|
|
46
46
|
return info.version;
|
|
47
47
|
});
|
package/lib/utils.d.ts
CHANGED
package/lib/utils.js
CHANGED
|
@@ -21,7 +21,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
21
21
|
};
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
23
|
exports.cleanRawInput = exports.cleanArgs = exports.sendTelemetry = exports.cleanColors = exports.checkIfRulesetExist = exports.sortTopLevelKeysForOas = exports.loadConfigAndHandleErrors = exports.isSubdir = exports.exitWithError = exports.printUnusedWarnings = exports.getOutputFileName = exports.printConfigLintTotals = exports.printLintTotals = exports.HandledError = exports.handleError = exports.pluralize = exports.writeYaml = exports.readYaml = exports.promptUser = exports.saveBundle = exports.dumpBundle = exports.CircularJSONNotSupportedError = exports.langToExt = exports.escapeLanguageName = exports.pathToFilename = exports.printExecutionTime = exports.getExecutionTime = exports.getFallbackApisOrExit = void 0;
|
|
24
|
-
const
|
|
24
|
+
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");
|
|
@@ -417,7 +417,6 @@ function sendTelemetry(argv, exit_code, has_config) {
|
|
|
417
417
|
const { _: [command], $0: _ } = argv, args = __rest(argv, ["_", "$0"]);
|
|
418
418
|
const event_time = new Date().toISOString();
|
|
419
419
|
const redoclyClient = new openapi_core_1.RedoclyClient();
|
|
420
|
-
const node_version = process.version;
|
|
421
420
|
const logged_in = yield redoclyClient.isAuthorizedWithRedoclyByRegion();
|
|
422
421
|
const data = {
|
|
423
422
|
event: 'cli_command',
|
|
@@ -425,14 +424,15 @@ function sendTelemetry(argv, exit_code, has_config) {
|
|
|
425
424
|
logged_in,
|
|
426
425
|
command,
|
|
427
426
|
arguments: cleanArgs(args),
|
|
428
|
-
node_version,
|
|
427
|
+
node_version: process.version,
|
|
429
428
|
version: update_version_notifier_1.version,
|
|
430
429
|
exit_code,
|
|
431
430
|
environment: process.env.REDOCLY_ENVIRONMENT,
|
|
431
|
+
environment_ci: process.env.CI,
|
|
432
432
|
raw_input: cleanRawInput(process.argv.slice(2)),
|
|
433
433
|
has_config,
|
|
434
434
|
};
|
|
435
|
-
yield
|
|
435
|
+
yield fetch_with_timeout_1.default(`https://api.redocly.com/registry/telemetry/cli`, {
|
|
436
436
|
method: 'POST',
|
|
437
437
|
headers: {
|
|
438
438
|
'content-type': 'application/json',
|
|
@@ -446,18 +446,27 @@ function sendTelemetry(argv, exit_code, has_config) {
|
|
|
446
446
|
});
|
|
447
447
|
}
|
|
448
448
|
exports.sendTelemetry = sendTelemetry;
|
|
449
|
+
function isFile(value) {
|
|
450
|
+
return fs.existsSync(value) && fs.statSync(value).isFile();
|
|
451
|
+
}
|
|
452
|
+
function isDirectory(value) {
|
|
453
|
+
return fs.existsSync(value) && fs.statSync(value).isDirectory();
|
|
454
|
+
}
|
|
449
455
|
function cleanString(value) {
|
|
450
456
|
if (!value) {
|
|
451
457
|
return value;
|
|
452
458
|
}
|
|
453
459
|
if (openapi_core_1.isAbsoluteUrl(value)) {
|
|
454
|
-
return value.split('://')[0] + '
|
|
460
|
+
return value.split('://')[0] + '://url';
|
|
461
|
+
}
|
|
462
|
+
if (isFile(value)) {
|
|
463
|
+
return value.replace(/.+\.([^.]+)$/, (_, ext) => 'file-' + ext);
|
|
455
464
|
}
|
|
456
|
-
if (
|
|
457
|
-
return
|
|
465
|
+
if (isDirectory(value)) {
|
|
466
|
+
return 'folder';
|
|
458
467
|
}
|
|
459
468
|
if (push_1.DESTINATION_REGEX.test(value)) {
|
|
460
|
-
return value.
|
|
469
|
+
return value.startsWith('@') ? '@organization/api-name@api-version' : 'api-name@api-version';
|
|
461
470
|
}
|
|
462
471
|
return value;
|
|
463
472
|
}
|
package/lib/wrapper.js
CHANGED
|
@@ -27,7 +27,7 @@ function commandWrapper(commandHandler) {
|
|
|
27
27
|
configPath: argv.config,
|
|
28
28
|
customExtends: argv.extends,
|
|
29
29
|
region: argv.region,
|
|
30
|
-
files: argv.
|
|
30
|
+
files: argv.files,
|
|
31
31
|
processRawConfig: lint_1.lintConfigCallback(argv, update_version_notifier_1.version),
|
|
32
32
|
}));
|
|
33
33
|
telemetry = config.telemetry;
|
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.130",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -33,23 +33,25 @@
|
|
|
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.130",
|
|
37
37
|
"assert-node-version": "^1.0.3",
|
|
38
38
|
"chokidar": "^3.5.1",
|
|
39
39
|
"colorette": "^1.2.0",
|
|
40
40
|
"glob": "^7.1.6",
|
|
41
41
|
"glob-promise": "^3.4.0",
|
|
42
42
|
"handlebars": "^4.7.6",
|
|
43
|
-
"mobx": "^6.3.2",
|
|
44
43
|
"portfinder": "^1.0.26",
|
|
45
|
-
"react": "^17.0.1",
|
|
46
|
-
"react-dom": "^17.0.1",
|
|
47
44
|
"redoc": "~2.0.0",
|
|
48
45
|
"semver": "^7.5.2",
|
|
49
46
|
"simple-websocket": "^9.0.0",
|
|
50
|
-
"styled-components": "5.3.3",
|
|
51
47
|
"yargs": "17.0.1"
|
|
52
48
|
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"mobx": "^6.0.4",
|
|
51
|
+
"react": "^16.8.4 || ^17.0.0",
|
|
52
|
+
"react-dom": "^16.8.4 || ^17.0.0",
|
|
53
|
+
"styled-components": "^4.1.1 || ^5.1.1"
|
|
54
|
+
},
|
|
53
55
|
"devDependencies": {
|
|
54
56
|
"@types/configstore": "^5.0.1",
|
|
55
57
|
"@types/react": "^17.0.8",
|