@redocly/cli 1.10.6 → 1.12.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 (39) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/lib/__tests__/commands/bundle.test.js +3 -32
  3. package/lib/__tests__/commands/join.test.js +0 -11
  4. package/lib/__tests__/utils.test.js +3 -3
  5. package/lib/cms/api/types.d.ts +22 -11
  6. package/lib/cms/commands/__tests__/push-status.test.js +338 -29
  7. package/lib/cms/commands/__tests__/push.test.js +32 -2
  8. package/lib/cms/commands/__tests__/utils.test.d.ts +1 -0
  9. package/lib/cms/commands/__tests__/utils.test.js +60 -0
  10. package/lib/cms/commands/push-status.d.ts +14 -4
  11. package/lib/cms/commands/push-status.js +160 -90
  12. package/lib/cms/commands/push.d.ts +6 -2
  13. package/lib/cms/commands/push.js +8 -2
  14. package/lib/cms/commands/utils.d.ts +22 -0
  15. package/lib/cms/commands/utils.js +53 -0
  16. package/lib/commands/bundle.d.ts +1 -4
  17. package/lib/commands/bundle.js +2 -32
  18. package/lib/commands/join.d.ts +0 -3
  19. package/lib/commands/join.js +13 -36
  20. package/lib/index.js +69 -27
  21. package/lib/utils/miscellaneous.js +5 -4
  22. package/lib/wrapper.d.ts +1 -1
  23. package/package.json +2 -2
  24. package/src/__tests__/commands/bundle.test.ts +4 -37
  25. package/src/__tests__/commands/join.test.ts +0 -17
  26. package/src/__tests__/utils.test.ts +3 -3
  27. package/src/cms/api/types.ts +19 -12
  28. package/src/cms/commands/__tests__/push-status.test.ts +473 -47
  29. package/src/cms/commands/__tests__/push.test.ts +40 -2
  30. package/src/cms/commands/__tests__/utils.test.ts +62 -0
  31. package/src/cms/commands/push-status.ts +242 -120
  32. package/src/cms/commands/push.ts +21 -5
  33. package/src/cms/commands/utils.ts +52 -0
  34. package/src/commands/bundle.ts +3 -53
  35. package/src/commands/join.ts +13 -49
  36. package/src/index.ts +89 -28
  37. package/src/utils/miscellaneous.ts +5 -4
  38. package/src/wrapper.ts +1 -1
  39. package/tsconfig.tsbuildinfo +1 -1
package/lib/index.js CHANGED
@@ -12,6 +12,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  require("./utils/assert-node-version");
14
14
  const yargs = require("yargs");
15
+ const colors = require("colorette");
15
16
  const types_1 = require("./types");
16
17
  const openapi_core_1 = require("@redocly/openapi-core");
17
18
  const preview_docs_1 = require("./commands/preview-docs");
@@ -92,9 +93,6 @@ yargs
92
93
  demandOption: true,
93
94
  })
94
95
  .option({
95
- lint: { description: 'Lint descriptions', type: 'boolean', default: false, hidden: true },
96
- decorate: { description: 'Run decorators', type: 'boolean', default: false },
97
- preprocess: { description: 'Run preprocessors', type: 'boolean', default: false },
98
96
  'prefix-tags-with-info-prop': {
99
97
  description: 'Prefix tags with property value from info object.',
100
98
  requiresArg: true,
@@ -129,7 +127,34 @@ yargs
129
127
  choices: ['warn', 'error', 'off'],
130
128
  default: 'warn',
131
129
  },
130
+ lint: {
131
+ hidden: true,
132
+ deprecated: true,
133
+ },
134
+ decorate: {
135
+ hidden: true,
136
+ deprecated: true,
137
+ },
138
+ preprocess: {
139
+ hidden: true,
140
+ deprecated: true,
141
+ },
132
142
  }), (argv) => {
143
+ const DEPRECATED_OPTIONS = ['lint', 'preprocess', 'decorate'];
144
+ const DECORATORS_DOCUMENTATION_LINK = 'https://redocly.com/docs/cli/decorators/#decorators';
145
+ const JOIN_COMMAND_DOCUMENTATION_LINK = 'https://redocly.com/docs/cli/commands/join/#join';
146
+ DEPRECATED_OPTIONS.forEach((option) => {
147
+ if (argv[option]) {
148
+ process.stdout.write(`${colors.red(`Option --${option} is no longer supported. Please review join command documentation ${JOIN_COMMAND_DOCUMENTATION_LINK}.`)}`);
149
+ process.stdout.write('\n\n');
150
+ if (['preprocess', 'decorate'].includes(option)) {
151
+ process.stdout.write(`${colors.red(`If you are looking for decorators, please review the decorators documentation ${DECORATORS_DOCUMENTATION_LINK}.`)}`);
152
+ process.stdout.write('\n\n');
153
+ }
154
+ yargs.showHelp();
155
+ process.exit(1);
156
+ }
157
+ });
133
158
  process.env.REDOCLY_CLI_COMMAND = 'join';
134
159
  (0, wrapper_1.commandWrapper)(join_1.handleJoin)(argv);
135
160
  })
@@ -149,9 +174,10 @@ yargs
149
174
  project: {
150
175
  description: 'Name of the project to push to.',
151
176
  type: 'string',
177
+ required: true,
152
178
  alias: 'p',
153
179
  },
154
- domain: { description: 'Specify a domain.', alias: 'd', type: 'string' },
180
+ domain: { description: 'Specify a domain.', alias: 'd', type: 'string', required: false },
155
181
  wait: {
156
182
  description: 'Wait for build to finish.',
157
183
  type: 'boolean',
@@ -161,6 +187,11 @@ yargs
161
187
  description: 'Maximum execution time in seconds.',
162
188
  type: 'number',
163
189
  },
190
+ 'continue-on-deploy-failures': {
191
+ description: 'Command does not fail even if the deployment fails.',
192
+ type: 'boolean',
193
+ default: false,
194
+ },
164
195
  }), (argv) => {
165
196
  process.env.REDOCLY_CLI_COMMAND = 'push-status';
166
197
  (0, wrapper_1.commandWrapper)(push_status_1.handlePushStatus)(argv);
@@ -314,6 +345,11 @@ yargs
314
345
  type: 'boolean',
315
346
  default: false,
316
347
  },
348
+ 'continue-on-deploy-failures': {
349
+ description: 'Command does not fail even if the deployment fails.',
350
+ type: 'boolean',
351
+ default: false,
352
+ },
317
353
  }), (argv) => {
318
354
  process.env.REDOCLY_CLI_COMMAND = 'push';
319
355
  (0, wrapper_1.commandWrapper)((0, push_1.commonPushHandler)(argv))(argv);
@@ -328,6 +364,7 @@ yargs
328
364
  'checkstyle',
329
365
  'codeclimate',
330
366
  'summary',
367
+ 'github-actions',
331
368
  ],
332
369
  default: 'codeframe',
333
370
  },
@@ -377,28 +414,11 @@ yargs
377
414
  description: 'Output file.',
378
415
  alias: 'o',
379
416
  },
380
- format: {
381
- description: 'Use a specific output format.',
382
- choices: ['stylish', 'codeframe', 'json', 'checkstyle'],
383
- hidden: true,
384
- },
385
- 'max-problems': {
386
- requiresArg: true,
387
- description: 'Reduce output to a maximum of N problems.',
388
- type: 'number',
389
- hidden: true,
390
- },
391
417
  ext: {
392
418
  description: 'Bundle file extension.',
393
419
  requiresArg: true,
394
420
  choices: types_1.outputExtensions,
395
421
  },
396
- 'skip-rule': {
397
- description: 'Ignore certain rules.',
398
- array: true,
399
- type: 'string',
400
- hidden: true,
401
- },
402
422
  'skip-preprocessor': {
403
423
  description: 'Ignore certain preprocessors.',
404
424
  array: true,
@@ -423,12 +443,6 @@ yargs
423
443
  description: 'Path to the config file.',
424
444
  type: 'string',
425
445
  },
426
- lint: {
427
- description: 'Lint API descriptions',
428
- type: 'boolean',
429
- default: false,
430
- hidden: true,
431
- },
432
446
  metafile: {
433
447
  description: 'Produce metadata about the bundle',
434
448
  type: 'string',
@@ -455,7 +469,35 @@ yargs
455
469
  choices: ['warn', 'error', 'off'],
456
470
  default: 'warn',
457
471
  },
472
+ format: {
473
+ hidden: true,
474
+ deprecated: true,
475
+ },
476
+ lint: {
477
+ hidden: true,
478
+ deprecated: true,
479
+ },
480
+ 'skip-rule': {
481
+ hidden: true,
482
+ deprecated: true,
483
+ array: true,
484
+ type: 'string',
485
+ },
486
+ 'max-problems': {
487
+ hidden: true,
488
+ deprecated: true,
489
+ },
458
490
  }), (argv) => {
491
+ const DEPRECATED_OPTIONS = ['lint', 'format', 'skip-rule', 'max-problems'];
492
+ const LINT_AND_BUNDLE_DOCUMENTATION_LINK = 'https://redocly.com/docs/cli/guides/lint-and-bundle/#lint-and-bundle-api-descriptions-with-redocly-cli';
493
+ DEPRECATED_OPTIONS.forEach((option) => {
494
+ if (argv[option]) {
495
+ process.stdout.write(`${colors.red(`Option --${option} is no longer supported. Please use separate commands, as described in the ${LINT_AND_BUNDLE_DOCUMENTATION_LINK}.`)}`);
496
+ process.stdout.write('\n\n');
497
+ yargs.showHelp();
498
+ process.exit(1);
499
+ }
500
+ });
459
501
  process.env.REDOCLY_CLI_COMMAND = 'bundle';
460
502
  (0, wrapper_1.commandWrapper)(bundle_1.handleBundle)(argv);
461
503
  })
@@ -30,6 +30,7 @@ const fs = require("fs");
30
30
  const readline = require("readline");
31
31
  const stream_1 = require("stream");
32
32
  const child_process_1 = require("child_process");
33
+ const util_1 = require("util");
33
34
  const openapi_core_1 = require("@redocly/openapi-core");
34
35
  const types_1 = require("../types");
35
36
  const utils_1 = require("@redocly/openapi-core/lib/utils");
@@ -89,7 +90,7 @@ function expandGlobsInEntrypoints(args, config) {
89
90
  return __awaiter(this, void 0, void 0, function* () {
90
91
  return (yield Promise.all(args.map((aliasOrPath) => __awaiter(this, void 0, void 0, function* () {
91
92
  return glob.hasMagic(aliasOrPath) && !(0, openapi_core_1.isAbsoluteUrl)(aliasOrPath)
92
- ? (yield glob.__promisify__(aliasOrPath)).map((g) => getAliasOrPath(config, g))
93
+ ? (yield (0, util_1.promisify)(glob)(aliasOrPath)).map((g) => getAliasOrPath(config, g))
93
94
  : getAliasOrPath(config, aliasOrPath);
94
95
  })))).flat();
95
96
  });
@@ -270,9 +271,9 @@ function handleError(e, ref) {
270
271
  throw e;
271
272
  }
272
273
  case openapi_core_1.ResolveError:
273
- return exitWithError(`Failed to resolve API description at ${ref}:\n\n - ${e.message}.`);
274
+ return exitWithError(`Failed to resolve API description at ${ref}:\n\n - ${e.message}`);
274
275
  case openapi_core_1.YamlParseError:
275
- return exitWithError(`Failed to parse API description at ${ref}:\n\n - ${e.message}.`);
276
+ return exitWithError(`Failed to parse API description at ${ref}:\n\n - ${e.message}`);
276
277
  case CircularJSONNotSupportedError: {
277
278
  return exitWithError(`Detected circular reference which can't be converted to JSON.\n` +
278
279
  `Try to use ${(0, colorette_1.blue)('yaml')} output or remove ${(0, colorette_1.blue)('--dereferenced')}.`);
@@ -282,7 +283,7 @@ function handleError(e, ref) {
282
283
  case config_1.ConfigValidationError:
283
284
  return exitWithError(e.message);
284
285
  default: {
285
- exitWithError(`Something went wrong when processing ${ref}:\n\n - ${e.message}.`);
286
+ exitWithError(`Something went wrong when processing ${ref}:\n\n - ${e.message}`);
286
287
  }
287
288
  }
288
289
  }
package/lib/wrapper.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import { Config } from '@redocly/openapi-core';
2
2
  import type { Arguments } from 'yargs';
3
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>;
4
+ export declare function commandWrapper<T extends CommandOptions>(commandHandler?: (argv: T, config: Config, version: string) => Promise<unknown>): (argv: Arguments<T>) => Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/cli",
3
- "version": "1.10.6",
3
+ "version": "1.12.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.10.6",
39
+ "@redocly/openapi-core": "1.12.0",
40
40
  "abort-controller": "^3.0.0",
41
41
  "chokidar": "^3.5.1",
42
42
  "colorette": "^1.2.0",
@@ -1,4 +1,4 @@
1
- import { lint, bundle, getTotals, getMergedConfig } from '@redocly/openapi-core';
1
+ import { bundle, getTotals, getMergedConfig } from '@redocly/openapi-core';
2
2
 
3
3
  import { BundleOptions, handleBundle } from '../../commands/bundle';
4
4
  import { handleError } from '../../utils/miscellaneous';
@@ -25,21 +25,18 @@ describe('bundle', () => {
25
25
  });
26
26
 
27
27
  afterEach(() => {
28
- (lint as jest.Mock).mockClear();
29
28
  (bundle as jest.Mock).mockClear();
30
29
  (getTotals as jest.Mock).mockReset();
31
30
  });
32
31
 
33
- it('bundles definitions w/o linting', async () => {
32
+ it('bundles definitions', async () => {
34
33
  const apis = ['foo.yaml', 'bar.yaml'];
35
34
 
36
35
  await commandWrapper(handleBundle)({
37
36
  apis,
38
37
  ext: 'yaml',
39
- format: 'codeframe',
40
38
  } as Arguments<BundleOptions>);
41
39
 
42
- expect(lint).toBeCalledTimes(0);
43
40
  expect(bundle).toBeCalledTimes(apis.length);
44
41
  });
45
42
 
@@ -49,48 +46,25 @@ describe('bundle', () => {
49
46
  await commandWrapper(handleBundle)({
50
47
  apis,
51
48
  ext: 'yaml',
52
- format: 'codeframe',
53
49
  } as Arguments<BundleOptions>);
54
50
 
55
51
  await exitCb?.();
56
52
  expect(processExitMock).toHaveBeenCalledWith(0);
57
53
  });
58
54
 
59
- it('bundles definitions w/ linting', async () => {
60
- const apis = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
61
-
62
- (getTotals as jest.Mock).mockReturnValue({
63
- errors: 0,
64
- warnings: 0,
65
- ignored: 0,
66
- });
67
-
68
- await commandWrapper(handleBundle)({
69
- apis,
70
- ext: 'yaml',
71
- format: 'codeframe',
72
- lint: true,
73
- } as Arguments<BundleOptions>);
74
-
75
- expect(lint).toBeCalledTimes(apis.length);
76
- expect(bundle).toBeCalledTimes(apis.length);
77
- });
78
-
79
- it('exits with code 0 when bundles definitions w/linting w/o errors', async () => {
55
+ it('exits with code 0 when bundles definitions w/o errors', async () => {
80
56
  const apis = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
81
57
 
82
58
  await commandWrapper(handleBundle)({
83
59
  apis,
84
60
  ext: 'yaml',
85
- format: 'codeframe',
86
- lint: true,
87
61
  } as Arguments<BundleOptions>);
88
62
 
89
63
  await exitCb?.();
90
64
  expect(processExitMock).toHaveBeenCalledWith(0);
91
65
  });
92
66
 
93
- it('exits with code 1 when bundles definitions w/linting w/errors', async () => {
67
+ it('exits with code 1 when bundles definitions w/errors', async () => {
94
68
  const apis = ['foo.yaml'];
95
69
 
96
70
  (getTotals as jest.Mock).mockReturnValue({
@@ -102,11 +76,8 @@ describe('bundle', () => {
102
76
  await commandWrapper(handleBundle)({
103
77
  apis,
104
78
  ext: 'yaml',
105
- format: 'codeframe',
106
- lint: true,
107
79
  } as Arguments<BundleOptions>);
108
80
 
109
- expect(lint).toBeCalledTimes(apis.length);
110
81
  await exitCb?.();
111
82
  expect(processExitMock).toHaveBeenCalledWith(1);
112
83
  });
@@ -121,8 +92,6 @@ describe('bundle', () => {
121
92
  await commandWrapper(handleBundle)({
122
93
  apis,
123
94
  ext: 'json',
124
- format: 'codeframe',
125
- lint: false,
126
95
  } as Arguments<BundleOptions>);
127
96
 
128
97
  expect(handleError).toHaveBeenCalledTimes(1);
@@ -141,8 +110,6 @@ describe('bundle', () => {
141
110
  await commandWrapper(handleBundle)({
142
111
  apis,
143
112
  ext: 'yaml',
144
- format: 'codeframe',
145
- lint: false,
146
113
  } as Arguments<BundleOptions>);
147
114
 
148
115
  expect(handleError).toHaveBeenCalledTimes(0);
@@ -165,23 +165,6 @@ describe('handleJoin', () => {
165
165
  expect(config.styleguide.skipPreprocessors).toHaveBeenCalled();
166
166
  });
167
167
 
168
- it('should not call skipDecorators and skipPreprocessors', async () => {
169
- (detectSpec as jest.Mock).mockReturnValue('oas3_0');
170
- await handleJoin(
171
- {
172
- apis: ['first.yaml', 'second.yaml'],
173
- decorate: true,
174
- preprocess: true,
175
- },
176
- ConfigFixture as any,
177
- 'cli-version'
178
- );
179
-
180
- const config = loadConfig();
181
- expect(config.styleguide.skipDecorators).not.toHaveBeenCalled();
182
- expect(config.styleguide.skipPreprocessors).not.toHaveBeenCalled();
183
- });
184
-
185
168
  it('should handle join with prefix-components-with-info-prop and null values', async () => {
186
169
  (detectSpec as jest.Mock).mockReturnValue('oas3_0');
187
170
 
@@ -415,7 +415,7 @@ describe('handleErrors', () => {
415
415
  });
416
416
 
417
417
  it('should handle ResolveError', () => {
418
- const resolveError = new ResolveError(new Error('File not found'));
418
+ const resolveError = new ResolveError(new Error('File not found.'));
419
419
  expect(() => handleError(resolveError, ref)).toThrowError(HandledError);
420
420
  expect(redColoretteMocks).toHaveBeenCalledTimes(1);
421
421
  expect(process.stderr.write).toHaveBeenCalledWith(
@@ -424,7 +424,7 @@ describe('handleErrors', () => {
424
424
  });
425
425
 
426
426
  it('should handle YamlParseError', () => {
427
- const yamlParseError = new YamlParseError(new Error('Invalid yaml'), {} as any);
427
+ const yamlParseError = new YamlParseError(new Error('Invalid yaml.'), {} as any);
428
428
  expect(() => handleError(yamlParseError, ref)).toThrowError(HandledError);
429
429
  expect(redColoretteMocks).toHaveBeenCalledTimes(1);
430
430
  expect(process.stderr.write).toHaveBeenCalledWith(
@@ -451,7 +451,7 @@ describe('handleErrors', () => {
451
451
  });
452
452
 
453
453
  it('should throw unknown error', () => {
454
- const testError = new Error('Test error');
454
+ const testError = new Error('Test error.');
455
455
  expect(() => handleError(testError, ref)).toThrowError(HandledError);
456
456
  expect(process.stderr.write).toHaveBeenCalledWith(
457
457
  `Something went wrong when processing openapi/test.yaml:\n\n - Test error.\n\n`
@@ -48,33 +48,42 @@ export type Remote = {
48
48
  export type PushResponse = {
49
49
  id: string;
50
50
  remoteId: string;
51
+ isMainBranch: boolean;
52
+ isOutdated: boolean;
53
+ hasChanges: boolean;
54
+ replace: boolean;
55
+ scoutJobId: string | null;
56
+ uploadedFiles: Array<{ path: string; mimeType: string }>;
51
57
  commit: {
52
- message: string;
53
58
  branchName: string;
54
- sha: string | null;
55
- url: string | null;
59
+ message: string;
56
60
  createdAt: string | null;
57
- namespace: string | null;
58
- repository: string | null;
61
+ namespaceId: string | null;
62
+ repositoryId: string | null;
63
+ url: string | null;
64
+ sha: string | null;
59
65
  author: {
60
66
  name: string;
61
67
  email: string;
62
68
  image: string | null;
63
69
  };
70
+ statuses: Array<{
71
+ name: string;
72
+ description: string;
73
+ status: 'pending' | 'running' | 'success' | 'failed';
74
+ url: string | null;
75
+ }>;
64
76
  };
65
77
  remote: {
66
78
  commits: {
67
- branchName: string;
68
79
  sha: string;
80
+ branchName: string;
69
81
  }[];
70
82
  };
71
- hasChanges: boolean;
72
- isOutdated: boolean;
73
- isMainBranch: boolean;
74
83
  status: PushStatusResponse;
75
84
  };
76
85
 
77
- type DeploymentStatusResponse = {
86
+ export type DeploymentStatusResponse = {
78
87
  deploy: {
79
88
  url: string | null;
80
89
  status: DeploymentStatus;
@@ -96,6 +105,4 @@ export type ScorecardItem = {
96
105
 
97
106
  export type PushStatusBase = 'pending' | 'success' | 'running' | 'failed';
98
107
 
99
- // export type BuildStatus = PushStatusBase | 'NOT_STARTED' | 'QUEUED';
100
-
101
108
  export type DeploymentStatus = 'skipped' | PushStatusBase;