@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.
- package/bin/cli.js +1 -1
- package/lib/__mocks__/@redocly/openapi-core.d.ts +2 -1
- package/lib/__mocks__/@redocly/openapi-core.js +2 -1
- package/lib/__mocks__/perf_hooks.js +1 -1
- package/lib/__mocks__/utils.d.ts +1 -1
- package/lib/__mocks__/utils.js +2 -2
- package/lib/__tests__/commands/bundle.test.js +52 -17
- package/lib/__tests__/commands/join.test.js +4 -4
- package/lib/__tests__/commands/lint.test.js +14 -8
- package/lib/__tests__/commands/push-region.test.js +2 -2
- package/lib/__tests__/commands/push.test.js +18 -18
- package/lib/__tests__/fixtures/config.d.ts +1 -1
- package/lib/__tests__/fixtures/config.js +1 -1
- package/lib/commands/bundle.d.ts +4 -12
- package/lib/commands/bundle.js +12 -11
- package/lib/commands/join.d.ts +1 -1
- package/lib/commands/join.js +105 -56
- package/lib/commands/lint.d.ts +3 -9
- package/lib/commands/lint.js +14 -11
- package/lib/commands/preview-docs/index.d.ts +3 -5
- package/lib/commands/preview-docs/index.js +14 -14
- package/lib/commands/push.d.ts +6 -6
- package/lib/commands/push.js +26 -26
- package/lib/commands/split/__tests__/index.test.js +8 -8
- package/lib/commands/split/index.d.ts +1 -1
- package/lib/commands/split/index.js +12 -11
- package/lib/commands/split/types.d.ts +2 -2
- package/lib/commands/split/types.js +2 -2
- package/lib/commands/stats.d.ts +1 -1
- package/lib/commands/stats.js +9 -7
- package/lib/index.js +12 -16
- package/lib/js-utils.js +2 -2
- package/lib/types.d.ts +13 -1
- package/lib/utils.d.ts +4 -4
- package/lib/utils.js +15 -17
- package/package.json +2 -2
- package/src/__mocks__/@redocly/openapi-core.ts +1 -0
- package/src/__mocks__/perf_hooks.ts +2 -2
- package/src/__mocks__/utils.ts +3 -1
- package/src/__tests__/commands/bundle.test.ts +71 -22
- package/src/__tests__/commands/join.test.ts +8 -8
- package/src/__tests__/commands/lint.test.ts +24 -11
- package/src/__tests__/commands/push-region.test.ts +2 -2
- package/src/__tests__/commands/push.test.ts +19 -24
- package/src/__tests__/fixtures/config.ts +1 -1
- package/src/__tests__/utils.test.ts +5 -8
- package/src/commands/bundle.ts +28 -40
- package/src/commands/join.ts +209 -119
- package/src/commands/lint.ts +30 -30
- package/src/commands/login.ts +2 -2
- package/src/commands/preview-docs/index.ts +33 -40
- package/src/commands/preview-docs/preview-server/preview-server.ts +6 -6
- package/src/commands/preview-docs/preview-server/server.ts +1 -1
- package/src/commands/push.ts +44 -53
- package/src/commands/split/__tests__/index.test.ts +47 -30
- package/src/commands/split/index.ts +84 -46
- package/src/commands/split/types.ts +19 -7
- package/src/commands/stats.ts +27 -24
- package/src/index.ts +16 -20
- package/src/js-utils.ts +2 -2
- package/src/types.ts +14 -1
- package/src/utils.ts +53 -53
- 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).
|
|
28
|
+
(getTotals as jest.Mock).mockReset();
|
|
28
29
|
});
|
|
29
30
|
|
|
30
31
|
it('bundles definitions w/o linting', async () => {
|
|
31
|
-
const
|
|
32
|
+
const apis = ['foo.yaml', 'bar.yaml'];
|
|
32
33
|
|
|
33
34
|
await handleBundle(
|
|
34
35
|
{
|
|
35
|
-
|
|
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(
|
|
44
|
+
expect(bundle).toBeCalledTimes(apis.length);
|
|
44
45
|
});
|
|
45
46
|
|
|
46
47
|
it('exits with code 0 when bundles definitions', async () => {
|
|
47
|
-
const
|
|
48
|
+
const apis = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
|
|
48
49
|
|
|
49
50
|
await handleBundle(
|
|
50
51
|
{
|
|
51
|
-
|
|
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
|
|
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
|
-
|
|
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(
|
|
76
|
-
expect(bundle).toBeCalledTimes(
|
|
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
|
|
87
|
+
const apis = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
|
|
81
88
|
|
|
82
89
|
await handleBundle(
|
|
83
90
|
{
|
|
84
|
-
|
|
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
|
|
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
|
-
|
|
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(
|
|
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({
|
|
14
|
-
expect(exitWithError).toHaveBeenCalledWith(`At least 2
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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('
|
|
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(
|
|
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: '
|
|
60
|
-
versionMock
|
|
72
|
+
{ ...argvMock, config: 'redocly.yaml', extends: ['some/path'] },
|
|
73
|
+
versionMock
|
|
61
74
|
);
|
|
62
|
-
expect(loadConfig).toHaveBeenCalledWith('
|
|
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.
|
|
91
|
-
expect(ConfigFixture.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
27
|
+
api: 'spec.json',
|
|
33
28
|
destination: '@org/my-api@1.0.0',
|
|
34
29
|
branchName: 'test',
|
|
35
|
-
|
|
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
|
-
|
|
54
|
+
api: 'spec.json',
|
|
60
55
|
destination: '@org/my-api@1.0.0',
|
|
61
56
|
branchName: 'test',
|
|
62
|
-
|
|
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
|
-
|
|
68
|
+
api: 'spec.json',
|
|
74
69
|
destination: '@org/my-api@1.0.0',
|
|
75
70
|
branchName: 'test',
|
|
76
|
-
|
|
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
|
-
|
|
84
|
+
maybeApiOrDestination: 'openapi.yaml',
|
|
90
85
|
maybeDestination: '@testing_org/main@v1',
|
|
91
86
|
});
|
|
92
87
|
expect(cb).toBeCalledWith({
|
|
93
|
-
|
|
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
|
-
|
|
95
|
+
maybeApiOrDestination: 'openapi.yaml',
|
|
101
96
|
maybeDestination: '@testing_org/main@v1',
|
|
102
97
|
maybeBranchName: 'other',
|
|
103
98
|
});
|
|
104
99
|
expect(cb).toBeCalledWith({
|
|
105
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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('
|
|
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(
|
|
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(
|
|
184
|
+
expect(getApiRoot({ name: 'main', version: 'latest', config })).toEqual('latest.yaml');
|
|
190
185
|
});
|
|
191
186
|
});
|
|
@@ -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
|
});
|
package/src/commands/bundle.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
26
|
-
|
|
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
|
-
|
|
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.
|
|
50
|
-
const
|
|
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
|
|
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
|
|
59
|
-
|
|
60
|
-
|
|
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.
|
|
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 (
|
|
123
|
+
if (apis.length > 1) {
|
|
136
124
|
process.stderr.write(
|
|
137
|
-
yellow(`[WARNING] "--metafile" cannot be used with multiple
|
|
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.
|
|
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
|