@redocly/cli 1.0.0-beta.127 → 1.0.0-beta.129

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.
@@ -120,18 +120,32 @@ describe('getFallbackApisOrExit', () => {
120
120
  jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
121
121
  jest.spyOn(process, 'exit').mockImplementation();
122
122
  });
123
+ afterEach(() => {
124
+ jest.clearAllMocks();
125
+ });
123
126
  it('should exit with error because no path provided', () => __awaiter(void 0, void 0, void 0, function* () {
124
127
  const apisConfig = {
125
128
  apis: {},
126
129
  };
127
- yield utils_1.getFallbackApisOrExit([''], apisConfig);
128
- expect(process.exit).toHaveBeenCalledWith(1);
130
+ expect.assertions(1);
131
+ try {
132
+ yield utils_1.getFallbackApisOrExit([''], apisConfig);
133
+ }
134
+ catch (e) {
135
+ expect(e.message).toEqual('Path cannot be empty.');
136
+ }
129
137
  }));
130
138
  it('should error if file from config do not exist', () => __awaiter(void 0, void 0, void 0, function* () {
131
139
  fs_1.existsSync.mockImplementationOnce(() => false);
132
- yield utils_1.getFallbackApisOrExit(undefined, config);
133
- expect(process.stderr.write).toHaveBeenCalledWith('\n someFile.yaml does not exist or is invalid. Please provide a valid path. \n\n');
134
- expect(process.exit).toHaveBeenCalledWith(1);
140
+ expect.assertions(3);
141
+ try {
142
+ yield utils_1.getFallbackApisOrExit(undefined, config);
143
+ }
144
+ catch (e) {
145
+ expect(process.stderr.write).toHaveBeenCalledWith('\nsomeFile.yaml does not exist or is invalid.\n\n');
146
+ expect(process.stderr.write).toHaveBeenCalledWith('Please provide a valid path.\n\n');
147
+ expect(e.message).toEqual('Please provide a valid path.');
148
+ }
135
149
  }));
136
150
  it('should return valid array with results if such file exist', () => __awaiter(void 0, void 0, void 0, function* () {
137
151
  fs_1.existsSync.mockImplementationOnce(() => true);
@@ -151,18 +165,30 @@ describe('getFallbackApisOrExit', () => {
151
165
  apis: {},
152
166
  };
153
167
  fs_1.existsSync.mockImplementationOnce(() => false);
154
- yield utils_1.getFallbackApisOrExit(['someFile.yaml'], apisConfig);
155
- expect(process.stderr.write).toHaveBeenCalledWith('\n someFile.yaml does not exist or is invalid. Please provide a valid path. \n\n');
156
- expect(process.exit).toHaveBeenCalledWith(1);
168
+ expect.assertions(3);
169
+ try {
170
+ yield utils_1.getFallbackApisOrExit(['someFile.yaml'], apisConfig);
171
+ }
172
+ catch (e) {
173
+ expect(process.stderr.write).toHaveBeenCalledWith('\nsomeFile.yaml does not exist or is invalid.\n\n');
174
+ expect(process.stderr.write).toHaveBeenCalledWith('Please provide a valid path.\n\n');
175
+ expect(e.message).toEqual('Please provide a valid path.');
176
+ }
157
177
  }));
158
178
  it('should exit with error in case if invalid 2 path provided as args', () => __awaiter(void 0, void 0, void 0, function* () {
159
179
  const apisConfig = {
160
180
  apis: {},
161
181
  };
162
182
  fs_1.existsSync.mockImplementationOnce(() => false);
163
- yield utils_1.getFallbackApisOrExit(['someFile.yaml', 'someFile2.yaml'], apisConfig);
164
- expect(process.stderr.write).lastCalledWith('\n someFile2.yaml does not exist or is invalid. Please provide a valid path. \n\n');
165
- expect(process.exit).toHaveBeenCalledWith(1);
183
+ expect.assertions(3);
184
+ try {
185
+ yield utils_1.getFallbackApisOrExit(['someFile.yaml', 'someFile2.yaml'], apisConfig);
186
+ }
187
+ catch (e) {
188
+ expect(process.stderr.write).toHaveBeenCalledWith('\nsomeFile.yaml does not exist or is invalid.\n\n');
189
+ expect(process.stderr.write).toHaveBeenCalledWith('Please provide a valid path.\n\n');
190
+ expect(e.message).toEqual('Please provide a valid path.');
191
+ }
166
192
  }));
167
193
  it('should exit with error if only one file exist ', () => __awaiter(void 0, void 0, void 0, function* () {
168
194
  const apisStub = Object.assign(Object.assign({}, apis), { notExist: {
@@ -170,10 +196,18 @@ describe('getFallbackApisOrExit', () => {
170
196
  styleguide: {},
171
197
  } });
172
198
  const configStub = { apis: apisStub };
173
- fs_1.existsSync.mockImplementationOnce((path) => path === 'someFile.yaml');
174
- yield utils_1.getFallbackApisOrExit(undefined, configStub);
175
- expect(process.stderr.write).toBeCalledWith('\n notExist.yaml does not exist or is invalid. Please provide a valid path. \n\n');
176
- expect(process.exit).toHaveBeenCalledWith(1);
199
+ const existSyncMock = fs_1.existsSync.mockImplementation((path) => path.endsWith('someFile.yaml'));
200
+ expect.assertions(4);
201
+ try {
202
+ yield utils_1.getFallbackApisOrExit(undefined, configStub);
203
+ }
204
+ catch (e) {
205
+ expect(process.stderr.write).toHaveBeenCalledWith('\nnotExist.yaml does not exist or is invalid.\n\n');
206
+ expect(process.stderr.write).toHaveBeenCalledWith('Please provide a valid path.\n\n');
207
+ expect(process.stderr.write).toHaveBeenCalledTimes(2);
208
+ expect(e.message).toEqual('Please provide a valid path.');
209
+ }
210
+ existSyncMock.mockClear();
177
211
  }));
178
212
  it('should work ok if it is url passed', () => __awaiter(void 0, void 0, void 0, function* () {
179
213
  fs_1.existsSync.mockImplementationOnce(() => false);
@@ -188,7 +222,6 @@ describe('getFallbackApisOrExit', () => {
188
222
  };
189
223
  const result = yield utils_1.getFallbackApisOrExit(undefined, apisConfig);
190
224
  expect(process.stderr.write).toHaveBeenCalledTimes(0);
191
- expect(process.exit).toHaveBeenCalledTimes(0);
192
225
  expect(result).toStrictEqual([
193
226
  {
194
227
  alias: 'main',
@@ -291,43 +324,43 @@ describe('sorTopLevelKeysForOas', () => {
291
324
  describe('handleErrors', () => {
292
325
  const ref = 'openapi/test.yaml';
293
326
  const redColoretteMocks = colorette_1.red;
327
+ const blueColoretteMocks = colorette_1.blue;
294
328
  beforeEach(() => {
295
329
  jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
296
330
  jest.spyOn(process, 'exit').mockImplementation((code) => code);
297
331
  redColoretteMocks.mockImplementation((text) => text);
332
+ blueColoretteMocks.mockImplementation((text) => text);
298
333
  });
299
334
  afterEach(() => {
300
335
  jest.clearAllMocks();
301
336
  });
302
337
  it('should handle ResolveError', () => {
303
338
  const resolveError = new openapi_core_1.ResolveError(new Error('File not found'));
304
- utils_1.handleError(resolveError, ref);
339
+ expect(() => utils_1.handleError(resolveError, ref)).toThrowError(utils_1.HandledError);
305
340
  expect(redColoretteMocks).toHaveBeenCalledTimes(1);
306
- expect(process.exit).toHaveBeenCalledWith(1);
307
341
  expect(process.stderr.write).toHaveBeenCalledWith(`Failed to resolve api definition at openapi/test.yaml:\n\n - File not found.\n\n`);
308
342
  });
309
343
  it('should handle YamlParseError', () => {
310
344
  const yamlParseError = new openapi_core_1.YamlParseError(new Error('Invalid yaml'), {});
311
- utils_1.handleError(yamlParseError, ref);
345
+ expect(() => utils_1.handleError(yamlParseError, ref)).toThrowError(utils_1.HandledError);
312
346
  expect(redColoretteMocks).toHaveBeenCalledTimes(1);
313
- expect(process.exit).toHaveBeenCalledWith(1);
314
347
  expect(process.stderr.write).toHaveBeenCalledWith(`Failed to parse api definition at openapi/test.yaml:\n\n - Invalid yaml.\n\n`);
315
348
  });
316
349
  it('should handle CircularJSONNotSupportedError', () => {
317
350
  const circularError = new utils_1.CircularJSONNotSupportedError(new Error('Circular json'));
318
- utils_1.handleError(circularError, ref);
319
- expect(process.exit).toHaveBeenCalledWith(1);
351
+ expect(() => utils_1.handleError(circularError, ref)).toThrowError(utils_1.HandledError);
320
352
  expect(process.stderr.write).toHaveBeenCalledWith(`Detected circular reference which can't be converted to JSON.\n` +
321
353
  `Try to use ${colorette_1.blue('yaml')} output or remove ${colorette_1.blue('--dereferenced')}.\n\n`);
322
354
  });
355
+ it('should handle SyntaxError', () => {
356
+ const testError = new SyntaxError('Unexpected identifier');
357
+ testError.stack = 'test stack';
358
+ expect(() => utils_1.handleError(testError, ref)).toThrowError(utils_1.HandledError);
359
+ expect(process.stderr.write).toHaveBeenCalledWith('Syntax error: Unexpected identifier test stack\n\n');
360
+ });
323
361
  it('should throw unknown error', () => {
324
362
  const testError = new Error('Test error');
325
- try {
326
- utils_1.handleError(testError, ref);
327
- }
328
- catch (e) {
329
- expect(e).toEqual(testError);
330
- }
363
+ expect(() => utils_1.handleError(testError, ref)).toThrowError(utils_1.HandledError);
331
364
  expect(process.stderr.write).toHaveBeenCalledWith(`Something went wrong when processing openapi/test.yaml:\n\n - Test error.\n\n`);
332
365
  });
333
366
  });
@@ -338,23 +371,21 @@ describe('checkIfRulesetExist', () => {
338
371
  afterEach(() => {
339
372
  jest.clearAllMocks();
340
373
  });
341
- it('should exit if rules not provided', () => {
374
+ it('should throw an error if rules are not provided', () => {
342
375
  const rules = {
343
376
  oas2: {},
344
377
  oas3_0: {},
345
378
  oas3_1: {},
346
379
  };
347
- utils_1.checkIfRulesetExist(rules);
348
- expect(process.exit).toHaveBeenCalledWith(1);
380
+ expect(() => utils_1.checkIfRulesetExist(rules)).toThrowError('⚠️ No rules were configured. Learn how to configure rules: https://redocly.com/docs/cli/rules/');
349
381
  });
350
- it('should not exit if rules provided', () => {
382
+ it('should not throw an error if rules are provided', () => {
351
383
  const rules = {
352
384
  oas2: { 'operation-4xx-response': 'error' },
353
385
  oas3_0: {},
354
386
  oas3_1: {},
355
387
  };
356
388
  utils_1.checkIfRulesetExist(rules);
357
- expect(process.exit).not.toHaveBeenCalled();
358
389
  });
359
390
  });
360
391
  describe('cleanColors', () => {
@@ -364,3 +395,44 @@ describe('cleanColors', () => {
364
395
  expect(result).not.toMatch(/\x1b\[\d+m/g);
365
396
  });
366
397
  });
398
+ describe('cleanArgs', () => {
399
+ beforeEach(() => {
400
+ // @ts-ignore
401
+ openapi_core_1.isAbsoluteUrl = jest.requireActual('@redocly/openapi-core').isAbsoluteUrl;
402
+ });
403
+ it('should remove potentially sensitive data from args', () => {
404
+ const testArgs = {
405
+ config: 'some-folder/redocly.yaml',
406
+ apis: ['main@v1', 'openapi.yaml', 'http://some.url/openapi.yaml'],
407
+ format: 'codeframe',
408
+ };
409
+ expect(utils_1.cleanArgs(testArgs)).toEqual({
410
+ config: '***.yaml',
411
+ apis: ['main@v1', '***.yaml', 'http://***'],
412
+ format: 'codeframe',
413
+ });
414
+ });
415
+ it('should remove potentially sensitive data from a push destination', () => {
416
+ const testArgs = {
417
+ destination: '@org/name@version',
418
+ };
419
+ expect(utils_1.cleanArgs(testArgs)).toEqual({
420
+ destination: '@***/name@version',
421
+ });
422
+ });
423
+ });
424
+ describe('cleanRawInput', () => {
425
+ it('should remove potentially sensitive data from raw CLI input', () => {
426
+ // @ts-ignore
427
+ openapi_core_1.isAbsoluteUrl = jest.requireActual('@redocly/openapi-core').isAbsoluteUrl;
428
+ const rawInput = [
429
+ 'redocly',
430
+ 'lint',
431
+ 'main@v1',
432
+ 'openapi.yaml',
433
+ 'http://some.url/openapi.yaml',
434
+ '--config=some-folder/redocly.yaml',
435
+ ];
436
+ expect(utils_1.cleanRawInput(rawInput)).toEqual('redocly lint main@v1 ***.yaml http://*** --config=***.yaml');
437
+ });
438
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const utils_1 = require("../utils");
13
+ const process = require("process");
14
+ const wrapper_1 = require("../wrapper");
15
+ const lint_1 = require("../commands/lint");
16
+ jest.mock('node-fetch');
17
+ jest.mock('../utils', () => ({
18
+ sendTelemetry: jest.fn(),
19
+ loadConfigAndHandleErrors: jest.fn(),
20
+ }));
21
+ jest.mock('../commands/lint', () => ({
22
+ handleLint: jest.fn(),
23
+ lintConfigCallback: jest.fn(),
24
+ }));
25
+ describe('commandWrapper', () => {
26
+ it('should send telemetry if there is "telemetry: on" in the config', () => __awaiter(void 0, void 0, void 0, function* () {
27
+ utils_1.loadConfigAndHandleErrors.mockImplementation(() => {
28
+ return { telemetry: 'on', styleguide: { recommendedFallback: true } };
29
+ });
30
+ process.env.REDOCLY_TELEMETRY = 'on';
31
+ const wrappedHandler = wrapper_1.commandWrapper(lint_1.handleLint);
32
+ yield wrappedHandler({});
33
+ expect(lint_1.handleLint).toHaveBeenCalledTimes(1);
34
+ expect(utils_1.sendTelemetry).toHaveBeenCalledTimes(1);
35
+ expect(utils_1.sendTelemetry).toHaveBeenCalledWith({}, 0, false);
36
+ }));
37
+ it('should NOT send telemetry if there is "telemetry: off" in the config', () => __awaiter(void 0, void 0, void 0, function* () {
38
+ utils_1.loadConfigAndHandleErrors.mockImplementation(() => {
39
+ return { telemetry: 'off', styleguide: { recommendedFallback: true } };
40
+ });
41
+ process.env.REDOCLY_TELEMETRY = 'on';
42
+ const wrappedHandler = wrapper_1.commandWrapper(lint_1.handleLint);
43
+ yield wrappedHandler({});
44
+ expect(lint_1.handleLint).toHaveBeenCalledTimes(1);
45
+ expect(utils_1.sendTelemetry).toHaveBeenCalledTimes(0);
46
+ }));
47
+ });
@@ -1,2 +1,3 @@
1
1
  import type { BuildDocsArgv } from './types';
2
- export declare const handlerBuildCommand: (argv: BuildDocsArgv) => Promise<void>;
2
+ import { Config } from '@redocly/openapi-core';
3
+ export declare const handlerBuildCommand: (argv: BuildDocsArgv, configFromFile: Config) => Promise<void>;
@@ -17,10 +17,9 @@ const perf_hooks_1 = require("perf_hooks");
17
17
  const utils_1 = require("./utils");
18
18
  const openapi_core_1 = require("@redocly/openapi-core");
19
19
  const utils_2 = require("../../utils");
20
- const handlerBuildCommand = (argv) => __awaiter(void 0, void 0, void 0, function* () {
20
+ const handlerBuildCommand = (argv, configFromFile) => __awaiter(void 0, void 0, void 0, function* () {
21
21
  var _a;
22
22
  const startedAt = perf_hooks_1.performance.now();
23
- const configFromFile = yield utils_2.loadConfigAndHandleErrors({ configPath: argv.config });
24
23
  const config = openapi_core_1.getMergedConfig(configFromFile, argv.api);
25
24
  const apis = yield utils_2.getFallbackApisOrExit(argv.api ? [argv.api] : [], config);
26
25
  const { path: pathToApi } = apis[0];
@@ -1,5 +1,11 @@
1
- import type { CommonOptions, OutputExtensions, Skips } from '../types';
2
- export declare type BundleOptions = CommonOptions & Skips & {
1
+ import { Config, OutputFormat } from '@redocly/openapi-core';
2
+ import type { OutputExtensions, Skips } from '../types';
3
+ export declare type BundleOptions = {
4
+ apis?: string[];
5
+ 'max-problems': number;
6
+ extends?: string[];
7
+ config?: string;
8
+ format: OutputFormat;
3
9
  output?: string;
4
10
  ext: OutputExtensions;
5
11
  dereferenced?: boolean;
@@ -8,5 +14,5 @@ export declare type BundleOptions = CommonOptions & Skips & {
8
14
  metafile?: string;
9
15
  'remove-unused-components'?: boolean;
10
16
  'keep-url-references'?: boolean;
11
- };
12
- export declare function handleBundle(argv: BundleOptions, version: string): Promise<void>;
17
+ } & Skips;
18
+ export declare function handleBundle(argv: BundleOptions, config: Config, version: string): Promise<void>;
@@ -26,13 +26,9 @@ const utils_1 = require("../utils");
26
26
  const perf_hooks_1 = require("perf_hooks");
27
27
  const colorette_1 = require("colorette");
28
28
  const fs_1 = require("fs");
29
- function handleBundle(argv, version) {
29
+ function handleBundle(argv, config, version) {
30
30
  var _a, _b, _c, _d, _e;
31
31
  return __awaiter(this, void 0, void 0, function* () {
32
- const config = yield utils_1.loadConfigAndHandleErrors({
33
- configPath: argv.config,
34
- customExtends: argv.extends,
35
- });
36
32
  const removeUnusedComponents = argv['remove-unused-components'] ||
37
33
  ((_c = (_b = (_a = config.rawConfig) === null || _a === void 0 ? void 0 : _a.styleguide) === null || _b === void 0 ? void 0 : _b.decorators) === null || _c === void 0 ? void 0 : _c.hasOwnProperty('remove-unused-components'));
38
34
  const apis = yield utils_1.getFallbackApisOrExit(argv.apis, config);
@@ -126,9 +122,9 @@ function handleBundle(argv, version) {
126
122
  }
127
123
  }
128
124
  utils_1.printUnusedWarnings(config.styleguide);
129
- // defer process exit to allow STDOUT pipe to flush
130
- // see https://github.com/nodejs/node-v0.x-archive/issues/3737#issuecomment-19156072
131
- process.once('exit', () => process.exit(totals.errors === 0 || argv.force ? 0 : 1));
125
+ if (!(totals.errors === 0 || argv.force)) {
126
+ throw new Error('Bundle failed.');
127
+ }
132
128
  });
133
129
  }
134
130
  exports.handleBundle = handleBundle;
@@ -1,4 +1,5 @@
1
- declare type JoinArgv = {
1
+ import { Config } from '@redocly/openapi-core';
2
+ export declare type JoinOptions = {
2
3
  apis: string[];
3
4
  lint?: boolean;
4
5
  decorate?: boolean;
@@ -8,6 +9,8 @@ declare type JoinArgv = {
8
9
  'prefix-components-with-info-prop'?: string;
9
10
  'without-x-tag-groups'?: boolean;
10
11
  output?: string;
12
+ config?: string;
13
+ extends?: undefined;
14
+ 'lint-config'?: undefined;
11
15
  };
12
- export declare function handleJoin(argv: JoinArgv, packageVersion: string): Promise<void>;
13
- export {};
16
+ export declare function handleJoin(argv: JoinOptions, config: Config, packageVersion: string): Promise<void>;
@@ -22,7 +22,7 @@ const COMPONENTS = 'components';
22
22
  const Tags = 'tags';
23
23
  const xTagGroups = 'x-tagGroups';
24
24
  let potentialConflictsTotal = 0;
25
- function handleJoin(argv, packageVersion) {
25
+ function handleJoin(argv, config, packageVersion) {
26
26
  return __awaiter(this, void 0, void 0, function* () {
27
27
  const startedAt = perf_hooks_1.performance.now();
28
28
  if (argv.apis.length < 2) {
@@ -37,7 +37,6 @@ function handleJoin(argv, packageVersion) {
37
37
  if (usedTagsOptions.length > 1) {
38
38
  return utils_1.exitWithError(`You use ${colorette_1.yellow(usedTagsOptions.join(', '))} together.\nPlease choose only one! \n\n`);
39
39
  }
40
- const config = yield utils_1.loadConfigAndHandleErrors();
41
40
  const apis = yield utils_1.getFallbackApisOrExit(argv.apis, config);
42
41
  const externalRefResolver = new openapi_core_1.BaseResolver(config.resolve);
43
42
  const documents = yield Promise.all(apis.map(({ path }) => externalRefResolver.resolveDocument(null, path, true)));
@@ -1,7 +1,14 @@
1
- import { RuleSeverity } from '@redocly/openapi-core';
2
- import type { CommonOptions, Skips } from '../types';
3
- export declare type LintOptions = CommonOptions & Omit<Skips, 'skip-decorator'> & {
1
+ import { Config } from '@redocly/openapi-core';
2
+ import type { OutputFormat, RawConfig, RuleSeverity } from '@redocly/openapi-core';
3
+ import type { CommandOptions, Skips } from '../types';
4
+ export declare type LintOptions = {
5
+ apis?: string[];
6
+ 'max-problems': number;
7
+ extends?: string[];
8
+ config?: string;
9
+ format: OutputFormat;
4
10
  'generate-ignore-file'?: boolean;
5
- 'lint-config': RuleSeverity;
6
- };
7
- export declare function handleLint(argv: LintOptions, version: string): Promise<void>;
11
+ 'lint-config'?: RuleSeverity;
12
+ } & Omit<Skips, 'skip-decorator'>;
13
+ export declare function handleLint(argv: LintOptions, config: Config, version: string): Promise<void>;
14
+ export declare function lintConfigCallback(argv: CommandOptions & Record<string, undefined>, version: string): ((config: RawConfig) => Promise<void>) | undefined;
@@ -9,24 +9,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.handleLint = void 0;
12
+ exports.lintConfigCallback = exports.handleLint = void 0;
13
13
  const openapi_core_1 = require("@redocly/openapi-core");
14
14
  const utils_1 = require("../utils");
15
15
  const colorette_1 = require("colorette");
16
16
  const perf_hooks_1 = require("perf_hooks");
17
- function handleLint(argv, version) {
17
+ function handleLint(argv, config, version) {
18
18
  return __awaiter(this, void 0, void 0, function* () {
19
- if (argv.config && !openapi_core_1.doesYamlFileExist(argv.config)) {
20
- return utils_1.exitWithError('Please, provide valid path to the configuration file');
21
- }
22
- const config = yield utils_1.loadConfigAndHandleErrors({
23
- configPath: argv.config,
24
- customExtends: argv.extends,
25
- processRawConfig: lintConfigCallback(argv, version),
26
- });
27
19
  const apis = yield utils_1.getFallbackApisOrExit(argv.apis, config);
28
20
  if (!apis.length) {
29
- return utils_1.exitWithError('No APIs were provided');
21
+ utils_1.exitWithError('No APIs were provided');
30
22
  }
31
23
  if (argv['generate-ignore-file']) {
32
24
  config.styleguide.ignore = {}; // clear ignore
@@ -83,9 +75,9 @@ function handleLint(argv, version) {
83
75
  utils_1.printLintTotals(totals, apis.length);
84
76
  }
85
77
  utils_1.printUnusedWarnings(config.styleguide);
86
- // defer process exit to allow STDOUT pipe to flush
87
- // see https://github.com/nodejs/node-v0.x-archive/issues/3737#issuecomment-19156072
88
- process.once('exit', () => process.exit(totals.errors === 0 || argv['generate-ignore-file'] ? 0 : 1));
78
+ if (!(totals.errors === 0 || argv['generate-ignore-file'])) {
79
+ throw new Error('Lint failed.');
80
+ }
89
81
  });
90
82
  }
91
83
  exports.handleLint = handleLint;
@@ -98,7 +90,6 @@ function lintConfigCallback(argv, version) {
98
90
  return;
99
91
  }
100
92
  return (config) => __awaiter(this, void 0, void 0, function* () {
101
- const { 'max-problems': maxProblems, format } = argv;
102
93
  const configPath = openapi_core_1.findConfig(argv.config) || '';
103
94
  const stringYaml = openapi_core_1.stringifyYaml(config);
104
95
  const configContent = openapi_core_1.makeDocumentFromString(stringYaml, configPath);
@@ -108,11 +99,12 @@ function lintConfigCallback(argv, version) {
108
99
  });
109
100
  const fileTotals = openapi_core_1.getTotals(problems);
110
101
  openapi_core_1.formatProblems(problems, {
111
- format,
112
- maxProblems,
102
+ format: argv.format,
103
+ maxProblems: argv['max-problems'],
113
104
  totals: fileTotals,
114
105
  version,
115
106
  });
116
107
  utils_1.printConfigLintTotals(fileTotals);
117
108
  });
118
109
  }
110
+ exports.lintConfigCallback = lintConfigCallback;
@@ -1,6 +1,8 @@
1
- import { Region } from '@redocly/openapi-core';
1
+ import { Region, Config } from '@redocly/openapi-core';
2
2
  export declare function promptClientToken(domain: string): Promise<string>;
3
- export declare function handleLogin(argv: {
3
+ export declare type LoginOptions = {
4
4
  verbose?: boolean;
5
5
  region?: Region;
6
- }): Promise<void>;
6
+ config?: string;
7
+ };
8
+ export declare function handleLogin(argv: LoginOptions, config: Config): Promise<void>;
@@ -17,9 +17,9 @@ function promptClientToken(domain) {
17
17
  return utils_1.promptUser(colorette_1.green(`\n 🔑 Copy your API key from ${colorette_1.blue(`https://app.${domain}/profile`)} and paste it below`), true);
18
18
  }
19
19
  exports.promptClientToken = promptClientToken;
20
- function handleLogin(argv) {
20
+ function handleLogin(argv, config) {
21
21
  return __awaiter(this, void 0, void 0, function* () {
22
- const region = argv.region || (yield utils_1.loadConfigAndHandleErrors()).region;
22
+ const region = argv.region || config.region;
23
23
  const client = new openapi_core_1.RedoclyClient(region);
24
24
  const clientToken = yield promptClientToken(client.domain);
25
25
  process.stdout.write(colorette_1.gray('\n Logging in...\n'));
@@ -1,10 +1,12 @@
1
+ import { Config } from '@redocly/openapi-core';
1
2
  import type { Skips } from '../../types';
2
- export declare function previewDocs(argv: {
3
+ export declare type PreviewDocsOptions = {
3
4
  port: number;
4
5
  host: string;
5
6
  'use-community-edition'?: boolean;
6
7
  config?: string;
7
8
  api?: string;
8
9
  force?: boolean;
9
- } & Omit<Skips, 'skip-rule'>): Promise<void>;
10
+ } & Omit<Skips, 'skip-rule'>;
11
+ export declare function previewDocs(argv: PreviewDocsOptions, configFromFile: Config): Promise<void>;
10
12
  export declare function debounce(func: Function, wait: number, immediate?: boolean): (...args: any[]) => void;
@@ -15,11 +15,11 @@ const chockidar = require("chokidar");
15
15
  const openapi_core_1 = require("@redocly/openapi-core");
16
16
  const utils_1 = require("../../utils");
17
17
  const preview_server_1 = require("./preview-server/preview-server");
18
- function previewDocs(argv) {
18
+ function previewDocs(argv, configFromFile) {
19
19
  return __awaiter(this, void 0, void 0, function* () {
20
20
  let isAuthorizedWithRedocly = false;
21
21
  let redocOptions = {};
22
- let config = yield reloadConfig();
22
+ let config = yield reloadConfig(configFromFile);
23
23
  const apis = yield utils_1.getFallbackApisOrExit(argv.api ? [argv.api] : [], config);
24
24
  const api = apis[0];
25
25
  let cachedBundle;
@@ -92,10 +92,17 @@ function previewDocs(argv) {
92
92
  watcher.on('ready', () => {
93
93
  process.stdout.write(`\n 👀 Watching ${colorette.blue(api.path)} and all related resources for changes\n\n`);
94
94
  });
95
- function reloadConfig() {
95
+ function reloadConfig(config) {
96
96
  var _a;
97
97
  return __awaiter(this, void 0, void 0, function* () {
98
- const config = yield utils_1.loadConfigAndHandleErrors({ configPath: argv.config });
98
+ if (!config) {
99
+ try {
100
+ config = (yield utils_1.loadConfigAndHandleErrors({ configPath: argv.config }));
101
+ }
102
+ catch (err) {
103
+ config = new openapi_core_1.Config({ apis: {}, styleguide: {} });
104
+ }
105
+ }
99
106
  const redoclyClient = new openapi_core_1.RedoclyClient();
100
107
  isAuthorizedWithRedocly = yield redoclyClient.isAuthorizedWithRedocly();
101
108
  const resolvedConfig = openapi_core_1.getMergedConfig(config, argv.api);
@@ -1,29 +1,34 @@
1
1
  import { Config, Region } from '@redocly/openapi-core';
2
- declare type PushArgs = {
2
+ export declare const DESTINATION_REGEX: RegExp;
3
+ export declare type PushOptions = {
3
4
  api?: string;
4
5
  destination?: string;
5
6
  branchName?: string;
6
7
  upsert?: boolean;
7
- 'batch-id'?: string;
8
+ 'job-id'?: string;
8
9
  'batch-size'?: number;
9
10
  region?: Region;
10
11
  'skip-decorator'?: string[];
11
12
  public?: boolean;
12
13
  files?: string[];
14
+ organization?: string;
15
+ config?: string;
13
16
  };
14
- export declare function handlePush(argv: PushArgs): Promise<void>;
17
+ export declare function handlePush(argv: PushOptions, config: Config): Promise<void>;
15
18
  export declare function getDestinationProps(destination: string | undefined, organization: string | undefined): {
16
19
  organizationId: string | undefined;
17
20
  name: string | undefined;
18
21
  version: string | undefined;
19
22
  };
20
- declare type BarePushArgs = Omit<PushArgs, 'api' | 'destination' | 'branchName'> & {
21
- maybeApiOrDestination?: string;
23
+ declare type BarePushArgs = Omit<PushOptions, 'destination' | 'branchName'> & {
22
24
  maybeDestination?: string;
23
25
  maybeBranchName?: string;
24
26
  branch?: string;
27
+ destination?: string;
25
28
  };
26
- export declare const transformPush: (callback: typeof handlePush) => ({ maybeApiOrDestination, maybeDestination, maybeBranchName, branch, ...rest }: BarePushArgs) => Promise<void>;
29
+ export declare const transformPush: (callback: typeof handlePush) => ({ api: maybeApiOrDestination, maybeDestination, maybeBranchName, branch, "batch-id": batchId, "job-id": jobId, ...rest }: BarePushArgs & {
30
+ 'batch-id'?: string;
31
+ }, config: Config) => Promise<void>;
27
32
  export declare function getApiRoot({ name, version, config: { apis }, }: {
28
33
  name: string;
29
34
  version: string;