@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.
Files changed (103) hide show
  1. package/README.md +83 -22
  2. package/bin/cli.js +1 -1
  3. package/lib/__mocks__/@redocly/openapi-core.d.ts +53 -1
  4. package/lib/__mocks__/@redocly/openapi-core.js +56 -5
  5. package/lib/__mocks__/documents.d.ts +92 -0
  6. package/lib/__mocks__/documents.js +63 -0
  7. package/lib/__mocks__/fs.d.ts +2 -0
  8. package/lib/__mocks__/fs.js +3 -1
  9. package/lib/__mocks__/perf_hooks.d.ts +4 -0
  10. package/lib/__mocks__/perf_hooks.js +6 -0
  11. package/lib/__mocks__/redoc.d.ts +7 -0
  12. package/lib/__mocks__/redoc.js +5 -0
  13. package/lib/__mocks__/utils.d.ts +26 -4
  14. package/lib/__mocks__/utils.js +8 -3
  15. package/lib/__tests__/commands/build-docs.test.d.ts +1 -0
  16. package/lib/__tests__/commands/build-docs.test.js +59 -0
  17. package/lib/__tests__/commands/bundle.test.js +66 -30
  18. package/lib/__tests__/commands/join.test.d.ts +1 -0
  19. package/lib/__tests__/commands/join.test.js +85 -0
  20. package/lib/__tests__/commands/lint.test.d.ts +1 -0
  21. package/lib/__tests__/commands/lint.test.js +149 -0
  22. package/lib/__tests__/commands/push-region.test.js +5 -4
  23. package/lib/__tests__/commands/push.test.js +254 -39
  24. package/lib/__tests__/fetch-with-timeout.test.d.ts +1 -0
  25. package/lib/__tests__/fetch-with-timeout.test.js +38 -0
  26. package/lib/__tests__/fixtures/config.d.ts +22 -0
  27. package/lib/__tests__/fixtures/config.js +24 -0
  28. package/lib/__tests__/utils.test.js +429 -1
  29. package/lib/__tests__/wrapper.test.d.ts +1 -0
  30. package/lib/__tests__/wrapper.test.js +57 -0
  31. package/lib/commands/build-docs/index.d.ts +3 -0
  32. package/lib/commands/build-docs/index.js +50 -0
  33. package/{src/commands/preview-docs/preview-server/default.hbs → lib/commands/build-docs/template.hbs} +2 -3
  34. package/lib/commands/build-docs/types.d.ts +23 -0
  35. package/lib/commands/build-docs/types.js +2 -0
  36. package/lib/commands/build-docs/utils.d.ts +7 -0
  37. package/lib/commands/build-docs/utils.js +99 -0
  38. package/lib/commands/bundle.d.ts +10 -12
  39. package/lib/commands/bundle.js +25 -24
  40. package/lib/commands/join.d.ts +12 -3
  41. package/lib/commands/join.js +295 -109
  42. package/lib/commands/lint.d.ts +11 -8
  43. package/lib/commands/lint.js +49 -19
  44. package/lib/commands/login.d.ts +5 -3
  45. package/lib/commands/login.js +2 -2
  46. package/lib/commands/preview-docs/index.d.ts +6 -6
  47. package/lib/commands/preview-docs/index.js +30 -20
  48. package/lib/commands/preview-docs/preview-server/oauth2-redirect.html +1 -1
  49. package/lib/commands/preview-docs/preview-server/preview-server.js +5 -4
  50. package/lib/commands/preview-docs/preview-server/server.d.ts +1 -1
  51. package/lib/commands/push.d.ts +21 -10
  52. package/lib/commands/push.js +110 -63
  53. package/lib/commands/split/__tests__/index.test.js +10 -8
  54. package/lib/commands/split/index.d.ts +5 -3
  55. package/lib/commands/split/index.js +15 -24
  56. package/lib/commands/split/types.d.ts +11 -11
  57. package/lib/commands/split/types.js +19 -19
  58. package/lib/commands/stats.d.ts +7 -4
  59. package/lib/commands/stats.js +13 -12
  60. package/lib/fetch-with-timeout.d.ts +2 -0
  61. package/lib/fetch-with-timeout.js +30 -0
  62. package/lib/index.js +194 -40
  63. package/lib/js-utils.d.ts +1 -0
  64. package/lib/js-utils.js +9 -3
  65. package/lib/types.d.ts +17 -1
  66. package/lib/update-version-notifier.d.ts +3 -0
  67. package/lib/update-version-notifier.js +105 -0
  68. package/lib/utils.d.ts +38 -5
  69. package/lib/utils.js +270 -41
  70. package/lib/wrapper.d.ts +4 -0
  71. package/lib/wrapper.js +52 -0
  72. package/package.json +18 -8
  73. package/src/__mocks__/@redocly/openapi-core.ts +0 -26
  74. package/src/__mocks__/fs.ts +0 -4
  75. package/src/__mocks__/utils.ts +0 -11
  76. package/src/__tests__/commands/bundle.test.ts +0 -120
  77. package/src/__tests__/commands/push-region.test.ts +0 -51
  78. package/src/__tests__/commands/push.test.ts +0 -158
  79. package/src/__tests__/utils.test.ts +0 -50
  80. package/src/assert-node-version.ts +0 -8
  81. package/src/commands/bundle.ts +0 -180
  82. package/src/commands/join.ts +0 -488
  83. package/src/commands/lint.ts +0 -110
  84. package/src/commands/login.ts +0 -21
  85. package/src/commands/preview-docs/index.ts +0 -188
  86. package/src/commands/preview-docs/preview-server/hot.js +0 -42
  87. package/src/commands/preview-docs/preview-server/oauth2-redirect.html +0 -21
  88. package/src/commands/preview-docs/preview-server/preview-server.ts +0 -155
  89. package/src/commands/preview-docs/preview-server/server.ts +0 -91
  90. package/src/commands/push.ts +0 -357
  91. package/src/commands/split/__tests__/fixtures/samples.json +0 -61
  92. package/src/commands/split/__tests__/fixtures/spec.json +0 -70
  93. package/src/commands/split/__tests__/fixtures/webhooks.json +0 -88
  94. package/src/commands/split/__tests__/index.test.ts +0 -117
  95. package/src/commands/split/index.ts +0 -349
  96. package/src/commands/split/types.ts +0 -73
  97. package/src/commands/stats.ts +0 -115
  98. package/src/index.ts +0 -316
  99. package/src/js-utils.ts +0 -12
  100. package/src/types.ts +0 -13
  101. package/src/utils.ts +0 -307
  102. package/tsconfig.json +0 -9
  103. 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.getFallbackEntryPointsOrExit = void 0;
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
- function getFallbackEntryPointsOrExit(argsEntrypoints, config) {
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(argsEntrypoints) && apis && Object.keys(apis).length > 0;
40
+ const shouldFallbackToAllDefinitions = !isNotEmptyArray(argsApis) && apis && Object.keys(apis).length > 0;
27
41
  const res = shouldFallbackToAllDefinitions
28
- ? Object.entries(apis).map(([alias, { root }]) => ({
29
- path: path_1.resolve(getConfigDirectory(config), root),
30
- alias,
31
- }))
32
- : (yield expandGlobsInEntrypoints(argsEntrypoints, config));
33
- if (!isNotEmptyArray(res)) {
34
- process.stderr.write('error: missing required argument `entrypoints`.\n');
35
- process.exit(1);
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.getFallbackEntryPointsOrExit = getFallbackEntryPointsOrExit;
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
- : { path: aliasOrPath };
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, entrypoint) {
101
+ function printExecutionTime(commandName, startedAt, api) {
69
102
  const elapsed = getExecutionTime(startedAt);
70
- process.stderr.write(colorette_1.gray(`\n${entrypoint}: ${commandName} processed in ${elapsed}\n\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(path.dirname(filename), { recursive: true });
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
- if (e instanceof openapi_core_1.ResolveError) {
174
- process.stderr.write(`Failed to resolve entrypoint definition at ${ref}:\n\n - ${e.message}.\n\n`);
175
- }
176
- else if (e instanceof openapi_core_1.YamlParseError) {
177
- process.stderr.write(`Failed to parse entrypoint definition at ${ref}:\n\n - ${e.message}.\n\n`);
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
- else { // @ts-ignore
181
- if (e instanceof CircularJSONNotSupportedError) {
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
- else {
186
- process.stderr.write(`Something went wrong when processing ${ref}:\n\n - ${e.message}.\n\n`);
187
- throw e;
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 \`openapi lint --generate-ignore-file\` to add all problems to the ignore file.\n`));
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 you added plugin prefix.\n`);
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
- process.exit(1);
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 relative = path.relative(parent, dir);
265
- return !!relative && !/^..($|\/)/.test(relative) && !path.isAbsolute(relative);
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;
@@ -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-beta.99",
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
- "Sergey Dubovyk <serhii@redoc.ly> (https://redoc.ly/)",
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-beta.99",
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/yargs": "16.0.2",
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();
@@ -1,4 +0,0 @@
1
- export const existsSync = jest.fn();
2
- export const readFileSync = jest.fn(() => '');
3
- export const statSync = jest.fn(() => ({ size: 0 }));
4
- export const createReadStream = jest.fn();
@@ -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();