@redocly/cli 1.3.0 → 1.4.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 (63) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/lib/__mocks__/@redocly/openapi-core.d.ts +1 -0
  3. package/lib/__mocks__/@redocly/openapi-core.js +4 -3
  4. package/lib/__mocks__/utils.d.ts +2 -0
  5. package/lib/__mocks__/utils.js +3 -1
  6. package/lib/__tests__/commands/build-docs.test.js +2 -2
  7. package/lib/__tests__/commands/bundle.test.js +7 -7
  8. package/lib/__tests__/commands/join.test.js +25 -18
  9. package/lib/__tests__/commands/lint.test.js +15 -15
  10. package/lib/__tests__/commands/push-region.test.js +2 -2
  11. package/lib/__tests__/commands/push.test.js +30 -30
  12. package/lib/__tests__/fetch-with-timeout.test.js +2 -2
  13. package/lib/__tests__/utils.test.js +63 -32
  14. package/lib/__tests__/wrapper.test.js +3 -3
  15. package/lib/assert-node-version.js +1 -1
  16. package/lib/commands/build-docs/index.js +9 -9
  17. package/lib/commands/build-docs/types.d.ts +2 -2
  18. package/lib/commands/build-docs/utils.js +10 -10
  19. package/lib/commands/bundle.d.ts +1 -1
  20. package/lib/commands/bundle.js +25 -25
  21. package/lib/commands/join.d.ts +1 -1
  22. package/lib/commands/join.js +49 -48
  23. package/lib/commands/lint.d.ts +1 -1
  24. package/lib/commands/lint.js +22 -22
  25. package/lib/commands/login.d.ts +1 -1
  26. package/lib/commands/login.js +3 -3
  27. package/lib/commands/preview-docs/index.d.ts +1 -1
  28. package/lib/commands/preview-docs/index.js +7 -7
  29. package/lib/commands/preview-docs/preview-server/hot.js +19 -2
  30. package/lib/commands/preview-docs/preview-server/preview-server.js +15 -14
  31. package/lib/commands/preview-docs/preview-server/server.d.ts +3 -1
  32. package/lib/commands/preview-docs/preview-server/server.js +2 -2
  33. package/lib/commands/push.d.ts +2 -2
  34. package/lib/commands/push.js +31 -31
  35. package/lib/commands/split/__tests__/index.test.js +9 -9
  36. package/lib/commands/split/index.d.ts +2 -2
  37. package/lib/commands/split/index.js +41 -40
  38. package/lib/commands/split/types.d.ts +2 -2
  39. package/lib/commands/split/types.js +2 -2
  40. package/lib/commands/stats.d.ts +1 -1
  41. package/lib/commands/stats.js +9 -9
  42. package/lib/fetch-with-timeout.js +5 -2
  43. package/lib/index.js +11 -12
  44. package/lib/types.d.ts +6 -6
  45. package/lib/update-version-notifier.js +18 -18
  46. package/lib/utils.d.ts +6 -3
  47. package/lib/utils.js +66 -38
  48. package/lib/wrapper.js +5 -5
  49. package/package.json +3 -3
  50. package/src/__mocks__/@redocly/openapi-core.ts +1 -0
  51. package/src/__mocks__/utils.ts +2 -0
  52. package/src/__tests__/commands/join.test.ts +37 -7
  53. package/src/__tests__/utils.test.ts +45 -1
  54. package/src/commands/join.ts +8 -3
  55. package/src/commands/preview-docs/preview-server/hot.js +19 -2
  56. package/src/commands/preview-docs/preview-server/preview-server.ts +6 -4
  57. package/src/commands/preview-docs/preview-server/server.ts +2 -2
  58. package/src/commands/split/__tests__/index.test.ts +14 -5
  59. package/src/commands/split/index.ts +25 -17
  60. package/src/fetch-with-timeout.ts +3 -0
  61. package/src/index.ts +0 -1
  62. package/src/utils.ts +40 -1
  63. package/tsconfig.tsbuildinfo +1 -1
@@ -14,13 +14,16 @@ const TIMEOUT = 3000;
14
14
  exports.default = (url, options = {}) => __awaiter(void 0, void 0, void 0, function* () {
15
15
  try {
16
16
  if (!global.AbortController) {
17
- return node_fetch_1.default(url, options);
17
+ return (0, node_fetch_1.default)(url, options);
18
18
  }
19
19
  const controller = new AbortController();
20
20
  const timeout = setTimeout(() => {
21
21
  controller.abort();
22
22
  }, TIMEOUT);
23
- const res = yield node_fetch_1.default(url, Object.assign({ signal: controller.signal }, options));
23
+ // FIXME: fix this (possibly along with this issue: https://github.com/Redocly/redocly-cli/issues/1260)
24
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
25
+ // @ts-ignore
26
+ const res = yield (0, node_fetch_1.default)(url, Object.assign({ signal: controller.signal }, options));
24
27
  clearTimeout(timeout);
25
28
  return res;
26
29
  }
package/lib/index.js CHANGED
@@ -29,7 +29,7 @@ const update_version_notifier_2 = require("./update-version-notifier");
29
29
  if (!('replaceAll' in String.prototype)) {
30
30
  require('core-js/actual/string/replace-all');
31
31
  }
32
- update_version_notifier_1.cacheLatestVersion();
32
+ (0, update_version_notifier_1.cacheLatestVersion)();
33
33
  yargs
34
34
  .version('version', 'Show version number.', update_version_notifier_2.version)
35
35
  .help('help', 'Show help.')
@@ -48,7 +48,7 @@ yargs
48
48
  },
49
49
  }), (argv) => {
50
50
  process.env.REDOCLY_CLI_COMMAND = 'stats';
51
- wrapper_1.commandWrapper(stats_1.handleStats)(argv);
51
+ (0, wrapper_1.commandWrapper)(stats_1.handleStats)(argv);
52
52
  })
53
53
  .command('split [api]', 'Split an API description into a multi-file structure.', (yargs) => yargs
54
54
  .positional('api', {
@@ -80,7 +80,7 @@ yargs
80
80
  })
81
81
  .demandOption('api'), (argv) => {
82
82
  process.env.REDOCLY_CLI_COMMAND = 'split';
83
- wrapper_1.commandWrapper(split_1.handleSplit)(argv);
83
+ (0, wrapper_1.commandWrapper)(split_1.handleSplit)(argv);
84
84
  })
85
85
  .command('join [apis...]', 'Join definitions [experimental].', (yargs) => yargs
86
86
  .positional('apis', {
@@ -115,7 +115,6 @@ yargs
115
115
  describe: 'Output file',
116
116
  alias: 'o',
117
117
  type: 'string',
118
- default: 'openapi.yaml',
119
118
  },
120
119
  config: {
121
120
  description: 'Path to the config file.',
@@ -129,7 +128,7 @@ yargs
129
128
  },
130
129
  }), (argv) => {
131
130
  process.env.REDOCLY_CLI_COMMAND = 'join';
132
- wrapper_1.commandWrapper(join_1.handleJoin)(argv);
131
+ (0, wrapper_1.commandWrapper)(join_1.handleJoin)(argv);
133
132
  })
134
133
  .command('push [api] [maybeDestination] [maybeBranchName]', 'Push an API description to the Redocly API registry.', (yargs) => yargs
135
134
  .usage('push [api]')
@@ -202,7 +201,7 @@ yargs
202
201
  .implies('batch-id', 'batch-size')
203
202
  .implies('batch-size', 'job-id'), (argv) => {
204
203
  process.env.REDOCLY_CLI_COMMAND = 'push';
205
- wrapper_1.commandWrapper(push_1.transformPush(push_1.handlePush))(argv);
204
+ (0, wrapper_1.commandWrapper)((0, push_1.transformPush)(push_1.handlePush))(argv);
206
205
  })
207
206
  .command('lint [apis...]', 'Lint definition.', (yargs) => yargs.positional('apis', { array: true, type: 'string', demandOption: true }).option({
208
207
  format: {
@@ -255,7 +254,7 @@ yargs
255
254
  },
256
255
  }), (argv) => {
257
256
  process.env.REDOCLY_CLI_COMMAND = 'lint';
258
- wrapper_1.commandWrapper(lint_1.handleLint)(argv);
257
+ (0, wrapper_1.commandWrapper)(lint_1.handleLint)(argv);
259
258
  })
260
259
  .command('bundle [apis...]', 'Bundle definition.', (yargs) => yargs.positional('apis', { array: true, type: 'string', demandOption: true }).options({
261
260
  output: { type: 'string', alias: 'o' },
@@ -336,7 +335,7 @@ yargs
336
335
  },
337
336
  }), (argv) => {
338
337
  process.env.REDOCLY_CLI_COMMAND = 'bundle';
339
- wrapper_1.commandWrapper(bundle_1.handleBundle)(argv);
338
+ (0, wrapper_1.commandWrapper)(bundle_1.handleBundle)(argv);
340
339
  })
341
340
  .command('login', 'Login to the Redocly API registry with an access token.', (yargs) => __awaiter(void 0, void 0, void 0, function* () {
342
341
  return yargs.options({
@@ -357,11 +356,11 @@ yargs
357
356
  });
358
357
  }), (argv) => {
359
358
  process.env.REDOCLY_CLI_COMMAND = 'login';
360
- wrapper_1.commandWrapper(login_1.handleLogin)(argv);
359
+ (0, wrapper_1.commandWrapper)(login_1.handleLogin)(argv);
361
360
  })
362
361
  .command('logout', 'Clear your stored credentials for the Redocly API registry.', (yargs) => yargs, (argv) => __awaiter(void 0, void 0, void 0, function* () {
363
362
  process.env.REDOCLY_CLI_COMMAND = 'logout';
364
- yield wrapper_1.commandWrapper(() => __awaiter(void 0, void 0, void 0, function* () {
363
+ yield (0, wrapper_1.commandWrapper)(() => __awaiter(void 0, void 0, void 0, function* () {
365
364
  const client = new openapi_core_1.RedoclyClient();
366
365
  client.logout();
367
366
  process.stdout.write('Logged out from the Redocly account. ✋\n');
@@ -410,7 +409,7 @@ yargs
410
409
  },
411
410
  }), (argv) => {
412
411
  process.env.REDOCLY_CLI_COMMAND = 'preview-docs';
413
- wrapper_1.commandWrapper(preview_docs_1.previewDocs)(argv);
412
+ (0, wrapper_1.commandWrapper)(preview_docs_1.previewDocs)(argv);
414
413
  })
415
414
  .command('build-docs [api]', 'Produce API documentation as an HTML file', (yargs) => yargs
416
415
  .positional('api', { type: 'string' })
@@ -458,7 +457,7 @@ yargs
458
457
  return true;
459
458
  }), (argv) => __awaiter(void 0, void 0, void 0, function* () {
460
459
  process.env.REDOCLY_CLI_COMMAND = 'build-docs';
461
- wrapper_1.commandWrapper(build_docs_1.handlerBuildCommand)(argv);
460
+ (0, wrapper_1.commandWrapper)(build_docs_1.handlerBuildCommand)(argv);
462
461
  }))
463
462
  .completion('completion', 'Generate completion script.')
464
463
  .demandCommand(1)
package/lib/types.d.ts CHANGED
@@ -8,22 +8,22 @@ import type { StatsOptions } from './commands/stats';
8
8
  import type { SplitOptions } from './commands/split';
9
9
  import type { PreviewDocsOptions } from './commands/preview-docs';
10
10
  import type { BuildDocsArgv } from './commands/build-docs/types';
11
- export declare type Totals = {
11
+ export type Totals = {
12
12
  errors: number;
13
13
  warnings: number;
14
14
  ignored: number;
15
15
  };
16
- export declare type Entrypoint = {
16
+ export type Entrypoint = {
17
17
  path: string;
18
18
  alias?: string;
19
19
  };
20
20
  export declare const outputExtensions: readonly BundleOutputFormat[];
21
- export declare type OutputExtensions = 'json' | 'yaml' | 'yml' | undefined;
21
+ export type OutputExtensions = 'json' | 'yaml' | 'yml' | undefined;
22
22
  export declare const regionChoices: readonly Region[];
23
- export declare type CommandOptions = StatsOptions | SplitOptions | JoinOptions | PushOptions | LintOptions | BundleOptions | LoginOptions | PreviewDocsOptions | BuildDocsArgv;
24
- export declare type Skips = {
23
+ export type CommandOptions = StatsOptions | SplitOptions | JoinOptions | PushOptions | LintOptions | BundleOptions | LoginOptions | PreviewDocsOptions | BuildDocsArgv;
24
+ export type Skips = {
25
25
  'skip-rule'?: string[];
26
26
  'skip-decorator'?: string[];
27
27
  'skip-preprocessor'?: string[];
28
28
  };
29
- export declare type ConfigApis = Pick<Config, 'apis' | 'configFile'>;
29
+ export type ConfigApis = Pick<Config, 'apis' | 'configFile'>;
@@ -28,7 +28,7 @@ const notifyUpdateCliVersion = () => {
28
28
  return;
29
29
  }
30
30
  try {
31
- const latestVersion = fs_1.readFileSync(path_1.join(os_1.tmpdir(), VERSION_CACHE_FILE)).toString();
31
+ const latestVersion = (0, fs_1.readFileSync)((0, path_1.join)((0, os_1.tmpdir)(), VERSION_CACHE_FILE)).toString();
32
32
  if (isNewVersionAvailable(exports.version, latestVersion)) {
33
33
  renderUpdateBanner(exports.version, latestVersion);
34
34
  }
@@ -38,10 +38,10 @@ const notifyUpdateCliVersion = () => {
38
38
  }
39
39
  };
40
40
  exports.notifyUpdateCliVersion = notifyUpdateCliVersion;
41
- const isNewVersionAvailable = (current, latest) => semver_1.compare(current, latest) < 0;
41
+ const isNewVersionAvailable = (current, latest) => (0, semver_1.compare)(current, latest) < 0;
42
42
  const getLatestVersion = (packageName) => __awaiter(void 0, void 0, void 0, function* () {
43
43
  const latestUrl = `http://registry.npmjs.org/${packageName}/latest`;
44
- const response = yield fetch_with_timeout_1.default(latestUrl);
44
+ const response = yield (0, fetch_with_timeout_1.default)(latestUrl);
45
45
  if (!response)
46
46
  return;
47
47
  const info = yield response.json();
@@ -54,8 +54,8 @@ const cacheLatestVersion = () => {
54
54
  getLatestVersion(exports.name)
55
55
  .then((version) => {
56
56
  if (version) {
57
- const lastCheckFile = path_1.join(os_1.tmpdir(), VERSION_CACHE_FILE);
58
- fs_1.writeFileSync(lastCheckFile, version);
57
+ const lastCheckFile = (0, path_1.join)((0, os_1.tmpdir)(), VERSION_CACHE_FILE);
58
+ (0, fs_1.writeFileSync)(lastCheckFile, version);
59
59
  }
60
60
  })
61
61
  .catch(() => { });
@@ -63,39 +63,39 @@ const cacheLatestVersion = () => {
63
63
  exports.cacheLatestVersion = cacheLatestVersion;
64
64
  const renderUpdateBanner = (current, latest) => {
65
65
  const messageLines = [
66
- `A new version of ${colorette_1.cyan('Redocly CLI')} (${colorette_1.green(latest)}) is available.`,
67
- `Update now: \`${colorette_1.cyan('npm i -g @redocly/cli@latest')}\`.`,
66
+ `A new version of ${(0, colorette_1.cyan)('Redocly CLI')} (${(0, colorette_1.green)(latest)}) is available.`,
67
+ `Update now: \`${(0, colorette_1.cyan)('npm i -g @redocly/cli@latest')}\`.`,
68
68
  `Changelog: https://redocly.com/docs/cli/changelog/`,
69
69
  ];
70
- const maxLength = Math.max(...messageLines.map((line) => utils_1.cleanColors(line).length));
71
- const border = colorette_1.yellow('═'.repeat(maxLength + SPACE_TO_BORDER));
70
+ const maxLength = Math.max(...messageLines.map((line) => (0, utils_1.cleanColors)(line).length));
71
+ const border = (0, colorette_1.yellow)('═'.repeat(maxLength + SPACE_TO_BORDER));
72
72
  const banner = `
73
- ${colorette_1.yellow('╔' + border + '╗')}
74
- ${colorette_1.yellow('║' + ' '.repeat(maxLength + SPACE_TO_BORDER) + '║')}
73
+ ${(0, colorette_1.yellow)('╔' + border + '╗')}
74
+ ${(0, colorette_1.yellow)('║' + ' '.repeat(maxLength + SPACE_TO_BORDER) + '║')}
75
75
  ${messageLines
76
76
  .map((line, index) => {
77
77
  return getLineWithPadding(maxLength, line, index);
78
78
  })
79
79
  .join('\n')}
80
- ${colorette_1.yellow('║' + ' '.repeat(maxLength + SPACE_TO_BORDER) + '║')}
81
- ${colorette_1.yellow('╚' + border + '╝')}
80
+ ${(0, colorette_1.yellow)('║' + ' '.repeat(maxLength + SPACE_TO_BORDER) + '║')}
81
+ ${(0, colorette_1.yellow)('╚' + border + '╝')}
82
82
  `;
83
83
  process.stderr.write(banner);
84
84
  };
85
85
  const getLineWithPadding = (maxLength, line, index) => {
86
- const padding = ' '.repeat(maxLength - utils_1.cleanColors(line).length);
86
+ const padding = ' '.repeat(maxLength - (0, utils_1.cleanColors)(line).length);
87
87
  const extraSpaces = index !== 0 ? ' '.repeat(SPACE_TO_BORDER) : '';
88
- return `${extraSpaces}${colorette_1.yellow('║')} ${line}${padding} ${colorette_1.yellow('║')}`;
88
+ return `${extraSpaces}${(0, colorette_1.yellow)('║')} ${line}${padding} ${(0, colorette_1.yellow)('║')}`;
89
89
  };
90
90
  const isNeedToBeCached = () => {
91
91
  try {
92
92
  // Last version from npm is stored in a file in the OS temp folder
93
- const versionFile = path_1.join(os_1.tmpdir(), VERSION_CACHE_FILE);
94
- if (!fs_1.existsSync(versionFile)) {
93
+ const versionFile = (0, path_1.join)((0, os_1.tmpdir)(), VERSION_CACHE_FILE);
94
+ if (!(0, fs_1.existsSync)(versionFile)) {
95
95
  return true;
96
96
  }
97
97
  const now = new Date().getTime();
98
- const stats = fs_1.statSync(versionFile);
98
+ const stats = (0, fs_1.statSync)(versionFile);
99
99
  const lastCheck = stats.mtime.getTime();
100
100
  return now - lastCheck >= INTERVAL_TO_CHECK;
101
101
  }
package/lib/utils.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { BundleOutputFormat, StyleguideConfig, RawConfig, Region, Config, Oas3Definition, Oas2Definition } from '@redocly/openapi-core';
2
- import { Totals, Entrypoint, ConfigApis, CommandOptions } from './types';
2
+ import { Totals, Entrypoint, ConfigApis, CommandOptions, OutputExtensions } from './types';
3
3
  import { Arguments } from 'yargs';
4
4
  export declare function getFallbackApisOrExit(argsApis: string[] | undefined, config: ConfigApis): Promise<Entrypoint[]>;
5
5
  export declare function getExecutionTime(startedAt: number): string;
@@ -15,7 +15,10 @@ export declare function dumpBundle(obj: any, format: BundleOutputFormat, derefer
15
15
  export declare function saveBundle(filename: string, output: string): void;
16
16
  export declare function promptUser(query: string, hideUserInput?: boolean): Promise<string>;
17
17
  export declare function readYaml(filename: string): unknown;
18
+ export declare function writeToFileByExtension(data: unknown, filePath: string, noRefs?: boolean): void;
18
19
  export declare function writeYaml(data: any, filename: string, noRefs?: boolean): void;
20
+ export declare function writeJson(data: unknown, filename: string): void;
21
+ export declare function getAndValidateFileExtension(fileName: string): NonNullable<OutputExtensions>;
19
22
  export declare function pluralize(label: string, num: number): string;
20
23
  export declare function handleError(e: Error, ref: string): void;
21
24
  export declare class HandledError extends Error {
@@ -43,8 +46,8 @@ export declare function sortTopLevelKeysForOas(document: Oas3Definition | Oas2De
43
46
  export declare function checkIfRulesetExist(rules: typeof StyleguideConfig.prototype.rules): void;
44
47
  export declare function cleanColors(input: string): string;
45
48
  export declare function sendTelemetry(argv: Arguments | undefined, exit_code: ExitCode, has_config: boolean | undefined): Promise<void>;
46
- export declare type ExitCode = 0 | 1 | 2;
47
- export declare type Analytics = {
49
+ export type ExitCode = 0 | 1 | 2;
50
+ export type Analytics = {
48
51
  event: string;
49
52
  event_time: string;
50
53
  logged_in: boolean;
package/lib/utils.js CHANGED
@@ -20,7 +20,7 @@ var __rest = (this && this.__rest) || function (s, e) {
20
20
  return t;
21
21
  };
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
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;
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.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;
24
24
  const fetch_with_timeout_1 = require("./fetch-with-timeout");
25
25
  const path_1 = require("path");
26
26
  const colorette_1 = require("colorette");
@@ -46,7 +46,7 @@ function getFallbackApisOrExit(argsApis, config) {
46
46
  const filteredInvalidEntrypoints = res.filter(({ path }) => !isApiPathValid(path));
47
47
  if (isNotEmptyArray(filteredInvalidEntrypoints)) {
48
48
  for (const { path } of filteredInvalidEntrypoints) {
49
- process.stderr.write(colorette_1.yellow(`\n${path_1.relative(process.cwd(), path)} ${colorette_1.red(`does not exist or is invalid.\n\n`)}`));
49
+ 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`)}`));
50
50
  }
51
51
  exitWithError('Please provide a valid path.');
52
52
  }
@@ -55,7 +55,7 @@ function getFallbackApisOrExit(argsApis, config) {
55
55
  }
56
56
  exports.getFallbackApisOrExit = getFallbackApisOrExit;
57
57
  function getConfigDirectory(config) {
58
- return config.configFile ? path_1.dirname(config.configFile) : process.cwd();
58
+ return config.configFile ? (0, path_1.dirname)(config.configFile) : process.cwd();
59
59
  }
60
60
  function isNotEmptyArray(args) {
61
61
  return Array.isArray(args) && !!args.length;
@@ -65,11 +65,11 @@ function isApiPathValid(apiPath) {
65
65
  exitWithError('Path cannot be empty.');
66
66
  return;
67
67
  }
68
- return fs.existsSync(apiPath) || openapi_core_1.isAbsoluteUrl(apiPath) ? apiPath : undefined;
68
+ return fs.existsSync(apiPath) || (0, openapi_core_1.isAbsoluteUrl)(apiPath) ? apiPath : undefined;
69
69
  }
70
70
  function fallbackToAllDefinitions(apis, config) {
71
71
  return Object.entries(apis).map(([alias, { root }]) => ({
72
- path: openapi_core_1.isAbsoluteUrl(root) ? root : path_1.resolve(getConfigDirectory(config), root),
72
+ path: (0, openapi_core_1.isAbsoluteUrl)(root) ? root : (0, path_1.resolve)(getConfigDirectory(config), root),
73
73
  alias,
74
74
  }));
75
75
  }
@@ -81,14 +81,14 @@ function getAliasOrPath(config, aliasOrPath) {
81
81
  path: aliasOrPath,
82
82
  // find alias by path, take the first match
83
83
  alias: (_c = (_b = Object.entries(config.apis).find(([_alias, api]) => {
84
- return path_1.resolve(api.root) === path_1.resolve(aliasOrPath);
84
+ return (0, path_1.resolve)(api.root) === (0, path_1.resolve)(aliasOrPath);
85
85
  })) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : undefined,
86
86
  };
87
87
  }
88
88
  function expandGlobsInEntrypoints(args, config) {
89
89
  return __awaiter(this, void 0, void 0, function* () {
90
90
  return (yield Promise.all(args.map((aliasOrPath) => __awaiter(this, void 0, void 0, function* () {
91
- return glob.hasMagic(aliasOrPath) && !openapi_core_1.isAbsoluteUrl(aliasOrPath)
91
+ return glob.hasMagic(aliasOrPath) && !(0, openapi_core_1.isAbsoluteUrl)(aliasOrPath)
92
92
  ? (yield glob.__promisify__(aliasOrPath)).map((g) => getAliasOrPath(config, g))
93
93
  : getAliasOrPath(config, aliasOrPath);
94
94
  })))).flat();
@@ -102,7 +102,7 @@ function getExecutionTime(startedAt) {
102
102
  exports.getExecutionTime = getExecutionTime;
103
103
  function printExecutionTime(commandName, startedAt, api) {
104
104
  const elapsed = getExecutionTime(startedAt);
105
- process.stderr.write(colorette_1.gray(`\n${api}: ${commandName} processed in ${elapsed}\n\n`));
105
+ process.stderr.write((0, colorette_1.gray)(`\n${api}: ${commandName} processed in ${elapsed}\n\n`));
106
106
  }
107
107
  exports.printExecutionTime = printExecutionTime;
108
108
  function pathToFilename(path, pathSeparator) {
@@ -153,7 +153,7 @@ function dumpBundle(obj, format, dereference) {
153
153
  }
154
154
  }
155
155
  else {
156
- return openapi_core_1.stringifyYaml(obj, {
156
+ return (0, openapi_core_1.stringifyYaml)(obj, {
157
157
  noRefs: !dereference,
158
158
  lineWidth: -1,
159
159
  });
@@ -161,7 +161,7 @@ function dumpBundle(obj, format, dereference) {
161
161
  }
162
162
  exports.dumpBundle = dumpBundle;
163
163
  function saveBundle(filename, output) {
164
- fs.mkdirSync(path_1.dirname(filename), { recursive: true });
164
+ fs.mkdirSync((0, path_1.dirname)(filename), { recursive: true });
165
165
  fs.writeFileSync(filename, output);
166
166
  }
167
167
  exports.saveBundle = saveBundle;
@@ -196,19 +196,47 @@ function promptUser(query, hideUserInput = false) {
196
196
  }
197
197
  exports.promptUser = promptUser;
198
198
  function readYaml(filename) {
199
- return openapi_core_1.parseYaml(fs.readFileSync(filename, 'utf-8'), { filename });
199
+ return (0, openapi_core_1.parseYaml)(fs.readFileSync(filename, 'utf-8'), { filename });
200
200
  }
201
201
  exports.readYaml = readYaml;
202
+ function writeToFileByExtension(data, filePath, noRefs) {
203
+ const ext = getAndValidateFileExtension(filePath);
204
+ if (ext === 'json') {
205
+ writeJson(data, filePath);
206
+ return;
207
+ }
208
+ writeYaml(data, filePath, noRefs);
209
+ }
210
+ exports.writeToFileByExtension = writeToFileByExtension;
202
211
  function writeYaml(data, filename, noRefs = false) {
203
- const content = openapi_core_1.stringifyYaml(data, { noRefs });
212
+ const content = (0, openapi_core_1.stringifyYaml)(data, { noRefs });
204
213
  if (process.env.NODE_ENV === 'test') {
205
214
  process.stderr.write(content);
206
215
  return;
207
216
  }
208
- fs.mkdirSync(path_1.dirname(filename), { recursive: true });
217
+ fs.mkdirSync((0, path_1.dirname)(filename), { recursive: true });
209
218
  fs.writeFileSync(filename, content);
210
219
  }
211
220
  exports.writeYaml = writeYaml;
221
+ function writeJson(data, filename) {
222
+ const content = JSON.stringify(data, null, 2);
223
+ if (process.env.NODE_ENV === 'test') {
224
+ process.stderr.write(content);
225
+ return;
226
+ }
227
+ fs.mkdirSync((0, path_1.dirname)(filename), { recursive: true });
228
+ fs.writeFileSync(filename, content);
229
+ }
230
+ exports.writeJson = writeJson;
231
+ function getAndValidateFileExtension(fileName) {
232
+ const ext = fileName.split('.').pop();
233
+ if (['yaml', 'yml', 'json'].includes(ext)) {
234
+ return ext;
235
+ }
236
+ process.stderr.write((0, colorette_1.yellow)(`Unsupported file extension: ${ext}. Using yaml.\n`));
237
+ return 'yaml';
238
+ }
239
+ exports.getAndValidateFileExtension = getAndValidateFileExtension;
212
240
  function pluralize(label, num) {
213
241
  if (label.endsWith('is')) {
214
242
  [label] = label.split(' ');
@@ -229,7 +257,7 @@ function handleError(e, ref) {
229
257
  return exitWithError(`Failed to parse API description at ${ref}:\n\n - ${e.message}.`);
230
258
  case CircularJSONNotSupportedError: {
231
259
  return exitWithError(`Detected circular reference which can't be converted to JSON.\n` +
232
- `Try to use ${colorette_1.blue('yaml')} output or remove ${colorette_1.blue('--dereferenced')}.`);
260
+ `Try to use ${(0, colorette_1.blue)('yaml')} output or remove ${(0, colorette_1.blue)('--dereferenced')}.`);
233
261
  }
234
262
  case SyntaxError:
235
263
  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]}`);
@@ -246,32 +274,32 @@ class HandledError extends Error {
246
274
  exports.HandledError = HandledError;
247
275
  function printLintTotals(totals, definitionsCount) {
248
276
  const ignored = totals.ignored
249
- ? colorette_1.yellow(`${totals.ignored} ${pluralize('problem is', totals.ignored)} explicitly ignored.\n\n`)
277
+ ? (0, colorette_1.yellow)(`${totals.ignored} ${pluralize('problem is', totals.ignored)} explicitly ignored.\n\n`)
250
278
  : '';
251
279
  if (totals.errors > 0) {
252
- process.stderr.write(colorette_1.red(`❌ Validation failed with ${totals.errors} ${pluralize('error', totals.errors)}${totals.warnings > 0
280
+ process.stderr.write((0, colorette_1.red)(`❌ Validation failed with ${totals.errors} ${pluralize('error', totals.errors)}${totals.warnings > 0
253
281
  ? ` and ${totals.warnings} ${pluralize('warning', totals.warnings)}`
254
282
  : ''}.\n${ignored}`));
255
283
  }
256
284
  else if (totals.warnings > 0) {
257
- process.stderr.write(colorette_1.green(`Woohoo! Your API ${pluralize('description is', definitionsCount)} valid. 🎉\n`));
258
- process.stderr.write(colorette_1.yellow(`You have ${totals.warnings} ${pluralize('warning', totals.warnings)}.\n${ignored}`));
285
+ process.stderr.write((0, colorette_1.green)(`Woohoo! Your API ${pluralize('description is', definitionsCount)} valid. 🎉\n`));
286
+ process.stderr.write((0, colorette_1.yellow)(`You have ${totals.warnings} ${pluralize('warning', totals.warnings)}.\n${ignored}`));
259
287
  }
260
288
  else {
261
- process.stderr.write(colorette_1.green(`Woohoo! Your API ${pluralize('description is', definitionsCount)} valid. 🎉\n${ignored}`));
289
+ process.stderr.write((0, colorette_1.green)(`Woohoo! Your API ${pluralize('description is', definitionsCount)} valid. 🎉\n${ignored}`));
262
290
  }
263
291
  if (totals.errors > 0) {
264
- process.stderr.write(colorette_1.gray(`run \`redocly lint --generate-ignore-file\` to add all problems to the ignore file.\n`));
292
+ process.stderr.write((0, colorette_1.gray)(`run \`redocly lint --generate-ignore-file\` to add all problems to the ignore file.\n`));
265
293
  }
266
294
  process.stderr.write('\n');
267
295
  }
268
296
  exports.printLintTotals = printLintTotals;
269
297
  function printConfigLintTotals(totals) {
270
298
  if (totals.errors > 0) {
271
- process.stderr.write(colorette_1.red(`❌ Your config has ${totals.errors} ${pluralize('error', totals.errors)}.`));
299
+ process.stderr.write((0, colorette_1.red)(`❌ Your config has ${totals.errors} ${pluralize('error', totals.errors)}.`));
272
300
  }
273
301
  else if (totals.warnings > 0) {
274
- process.stderr.write(colorette_1.yellow(`⚠️ Your config has ${totals.warnings} ${pluralize('warning', totals.warnings)}.\n`));
302
+ process.stderr.write((0, colorette_1.yellow)(`⚠️ Your config has ${totals.warnings} ${pluralize('warning', totals.warnings)}.\n`));
275
303
  }
276
304
  }
277
305
  exports.printConfigLintTotals = printConfigLintTotals;
@@ -281,21 +309,21 @@ function getOutputFileName(entrypoint, entries, output, ext) {
281
309
  }
282
310
  let outputFile = output;
283
311
  if (entries > 1) {
284
- ext = ext || path_1.extname(entrypoint).substring(1);
312
+ ext = ext || (0, path_1.extname)(entrypoint).substring(1);
285
313
  if (!types_1.outputExtensions.includes(ext)) {
286
314
  throw new Error(`Invalid file extension: ${ext}.`);
287
315
  }
288
- outputFile = path_1.join(output, path_1.basename(entrypoint, path_1.extname(entrypoint))) + '.' + ext;
316
+ outputFile = (0, path_1.join)(output, (0, path_1.basename)(entrypoint, (0, path_1.extname)(entrypoint))) + '.' + ext;
289
317
  }
290
318
  else {
291
319
  if (output) {
292
- ext = ext || path_1.extname(output).substring(1);
320
+ ext = ext || (0, path_1.extname)(output).substring(1);
293
321
  }
294
- ext = ext || path_1.extname(entrypoint).substring(1);
322
+ ext = ext || (0, path_1.extname)(entrypoint).substring(1);
295
323
  if (!types_1.outputExtensions.includes(ext)) {
296
324
  throw new Error(`Invalid file extension: ${ext}.`);
297
325
  }
298
- outputFile = path_1.join(path_1.dirname(outputFile), path_1.basename(outputFile, path_1.extname(outputFile))) + '.' + ext;
326
+ outputFile = (0, path_1.join)((0, path_1.dirname)(outputFile), (0, path_1.basename)(outputFile, (0, path_1.extname)(outputFile))) + '.' + ext;
299
327
  }
300
328
  return { outputFile, ext };
301
329
  }
@@ -303,13 +331,13 @@ exports.getOutputFileName = getOutputFileName;
303
331
  function printUnusedWarnings(config) {
304
332
  const { preprocessors, rules, decorators } = config.getUnusedRules();
305
333
  if (rules.length) {
306
- process.stderr.write(colorette_1.yellow(`[WARNING] Unused rules found in ${colorette_1.blue(config.configFile || '')}: ${rules.join(', ')}.\n`));
334
+ process.stderr.write((0, colorette_1.yellow)(`[WARNING] Unused rules found in ${(0, colorette_1.blue)(config.configFile || '')}: ${rules.join(', ')}.\n`));
307
335
  }
308
336
  if (preprocessors.length) {
309
- process.stderr.write(colorette_1.yellow(`[WARNING] Unused preprocessors found in ${colorette_1.blue(config.configFile || '')}: ${preprocessors.join(', ')}.\n`));
337
+ process.stderr.write((0, colorette_1.yellow)(`[WARNING] Unused preprocessors found in ${(0, colorette_1.blue)(config.configFile || '')}: ${preprocessors.join(', ')}.\n`));
310
338
  }
311
339
  if (decorators.length) {
312
- process.stderr.write(colorette_1.yellow(`[WARNING] Unused decorators found in ${colorette_1.blue(config.configFile || '')}: ${decorators.join(', ')}.\n`));
340
+ process.stderr.write((0, colorette_1.yellow)(`[WARNING] Unused decorators found in ${(0, colorette_1.blue)(config.configFile || '')}: ${decorators.join(', ')}.\n`));
313
341
  }
314
342
  if (rules.length || preprocessors.length) {
315
343
  process.stderr.write(`Check the spelling and verify the added plugin prefix.\n`);
@@ -317,7 +345,7 @@ function printUnusedWarnings(config) {
317
345
  }
318
346
  exports.printUnusedWarnings = printUnusedWarnings;
319
347
  function exitWithError(message) {
320
- process.stderr.write(colorette_1.red(message) + '\n\n');
348
+ process.stderr.write((0, colorette_1.red)(message) + '\n\n');
321
349
  throw new HandledError(message);
322
350
  }
323
351
  exports.exitWithError = exitWithError;
@@ -325,14 +353,14 @@ exports.exitWithError = exitWithError;
325
353
  * Checks if dir is subdir of parent
326
354
  */
327
355
  function isSubdir(parent, dir) {
328
- const relativePath = path_1.relative(parent, dir);
329
- return !!relativePath && !/^..($|\/)/.test(relativePath) && !path_1.isAbsolute(relativePath);
356
+ const relativePath = (0, path_1.relative)(parent, dir);
357
+ return !!relativePath && !/^..($|\/)/.test(relativePath) && !(0, path_1.isAbsolute)(relativePath);
330
358
  }
331
359
  exports.isSubdir = isSubdir;
332
360
  function loadConfigAndHandleErrors(options = {}) {
333
361
  return __awaiter(this, void 0, void 0, function* () {
334
362
  try {
335
- return yield openapi_core_1.loadConfig(options);
363
+ return yield (0, openapi_core_1.loadConfig)(options);
336
364
  }
337
365
  catch (e) {
338
366
  handleError(e, '');
@@ -399,7 +427,7 @@ function sortOas3Keys(document) {
399
427
  }
400
428
  function checkIfRulesetExist(rules) {
401
429
  const ruleset = Object.assign(Object.assign(Object.assign({}, rules.oas2), rules.oas3_0), rules.oas3_0);
402
- if (utils_1.isEmptyObject(ruleset)) {
430
+ if ((0, utils_1.isEmptyObject)(ruleset)) {
403
431
  exitWithError('⚠️ No rules were configured. Learn how to configure rules: https://redocly.com/docs/cli/rules/');
404
432
  }
405
433
  }
@@ -426,7 +454,7 @@ function sendTelemetry(argv, exit_code, has_config) {
426
454
  command,
427
455
  arguments: cleanArgs(args),
428
456
  node_version: process.version,
429
- npm_version: child_process_1.execSync('npm -v').toString().replace('\n', ''),
457
+ npm_version: (0, child_process_1.execSync)('npm -v').toString().replace('\n', ''),
430
458
  version: update_version_notifier_1.version,
431
459
  exit_code,
432
460
  environment: process.env.REDOCLY_ENVIRONMENT,
@@ -434,7 +462,7 @@ function sendTelemetry(argv, exit_code, has_config) {
434
462
  raw_input: cleanRawInput(process.argv.slice(2)),
435
463
  has_config,
436
464
  };
437
- yield fetch_with_timeout_1.default(`https://api.redocly.com/registry/telemetry/cli`, {
465
+ yield (0, fetch_with_timeout_1.default)(`https://api.redocly.com/registry/telemetry/cli`, {
438
466
  method: 'POST',
439
467
  headers: {
440
468
  'content-type': 'application/json',
@@ -458,7 +486,7 @@ function cleanString(value) {
458
486
  if (!value) {
459
487
  return value;
460
488
  }
461
- if (openapi_core_1.isAbsoluteUrl(value)) {
489
+ if ((0, openapi_core_1.isAbsoluteUrl)(value)) {
462
490
  return value.split('://')[0] + '://url';
463
491
  }
464
492
  if (isFile(value)) {
package/lib/wrapper.js CHANGED
@@ -20,15 +20,15 @@ function commandWrapper(commandHandler) {
20
20
  let hasConfig;
21
21
  let telemetry;
22
22
  try {
23
- if (argv.config && !openapi_core_1.doesYamlFileExist(argv.config)) {
24
- utils_1.exitWithError('Please, provide valid path to the configuration file');
23
+ if (argv.config && !(0, openapi_core_1.doesYamlFileExist)(argv.config)) {
24
+ (0, utils_1.exitWithError)('Please, provide valid path to the configuration file');
25
25
  }
26
- const config = (yield utils_1.loadConfigAndHandleErrors({
26
+ const config = (yield (0, utils_1.loadConfigAndHandleErrors)({
27
27
  configPath: argv.config,
28
28
  customExtends: argv.extends,
29
29
  region: argv.region,
30
30
  files: argv.files,
31
- processRawConfig: lint_1.lintConfigCallback(argv, update_version_notifier_1.version),
31
+ processRawConfig: (0, lint_1.lintConfigCallback)(argv, update_version_notifier_1.version),
32
32
  }));
33
33
  telemetry = config.telemetry;
34
34
  hasConfig = !config.styleguide.recommendedFallback;
@@ -41,7 +41,7 @@ function commandWrapper(commandHandler) {
41
41
  }
42
42
  finally {
43
43
  if (process.env.REDOCLY_TELEMETRY !== 'off' && telemetry !== 'off') {
44
- yield utils_1.sendTelemetry(argv, code, hasConfig);
44
+ yield (0, utils_1.sendTelemetry)(argv, code, hasConfig);
45
45
  }
46
46
  process.once('beforeExit', () => {
47
47
  process.exit(code);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/cli",
3
- "version": "1.3.0",
3
+ "version": "1.4.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.3.0",
39
+ "@redocly/openapi-core": "1.4.0",
40
40
  "chokidar": "^3.5.1",
41
41
  "colorette": "^1.2.0",
42
42
  "core-js": "^3.32.1",
@@ -59,6 +59,6 @@
59
59
  "@types/react-dom": "^17.0.0 || ^18.2.7",
60
60
  "@types/semver": "^7.5.0",
61
61
  "@types/yargs": "17.0.5",
62
- "typescript": "^4.0.3"
62
+ "typescript": "^5.2.2"
63
63
  }
64
64
  }
@@ -31,6 +31,7 @@ export const doesYamlFileExist = jest.fn();
31
31
  export const bundleDocument = jest.fn(() => Promise.resolve({ problems: {} }));
32
32
  export const detectSpec = jest.fn();
33
33
  export const isAbsoluteUrl = jest.fn();
34
+ export const stringifyYaml = jest.fn((data) => data);
34
35
 
35
36
  export class BaseResolver {
36
37
  cache = new Map<string, Promise<Document | ResolveError>>();
@@ -17,3 +17,5 @@ export const writeYaml = jest.fn();
17
17
  export const loadConfigAndHandleErrors = jest.fn(() => ConfigFixture);
18
18
  export const checkIfRulesetExist = jest.fn();
19
19
  export const sortTopLevelKeysForOas = jest.fn((document) => document);
20
+ export const getAndValidateFileExtension = jest.fn((fileName: string) => fileName.split('.').pop());
21
+ export const writeToFileByExtension = jest.fn();