@redocly/cli 1.18.1 → 1.20.0
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 +24 -0
- package/lib/__mocks__/@redocly/openapi-core.d.ts +2 -2
- package/lib/__mocks__/@redocly/openapi-core.js +1 -0
- package/lib/__mocks__/fs.d.ts +0 -1
- package/lib/__mocks__/perf_hooks.d.ts +0 -1
- package/lib/__mocks__/redoc.d.ts +0 -1
- package/lib/__tests__/commands/build-docs.test.js +21 -23
- package/lib/__tests__/commands/bundle.test.js +21 -30
- package/lib/__tests__/commands/join.test.js +101 -70
- package/lib/__tests__/commands/lint.test.js +54 -54
- package/lib/__tests__/commands/push-region.test.js +24 -25
- package/lib/__tests__/commands/push.test.js +269 -170
- package/lib/__tests__/fetch-with-timeout.test.js +3 -12
- package/lib/__tests__/fixtures/config.d.ts +0 -1
- package/lib/__tests__/utils.test.js +32 -37
- package/lib/__tests__/wrapper.test.js +31 -20
- package/lib/cms/api/__tests__/api.client.test.js +29 -38
- package/lib/cms/api/api-client.d.ts +0 -2
- package/lib/cms/api/api-client.js +107 -128
- package/lib/cms/api/api-keys.js +1 -2
- package/lib/cms/api/domains.js +1 -2
- package/lib/cms/commands/__tests__/push-status.test.js +251 -162
- package/lib/cms/commands/__tests__/push.test.js +120 -102
- package/lib/cms/commands/__tests__/utils.test.js +12 -21
- package/lib/cms/commands/push-status.d.ts +3 -2
- package/lib/cms/commands/push-status.js +94 -106
- package/lib/cms/commands/push.d.ts +3 -2
- package/lib/cms/commands/push.js +66 -74
- package/lib/cms/commands/utils.js +20 -34
- package/lib/commands/build-docs/index.d.ts +2 -2
- package/lib/commands/build-docs/index.js +8 -17
- package/lib/commands/build-docs/utils.d.ts +1 -1
- package/lib/commands/build-docs/utils.js +27 -39
- package/lib/commands/bundle.d.ts +2 -2
- package/lib/commands/bundle.js +70 -94
- package/lib/commands/join.d.ts +2 -2
- package/lib/commands/join.js +375 -388
- package/lib/commands/lint.d.ts +2 -2
- package/lib/commands/lint.js +64 -75
- package/lib/commands/login.d.ts +3 -2
- package/lib/commands/login.js +10 -22
- package/lib/commands/preview-docs/index.d.ts +2 -2
- package/lib/commands/preview-docs/index.js +93 -106
- package/lib/commands/preview-docs/preview-server/preview-server.js +64 -76
- package/lib/commands/preview-docs/preview-server/server.d.ts +1 -4
- package/lib/commands/preview-docs/preview-server/server.js +6 -6
- package/lib/commands/preview-project/constants.d.ts +1 -1
- package/lib/commands/preview-project/index.d.ts +2 -1
- package/lib/commands/preview-project/index.js +5 -14
- package/lib/commands/preview-project/types.d.ts +1 -1
- package/lib/commands/push.d.ts +9 -12
- package/lib/commands/push.js +180 -196
- package/lib/commands/split/__tests__/index.test.js +31 -25
- package/lib/commands/split/index.d.ts +2 -1
- package/lib/commands/split/index.js +20 -33
- package/lib/commands/stats.d.ts +2 -2
- package/lib/commands/stats.js +36 -47
- package/lib/index.js +34 -49
- package/lib/types.d.ts +4 -5
- package/lib/utils/__mocks__/miscellaneous.d.ts +0 -1
- package/lib/utils/fetch-with-timeout.js +7 -12
- package/lib/utils/getCommandNameFromArgs.d.ts +1 -1
- package/lib/utils/getCommandNameFromArgs.js +2 -4
- package/lib/utils/js-utils.js +6 -7
- package/lib/utils/miscellaneous.d.ts +4 -1
- package/lib/utils/miscellaneous.js +130 -152
- package/lib/utils/update-version-notifier.js +4 -13
- package/lib/wrapper.d.ts +9 -2
- package/lib/wrapper.js +27 -16
- package/package.json +3 -3
- package/src/__mocks__/@redocly/openapi-core.ts +1 -0
- package/src/__tests__/commands/build-docs.test.ts +5 -4
- package/src/__tests__/commands/join.test.ts +51 -51
- package/src/__tests__/commands/push-region.test.ts +10 -8
- package/src/__tests__/commands/push.test.ts +127 -102
- package/src/__tests__/utils.test.ts +1 -0
- package/src/__tests__/wrapper.test.ts +24 -2
- package/src/cms/api/api-client.ts +2 -1
- package/src/cms/commands/__tests__/push-status.test.ts +70 -56
- package/src/cms/commands/__tests__/push.test.ts +30 -24
- package/src/cms/commands/push-status.ts +8 -7
- package/src/cms/commands/push.ts +12 -9
- package/src/commands/build-docs/index.ts +10 -5
- package/src/commands/build-docs/utils.ts +4 -4
- package/src/commands/bundle.ts +14 -6
- package/src/commands/join.ts +6 -2
- package/src/commands/lint.ts +9 -3
- package/src/commands/login.ts +5 -2
- package/src/commands/preview-docs/index.ts +7 -1
- package/src/commands/preview-docs/preview-server/preview-server.ts +4 -3
- package/src/commands/preview-docs/preview-server/server.ts +2 -1
- package/src/commands/preview-project/constants.ts +1 -1
- package/src/commands/preview-project/index.ts +5 -4
- package/src/commands/preview-project/types.ts +1 -1
- package/src/commands/push.ts +15 -18
- package/src/commands/split/__tests__/index.test.ts +17 -6
- package/src/commands/split/index.ts +4 -2
- package/src/commands/stats.ts +13 -6
- package/src/index.ts +13 -7
- package/src/types.ts +2 -3
- package/src/utils/getCommandNameFromArgs.ts +1 -1
- package/src/utils/miscellaneous.ts +11 -1
- package/src/wrapper.ts +37 -11
- package/tsconfig.tsbuildinfo +1 -1
package/lib/commands/push.js
CHANGED
|
@@ -1,26 +1,10 @@
|
|
|
1
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
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
-
exports.
|
|
3
|
+
exports.transformPush = exports.DESTINATION_REGEX = void 0;
|
|
4
|
+
exports.commonPushHandler = commonPushHandler;
|
|
5
|
+
exports.handlePush = handlePush;
|
|
6
|
+
exports.getDestinationProps = getDestinationProps;
|
|
7
|
+
exports.getApiRoot = getApiRoot;
|
|
24
8
|
const fs = require("fs");
|
|
25
9
|
const path = require("path");
|
|
26
10
|
const node_fetch_1 = require("node-fetch");
|
|
@@ -32,120 +16,118 @@ const miscellaneous_1 = require("../utils/miscellaneous");
|
|
|
32
16
|
const login_1 = require("./login");
|
|
33
17
|
const push_1 = require("../cms/commands/push");
|
|
34
18
|
const DEFAULT_VERSION = 'latest';
|
|
35
|
-
exports.DESTINATION_REGEX =
|
|
19
|
+
exports.DESTINATION_REGEX =
|
|
20
|
+
// eslint-disable-next-line no-useless-escape
|
|
21
|
+
/^(@(?<organizationId>[\w\-\s]+)\/)?(?<name>[^@]*)@(?<version>[\w\.\-]+)$/;
|
|
36
22
|
function commonPushHandler({ project, 'mount-path': mountPath, }) {
|
|
37
23
|
if (project && mountPath) {
|
|
38
24
|
return push_1.handlePush;
|
|
39
25
|
}
|
|
40
26
|
return (0, exports.transformPush)(handlePush);
|
|
41
27
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const clientToken = yield (0, login_1.promptClientToken)(client.domain);
|
|
50
|
-
yield client.login(clientToken);
|
|
51
|
-
}
|
|
52
|
-
catch (e) {
|
|
53
|
-
(0, miscellaneous_1.exitWithError)(e);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
const startedAt = perf_hooks_1.performance.now();
|
|
57
|
-
const { destination, branchName, upsert } = argv;
|
|
58
|
-
const jobId = argv['job-id'];
|
|
59
|
-
const batchSize = argv['batch-size'];
|
|
60
|
-
if (destination && !exports.DESTINATION_REGEX.test(destination)) {
|
|
61
|
-
(0, miscellaneous_1.exitWithError)(`Destination argument value is not valid, please use the right format: ${(0, colorette_1.yellow)('<api-name@api-version>')}.`);
|
|
62
|
-
}
|
|
63
|
-
const destinationProps = getDestinationProps(destination, config.organization);
|
|
64
|
-
const organizationId = argv.organization || destinationProps.organizationId;
|
|
65
|
-
const { name, version } = destinationProps;
|
|
66
|
-
if (!organizationId) {
|
|
67
|
-
return (0, miscellaneous_1.exitWithError)(`No organization provided, please use --organization option or specify the 'organization' field in the config file.`);
|
|
68
|
-
}
|
|
69
|
-
const api = argv.api || (name && version && getApiRoot({ name, version, config }));
|
|
70
|
-
if (name && version && !api) {
|
|
71
|
-
(0, miscellaneous_1.exitWithError)(`No api found that matches ${(0, colorette_1.blue)(`${name}@${version}`)}. Please make sure you have provided the correct data in the config file.`);
|
|
72
|
-
}
|
|
73
|
-
// Ensure that a destination for the api is provided.
|
|
74
|
-
if (!name && api) {
|
|
75
|
-
return (0, miscellaneous_1.exitWithError)(`No destination provided, please use --destination option to provide destination.`);
|
|
76
|
-
}
|
|
77
|
-
if (jobId && !jobId.trim()) {
|
|
78
|
-
(0, miscellaneous_1.exitWithError)(`The ${(0, colorette_1.blue)(`job-id`)} option value is not valid, please avoid using an empty string.`);
|
|
28
|
+
async function handlePush({ argv, config }) {
|
|
29
|
+
const client = new openapi_core_1.RedoclyClient(config.region);
|
|
30
|
+
const isAuthorized = await client.isAuthorizedWithRedoclyByRegion();
|
|
31
|
+
if (!isAuthorized) {
|
|
32
|
+
try {
|
|
33
|
+
const clientToken = await (0, login_1.promptClientToken)(client.domain);
|
|
34
|
+
await client.login(clientToken);
|
|
79
35
|
}
|
|
80
|
-
|
|
81
|
-
(0, miscellaneous_1.exitWithError)(
|
|
36
|
+
catch (e) {
|
|
37
|
+
(0, miscellaneous_1.exitWithError)(e);
|
|
82
38
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
39
|
+
}
|
|
40
|
+
const startedAt = perf_hooks_1.performance.now();
|
|
41
|
+
const { destination, branchName, upsert } = argv;
|
|
42
|
+
const jobId = argv['job-id'];
|
|
43
|
+
const batchSize = argv['batch-size'];
|
|
44
|
+
if (destination && !exports.DESTINATION_REGEX.test(destination)) {
|
|
45
|
+
(0, miscellaneous_1.exitWithError)(`Destination argument value is not valid, please use the right format: ${(0, colorette_1.yellow)('<api-name@api-version>')}.`);
|
|
46
|
+
}
|
|
47
|
+
const destinationProps = getDestinationProps(destination, config.organization);
|
|
48
|
+
const organizationId = argv.organization || destinationProps.organizationId;
|
|
49
|
+
const { name, version } = destinationProps;
|
|
50
|
+
if (!organizationId) {
|
|
51
|
+
return (0, miscellaneous_1.exitWithError)(`No organization provided, please use --organization option or specify the 'organization' field in the config file.`);
|
|
52
|
+
}
|
|
53
|
+
const api = argv.api || (name && version && getApiRoot({ name, version, config }));
|
|
54
|
+
if (name && version && !api) {
|
|
55
|
+
(0, miscellaneous_1.exitWithError)(`No api found that matches ${(0, colorette_1.blue)(`${name}@${version}`)}. Please make sure you have provided the correct data in the config file.`);
|
|
56
|
+
}
|
|
57
|
+
// Ensure that a destination for the api is provided.
|
|
58
|
+
if (!name && api) {
|
|
59
|
+
return (0, miscellaneous_1.exitWithError)(`No destination provided, please use --destination option to provide destination.`);
|
|
60
|
+
}
|
|
61
|
+
if (jobId && !jobId.trim()) {
|
|
62
|
+
(0, miscellaneous_1.exitWithError)(`The ${(0, colorette_1.blue)(`job-id`)} option value is not valid, please avoid using an empty string.`);
|
|
63
|
+
}
|
|
64
|
+
if (batchSize && batchSize < 2) {
|
|
65
|
+
(0, miscellaneous_1.exitWithError)(`The ${(0, colorette_1.blue)(`batch-size`)} option value is not valid, please use the integer bigger than 1.`);
|
|
66
|
+
}
|
|
67
|
+
const apis = api ? { [`${name}@${version}`]: { root: api } } : config.apis;
|
|
68
|
+
if (!Object.keys(apis).length) {
|
|
69
|
+
(0, miscellaneous_1.exitWithError)(`Api not found. Please make sure you have provided the correct data in the config file.`);
|
|
70
|
+
}
|
|
71
|
+
for (const [apiNameAndVersion, { root: api }] of Object.entries(apis)) {
|
|
72
|
+
const resolvedConfig = (0, openapi_core_1.getMergedConfig)(config, apiNameAndVersion);
|
|
73
|
+
resolvedConfig.styleguide.skipDecorators(argv['skip-decorator']);
|
|
74
|
+
const [name, version = DEFAULT_VERSION] = apiNameAndVersion.split('@');
|
|
75
|
+
const encodedName = encodeURIComponent(name);
|
|
76
|
+
try {
|
|
77
|
+
let rootFilePath = '';
|
|
78
|
+
const filePaths = [];
|
|
79
|
+
const filesToUpload = await collectFilesToUpload(api, resolvedConfig);
|
|
80
|
+
const filesHash = hashFiles(filesToUpload.files);
|
|
81
|
+
process.stdout.write(`Uploading ${filesToUpload.files.length} ${(0, miscellaneous_1.pluralize)('file', filesToUpload.files.length)}:\n`);
|
|
82
|
+
let uploaded = 0;
|
|
83
|
+
for (const file of filesToUpload.files) {
|
|
84
|
+
const { signedUploadUrl, filePath } = await client.registryApi.prepareFileUpload({
|
|
122
85
|
organizationId,
|
|
123
86
|
name: encodedName,
|
|
124
87
|
version,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
branch: branchName,
|
|
88
|
+
filesHash,
|
|
89
|
+
filename: file.keyOnS3,
|
|
128
90
|
isUpsert: upsert,
|
|
129
|
-
isPublic: argv['public'],
|
|
130
|
-
batchId: jobId,
|
|
131
|
-
batchSize: batchSize,
|
|
132
91
|
});
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (error.message === 'ORGANIZATION_NOT_FOUND') {
|
|
136
|
-
(0, miscellaneous_1.exitWithError)(`Organization ${(0, colorette_1.blue)(organizationId)} not found.`);
|
|
92
|
+
if (file.filePath === filesToUpload.root) {
|
|
93
|
+
rootFilePath = filePath;
|
|
137
94
|
}
|
|
138
|
-
|
|
139
|
-
|
|
95
|
+
filePaths.push(filePath);
|
|
96
|
+
process.stdout.write(`Uploading ${file.contents ? 'bundle for ' : ''}${(0, colorette_1.blue)(file.filePath)}...`);
|
|
97
|
+
const uploadResponse = await uploadFileToS3(signedUploadUrl, file.contents || file.filePath);
|
|
98
|
+
const fileCounter = `(${++uploaded}/${filesToUpload.files.length})`;
|
|
99
|
+
if (!uploadResponse.ok) {
|
|
100
|
+
(0, miscellaneous_1.exitWithError)(`✗ ${fileCounter}\nFile upload failed.`);
|
|
140
101
|
}
|
|
141
|
-
|
|
102
|
+
process.stdout.write((0, colorette_1.green)(`✓ ${fileCounter}\n`));
|
|
142
103
|
}
|
|
143
|
-
process.stdout.write(
|
|
104
|
+
process.stdout.write('\n');
|
|
105
|
+
await client.registryApi.pushApi({
|
|
106
|
+
organizationId,
|
|
107
|
+
name: encodedName,
|
|
108
|
+
version,
|
|
109
|
+
rootFilePath,
|
|
110
|
+
filePaths,
|
|
111
|
+
branch: branchName,
|
|
112
|
+
isUpsert: upsert,
|
|
113
|
+
isPublic: argv['public'],
|
|
114
|
+
batchId: jobId,
|
|
115
|
+
batchSize: batchSize,
|
|
116
|
+
});
|
|
144
117
|
}
|
|
145
|
-
(
|
|
146
|
-
|
|
118
|
+
catch (error) {
|
|
119
|
+
if (error.message === 'ORGANIZATION_NOT_FOUND') {
|
|
120
|
+
(0, miscellaneous_1.exitWithError)(`Organization ${(0, colorette_1.blue)(organizationId)} not found.`);
|
|
121
|
+
}
|
|
122
|
+
if (error.message === 'API_VERSION_NOT_FOUND') {
|
|
123
|
+
(0, miscellaneous_1.exitWithError)(`The definition version ${(0, colorette_1.blue)(`${name}@${version}`)} does not exist in organization ${(0, colorette_1.blue)(organizationId)}!\n${(0, colorette_1.yellow)('Suggestion:')} please use ${(0, colorette_1.blue)('-u')} or ${(0, colorette_1.blue)('--upsert')} to create definition.`);
|
|
124
|
+
}
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
process.stdout.write(`Definition: ${(0, colorette_1.blue)(api)} is successfully pushed to Redocly API Registry.\n`);
|
|
128
|
+
}
|
|
129
|
+
(0, miscellaneous_1.printExecutionTime)('push', startedAt, api || `apis in organization ${organizationId}`);
|
|
147
130
|
}
|
|
148
|
-
exports.handlePush = handlePush;
|
|
149
131
|
function getFilesList(dir, files) {
|
|
150
132
|
files = files || [];
|
|
151
133
|
const filesAndDirs = fs.readdirSync(dir);
|
|
@@ -160,82 +142,79 @@ function getFilesList(dir, files) {
|
|
|
160
142
|
}
|
|
161
143
|
return files;
|
|
162
144
|
}
|
|
163
|
-
function collectFilesToUpload(api, config) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
files.push(getFileEntry(
|
|
183
|
-
|
|
184
|
-
|
|
145
|
+
async function collectFilesToUpload(api, config) {
|
|
146
|
+
const files = [];
|
|
147
|
+
const [{ path: apiPath }] = await (0, miscellaneous_1.getFallbackApisOrExit)([api], config);
|
|
148
|
+
process.stdout.write('Bundling definition\n');
|
|
149
|
+
const { bundle: openapiBundle, problems } = await (0, openapi_core_1.bundle)({
|
|
150
|
+
config,
|
|
151
|
+
ref: apiPath,
|
|
152
|
+
skipRedoclyRegistryRefs: true,
|
|
153
|
+
});
|
|
154
|
+
const fileTotals = (0, openapi_core_1.getTotals)(problems);
|
|
155
|
+
if (fileTotals.errors === 0) {
|
|
156
|
+
process.stdout.write(`Created a bundle for ${(0, colorette_1.blue)(api)} ${fileTotals.warnings > 0 ? 'with warnings' : ''}\n`);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
(0, miscellaneous_1.exitWithError)(`Failed to create a bundle for ${(0, colorette_1.blue)(api)}.`);
|
|
160
|
+
}
|
|
161
|
+
const fileExt = path.extname(apiPath).split('.').pop();
|
|
162
|
+
files.push(getFileEntry(apiPath, (0, miscellaneous_1.dumpBundle)(openapiBundle.parsed, fileExt)));
|
|
163
|
+
if (fs.existsSync('package.json')) {
|
|
164
|
+
files.push(getFileEntry('package.json'));
|
|
165
|
+
}
|
|
166
|
+
if (fs.existsSync(openapi_core_1.IGNORE_FILE)) {
|
|
167
|
+
files.push(getFileEntry(openapi_core_1.IGNORE_FILE));
|
|
168
|
+
}
|
|
169
|
+
if (config.configFile) {
|
|
170
|
+
// All config file paths including the root one
|
|
171
|
+
files.push(...[...new Set(config.styleguide.extendPaths)].map((f) => getFileEntry(f)));
|
|
172
|
+
if (config.theme?.openapi?.htmlTemplate) {
|
|
173
|
+
const dir = getFolder(config.theme.openapi.htmlTemplate);
|
|
174
|
+
const fileList = getFilesList(dir, []);
|
|
175
|
+
files.push(...fileList.map((f) => getFileEntry(f)));
|
|
185
176
|
}
|
|
186
|
-
|
|
187
|
-
|
|
177
|
+
const pluginFiles = new Set();
|
|
178
|
+
for (const plugin of config.styleguide.pluginPaths) {
|
|
179
|
+
if (typeof plugin !== 'string')
|
|
180
|
+
continue;
|
|
181
|
+
const fileList = getFilesList(getFolder(plugin), []);
|
|
182
|
+
fileList.forEach((f) => pluginFiles.add(f));
|
|
188
183
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const pluginFiles = new Set();
|
|
198
|
-
for (const plugin of config.styleguide.pluginPaths) {
|
|
199
|
-
if (typeof plugin !== 'string')
|
|
200
|
-
continue;
|
|
201
|
-
const fileList = getFilesList(getFolder(plugin), []);
|
|
202
|
-
fileList.forEach((f) => pluginFiles.add(f));
|
|
184
|
+
files.push(...filterPluginFilesByExt(Array.from(pluginFiles)).map((f) => getFileEntry(f)));
|
|
185
|
+
}
|
|
186
|
+
if (config.files) {
|
|
187
|
+
const otherFiles = new Set();
|
|
188
|
+
for (const file of config.files) {
|
|
189
|
+
if (fs.statSync(file).isDirectory()) {
|
|
190
|
+
const fileList = getFilesList(file, []);
|
|
191
|
+
fileList.forEach((f) => otherFiles.add(f));
|
|
203
192
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if (config.files) {
|
|
207
|
-
const otherFiles = new Set();
|
|
208
|
-
for (const file of config.files) {
|
|
209
|
-
if (fs.statSync(file).isDirectory()) {
|
|
210
|
-
const fileList = getFilesList(file, []);
|
|
211
|
-
fileList.forEach((f) => otherFiles.add(f));
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
otherFiles.add(file);
|
|
215
|
-
}
|
|
193
|
+
else {
|
|
194
|
+
otherFiles.add(file);
|
|
216
195
|
}
|
|
217
|
-
files.push(...Array.from(otherFiles).map((f) => getFileEntry(f)));
|
|
218
196
|
}
|
|
197
|
+
files.push(...Array.from(otherFiles).map((f) => getFileEntry(f)));
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
files,
|
|
201
|
+
root: path.resolve(apiPath),
|
|
202
|
+
};
|
|
203
|
+
function filterPluginFilesByExt(files) {
|
|
204
|
+
return files.filter((file) => {
|
|
205
|
+
const fileExt = path.extname(file).toLowerCase();
|
|
206
|
+
return fileExt === '.js' || fileExt === '.ts' || fileExt === '.mjs' || fileExt === 'json';
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
function getFileEntry(filename, contents) {
|
|
219
210
|
return {
|
|
220
|
-
|
|
221
|
-
|
|
211
|
+
filePath: path.resolve(filename),
|
|
212
|
+
keyOnS3: config.configFile
|
|
213
|
+
? (0, openapi_core_1.slash)(path.relative(path.dirname(config.configFile), filename))
|
|
214
|
+
: (0, openapi_core_1.slash)(path.basename(filename)),
|
|
215
|
+
contents: (contents && Buffer.from(contents, 'utf-8')) || undefined,
|
|
222
216
|
};
|
|
223
|
-
|
|
224
|
-
return files.filter((file) => {
|
|
225
|
-
const fileExt = path.extname(file).toLowerCase();
|
|
226
|
-
return fileExt === '.js' || fileExt === '.ts' || fileExt === '.mjs' || fileExt === 'json';
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
function getFileEntry(filename, contents) {
|
|
230
|
-
return {
|
|
231
|
-
filePath: path.resolve(filename),
|
|
232
|
-
keyOnS3: config.configFile
|
|
233
|
-
? (0, openapi_core_1.slash)(path.relative(path.dirname(config.configFile), filename))
|
|
234
|
-
: (0, openapi_core_1.slash)(path.basename(filename)),
|
|
235
|
-
contents: (contents && Buffer.from(contents, 'utf-8')) || undefined,
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
});
|
|
217
|
+
}
|
|
239
218
|
}
|
|
240
219
|
function getFolder(filePath) {
|
|
241
220
|
return path.resolve(path.dirname(filePath));
|
|
@@ -246,8 +225,7 @@ function hashFiles(filePaths) {
|
|
|
246
225
|
return sum.digest('hex');
|
|
247
226
|
}
|
|
248
227
|
function parseDestination(destination) {
|
|
249
|
-
|
|
250
|
-
return (_a = destination === null || destination === void 0 ? void 0 : destination.match(exports.DESTINATION_REGEX)) === null || _a === void 0 ? void 0 : _a.groups;
|
|
228
|
+
return destination?.match(exports.DESTINATION_REGEX)?.groups;
|
|
251
229
|
}
|
|
252
230
|
function getDestinationProps(destination, organization) {
|
|
253
231
|
const groups = destination && parseDestination(destination);
|
|
@@ -262,10 +240,7 @@ function getDestinationProps(destination, organization) {
|
|
|
262
240
|
return { organizationId: organization, name: undefined, version: undefined };
|
|
263
241
|
}
|
|
264
242
|
}
|
|
265
|
-
|
|
266
|
-
const transformPush = (callback) => (_a, config) => {
|
|
267
|
-
var _b;
|
|
268
|
-
var { apis, branch, 'batch-id': batchId, 'job-id': jobId } = _a, rest = __rest(_a, ["apis", "branch", 'batch-id', 'job-id']);
|
|
243
|
+
const transformPush = (callback) => ({ argv: { apis, branch, 'batch-id': batchId, 'job-id': jobId, ...rest }, config, version, }) => {
|
|
269
244
|
const [maybeApiOrDestination, maybeDestination, maybeBranchName] = apis || [];
|
|
270
245
|
if (batchId) {
|
|
271
246
|
process.stderr.write((0, colorette_1.yellow)(`The ${(0, colorette_1.red)('batch-id')} option is deprecated. Please use ${(0, colorette_1.green)('job-id')} instead.\n\n`));
|
|
@@ -286,14 +261,23 @@ const transformPush = (callback) => (_a, config) => {
|
|
|
286
261
|
else if (maybeApiOrDestination && !exports.DESTINATION_REGEX.test(maybeApiOrDestination)) {
|
|
287
262
|
apiFile = maybeApiOrDestination;
|
|
288
263
|
}
|
|
289
|
-
return callback(
|
|
264
|
+
return callback({
|
|
265
|
+
argv: {
|
|
266
|
+
...rest,
|
|
267
|
+
destination: rest.destination ?? destination,
|
|
268
|
+
api: apiFile,
|
|
269
|
+
branchName: branch ?? maybeBranchName,
|
|
270
|
+
'job-id': jobId || batchId,
|
|
271
|
+
},
|
|
272
|
+
config,
|
|
273
|
+
version,
|
|
274
|
+
});
|
|
290
275
|
};
|
|
291
276
|
exports.transformPush = transformPush;
|
|
292
277
|
function getApiRoot({ name, version, config: { apis }, }) {
|
|
293
|
-
const api =
|
|
294
|
-
return api
|
|
278
|
+
const api = apis?.[`${name}@${version}`] || (version === DEFAULT_VERSION && apis?.[name]);
|
|
279
|
+
return api?.root;
|
|
295
280
|
}
|
|
296
|
-
exports.getApiRoot = getApiRoot;
|
|
297
281
|
function uploadFileToS3(url, filePathOrBuffer) {
|
|
298
282
|
const fileSizeInBytes = typeof filePathOrBuffer === 'string'
|
|
299
283
|
? fs.statSync(filePathOrBuffer).size
|
|
@@ -1,48 +1,54 @@
|
|
|
1
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
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
const index_1 = require("../index");
|
|
13
4
|
const path = require("path");
|
|
14
5
|
const openapiCore = require("@redocly/openapi-core");
|
|
15
6
|
const colorette_1 = require("colorette");
|
|
7
|
+
const miscellaneous_1 = require("../../../utils/__mocks__/miscellaneous");
|
|
16
8
|
const utils = require('../../../utils/miscellaneous');
|
|
17
|
-
jest.mock('../../../utils/miscellaneous', () => (
|
|
18
|
-
jest.
|
|
9
|
+
jest.mock('../../../utils/miscellaneous', () => ({
|
|
10
|
+
...jest.requireActual('../../../utils/miscellaneous'),
|
|
11
|
+
writeToFileByExtension: jest.fn(),
|
|
12
|
+
}));
|
|
13
|
+
jest.mock('@redocly/openapi-core', () => ({
|
|
14
|
+
...jest.requireActual('@redocly/openapi-core'),
|
|
15
|
+
isRef: jest.fn(),
|
|
16
|
+
}));
|
|
19
17
|
describe('#split', () => {
|
|
20
18
|
const openapiDir = 'test';
|
|
21
19
|
const componentsFiles = {};
|
|
22
|
-
it('should split the file and show the success message', () =>
|
|
20
|
+
it('should split the file and show the success message', async () => {
|
|
23
21
|
const filePath = 'packages/cli/src/commands/split/__tests__/fixtures/spec.json';
|
|
24
22
|
jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
await (0, index_1.handleSplit)({
|
|
24
|
+
argv: {
|
|
25
|
+
api: filePath,
|
|
26
|
+
outDir: openapiDir,
|
|
27
|
+
separator: '_',
|
|
28
|
+
},
|
|
29
|
+
config: (0, miscellaneous_1.loadConfigAndHandleErrors)(),
|
|
30
|
+
version: 'cli-version',
|
|
29
31
|
});
|
|
30
32
|
expect(process.stderr.write).toBeCalledTimes(2);
|
|
31
33
|
expect(process.stderr.write.mock.calls[0][0]).toBe(`🪓 Document: ${(0, colorette_1.blue)(filePath)} ${(0, colorette_1.green)('is successfully split')}
|
|
32
34
|
and all related files are saved to the directory: ${(0, colorette_1.blue)(openapiDir)} \n`);
|
|
33
35
|
expect(process.stderr.write.mock.calls[1][0]).toContain(`${filePath}: split processed in <test>ms`);
|
|
34
|
-
})
|
|
35
|
-
it('should use the correct separator', () =>
|
|
36
|
+
});
|
|
37
|
+
it('should use the correct separator', async () => {
|
|
36
38
|
const filePath = 'packages/cli/src/commands/split/__tests__/fixtures/spec.json';
|
|
37
39
|
jest.spyOn(utils, 'pathToFilename').mockImplementation(() => 'newFilePath');
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
await (0, index_1.handleSplit)({
|
|
41
|
+
argv: {
|
|
42
|
+
api: filePath,
|
|
43
|
+
outDir: openapiDir,
|
|
44
|
+
separator: '_',
|
|
45
|
+
},
|
|
46
|
+
config: (0, miscellaneous_1.loadConfigAndHandleErrors)(),
|
|
47
|
+
version: 'cli-version',
|
|
42
48
|
});
|
|
43
49
|
expect(utils.pathToFilename).toBeCalledWith(expect.anything(), '_');
|
|
44
50
|
utils.pathToFilename.mockRestore();
|
|
45
|
-
})
|
|
51
|
+
});
|
|
46
52
|
it('should have correct path with paths', () => {
|
|
47
53
|
const openapi = require('./fixtures/spec.json');
|
|
48
54
|
jest.spyOn(openapiCore, 'slash').mockImplementation(() => 'paths/test.yaml');
|
|
@@ -67,7 +73,7 @@ describe('#split', () => {
|
|
|
67
73
|
expect(openapiCore.slash).toHaveBeenCalledWith('webhooks/test.yaml');
|
|
68
74
|
expect(path.relative).toHaveBeenCalledWith('test', 'test/webhooks/test.yaml');
|
|
69
75
|
});
|
|
70
|
-
it('should create correct folder name for code samples', () =>
|
|
76
|
+
it('should create correct folder name for code samples', async () => {
|
|
71
77
|
const openapi = require('./fixtures/samples.json');
|
|
72
78
|
const fs = require('fs');
|
|
73
79
|
jest.spyOn(fs, 'writeFileSync').mockImplementation(() => { });
|
|
@@ -81,5 +87,5 @@ describe('#split', () => {
|
|
|
81
87
|
expect(utils.escapeLanguageName).nthReturnedWith(3, 'VisualBasic');
|
|
82
88
|
expect(utils.escapeLanguageName).toBeCalledTimes(3);
|
|
83
89
|
utils.escapeLanguageName.mockRestore();
|
|
84
|
-
})
|
|
90
|
+
});
|
|
85
91
|
});
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { Oas3PathItem, Referenced } from './types';
|
|
2
|
+
import type { CommandArgs } from '../../wrapper';
|
|
2
3
|
export type SplitOptions = {
|
|
3
4
|
api: string;
|
|
4
5
|
outDir: string;
|
|
5
6
|
separator: string;
|
|
6
7
|
config?: string;
|
|
7
8
|
};
|
|
8
|
-
export declare function handleSplit(argv: SplitOptions): Promise<void>;
|
|
9
|
+
export declare function handleSplit({ argv, collectSpecData }: CommandArgs<SplitOptions>): Promise<void>;
|
|
9
10
|
export declare function startsWithComponents(node: string): boolean;
|
|
10
11
|
export declare function crawl(object: unknown, visitor: (node: Record<string, unknown>) => void): void;
|
|
11
12
|
declare function iteratePathItems(pathItems: Record<string, Referenced<Oas3PathItem>> | undefined, openapiDir: string, outDir: string, componentsFiles: object, pathSeparator: string, codeSamplesPathPrefix: string | undefined, ext: string): void;
|