@redocly/cli 1.0.0-beta.106 → 1.0.0-beta.109
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/lib/__mocks__/@redocly/openapi-core.d.ts +28 -0
- package/lib/__mocks__/@redocly/openapi-core.js +35 -1
- package/lib/__mocks__/documents.d.ts +92 -0
- package/lib/__mocks__/documents.js +63 -0
- package/lib/__mocks__/utils.d.ts +1 -0
- package/lib/__mocks__/utils.js +2 -1
- package/lib/__tests__/commands/join.test.js +14 -0
- package/lib/commands/join.js +126 -53
- package/lib/commands/lint.js +5 -1
- package/lib/commands/preview-docs/index.js +3 -1
- package/lib/commands/preview-docs/preview-server/preview-server.js +2 -1
- package/lib/commands/push.js +6 -6
- package/lib/commands/split/index.js +5 -2
- package/lib/commands/split/types.d.ts +9 -9
- package/lib/commands/split/types.js +18 -18
- package/lib/commands/stats.js +2 -2
- package/lib/index.js +25 -5
- package/lib/js-utils.d.ts +1 -0
- package/lib/js-utils.js +7 -1
- package/lib/utils.js +1 -1
- package/package.json +2 -2
- package/src/__mocks__/@redocly/openapi-core.ts +38 -0
- package/src/__mocks__/documents.ts +63 -0
- package/src/__mocks__/utils.ts +1 -0
- package/src/__tests__/commands/join.test.ts +23 -1
- package/src/commands/join.ts +166 -62
- package/src/commands/lint.ts +6 -1
- package/src/commands/preview-docs/index.ts +4 -2
- package/src/commands/preview-docs/preview-server/preview-server.ts +2 -1
- package/src/commands/push.ts +6 -6
- package/src/commands/split/index.ts +9 -5
- package/src/commands/split/types.ts +17 -17
- package/src/commands/stats.ts +2 -2
- package/src/index.ts +25 -5
- package/src/js-utils.ts +5 -0
- package/src/utils.ts +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="jest" />
|
|
2
|
+
import { Document, ResolveError } from '@redocly/openapi-core';
|
|
2
3
|
export declare const __redoclyClient: {
|
|
3
4
|
isAuthorizedWithRedocly: jest.Mock<any, any>;
|
|
4
5
|
isAuthorizedWithRedoclyByRegion: jest.Mock<any, any>;
|
|
@@ -47,3 +48,30 @@ export declare const formatProblems: jest.Mock<any, any>;
|
|
|
47
48
|
export declare const slash: jest.Mock<any, any>;
|
|
48
49
|
export declare const findConfig: jest.Mock<any, any>;
|
|
49
50
|
export declare const doesYamlFileExist: jest.Mock<any, any>;
|
|
51
|
+
export declare const bundleDocument: jest.Mock<Promise<{
|
|
52
|
+
problems: {};
|
|
53
|
+
}>, []>;
|
|
54
|
+
export declare const detectOpenAPI: jest.Mock<any, any>;
|
|
55
|
+
export declare class BaseResolver {
|
|
56
|
+
cache: Map<string, Promise<ResolveError | Document>>;
|
|
57
|
+
getFiles: jest.Mock<any, any>;
|
|
58
|
+
resolveExternalRef: jest.Mock<any, any>;
|
|
59
|
+
loadExternalRef: typeof jest.fn;
|
|
60
|
+
parseDocument: jest.Mock<any, any>;
|
|
61
|
+
resolveDocument: jest.Mock<any, any>;
|
|
62
|
+
}
|
|
63
|
+
export declare enum OasVersion {
|
|
64
|
+
Version2 = "oas2",
|
|
65
|
+
Version3_0 = "oas3_0",
|
|
66
|
+
Version3_1 = "oas3_1"
|
|
67
|
+
}
|
|
68
|
+
export declare enum Oas3Operations {
|
|
69
|
+
get = "get",
|
|
70
|
+
put = "put",
|
|
71
|
+
post = "post",
|
|
72
|
+
delete = "delete",
|
|
73
|
+
options = "options",
|
|
74
|
+
head = "head",
|
|
75
|
+
patch = "patch",
|
|
76
|
+
trace = "trace"
|
|
77
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.doesYamlFileExist = exports.findConfig = exports.slash = exports.formatProblems = exports.getTotals = exports.bundle = exports.lint = exports.getMergedConfig = exports.loadConfig = exports.RedoclyClient = exports.__redoclyClient = void 0;
|
|
3
|
+
exports.Oas3Operations = exports.OasVersion = exports.BaseResolver = exports.detectOpenAPI = exports.bundleDocument = exports.doesYamlFileExist = exports.findConfig = exports.slash = exports.formatProblems = exports.getTotals = exports.bundle = exports.lint = exports.getMergedConfig = exports.loadConfig = exports.RedoclyClient = exports.__redoclyClient = void 0;
|
|
4
4
|
const config_1 = require("./../../__tests__/fixtures/config");
|
|
5
|
+
const documents_1 = require("../documents");
|
|
5
6
|
exports.__redoclyClient = {
|
|
6
7
|
isAuthorizedWithRedocly: jest.fn().mockResolvedValue(true),
|
|
7
8
|
isAuthorizedWithRedoclyByRegion: jest.fn().mockResolvedValue(true),
|
|
@@ -26,3 +27,36 @@ exports.formatProblems = jest.fn();
|
|
|
26
27
|
exports.slash = jest.fn();
|
|
27
28
|
exports.findConfig = jest.fn();
|
|
28
29
|
exports.doesYamlFileExist = jest.fn();
|
|
30
|
+
exports.bundleDocument = jest.fn(() => Promise.resolve({ problems: {} }));
|
|
31
|
+
exports.detectOpenAPI = jest.fn();
|
|
32
|
+
class BaseResolver {
|
|
33
|
+
constructor() {
|
|
34
|
+
this.cache = new Map();
|
|
35
|
+
this.getFiles = jest.fn();
|
|
36
|
+
this.resolveExternalRef = jest.fn();
|
|
37
|
+
this.loadExternalRef = jest.fn;
|
|
38
|
+
this.parseDocument = jest.fn();
|
|
39
|
+
this.resolveDocument = jest
|
|
40
|
+
.fn()
|
|
41
|
+
.mockImplementationOnce(() => Promise.resolve({ source: { absoluteRef: 'ref' }, parsed: documents_1.firstDocument }))
|
|
42
|
+
.mockImplementationOnce(() => Promise.resolve({ source: { absoluteRef: 'ref' }, parsed: documents_1.secondDocument }));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.BaseResolver = BaseResolver;
|
|
46
|
+
var OasVersion;
|
|
47
|
+
(function (OasVersion) {
|
|
48
|
+
OasVersion["Version2"] = "oas2";
|
|
49
|
+
OasVersion["Version3_0"] = "oas3_0";
|
|
50
|
+
OasVersion["Version3_1"] = "oas3_1";
|
|
51
|
+
})(OasVersion = exports.OasVersion || (exports.OasVersion = {}));
|
|
52
|
+
var Oas3Operations;
|
|
53
|
+
(function (Oas3Operations) {
|
|
54
|
+
Oas3Operations["get"] = "get";
|
|
55
|
+
Oas3Operations["put"] = "put";
|
|
56
|
+
Oas3Operations["post"] = "post";
|
|
57
|
+
Oas3Operations["delete"] = "delete";
|
|
58
|
+
Oas3Operations["options"] = "options";
|
|
59
|
+
Oas3Operations["head"] = "head";
|
|
60
|
+
Oas3Operations["patch"] = "patch";
|
|
61
|
+
Oas3Operations["trace"] = "trace";
|
|
62
|
+
})(Oas3Operations = exports.Oas3Operations || (exports.Oas3Operations = {}));
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export declare const firstDocument: {
|
|
2
|
+
openapi: string;
|
|
3
|
+
servers: {
|
|
4
|
+
url: string;
|
|
5
|
+
}[];
|
|
6
|
+
info: {
|
|
7
|
+
description: string;
|
|
8
|
+
version: string;
|
|
9
|
+
title: string;
|
|
10
|
+
termsOfService: string;
|
|
11
|
+
license: {
|
|
12
|
+
name: string;
|
|
13
|
+
url: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
paths: {
|
|
17
|
+
'/GETUser/{userId}': {
|
|
18
|
+
summary: string;
|
|
19
|
+
description: string;
|
|
20
|
+
servers: ({
|
|
21
|
+
url: string;
|
|
22
|
+
description?: undefined;
|
|
23
|
+
} | {
|
|
24
|
+
url: string;
|
|
25
|
+
description: string;
|
|
26
|
+
})[];
|
|
27
|
+
get: {
|
|
28
|
+
tags: string[];
|
|
29
|
+
summary: string;
|
|
30
|
+
description: string;
|
|
31
|
+
operationId: string;
|
|
32
|
+
servers: {
|
|
33
|
+
url: string;
|
|
34
|
+
}[];
|
|
35
|
+
};
|
|
36
|
+
parameters: {
|
|
37
|
+
name: string;
|
|
38
|
+
in: string;
|
|
39
|
+
schema: {
|
|
40
|
+
description: string;
|
|
41
|
+
};
|
|
42
|
+
}[];
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
components: {};
|
|
46
|
+
};
|
|
47
|
+
export declare const secondDocument: {
|
|
48
|
+
openapi: string;
|
|
49
|
+
servers: {
|
|
50
|
+
url: string;
|
|
51
|
+
}[];
|
|
52
|
+
info: {
|
|
53
|
+
description: string;
|
|
54
|
+
version: string;
|
|
55
|
+
title: string;
|
|
56
|
+
termsOfService: string;
|
|
57
|
+
license: {
|
|
58
|
+
name: string;
|
|
59
|
+
url: string;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
post: {
|
|
63
|
+
'/GETUser/{userId}': {
|
|
64
|
+
summary: string;
|
|
65
|
+
description: string;
|
|
66
|
+
servers: ({
|
|
67
|
+
url: string;
|
|
68
|
+
description?: undefined;
|
|
69
|
+
} | {
|
|
70
|
+
url: string;
|
|
71
|
+
description: string;
|
|
72
|
+
})[];
|
|
73
|
+
get: {
|
|
74
|
+
tags: string[];
|
|
75
|
+
summary: string;
|
|
76
|
+
description: string;
|
|
77
|
+
operationId: string;
|
|
78
|
+
servers: {
|
|
79
|
+
url: string;
|
|
80
|
+
}[];
|
|
81
|
+
};
|
|
82
|
+
parameters: {
|
|
83
|
+
name: string;
|
|
84
|
+
in: string;
|
|
85
|
+
schema: {
|
|
86
|
+
description: string;
|
|
87
|
+
};
|
|
88
|
+
}[];
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
components: {};
|
|
92
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.secondDocument = exports.firstDocument = void 0;
|
|
4
|
+
exports.firstDocument = {
|
|
5
|
+
openapi: '3.0.0',
|
|
6
|
+
servers: [{ url: 'http://localhost:8080' }],
|
|
7
|
+
info: {
|
|
8
|
+
description: 'example test',
|
|
9
|
+
version: '1.0.0',
|
|
10
|
+
title: 'Swagger Petstore',
|
|
11
|
+
termsOfService: 'http://swagger.io/terms/',
|
|
12
|
+
license: {
|
|
13
|
+
name: 'Apache 2.0',
|
|
14
|
+
url: 'http://www.apache.org/licenses/LICENSE-2.0.html',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
paths: {
|
|
18
|
+
'/GETUser/{userId}': {
|
|
19
|
+
summary: 'get user by id',
|
|
20
|
+
description: 'user info',
|
|
21
|
+
servers: [{ url: '/user' }, { url: '/pet', description: 'pet server' }],
|
|
22
|
+
get: {
|
|
23
|
+
tags: ['pet'],
|
|
24
|
+
summary: 'Find pet by ID',
|
|
25
|
+
description: 'Returns a single pet',
|
|
26
|
+
operationId: 'getPetById',
|
|
27
|
+
servers: [{ url: '/pet' }],
|
|
28
|
+
},
|
|
29
|
+
parameters: [{ name: 'param1', in: 'header', schema: { description: 'string' } }],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
components: {},
|
|
33
|
+
};
|
|
34
|
+
exports.secondDocument = {
|
|
35
|
+
openapi: '3.0.0',
|
|
36
|
+
servers: [{ url: 'http://localhost:8080' }],
|
|
37
|
+
info: {
|
|
38
|
+
description: 'example test',
|
|
39
|
+
version: '1.0.0',
|
|
40
|
+
title: 'Swagger Petstore',
|
|
41
|
+
termsOfService: 'http://swagger.io/terms/',
|
|
42
|
+
license: {
|
|
43
|
+
name: 'Apache 2.0',
|
|
44
|
+
url: 'http://www.apache.org/licenses/LICENSE-2.0.html',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
post: {
|
|
48
|
+
'/GETUser/{userId}': {
|
|
49
|
+
summary: 'get user',
|
|
50
|
+
description: 'user information',
|
|
51
|
+
servers: [{ url: '/user' }, { url: '/pet', description: '' }],
|
|
52
|
+
get: {
|
|
53
|
+
tags: ['pet'],
|
|
54
|
+
summary: 'Find pet by ID',
|
|
55
|
+
description: 'Returns a single pet',
|
|
56
|
+
operationId: 'getPetById',
|
|
57
|
+
servers: [{ url: '/pet' }],
|
|
58
|
+
},
|
|
59
|
+
parameters: [{ name: 'param1', in: 'header', schema: { description: 'string' } }],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
components: {},
|
|
63
|
+
};
|
package/lib/__mocks__/utils.d.ts
CHANGED
package/lib/__mocks__/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.exitWithError = exports.handleError = exports.getOutputFileName = exports.printLintTotals = exports.printUnusedWarnings = exports.printExecutionTime = exports.getExecutionTime = exports.pluralize = exports.slash = exports.dumpBundle = exports.getFallbackApisOrExit = void 0;
|
|
3
|
+
exports.writeYaml = exports.exitWithError = exports.handleError = exports.getOutputFileName = exports.printLintTotals = exports.printUnusedWarnings = exports.printExecutionTime = exports.getExecutionTime = exports.pluralize = exports.slash = exports.dumpBundle = exports.getFallbackApisOrExit = void 0;
|
|
4
4
|
exports.getFallbackApisOrExit = jest.fn((entrypoints) => entrypoints.map((path) => ({ path })));
|
|
5
5
|
exports.dumpBundle = jest.fn(() => '');
|
|
6
6
|
exports.slash = jest.fn();
|
|
@@ -12,3 +12,4 @@ exports.printLintTotals = jest.fn();
|
|
|
12
12
|
exports.getOutputFileName = jest.fn(() => ({ outputFile: 'test.yaml', ext: 'yaml' }));
|
|
13
13
|
exports.handleError = jest.fn();
|
|
14
14
|
exports.exitWithError = jest.fn();
|
|
15
|
+
exports.writeYaml = jest.fn();
|
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
const join_1 = require("../../commands/join");
|
|
13
13
|
const utils_1 = require("../../utils");
|
|
14
14
|
const colorette_1 = require("colorette");
|
|
15
|
+
const openapi_core_1 = require("@redocly/openapi-core");
|
|
15
16
|
jest.mock('../../utils');
|
|
16
17
|
jest.mock('colorette');
|
|
17
18
|
describe('handleJoin fails', () => {
|
|
@@ -38,4 +39,17 @@ describe('handleJoin fails', () => {
|
|
|
38
39
|
}, 'cli-version');
|
|
39
40
|
expect(utils_1.exitWithError).toHaveBeenCalledWith(`You use prefix-tags-with-filename, without-x-tag-groups together.\nPlease choose only one! \n\n`);
|
|
40
41
|
}));
|
|
42
|
+
it('should call exitWithError because Only OpenAPI 3 is supported', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
43
|
+
yield join_1.handleJoin({
|
|
44
|
+
apis: ['first.yaml', 'second.yaml'],
|
|
45
|
+
}, 'cli-version');
|
|
46
|
+
expect(utils_1.exitWithError).toHaveBeenCalledWith('Only OpenAPI 3 is supported: undefined \n\n');
|
|
47
|
+
}));
|
|
48
|
+
it('should call writeYaml function', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
49
|
+
openapi_core_1.detectOpenAPI.mockReturnValue('oas3_0');
|
|
50
|
+
yield join_1.handleJoin({
|
|
51
|
+
apis: ['first.yaml', 'second.yaml'],
|
|
52
|
+
}, 'cli-version');
|
|
53
|
+
expect(utils_1.writeYaml).toHaveBeenCalled();
|
|
54
|
+
}));
|
|
41
55
|
});
|
package/lib/commands/join.js
CHANGED
|
@@ -17,6 +17,7 @@ const isEqual = require('lodash.isequal');
|
|
|
17
17
|
const openapi_core_1 = require("@redocly/openapi-core");
|
|
18
18
|
const utils_1 = require("../utils");
|
|
19
19
|
const js_utils_1 = require("../js-utils");
|
|
20
|
+
const types_1 = require("./split/types");
|
|
20
21
|
const COMPONENTS = 'components';
|
|
21
22
|
const Tags = 'tags';
|
|
22
23
|
const xTagGroups = 'x-tagGroups';
|
|
@@ -73,8 +74,8 @@ function handleJoin(argv, packageVersion) {
|
|
|
73
74
|
yield validateApi(document, config.styleguide, externalRefResolver, packageVersion);
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
const joinedDef = {};
|
|
78
|
+
const potentialConflicts = {
|
|
78
79
|
tags: {},
|
|
79
80
|
paths: {},
|
|
80
81
|
components: {},
|
|
@@ -225,69 +226,144 @@ function handleJoin(argv, packageVersion) {
|
|
|
225
226
|
}
|
|
226
227
|
function collectPaths(openapi, { apiFilename, api, potentialConflicts, tagsPrefix, componentsPrefix }) {
|
|
227
228
|
const { paths } = openapi;
|
|
229
|
+
const operationsSet = new Set(js_utils_1.keysOf(types_1.OPENAPI3_METHOD));
|
|
228
230
|
if (paths) {
|
|
229
231
|
if (!joinedDef.hasOwnProperty('paths')) {
|
|
230
232
|
joinedDef['paths'] = {};
|
|
231
233
|
}
|
|
232
|
-
for (const path of
|
|
234
|
+
for (const path of js_utils_1.keysOf(paths)) {
|
|
233
235
|
if (!joinedDef.paths.hasOwnProperty(path)) {
|
|
234
236
|
joinedDef.paths[path] = {};
|
|
235
237
|
}
|
|
236
238
|
if (!potentialConflicts.paths.hasOwnProperty(path)) {
|
|
237
239
|
potentialConflicts.paths[path] = {};
|
|
238
240
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
potentialConflicts.paths[path][operation] = [
|
|
244
|
-
...(potentialConflicts.paths[path][operation] || []),
|
|
245
|
-
api,
|
|
246
|
-
];
|
|
247
|
-
const { operationId } = pathOperation;
|
|
248
|
-
if (operationId) {
|
|
249
|
-
if (!potentialConflicts.paths.hasOwnProperty('operationIds')) {
|
|
250
|
-
potentialConflicts.paths['operationIds'] = {};
|
|
251
|
-
}
|
|
252
|
-
potentialConflicts.paths.operationIds[operationId] = [
|
|
253
|
-
...(potentialConflicts.paths.operationIds[operationId] || []),
|
|
254
|
-
api,
|
|
255
|
-
];
|
|
241
|
+
const pathItem = paths[path];
|
|
242
|
+
for (const field of js_utils_1.keysOf(pathItem)) {
|
|
243
|
+
if (operationsSet.has(field)) {
|
|
244
|
+
collectPathOperation(pathItem, path, field);
|
|
256
245
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
joinedDef.paths[path][operation].tags = tags.map((tag) => addPrefix(tag, tagsPrefix));
|
|
260
|
-
populateTags({
|
|
261
|
-
api,
|
|
262
|
-
apiFilename,
|
|
263
|
-
tags: formatTags(tags),
|
|
264
|
-
potentialConflicts,
|
|
265
|
-
tagsPrefix,
|
|
266
|
-
componentsPrefix,
|
|
267
|
-
});
|
|
246
|
+
if (field === 'servers') {
|
|
247
|
+
collectPathServers(pathItem, path);
|
|
268
248
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
api,
|
|
275
|
-
apiFilename,
|
|
276
|
-
tags: formatTags(['other']),
|
|
277
|
-
potentialConflicts,
|
|
278
|
-
tagsPrefix: tagsPrefix || apiFilename,
|
|
279
|
-
componentsPrefix,
|
|
280
|
-
});
|
|
249
|
+
if (field === 'parameters') {
|
|
250
|
+
collectPathParameters(pathItem, path);
|
|
251
|
+
}
|
|
252
|
+
if (typeof pathItem[field] === 'string') {
|
|
253
|
+
collectPathStringFields(pathItem, path, field);
|
|
281
254
|
}
|
|
282
|
-
|
|
283
|
-
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function collectPathStringFields(pathItem, path, field) {
|
|
259
|
+
const fieldValue = pathItem[field];
|
|
260
|
+
if (joinedDef.paths[path].hasOwnProperty(field) &&
|
|
261
|
+
joinedDef.paths[path][field] !== fieldValue) {
|
|
262
|
+
process.stderr.write(colorette_1.yellow(`warning: different ${field} values in ${path}\n`));
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
joinedDef.paths[path][field] = fieldValue;
|
|
266
|
+
}
|
|
267
|
+
function collectPathServers(pathItem, path) {
|
|
268
|
+
if (!pathItem.servers) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (!joinedDef.paths[path].hasOwnProperty('servers')) {
|
|
272
|
+
joinedDef.paths[path].servers = [];
|
|
273
|
+
}
|
|
274
|
+
for (const server of pathItem.servers) {
|
|
275
|
+
let isFoundServer = false;
|
|
276
|
+
for (const pathServer of joinedDef.paths[path].servers) {
|
|
277
|
+
if (pathServer.url === server.url) {
|
|
278
|
+
if (!isServersEqual(pathServer, server)) {
|
|
279
|
+
utils_1.exitWithError(`Different server values for (${server.url}) in ${path}`);
|
|
280
|
+
}
|
|
281
|
+
isFoundServer = true;
|
|
284
282
|
}
|
|
285
|
-
|
|
286
|
-
|
|
283
|
+
}
|
|
284
|
+
if (!isFoundServer) {
|
|
285
|
+
joinedDef.paths[path].servers.push(server);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
function collectPathParameters(pathItem, path) {
|
|
290
|
+
if (!pathItem.parameters) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
if (!joinedDef.paths[path].hasOwnProperty('parameters')) {
|
|
294
|
+
joinedDef.paths[path].parameters = [];
|
|
295
|
+
}
|
|
296
|
+
for (const parameter of pathItem.parameters) {
|
|
297
|
+
let isFoundParameter = false;
|
|
298
|
+
for (const pathParameter of joinedDef.paths[path].parameters) {
|
|
299
|
+
if (pathParameter.name === parameter.name && pathParameter.in === parameter.in) {
|
|
300
|
+
if (!isEqual(pathParameter.schema, parameter.schema)) {
|
|
301
|
+
utils_1.exitWithError(`Different parameter schemas for (${parameter.name}) in ${path}`);
|
|
302
|
+
}
|
|
303
|
+
isFoundParameter = true;
|
|
287
304
|
}
|
|
288
305
|
}
|
|
306
|
+
if (!isFoundParameter) {
|
|
307
|
+
joinedDef.paths[path].parameters.push(parameter);
|
|
308
|
+
}
|
|
289
309
|
}
|
|
290
310
|
}
|
|
311
|
+
function collectPathOperation(pathItem, path, operation) {
|
|
312
|
+
const pathOperation = pathItem[operation];
|
|
313
|
+
if (!pathOperation) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
joinedDef.paths[path][operation] = pathOperation;
|
|
317
|
+
potentialConflicts.paths[path][operation] = [
|
|
318
|
+
...(potentialConflicts.paths[path][operation] || []),
|
|
319
|
+
api,
|
|
320
|
+
];
|
|
321
|
+
const { operationId } = pathOperation;
|
|
322
|
+
if (operationId) {
|
|
323
|
+
if (!potentialConflicts.paths.hasOwnProperty('operationIds')) {
|
|
324
|
+
potentialConflicts.paths['operationIds'] = {};
|
|
325
|
+
}
|
|
326
|
+
potentialConflicts.paths.operationIds[operationId] = [
|
|
327
|
+
...(potentialConflicts.paths.operationIds[operationId] || []),
|
|
328
|
+
api,
|
|
329
|
+
];
|
|
330
|
+
}
|
|
331
|
+
const { tags, security } = joinedDef.paths[path][operation];
|
|
332
|
+
if (tags) {
|
|
333
|
+
joinedDef.paths[path][operation].tags = tags.map((tag) => addPrefix(tag, tagsPrefix));
|
|
334
|
+
populateTags({
|
|
335
|
+
api,
|
|
336
|
+
apiFilename,
|
|
337
|
+
tags: formatTags(tags),
|
|
338
|
+
potentialConflicts,
|
|
339
|
+
tagsPrefix,
|
|
340
|
+
componentsPrefix,
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
joinedDef.paths[path][operation]['tags'] = [addPrefix('other', tagsPrefix || apiFilename)];
|
|
345
|
+
populateTags({
|
|
346
|
+
api,
|
|
347
|
+
apiFilename,
|
|
348
|
+
tags: formatTags(['other']),
|
|
349
|
+
potentialConflicts,
|
|
350
|
+
tagsPrefix: tagsPrefix || apiFilename,
|
|
351
|
+
componentsPrefix,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
if (!security && openapi.hasOwnProperty('security')) {
|
|
355
|
+
joinedDef.paths[path][operation]['security'] = addSecurityPrefix(openapi.security, componentsPrefix);
|
|
356
|
+
}
|
|
357
|
+
else if (pathOperation.security) {
|
|
358
|
+
joinedDef.paths[path][operation].security = addSecurityPrefix(pathOperation.security, componentsPrefix);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
function isServersEqual(serverOne, serverTwo) {
|
|
363
|
+
if (serverOne.description === serverTwo.description) {
|
|
364
|
+
return isEqual(serverOne.variables, serverTwo.variables);
|
|
365
|
+
}
|
|
366
|
+
return false;
|
|
291
367
|
}
|
|
292
368
|
function collectComponents(openapi, { api, potentialConflicts, componentsPrefix }) {
|
|
293
369
|
const { components } = openapi;
|
|
@@ -295,13 +371,11 @@ function handleJoin(argv, packageVersion) {
|
|
|
295
371
|
if (!joinedDef.hasOwnProperty(COMPONENTS)) {
|
|
296
372
|
joinedDef[COMPONENTS] = {};
|
|
297
373
|
}
|
|
298
|
-
for (const component of Object.
|
|
374
|
+
for (const [component, componentObj] of Object.entries(components)) {
|
|
299
375
|
if (!potentialConflicts[COMPONENTS].hasOwnProperty(component)) {
|
|
300
376
|
potentialConflicts[COMPONENTS][component] = {};
|
|
301
377
|
joinedDef[COMPONENTS][component] = {};
|
|
302
378
|
}
|
|
303
|
-
// @ts-ignore
|
|
304
|
-
const componentObj = components[component];
|
|
305
379
|
for (const item of Object.keys(componentObj)) {
|
|
306
380
|
const componentPrefix = addPrefix(item, componentsPrefix);
|
|
307
381
|
potentialConflicts.components[component][componentPrefix] = [
|
|
@@ -315,7 +389,6 @@ function handleJoin(argv, packageVersion) {
|
|
|
315
389
|
}
|
|
316
390
|
function collectXWebhooks(openapi, { apiFilename, api, potentialConflicts, tagsPrefix, componentsPrefix }) {
|
|
317
391
|
const xWebhooks = 'x-webhooks';
|
|
318
|
-
// @ts-ignore
|
|
319
392
|
const openapiXWebhooks = openapi[xWebhooks];
|
|
320
393
|
if (openapiXWebhooks) {
|
|
321
394
|
if (!joinedDef.hasOwnProperty(xWebhooks)) {
|
|
@@ -333,7 +406,7 @@ function handleJoin(argv, packageVersion) {
|
|
|
333
406
|
];
|
|
334
407
|
}
|
|
335
408
|
for (const operationKey of Object.keys(joinedDef[xWebhooks][webhook])) {
|
|
336
|
-
|
|
409
|
+
const { tags } = joinedDef[xWebhooks][webhook][operationKey];
|
|
337
410
|
if (tags) {
|
|
338
411
|
joinedDef[xWebhooks][webhook][operationKey].tags = tags.map((tag) => addPrefix(tag, tagsPrefix));
|
|
339
412
|
populateTags({
|
|
@@ -373,7 +446,7 @@ function doesComponentsDiffer(curr, next) {
|
|
|
373
446
|
function validateComponentsDifference(files) {
|
|
374
447
|
let isDiffer = false;
|
|
375
448
|
for (let i = 0, len = files.length; i < len; i++) {
|
|
376
|
-
|
|
449
|
+
const next = files[i + 1];
|
|
377
450
|
if (next && doesComponentsDiffer(files[i], next)) {
|
|
378
451
|
isDiffer = true;
|
|
379
452
|
}
|
package/lib/commands/lint.js
CHANGED
|
@@ -47,7 +47,7 @@ function handleLint(argv, version) {
|
|
|
47
47
|
totals.warnings += fileTotals.warnings;
|
|
48
48
|
totals.ignored += fileTotals.ignored;
|
|
49
49
|
if (argv['generate-ignore-file']) {
|
|
50
|
-
for (
|
|
50
|
+
for (const m of results) {
|
|
51
51
|
config.styleguide.addIgnore(m);
|
|
52
52
|
totalIgnored++;
|
|
53
53
|
}
|
|
@@ -85,6 +85,10 @@ function lintConfigCallback(argv, version) {
|
|
|
85
85
|
if (argv['lint-config'] === 'off') {
|
|
86
86
|
return;
|
|
87
87
|
}
|
|
88
|
+
if (argv.format === 'json') {
|
|
89
|
+
// we can't print config lint results as it will break json output
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
88
92
|
return (config) => __awaiter(this, void 0, void 0, function* () {
|
|
89
93
|
const { 'max-problems': maxProblems, format } = argv;
|
|
90
94
|
const configPath = openapi_core_1.findConfig(argv.config) || '';
|
|
@@ -94,7 +94,7 @@ function previewDocs(argv) {
|
|
|
94
94
|
});
|
|
95
95
|
function reloadConfig() {
|
|
96
96
|
return __awaiter(this, void 0, void 0, function* () {
|
|
97
|
-
|
|
97
|
+
const config = yield openapi_core_1.loadConfig(argv.config);
|
|
98
98
|
const redoclyClient = new openapi_core_1.RedoclyClient();
|
|
99
99
|
isAuthorizedWithRedocly = yield redoclyClient.isAuthorizedWithRedocly();
|
|
100
100
|
const resolvedConfig = openapi_core_1.getMergedConfig(config, argv.api);
|
|
@@ -112,7 +112,9 @@ exports.previewDocs = previewDocs;
|
|
|
112
112
|
function debounce(func, wait, immediate) {
|
|
113
113
|
let timeout;
|
|
114
114
|
return function executedFunction(...args) {
|
|
115
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
115
116
|
// @ts-ignore
|
|
117
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
116
118
|
const context = this;
|
|
117
119
|
const later = () => {
|
|
118
120
|
timeout = null;
|
|
@@ -79,6 +79,7 @@ function startPreviewServer(port, host, { getBundle, getOptions, useRedocPro, })
|
|
|
79
79
|
}
|
|
80
80
|
else {
|
|
81
81
|
let filePath =
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
82
83
|
// @ts-ignore
|
|
83
84
|
{
|
|
84
85
|
'/hot.js': path.join(__dirname, 'hot.js'),
|
|
@@ -112,7 +113,7 @@ function startPreviewServer(port, host, { getBundle, getOptions, useRedocPro, })
|
|
|
112
113
|
}
|
|
113
114
|
console.timeEnd(colorette.dim(`GET ${request.url}`));
|
|
114
115
|
});
|
|
115
|
-
|
|
116
|
+
const wsPort = yield portfinder.getPortPromise({ port: 32201 });
|
|
116
117
|
const server = server_1.startHttpServer(port, host, handler);
|
|
117
118
|
server.on('listening', () => {
|
|
118
119
|
process.stdout.write(`\n 🔎 Preview server running at ${colorette.blue(`http://${host}:${port}\n`)}`);
|
package/lib/commands/push.js
CHANGED
|
@@ -75,7 +75,7 @@ function handlePush(argv) {
|
|
|
75
75
|
const filesHash = hashFiles(filesToUpload.files);
|
|
76
76
|
process.stdout.write(`Uploading ${filesToUpload.files.length} ${utils_1.pluralize('file', filesToUpload.files.length)}:\n`);
|
|
77
77
|
let uploaded = 0;
|
|
78
|
-
for (
|
|
78
|
+
for (const file of filesToUpload.files) {
|
|
79
79
|
const { signedUploadUrl, filePath } = yield client.registryApi.prepareFileUpload({
|
|
80
80
|
organizationId,
|
|
81
81
|
name,
|
|
@@ -142,7 +142,7 @@ function getFilesList(dir, files) {
|
|
|
142
142
|
}
|
|
143
143
|
function collectFilesToUpload(api, config) {
|
|
144
144
|
return __awaiter(this, void 0, void 0, function* () {
|
|
145
|
-
|
|
145
|
+
const files = [];
|
|
146
146
|
const [{ path: apiPath }] = yield utils_1.getFallbackApisOrExit([api], config);
|
|
147
147
|
process.stdout.write('Bundling definition\n');
|
|
148
148
|
const { bundle: openapiBundle, problems } = yield openapi_core_1.bundle({
|
|
@@ -173,7 +173,7 @@ function collectFilesToUpload(api, config) {
|
|
|
173
173
|
const fileList = getFilesList(dir, []);
|
|
174
174
|
files.push(...fileList.map((f) => getFileEntry(f)));
|
|
175
175
|
}
|
|
176
|
-
|
|
176
|
+
const pluginFiles = new Set();
|
|
177
177
|
for (const plugin of config.styleguide.pluginPaths) {
|
|
178
178
|
if (typeof plugin !== 'string')
|
|
179
179
|
continue;
|
|
@@ -207,7 +207,7 @@ function getFolder(filePath) {
|
|
|
207
207
|
return path.resolve(path.dirname(filePath));
|
|
208
208
|
}
|
|
209
209
|
function hashFiles(filePaths) {
|
|
210
|
-
|
|
210
|
+
const sum = crypto_1.createHash('sha256');
|
|
211
211
|
filePaths.forEach((file) => sum.update(fs.readFileSync(file.filePath)));
|
|
212
212
|
return sum.digest('hex');
|
|
213
213
|
}
|
|
@@ -229,7 +229,7 @@ function getDestinationProps(destination, organization) {
|
|
|
229
229
|
exports.getDestinationProps = getDestinationProps;
|
|
230
230
|
const transformPush = (callback) => (_a) => {
|
|
231
231
|
var { maybeApiOrDestination, maybeDestination, maybeBranchName, branch } = _a, rest = __rest(_a, ["maybeApiOrDestination", "maybeDestination", "maybeBranchName", "branch"]);
|
|
232
|
-
if (
|
|
232
|
+
if (maybeBranchName) {
|
|
233
233
|
process.stderr.write(colorette_1.yellow('Deprecation warning: Do not use the third parameter as a branch name. Please use a separate --branch option instead.'));
|
|
234
234
|
}
|
|
235
235
|
const api = maybeDestination ? maybeApiOrDestination : undefined;
|
|
@@ -247,7 +247,7 @@ function uploadFileToS3(url, filePathOrBuffer) {
|
|
|
247
247
|
const fileSizeInBytes = typeof filePathOrBuffer === 'string'
|
|
248
248
|
? fs.statSync(filePathOrBuffer).size
|
|
249
249
|
: filePathOrBuffer.byteLength;
|
|
250
|
-
|
|
250
|
+
const readStream = typeof filePathOrBuffer === 'string' ? fs.createReadStream(filePathOrBuffer) : filePathOrBuffer;
|
|
251
251
|
return node_fetch_1.default(url, {
|
|
252
252
|
method: 'PUT',
|
|
253
253
|
headers: {
|