@redocly/cli 1.0.0-beta.96
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/README.md +39 -0
- package/bin/cli.js +3 -0
- package/lib/__mocks__/utils.d.ts +17 -0
- package/lib/__mocks__/utils.js +14 -0
- package/lib/__tests__/commands/bundle.test.d.ts +1 -0
- package/lib/__tests__/commands/bundle.test.js +92 -0
- package/lib/__tests__/commands/push-region.test.d.ts +1 -0
- package/lib/__tests__/commands/push-region.test.js +55 -0
- package/lib/__tests__/commands/push.test.d.ts +1 -0
- package/lib/__tests__/commands/push.test.js +153 -0
- package/lib/__tests__/utils.test.d.ts +1 -0
- package/lib/__tests__/utils.test.js +41 -0
- package/lib/assert-node-version.d.ts +1 -0
- package/lib/assert-node-version.js +10 -0
- package/lib/commands/bundle.d.ts +19 -0
- package/lib/commands/bundle.js +128 -0
- package/lib/commands/join.d.ts +7 -0
- package/lib/commands/join.js +421 -0
- package/lib/commands/lint.d.ts +11 -0
- package/lib/commands/lint.js +80 -0
- package/lib/commands/login.d.ts +6 -0
- package/lib/commands/login.js +28 -0
- package/lib/commands/preview-docs/index.d.ts +12 -0
- package/lib/commands/preview-docs/index.js +141 -0
- package/lib/commands/preview-docs/preview-server/default.hbs +24 -0
- package/lib/commands/preview-docs/preview-server/hot.js +42 -0
- package/lib/commands/preview-docs/preview-server/oauth2-redirect.html +21 -0
- package/lib/commands/preview-docs/preview-server/preview-server.d.ts +5 -0
- package/lib/commands/preview-docs/preview-server/preview-server.js +120 -0
- package/lib/commands/preview-docs/preview-server/server.d.ts +23 -0
- package/lib/commands/preview-docs/preview-server/server.js +85 -0
- package/lib/commands/push.d.ts +25 -0
- package/lib/commands/push.js +247 -0
- package/lib/commands/split/__tests__/index.test.d.ts +1 -0
- package/lib/commands/split/__tests__/index.test.js +70 -0
- package/lib/commands/split/index.d.ts +8 -0
- package/lib/commands/split/index.js +279 -0
- package/lib/commands/split/types.d.ts +37 -0
- package/lib/commands/split/types.js +52 -0
- package/lib/commands/stats.d.ts +5 -0
- package/lib/commands/stats.js +92 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +269 -0
- package/lib/js-utils.d.ts +3 -0
- package/lib/js-utils.js +16 -0
- package/lib/types.d.ts +13 -0
- package/lib/types.js +5 -0
- package/lib/utils.d.ts +28 -0
- package/lib/utils.js +260 -0
- package/package.json +54 -0
- package/src/__mocks__/utils.ts +11 -0
- package/src/__tests__/commands/bundle.test.ts +120 -0
- package/src/__tests__/commands/push-region.test.ts +51 -0
- package/src/__tests__/commands/push.test.ts +156 -0
- package/src/__tests__/utils.test.ts +50 -0
- package/src/assert-node-version.ts +8 -0
- package/src/commands/bundle.ts +178 -0
- package/src/commands/join.ts +488 -0
- package/src/commands/lint.ts +110 -0
- package/src/commands/login.ts +19 -0
- package/src/commands/preview-docs/index.ts +188 -0
- package/src/commands/preview-docs/preview-server/default.hbs +24 -0
- package/src/commands/preview-docs/preview-server/hot.js +42 -0
- package/src/commands/preview-docs/preview-server/oauth2-redirect.html +21 -0
- package/src/commands/preview-docs/preview-server/preview-server.ts +150 -0
- package/src/commands/preview-docs/preview-server/server.ts +91 -0
- package/src/commands/push.ts +355 -0
- package/src/commands/split/__tests__/fixtures/spec.json +70 -0
- package/src/commands/split/__tests__/fixtures/webhooks.json +88 -0
- package/src/commands/split/__tests__/index.test.ts +96 -0
- package/src/commands/split/index.ts +349 -0
- package/src/commands/split/types.ts +73 -0
- package/src/commands/stats.ts +115 -0
- package/src/index.ts +311 -0
- package/src/js-utils.ts +12 -0
- package/src/types.ts +13 -0
- package/src/utils.ts +300 -0
- package/tsconfig.json +9 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
12
|
+
var t = {};
|
|
13
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
14
|
+
t[p] = s[p];
|
|
15
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
16
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
17
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
18
|
+
t[p[i]] = s[p[i]];
|
|
19
|
+
}
|
|
20
|
+
return t;
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.getApiEntrypoint = exports.transformPush = exports.getDestinationProps = exports.handlePush = void 0;
|
|
24
|
+
const fs = require("fs");
|
|
25
|
+
const path = require("path");
|
|
26
|
+
const node_fetch_1 = require("node-fetch");
|
|
27
|
+
const perf_hooks_1 = require("perf_hooks");
|
|
28
|
+
const colorette_1 = require("colorette");
|
|
29
|
+
const crypto_1 = require("crypto");
|
|
30
|
+
const openapi_core_1 = require("@redocly/openapi-core");
|
|
31
|
+
const utils_1 = require("../utils");
|
|
32
|
+
const login_1 = require("./login");
|
|
33
|
+
const DEFAULT_VERSION = 'latest';
|
|
34
|
+
function handlePush(argv) {
|
|
35
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
const config = yield openapi_core_1.loadConfig();
|
|
37
|
+
const region = argv.region || config.region;
|
|
38
|
+
const client = new openapi_core_1.RedoclyClient(region);
|
|
39
|
+
const isAuthorized = yield client.isAuthorizedWithRedoclyByRegion();
|
|
40
|
+
if (!isAuthorized) {
|
|
41
|
+
const clientToken = yield login_1.promptClientToken(client.domain);
|
|
42
|
+
yield client.login(clientToken);
|
|
43
|
+
}
|
|
44
|
+
const startedAt = perf_hooks_1.performance.now();
|
|
45
|
+
const { destination, branchName, upsert } = argv;
|
|
46
|
+
if (destination &&
|
|
47
|
+
!(validateDestination(destination) || validateDestinationWithoutOrganization(destination))) {
|
|
48
|
+
utils_1.exitWithError(`Destination argument value is not valid, please use the right format: ${colorette_1.yellow('<@organization-id/api-name@api-version>')}`);
|
|
49
|
+
}
|
|
50
|
+
const [organizationId, name, version] = getDestinationProps(destination, config.organization);
|
|
51
|
+
if (!organizationId) {
|
|
52
|
+
return utils_1.exitWithError(`No organization provided, please use the right format: ${colorette_1.yellow('<@organization-id/api-name@api-version>')} or specify the 'organization' field in the config file.`);
|
|
53
|
+
}
|
|
54
|
+
const entrypoint = argv.entrypoint || (name && version && getApiEntrypoint({ name, version, config }));
|
|
55
|
+
if (name && version && !entrypoint) {
|
|
56
|
+
utils_1.exitWithError(`No entrypoint found that matches ${colorette_1.blue(`${name}@${version}`)}. Please make sure you have provided the correct data in the config file.`);
|
|
57
|
+
}
|
|
58
|
+
const apis = entrypoint ? { [`${name}@${version}`]: { root: entrypoint } } : config.apis;
|
|
59
|
+
for (const [apiNameAndVersion, { root: entrypoint }] of Object.entries(apis)) {
|
|
60
|
+
const resolvedConfig = openapi_core_1.getMergedConfig(config, apiNameAndVersion);
|
|
61
|
+
resolvedConfig.lint.skipDecorators(argv['skip-decorator']);
|
|
62
|
+
const [name, version = DEFAULT_VERSION] = apiNameAndVersion.split('@');
|
|
63
|
+
try {
|
|
64
|
+
let rootFilePath = '';
|
|
65
|
+
const filePaths = [];
|
|
66
|
+
const filesToUpload = yield collectFilesToUpload(entrypoint, resolvedConfig);
|
|
67
|
+
const filesHash = hashFiles(filesToUpload.files);
|
|
68
|
+
process.stdout.write(`Uploading ${filesToUpload.files.length} ${utils_1.pluralize('file', filesToUpload.files.length)}:\n`);
|
|
69
|
+
let uploaded = 0;
|
|
70
|
+
for (let file of filesToUpload.files) {
|
|
71
|
+
const { signedUploadUrl, filePath } = yield client.registryApi.prepareFileUpload({
|
|
72
|
+
organizationId,
|
|
73
|
+
name,
|
|
74
|
+
version,
|
|
75
|
+
filesHash,
|
|
76
|
+
filename: file.keyOnS3,
|
|
77
|
+
isUpsert: upsert,
|
|
78
|
+
});
|
|
79
|
+
if (file.filePath === filesToUpload.root) {
|
|
80
|
+
rootFilePath = filePath;
|
|
81
|
+
}
|
|
82
|
+
filePaths.push(filePath);
|
|
83
|
+
process.stdout.write(`Uploading ${file.contents ? 'bundle for ' : ''}${colorette_1.blue(file.filePath)}...`);
|
|
84
|
+
const uploadResponse = yield uploadFileToS3(signedUploadUrl, file.contents || file.filePath);
|
|
85
|
+
const fileCounter = `(${++uploaded}/${filesToUpload.files.length})`;
|
|
86
|
+
if (!uploadResponse.ok) {
|
|
87
|
+
utils_1.exitWithError(`✗ ${fileCounter}\nFile upload failed\n`);
|
|
88
|
+
}
|
|
89
|
+
process.stdout.write(colorette_1.green(`✓ ${fileCounter}\n`));
|
|
90
|
+
}
|
|
91
|
+
process.stdout.write('\n');
|
|
92
|
+
yield client.registryApi.pushApi({
|
|
93
|
+
organizationId,
|
|
94
|
+
name,
|
|
95
|
+
version,
|
|
96
|
+
rootFilePath,
|
|
97
|
+
filePaths,
|
|
98
|
+
branch: branchName,
|
|
99
|
+
isUpsert: upsert,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
if (error.message === 'ORGANIZATION_NOT_FOUND') {
|
|
104
|
+
utils_1.exitWithError(`Organization ${colorette_1.blue(organizationId)} not found`);
|
|
105
|
+
}
|
|
106
|
+
if (error.message === 'API_VERSION_NOT_FOUND') {
|
|
107
|
+
utils_1.exitWithError(`The definition version ${colorette_1.blue(name)}/${colorette_1.blue(version)} does not exist in organization ${colorette_1.blue(organizationId)}!\n${colorette_1.yellow('Suggestion:')} please use ${colorette_1.blue('-u')} or ${colorette_1.blue('--upsert')} to create definition.
|
|
108
|
+
`);
|
|
109
|
+
}
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
process.stdout.write(`Definition: ${colorette_1.blue(entrypoint)} is successfully pushed to Redocly API Registry \n`);
|
|
113
|
+
}
|
|
114
|
+
utils_1.printExecutionTime('push', startedAt, entrypoint || `apis in organization ${organizationId}`);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
exports.handlePush = handlePush;
|
|
118
|
+
function getFilesList(dir, files) {
|
|
119
|
+
files = files || [];
|
|
120
|
+
const filesAndDirs = fs.readdirSync(dir);
|
|
121
|
+
for (const name of filesAndDirs) {
|
|
122
|
+
if (fs.statSync(path.join(dir, name)).isDirectory()) {
|
|
123
|
+
files = getFilesList(path.join(dir, name), files);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
const currentPath = dir + '/' + name;
|
|
127
|
+
files.push(currentPath);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return files;
|
|
131
|
+
}
|
|
132
|
+
function collectFilesToUpload(entrypoint, config) {
|
|
133
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
134
|
+
let files = [];
|
|
135
|
+
const [{ path: entrypointPath }] = yield utils_1.getFallbackEntryPointsOrExit([entrypoint], config);
|
|
136
|
+
process.stdout.write('Bundling definition\n');
|
|
137
|
+
const { bundle: openapiBundle, problems } = yield openapi_core_1.bundle({
|
|
138
|
+
config,
|
|
139
|
+
ref: entrypointPath,
|
|
140
|
+
skipRedoclyRegistryRefs: true,
|
|
141
|
+
});
|
|
142
|
+
const fileTotals = openapi_core_1.getTotals(problems);
|
|
143
|
+
if (fileTotals.errors === 0) {
|
|
144
|
+
process.stdout.write(`Created a bundle for ${colorette_1.blue(entrypoint)} ${fileTotals.warnings > 0 ? 'with warnings' : ''}\n`);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
utils_1.exitWithError(`Failed to create a bundle for ${colorette_1.blue(entrypoint)}\n`);
|
|
148
|
+
}
|
|
149
|
+
const fileExt = path.extname(entrypointPath).split('.').pop();
|
|
150
|
+
files.push(getFileEntry(entrypointPath, utils_1.dumpBundle(openapiBundle.parsed, fileExt)));
|
|
151
|
+
if (fs.existsSync('package.json')) {
|
|
152
|
+
files.push(getFileEntry('package.json'));
|
|
153
|
+
}
|
|
154
|
+
if (fs.existsSync(openapi_core_1.IGNORE_FILE)) {
|
|
155
|
+
files.push(getFileEntry(openapi_core_1.IGNORE_FILE));
|
|
156
|
+
}
|
|
157
|
+
if (config.configFile) {
|
|
158
|
+
// All config file paths including the root one
|
|
159
|
+
files.push(...[...new Set(config.lint.extendPaths)].map((f) => getFileEntry(f)));
|
|
160
|
+
if (config['features.openapi'].htmlTemplate) {
|
|
161
|
+
const dir = getFolder(config['features.openapi'].htmlTemplate);
|
|
162
|
+
const fileList = getFilesList(dir, []);
|
|
163
|
+
files.push(...fileList.map((f) => getFileEntry(f)));
|
|
164
|
+
}
|
|
165
|
+
let pluginFiles = new Set();
|
|
166
|
+
for (const plugin of config.lint.pluginPaths) {
|
|
167
|
+
if (typeof plugin !== 'string')
|
|
168
|
+
continue;
|
|
169
|
+
const fileList = getFilesList(getFolder(plugin), []);
|
|
170
|
+
fileList.forEach((f) => pluginFiles.add(f));
|
|
171
|
+
}
|
|
172
|
+
files.push(...filterPluginFilesByExt(Array.from(pluginFiles)).map((f) => getFileEntry(f)));
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
files,
|
|
176
|
+
root: path.resolve(entrypointPath),
|
|
177
|
+
};
|
|
178
|
+
function filterPluginFilesByExt(files) {
|
|
179
|
+
return files.filter((file) => {
|
|
180
|
+
const fileExt = path.extname(file).toLowerCase();
|
|
181
|
+
return fileExt === '.js' || fileExt === '.ts' || fileExt === '.mjs' || fileExt === 'json';
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
function getFileEntry(filename, contents) {
|
|
185
|
+
return {
|
|
186
|
+
filePath: path.resolve(filename),
|
|
187
|
+
keyOnS3: config.configFile
|
|
188
|
+
? openapi_core_1.slash(path.relative(path.dirname(config.configFile), filename))
|
|
189
|
+
: openapi_core_1.slash(path.basename(filename)),
|
|
190
|
+
contents: (contents && Buffer.from(contents, 'utf-8')) || undefined,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
function getFolder(filePath) {
|
|
196
|
+
return path.resolve(path.dirname(filePath));
|
|
197
|
+
}
|
|
198
|
+
function hashFiles(filePaths) {
|
|
199
|
+
let sum = crypto_1.createHash('sha256');
|
|
200
|
+
filePaths.forEach((file) => sum.update(fs.readFileSync(file.filePath)));
|
|
201
|
+
return sum.digest('hex');
|
|
202
|
+
}
|
|
203
|
+
function validateDestination(destination) {
|
|
204
|
+
const regexp = /^@+([a-zA-Z0-9-_.& ]+)\/+([^@\/]+)@([^@\/]+)$/;
|
|
205
|
+
return regexp.test(destination);
|
|
206
|
+
}
|
|
207
|
+
function validateDestinationWithoutOrganization(destination) {
|
|
208
|
+
const regexp = /^()([^@\/]+)@([^@\/]+)$/;
|
|
209
|
+
return regexp.test(destination);
|
|
210
|
+
}
|
|
211
|
+
function getDestinationProps(destination, organization) {
|
|
212
|
+
return destination && validateDestination(destination)
|
|
213
|
+
? destination.substring(1).split(/[@\/]/)
|
|
214
|
+
: destination && validateDestinationWithoutOrganization(destination)
|
|
215
|
+
? [organization, ...destination.split('@')]
|
|
216
|
+
: [organization];
|
|
217
|
+
}
|
|
218
|
+
exports.getDestinationProps = getDestinationProps;
|
|
219
|
+
const transformPush = (callback) => (_a) => {
|
|
220
|
+
var { maybeEntrypointOrAliasOrDestination, maybeDestination, maybeBranchName, branch } = _a, rest = __rest(_a, ["maybeEntrypointOrAliasOrDestination", "maybeDestination", "maybeBranchName", "branch"]);
|
|
221
|
+
if (!!maybeBranchName) {
|
|
222
|
+
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.'));
|
|
223
|
+
}
|
|
224
|
+
const entrypoint = maybeDestination ? maybeEntrypointOrAliasOrDestination : undefined;
|
|
225
|
+
const destination = maybeDestination || maybeEntrypointOrAliasOrDestination;
|
|
226
|
+
return callback(Object.assign(Object.assign({}, rest), { destination,
|
|
227
|
+
entrypoint, branchName: branch !== null && branch !== void 0 ? branch : maybeBranchName }));
|
|
228
|
+
};
|
|
229
|
+
exports.transformPush = transformPush;
|
|
230
|
+
function getApiEntrypoint({ name, version, config: { apis }, }) {
|
|
231
|
+
const api = (apis === null || apis === void 0 ? void 0 : apis[`${name}@${version}`]) || (version === DEFAULT_VERSION && (apis === null || apis === void 0 ? void 0 : apis[name]));
|
|
232
|
+
return api === null || api === void 0 ? void 0 : api.root;
|
|
233
|
+
}
|
|
234
|
+
exports.getApiEntrypoint = getApiEntrypoint;
|
|
235
|
+
function uploadFileToS3(url, filePathOrBuffer) {
|
|
236
|
+
const fileSizeInBytes = typeof filePathOrBuffer === 'string'
|
|
237
|
+
? fs.statSync(filePathOrBuffer).size
|
|
238
|
+
: filePathOrBuffer.byteLength;
|
|
239
|
+
let readStream = typeof filePathOrBuffer === 'string' ? fs.createReadStream(filePathOrBuffer) : filePathOrBuffer;
|
|
240
|
+
return node_fetch_1.default(url, {
|
|
241
|
+
method: 'PUT',
|
|
242
|
+
headers: {
|
|
243
|
+
'Content-Length': fileSizeInBytes.toString(),
|
|
244
|
+
},
|
|
245
|
+
body: readStream,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const index_1 = require("../index");
|
|
13
|
+
const path = require("path");
|
|
14
|
+
const openapiCore = require("@redocly/openapi-core");
|
|
15
|
+
const colorette_1 = require("colorette");
|
|
16
|
+
jest.mock('../../../utils', () => (Object.assign(Object.assign({}, jest.requireActual('../../../utils')), { writeYaml: jest.fn() })));
|
|
17
|
+
jest.mock('@redocly/openapi-core', () => (Object.assign(Object.assign({}, jest.requireActual('@redocly/openapi-core')), { isRef: jest.fn() })));
|
|
18
|
+
describe('#split', () => {
|
|
19
|
+
const openapiDir = 'test';
|
|
20
|
+
const componentsFiles = {};
|
|
21
|
+
it('should split the file and show the success message', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
22
|
+
const filePath = "./packages/cli/src/commands/split/__tests__/fixtures/spec.json";
|
|
23
|
+
jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
24
|
+
yield index_1.handleSplit({
|
|
25
|
+
entrypoint: filePath,
|
|
26
|
+
outDir: openapiDir,
|
|
27
|
+
separator: '_',
|
|
28
|
+
});
|
|
29
|
+
expect(process.stderr.write).toBeCalledTimes(2);
|
|
30
|
+
expect(process.stderr.write.mock.calls[0][0]).toBe(`🪓 Document: ${colorette_1.blue(filePath)} ${colorette_1.green('is successfully split')}
|
|
31
|
+
and all related files are saved to the directory: ${colorette_1.blue(openapiDir)} \n`);
|
|
32
|
+
expect(process.stderr.write.mock.calls[1][0]).toContain(`${filePath}: split processed in <test>ms`);
|
|
33
|
+
}));
|
|
34
|
+
it('should use the correct separator', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
35
|
+
const filePath = "./packages/cli/src/commands/split/__tests__/fixtures/spec.json";
|
|
36
|
+
const utils = require('../../../utils');
|
|
37
|
+
jest.spyOn(utils, 'pathToFilename').mockImplementation(() => 'newFilePath');
|
|
38
|
+
yield index_1.handleSplit({
|
|
39
|
+
entrypoint: filePath,
|
|
40
|
+
outDir: openapiDir,
|
|
41
|
+
separator: '_',
|
|
42
|
+
});
|
|
43
|
+
expect(utils.pathToFilename).toBeCalledWith(expect.anything(), '_');
|
|
44
|
+
utils.pathToFilename.mockRestore();
|
|
45
|
+
}));
|
|
46
|
+
it('should have correct path with paths', () => {
|
|
47
|
+
const openapi = require("./fixtures/spec.json");
|
|
48
|
+
jest.spyOn(openapiCore, 'slash').mockImplementation(() => 'paths/test.yaml');
|
|
49
|
+
jest.spyOn(path, 'relative').mockImplementation(() => 'paths/test.yaml');
|
|
50
|
+
index_1.iteratePathItems(openapi.paths, openapiDir, path.join(openapiDir, 'paths'), componentsFiles, '_');
|
|
51
|
+
expect(openapiCore.slash).toHaveBeenCalledWith('paths/test.yaml');
|
|
52
|
+
expect(path.relative).toHaveBeenCalledWith('test', 'test/paths/test.yaml');
|
|
53
|
+
});
|
|
54
|
+
it('should have correct path with webhooks', () => {
|
|
55
|
+
const openapi = require("./fixtures/webhooks.json");
|
|
56
|
+
jest.spyOn(openapiCore, 'slash').mockImplementation(() => 'webhooks/test.yaml');
|
|
57
|
+
jest.spyOn(path, 'relative').mockImplementation(() => 'webhooks/test.yaml');
|
|
58
|
+
index_1.iteratePathItems(openapi.webhooks, openapiDir, path.join(openapiDir, 'webhooks'), componentsFiles, 'webhook_');
|
|
59
|
+
expect(openapiCore.slash).toHaveBeenCalledWith('webhooks/test.yaml');
|
|
60
|
+
expect(path.relative).toHaveBeenCalledWith('test', 'test/webhooks/test.yaml');
|
|
61
|
+
});
|
|
62
|
+
it('should have correct path with x-webhooks', () => {
|
|
63
|
+
const openapi = require("./fixtures/spec.json");
|
|
64
|
+
jest.spyOn(openapiCore, 'slash').mockImplementation(() => 'webhooks/test.yaml');
|
|
65
|
+
jest.spyOn(path, 'relative').mockImplementation(() => 'webhooks/test.yaml');
|
|
66
|
+
index_1.iteratePathItems(openapi['x-webhooks'], openapiDir, path.join(openapiDir, 'webhooks'), componentsFiles, 'webhook_');
|
|
67
|
+
expect(openapiCore.slash).toHaveBeenCalledWith('webhooks/test.yaml');
|
|
68
|
+
expect(path.relative).toHaveBeenCalledWith('test', 'test/webhooks/test.yaml');
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Oas3PathItem, Referenced } from './types';
|
|
2
|
+
export declare function handleSplit(argv: {
|
|
3
|
+
entrypoint: string;
|
|
4
|
+
outDir: string;
|
|
5
|
+
separator: string;
|
|
6
|
+
}): Promise<void>;
|
|
7
|
+
declare function iteratePathItems(pathItems: Record<string, Referenced<Oas3PathItem>> | undefined, openapiDir: string, outDir: string, componentsFiles: object, pathSeparator: string, codeSamplesPathPrefix?: string): void;
|
|
8
|
+
export { iteratePathItems };
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.iteratePathItems = exports.handleSplit = void 0;
|
|
13
|
+
const colorette_1 = require("colorette");
|
|
14
|
+
const fs = require("fs");
|
|
15
|
+
const openapi_core_1 = require("@redocly/openapi-core");
|
|
16
|
+
const path = require("path");
|
|
17
|
+
const perf_hooks_1 = require("perf_hooks");
|
|
18
|
+
const isEqual = require('lodash.isequal');
|
|
19
|
+
const utils_1 = require("../../utils");
|
|
20
|
+
const js_utils_1 = require("../../js-utils");
|
|
21
|
+
const types_1 = require("./types");
|
|
22
|
+
function handleSplit(argv) {
|
|
23
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
const startedAt = perf_hooks_1.performance.now();
|
|
25
|
+
const { entrypoint, outDir, separator } = argv;
|
|
26
|
+
validateDefinitionFileName(entrypoint);
|
|
27
|
+
const openapi = utils_1.readYaml(entrypoint);
|
|
28
|
+
splitDefinition(openapi, outDir, separator);
|
|
29
|
+
process.stderr.write(`🪓 Document: ${colorette_1.blue(entrypoint)} ${colorette_1.green('is successfully split')}
|
|
30
|
+
and all related files are saved to the directory: ${colorette_1.blue(outDir)} \n`);
|
|
31
|
+
utils_1.printExecutionTime('split', startedAt, entrypoint);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
exports.handleSplit = handleSplit;
|
|
35
|
+
function splitDefinition(openapi, openapiDir, pathSeparator) {
|
|
36
|
+
fs.mkdirSync(openapiDir, { recursive: true });
|
|
37
|
+
const componentsFiles = {};
|
|
38
|
+
iterateComponents(openapi, openapiDir, componentsFiles);
|
|
39
|
+
iteratePathItems(openapi.paths, openapiDir, path.join(openapiDir, 'paths'), componentsFiles, pathSeparator);
|
|
40
|
+
const webhooks = openapi.webhooks || openapi['x-webhooks'];
|
|
41
|
+
// use webhook_ prefix for code samples to prevent potential name-clashes with paths samples
|
|
42
|
+
iteratePathItems(webhooks, openapiDir, path.join(openapiDir, 'webhooks'), componentsFiles, pathSeparator, 'webhook_');
|
|
43
|
+
replace$Refs(openapi, openapiDir, componentsFiles);
|
|
44
|
+
utils_1.writeYaml(openapi, path.join(openapiDir, 'openapi.yaml'));
|
|
45
|
+
}
|
|
46
|
+
function isStartsWithComponents(node) {
|
|
47
|
+
return node.startsWith(types_1.componentsPath);
|
|
48
|
+
}
|
|
49
|
+
function isNotYaml(filename) {
|
|
50
|
+
return !(filename.endsWith('.yaml') || filename.endsWith('.yml'));
|
|
51
|
+
}
|
|
52
|
+
function loadFile(fileName) {
|
|
53
|
+
try {
|
|
54
|
+
return openapi_core_1.parseYaml(fs.readFileSync(fileName, 'utf8'));
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
return utils_1.exitWithError(e.message);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function validateDefinitionFileName(fileName) {
|
|
61
|
+
if (!fs.existsSync(fileName))
|
|
62
|
+
utils_1.exitWithError(`File ${colorette_1.blue(fileName)} does not exist \n`);
|
|
63
|
+
const file = loadFile(fileName);
|
|
64
|
+
if (file.swagger)
|
|
65
|
+
utils_1.exitWithError('OpenAPI 2 is not supported by this command');
|
|
66
|
+
if (!file.openapi)
|
|
67
|
+
utils_1.exitWithError('File does not conform to the OpenAPI Specification. OpenAPI version is not specified');
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
function langToExt(lang) {
|
|
71
|
+
const langObj = {
|
|
72
|
+
php: '.php',
|
|
73
|
+
'c#': '.cs',
|
|
74
|
+
shell: '.sh',
|
|
75
|
+
curl: '.sh',
|
|
76
|
+
bash: '.sh',
|
|
77
|
+
javascript: '.js',
|
|
78
|
+
js: '.js',
|
|
79
|
+
python: '.py'
|
|
80
|
+
};
|
|
81
|
+
return langObj[lang];
|
|
82
|
+
}
|
|
83
|
+
function traverseDirectoryDeep(directory, callback, componentsFiles) {
|
|
84
|
+
if (!fs.existsSync(directory) || !fs.statSync(directory).isDirectory())
|
|
85
|
+
return;
|
|
86
|
+
const files = fs.readdirSync(directory);
|
|
87
|
+
for (const f of files) {
|
|
88
|
+
const filename = path.join(directory, f);
|
|
89
|
+
if (fs.statSync(filename).isDirectory()) {
|
|
90
|
+
traverseDirectoryDeep(filename, callback, componentsFiles);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
callback(filename, directory, componentsFiles);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function traverseDirectoryDeepCallback(filename, directory, componentsFiles) {
|
|
98
|
+
if (isNotYaml(filename))
|
|
99
|
+
return;
|
|
100
|
+
const pathData = utils_1.readYaml(filename);
|
|
101
|
+
replace$Refs(pathData, directory, componentsFiles);
|
|
102
|
+
utils_1.writeYaml(pathData, filename);
|
|
103
|
+
}
|
|
104
|
+
function crawl(object, visitor) {
|
|
105
|
+
if (!js_utils_1.isObject(object))
|
|
106
|
+
return;
|
|
107
|
+
for (const key of Object.keys(object)) {
|
|
108
|
+
visitor(object, key);
|
|
109
|
+
crawl(object[key], visitor);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function replace$Refs(obj, relativeFrom, componentFiles = {}) {
|
|
113
|
+
crawl(obj, (node) => {
|
|
114
|
+
if (node.$ref && js_utils_1.isString(node.$ref) && isStartsWithComponents(node.$ref)) {
|
|
115
|
+
replace(node, '$ref');
|
|
116
|
+
}
|
|
117
|
+
else if (node.discriminator &&
|
|
118
|
+
node.discriminator.mapping &&
|
|
119
|
+
js_utils_1.isObject(node.discriminator.mapping)) {
|
|
120
|
+
const { mapping } = node.discriminator;
|
|
121
|
+
for (const name of Object.keys(mapping)) {
|
|
122
|
+
if (js_utils_1.isString(mapping[name]) && isStartsWithComponents(mapping[name])) {
|
|
123
|
+
replace(node.discriminator.mapping, name);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
function replace(node, key) {
|
|
129
|
+
const splittedNode = node[key].split('/');
|
|
130
|
+
const name = splittedNode.pop();
|
|
131
|
+
const groupName = splittedNode[2];
|
|
132
|
+
const filesGroupName = componentFiles[groupName];
|
|
133
|
+
if (!filesGroupName || !filesGroupName[name])
|
|
134
|
+
return;
|
|
135
|
+
let filename = path.relative(relativeFrom, filesGroupName[name].filename);
|
|
136
|
+
if (!filename.startsWith('.')) {
|
|
137
|
+
filename = '.' + path.sep + filename;
|
|
138
|
+
}
|
|
139
|
+
node[key] = filename;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function implicitlyReferenceDiscriminator(obj, defName, filename, schemaFiles) {
|
|
143
|
+
if (!obj.discriminator)
|
|
144
|
+
return;
|
|
145
|
+
const defPtr = `#/${types_1.COMPONENTS}/${types_1.OPENAPI3_COMPONENT.Schemas}/${defName}`;
|
|
146
|
+
const implicitMapping = {};
|
|
147
|
+
for (const [name, { inherits, filename: parentFilename }] of Object.entries(schemaFiles)) {
|
|
148
|
+
if (inherits.indexOf(defPtr) > -1) {
|
|
149
|
+
const res = path.relative(path.dirname(filename), parentFilename);
|
|
150
|
+
implicitMapping[name] = res.startsWith('.') ? res : '.' + path.sep + res;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (js_utils_1.isEmptyObject(implicitMapping))
|
|
154
|
+
return;
|
|
155
|
+
const discriminatorPropSchema = obj.properties[obj.discriminator.propertyName];
|
|
156
|
+
const discriminatorEnum = discriminatorPropSchema && discriminatorPropSchema.enum;
|
|
157
|
+
const mapping = (obj.discriminator.mapping = obj.discriminator.mapping || {});
|
|
158
|
+
for (const name of Object.keys(implicitMapping)) {
|
|
159
|
+
if (discriminatorEnum && !discriminatorEnum.includes(name)) {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (mapping[name] && mapping[name] !== implicitMapping[name]) {
|
|
163
|
+
process.stderr.write(colorette_1.yellow(`warning: explicit mapping overlaps with local mapping entry ${colorette_1.red(name)} at ${colorette_1.blue(filename)}. Please check it.`));
|
|
164
|
+
}
|
|
165
|
+
mapping[name] = implicitMapping[name];
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function isNotSecurityComponentType(componentType) {
|
|
169
|
+
return componentType !== types_1.OPENAPI3_COMPONENT.SecuritySchemes;
|
|
170
|
+
}
|
|
171
|
+
function findComponentTypes(components) {
|
|
172
|
+
return types_1.OPENAPI3_COMPONENT_NAMES
|
|
173
|
+
.filter(item => isNotSecurityComponentType(item) && Object.keys(components).includes(item));
|
|
174
|
+
}
|
|
175
|
+
function doesFileDiffer(filename, componentData) {
|
|
176
|
+
return fs.existsSync(filename) && !isEqual(utils_1.readYaml(filename), componentData);
|
|
177
|
+
}
|
|
178
|
+
function removeEmptyComponents(openapi, componentType) {
|
|
179
|
+
if (openapi.components && js_utils_1.isEmptyObject(openapi.components[componentType])) {
|
|
180
|
+
delete openapi.components[componentType];
|
|
181
|
+
}
|
|
182
|
+
if (js_utils_1.isEmptyObject(openapi.components)) {
|
|
183
|
+
delete openapi.components;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function createComponentDir(componentDirPath, componentType) {
|
|
187
|
+
if (isNotSecurityComponentType(componentType)) {
|
|
188
|
+
fs.mkdirSync(componentDirPath, { recursive: true });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function extractFileNameFromPath(filename) {
|
|
192
|
+
return path.basename(filename, path.extname(filename));
|
|
193
|
+
}
|
|
194
|
+
function getFileNamePath(componentDirPath, componentName) {
|
|
195
|
+
return path.join(componentDirPath, componentName) + '.yaml';
|
|
196
|
+
}
|
|
197
|
+
function gatherComponentsFiles(components, componentsFiles, componentType, componentName, filename) {
|
|
198
|
+
var _a, _b;
|
|
199
|
+
let inherits = [];
|
|
200
|
+
if (componentType === types_1.OPENAPI3_COMPONENT.Schemas) {
|
|
201
|
+
inherits = (((_b = (_a = components === null || components === void 0 ? void 0 : components[componentType]) === null || _a === void 0 ? void 0 : _a[componentName]) === null || _b === void 0 ? void 0 : _b.allOf) || []).map((s) => s.$ref).filter(Boolean);
|
|
202
|
+
}
|
|
203
|
+
componentsFiles[componentType] = componentsFiles[componentType] || {};
|
|
204
|
+
componentsFiles[componentType][componentName] = { inherits, filename };
|
|
205
|
+
}
|
|
206
|
+
function iteratePathItems(pathItems, openapiDir, outDir, componentsFiles, pathSeparator, codeSamplesPathPrefix = '') {
|
|
207
|
+
if (!pathItems)
|
|
208
|
+
return;
|
|
209
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
210
|
+
for (const pathName of Object.keys(pathItems)) {
|
|
211
|
+
const pathFile = `${path.join(outDir, utils_1.pathToFilename(pathName, pathSeparator))}.yaml`;
|
|
212
|
+
const pathData = pathItems[pathName];
|
|
213
|
+
if (openapi_core_1.isRef(pathData))
|
|
214
|
+
continue;
|
|
215
|
+
for (const method of types_1.OPENAPI3_METHOD_NAMES) {
|
|
216
|
+
const methodData = pathData[method];
|
|
217
|
+
const methodDataXCode = (methodData === null || methodData === void 0 ? void 0 : methodData['x-code-samples']) || (methodData === null || methodData === void 0 ? void 0 : methodData['x-codeSamples']);
|
|
218
|
+
if (!methodDataXCode || !Array.isArray(methodDataXCode)) {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
for (const sample of methodDataXCode) {
|
|
222
|
+
if (sample.source && sample.source.$ref)
|
|
223
|
+
continue;
|
|
224
|
+
const sampleFileName = path.join(openapiDir, 'code_samples', sample.lang, codeSamplesPathPrefix + utils_1.pathToFilename(pathName, pathSeparator), method + langToExt(sample.lang));
|
|
225
|
+
fs.mkdirSync(path.dirname(sampleFileName), { recursive: true });
|
|
226
|
+
fs.writeFileSync(sampleFileName, sample.source);
|
|
227
|
+
// @ts-ignore
|
|
228
|
+
sample.source = {
|
|
229
|
+
$ref: openapi_core_1.slash(path.relative(outDir, sampleFileName))
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
utils_1.writeYaml(pathData, pathFile);
|
|
234
|
+
pathItems[pathName] = {
|
|
235
|
+
$ref: openapi_core_1.slash(path.relative(openapiDir, pathFile))
|
|
236
|
+
};
|
|
237
|
+
traverseDirectoryDeep(outDir, traverseDirectoryDeepCallback, componentsFiles);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
exports.iteratePathItems = iteratePathItems;
|
|
241
|
+
function iterateComponents(openapi, openapiDir, componentsFiles) {
|
|
242
|
+
const { components } = openapi;
|
|
243
|
+
if (components) {
|
|
244
|
+
const componentsDir = path.join(openapiDir, types_1.COMPONENTS);
|
|
245
|
+
fs.mkdirSync(componentsDir, { recursive: true });
|
|
246
|
+
const componentTypes = findComponentTypes(components);
|
|
247
|
+
componentTypes.forEach(iterateAndGatherComponentsFiles);
|
|
248
|
+
componentTypes.forEach(iterateComponentTypes);
|
|
249
|
+
function iterateAndGatherComponentsFiles(componentType) {
|
|
250
|
+
const componentDirPath = path.join(componentsDir, componentType);
|
|
251
|
+
for (const componentName of Object.keys((components === null || components === void 0 ? void 0 : components[componentType]) || {})) {
|
|
252
|
+
const filename = getFileNamePath(componentDirPath, componentName);
|
|
253
|
+
gatherComponentsFiles(components, componentsFiles, componentType, componentName, filename);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function iterateComponentTypes(componentType) {
|
|
257
|
+
var _a, _b, _c;
|
|
258
|
+
const componentDirPath = path.join(componentsDir, componentType);
|
|
259
|
+
createComponentDir(componentDirPath, componentType);
|
|
260
|
+
for (const componentName of Object.keys((components === null || components === void 0 ? void 0 : components[componentType]) || {})) {
|
|
261
|
+
const filename = getFileNamePath(componentDirPath, componentName);
|
|
262
|
+
const componentData = (_a = components === null || components === void 0 ? void 0 : components[componentType]) === null || _a === void 0 ? void 0 : _a[componentName];
|
|
263
|
+
replace$Refs(componentData, path.dirname(filename), componentsFiles);
|
|
264
|
+
implicitlyReferenceDiscriminator(componentData, extractFileNameFromPath(filename), filename, componentsFiles.schemas || {});
|
|
265
|
+
if (doesFileDiffer(filename, componentData)) {
|
|
266
|
+
process.stderr.write(colorette_1.yellow(`warning: conflict for ${componentName} - file already exists with different content: ${colorette_1.blue(filename)} ... Skip.\n`));
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
utils_1.writeYaml(componentData, filename);
|
|
270
|
+
}
|
|
271
|
+
if (isNotSecurityComponentType(componentType)) {
|
|
272
|
+
// security schemas must referenced from components
|
|
273
|
+
(_c = (_b = openapi.components) === null || _b === void 0 ? void 0 : _b[componentType]) === null || _c === void 0 ? true : delete _c[componentName];
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
removeEmptyComponents(openapi, componentType);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Oas3Schema, Oas3_1Schema, Oas3Definition, Oas3_1Definition, Oas3Components, Oas3PathItem, Oas3Paths, Oas3ComponentName, Oas3_1Webhooks, Oas2Definition, Referenced } from "@redocly/openapi-core";
|
|
2
|
+
export { Oas3_1Definition, Oas3Definition, Oas2Definition, Oas3Components, Oas3Paths, Oas3PathItem, Oas3ComponentName, Oas3_1Schema, Oas3Schema, Oas3_1Webhooks, Referenced };
|
|
3
|
+
export declare type Definition = Oas3_1Definition | Oas3Definition | Oas2Definition;
|
|
4
|
+
export interface ComponentsFiles {
|
|
5
|
+
[schemas: string]: any;
|
|
6
|
+
}
|
|
7
|
+
export interface refObj {
|
|
8
|
+
[$ref: string]: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const COMPONENTS = "components";
|
|
11
|
+
export declare const PATHS = "paths";
|
|
12
|
+
export declare const WEBHOOKS = "webhooks";
|
|
13
|
+
export declare const xWEBHOOKS = "x-webhooks";
|
|
14
|
+
export declare const componentsPath: string;
|
|
15
|
+
declare enum OPENAPI3_METHOD {
|
|
16
|
+
Get = "get",
|
|
17
|
+
Put = "put",
|
|
18
|
+
Post = "post",
|
|
19
|
+
Delete = "delete",
|
|
20
|
+
Options = "options",
|
|
21
|
+
Head = "head",
|
|
22
|
+
Patch = "patch",
|
|
23
|
+
Trace = "trace"
|
|
24
|
+
}
|
|
25
|
+
export declare const OPENAPI3_METHOD_NAMES: OPENAPI3_METHOD[];
|
|
26
|
+
export declare enum OPENAPI3_COMPONENT {
|
|
27
|
+
Schemas = "schemas",
|
|
28
|
+
Responses = "responses",
|
|
29
|
+
Parameters = "parameters",
|
|
30
|
+
Examples = "examples",
|
|
31
|
+
Headers = "headers",
|
|
32
|
+
RequestBodies = "requestBodies",
|
|
33
|
+
Links = "links",
|
|
34
|
+
Callbacks = "callbacks",
|
|
35
|
+
SecuritySchemes = "securitySchemes"
|
|
36
|
+
}
|
|
37
|
+
export declare const OPENAPI3_COMPONENT_NAMES: OPENAPI3_COMPONENT[];
|