@redocly/cli 1.9.0 → 1.9.1
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/CHANGELOG.md +9 -0
- package/lib/__mocks__/@redocly/openapi-core.js +2 -1
- package/lib/__mocks__/documents.d.ts +58 -0
- package/lib/__mocks__/documents.js +63 -3
- package/lib/__tests__/commands/join.test.js +126 -3
- package/lib/commands/join.d.ts +2 -1
- package/lib/commands/join.js +20 -26
- package/lib/commands/split/index.d.ts +3 -1
- package/lib/commands/split/index.js +10 -9
- package/lib/commands/split/types.d.ts +1 -2
- package/lib/commands/split/types.js +1 -2
- package/lib/utils/js-utils.d.ts +1 -1
- package/package.json +2 -2
- package/src/__mocks__/@redocly/openapi-core.ts +4 -1
- package/src/__mocks__/documents.ts +63 -2
- package/src/__tests__/commands/join.test.ts +137 -3
- package/src/commands/join.ts +25 -31
- package/src/commands/split/index.ts +24 -25
- package/src/commands/split/types.ts +1 -3
- package/src/utils/js-utils.ts +1 -1
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @redocly/cli
|
|
2
2
|
|
|
3
|
+
## 1.9.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Adds support for using logical AND for the security schema so that the `join` command generates the correct schema.
|
|
8
|
+
- Fixed a bug with resolving $refs to file names that contain the hash symbol.
|
|
9
|
+
- Fixed a problem where the `join` command did not process schemas containing `null` values when the `--prefix-components-with-info-prop` option was used.'
|
|
10
|
+
- Updated @redocly/openapi-core to v1.9.1.
|
|
11
|
+
|
|
3
12
|
## 1.9.0
|
|
4
13
|
|
|
5
14
|
### Minor Changes
|
|
@@ -41,7 +41,8 @@ class BaseResolver {
|
|
|
41
41
|
this.resolveDocument = jest
|
|
42
42
|
.fn()
|
|
43
43
|
.mockImplementationOnce(() => Promise.resolve({ source: { absoluteRef: 'ref' }, parsed: documents_1.firstDocument }))
|
|
44
|
-
.mockImplementationOnce(() => Promise.resolve({ source: { absoluteRef: 'ref' }, parsed: documents_1.secondDocument }))
|
|
44
|
+
.mockImplementationOnce(() => Promise.resolve({ source: { absoluteRef: 'ref' }, parsed: documents_1.secondDocument }))
|
|
45
|
+
.mockImplementationOnce(() => Promise.resolve({ source: { absoluteRef: 'ref' }, parsed: documents_1.thirdDocument }));
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
exports.BaseResolver = BaseResolver;
|
|
@@ -90,3 +90,61 @@ export declare const secondDocument: {
|
|
|
90
90
|
};
|
|
91
91
|
components: {};
|
|
92
92
|
};
|
|
93
|
+
export declare const thirdDocument: {
|
|
94
|
+
openapi: string;
|
|
95
|
+
info: {
|
|
96
|
+
title: string;
|
|
97
|
+
version: string;
|
|
98
|
+
};
|
|
99
|
+
servers: {
|
|
100
|
+
url: string;
|
|
101
|
+
}[];
|
|
102
|
+
paths: {};
|
|
103
|
+
components: {
|
|
104
|
+
schemas: {
|
|
105
|
+
SchemaWithNull: {
|
|
106
|
+
type: string;
|
|
107
|
+
default: null;
|
|
108
|
+
nullable: boolean;
|
|
109
|
+
};
|
|
110
|
+
SchemaWithRef: {
|
|
111
|
+
type: string;
|
|
112
|
+
properties: {
|
|
113
|
+
schemaType: {
|
|
114
|
+
type: string;
|
|
115
|
+
enum: string[];
|
|
116
|
+
};
|
|
117
|
+
foo: {
|
|
118
|
+
$ref: string;
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
SchemaWithDiscriminator: {
|
|
123
|
+
discriminator: {
|
|
124
|
+
propertyName: string;
|
|
125
|
+
mapping: {
|
|
126
|
+
foo: string;
|
|
127
|
+
bar: string;
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
oneOf: ({
|
|
131
|
+
$ref: string;
|
|
132
|
+
type?: undefined;
|
|
133
|
+
properties?: undefined;
|
|
134
|
+
} | {
|
|
135
|
+
type: string;
|
|
136
|
+
properties: {
|
|
137
|
+
schemaType: {
|
|
138
|
+
type: string;
|
|
139
|
+
enum: string[];
|
|
140
|
+
};
|
|
141
|
+
bar: {
|
|
142
|
+
type: string;
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
$ref?: undefined;
|
|
146
|
+
})[];
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.secondDocument = exports.firstDocument = void 0;
|
|
3
|
+
exports.thirdDocument = exports.secondDocument = exports.firstDocument = void 0;
|
|
4
4
|
exports.firstDocument = {
|
|
5
5
|
openapi: '3.0.0',
|
|
6
6
|
servers: [{ url: 'http://localhost:8080' }],
|
|
7
7
|
info: {
|
|
8
8
|
description: 'example test',
|
|
9
9
|
version: '1.0.0',
|
|
10
|
-
title: '
|
|
10
|
+
title: 'First API',
|
|
11
11
|
termsOfService: 'http://swagger.io/terms/',
|
|
12
12
|
license: {
|
|
13
13
|
name: 'Apache 2.0',
|
|
@@ -37,7 +37,7 @@ exports.secondDocument = {
|
|
|
37
37
|
info: {
|
|
38
38
|
description: 'example test',
|
|
39
39
|
version: '1.0.0',
|
|
40
|
-
title: '
|
|
40
|
+
title: 'Second API',
|
|
41
41
|
termsOfService: 'http://swagger.io/terms/',
|
|
42
42
|
license: {
|
|
43
43
|
name: 'Apache 2.0',
|
|
@@ -61,3 +61,63 @@ exports.secondDocument = {
|
|
|
61
61
|
},
|
|
62
62
|
components: {},
|
|
63
63
|
};
|
|
64
|
+
exports.thirdDocument = {
|
|
65
|
+
openapi: '3.0.0',
|
|
66
|
+
info: {
|
|
67
|
+
title: 'Third API',
|
|
68
|
+
version: '1.0',
|
|
69
|
+
},
|
|
70
|
+
servers: [
|
|
71
|
+
{
|
|
72
|
+
url: 'https://api.server.test/v1',
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
paths: {},
|
|
76
|
+
components: {
|
|
77
|
+
schemas: {
|
|
78
|
+
SchemaWithNull: {
|
|
79
|
+
type: 'string',
|
|
80
|
+
default: null,
|
|
81
|
+
nullable: true,
|
|
82
|
+
},
|
|
83
|
+
SchemaWithRef: {
|
|
84
|
+
type: 'object',
|
|
85
|
+
properties: {
|
|
86
|
+
schemaType: {
|
|
87
|
+
type: 'string',
|
|
88
|
+
enum: ['foo'],
|
|
89
|
+
},
|
|
90
|
+
foo: {
|
|
91
|
+
$ref: '#/components/schemas/SchemaWithNull',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
SchemaWithDiscriminator: {
|
|
96
|
+
discriminator: {
|
|
97
|
+
propertyName: 'schemaType',
|
|
98
|
+
mapping: {
|
|
99
|
+
foo: '#/components/schemas/SchemaWithRef',
|
|
100
|
+
bar: '#/components/schemas/SchemaWithNull',
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
oneOf: [
|
|
104
|
+
{
|
|
105
|
+
$ref: '#/components/schemas/SchemaWithRef',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
type: 'object',
|
|
109
|
+
properties: {
|
|
110
|
+
schemaType: {
|
|
111
|
+
type: 'string',
|
|
112
|
+
enum: ['bar'],
|
|
113
|
+
},
|
|
114
|
+
bar: {
|
|
115
|
+
type: 'string',
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
};
|
|
@@ -9,15 +9,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
const join_1 = require("../../commands/join");
|
|
13
|
-
const miscellaneous_1 = require("../../utils/miscellaneous");
|
|
14
12
|
const colorette_1 = require("colorette");
|
|
15
13
|
const openapi_core_1 = require("@redocly/openapi-core");
|
|
14
|
+
const join_1 = require("../../commands/join");
|
|
15
|
+
const miscellaneous_1 = require("../../utils/miscellaneous");
|
|
16
16
|
const openapi_core_2 = require("../../__mocks__/@redocly/openapi-core");
|
|
17
17
|
const config_1 = require("../fixtures/config");
|
|
18
18
|
jest.mock('../../utils/miscellaneous');
|
|
19
19
|
jest.mock('colorette');
|
|
20
|
-
describe('handleJoin
|
|
20
|
+
describe('handleJoin', () => {
|
|
21
21
|
const colloreteYellowMock = colorette_1.yellow;
|
|
22
22
|
colloreteYellowMock.mockImplementation((string) => string);
|
|
23
23
|
it('should call exitWithError because only one entrypoint', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -105,4 +105,127 @@ describe('handleJoin fails', () => {
|
|
|
105
105
|
expect(config.styleguide.skipDecorators).not.toHaveBeenCalled();
|
|
106
106
|
expect(config.styleguide.skipPreprocessors).not.toHaveBeenCalled();
|
|
107
107
|
}));
|
|
108
|
+
it('should handle join with prefix-components-with-info-prop and null values', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
109
|
+
openapi_core_1.detectSpec.mockReturnValue('oas3_0');
|
|
110
|
+
yield (0, join_1.handleJoin)({
|
|
111
|
+
apis: ['first.yaml', 'second.yaml', 'third.yaml'],
|
|
112
|
+
'prefix-components-with-info-prop': 'title',
|
|
113
|
+
output: 'join-result.yaml',
|
|
114
|
+
}, config_1.ConfigFixture, 'cli-version');
|
|
115
|
+
expect(miscellaneous_1.writeToFileByExtension).toHaveBeenCalledWith({
|
|
116
|
+
openapi: '3.0.0',
|
|
117
|
+
info: {
|
|
118
|
+
description: 'example test',
|
|
119
|
+
version: '1.0.0',
|
|
120
|
+
title: 'First API',
|
|
121
|
+
termsOfService: 'http://swagger.io/terms/',
|
|
122
|
+
license: {
|
|
123
|
+
name: 'Apache 2.0',
|
|
124
|
+
url: 'http://www.apache.org/licenses/LICENSE-2.0.html',
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
servers: [
|
|
128
|
+
{
|
|
129
|
+
url: 'http://localhost:8080',
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
url: 'https://api.server.test/v1',
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
tags: [
|
|
136
|
+
{
|
|
137
|
+
name: 'pet',
|
|
138
|
+
'x-displayName': 'pet',
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
paths: {
|
|
142
|
+
'/GETUser/{userId}': {
|
|
143
|
+
summary: 'get user by id',
|
|
144
|
+
description: 'user info',
|
|
145
|
+
servers: [
|
|
146
|
+
{
|
|
147
|
+
url: '/user',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
url: '/pet',
|
|
151
|
+
description: 'pet server',
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
get: {
|
|
155
|
+
tags: ['pet'],
|
|
156
|
+
summary: 'Find pet by ID',
|
|
157
|
+
description: 'Returns a single pet',
|
|
158
|
+
operationId: 'getPetById',
|
|
159
|
+
servers: [
|
|
160
|
+
{
|
|
161
|
+
url: '/pet',
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
},
|
|
165
|
+
parameters: [
|
|
166
|
+
{
|
|
167
|
+
name: 'param1',
|
|
168
|
+
in: 'header',
|
|
169
|
+
schema: {
|
|
170
|
+
description: 'string',
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
components: {
|
|
177
|
+
schemas: {
|
|
178
|
+
'Third API_SchemaWithNull': {
|
|
179
|
+
type: 'string',
|
|
180
|
+
default: null,
|
|
181
|
+
nullable: true,
|
|
182
|
+
},
|
|
183
|
+
'Third API_SchemaWithRef': {
|
|
184
|
+
type: 'object',
|
|
185
|
+
properties: {
|
|
186
|
+
schemaType: {
|
|
187
|
+
type: 'string',
|
|
188
|
+
enum: ['foo'],
|
|
189
|
+
},
|
|
190
|
+
foo: {
|
|
191
|
+
$ref: '#/components/schemas/Third API_SchemaWithNull',
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
'Third API_SchemaWithDiscriminator': {
|
|
196
|
+
discriminator: {
|
|
197
|
+
propertyName: 'schemaType',
|
|
198
|
+
mapping: {
|
|
199
|
+
foo: '#/components/schemas/Third API_SchemaWithRef',
|
|
200
|
+
bar: '#/components/schemas/Third API_SchemaWithNull',
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
oneOf: [
|
|
204
|
+
{
|
|
205
|
+
$ref: '#/components/schemas/Third API_SchemaWithRef',
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
type: 'object',
|
|
209
|
+
properties: {
|
|
210
|
+
schemaType: {
|
|
211
|
+
type: 'string',
|
|
212
|
+
enum: ['bar'],
|
|
213
|
+
},
|
|
214
|
+
bar: {
|
|
215
|
+
type: 'string',
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
'x-tagGroups': [
|
|
224
|
+
{
|
|
225
|
+
name: 'First API',
|
|
226
|
+
tags: ['pet'],
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
}, 'join-result.yaml', true);
|
|
230
|
+
}));
|
|
108
231
|
});
|
package/lib/commands/join.d.ts
CHANGED
package/lib/commands/join.js
CHANGED
|
@@ -18,7 +18,7 @@ const openapi_core_1 = require("@redocly/openapi-core");
|
|
|
18
18
|
const miscellaneous_1 = require("../utils/miscellaneous");
|
|
19
19
|
const js_utils_1 = require("../utils/js-utils");
|
|
20
20
|
const types_1 = require("./split/types");
|
|
21
|
-
const
|
|
21
|
+
const split_1 = require("./split");
|
|
22
22
|
const Tags = 'tags';
|
|
23
23
|
const xTagGroups = 'x-tagGroups';
|
|
24
24
|
let potentialConflictsTotal = 0;
|
|
@@ -112,7 +112,7 @@ function handleJoin(argv, config, packageVersion) {
|
|
|
112
112
|
const tagsPrefix = prefixTagsWithFilename
|
|
113
113
|
? apiFilename
|
|
114
114
|
: getInfoPrefix(info, prefixTagsWithInfoProp, 'tags');
|
|
115
|
-
const componentsPrefix = getInfoPrefix(info, prefixComponentsWithInfoProp, COMPONENTS);
|
|
115
|
+
const componentsPrefix = getInfoPrefix(info, prefixComponentsWithInfoProp, types_1.COMPONENTS);
|
|
116
116
|
if (openapi.hasOwnProperty('x-tagGroups')) {
|
|
117
117
|
process.stderr.write((0, colorette_1.yellow)(`warning: x-tagGroups at ${(0, colorette_1.blue)(api)} will be skipped \n`));
|
|
118
118
|
}
|
|
@@ -390,13 +390,13 @@ function handleJoin(argv, config, packageVersion) {
|
|
|
390
390
|
function collectComponents(openapi, { api, potentialConflicts, componentsPrefix }) {
|
|
391
391
|
const { components } = openapi;
|
|
392
392
|
if (components) {
|
|
393
|
-
if (!joinedDef.hasOwnProperty(COMPONENTS)) {
|
|
394
|
-
joinedDef[COMPONENTS] = {};
|
|
393
|
+
if (!joinedDef.hasOwnProperty(types_1.COMPONENTS)) {
|
|
394
|
+
joinedDef[types_1.COMPONENTS] = {};
|
|
395
395
|
}
|
|
396
396
|
for (const [component, componentObj] of Object.entries(components)) {
|
|
397
|
-
if (!potentialConflicts[COMPONENTS].hasOwnProperty(component)) {
|
|
398
|
-
potentialConflicts[COMPONENTS][component] = {};
|
|
399
|
-
joinedDef[COMPONENTS][component] = {};
|
|
397
|
+
if (!potentialConflicts[types_1.COMPONENTS].hasOwnProperty(component)) {
|
|
398
|
+
potentialConflicts[types_1.COMPONENTS][component] = {};
|
|
399
|
+
joinedDef[types_1.COMPONENTS][component] = {};
|
|
400
400
|
}
|
|
401
401
|
for (const item of Object.keys(componentObj)) {
|
|
402
402
|
const componentPrefix = addPrefix(item, componentsPrefix);
|
|
@@ -449,7 +449,7 @@ function handleJoin(argv, config, packageVersion) {
|
|
|
449
449
|
var _a;
|
|
450
450
|
const firstApi = documents[0];
|
|
451
451
|
const openapi = firstApi.parsed;
|
|
452
|
-
const componentsPrefix = getInfoPrefix(openapi.info, prefixComponentsWithInfoProp, COMPONENTS);
|
|
452
|
+
const componentsPrefix = getInfoPrefix(openapi.info, prefixComponentsWithInfoProp, types_1.COMPONENTS);
|
|
453
453
|
if (!openapi.openapi)
|
|
454
454
|
(0, miscellaneous_1.exitWithError)('Version of specification is not found in. \n');
|
|
455
455
|
if (!openapi.info)
|
|
@@ -481,7 +481,7 @@ function iteratePotentialConflicts(potentialConflicts, withoutXTagGroups) {
|
|
|
481
481
|
for (const [key, value] of Object.entries(potentialConflicts[group])) {
|
|
482
482
|
const conflicts = filterConflicts(value);
|
|
483
483
|
if (conflicts.length) {
|
|
484
|
-
if (group === COMPONENTS) {
|
|
484
|
+
if (group === types_1.COMPONENTS) {
|
|
485
485
|
for (const [_, conflict] of Object.entries(conflicts)) {
|
|
486
486
|
if (validateComponentsDifference(conflict[1])) {
|
|
487
487
|
conflict[1] = conflict[1].map((c) => Object.keys(c)[0]);
|
|
@@ -540,8 +540,11 @@ function addComponentsPrefix(description, componentsPrefix) {
|
|
|
540
540
|
function addSecurityPrefix(security, componentsPrefix) {
|
|
541
541
|
return componentsPrefix
|
|
542
542
|
? security === null || security === void 0 ? void 0 : security.map((s) => {
|
|
543
|
-
const
|
|
544
|
-
|
|
543
|
+
const joinedSecuritySchema = {};
|
|
544
|
+
for (const [key, value] of Object.entries(s)) {
|
|
545
|
+
Object.assign(joinedSecuritySchema, { [componentsPrefix + '_' + key]: value });
|
|
546
|
+
}
|
|
547
|
+
return joinedSecuritySchema;
|
|
545
548
|
})
|
|
546
549
|
: security;
|
|
547
550
|
}
|
|
@@ -571,27 +574,18 @@ function validateApi(document, config, externalRefResolver, packageVersion) {
|
|
|
571
574
|
}
|
|
572
575
|
});
|
|
573
576
|
}
|
|
574
|
-
function crawl(object, visitor) {
|
|
575
|
-
if (!(0, js_utils_1.isObject)(object))
|
|
576
|
-
return;
|
|
577
|
-
for (const key of Object.keys(object)) {
|
|
578
|
-
visitor(object[key], key);
|
|
579
|
-
crawl(object[key], visitor);
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
577
|
function replace$Refs(obj, componentsPrefix) {
|
|
583
|
-
crawl(obj, (node) => {
|
|
584
|
-
if (node.$ref && (0,
|
|
578
|
+
(0, split_1.crawl)(obj, (node) => {
|
|
579
|
+
if (node.$ref && typeof node.$ref === 'string' && (0, split_1.startsWithComponents)(node.$ref)) {
|
|
585
580
|
const name = path.basename(node.$ref);
|
|
586
581
|
node.$ref = node.$ref.replace(name, componentsPrefix + '_' + name);
|
|
587
582
|
}
|
|
588
|
-
else if (node.discriminator &&
|
|
589
|
-
node.discriminator.mapping &&
|
|
590
|
-
(0, js_utils_1.isObject)(node.discriminator.mapping)) {
|
|
583
|
+
else if ((0, js_utils_1.isObject)(node.discriminator) && (0, js_utils_1.isObject)(node.discriminator.mapping)) {
|
|
591
584
|
const { mapping } = node.discriminator;
|
|
592
585
|
for (const name of Object.keys(mapping)) {
|
|
593
|
-
|
|
594
|
-
|
|
586
|
+
const mappingPointer = mapping[name];
|
|
587
|
+
if (typeof mappingPointer === 'string' && (0, split_1.startsWithComponents)(mappingPointer)) {
|
|
588
|
+
mapping[name] = mappingPointer
|
|
595
589
|
.split('/')
|
|
596
590
|
.map((name, i, arr) => {
|
|
597
591
|
return arr.length - 1 === i && !name.includes(componentsPrefix)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Oas3PathItem, Referenced } from './types';
|
|
1
|
+
import type { Oas3PathItem, Referenced } from './types';
|
|
2
2
|
export type SplitOptions = {
|
|
3
3
|
api: string;
|
|
4
4
|
outDir: string;
|
|
@@ -6,5 +6,7 @@ export type SplitOptions = {
|
|
|
6
6
|
config?: string;
|
|
7
7
|
};
|
|
8
8
|
export declare function handleSplit(argv: SplitOptions): Promise<void>;
|
|
9
|
+
export declare function startsWithComponents(node: string): boolean;
|
|
10
|
+
export declare function crawl(object: unknown, visitor: (node: Record<string, unknown>) => void): void;
|
|
9
11
|
declare function iteratePathItems(pathItems: Record<string, Referenced<Oas3PathItem>> | undefined, openapiDir: string, outDir: string, componentsFiles: object, pathSeparator: string, codeSamplesPathPrefix: string | undefined, ext: string): void;
|
|
10
12
|
export { iteratePathItems };
|
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.iteratePathItems = exports.handleSplit = void 0;
|
|
12
|
+
exports.iteratePathItems = exports.crawl = exports.startsWithComponents = exports.handleSplit = void 0;
|
|
13
13
|
const colorette_1 = require("colorette");
|
|
14
14
|
const fs = require("fs");
|
|
15
15
|
const openapi_core_1 = require("@redocly/openapi-core");
|
|
@@ -44,9 +44,10 @@ function splitDefinition(openapi, openapiDir, pathSeparator, ext) {
|
|
|
44
44
|
replace$Refs(openapi, openapiDir, componentsFiles);
|
|
45
45
|
(0, miscellaneous_1.writeToFileByExtension)(openapi, path.join(openapiDir, `openapi.${ext}`));
|
|
46
46
|
}
|
|
47
|
-
function
|
|
48
|
-
return node.startsWith(types_1.
|
|
47
|
+
function startsWithComponents(node) {
|
|
48
|
+
return node.startsWith(`#/${types_1.COMPONENTS}/`);
|
|
49
49
|
}
|
|
50
|
+
exports.startsWithComponents = startsWithComponents;
|
|
50
51
|
function isSupportedExtension(filename) {
|
|
51
52
|
return filename.endsWith('.yaml') || filename.endsWith('.yml') || filename.endsWith('.json');
|
|
52
53
|
}
|
|
@@ -92,22 +93,22 @@ function traverseDirectoryDeepCallback(filename, directory, componentsFiles) {
|
|
|
92
93
|
function crawl(object, visitor) {
|
|
93
94
|
if (!(0, js_utils_1.isObject)(object))
|
|
94
95
|
return;
|
|
96
|
+
visitor(object);
|
|
95
97
|
for (const key of Object.keys(object)) {
|
|
96
|
-
visitor(object, key);
|
|
97
98
|
crawl(object[key], visitor);
|
|
98
99
|
}
|
|
99
100
|
}
|
|
101
|
+
exports.crawl = crawl;
|
|
100
102
|
function replace$Refs(obj, relativeFrom, componentFiles = {}) {
|
|
101
103
|
crawl(obj, (node) => {
|
|
102
|
-
if (node.$ref &&
|
|
104
|
+
if (node.$ref && typeof node.$ref === 'string' && startsWithComponents(node.$ref)) {
|
|
103
105
|
replace(node, '$ref');
|
|
104
106
|
}
|
|
105
|
-
else if (node.discriminator &&
|
|
106
|
-
node.discriminator.mapping &&
|
|
107
|
-
(0, js_utils_1.isObject)(node.discriminator.mapping)) {
|
|
107
|
+
else if ((0, js_utils_1.isObject)(node.discriminator) && (0, js_utils_1.isObject)(node.discriminator.mapping)) {
|
|
108
108
|
const { mapping } = node.discriminator;
|
|
109
109
|
for (const name of Object.keys(mapping)) {
|
|
110
|
-
|
|
110
|
+
const mappingPointer = mapping[name];
|
|
111
|
+
if (typeof mappingPointer === 'string' && startsWithComponents(mappingPointer)) {
|
|
111
112
|
replace(node.discriminator.mapping, name);
|
|
112
113
|
}
|
|
113
114
|
}
|
|
@@ -4,14 +4,13 @@ export type Definition = Oas3_1Definition | Oas3Definition | Oas2Definition;
|
|
|
4
4
|
export interface ComponentsFiles {
|
|
5
5
|
[schemas: string]: any;
|
|
6
6
|
}
|
|
7
|
-
export interface
|
|
7
|
+
export interface RefObject {
|
|
8
8
|
[$ref: string]: string;
|
|
9
9
|
}
|
|
10
10
|
export declare const COMPONENTS = "components";
|
|
11
11
|
export declare const PATHS = "paths";
|
|
12
12
|
export declare const WEBHOOKS = "webhooks";
|
|
13
13
|
export declare const xWEBHOOKS = "x-webhooks";
|
|
14
|
-
export declare const componentsPath = "#/components/";
|
|
15
14
|
export declare enum OPENAPI3_METHOD {
|
|
16
15
|
get = "get",
|
|
17
16
|
put = "put",
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OPENAPI3_COMPONENT_NAMES = exports.OPENAPI3_COMPONENT = exports.OPENAPI3_METHOD_NAMES = exports.OPENAPI3_METHOD = exports.
|
|
3
|
+
exports.OPENAPI3_COMPONENT_NAMES = exports.OPENAPI3_COMPONENT = exports.OPENAPI3_METHOD_NAMES = exports.OPENAPI3_METHOD = exports.xWEBHOOKS = exports.WEBHOOKS = exports.PATHS = exports.COMPONENTS = void 0;
|
|
4
4
|
exports.COMPONENTS = 'components';
|
|
5
5
|
exports.PATHS = 'paths';
|
|
6
6
|
exports.WEBHOOKS = 'webhooks';
|
|
7
7
|
exports.xWEBHOOKS = 'x-webhooks';
|
|
8
|
-
exports.componentsPath = `#/${exports.COMPONENTS}/`;
|
|
9
8
|
var OPENAPI3_METHOD;
|
|
10
9
|
(function (OPENAPI3_METHOD) {
|
|
11
10
|
OPENAPI3_METHOD["get"] = "get";
|
package/lib/utils/js-utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare function isObject(obj:
|
|
1
|
+
export declare function isObject(obj: unknown): obj is Record<string, unknown>;
|
|
2
2
|
export declare function isEmptyObject(obj: any): boolean;
|
|
3
3
|
export declare function isString(str: string): boolean;
|
|
4
4
|
export declare function keysOf<T>(obj: T): (keyof T)[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/cli",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"Roman Hotsiy <roman@redoc.ly> (https://redoc.ly/)"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@redocly/openapi-core": "1.9.
|
|
39
|
+
"@redocly/openapi-core": "1.9.1",
|
|
40
40
|
"abort-controller": "^3.0.0",
|
|
41
41
|
"chokidar": "^3.5.1",
|
|
42
42
|
"colorette": "^1.2.0",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ConfigFixture } from './../../__tests__/fixtures/config';
|
|
2
|
-
import { firstDocument, secondDocument } from '../documents';
|
|
2
|
+
import { firstDocument, secondDocument, thirdDocument } from '../documents';
|
|
3
3
|
|
|
4
4
|
import type { Document } from '@redocly/openapi-core';
|
|
5
5
|
|
|
@@ -47,6 +47,9 @@ export class BaseResolver {
|
|
|
47
47
|
)
|
|
48
48
|
.mockImplementationOnce(() =>
|
|
49
49
|
Promise.resolve({ source: { absoluteRef: 'ref' }, parsed: secondDocument })
|
|
50
|
+
)
|
|
51
|
+
.mockImplementationOnce(() =>
|
|
52
|
+
Promise.resolve({ source: { absoluteRef: 'ref' }, parsed: thirdDocument })
|
|
50
53
|
);
|
|
51
54
|
}
|
|
52
55
|
|
|
@@ -4,7 +4,7 @@ export const firstDocument = {
|
|
|
4
4
|
info: {
|
|
5
5
|
description: 'example test',
|
|
6
6
|
version: '1.0.0',
|
|
7
|
-
title: '
|
|
7
|
+
title: 'First API',
|
|
8
8
|
termsOfService: 'http://swagger.io/terms/',
|
|
9
9
|
license: {
|
|
10
10
|
name: 'Apache 2.0',
|
|
@@ -36,7 +36,7 @@ export const secondDocument = {
|
|
|
36
36
|
info: {
|
|
37
37
|
description: 'example test',
|
|
38
38
|
version: '1.0.0',
|
|
39
|
-
title: '
|
|
39
|
+
title: 'Second API',
|
|
40
40
|
termsOfService: 'http://swagger.io/terms/',
|
|
41
41
|
license: {
|
|
42
42
|
name: 'Apache 2.0',
|
|
@@ -61,3 +61,64 @@ export const secondDocument = {
|
|
|
61
61
|
},
|
|
62
62
|
components: {},
|
|
63
63
|
};
|
|
64
|
+
|
|
65
|
+
export const thirdDocument = {
|
|
66
|
+
openapi: '3.0.0',
|
|
67
|
+
info: {
|
|
68
|
+
title: 'Third API',
|
|
69
|
+
version: '1.0',
|
|
70
|
+
},
|
|
71
|
+
servers: [
|
|
72
|
+
{
|
|
73
|
+
url: 'https://api.server.test/v1',
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
paths: {},
|
|
77
|
+
components: {
|
|
78
|
+
schemas: {
|
|
79
|
+
SchemaWithNull: {
|
|
80
|
+
type: 'string',
|
|
81
|
+
default: null,
|
|
82
|
+
nullable: true,
|
|
83
|
+
},
|
|
84
|
+
SchemaWithRef: {
|
|
85
|
+
type: 'object',
|
|
86
|
+
properties: {
|
|
87
|
+
schemaType: {
|
|
88
|
+
type: 'string',
|
|
89
|
+
enum: ['foo'],
|
|
90
|
+
},
|
|
91
|
+
foo: {
|
|
92
|
+
$ref: '#/components/schemas/SchemaWithNull',
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
SchemaWithDiscriminator: {
|
|
97
|
+
discriminator: {
|
|
98
|
+
propertyName: 'schemaType',
|
|
99
|
+
mapping: {
|
|
100
|
+
foo: '#/components/schemas/SchemaWithRef',
|
|
101
|
+
bar: '#/components/schemas/SchemaWithNull',
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
oneOf: [
|
|
105
|
+
{
|
|
106
|
+
$ref: '#/components/schemas/SchemaWithRef',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
type: 'object',
|
|
110
|
+
properties: {
|
|
111
|
+
schemaType: {
|
|
112
|
+
type: 'string',
|
|
113
|
+
enum: ['bar'],
|
|
114
|
+
},
|
|
115
|
+
bar: {
|
|
116
|
+
type: 'string',
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
};
|