@redocly/cli 1.0.0-beta.104 → 1.0.0-beta.107

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/bin/cli.js +1 -1
  2. package/lib/__mocks__/@redocly/openapi-core.d.ts +2 -1
  3. package/lib/__mocks__/@redocly/openapi-core.js +2 -1
  4. package/lib/__mocks__/perf_hooks.js +1 -1
  5. package/lib/__mocks__/utils.d.ts +1 -1
  6. package/lib/__mocks__/utils.js +2 -2
  7. package/lib/__tests__/commands/bundle.test.js +52 -17
  8. package/lib/__tests__/commands/join.test.js +4 -4
  9. package/lib/__tests__/commands/lint.test.js +14 -8
  10. package/lib/__tests__/commands/push-region.test.js +2 -2
  11. package/lib/__tests__/commands/push.test.js +18 -18
  12. package/lib/__tests__/fixtures/config.d.ts +1 -1
  13. package/lib/__tests__/fixtures/config.js +1 -1
  14. package/lib/commands/bundle.d.ts +4 -12
  15. package/lib/commands/bundle.js +12 -11
  16. package/lib/commands/join.d.ts +1 -1
  17. package/lib/commands/join.js +105 -56
  18. package/lib/commands/lint.d.ts +3 -9
  19. package/lib/commands/lint.js +14 -11
  20. package/lib/commands/preview-docs/index.d.ts +3 -5
  21. package/lib/commands/preview-docs/index.js +14 -14
  22. package/lib/commands/push.d.ts +6 -6
  23. package/lib/commands/push.js +26 -26
  24. package/lib/commands/split/__tests__/index.test.js +8 -8
  25. package/lib/commands/split/index.d.ts +1 -1
  26. package/lib/commands/split/index.js +12 -11
  27. package/lib/commands/split/types.d.ts +2 -2
  28. package/lib/commands/split/types.js +2 -2
  29. package/lib/commands/stats.d.ts +1 -1
  30. package/lib/commands/stats.js +9 -7
  31. package/lib/index.js +12 -16
  32. package/lib/js-utils.js +2 -2
  33. package/lib/types.d.ts +13 -1
  34. package/lib/utils.d.ts +4 -4
  35. package/lib/utils.js +15 -17
  36. package/package.json +2 -2
  37. package/src/__mocks__/@redocly/openapi-core.ts +1 -0
  38. package/src/__mocks__/perf_hooks.ts +2 -2
  39. package/src/__mocks__/utils.ts +3 -1
  40. package/src/__tests__/commands/bundle.test.ts +71 -22
  41. package/src/__tests__/commands/join.test.ts +8 -8
  42. package/src/__tests__/commands/lint.test.ts +24 -11
  43. package/src/__tests__/commands/push-region.test.ts +2 -2
  44. package/src/__tests__/commands/push.test.ts +19 -24
  45. package/src/__tests__/fixtures/config.ts +1 -1
  46. package/src/__tests__/utils.test.ts +5 -8
  47. package/src/commands/bundle.ts +28 -40
  48. package/src/commands/join.ts +209 -119
  49. package/src/commands/lint.ts +30 -30
  50. package/src/commands/login.ts +2 -2
  51. package/src/commands/preview-docs/index.ts +33 -40
  52. package/src/commands/preview-docs/preview-server/preview-server.ts +6 -6
  53. package/src/commands/preview-docs/preview-server/server.ts +1 -1
  54. package/src/commands/push.ts +44 -53
  55. package/src/commands/split/__tests__/index.test.ts +47 -30
  56. package/src/commands/split/index.ts +84 -46
  57. package/src/commands/split/types.ts +19 -7
  58. package/src/commands/stats.ts +27 -24
  59. package/src/index.ts +16 -20
  60. package/src/js-utils.ts +2 -2
  61. package/src/types.ts +14 -1
  62. package/src/utils.ts +53 -53
  63. package/tsconfig.tsbuildinfo +1 -1
@@ -1,12 +1,13 @@
1
1
  import { lint, bundle, getTotals, getMergedConfig } from '@redocly/openapi-core';
2
2
 
3
3
  import { handleBundle } from '../../commands/bundle';
4
+ import { handleError } from '../../utils';
4
5
  import SpyInstance = jest.SpyInstance;
5
6
 
6
7
  jest.mock('@redocly/openapi-core');
7
8
  jest.mock('../../utils');
8
9
 
9
- (getMergedConfig as jest.Mock).mockImplementation(config => config)
10
+ (getMergedConfig as jest.Mock).mockImplementation((config) => config);
10
11
 
11
12
  describe('bundle', () => {
12
13
  let processExitMock: SpyInstance;
@@ -24,35 +25,35 @@ describe('bundle', () => {
24
25
  afterEach(() => {
25
26
  (lint as jest.Mock).mockClear();
26
27
  (bundle as jest.Mock).mockClear();
27
- (getTotals as jest.Mock).mockClear();
28
+ (getTotals as jest.Mock).mockReset();
28
29
  });
29
30
 
30
31
  it('bundles definitions w/o linting', async () => {
31
- const entrypoints = ['foo.yaml', 'bar.yaml'];
32
+ const apis = ['foo.yaml', 'bar.yaml'];
32
33
 
33
34
  await handleBundle(
34
35
  {
35
- entrypoints,
36
+ apis,
36
37
  ext: 'yaml',
37
38
  format: 'codeframe',
38
39
  },
39
- '1.0.0',
40
+ '1.0.0'
40
41
  );
41
42
 
42
43
  expect(lint).toBeCalledTimes(0);
43
- expect(bundle).toBeCalledTimes(entrypoints.length);
44
+ expect(bundle).toBeCalledTimes(apis.length);
44
45
  });
45
46
 
46
47
  it('exits with code 0 when bundles definitions', async () => {
47
- const entrypoints = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
48
+ const apis = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
48
49
 
49
50
  await handleBundle(
50
51
  {
51
- entrypoints,
52
+ apis,
52
53
  ext: 'yaml',
53
54
  format: 'codeframe',
54
55
  },
55
- '1.0.0',
56
+ '1.0.0'
56
57
  );
57
58
 
58
59
  exitCb?.();
@@ -60,33 +61,39 @@ describe('bundle', () => {
60
61
  });
61
62
 
62
63
  it('bundles definitions w/ linting', async () => {
63
- const entrypoints = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
64
+ const apis = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
65
+
66
+ (getTotals as jest.Mock).mockReturnValue({
67
+ errors: 0,
68
+ warnings: 0,
69
+ ignored: 0,
70
+ });
64
71
 
65
72
  await handleBundle(
66
73
  {
67
- entrypoints,
74
+ apis,
68
75
  ext: 'yaml',
69
76
  format: 'codeframe',
70
77
  lint: true,
71
78
  },
72
- '1.0.0',
79
+ '1.0.0'
73
80
  );
74
81
 
75
- expect(lint).toBeCalledTimes(entrypoints.length);
76
- expect(bundle).toBeCalledTimes(entrypoints.length);
82
+ expect(lint).toBeCalledTimes(apis.length);
83
+ expect(bundle).toBeCalledTimes(apis.length);
77
84
  });
78
85
 
79
86
  it('exits with code 0 when bundles definitions w/linting w/o errors', async () => {
80
- const entrypoints = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
87
+ const apis = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
81
88
 
82
89
  await handleBundle(
83
90
  {
84
- entrypoints,
91
+ apis,
85
92
  ext: 'yaml',
86
93
  format: 'codeframe',
87
94
  lint: true,
88
95
  },
89
- '1.0.0',
96
+ '1.0.0'
90
97
  );
91
98
 
92
99
  exitCb?.();
@@ -94,27 +101,69 @@ describe('bundle', () => {
94
101
  });
95
102
 
96
103
  it('exits with code 1 when bundles definitions w/linting w/errors', async () => {
97
- const entrypoints = ['foo.yaml'];
104
+ const apis = ['foo.yaml'];
98
105
 
99
106
  (getTotals as jest.Mock).mockReturnValue({
100
107
  errors: 1,
101
108
  warnings: 0,
102
- ignored: 0
109
+ ignored: 0,
103
110
  });
104
111
 
105
112
  await handleBundle(
106
113
  {
107
- entrypoints,
114
+ apis,
108
115
  ext: 'yaml',
109
116
  format: 'codeframe',
110
117
  lint: true,
111
118
  },
112
- '1.0.0',
119
+ '1.0.0'
113
120
  );
114
121
 
115
- expect(lint).toBeCalledTimes(entrypoints.length);
122
+ expect(lint).toBeCalledTimes(apis.length);
116
123
  exitCb?.();
117
124
  expect(processExitMock).toHaveBeenCalledWith(1);
118
125
  });
119
126
 
127
+ it('handleError is called when bundles an invalid definition', async () => {
128
+ const apis = ['invalid.json'];
129
+
130
+ (bundle as jest.Mock).mockImplementationOnce(() => {
131
+ throw new Error('Invalid definition');
132
+ });
133
+
134
+ await handleBundle(
135
+ {
136
+ apis,
137
+ ext: 'json',
138
+ format: 'codeframe',
139
+ lint: false,
140
+ },
141
+ '1.0.0'
142
+ );
143
+
144
+ expect(handleError).toHaveBeenCalledTimes(1);
145
+ expect(handleError).toHaveBeenCalledWith(new Error('Invalid definition'), 'invalid.json');
146
+ });
147
+
148
+ it("handleError isn't called when bundles a valid definition", async () => {
149
+ const apis = ['foo.yaml'];
150
+
151
+ (getTotals as jest.Mock).mockReturnValue({
152
+ errors: 0,
153
+ warnings: 0,
154
+ ignored: 0,
155
+ });
156
+
157
+ await handleBundle(
158
+ {
159
+ apis,
160
+ ext: 'yaml',
161
+ format: 'codeframe',
162
+ lint: false,
163
+ },
164
+ '1.0.0'
165
+ );
166
+
167
+ expect(handleError).toHaveBeenCalledTimes(0);
168
+ });
120
169
  });
@@ -10,38 +10,38 @@ describe('handleJoin fails', () => {
10
10
  colloreteYellowMock.mockImplementation((string: string) => string);
11
11
 
12
12
  it('should call exitWithError because only one entrypoint', async () => {
13
- await handleJoin({ entrypoints: ['first.yaml'] }, 'cli-version');
14
- expect(exitWithError).toHaveBeenCalledWith(`At least 2 entrypoints should be provided. \n\n`);
13
+ await handleJoin({ apis: ['first.yaml'] }, 'cli-version');
14
+ expect(exitWithError).toHaveBeenCalledWith(`At least 2 apis should be provided. \n\n`);
15
15
  });
16
16
 
17
17
  it('should call exitWithError because passed all 3 options for tags', async () => {
18
18
  await handleJoin(
19
19
  {
20
- entrypoints: ['first.yaml', 'second.yaml'],
20
+ apis: ['first.yaml', 'second.yaml'],
21
21
  'prefix-tags-with-info-prop': 'something',
22
22
  'without-x-tag-groups': true,
23
23
  'prefix-tags-with-filename': true,
24
24
  },
25
- 'cli-version',
25
+ 'cli-version'
26
26
  );
27
27
 
28
28
  expect(exitWithError).toHaveBeenCalledWith(
29
- `You use prefix-tags-with-filename, prefix-tags-with-info-prop, without-x-tag-groups together.\nPlease choose only one! \n\n`,
29
+ `You use prefix-tags-with-filename, prefix-tags-with-info-prop, without-x-tag-groups together.\nPlease choose only one! \n\n`
30
30
  );
31
31
  });
32
32
 
33
33
  it('should call exitWithError because passed all 2 options for tags', async () => {
34
34
  await handleJoin(
35
35
  {
36
- entrypoints: ['first.yaml', 'second.yaml'],
36
+ apis: ['first.yaml', 'second.yaml'],
37
37
  'without-x-tag-groups': true,
38
38
  'prefix-tags-with-filename': true,
39
39
  },
40
- 'cli-version',
40
+ 'cli-version'
41
41
  );
42
42
 
43
43
  expect(exitWithError).toHaveBeenCalledWith(
44
- `You use prefix-tags-with-filename, without-x-tag-groups together.\nPlease choose only one! \n\n`,
44
+ `You use prefix-tags-with-filename, without-x-tag-groups together.\nPlease choose only one! \n\n`
45
45
  );
46
46
  });
47
47
  });
@@ -5,12 +5,14 @@ import {
5
5
  lint,
6
6
  getTotals,
7
7
  formatProblems,
8
+ doesYamlFileExist,
8
9
  } from '@redocly/openapi-core';
9
10
  import {
10
- getFallbackEntryPointsOrExit,
11
+ getFallbackApisOrExit,
11
12
  getExecutionTime,
12
13
  printUnusedWarnings,
13
14
  handleError,
15
+ exitWithError,
14
16
  } from '../../utils';
15
17
  import { ConfigFixture } from '../fixtures/config';
16
18
  import { performance } from 'perf_hooks';
@@ -20,7 +22,7 @@ jest.mock('../../utils');
20
22
  jest.mock('perf_hooks');
21
23
 
22
24
  const argvMock: LintOptions = {
23
- entrypoints: ['openapi.yaml'],
25
+ apis: ['openapi.yaml'],
24
26
  'lint-config': 'off',
25
27
  format: 'codeframe',
26
28
  };
@@ -41,6 +43,9 @@ describe('handleLint', () => {
41
43
  return process.on(_e, cb);
42
44
  });
43
45
  getMergedConfigMock.mockReturnValue(ConfigFixture);
46
+ (doesYamlFileExist as jest.Mock<any, any>).mockImplementation(
47
+ (path) => path === 'redocly.yaml'
48
+ );
44
49
  });
45
50
 
46
51
  afterEach(() => {
@@ -48,18 +53,26 @@ describe('handleLint', () => {
48
53
  });
49
54
 
50
55
  describe('loadConfig and getEnrtypoints stage', () => {
51
- it('shoul call loadConfig and getFallbackEntryPointsOrExit', async () => {
56
+ it('should fail if config file does not exist', async () => {
57
+ await handleLint({ ...argvMock, config: 'config.yaml' }, versionMock);
58
+ expect(exitWithError).toHaveBeenCalledWith(
59
+ 'Please, provide valid path to the configuration file'
60
+ );
61
+ expect(loadConfig).toHaveBeenCalledTimes(0);
62
+ });
63
+
64
+ it('should call loadConfig and getFallbackApisOrExit', async () => {
52
65
  await handleLint(argvMock, versionMock);
53
66
  expect(loadConfig).toHaveBeenCalledWith(undefined, undefined, undefined);
54
- expect(getFallbackEntryPointsOrExit).toHaveBeenCalled();
67
+ expect(getFallbackApisOrExit).toHaveBeenCalled();
55
68
  });
56
69
 
57
70
  it('should call loadConfig with args if such exist', async () => {
58
71
  await handleLint(
59
- { ...argvMock, config: '/path/redocly.yaml', extends: ['some/path'] },
60
- versionMock,
72
+ { ...argvMock, config: 'redocly.yaml', extends: ['some/path'] },
73
+ versionMock
61
74
  );
62
- expect(loadConfig).toHaveBeenCalledWith('/path/redocly.yaml', ['some/path'], undefined);
75
+ expect(loadConfig).toHaveBeenCalledWith('redocly.yaml', ['some/path'], undefined);
63
76
  });
64
77
 
65
78
  it('should call mergedConfig with clear ignore if `generate-ignore-file` argv', async () => {
@@ -85,10 +98,10 @@ describe('handleLint', () => {
85
98
  'skip-rule': ['rule'],
86
99
  'generate-ignore-file': true,
87
100
  },
88
- versionMock,
101
+ versionMock
89
102
  );
90
- expect(ConfigFixture.lint.skipRules).toHaveBeenCalledWith(['rule']);
91
- expect(ConfigFixture.lint.skipPreprocessors).toHaveBeenCalledWith(['preprocessor']);
103
+ expect(ConfigFixture.styleguide.skipRules).toHaveBeenCalledWith(['rule']);
104
+ expect(ConfigFixture.styleguide.skipPreprocessors).toHaveBeenCalledWith(['preprocessor']);
92
105
  });
93
106
 
94
107
  it('should call formatProblems and getExecutionTime with argv', async () => {
@@ -107,7 +120,7 @@ describe('handleLint', () => {
107
120
  it('should catch error in handleError if something fails', async () => {
108
121
  (lint as jest.Mock<any, any>).mockRejectedValueOnce('error');
109
122
  await handleLint(argvMock, versionMock);
110
- expect(handleError).toHaveBeenCalledWith('error', '');
123
+ expect(handleError).toHaveBeenCalledWith('error', 'openapi.yaml');
111
124
  });
112
125
  });
113
126
 
@@ -29,7 +29,7 @@ describe('push-with-region', () => {
29
29
  redoclyClient.domain = 'redoc.ly';
30
30
  await handlePush({
31
31
  upsert: true,
32
- entrypoint: 'spec.json',
32
+ api: 'spec.json',
33
33
  destination: '@org/my-api@1.0.0',
34
34
  branchName: 'test',
35
35
  });
@@ -41,7 +41,7 @@ describe('push-with-region', () => {
41
41
  redoclyClient.domain = 'eu.redocly.com';
42
42
  await handlePush({
43
43
  upsert: true,
44
- entrypoint: 'spec.json',
44
+ api: 'spec.json',
45
45
  destination: '@org/my-api@1.0.0',
46
46
  branchName: 'test',
47
47
  });
@@ -1,11 +1,6 @@
1
1
  import { Config, getMergedConfig } from '@redocly/openapi-core';
2
2
  import { exitWithError } from '../../utils';
3
- import {
4
- getApiEntrypoint,
5
- getDestinationProps,
6
- handlePush,
7
- transformPush,
8
- } from '../../commands/push';
3
+ import { getApiRoot, getDestinationProps, handlePush, transformPush } from '../../commands/push';
9
4
 
10
5
  jest.mock('fs');
11
6
  jest.mock('node-fetch', () => ({
@@ -29,10 +24,10 @@ describe('push', () => {
29
24
  it('pushes definition', async () => {
30
25
  await handlePush({
31
26
  upsert: true,
32
- entrypoint: 'spec.json',
27
+ api: 'spec.json',
33
28
  destination: '@org/my-api@1.0.0',
34
29
  branchName: 'test',
35
- 'public': true,
30
+ public: true,
36
31
  'batch-id': '123',
37
32
  'batch-size': 2,
38
33
  });
@@ -56,10 +51,10 @@ describe('push', () => {
56
51
  it('fails if batchId value is an empty string', async () => {
57
52
  await handlePush({
58
53
  upsert: true,
59
- entrypoint: 'spec.json',
54
+ api: 'spec.json',
60
55
  destination: '@org/my-api@1.0.0',
61
56
  branchName: 'test',
62
- 'public': true,
57
+ public: true,
63
58
  'batch-id': ' ',
64
59
  'batch-size': 2,
65
60
  });
@@ -70,10 +65,10 @@ describe('push', () => {
70
65
  it('fails if batchSize value is less than 2', async () => {
71
66
  await handlePush({
72
67
  upsert: true,
73
- entrypoint: 'spec.json',
68
+ api: 'spec.json',
74
69
  destination: '@org/my-api@1.0.0',
75
70
  branchName: 'test',
76
- 'public': true,
71
+ public: true,
77
72
  'batch-id': '123',
78
73
  'batch-size': 1,
79
74
  });
@@ -86,23 +81,23 @@ describe('transformPush', () => {
86
81
  it('should adapt the existing syntax', () => {
87
82
  const cb = jest.fn();
88
83
  transformPush(cb)({
89
- maybeEntrypointOrAliasOrDestination: 'openapi.yaml',
84
+ maybeApiOrDestination: 'openapi.yaml',
90
85
  maybeDestination: '@testing_org/main@v1',
91
86
  });
92
87
  expect(cb).toBeCalledWith({
93
- entrypoint: 'openapi.yaml',
88
+ api: 'openapi.yaml',
94
89
  destination: '@testing_org/main@v1',
95
90
  });
96
91
  });
97
92
  it('should adapt the existing syntax (including branchName)', () => {
98
93
  const cb = jest.fn();
99
94
  transformPush(cb)({
100
- maybeEntrypointOrAliasOrDestination: 'openapi.yaml',
95
+ maybeApiOrDestination: 'openapi.yaml',
101
96
  maybeDestination: '@testing_org/main@v1',
102
97
  maybeBranchName: 'other',
103
98
  });
104
99
  expect(cb).toBeCalledWith({
105
- entrypoint: 'openapi.yaml',
100
+ api: 'openapi.yaml',
106
101
  destination: '@testing_org/main@v1',
107
102
  branchName: 'other',
108
103
  });
@@ -110,13 +105,13 @@ describe('transformPush', () => {
110
105
  it('should use --branch option firstly', () => {
111
106
  const cb = jest.fn();
112
107
  transformPush(cb)({
113
- maybeEntrypointOrAliasOrDestination: 'openapi.yaml',
108
+ maybeApiOrDestination: 'openapi.yaml',
114
109
  maybeDestination: '@testing_org/main@v1',
115
110
  maybeBranchName: 'other',
116
111
  branch: 'priority-branch',
117
112
  });
118
113
  expect(cb).toBeCalledWith({
119
- entrypoint: 'openapi.yaml',
114
+ api: 'openapi.yaml',
120
115
  destination: '@testing_org/main@v1',
121
116
  branchName: 'priority-branch',
122
117
  });
@@ -124,7 +119,7 @@ describe('transformPush', () => {
124
119
  it('should work for a destination only', () => {
125
120
  const cb = jest.fn();
126
121
  transformPush(cb)({
127
- maybeEntrypointOrAliasOrDestination: '@testing_org/main@v1',
122
+ maybeApiOrDestination: '@testing_org/main@v1',
128
123
  });
129
124
  expect(cb).toBeCalledWith({
130
125
  destination: '@testing_org/main@v1',
@@ -133,12 +128,12 @@ describe('transformPush', () => {
133
128
  it('should accept aliases for the old syntax', () => {
134
129
  const cb = jest.fn();
135
130
  transformPush(cb)({
136
- maybeEntrypointOrAliasOrDestination: 'alias',
131
+ maybeApiOrDestination: 'alias',
137
132
  maybeDestination: '@testing_org/main@v1',
138
133
  });
139
134
  expect(cb).toBeCalledWith({
140
135
  destination: '@testing_org/main@v1',
141
- entrypoint: 'alias',
136
+ api: 'alias',
142
137
  });
143
138
  });
144
139
  it('should accept no arguments at all', () => {
@@ -171,7 +166,7 @@ describe('getDestinationProps', () => {
171
166
  });
172
167
  });
173
168
 
174
- describe('getApiEntrypoint', () => {
169
+ describe('getApiRoot', () => {
175
170
  let config: Config = {
176
171
  apis: {
177
172
  'main@v1': {
@@ -183,9 +178,9 @@ describe('getApiEntrypoint', () => {
183
178
  },
184
179
  } as unknown as Config;
185
180
  it('should resolve the correct api for a valid name & version', () => {
186
- expect(getApiEntrypoint({ name: 'main', version: 'v1', config })).toEqual('openapi.yaml');
181
+ expect(getApiRoot({ name: 'main', version: 'v1', config })).toEqual('openapi.yaml');
187
182
  });
188
183
  it('should resolve the latest version of api if there is no matching version', () => {
189
- expect(getApiEntrypoint({ name: 'main', version: 'latest', config })).toEqual('latest.yaml');
184
+ expect(getApiRoot({ name: 'main', version: 'latest', config })).toEqual('latest.yaml');
190
185
  });
191
186
  });
@@ -1,6 +1,6 @@
1
1
  export const ConfigFixture = {
2
2
  configFile: null,
3
- lint: {
3
+ styleguide: {
4
4
  addIgnore: jest.fn(),
5
5
  skipRules: jest.fn(),
6
6
  skipPreprocessors: jest.fn(),
@@ -1,10 +1,9 @@
1
1
  import { Totals } from '@redocly/openapi-core';
2
- import { isSubdir, pathToFilename, printConfigLintTotals} from '../utils';
2
+ import { isSubdir, pathToFilename, printConfigLintTotals } from '../utils';
3
3
  import { red, yellow } from 'colorette';
4
4
 
5
-
6
5
  jest.mock('os');
7
- jest.mock('colorette')
6
+ jest.mock('colorette');
8
7
 
9
8
  describe('isSubdir', () => {
10
9
  it('can correctly determine if subdir', () => {
@@ -41,11 +40,10 @@ describe('isSubdir', () => {
41
40
  });
42
41
 
43
42
  afterEach(() => {
44
- jest.resetModules()
45
- })
43
+ jest.resetModules();
44
+ });
46
45
  });
47
46
 
48
-
49
47
  describe('pathToFilename', () => {
50
48
  it('should use correct path separator', () => {
51
49
  const processedPath = pathToFilename('/user/createWithList', '_');
@@ -53,7 +51,6 @@ describe('pathToFilename', () => {
53
51
  });
54
52
  });
55
53
 
56
-
57
54
  describe('printConfigLintTotals', () => {
58
55
  const totalProblemsMock: Totals = {
59
56
  errors: 1,
@@ -79,7 +76,7 @@ describe('printConfigLintTotals', () => {
79
76
  it('should print warnign and error', () => {
80
77
  printConfigLintTotals({ ...totalProblemsMock, warnings: 2 });
81
78
  expect(process.stderr.write).toHaveBeenCalledWith(
82
- '❌ Your config has 1 error and 2 warnings.\n',
79
+ '❌ Your config has 1 error and 2 warnings.\n'
83
80
  );
84
81
  expect(redColoretteMocks).toHaveBeenCalledWith('❌ Your config has 1 error and 2 warnings.\n');
85
82
  });
@@ -3,70 +3,63 @@ import {
3
3
  getTotals,
4
4
  loadConfig,
5
5
  getMergedConfig,
6
- OutputFormat,
7
6
  lint,
8
7
  bundle,
9
8
  } from '@redocly/openapi-core';
10
9
  import {
11
10
  dumpBundle,
12
11
  getExecutionTime,
13
- getFallbackEntryPointsOrExit,
12
+ getFallbackApisOrExit,
14
13
  getOutputFileName,
15
14
  handleError,
16
15
  printUnusedWarnings,
17
16
  saveBundle,
18
17
  printLintTotals,
19
18
  } from '../utils';
20
- import { OutputExtensions, Totals } from '../types';
19
+ import type { CommonOptions, OutputExtensions, Skips, Totals } from '../types';
21
20
  import { performance } from 'perf_hooks';
22
21
  import { blue, gray, green, red, yellow } from 'colorette';
23
22
  import { writeFileSync } from 'fs';
24
23
 
25
- export async function handleBundle(
26
- argv: {
27
- entrypoints: string[];
24
+ export type BundleOptions = CommonOptions &
25
+ Skips & {
28
26
  output?: string;
29
27
  ext: OutputExtensions;
30
- 'max-problems'?: number;
31
- 'skip-rule'?: string[];
32
- 'skip-preprocessor'?: string[];
33
- 'skip-decorator'?: string[];
34
28
  dereferenced?: boolean;
35
29
  force?: boolean;
36
- config?: string;
37
30
  lint?: boolean;
38
- format: OutputFormat;
39
31
  metafile?: string;
40
- extends?: string[];
41
32
  'remove-unused-components'?: boolean;
42
33
  'keep-url-references'?: boolean;
43
- },
44
- version: string,
45
- ) {
34
+ };
35
+
36
+ export async function handleBundle(argv: BundleOptions, version: string) {
46
37
  const config = await loadConfig(argv.config, argv.extends);
47
38
  const removeUnusedComponents =
48
39
  argv['remove-unused-components'] &&
49
- !config.rawConfig.lint?.decorators?.hasOwnProperty('remove-unused-components');
50
- const entrypoints = await getFallbackEntryPointsOrExit(argv.entrypoints, config);
40
+ !config.rawConfig.styleguide?.decorators?.hasOwnProperty('remove-unused-components');
41
+ const apis = await getFallbackApisOrExit(argv.apis, config);
51
42
  const totals: Totals = { errors: 0, warnings: 0, ignored: 0 };
52
43
  const maxProblems = argv['max-problems'];
53
44
 
54
- for (const { path, alias } of entrypoints) {
45
+ for (const { path, alias } of apis) {
55
46
  try {
56
47
  const startedAt = performance.now();
57
48
  const resolvedConfig = getMergedConfig(config, alias);
58
- resolvedConfig.lint.skipRules(argv['skip-rule']);
59
- resolvedConfig.lint.skipPreprocessors(argv['skip-preprocessor']);
60
- resolvedConfig.lint.skipDecorators(argv['skip-decorator']);
49
+ const { styleguide } = resolvedConfig;
50
+
51
+ styleguide.skipRules(argv['skip-rule']);
52
+ styleguide.skipPreprocessors(argv['skip-preprocessor']);
53
+ styleguide.skipDecorators(argv['skip-decorator']);
61
54
 
62
55
  if (argv.lint) {
63
- if (config.lint.recommendedFallback) {
56
+ if (config.styleguide.recommendedFallback) {
64
57
  process.stderr.write(
65
58
  `No configurations were defined in extends -- using built in ${blue(
66
- 'recommended',
59
+ 'recommended'
67
60
  )} configuration by default.\n${red(
68
- 'Warning! This default behavior is going to be deprecated soon.',
69
- )}\n\n`,
61
+ 'Warning! This default behavior is going to be deprecated soon.'
62
+ )}\n\n`
70
63
  );
71
64
  }
72
65
  const results = await lint({
@@ -103,12 +96,7 @@ export async function handleBundle(
103
96
  });
104
97
 
105
98
  const fileTotals = getTotals(problems);
106
- const { outputFile, ext } = getOutputFileName(
107
- path,
108
- entrypoints.length,
109
- argv.output,
110
- argv.ext,
111
- );
99
+ const { outputFile, ext } = getOutputFileName(path, apis.length, argv.output, argv.ext);
112
100
 
113
101
  if (fileTotals.errors === 0 || argv.force) {
114
102
  if (!argv.output) {
@@ -132,9 +120,9 @@ export async function handleBundle(
132
120
  });
133
121
 
134
122
  if (argv.metafile) {
135
- if (entrypoints.length > 1) {
123
+ if (apis.length > 1) {
136
124
  process.stderr.write(
137
- yellow(`[WARNING] "--metafile" cannot be used with multiple entrypoints. Skipping...`),
125
+ yellow(`[WARNING] "--metafile" cannot be used with multiple apis. Skipping...`)
138
126
  );
139
127
  }
140
128
  {
@@ -147,19 +135,19 @@ export async function handleBundle(
147
135
  if (argv.force) {
148
136
  process.stderr.write(
149
137
  `❓ Created a bundle for ${blue(path)} at ${blue(outputFile)} with errors ${green(
150
- elapsed,
151
- )}.\n${yellow('Errors ignored because of --force')}.\n`,
138
+ elapsed
139
+ )}.\n${yellow('Errors ignored because of --force')}.\n`
152
140
  );
153
141
  } else {
154
142
  process.stderr.write(
155
143
  `❌ Errors encountered while bundling ${blue(
156
- path,
157
- )}: bundle not created (use --force to ignore errors).\n`,
144
+ path
145
+ )}: bundle not created (use --force to ignore errors).\n`
158
146
  );
159
147
  }
160
148
  } else {
161
149
  process.stderr.write(
162
- `📦 Created a bundle for ${blue(path)} at ${blue(outputFile)} ${green(elapsed)}.\n`,
150
+ `📦 Created a bundle for ${blue(path)} at ${blue(outputFile)} ${green(elapsed)}.\n`
163
151
  );
164
152
  }
165
153
 
@@ -172,7 +160,7 @@ export async function handleBundle(
172
160
  }
173
161
  }
174
162
 
175
- printUnusedWarnings(config.lint);
163
+ printUnusedWarnings(config.styleguide);
176
164
 
177
165
  // defer process exit to allow STDOUT pipe to flush
178
166
  // see https://github.com/nodejs/node-v0.x-archive/issues/3737#issuecomment-19156072