@redocly/cli 1.18.1 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/lib/__mocks__/@redocly/openapi-core.d.ts +2 -2
  3. package/lib/__mocks__/@redocly/openapi-core.js +1 -0
  4. package/lib/__mocks__/fs.d.ts +0 -1
  5. package/lib/__mocks__/perf_hooks.d.ts +0 -1
  6. package/lib/__mocks__/redoc.d.ts +0 -1
  7. package/lib/__tests__/commands/build-docs.test.js +21 -23
  8. package/lib/__tests__/commands/bundle.test.js +21 -30
  9. package/lib/__tests__/commands/join.test.js +101 -70
  10. package/lib/__tests__/commands/lint.test.js +54 -54
  11. package/lib/__tests__/commands/push-region.test.js +24 -25
  12. package/lib/__tests__/commands/push.test.js +269 -170
  13. package/lib/__tests__/fetch-with-timeout.test.js +3 -12
  14. package/lib/__tests__/fixtures/config.d.ts +0 -1
  15. package/lib/__tests__/utils.test.js +32 -37
  16. package/lib/__tests__/wrapper.test.js +31 -20
  17. package/lib/cms/api/__tests__/api.client.test.js +29 -38
  18. package/lib/cms/api/api-client.d.ts +0 -2
  19. package/lib/cms/api/api-client.js +106 -127
  20. package/lib/cms/api/api-keys.js +1 -2
  21. package/lib/cms/api/domains.js +1 -2
  22. package/lib/cms/commands/__tests__/push-status.test.js +251 -162
  23. package/lib/cms/commands/__tests__/push.test.js +120 -102
  24. package/lib/cms/commands/__tests__/utils.test.js +12 -21
  25. package/lib/cms/commands/push-status.d.ts +3 -2
  26. package/lib/cms/commands/push-status.js +94 -106
  27. package/lib/cms/commands/push.d.ts +3 -2
  28. package/lib/cms/commands/push.js +66 -74
  29. package/lib/cms/commands/utils.js +20 -34
  30. package/lib/commands/build-docs/index.d.ts +2 -2
  31. package/lib/commands/build-docs/index.js +8 -17
  32. package/lib/commands/build-docs/utils.js +26 -38
  33. package/lib/commands/bundle.d.ts +2 -2
  34. package/lib/commands/bundle.js +70 -94
  35. package/lib/commands/join.d.ts +2 -2
  36. package/lib/commands/join.js +375 -388
  37. package/lib/commands/lint.d.ts +2 -2
  38. package/lib/commands/lint.js +64 -75
  39. package/lib/commands/login.d.ts +3 -2
  40. package/lib/commands/login.js +9 -21
  41. package/lib/commands/preview-docs/index.d.ts +2 -2
  42. package/lib/commands/preview-docs/index.js +92 -106
  43. package/lib/commands/preview-docs/preview-server/preview-server.js +64 -76
  44. package/lib/commands/preview-docs/preview-server/server.d.ts +0 -3
  45. package/lib/commands/preview-docs/preview-server/server.js +6 -6
  46. package/lib/commands/preview-project/index.d.ts +2 -1
  47. package/lib/commands/preview-project/index.js +5 -14
  48. package/lib/commands/push.d.ts +8 -11
  49. package/lib/commands/push.js +177 -195
  50. package/lib/commands/split/__tests__/index.test.js +31 -25
  51. package/lib/commands/split/index.d.ts +2 -1
  52. package/lib/commands/split/index.js +20 -33
  53. package/lib/commands/stats.d.ts +2 -2
  54. package/lib/commands/stats.js +34 -45
  55. package/lib/index.js +32 -46
  56. package/lib/types.d.ts +2 -2
  57. package/lib/utils/__mocks__/miscellaneous.d.ts +0 -1
  58. package/lib/utils/fetch-with-timeout.js +7 -12
  59. package/lib/utils/getCommandNameFromArgs.js +2 -4
  60. package/lib/utils/js-utils.js +6 -7
  61. package/lib/utils/miscellaneous.d.ts +4 -1
  62. package/lib/utils/miscellaneous.js +130 -152
  63. package/lib/utils/update-version-notifier.js +4 -13
  64. package/lib/wrapper.d.ts +9 -2
  65. package/lib/wrapper.js +27 -16
  66. package/package.json +3 -3
  67. package/src/__mocks__/@redocly/openapi-core.ts +1 -0
  68. package/src/__tests__/commands/build-docs.test.ts +5 -4
  69. package/src/__tests__/commands/join.test.ts +51 -51
  70. package/src/__tests__/commands/push-region.test.ts +10 -8
  71. package/src/__tests__/commands/push.test.ts +127 -102
  72. package/src/__tests__/utils.test.ts +1 -0
  73. package/src/__tests__/wrapper.test.ts +24 -2
  74. package/src/cms/commands/__tests__/push-status.test.ts +70 -56
  75. package/src/cms/commands/__tests__/push.test.ts +30 -24
  76. package/src/cms/commands/push-status.ts +8 -7
  77. package/src/cms/commands/push.ts +12 -9
  78. package/src/commands/build-docs/index.ts +10 -5
  79. package/src/commands/bundle.ts +14 -6
  80. package/src/commands/join.ts +6 -2
  81. package/src/commands/lint.ts +9 -3
  82. package/src/commands/login.ts +4 -2
  83. package/src/commands/preview-docs/index.ts +6 -1
  84. package/src/commands/preview-project/index.ts +5 -4
  85. package/src/commands/push.ts +13 -15
  86. package/src/commands/split/__tests__/index.test.ts +17 -6
  87. package/src/commands/split/index.ts +4 -2
  88. package/src/commands/stats.ts +4 -2
  89. package/src/utils/miscellaneous.ts +11 -1
  90. package/src/wrapper.ts +37 -11
  91. package/tsconfig.tsbuildinfo +1 -1
@@ -1,26 +1,37 @@
1
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
- 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
- };
22
2
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.notifyAboutIncompatibleConfigOptions = exports.checkForDeprecatedOptions = 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.getAndValidateFileExtension = exports.writeJson = exports.writeYaml = exports.writeToFileByExtension = exports.readYaml = exports.promptUser = exports.saveBundle = exports.dumpBundle = exports.CircularJSONNotSupportedError = exports.langToExt = exports.escapeLanguageName = exports.pathToFilename = exports.printExecutionTime = exports.getExecutionTime = exports.getFallbackApisOrExit = void 0;
3
+ exports.HandledError = exports.CircularJSONNotSupportedError = void 0;
4
+ exports.getFallbackApisOrExit = getFallbackApisOrExit;
5
+ exports.getExecutionTime = getExecutionTime;
6
+ exports.printExecutionTime = printExecutionTime;
7
+ exports.pathToFilename = pathToFilename;
8
+ exports.escapeLanguageName = escapeLanguageName;
9
+ exports.langToExt = langToExt;
10
+ exports.dumpBundle = dumpBundle;
11
+ exports.saveBundle = saveBundle;
12
+ exports.promptUser = promptUser;
13
+ exports.readYaml = readYaml;
14
+ exports.writeToFileByExtension = writeToFileByExtension;
15
+ exports.writeYaml = writeYaml;
16
+ exports.writeJson = writeJson;
17
+ exports.getAndValidateFileExtension = getAndValidateFileExtension;
18
+ exports.pluralize = pluralize;
19
+ exports.handleError = handleError;
20
+ exports.printLintTotals = printLintTotals;
21
+ exports.printConfigLintTotals = printConfigLintTotals;
22
+ exports.getOutputFileName = getOutputFileName;
23
+ exports.printUnusedWarnings = printUnusedWarnings;
24
+ exports.exitWithError = exitWithError;
25
+ exports.isSubdir = isSubdir;
26
+ exports.loadConfigAndHandleErrors = loadConfigAndHandleErrors;
27
+ exports.sortTopLevelKeysForOas = sortTopLevelKeysForOas;
28
+ exports.checkIfRulesetExist = checkIfRulesetExist;
29
+ exports.cleanColors = cleanColors;
30
+ exports.sendTelemetry = sendTelemetry;
31
+ exports.cleanArgs = cleanArgs;
32
+ exports.cleanRawInput = cleanRawInput;
33
+ exports.checkForDeprecatedOptions = checkForDeprecatedOptions;
34
+ exports.notifyAboutIncompatibleConfigOptions = notifyAboutIncompatibleConfigOptions;
24
35
  const pluralizeOne = require("pluralize");
25
36
  const path_1 = require("path");
26
37
  const colorette_1 = require("colorette");
@@ -39,24 +50,21 @@ const types_1 = require("../types");
39
50
  const update_version_notifier_1 = require("./update-version-notifier");
40
51
  const push_1 = require("../commands/push");
41
52
  const fetch_with_timeout_1 = require("./fetch-with-timeout");
42
- function getFallbackApisOrExit(argsApis, config) {
43
- return __awaiter(this, void 0, void 0, function* () {
44
- const { apis } = config;
45
- const shouldFallbackToAllDefinitions = !isNotEmptyArray(argsApis) && apis && Object.keys(apis).length > 0;
46
- const res = shouldFallbackToAllDefinitions
47
- ? fallbackToAllDefinitions(apis, config)
48
- : yield expandGlobsInEntrypoints(argsApis, config);
49
- const filteredInvalidEntrypoints = res.filter(({ path }) => !isApiPathValid(path));
50
- if (isNotEmptyArray(filteredInvalidEntrypoints)) {
51
- for (const { path } of filteredInvalidEntrypoints) {
52
- process.stderr.write((0, colorette_1.yellow)(`\n${(0, path_1.relative)(process.cwd(), path)} ${(0, colorette_1.red)(`does not exist or is invalid.\n\n`)}`));
53
- }
54
- exitWithError('Please provide a valid path.');
53
+ async function getFallbackApisOrExit(argsApis, config) {
54
+ const { apis } = config;
55
+ const shouldFallbackToAllDefinitions = !isNotEmptyArray(argsApis) && apis && Object.keys(apis).length > 0;
56
+ const res = shouldFallbackToAllDefinitions
57
+ ? fallbackToAllDefinitions(apis, config)
58
+ : await expandGlobsInEntrypoints(argsApis, config);
59
+ const filteredInvalidEntrypoints = res.filter(({ path }) => !isApiPathValid(path));
60
+ if (isNotEmptyArray(filteredInvalidEntrypoints)) {
61
+ for (const { path } of filteredInvalidEntrypoints) {
62
+ process.stderr.write((0, colorette_1.yellow)(`\n${(0, path_1.relative)(process.cwd(), path)} ${(0, colorette_1.red)(`does not exist or is invalid.\n\n`)}`));
55
63
  }
56
- return res;
57
- });
64
+ exitWithError('Please provide a valid path.');
65
+ }
66
+ return res;
58
67
  }
59
- exports.getFallbackApisOrExit = getFallbackApisOrExit;
60
68
  function getConfigDirectory(config) {
61
69
  return config.configFile ? (0, path_1.dirname)(config.configFile) : process.cwd();
62
70
  }
@@ -77,37 +85,32 @@ function fallbackToAllDefinitions(apis, config) {
77
85
  }));
78
86
  }
79
87
  function getAliasOrPath(config, aliasOrPath) {
80
- var _a, _b, _c;
81
88
  return config.apis[aliasOrPath]
82
- ? { path: (_a = config.apis[aliasOrPath]) === null || _a === void 0 ? void 0 : _a.root, alias: aliasOrPath }
89
+ ? { path: config.apis[aliasOrPath]?.root, alias: aliasOrPath }
83
90
  : {
84
91
  path: aliasOrPath,
85
92
  // find alias by path, take the first match
86
- alias: (_c = (_b = Object.entries(config.apis).find(([_alias, api]) => {
93
+ alias: Object.entries(config.apis).find(([_alias, api]) => {
87
94
  return (0, path_1.resolve)(api.root) === (0, path_1.resolve)(aliasOrPath);
88
- })) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : undefined,
95
+ })?.[0] ?? undefined,
89
96
  };
90
97
  }
91
- function expandGlobsInEntrypoints(args, config) {
92
- return __awaiter(this, void 0, void 0, function* () {
93
- return (yield Promise.all(args.map((aliasOrPath) => __awaiter(this, void 0, void 0, function* () {
94
- return glob.hasMagic(aliasOrPath) && !(0, openapi_core_1.isAbsoluteUrl)(aliasOrPath)
95
- ? (yield (0, util_1.promisify)(glob)(aliasOrPath)).map((g) => getAliasOrPath(config, g))
96
- : getAliasOrPath(config, aliasOrPath);
97
- })))).flat();
98
- });
98
+ async function expandGlobsInEntrypoints(args, config) {
99
+ return (await Promise.all(args.map(async (aliasOrPath) => {
100
+ return glob.hasMagic(aliasOrPath) && !(0, openapi_core_1.isAbsoluteUrl)(aliasOrPath)
101
+ ? (await (0, util_1.promisify)(glob)(aliasOrPath)).map((g) => getAliasOrPath(config, g))
102
+ : getAliasOrPath(config, aliasOrPath);
103
+ }))).flat();
99
104
  }
100
105
  function getExecutionTime(startedAt) {
101
106
  return process.env.NODE_ENV === 'test'
102
107
  ? '<test>ms'
103
108
  : `${Math.ceil(perf_hooks_1.performance.now() - startedAt)}ms`;
104
109
  }
105
- exports.getExecutionTime = getExecutionTime;
106
110
  function printExecutionTime(commandName, startedAt, api) {
107
111
  const elapsed = getExecutionTime(startedAt);
108
112
  process.stderr.write((0, colorette_1.gray)(`\n${api}: ${commandName} processed in ${elapsed}\n\n`));
109
113
  }
110
- exports.printExecutionTime = printExecutionTime;
111
114
  function pathToFilename(path, pathSeparator) {
112
115
  return path
113
116
  .replace(/~1/g, '/')
@@ -115,11 +118,9 @@ function pathToFilename(path, pathSeparator) {
115
118
  .replace(/^\//, '')
116
119
  .replace(/\//g, pathSeparator);
117
120
  }
118
- exports.pathToFilename = pathToFilename;
119
121
  function escapeLanguageName(lang) {
120
122
  return lang.replace(/#/g, '_sharp').replace(/\//, '_').replace(/\s/g, '');
121
123
  }
122
- exports.escapeLanguageName = escapeLanguageName;
123
124
  function langToExt(lang) {
124
125
  const langObj = {
125
126
  php: '.php',
@@ -151,7 +152,6 @@ function langToExt(lang) {
151
152
  };
152
153
  return langObj[lang.toLowerCase()];
153
154
  }
154
- exports.langToExt = langToExt;
155
155
  class CircularJSONNotSupportedError extends Error {
156
156
  constructor(originalError) {
157
157
  super(originalError.message);
@@ -180,46 +180,40 @@ function dumpBundle(obj, format, dereference) {
180
180
  });
181
181
  }
182
182
  }
183
- exports.dumpBundle = dumpBundle;
184
183
  function saveBundle(filename, output) {
185
184
  fs.mkdirSync((0, path_1.dirname)(filename), { recursive: true });
186
185
  fs.writeFileSync(filename, output);
187
186
  }
188
- exports.saveBundle = saveBundle;
189
- function promptUser(query, hideUserInput = false) {
190
- return __awaiter(this, void 0, void 0, function* () {
191
- return new Promise((resolve) => {
192
- let output = process.stdout;
193
- let isOutputMuted = false;
194
- if (hideUserInput) {
195
- output = new stream_1.Writable({
196
- write: (chunk, encoding, callback) => {
197
- if (!isOutputMuted) {
198
- process.stdout.write(chunk, encoding);
199
- }
200
- callback();
201
- },
202
- });
203
- }
204
- const rl = readline.createInterface({
205
- input: process.stdin,
206
- output,
207
- terminal: true,
208
- historySize: hideUserInput ? 0 : 30,
209
- });
210
- rl.question(`${query}:\n\n `, (answer) => {
211
- rl.close();
212
- resolve(answer);
187
+ async function promptUser(query, hideUserInput = false) {
188
+ return new Promise((resolve) => {
189
+ let output = process.stdout;
190
+ let isOutputMuted = false;
191
+ if (hideUserInput) {
192
+ output = new stream_1.Writable({
193
+ write: (chunk, encoding, callback) => {
194
+ if (!isOutputMuted) {
195
+ process.stdout.write(chunk, encoding);
196
+ }
197
+ callback();
198
+ },
213
199
  });
214
- isOutputMuted = hideUserInput;
200
+ }
201
+ const rl = readline.createInterface({
202
+ input: process.stdin,
203
+ output,
204
+ terminal: true,
205
+ historySize: hideUserInput ? 0 : 30,
215
206
  });
207
+ rl.question(`${query}:\n\n `, (answer) => {
208
+ rl.close();
209
+ resolve(answer);
210
+ });
211
+ isOutputMuted = hideUserInput;
216
212
  });
217
213
  }
218
- exports.promptUser = promptUser;
219
214
  function readYaml(filename) {
220
215
  return (0, openapi_core_1.parseYaml)(fs.readFileSync(filename, 'utf-8'), { filename });
221
216
  }
222
- exports.readYaml = readYaml;
223
217
  function writeToFileByExtension(data, filePath, noRefs) {
224
218
  const ext = getAndValidateFileExtension(filePath);
225
219
  if (ext === 'json') {
@@ -228,7 +222,6 @@ function writeToFileByExtension(data, filePath, noRefs) {
228
222
  }
229
223
  writeYaml(data, filePath, noRefs);
230
224
  }
231
- exports.writeToFileByExtension = writeToFileByExtension;
232
225
  function writeYaml(data, filename, noRefs = false) {
233
226
  const content = (0, openapi_core_1.stringifyYaml)(data, { noRefs });
234
227
  if (process.env.NODE_ENV === 'test') {
@@ -238,7 +231,6 @@ function writeYaml(data, filename, noRefs = false) {
238
231
  fs.mkdirSync((0, path_1.dirname)(filename), { recursive: true });
239
232
  fs.writeFileSync(filename, content);
240
233
  }
241
- exports.writeYaml = writeYaml;
242
234
  function writeJson(data, filename) {
243
235
  const content = JSON.stringify(data, null, 2);
244
236
  if (process.env.NODE_ENV === 'test') {
@@ -248,7 +240,6 @@ function writeJson(data, filename) {
248
240
  fs.mkdirSync((0, path_1.dirname)(filename), { recursive: true });
249
241
  fs.writeFileSync(filename, content);
250
242
  }
251
- exports.writeJson = writeJson;
252
243
  function getAndValidateFileExtension(fileName) {
253
244
  const ext = fileName.split('.').pop();
254
245
  if (['yaml', 'yml', 'json'].includes(ext)) {
@@ -257,16 +248,13 @@ function getAndValidateFileExtension(fileName) {
257
248
  process.stderr.write((0, colorette_1.yellow)(`Unsupported file extension: ${ext}. Using yaml.\n`));
258
249
  return 'yaml';
259
250
  }
260
- exports.getAndValidateFileExtension = getAndValidateFileExtension;
261
251
  function pluralize(sentence, count, inclusive) {
262
252
  return sentence
263
253
  .split(' ')
264
254
  .map((word) => pluralizeOne(word, count, inclusive))
265
255
  .join(' ');
266
256
  }
267
- exports.pluralize = pluralize;
268
257
  function handleError(e, ref) {
269
- var _a, _b;
270
258
  switch (e.constructor) {
271
259
  case HandledError: {
272
260
  throw e;
@@ -280,7 +268,7 @@ function handleError(e, ref) {
280
268
  `Try to use ${(0, colorette_1.blue)('yaml')} output or remove ${(0, colorette_1.blue)('--dereferenced')}.`);
281
269
  }
282
270
  case SyntaxError:
283
- 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]}`);
271
+ return exitWithError(`Syntax error: ${e.message} ${e.stack?.split('\n\n')?.[0]}`);
284
272
  case config_1.ConfigValidationError:
285
273
  return exitWithError(e.message);
286
274
  default: {
@@ -288,7 +276,6 @@ function handleError(e, ref) {
288
276
  }
289
277
  }
290
278
  }
291
- exports.handleError = handleError;
292
279
  class HandledError extends Error {
293
280
  }
294
281
  exports.HandledError = HandledError;
@@ -313,7 +300,6 @@ function printLintTotals(totals, definitionsCount) {
313
300
  }
314
301
  process.stderr.write('\n');
315
302
  }
316
- exports.printLintTotals = printLintTotals;
317
303
  function printConfigLintTotals(totals, command) {
318
304
  if (totals.errors > 0) {
319
305
  process.stderr.write((0, colorette_1.red)(`❌ Your config has ${totals.errors} ${pluralize('error', totals.errors)}.`));
@@ -325,7 +311,6 @@ function printConfigLintTotals(totals, command) {
325
311
  process.stderr.write((0, colorette_1.green)('✅ Your config is valid.\n'));
326
312
  }
327
313
  }
328
- exports.printConfigLintTotals = printConfigLintTotals;
329
314
  function getOutputFileName(entrypoint, entries, output, ext) {
330
315
  if (!output) {
331
316
  return { outputFile: 'stdout', ext: ext || 'yaml' };
@@ -350,7 +335,6 @@ function getOutputFileName(entrypoint, entries, output, ext) {
350
335
  }
351
336
  return { outputFile, ext };
352
337
  }
353
- exports.getOutputFileName = getOutputFileName;
354
338
  function printUnusedWarnings(config) {
355
339
  const { preprocessors, rules, decorators } = config.getUnusedRules();
356
340
  if (rules.length) {
@@ -366,12 +350,10 @@ function printUnusedWarnings(config) {
366
350
  process.stderr.write(`Check the spelling and verify the added plugin prefix.\n`);
367
351
  }
368
352
  }
369
- exports.printUnusedWarnings = printUnusedWarnings;
370
353
  function exitWithError(message) {
371
354
  process.stderr.write((0, colorette_1.red)(message) + '\n\n');
372
355
  throw new HandledError(message);
373
356
  }
374
- exports.exitWithError = exitWithError;
375
357
  /**
376
358
  * Checks if dir is subdir of parent
377
359
  */
@@ -379,25 +361,20 @@ function isSubdir(parent, dir) {
379
361
  const relativePath = (0, path_1.relative)(parent, dir);
380
362
  return !!relativePath && !/^..($|\/)/.test(relativePath) && !(0, path_1.isAbsolute)(relativePath);
381
363
  }
382
- exports.isSubdir = isSubdir;
383
- function loadConfigAndHandleErrors(options = {}) {
384
- return __awaiter(this, void 0, void 0, function* () {
385
- try {
386
- return yield (0, openapi_core_1.loadConfig)(options);
387
- }
388
- catch (e) {
389
- handleError(e, '');
390
- }
391
- });
364
+ async function loadConfigAndHandleErrors(options = {}) {
365
+ try {
366
+ return await (0, openapi_core_1.loadConfig)(options);
367
+ }
368
+ catch (e) {
369
+ handleError(e, '');
370
+ }
392
371
  }
393
- exports.loadConfigAndHandleErrors = loadConfigAndHandleErrors;
394
372
  function sortTopLevelKeysForOas(document) {
395
373
  if ('swagger' in document) {
396
374
  return sortOas2Keys(document);
397
375
  }
398
376
  return sortOas3Keys(document);
399
377
  }
400
- exports.sortTopLevelKeysForOas = sortTopLevelKeysForOas;
401
378
  function sortOas2Keys(document) {
402
379
  const orderedKeys = [
403
380
  'swagger',
@@ -449,56 +426,61 @@ function sortOas3Keys(document) {
449
426
  return Object.assign(result, document);
450
427
  }
451
428
  function checkIfRulesetExist(rules) {
452
- const ruleset = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, rules.oas2), rules.oas3_0), rules.oas3_1), rules.async2), rules.arazzo);
429
+ const ruleset = {
430
+ ...rules.oas2,
431
+ ...rules.oas3_0,
432
+ ...rules.oas3_1,
433
+ ...rules.async2,
434
+ ...rules.async3,
435
+ ...rules.arazzo,
436
+ };
453
437
  if ((0, utils_1.isEmptyObject)(ruleset)) {
454
438
  exitWithError('⚠️ No rules were configured. Learn how to configure rules: https://redocly.com/docs/cli/rules/');
455
439
  }
456
440
  }
457
- exports.checkIfRulesetExist = checkIfRulesetExist;
458
441
  function cleanColors(input) {
459
442
  // eslint-disable-next-line no-control-regex
460
443
  return input.replace(/\x1b\[\d+m/g, '');
461
444
  }
462
- exports.cleanColors = cleanColors;
463
- function sendTelemetry(argv, exit_code, has_config) {
464
- return __awaiter(this, void 0, void 0, function* () {
465
- try {
466
- if (!argv) {
467
- return;
468
- }
469
- const { _: [command], $0: _ } = argv, args = __rest(argv, ["_", "$0"]);
470
- const event_time = new Date().toISOString();
471
- const redoclyClient = new openapi_core_1.RedoclyClient();
472
- const logged_in = redoclyClient.hasTokens();
473
- const data = {
474
- event: 'cli_command',
475
- event_time,
476
- logged_in,
477
- command,
478
- arguments: cleanArgs(args),
479
- node_version: process.version,
480
- npm_version: (0, child_process_1.execSync)('npm -v').toString().replace('\n', ''),
481
- version: update_version_notifier_1.version,
482
- exit_code,
483
- environment: process.env.REDOCLY_ENVIRONMENT,
484
- environment_ci: process.env.CI,
485
- raw_input: cleanRawInput(process.argv.slice(2)),
486
- has_config,
487
- };
488
- yield (0, fetch_with_timeout_1.default)(`https://api.redocly.com/registry/telemetry/cli`, {
489
- method: 'POST',
490
- headers: {
491
- 'content-type': 'application/json',
492
- },
493
- body: JSON.stringify(data),
494
- });
445
+ async function sendTelemetry(argv, exit_code, has_config, spec_version, spec_keyword, spec_full_version) {
446
+ try {
447
+ if (!argv) {
448
+ return;
495
449
  }
496
- catch (err) {
497
- // Do nothing.
498
- }
499
- });
450
+ const { _: [command], $0: _, ...args } = argv;
451
+ const event_time = new Date().toISOString();
452
+ const redoclyClient = new openapi_core_1.RedoclyClient();
453
+ const logged_in = redoclyClient.hasTokens();
454
+ const data = {
455
+ event: 'cli_command',
456
+ event_time,
457
+ logged_in,
458
+ command,
459
+ arguments: cleanArgs(args),
460
+ node_version: process.version,
461
+ npm_version: (0, child_process_1.execSync)('npm -v').toString().replace('\n', ''),
462
+ version: update_version_notifier_1.version,
463
+ exit_code,
464
+ environment: process.env.REDOCLY_ENVIRONMENT,
465
+ environment_ci: process.env.CI,
466
+ raw_input: cleanRawInput(process.argv.slice(2)),
467
+ has_config,
468
+ spec_version,
469
+ spec_keyword,
470
+ spec_full_version,
471
+ };
472
+ await (0, fetch_with_timeout_1.default)(`https://api.redocly.com/registry/telemetry/cli`, {
473
+ method: 'POST',
474
+ headers: {
475
+ 'content-type': 'application/json',
476
+ },
477
+ body: JSON.stringify(data),
478
+ });
479
+ }
480
+ catch (err) {
481
+ // Do nothing.
482
+ }
500
483
  }
501
- exports.sendTelemetry = sendTelemetry;
502
484
  function isFile(value) {
503
485
  return fs.existsSync(value) && fs.statSync(value).isFile();
504
486
  }
@@ -542,11 +524,9 @@ function cleanArgs(args) {
542
524
  }
543
525
  return result;
544
526
  }
545
- exports.cleanArgs = cleanArgs;
546
527
  function cleanRawInput(argv) {
547
528
  return argv.map((entry) => entry.split('=').map(cleanString).join('=')).join(' ');
548
529
  }
549
- exports.cleanRawInput = cleanRawInput;
550
530
  function checkForDeprecatedOptions(argv, deprecatedOptions) {
551
531
  for (const option of deprecatedOptions) {
552
532
  if (argv[option]) {
@@ -554,7 +534,6 @@ function checkForDeprecatedOptions(argv, deprecatedOptions) {
554
534
  }
555
535
  }
556
536
  }
557
- exports.checkForDeprecatedOptions = checkForDeprecatedOptions;
558
537
  function notifyAboutIncompatibleConfigOptions(themeOpenapiOptions) {
559
538
  if ((0, utils_1.isPlainObject)(themeOpenapiOptions)) {
560
539
  const propertiesSet = Object.keys(themeOpenapiOptions);
@@ -565,4 +544,3 @@ function notifyAboutIncompatibleConfigOptions(themeOpenapiOptions) {
565
544
  }
566
545
  }
567
546
  }
568
- exports.notifyAboutIncompatibleConfigOptions = notifyAboutIncompatibleConfigOptions;
@@ -1,13 +1,4 @@
1
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
2
  var _a;
12
3
  Object.defineProperty(exports, "__esModule", { value: true });
13
4
  exports.cacheLatestVersion = exports.notifyUpdateCliVersion = exports.name = exports.version = void 0;
@@ -39,14 +30,14 @@ const notifyUpdateCliVersion = () => {
39
30
  };
40
31
  exports.notifyUpdateCliVersion = notifyUpdateCliVersion;
41
32
  const isNewVersionAvailable = (current, latest) => (0, semver_1.compare)(current, latest) < 0;
42
- const getLatestVersion = (packageName) => __awaiter(void 0, void 0, void 0, function* () {
33
+ const getLatestVersion = async (packageName) => {
43
34
  const latestUrl = `http://registry.npmjs.org/${packageName}/latest`;
44
- const response = yield (0, fetch_with_timeout_1.default)(latestUrl);
35
+ const response = await (0, fetch_with_timeout_1.default)(latestUrl);
45
36
  if (!response)
46
37
  return;
47
- const info = yield response.json();
38
+ const info = await response.json();
48
39
  return info.version;
49
- });
40
+ };
50
41
  const cacheLatestVersion = () => {
51
42
  if (!isNeedToBeCached() || SHOULD_NOT_NOTIFY) {
52
43
  return;
package/lib/wrapper.d.ts CHANGED
@@ -1,4 +1,11 @@
1
- import { Config } from '@redocly/openapi-core';
2
1
  import type { Arguments } from 'yargs';
2
+ import type { Config } from '@redocly/openapi-core';
3
+ import type { CollectFn } from '@redocly/openapi-core/lib/utils';
3
4
  import type { CommandOptions } from './types';
4
- export declare function commandWrapper<T extends CommandOptions>(commandHandler?: (argv: T, config: Config, version: string) => Promise<unknown>): (argv: Arguments<T>) => Promise<void>;
5
+ export type CommandArgs<T extends CommandOptions> = {
6
+ argv: T;
7
+ config: Config;
8
+ version: string;
9
+ collectSpecData?: CollectFn;
10
+ };
11
+ export declare function commandWrapper<T extends CommandOptions>(commandHandler?: (wrapperArgs: CommandArgs<T>) => Promise<unknown>): (argv: Arguments<T>) => Promise<void>;
package/lib/wrapper.js CHANGED
@@ -1,29 +1,41 @@
1
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
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.commandWrapper = void 0;
3
+ exports.commandWrapper = commandWrapper;
13
4
  const openapi_core_1 = require("@redocly/openapi-core");
5
+ const utils_1 = require("@redocly/openapi-core/lib/utils");
14
6
  const update_version_notifier_1 = require("./utils/update-version-notifier");
15
7
  const miscellaneous_1 = require("./utils/miscellaneous");
16
8
  const lint_1 = require("./commands/lint");
17
9
  function commandWrapper(commandHandler) {
18
- return (argv) => __awaiter(this, void 0, void 0, function* () {
10
+ return async (argv) => {
19
11
  let code = 2;
20
12
  let hasConfig;
21
13
  let telemetry;
14
+ let specVersion;
15
+ let specKeyword;
16
+ let specFullVersion;
17
+ const collectSpecData = (document) => {
18
+ specVersion = (0, openapi_core_1.detectSpec)(document);
19
+ if (!(0, utils_1.isPlainObject)(document))
20
+ return;
21
+ specKeyword = document?.openapi
22
+ ? 'openapi'
23
+ : document?.swagger
24
+ ? 'swagger'
25
+ : document?.asyncapi
26
+ ? 'asyncapi'
27
+ : document?.arazzo
28
+ ? 'arazzo'
29
+ : undefined;
30
+ if (specKeyword) {
31
+ specFullVersion = document[specKeyword];
32
+ }
33
+ };
22
34
  try {
23
35
  if (argv.config && !(0, openapi_core_1.doesYamlFileExist)(argv.config)) {
24
36
  (0, miscellaneous_1.exitWithError)('Please provide a valid path to the configuration file.');
25
37
  }
26
- const config = (yield (0, miscellaneous_1.loadConfigAndHandleErrors)({
38
+ const config = (await (0, miscellaneous_1.loadConfigAndHandleErrors)({
27
39
  configPath: argv.config,
28
40
  customExtends: argv.extends,
29
41
  region: argv.region,
@@ -34,7 +46,7 @@ function commandWrapper(commandHandler) {
34
46
  hasConfig = !config.styleguide.recommendedFallback;
35
47
  code = 1;
36
48
  if (typeof commandHandler === 'function') {
37
- yield commandHandler(argv, config, update_version_notifier_1.version);
49
+ await commandHandler({ argv, config, version: update_version_notifier_1.version, collectSpecData });
38
50
  }
39
51
  code = 0;
40
52
  }
@@ -43,12 +55,11 @@ function commandWrapper(commandHandler) {
43
55
  }
44
56
  finally {
45
57
  if (process.env.REDOCLY_TELEMETRY !== 'off' && telemetry !== 'off') {
46
- yield (0, miscellaneous_1.sendTelemetry)(argv, code, hasConfig);
58
+ await (0, miscellaneous_1.sendTelemetry)(argv, code, hasConfig, specVersion, specKeyword, specFullVersion);
47
59
  }
48
60
  process.once('beforeExit', () => {
49
61
  process.exit(code);
50
62
  });
51
63
  }
52
- });
64
+ };
53
65
  }
54
- exports.commandWrapper = commandWrapper;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/cli",
3
- "version": "1.18.1",
3
+ "version": "1.19.0",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -36,7 +36,7 @@
36
36
  "Roman Hotsiy <roman@redoc.ly> (https://redoc.ly/)"
37
37
  ],
38
38
  "dependencies": {
39
- "@redocly/openapi-core": "1.18.1",
39
+ "@redocly/openapi-core": "1.19.0",
40
40
  "abort-controller": "^3.0.0",
41
41
  "chokidar": "^3.5.1",
42
42
  "colorette": "^1.2.0",
@@ -64,6 +64,6 @@
64
64
  "@types/react-dom": "^17.0.0 || ^18.2.7",
65
65
  "@types/semver": "^7.5.0",
66
66
  "@types/yargs": "17.0.32",
67
- "typescript": "^5.2.2"
67
+ "typescript": "5.5.3"
68
68
  }
69
69
  }
@@ -73,6 +73,7 @@ export enum SpecVersion {
73
73
  OAS3_0 = 'oas3_0',
74
74
  OAS3_1 = 'oas3_1',
75
75
  Async2 = 'async2',
76
+ Async3 = 'async3',
76
77
  }
77
78
 
78
79
  export enum Oas3Operations {
@@ -39,8 +39,8 @@ describe('build-docs', () => {
39
39
 
40
40
  it('should work correctly when calling handlerBuildCommand', async () => {
41
41
  const processExitMock = jest.spyOn(process, 'exit').mockImplementation();
42
- await handlerBuildCommand(
43
- {
42
+ await handlerBuildCommand({
43
+ argv: {
44
44
  o: '',
45
45
  title: 'test',
46
46
  disableGoogleFont: false,
@@ -49,8 +49,9 @@ describe('build-docs', () => {
49
49
  theme: { openapi: {} },
50
50
  api: '../some-path/openapi.yaml',
51
51
  } as BuildDocsArgv,
52
- {} as any
53
- );
52
+ config: {} as any,
53
+ version: 'cli-version',
54
+ });
54
55
  expect(loadAndBundleSpec).toBeCalledTimes(1);
55
56
  expect(getFallbackApisOrExit).toBeCalledTimes(1);
56
57
  expect(processExitMock).toBeCalledTimes(0);