@redocly/cli 1.0.0-beta.99 → 1.0.0-rc.2
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/README.md +83 -22
- package/bin/cli.js +1 -1
- package/lib/__mocks__/@redocly/openapi-core.d.ts +53 -1
- package/lib/__mocks__/@redocly/openapi-core.js +56 -5
- package/lib/__mocks__/documents.d.ts +92 -0
- package/lib/__mocks__/documents.js +63 -0
- package/lib/__mocks__/fs.d.ts +2 -0
- package/lib/__mocks__/fs.js +3 -1
- package/lib/__mocks__/perf_hooks.d.ts +4 -0
- package/lib/__mocks__/perf_hooks.js +6 -0
- package/lib/__mocks__/redoc.d.ts +7 -0
- package/lib/__mocks__/redoc.js +5 -0
- package/lib/__mocks__/utils.d.ts +26 -4
- package/lib/__mocks__/utils.js +8 -3
- package/lib/__tests__/commands/build-docs.test.d.ts +1 -0
- package/lib/__tests__/commands/build-docs.test.js +59 -0
- package/lib/__tests__/commands/bundle.test.js +66 -30
- package/lib/__tests__/commands/join.test.d.ts +1 -0
- package/lib/__tests__/commands/join.test.js +85 -0
- package/lib/__tests__/commands/lint.test.d.ts +1 -0
- package/lib/__tests__/commands/lint.test.js +149 -0
- package/lib/__tests__/commands/push-region.test.js +5 -4
- package/lib/__tests__/commands/push.test.js +254 -39
- package/lib/__tests__/fetch-with-timeout.test.d.ts +1 -0
- package/lib/__tests__/fetch-with-timeout.test.js +38 -0
- package/lib/__tests__/fixtures/config.d.ts +22 -0
- package/lib/__tests__/fixtures/config.js +24 -0
- package/lib/__tests__/utils.test.js +429 -1
- package/lib/__tests__/wrapper.test.d.ts +1 -0
- package/lib/__tests__/wrapper.test.js +57 -0
- package/lib/commands/build-docs/index.d.ts +3 -0
- package/lib/commands/build-docs/index.js +50 -0
- package/{src/commands/preview-docs/preview-server/default.hbs → lib/commands/build-docs/template.hbs} +2 -3
- package/lib/commands/build-docs/types.d.ts +23 -0
- package/lib/commands/build-docs/types.js +2 -0
- package/lib/commands/build-docs/utils.d.ts +7 -0
- package/lib/commands/build-docs/utils.js +99 -0
- package/lib/commands/bundle.d.ts +10 -12
- package/lib/commands/bundle.js +25 -24
- package/lib/commands/join.d.ts +12 -3
- package/lib/commands/join.js +295 -109
- package/lib/commands/lint.d.ts +11 -8
- package/lib/commands/lint.js +49 -19
- package/lib/commands/login.d.ts +5 -3
- package/lib/commands/login.js +2 -2
- package/lib/commands/preview-docs/index.d.ts +6 -6
- package/lib/commands/preview-docs/index.js +30 -20
- package/lib/commands/preview-docs/preview-server/oauth2-redirect.html +1 -1
- package/lib/commands/preview-docs/preview-server/preview-server.js +5 -4
- package/lib/commands/preview-docs/preview-server/server.d.ts +1 -1
- package/lib/commands/push.d.ts +21 -10
- package/lib/commands/push.js +110 -63
- package/lib/commands/split/__tests__/index.test.js +10 -8
- package/lib/commands/split/index.d.ts +5 -3
- package/lib/commands/split/index.js +15 -24
- package/lib/commands/split/types.d.ts +11 -11
- package/lib/commands/split/types.js +19 -19
- package/lib/commands/stats.d.ts +7 -4
- package/lib/commands/stats.js +13 -12
- package/lib/fetch-with-timeout.d.ts +2 -0
- package/lib/fetch-with-timeout.js +30 -0
- package/lib/index.js +194 -40
- package/lib/js-utils.d.ts +1 -0
- package/lib/js-utils.js +9 -3
- package/lib/types.d.ts +17 -1
- package/lib/update-version-notifier.d.ts +3 -0
- package/lib/update-version-notifier.js +105 -0
- package/lib/utils.d.ts +38 -5
- package/lib/utils.js +270 -41
- package/lib/wrapper.d.ts +4 -0
- package/lib/wrapper.js +52 -0
- package/package.json +18 -8
- package/src/__mocks__/@redocly/openapi-core.ts +0 -26
- package/src/__mocks__/fs.ts +0 -4
- package/src/__mocks__/utils.ts +0 -11
- package/src/__tests__/commands/bundle.test.ts +0 -120
- package/src/__tests__/commands/push-region.test.ts +0 -51
- package/src/__tests__/commands/push.test.ts +0 -158
- package/src/__tests__/utils.test.ts +0 -50
- package/src/assert-node-version.ts +0 -8
- package/src/commands/bundle.ts +0 -180
- package/src/commands/join.ts +0 -488
- package/src/commands/lint.ts +0 -110
- package/src/commands/login.ts +0 -21
- package/src/commands/preview-docs/index.ts +0 -188
- package/src/commands/preview-docs/preview-server/hot.js +0 -42
- package/src/commands/preview-docs/preview-server/oauth2-redirect.html +0 -21
- package/src/commands/preview-docs/preview-server/preview-server.ts +0 -155
- package/src/commands/preview-docs/preview-server/server.ts +0 -91
- package/src/commands/push.ts +0 -357
- package/src/commands/split/__tests__/fixtures/samples.json +0 -61
- package/src/commands/split/__tests__/fixtures/spec.json +0 -70
- package/src/commands/split/__tests__/fixtures/webhooks.json +0 -88
- package/src/commands/split/__tests__/index.test.ts +0 -117
- package/src/commands/split/index.ts +0 -349
- package/src/commands/split/types.ts +0 -73
- package/src/commands/stats.ts +0 -115
- package/src/index.ts +0 -316
- package/src/js-utils.ts +0 -12
- package/src/types.ts +0 -13
- package/src/utils.ts +0 -307
- package/tsconfig.json +0 -9
- package/tsconfig.tsbuildinfo +0 -1
package/lib/utils.js
CHANGED
|
@@ -8,52 +8,85 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
12
|
+
var t = {};
|
|
13
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
14
|
+
t[p] = s[p];
|
|
15
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
16
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
17
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
18
|
+
t[p[i]] = s[p[i]];
|
|
19
|
+
}
|
|
20
|
+
return t;
|
|
21
|
+
};
|
|
11
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.isSubdir = exports.exitWithError = exports.printUnusedWarnings = exports.getOutputFileName = 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.
|
|
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 fetch_with_timeout_1 = require("./fetch-with-timeout");
|
|
13
25
|
const path_1 = require("path");
|
|
14
26
|
const colorette_1 = require("colorette");
|
|
15
27
|
const perf_hooks_1 = require("perf_hooks");
|
|
16
28
|
const glob = require("glob-promise");
|
|
17
29
|
const fs = require("fs");
|
|
18
|
-
const path = require("path");
|
|
19
30
|
const readline = require("readline");
|
|
20
31
|
const stream_1 = require("stream");
|
|
21
32
|
const openapi_core_1 = require("@redocly/openapi-core");
|
|
22
33
|
const types_1 = require("./types");
|
|
23
|
-
|
|
34
|
+
const utils_1 = require("@redocly/openapi-core/lib/utils");
|
|
35
|
+
const update_version_notifier_1 = require("./update-version-notifier");
|
|
36
|
+
const push_1 = require("./commands/push");
|
|
37
|
+
function getFallbackApisOrExit(argsApis, config) {
|
|
24
38
|
return __awaiter(this, void 0, void 0, function* () {
|
|
25
39
|
const { apis } = config;
|
|
26
|
-
const shouldFallbackToAllDefinitions = !isNotEmptyArray(
|
|
40
|
+
const shouldFallbackToAllDefinitions = !isNotEmptyArray(argsApis) && apis && Object.keys(apis).length > 0;
|
|
27
41
|
const res = shouldFallbackToAllDefinitions
|
|
28
|
-
?
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
42
|
+
? fallbackToAllDefinitions(apis, config)
|
|
43
|
+
: yield expandGlobsInEntrypoints(argsApis, config);
|
|
44
|
+
const filteredInvalidEntrypoints = res.filter(({ path }) => !isApiPathValid(path));
|
|
45
|
+
if (isNotEmptyArray(filteredInvalidEntrypoints)) {
|
|
46
|
+
for (const { path } of filteredInvalidEntrypoints) {
|
|
47
|
+
process.stderr.write(colorette_1.yellow(`\n${path_1.relative(process.cwd(), path)} ${colorette_1.red(`does not exist or is invalid.\n\n`)}`));
|
|
48
|
+
}
|
|
49
|
+
exitWithError('Please provide a valid path.');
|
|
36
50
|
}
|
|
37
51
|
return res;
|
|
38
52
|
});
|
|
39
53
|
}
|
|
40
|
-
exports.
|
|
54
|
+
exports.getFallbackApisOrExit = getFallbackApisOrExit;
|
|
41
55
|
function getConfigDirectory(config) {
|
|
42
56
|
return config.configFile ? path_1.dirname(config.configFile) : process.cwd();
|
|
43
57
|
}
|
|
44
58
|
function isNotEmptyArray(args) {
|
|
45
59
|
return Array.isArray(args) && !!args.length;
|
|
46
60
|
}
|
|
61
|
+
function isApiPathValid(apiPath) {
|
|
62
|
+
if (!apiPath.trim()) {
|
|
63
|
+
exitWithError('Path cannot be empty.');
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
return fs.existsSync(apiPath) || openapi_core_1.isAbsoluteUrl(apiPath) ? apiPath : undefined;
|
|
67
|
+
}
|
|
68
|
+
function fallbackToAllDefinitions(apis, config) {
|
|
69
|
+
return Object.entries(apis).map(([alias, { root }]) => ({
|
|
70
|
+
path: openapi_core_1.isAbsoluteUrl(root) ? root : path_1.resolve(getConfigDirectory(config), root),
|
|
71
|
+
alias,
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
47
74
|
function getAliasOrPath(config, aliasOrPath) {
|
|
48
|
-
var _a;
|
|
75
|
+
var _a, _b, _c;
|
|
49
76
|
return config.apis[aliasOrPath]
|
|
50
77
|
? { path: (_a = config.apis[aliasOrPath]) === null || _a === void 0 ? void 0 : _a.root, alias: aliasOrPath }
|
|
51
|
-
: {
|
|
78
|
+
: {
|
|
79
|
+
path: aliasOrPath,
|
|
80
|
+
// find alias by path, take the first match
|
|
81
|
+
alias: (_c = (_b = Object.entries(config.apis).find(([_alias, api]) => {
|
|
82
|
+
return path_1.resolve(api.root) === path_1.resolve(aliasOrPath);
|
|
83
|
+
})) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : undefined,
|
|
84
|
+
};
|
|
52
85
|
}
|
|
53
86
|
function expandGlobsInEntrypoints(args, config) {
|
|
54
87
|
return __awaiter(this, void 0, void 0, function* () {
|
|
55
88
|
return (yield Promise.all(args.map((aliasOrPath) => __awaiter(this, void 0, void 0, function* () {
|
|
56
|
-
return glob.hasMagic(aliasOrPath)
|
|
89
|
+
return glob.hasMagic(aliasOrPath) && !openapi_core_1.isAbsoluteUrl(aliasOrPath)
|
|
57
90
|
? (yield glob(aliasOrPath)).map((g) => getAliasOrPath(config, g))
|
|
58
91
|
: getAliasOrPath(config, aliasOrPath);
|
|
59
92
|
})))).flat();
|
|
@@ -65,9 +98,9 @@ function getExecutionTime(startedAt) {
|
|
|
65
98
|
: `${Math.ceil(perf_hooks_1.performance.now() - startedAt)}ms`;
|
|
66
99
|
}
|
|
67
100
|
exports.getExecutionTime = getExecutionTime;
|
|
68
|
-
function printExecutionTime(commandName, startedAt,
|
|
101
|
+
function printExecutionTime(commandName, startedAt, api) {
|
|
69
102
|
const elapsed = getExecutionTime(startedAt);
|
|
70
|
-
process.stderr.write(colorette_1.gray(`\n${
|
|
103
|
+
process.stderr.write(colorette_1.gray(`\n${api}: ${commandName} processed in ${elapsed}\n\n`));
|
|
71
104
|
}
|
|
72
105
|
exports.printExecutionTime = printExecutionTime;
|
|
73
106
|
function pathToFilename(path, pathSeparator) {
|
|
@@ -79,12 +112,23 @@ function pathToFilename(path, pathSeparator) {
|
|
|
79
112
|
}
|
|
80
113
|
exports.pathToFilename = pathToFilename;
|
|
81
114
|
function escapeLanguageName(lang) {
|
|
82
|
-
return lang
|
|
83
|
-
.replace(/#/g, "_sharp")
|
|
84
|
-
.replace(/\//, '_')
|
|
85
|
-
.replace(/\s/g, '');
|
|
115
|
+
return lang.replace(/#/g, '_sharp').replace(/\//, '_').replace(/\s/g, '');
|
|
86
116
|
}
|
|
87
117
|
exports.escapeLanguageName = escapeLanguageName;
|
|
118
|
+
function langToExt(lang) {
|
|
119
|
+
const langObj = {
|
|
120
|
+
php: '.php',
|
|
121
|
+
'c#': '.cs',
|
|
122
|
+
shell: '.sh',
|
|
123
|
+
curl: '.sh',
|
|
124
|
+
bash: '.sh',
|
|
125
|
+
javascript: '.js',
|
|
126
|
+
js: '.js',
|
|
127
|
+
python: '.py',
|
|
128
|
+
};
|
|
129
|
+
return langObj[lang.toLowerCase()];
|
|
130
|
+
}
|
|
131
|
+
exports.langToExt = langToExt;
|
|
88
132
|
class CircularJSONNotSupportedError extends Error {
|
|
89
133
|
constructor(originalError) {
|
|
90
134
|
super(originalError.message);
|
|
@@ -109,12 +153,13 @@ function dumpBundle(obj, format, dereference) {
|
|
|
109
153
|
else {
|
|
110
154
|
return openapi_core_1.stringifyYaml(obj, {
|
|
111
155
|
noRefs: !dereference,
|
|
156
|
+
lineWidth: -1,
|
|
112
157
|
});
|
|
113
158
|
}
|
|
114
159
|
}
|
|
115
160
|
exports.dumpBundle = dumpBundle;
|
|
116
161
|
function saveBundle(filename, output) {
|
|
117
|
-
fs.mkdirSync(
|
|
162
|
+
fs.mkdirSync(path_1.dirname(filename), { recursive: true });
|
|
118
163
|
fs.writeFileSync(filename, output);
|
|
119
164
|
}
|
|
120
165
|
exports.saveBundle = saveBundle;
|
|
@@ -158,6 +203,7 @@ function writeYaml(data, filename, noRefs = false) {
|
|
|
158
203
|
process.stderr.write(content);
|
|
159
204
|
return;
|
|
160
205
|
}
|
|
206
|
+
fs.mkdirSync(path_1.dirname(filename), { recursive: true });
|
|
161
207
|
fs.writeFileSync(filename, content);
|
|
162
208
|
}
|
|
163
209
|
exports.writeYaml = writeYaml;
|
|
@@ -170,25 +216,31 @@ function pluralize(label, num) {
|
|
|
170
216
|
}
|
|
171
217
|
exports.pluralize = pluralize;
|
|
172
218
|
function handleError(e, ref) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
219
|
+
var _a, _b;
|
|
220
|
+
switch (e.constructor) {
|
|
221
|
+
case HandledError: {
|
|
222
|
+
throw e;
|
|
223
|
+
}
|
|
224
|
+
case openapi_core_1.ResolveError:
|
|
225
|
+
return exitWithError(`Failed to resolve api definition at ${ref}:\n\n - ${e.message}.`);
|
|
226
|
+
case openapi_core_1.YamlParseError:
|
|
227
|
+
return exitWithError(`Failed to parse api definition at ${ref}:\n\n - ${e.message}.`);
|
|
178
228
|
// TODO: codeframe
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
process.stderr.write(colorette_1.red(`Detected circular reference which can't be converted to JSON.\n`) +
|
|
183
|
-
`Try to use ${colorette_1.blue('yaml')} output or remove ${colorette_1.blue('--dereferenced')}.\n\n`);
|
|
229
|
+
case CircularJSONNotSupportedError: {
|
|
230
|
+
return exitWithError(`Detected circular reference which can't be converted to JSON.\n` +
|
|
231
|
+
`Try to use ${colorette_1.blue('yaml')} output or remove ${colorette_1.blue('--dereferenced')}.`);
|
|
184
232
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
233
|
+
case SyntaxError:
|
|
234
|
+
return exitWithError(`Syntax error: ${e.message} ${(_b = (_a = e.stack) === null || _a === void 0 ? void 0 : _a.split('\n\n')) === null || _b === void 0 ? void 0 : _b[0]}`);
|
|
235
|
+
default: {
|
|
236
|
+
exitWithError(`Something went wrong when processing ${ref}:\n\n - ${e.message}.`);
|
|
188
237
|
}
|
|
189
238
|
}
|
|
190
239
|
}
|
|
191
240
|
exports.handleError = handleError;
|
|
241
|
+
class HandledError extends Error {
|
|
242
|
+
}
|
|
243
|
+
exports.HandledError = HandledError;
|
|
192
244
|
function printLintTotals(totals, definitionsCount) {
|
|
193
245
|
const ignored = totals.ignored
|
|
194
246
|
? colorette_1.yellow(`${totals.ignored} ${pluralize('problem is', totals.ignored)} explicitly ignored.\n\n`)
|
|
@@ -206,11 +258,22 @@ function printLintTotals(totals, definitionsCount) {
|
|
|
206
258
|
process.stderr.write(colorette_1.green(`Woohoo! Your OpenAPI ${pluralize('definition is', definitionsCount)} valid. 🎉\n${ignored}`));
|
|
207
259
|
}
|
|
208
260
|
if (totals.errors > 0) {
|
|
209
|
-
process.stderr.write(colorette_1.gray(`run \`
|
|
261
|
+
process.stderr.write(colorette_1.gray(`run \`redocly lint --generate-ignore-file\` to add all problems to the ignore file.\n`));
|
|
210
262
|
}
|
|
211
263
|
process.stderr.write('\n');
|
|
212
264
|
}
|
|
213
265
|
exports.printLintTotals = printLintTotals;
|
|
266
|
+
function printConfigLintTotals(totals) {
|
|
267
|
+
if (totals.errors > 0) {
|
|
268
|
+
process.stderr.write(colorette_1.red(`❌ Your config has ${totals.errors} ${pluralize('error', totals.errors)}${totals.warnings > 0
|
|
269
|
+
? ` and ${totals.warnings} ${pluralize('warning', totals.warnings)}`
|
|
270
|
+
: ''}.\n`));
|
|
271
|
+
}
|
|
272
|
+
else if (totals.warnings > 0) {
|
|
273
|
+
process.stderr.write(colorette_1.yellow(`You have ${totals.warnings} ${pluralize('warning', totals.warnings)}.\n`));
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
exports.printConfigLintTotals = printConfigLintTotals;
|
|
214
277
|
function getOutputFileName(entrypoint, entries, output, ext) {
|
|
215
278
|
if (!output) {
|
|
216
279
|
return { outputFile: 'stdout', ext: ext || 'yaml' };
|
|
@@ -248,20 +311,186 @@ function printUnusedWarnings(config) {
|
|
|
248
311
|
process.stderr.write(colorette_1.yellow(`[WARNING] Unused decorators found in ${colorette_1.blue(config.configFile || '')}: ${decorators.join(', ')}.\n`));
|
|
249
312
|
}
|
|
250
313
|
if (rules.length || preprocessors.length) {
|
|
251
|
-
process.stderr.write(`Check the spelling and verify
|
|
314
|
+
process.stderr.write(`Check the spelling and verify the added plugin prefix.\n`);
|
|
252
315
|
}
|
|
253
316
|
}
|
|
254
317
|
exports.printUnusedWarnings = printUnusedWarnings;
|
|
255
318
|
function exitWithError(message) {
|
|
256
319
|
process.stderr.write(colorette_1.red(message) + '\n\n');
|
|
257
|
-
|
|
320
|
+
throw new HandledError(message);
|
|
258
321
|
}
|
|
259
322
|
exports.exitWithError = exitWithError;
|
|
260
323
|
/**
|
|
261
324
|
* Checks if dir is subdir of parent
|
|
262
325
|
*/
|
|
263
326
|
function isSubdir(parent, dir) {
|
|
264
|
-
const
|
|
265
|
-
return !!
|
|
327
|
+
const relativePath = path_1.relative(parent, dir);
|
|
328
|
+
return !!relativePath && !/^..($|\/)/.test(relativePath) && !path_1.isAbsolute(relativePath);
|
|
266
329
|
}
|
|
267
330
|
exports.isSubdir = isSubdir;
|
|
331
|
+
function loadConfigAndHandleErrors(options = {}) {
|
|
332
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
333
|
+
try {
|
|
334
|
+
return yield openapi_core_1.loadConfig(options);
|
|
335
|
+
}
|
|
336
|
+
catch (e) {
|
|
337
|
+
handleError(e, '');
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
exports.loadConfigAndHandleErrors = loadConfigAndHandleErrors;
|
|
342
|
+
function sortTopLevelKeysForOas(document) {
|
|
343
|
+
if ('swagger' in document) {
|
|
344
|
+
return sortOas2Keys(document);
|
|
345
|
+
}
|
|
346
|
+
return sortOas3Keys(document);
|
|
347
|
+
}
|
|
348
|
+
exports.sortTopLevelKeysForOas = sortTopLevelKeysForOas;
|
|
349
|
+
function sortOas2Keys(document) {
|
|
350
|
+
const orderedKeys = [
|
|
351
|
+
'swagger',
|
|
352
|
+
'info',
|
|
353
|
+
'host',
|
|
354
|
+
'basePath',
|
|
355
|
+
'schemes',
|
|
356
|
+
'consumes',
|
|
357
|
+
'produces',
|
|
358
|
+
'security',
|
|
359
|
+
'tags',
|
|
360
|
+
'externalDocs',
|
|
361
|
+
'paths',
|
|
362
|
+
'definitions',
|
|
363
|
+
'parameters',
|
|
364
|
+
'responses',
|
|
365
|
+
'securityDefinitions',
|
|
366
|
+
];
|
|
367
|
+
const result = {};
|
|
368
|
+
for (const key of orderedKeys) {
|
|
369
|
+
if (document.hasOwnProperty(key)) {
|
|
370
|
+
result[key] = document[key];
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
// merge any other top-level keys (e.g. vendor extensions)
|
|
374
|
+
return Object.assign(result, document);
|
|
375
|
+
}
|
|
376
|
+
function sortOas3Keys(document) {
|
|
377
|
+
const orderedKeys = [
|
|
378
|
+
'openapi',
|
|
379
|
+
'info',
|
|
380
|
+
'jsonSchemaDialect',
|
|
381
|
+
'servers',
|
|
382
|
+
'security',
|
|
383
|
+
'tags',
|
|
384
|
+
'externalDocs',
|
|
385
|
+
'paths',
|
|
386
|
+
'webhooks',
|
|
387
|
+
'x-webhooks',
|
|
388
|
+
'components',
|
|
389
|
+
];
|
|
390
|
+
const result = {};
|
|
391
|
+
for (const key of orderedKeys) {
|
|
392
|
+
if (document.hasOwnProperty(key)) {
|
|
393
|
+
result[key] = document[key];
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
// merge any other top-level keys (e.g. vendor extensions)
|
|
397
|
+
return Object.assign(result, document);
|
|
398
|
+
}
|
|
399
|
+
function checkIfRulesetExist(rules) {
|
|
400
|
+
const ruleset = Object.assign(Object.assign(Object.assign({}, rules.oas2), rules.oas3_0), rules.oas3_0);
|
|
401
|
+
if (utils_1.isEmptyObject(ruleset)) {
|
|
402
|
+
exitWithError('⚠️ No rules were configured. Learn how to configure rules: https://redocly.com/docs/cli/rules/');
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
exports.checkIfRulesetExist = checkIfRulesetExist;
|
|
406
|
+
function cleanColors(input) {
|
|
407
|
+
// eslint-disable-next-line no-control-regex
|
|
408
|
+
return input.replace(/\x1b\[\d+m/g, '');
|
|
409
|
+
}
|
|
410
|
+
exports.cleanColors = cleanColors;
|
|
411
|
+
function sendTelemetry(argv, exit_code, has_config) {
|
|
412
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
413
|
+
try {
|
|
414
|
+
if (!argv) {
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
const { _: [command], $0: _ } = argv, args = __rest(argv, ["_", "$0"]);
|
|
418
|
+
const event_time = new Date().toISOString();
|
|
419
|
+
const redoclyClient = new openapi_core_1.RedoclyClient();
|
|
420
|
+
const logged_in = redoclyClient.hasTokens();
|
|
421
|
+
const data = {
|
|
422
|
+
event: 'cli_command',
|
|
423
|
+
event_time,
|
|
424
|
+
logged_in,
|
|
425
|
+
command,
|
|
426
|
+
arguments: cleanArgs(args),
|
|
427
|
+
node_version: process.version,
|
|
428
|
+
version: update_version_notifier_1.version,
|
|
429
|
+
exit_code,
|
|
430
|
+
environment: process.env.REDOCLY_ENVIRONMENT,
|
|
431
|
+
environment_ci: process.env.CI,
|
|
432
|
+
raw_input: cleanRawInput(process.argv.slice(2)),
|
|
433
|
+
has_config,
|
|
434
|
+
};
|
|
435
|
+
yield fetch_with_timeout_1.default(`https://api.redocly.com/registry/telemetry/cli`, {
|
|
436
|
+
method: 'POST',
|
|
437
|
+
headers: {
|
|
438
|
+
'content-type': 'application/json',
|
|
439
|
+
},
|
|
440
|
+
body: JSON.stringify(data),
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
catch (err) {
|
|
444
|
+
// Do nothing.
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
}
|
|
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
|
+
}
|
|
455
|
+
function cleanString(value) {
|
|
456
|
+
if (!value) {
|
|
457
|
+
return value;
|
|
458
|
+
}
|
|
459
|
+
if (openapi_core_1.isAbsoluteUrl(value)) {
|
|
460
|
+
return value.split('://')[0] + '://url';
|
|
461
|
+
}
|
|
462
|
+
if (isFile(value)) {
|
|
463
|
+
return value.replace(/.+\.([^.]+)$/, (_, ext) => 'file-' + ext);
|
|
464
|
+
}
|
|
465
|
+
if (isDirectory(value)) {
|
|
466
|
+
return 'folder';
|
|
467
|
+
}
|
|
468
|
+
if (push_1.DESTINATION_REGEX.test(value)) {
|
|
469
|
+
return value.startsWith('@') ? '@organization/api-name@api-version' : 'api-name@api-version';
|
|
470
|
+
}
|
|
471
|
+
return value;
|
|
472
|
+
}
|
|
473
|
+
function cleanArgs(args) {
|
|
474
|
+
const keysToClean = ['organization', 'o'];
|
|
475
|
+
const result = {};
|
|
476
|
+
for (const [key, value] of Object.entries(args)) {
|
|
477
|
+
if (keysToClean.includes(key)) {
|
|
478
|
+
result[key] = '***';
|
|
479
|
+
}
|
|
480
|
+
else if (typeof value === 'string') {
|
|
481
|
+
result[key] = cleanString(value);
|
|
482
|
+
}
|
|
483
|
+
else if (Array.isArray(value)) {
|
|
484
|
+
result[key] = value.map(cleanString);
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
result[key] = value;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return result;
|
|
491
|
+
}
|
|
492
|
+
exports.cleanArgs = cleanArgs;
|
|
493
|
+
function cleanRawInput(argv) {
|
|
494
|
+
return argv.map((entry) => entry.split('=').map(cleanString).join('=')).join(' ');
|
|
495
|
+
}
|
|
496
|
+
exports.cleanRawInput = cleanRawInput;
|
package/lib/wrapper.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Config } from '@redocly/openapi-core';
|
|
2
|
+
import type { Arguments } from 'yargs';
|
|
3
|
+
import type { CommandOptions } from './types';
|
|
4
|
+
export declare function commandWrapper<T extends CommandOptions>(commandHandler: (argv: T, config: Config, version: string) => Promise<void>): (argv: Arguments<T>) => Promise<void>;
|
package/lib/wrapper.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
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
|
+
exports.commandWrapper = void 0;
|
|
13
|
+
const openapi_core_1 = require("@redocly/openapi-core");
|
|
14
|
+
const update_version_notifier_1 = require("./update-version-notifier");
|
|
15
|
+
const utils_1 = require("./utils");
|
|
16
|
+
const lint_1 = require("./commands/lint");
|
|
17
|
+
function commandWrapper(commandHandler) {
|
|
18
|
+
return (argv) => __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
let code = 2;
|
|
20
|
+
let hasConfig;
|
|
21
|
+
let telemetry;
|
|
22
|
+
try {
|
|
23
|
+
if (argv.config && !openapi_core_1.doesYamlFileExist(argv.config)) {
|
|
24
|
+
utils_1.exitWithError('Please, provide valid path to the configuration file');
|
|
25
|
+
}
|
|
26
|
+
const config = (yield utils_1.loadConfigAndHandleErrors({
|
|
27
|
+
configPath: argv.config,
|
|
28
|
+
customExtends: argv.extends,
|
|
29
|
+
region: argv.region,
|
|
30
|
+
files: argv.files,
|
|
31
|
+
processRawConfig: lint_1.lintConfigCallback(argv, update_version_notifier_1.version),
|
|
32
|
+
}));
|
|
33
|
+
telemetry = config.telemetry;
|
|
34
|
+
hasConfig = !config.styleguide.recommendedFallback;
|
|
35
|
+
code = 1;
|
|
36
|
+
yield commandHandler(argv, config, update_version_notifier_1.version);
|
|
37
|
+
code = 0;
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
// Do nothing
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
if (process.env.REDOCLY_TELEMETRY !== 'off' && telemetry !== 'off') {
|
|
44
|
+
yield utils_1.sendTelemetry(argv, code, hasConfig);
|
|
45
|
+
}
|
|
46
|
+
process.once('beforeExit', () => {
|
|
47
|
+
process.exit(code);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
exports.commandWrapper = commandWrapper;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/cli",
|
|
3
|
-
"version": "1.0.0-
|
|
3
|
+
"version": "1.0.0-rc.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"engineStrict": true,
|
|
14
14
|
"scripts": {
|
|
15
15
|
"compile": "tsc",
|
|
16
|
-
"copy-assets": "cp src/commands/preview-docs/preview-server/default.hbs lib/commands/preview-docs/preview-server/default.hbs && cp src/commands/preview-docs/preview-server/hot.js lib/commands/preview-docs/preview-server/hot.js && cp src/commands/preview-docs/preview-server/oauth2-redirect.html lib/commands/preview-docs/preview-server/oauth2-redirect.html",
|
|
16
|
+
"copy-assets": "cp src/commands/preview-docs/preview-server/default.hbs lib/commands/preview-docs/preview-server/default.hbs && cp src/commands/preview-docs/preview-server/hot.js lib/commands/preview-docs/preview-server/hot.js && cp src/commands/preview-docs/preview-server/oauth2-redirect.html lib/commands/preview-docs/preview-server/oauth2-redirect.html && cp src/commands/build-docs/template.hbs lib/commands/build-docs/template.hbs && cp ../../README.md .",
|
|
17
|
+
"prepack": "npm run copy-assets",
|
|
17
18
|
"prepublishOnly": "npm run copy-assets"
|
|
18
19
|
},
|
|
19
20
|
"repository": {
|
|
@@ -30,12 +31,10 @@
|
|
|
30
31
|
"oas"
|
|
31
32
|
],
|
|
32
33
|
"contributors": [
|
|
33
|
-
"
|
|
34
|
-
"Roman Hotsiy <roman@redoc.ly> (https://redoc.ly/)",
|
|
35
|
-
"Andriy Leliv <andriy@redoc.ly> (https://redoc.ly/)"
|
|
34
|
+
"Roman Hotsiy <roman@redoc.ly> (https://redoc.ly/)"
|
|
36
35
|
],
|
|
37
36
|
"dependencies": {
|
|
38
|
-
"@redocly/openapi-core": "1.0.0-
|
|
37
|
+
"@redocly/openapi-core": "1.0.0-rc.2",
|
|
39
38
|
"assert-node-version": "^1.0.3",
|
|
40
39
|
"chokidar": "^3.5.1",
|
|
41
40
|
"colorette": "^1.2.0",
|
|
@@ -43,11 +42,22 @@
|
|
|
43
42
|
"glob-promise": "^3.4.0",
|
|
44
43
|
"handlebars": "^4.7.6",
|
|
45
44
|
"portfinder": "^1.0.26",
|
|
45
|
+
"redoc": "~2.0.0",
|
|
46
|
+
"semver": "^7.5.2",
|
|
46
47
|
"simple-websocket": "^9.0.0",
|
|
47
|
-
"yargs": "17.0.1"
|
|
48
|
+
"yargs": "17.0.1",
|
|
49
|
+
"mobx": "^6.0.4",
|
|
50
|
+
"react": "^17.0.0",
|
|
51
|
+
"react-dom": "^17.0.0",
|
|
52
|
+
"styled-components": "^5.1.1"
|
|
48
53
|
},
|
|
49
54
|
"devDependencies": {
|
|
50
|
-
"@types/
|
|
55
|
+
"@types/configstore": "^5.0.1",
|
|
56
|
+
"@types/react": "^17.0.8",
|
|
57
|
+
"@types/react-dom": "^17.0.5",
|
|
58
|
+
"@types/styled-components": "^5.1.1",
|
|
59
|
+
"@types/yargs": "17.0.5",
|
|
60
|
+
"@types/semver": "^7.5.0",
|
|
51
61
|
"typescript": "^4.0.3"
|
|
52
62
|
}
|
|
53
63
|
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export const __redoclyClient = {
|
|
2
|
-
isAuthorizedWithRedocly: jest.fn().mockResolvedValue(true),
|
|
3
|
-
isAuthorizedWithRedoclyByRegion: jest.fn().mockResolvedValue(true),
|
|
4
|
-
login: jest.fn(),
|
|
5
|
-
registryApi: {
|
|
6
|
-
setAccessTokens: jest.fn(),
|
|
7
|
-
authStatus: jest.fn(),
|
|
8
|
-
prepareFileUpload: jest.fn().mockResolvedValue({
|
|
9
|
-
signedUploadUrl: 'signedUploadUrl',
|
|
10
|
-
filePath: 'filePath',
|
|
11
|
-
}),
|
|
12
|
-
pushApi: jest.fn(),
|
|
13
|
-
},
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export const RedoclyClient = jest.fn(() => __redoclyClient);
|
|
17
|
-
export const loadConfig = jest.fn(() => ({
|
|
18
|
-
configFile: null,
|
|
19
|
-
lint: { skipRules: jest.fn(), skipPreprocessors: jest.fn(), skipDecorators: jest.fn() },
|
|
20
|
-
}));
|
|
21
|
-
export const getMergedConfig = jest.fn();
|
|
22
|
-
export const lint = jest.fn();
|
|
23
|
-
export const bundle = jest.fn(() => ({ bundle: { parsed: null }, problems: null }));
|
|
24
|
-
export const getTotals = jest.fn(() => ({ errors: 0 }));
|
|
25
|
-
export const formatProblems = jest.fn();
|
|
26
|
-
export const slash = jest.fn();
|
package/src/__mocks__/fs.ts
DELETED
package/src/__mocks__/utils.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export const getFallbackEntryPointsOrExit = jest.fn((entrypoints) => entrypoints.map(() => ({ path: '' })));
|
|
2
|
-
export const getTotals = jest.fn(() => ({ errors: 0 }));
|
|
3
|
-
export const dumpBundle = jest.fn(() => '');
|
|
4
|
-
export const slash = jest.fn();
|
|
5
|
-
export const pluralize = jest.fn();
|
|
6
|
-
export const getExecutionTime = jest.fn();
|
|
7
|
-
export const printExecutionTime = jest.fn();
|
|
8
|
-
export const printUnusedWarnings = jest.fn();
|
|
9
|
-
export const printLintTotals = jest.fn();
|
|
10
|
-
export const getOutputFileName = jest.fn(() => ({ outputFile: 'test.yaml', ext: 'yaml' }));
|
|
11
|
-
export const handleError = jest.fn();
|