@redocly/cli 0.0.0-snapshot.1737554067
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 +114 -0
- package/bin/cli.js +3 -0
- package/lib/__mocks__/@redocly/openapi-core.d.ts +99 -0
- package/lib/__mocks__/@redocly/openapi-core.js +84 -0
- package/lib/__mocks__/documents.d.ts +150 -0
- package/lib/__mocks__/documents.js +123 -0
- package/lib/__mocks__/fs.d.ts +8 -0
- package/lib/__mocks__/fs.js +9 -0
- package/lib/__mocks__/perf_hooks.d.ts +3 -0
- package/lib/__mocks__/perf_hooks.js +6 -0
- package/lib/__mocks__/redoc.d.ts +6 -0
- package/lib/__mocks__/redoc.js +5 -0
- package/lib/__tests__/commands/build-docs.test.d.ts +1 -0
- package/lib/__tests__/commands/build-docs.test.js +54 -0
- package/lib/__tests__/commands/bundle.test.d.ts +1 -0
- package/lib/__tests__/commands/bundle.test.js +235 -0
- package/lib/__tests__/commands/join.test.d.ts +1 -0
- package/lib/__tests__/commands/join.test.js +274 -0
- package/lib/__tests__/commands/lint.test.d.ts +1 -0
- package/lib/__tests__/commands/lint.test.js +149 -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 +463 -0
- package/lib/__tests__/fetch-with-timeout.test.d.ts +1 -0
- package/lib/__tests__/fetch-with-timeout.test.js +44 -0
- package/lib/__tests__/fixtures/config.d.ts +21 -0
- package/lib/__tests__/fixtures/config.js +24 -0
- package/lib/__tests__/spinner.test.d.ts +1 -0
- package/lib/__tests__/spinner.test.js +43 -0
- package/lib/__tests__/utils.test.d.ts +1 -0
- package/lib/__tests__/utils.test.js +593 -0
- package/lib/__tests__/wrapper.test.d.ts +1 -0
- package/lib/__tests__/wrapper.test.js +68 -0
- package/lib/cms/api/__tests__/api-keys.test.d.ts +1 -0
- package/lib/cms/api/__tests__/api-keys.test.js +26 -0
- package/lib/cms/api/__tests__/api.client.test.d.ts +1 -0
- package/lib/cms/api/__tests__/api.client.test.js +333 -0
- package/lib/cms/api/__tests__/domains.test.d.ts +1 -0
- package/lib/cms/api/__tests__/domains.test.js +13 -0
- package/lib/cms/api/api-client.d.ts +75 -0
- package/lib/cms/api/api-client.js +225 -0
- package/lib/cms/api/api-keys.d.ts +1 -0
- package/lib/cms/api/api-keys.js +23 -0
- package/lib/cms/api/domains.d.ts +1 -0
- package/lib/cms/api/domains.js +11 -0
- package/lib/cms/api/index.d.ts +3 -0
- package/lib/cms/api/index.js +19 -0
- package/lib/cms/api/types.d.ts +102 -0
- package/lib/cms/api/types.js +2 -0
- package/lib/cms/commands/__tests__/push-status.test.d.ts +1 -0
- package/lib/cms/commands/__tests__/push-status.test.js +563 -0
- package/lib/cms/commands/__tests__/push.test.d.ts +1 -0
- package/lib/cms/commands/__tests__/push.test.js +315 -0
- package/lib/cms/commands/__tests__/utils.test.d.ts +1 -0
- package/lib/cms/commands/__tests__/utils.test.js +51 -0
- package/lib/cms/commands/push-status.d.ts +23 -0
- package/lib/cms/commands/push-status.js +206 -0
- package/lib/cms/commands/push.d.ts +28 -0
- package/lib/cms/commands/push.js +142 -0
- package/lib/cms/commands/utils.d.ts +25 -0
- package/lib/cms/commands/utils.js +46 -0
- package/lib/cms/utils.d.ts +2 -0
- package/lib/cms/utils.js +6 -0
- package/lib/commands/build-docs/index.d.ts +3 -0
- package/lib/commands/build-docs/index.js +39 -0
- package/lib/commands/build-docs/template.hbs +23 -0
- package/lib/commands/build-docs/types.d.ts +23 -0
- package/lib/commands/build-docs/types.js +2 -0
- package/lib/commands/build-docs/utils.d.ts +7 -0
- package/lib/commands/build-docs/utils.js +87 -0
- package/lib/commands/bundle.d.ts +14 -0
- package/lib/commands/bundle.js +91 -0
- package/lib/commands/eject.d.ts +9 -0
- package/lib/commands/eject.js +28 -0
- package/lib/commands/join.d.ts +11 -0
- package/lib/commands/join.js +565 -0
- package/lib/commands/lint.d.ts +13 -0
- package/lib/commands/lint.js +108 -0
- package/lib/commands/login.d.ts +9 -0
- package/lib/commands/login.js +23 -0
- package/lib/commands/preview-docs/index.d.ts +12 -0
- package/lib/commands/preview-docs/index.js +127 -0
- package/lib/commands/preview-docs/preview-server/default.hbs +24 -0
- package/lib/commands/preview-docs/preview-server/hot.js +59 -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 +113 -0
- package/lib/commands/preview-docs/preview-server/server.d.ts +22 -0
- package/lib/commands/preview-docs/preview-server/server.js +85 -0
- package/lib/commands/preview-project/constants.d.ts +14 -0
- package/lib/commands/preview-project/constants.js +22 -0
- package/lib/commands/preview-project/index.d.ts +3 -0
- package/lib/commands/preview-project/index.js +56 -0
- package/lib/commands/preview-project/types.d.ts +10 -0
- package/lib/commands/preview-project/types.js +2 -0
- package/lib/commands/push.d.ts +44 -0
- package/lib/commands/push.js +295 -0
- package/lib/commands/split/__tests__/index.test.d.ts +1 -0
- package/lib/commands/split/__tests__/index.test.js +91 -0
- package/lib/commands/split/index.d.ts +13 -0
- package/lib/commands/split/index.js +259 -0
- package/lib/commands/split/types.d.ts +36 -0
- package/lib/commands/split/types.js +51 -0
- package/lib/commands/stats.d.ts +8 -0
- package/lib/commands/stats.js +96 -0
- package/lib/commands/translations.d.ts +7 -0
- package/lib/commands/translations.js +20 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +733 -0
- package/lib/types.d.ts +43 -0
- package/lib/types.js +5 -0
- package/lib/utils/__mocks__/miscellaneous.d.ts +43 -0
- package/lib/utils/__mocks__/miscellaneous.js +24 -0
- package/lib/utils/assert-node-version.d.ts +1 -0
- package/lib/utils/assert-node-version.js +16 -0
- package/lib/utils/fetch-with-timeout.d.ts +7 -0
- package/lib/utils/fetch-with-timeout.js +26 -0
- package/lib/utils/getCommandNameFromArgs.d.ts +2 -0
- package/lib/utils/getCommandNameFromArgs.js +6 -0
- package/lib/utils/js-utils.d.ts +5 -0
- package/lib/utils/js-utils.js +28 -0
- package/lib/utils/miscellaneous.d.ts +81 -0
- package/lib/utils/miscellaneous.js +551 -0
- package/lib/utils/platform.d.ts +16 -0
- package/lib/utils/platform.js +34 -0
- package/lib/utils/spinner.d.ts +10 -0
- package/lib/utils/spinner.js +42 -0
- package/lib/utils/update-version-notifier.d.ts +3 -0
- package/lib/utils/update-version-notifier.js +102 -0
- package/lib/wrapper.d.ts +11 -0
- package/lib/wrapper.js +65 -0
- package/package.json +69 -0
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HandledError = exports.CircularJSONNotSupportedError = void 0;
|
|
4
|
+
exports.getFallbackApisOrExit = getFallbackApisOrExit;
|
|
5
|
+
exports.getExecutionTime = getExecutionTime;
|
|
6
|
+
exports.printExecutionTime = printExecutionTime;
|
|
7
|
+
exports.pathToFilename = pathToFilename;
|
|
8
|
+
exports.escapeLanguageName = escapeLanguageName;
|
|
9
|
+
exports.langToExt = langToExt;
|
|
10
|
+
exports.dumpBundle = dumpBundle;
|
|
11
|
+
exports.saveBundle = saveBundle;
|
|
12
|
+
exports.promptUser = promptUser;
|
|
13
|
+
exports.readYaml = readYaml;
|
|
14
|
+
exports.writeToFileByExtension = writeToFileByExtension;
|
|
15
|
+
exports.writeYaml = writeYaml;
|
|
16
|
+
exports.writeJson = writeJson;
|
|
17
|
+
exports.getAndValidateFileExtension = getAndValidateFileExtension;
|
|
18
|
+
exports.handleError = handleError;
|
|
19
|
+
exports.printLintTotals = printLintTotals;
|
|
20
|
+
exports.printConfigLintTotals = printConfigLintTotals;
|
|
21
|
+
exports.getOutputFileName = getOutputFileName;
|
|
22
|
+
exports.printUnusedWarnings = printUnusedWarnings;
|
|
23
|
+
exports.exitWithError = exitWithError;
|
|
24
|
+
exports.isSubdir = isSubdir;
|
|
25
|
+
exports.loadConfigAndHandleErrors = loadConfigAndHandleErrors;
|
|
26
|
+
exports.sortTopLevelKeysForOas = sortTopLevelKeysForOas;
|
|
27
|
+
exports.checkIfRulesetExist = checkIfRulesetExist;
|
|
28
|
+
exports.cleanColors = cleanColors;
|
|
29
|
+
exports.sendTelemetry = sendTelemetry;
|
|
30
|
+
exports.cleanArgs = cleanArgs;
|
|
31
|
+
exports.cleanRawInput = cleanRawInput;
|
|
32
|
+
exports.checkForDeprecatedOptions = checkForDeprecatedOptions;
|
|
33
|
+
exports.notifyAboutIncompatibleConfigOptions = notifyAboutIncompatibleConfigOptions;
|
|
34
|
+
exports.formatPath = formatPath;
|
|
35
|
+
const path_1 = require("path");
|
|
36
|
+
const colorette_1 = require("colorette");
|
|
37
|
+
const perf_hooks_1 = require("perf_hooks");
|
|
38
|
+
const glob = require("glob");
|
|
39
|
+
const fs = require("fs");
|
|
40
|
+
const readline = require("readline");
|
|
41
|
+
const stream_1 = require("stream");
|
|
42
|
+
const child_process_1 = require("child_process");
|
|
43
|
+
const util_1 = require("util");
|
|
44
|
+
const openapi_core_1 = require("@redocly/openapi-core");
|
|
45
|
+
const utils_1 = require("@redocly/openapi-core/lib/utils");
|
|
46
|
+
const config_1 = require("@redocly/openapi-core/lib/config");
|
|
47
|
+
const reference_docs_config_schema_1 = require("@redocly/config/lib/reference-docs-config-schema");
|
|
48
|
+
const types_1 = require("../types");
|
|
49
|
+
const update_version_notifier_1 = require("./update-version-notifier");
|
|
50
|
+
const push_1 = require("../commands/push");
|
|
51
|
+
const fetch_with_timeout_1 = require("./fetch-with-timeout");
|
|
52
|
+
async function getFallbackApisOrExit(argsApis, config) {
|
|
53
|
+
const { apis } = config;
|
|
54
|
+
const shouldFallbackToAllDefinitions = !(0, utils_1.isNotEmptyArray)(argsApis) && (0, utils_1.isNotEmptyObject)(apis);
|
|
55
|
+
const res = shouldFallbackToAllDefinitions
|
|
56
|
+
? fallbackToAllDefinitions(apis, config)
|
|
57
|
+
: await expandGlobsInEntrypoints(argsApis, config);
|
|
58
|
+
const filteredInvalidEntrypoints = res.filter(({ path }) => !isApiPathValid(path));
|
|
59
|
+
if ((0, utils_1.isNotEmptyArray)(filteredInvalidEntrypoints)) {
|
|
60
|
+
for (const { path } of filteredInvalidEntrypoints) {
|
|
61
|
+
process.stderr.write((0, colorette_1.yellow)(`\n${formatPath(path)} ${(0, colorette_1.red)(`does not exist or is invalid.\n\n`)}`));
|
|
62
|
+
}
|
|
63
|
+
exitWithError('Please provide a valid path.');
|
|
64
|
+
}
|
|
65
|
+
return res;
|
|
66
|
+
}
|
|
67
|
+
function getConfigDirectory(config) {
|
|
68
|
+
return config.configFile ? (0, path_1.dirname)(config.configFile) : process.cwd();
|
|
69
|
+
}
|
|
70
|
+
function isApiPathValid(apiPath) {
|
|
71
|
+
if (!apiPath.trim()) {
|
|
72
|
+
exitWithError('Path cannot be empty.');
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
return fs.existsSync(apiPath) || (0, openapi_core_1.isAbsoluteUrl)(apiPath) ? apiPath : undefined;
|
|
76
|
+
}
|
|
77
|
+
function fallbackToAllDefinitions(apis, config) {
|
|
78
|
+
return Object.entries(apis).map(([alias, { root, output }]) => ({
|
|
79
|
+
path: (0, openapi_core_1.isAbsoluteUrl)(root) ? root : (0, path_1.resolve)(getConfigDirectory(config), root),
|
|
80
|
+
alias,
|
|
81
|
+
output: output && (0, path_1.resolve)(getConfigDirectory(config), output),
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
function getAliasOrPath(config, aliasOrPath) {
|
|
85
|
+
const aliasApi = config.apis[aliasOrPath];
|
|
86
|
+
return aliasApi
|
|
87
|
+
? {
|
|
88
|
+
path: (0, openapi_core_1.isAbsoluteUrl)(aliasApi.root)
|
|
89
|
+
? aliasApi.root
|
|
90
|
+
: (0, path_1.resolve)(getConfigDirectory(config), aliasApi.root),
|
|
91
|
+
alias: aliasOrPath,
|
|
92
|
+
output: aliasApi.output && (0, path_1.resolve)(getConfigDirectory(config), aliasApi.output),
|
|
93
|
+
}
|
|
94
|
+
: {
|
|
95
|
+
path: aliasOrPath,
|
|
96
|
+
// find alias by path, take the first match
|
|
97
|
+
alias: Object.entries(config.apis).find(([_alias, api]) => {
|
|
98
|
+
return (0, path_1.resolve)(api.root) === (0, path_1.resolve)(aliasOrPath);
|
|
99
|
+
})?.[0] ?? undefined,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
async function expandGlobsInEntrypoints(argApis, config) {
|
|
103
|
+
return (await Promise.all(argApis.map(async (aliasOrPath) => {
|
|
104
|
+
return glob.hasMagic(aliasOrPath) && !(0, openapi_core_1.isAbsoluteUrl)(aliasOrPath)
|
|
105
|
+
? (await (0, util_1.promisify)(glob)(aliasOrPath)).map((g) => getAliasOrPath(config, g))
|
|
106
|
+
: getAliasOrPath(config, aliasOrPath);
|
|
107
|
+
}))).flat();
|
|
108
|
+
}
|
|
109
|
+
function getExecutionTime(startedAt) {
|
|
110
|
+
return process.env.NODE_ENV === 'test'
|
|
111
|
+
? '<test>ms'
|
|
112
|
+
: `${Math.ceil(perf_hooks_1.performance.now() - startedAt)}ms`;
|
|
113
|
+
}
|
|
114
|
+
function printExecutionTime(commandName, startedAt, api) {
|
|
115
|
+
const elapsed = getExecutionTime(startedAt);
|
|
116
|
+
process.stderr.write((0, colorette_1.gray)(`\n${api}: ${commandName} processed in ${elapsed}\n\n`));
|
|
117
|
+
}
|
|
118
|
+
function pathToFilename(path, pathSeparator) {
|
|
119
|
+
return path
|
|
120
|
+
.replace(/~1/g, '/')
|
|
121
|
+
.replace(/~0/g, '~')
|
|
122
|
+
.replace(/^\//, '')
|
|
123
|
+
.replace(/\//g, pathSeparator);
|
|
124
|
+
}
|
|
125
|
+
function escapeLanguageName(lang) {
|
|
126
|
+
return lang.replace(/#/g, '_sharp').replace(/\//, '_').replace(/\s/g, '');
|
|
127
|
+
}
|
|
128
|
+
function langToExt(lang) {
|
|
129
|
+
const langObj = {
|
|
130
|
+
php: '.php',
|
|
131
|
+
'c#': '.cs',
|
|
132
|
+
shell: '.sh',
|
|
133
|
+
curl: '.sh',
|
|
134
|
+
bash: '.sh',
|
|
135
|
+
javascript: '.js',
|
|
136
|
+
js: '.js',
|
|
137
|
+
python: '.py',
|
|
138
|
+
c: '.c',
|
|
139
|
+
'c++': '.cpp',
|
|
140
|
+
coffeescript: '.litcoffee',
|
|
141
|
+
dart: '.dart',
|
|
142
|
+
elixir: '.ex',
|
|
143
|
+
go: '.go',
|
|
144
|
+
groovy: '.groovy',
|
|
145
|
+
java: '.java',
|
|
146
|
+
kotlin: '.kt',
|
|
147
|
+
'objective-c': '.m',
|
|
148
|
+
perl: '.pl',
|
|
149
|
+
powershell: '.ps1',
|
|
150
|
+
ruby: '.rb',
|
|
151
|
+
rust: '.rs',
|
|
152
|
+
scala: '.sc',
|
|
153
|
+
swift: '.swift',
|
|
154
|
+
typescript: '.ts',
|
|
155
|
+
tsx: '.tsx',
|
|
156
|
+
};
|
|
157
|
+
return langObj[lang.toLowerCase()];
|
|
158
|
+
}
|
|
159
|
+
class CircularJSONNotSupportedError extends Error {
|
|
160
|
+
constructor(originalError) {
|
|
161
|
+
super(originalError.message);
|
|
162
|
+
this.originalError = originalError;
|
|
163
|
+
// Set the prototype explicitly.
|
|
164
|
+
Object.setPrototypeOf(this, CircularJSONNotSupportedError.prototype);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
exports.CircularJSONNotSupportedError = CircularJSONNotSupportedError;
|
|
168
|
+
function dumpBundle(obj, format, dereference) {
|
|
169
|
+
if (format === 'json') {
|
|
170
|
+
try {
|
|
171
|
+
return JSON.stringify(obj, null, 2);
|
|
172
|
+
}
|
|
173
|
+
catch (e) {
|
|
174
|
+
if (e.message.indexOf('circular') > -1) {
|
|
175
|
+
throw new CircularJSONNotSupportedError(e);
|
|
176
|
+
}
|
|
177
|
+
throw e;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
return (0, openapi_core_1.stringifyYaml)(obj, {
|
|
182
|
+
noRefs: !dereference,
|
|
183
|
+
lineWidth: -1,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function saveBundle(filename, output) {
|
|
188
|
+
fs.mkdirSync((0, path_1.dirname)(filename), { recursive: true });
|
|
189
|
+
fs.writeFileSync(filename, output);
|
|
190
|
+
}
|
|
191
|
+
async function promptUser(query, hideUserInput = false) {
|
|
192
|
+
return new Promise((resolve) => {
|
|
193
|
+
let output = process.stdout;
|
|
194
|
+
let isOutputMuted = false;
|
|
195
|
+
if (hideUserInput) {
|
|
196
|
+
output = new stream_1.Writable({
|
|
197
|
+
write: (chunk, encoding, callback) => {
|
|
198
|
+
if (!isOutputMuted) {
|
|
199
|
+
process.stdout.write(chunk, encoding);
|
|
200
|
+
}
|
|
201
|
+
callback();
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
const rl = readline.createInterface({
|
|
206
|
+
input: process.stdin,
|
|
207
|
+
output,
|
|
208
|
+
terminal: true,
|
|
209
|
+
historySize: hideUserInput ? 0 : 30,
|
|
210
|
+
});
|
|
211
|
+
rl.question(`${query}:\n\n `, (answer) => {
|
|
212
|
+
rl.close();
|
|
213
|
+
resolve(answer);
|
|
214
|
+
});
|
|
215
|
+
isOutputMuted = hideUserInput;
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
function readYaml(filename) {
|
|
219
|
+
return (0, openapi_core_1.parseYaml)(fs.readFileSync(filename, 'utf-8'), { filename });
|
|
220
|
+
}
|
|
221
|
+
function writeToFileByExtension(data, filePath, noRefs) {
|
|
222
|
+
const ext = getAndValidateFileExtension(filePath);
|
|
223
|
+
if (ext === 'json') {
|
|
224
|
+
writeJson(data, filePath);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
writeYaml(data, filePath, noRefs);
|
|
228
|
+
}
|
|
229
|
+
function writeYaml(data, filename, noRefs = false) {
|
|
230
|
+
const content = (0, openapi_core_1.stringifyYaml)(data, { noRefs });
|
|
231
|
+
if (process.env.NODE_ENV === 'test') {
|
|
232
|
+
process.stderr.write(content);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
fs.mkdirSync((0, path_1.dirname)(filename), { recursive: true });
|
|
236
|
+
fs.writeFileSync(filename, content);
|
|
237
|
+
}
|
|
238
|
+
function writeJson(data, filename) {
|
|
239
|
+
const content = JSON.stringify(data, null, 2);
|
|
240
|
+
if (process.env.NODE_ENV === 'test') {
|
|
241
|
+
process.stderr.write(content);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
fs.mkdirSync((0, path_1.dirname)(filename), { recursive: true });
|
|
245
|
+
fs.writeFileSync(filename, content);
|
|
246
|
+
}
|
|
247
|
+
function getAndValidateFileExtension(fileName) {
|
|
248
|
+
const ext = fileName.split('.').pop();
|
|
249
|
+
if (['yaml', 'yml', 'json'].includes(ext)) {
|
|
250
|
+
return ext;
|
|
251
|
+
}
|
|
252
|
+
process.stderr.write((0, colorette_1.yellow)(`Unsupported file extension: ${ext}. Using yaml.\n`));
|
|
253
|
+
return 'yaml';
|
|
254
|
+
}
|
|
255
|
+
function handleError(e, ref) {
|
|
256
|
+
switch (e.constructor) {
|
|
257
|
+
case HandledError: {
|
|
258
|
+
throw e;
|
|
259
|
+
}
|
|
260
|
+
case openapi_core_1.ResolveError:
|
|
261
|
+
return exitWithError(`Failed to resolve API description at ${ref}:\n\n - ${e.message}`);
|
|
262
|
+
case openapi_core_1.YamlParseError:
|
|
263
|
+
return exitWithError(`Failed to parse API description at ${ref}:\n\n - ${e.message}`);
|
|
264
|
+
case CircularJSONNotSupportedError: {
|
|
265
|
+
return exitWithError(`Detected circular reference which can't be converted to JSON.\n` +
|
|
266
|
+
`Try to use ${(0, colorette_1.blue)('yaml')} output or remove ${(0, colorette_1.blue)('--dereferenced')}.`);
|
|
267
|
+
}
|
|
268
|
+
case SyntaxError:
|
|
269
|
+
return exitWithError(`Syntax error: ${e.message} ${e.stack?.split('\n\n')?.[0]}`);
|
|
270
|
+
case config_1.ConfigValidationError:
|
|
271
|
+
return exitWithError(e.message);
|
|
272
|
+
default: {
|
|
273
|
+
exitWithError(`Something went wrong when processing ${ref}:\n\n - ${e.message}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
class HandledError extends Error {
|
|
278
|
+
}
|
|
279
|
+
exports.HandledError = HandledError;
|
|
280
|
+
function printLintTotals(totals, definitionsCount) {
|
|
281
|
+
const ignored = totals.ignored
|
|
282
|
+
? (0, colorette_1.yellow)(`${totals.ignored} ${(0, utils_1.pluralize)('problem is', totals.ignored)} explicitly ignored.\n\n`)
|
|
283
|
+
: '';
|
|
284
|
+
if (totals.errors > 0) {
|
|
285
|
+
process.stderr.write((0, colorette_1.red)(`❌ Validation failed with ${totals.errors} ${(0, utils_1.pluralize)('error', totals.errors)}${totals.warnings > 0
|
|
286
|
+
? ` and ${totals.warnings} ${(0, utils_1.pluralize)('warning', totals.warnings)}`
|
|
287
|
+
: ''}.\n${ignored}`));
|
|
288
|
+
}
|
|
289
|
+
else if (totals.warnings > 0) {
|
|
290
|
+
process.stderr.write((0, colorette_1.green)(`Woohoo! Your API ${(0, utils_1.pluralize)('description is', definitionsCount)} valid. 🎉\n`));
|
|
291
|
+
process.stderr.write((0, colorette_1.yellow)(`You have ${totals.warnings} ${(0, utils_1.pluralize)('warning', totals.warnings)}.\n${ignored}`));
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
process.stderr.write((0, colorette_1.green)(`Woohoo! Your API ${(0, utils_1.pluralize)('description is', definitionsCount)} valid. 🎉\n${ignored}`));
|
|
295
|
+
}
|
|
296
|
+
if (totals.errors > 0) {
|
|
297
|
+
process.stderr.write((0, colorette_1.gray)(`run \`redocly lint --generate-ignore-file\` to add all problems to the ignore file.\n`));
|
|
298
|
+
}
|
|
299
|
+
process.stderr.write('\n');
|
|
300
|
+
}
|
|
301
|
+
function printConfigLintTotals(totals, command) {
|
|
302
|
+
if (totals.errors > 0) {
|
|
303
|
+
process.stderr.write((0, colorette_1.red)(`❌ Your config has ${totals.errors} ${(0, utils_1.pluralize)('error', totals.errors)}.`));
|
|
304
|
+
}
|
|
305
|
+
else if (totals.warnings > 0) {
|
|
306
|
+
process.stderr.write((0, colorette_1.yellow)(`⚠️ Your config has ${totals.warnings} ${(0, utils_1.pluralize)('warning', totals.warnings)}.\n`));
|
|
307
|
+
}
|
|
308
|
+
else if (command === 'check-config') {
|
|
309
|
+
process.stderr.write((0, colorette_1.green)('✅ Your config is valid.\n'));
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
function getOutputFileName({ entrypoint, output, argvOutput, ext, entries, }) {
|
|
313
|
+
let outputFile = output || argvOutput;
|
|
314
|
+
if (!outputFile) {
|
|
315
|
+
return { ext: ext || 'yaml' };
|
|
316
|
+
}
|
|
317
|
+
if (entries > 1 && argvOutput) {
|
|
318
|
+
ext = ext || (0, path_1.extname)(entrypoint).substring(1);
|
|
319
|
+
if (!types_1.outputExtensions.includes(ext)) {
|
|
320
|
+
throw new Error(`Invalid file extension: ${ext}.`);
|
|
321
|
+
}
|
|
322
|
+
outputFile = (0, path_1.join)(argvOutput, (0, path_1.basename)(entrypoint, (0, path_1.extname)(entrypoint))) + '.' + ext;
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
ext =
|
|
326
|
+
ext ||
|
|
327
|
+
(0, path_1.extname)(outputFile).substring(1) ||
|
|
328
|
+
(0, path_1.extname)(entrypoint).substring(1);
|
|
329
|
+
if (!types_1.outputExtensions.includes(ext)) {
|
|
330
|
+
throw new Error(`Invalid file extension: ${ext}.`);
|
|
331
|
+
}
|
|
332
|
+
outputFile = (0, path_1.join)((0, path_1.dirname)(outputFile), (0, path_1.basename)(outputFile, (0, path_1.extname)(outputFile))) + '.' + ext;
|
|
333
|
+
}
|
|
334
|
+
return { outputFile, ext };
|
|
335
|
+
}
|
|
336
|
+
function printUnusedWarnings(config) {
|
|
337
|
+
const { preprocessors, rules, decorators } = config.getUnusedRules();
|
|
338
|
+
if (rules.length) {
|
|
339
|
+
process.stderr.write((0, colorette_1.yellow)(`[WARNING] Unused rules found in ${(0, colorette_1.blue)(config.configFile || '')}: ${rules.join(', ')}.\n`));
|
|
340
|
+
}
|
|
341
|
+
if (preprocessors.length) {
|
|
342
|
+
process.stderr.write((0, colorette_1.yellow)(`[WARNING] Unused preprocessors found in ${(0, colorette_1.blue)(config.configFile || '')}: ${preprocessors.join(', ')}.\n`));
|
|
343
|
+
}
|
|
344
|
+
if (decorators.length) {
|
|
345
|
+
process.stderr.write((0, colorette_1.yellow)(`[WARNING] Unused decorators found in ${(0, colorette_1.blue)(config.configFile || '')}: ${decorators.join(', ')}.\n`));
|
|
346
|
+
}
|
|
347
|
+
if (rules.length || preprocessors.length) {
|
|
348
|
+
process.stderr.write(`Check the spelling and verify the added plugin prefix.\n`);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function exitWithError(message) {
|
|
352
|
+
process.stderr.write((0, colorette_1.red)(message) + '\n\n');
|
|
353
|
+
throw new HandledError(message);
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Checks if dir is subdir of parent
|
|
357
|
+
*/
|
|
358
|
+
function isSubdir(parent, dir) {
|
|
359
|
+
const relativePath = (0, path_1.relative)(parent, dir);
|
|
360
|
+
return !!relativePath && !/^..($|\/)/.test(relativePath) && !(0, path_1.isAbsolute)(relativePath);
|
|
361
|
+
}
|
|
362
|
+
async function loadConfigAndHandleErrors(options = {}) {
|
|
363
|
+
try {
|
|
364
|
+
return await (0, openapi_core_1.loadConfig)(options);
|
|
365
|
+
}
|
|
366
|
+
catch (e) {
|
|
367
|
+
handleError(e, '');
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
function sortTopLevelKeysForOas(document) {
|
|
371
|
+
if ('swagger' in document) {
|
|
372
|
+
return sortOas2Keys(document);
|
|
373
|
+
}
|
|
374
|
+
return sortOas3Keys(document);
|
|
375
|
+
}
|
|
376
|
+
function sortOas2Keys(document) {
|
|
377
|
+
const orderedKeys = [
|
|
378
|
+
'swagger',
|
|
379
|
+
'info',
|
|
380
|
+
'host',
|
|
381
|
+
'basePath',
|
|
382
|
+
'schemes',
|
|
383
|
+
'consumes',
|
|
384
|
+
'produces',
|
|
385
|
+
'security',
|
|
386
|
+
'tags',
|
|
387
|
+
'externalDocs',
|
|
388
|
+
'paths',
|
|
389
|
+
'definitions',
|
|
390
|
+
'parameters',
|
|
391
|
+
'responses',
|
|
392
|
+
'securityDefinitions',
|
|
393
|
+
];
|
|
394
|
+
const result = {};
|
|
395
|
+
for (const key of orderedKeys) {
|
|
396
|
+
if (document.hasOwnProperty(key)) {
|
|
397
|
+
result[key] = document[key];
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
// merge any other top-level keys (e.g. vendor extensions)
|
|
401
|
+
return Object.assign(result, document);
|
|
402
|
+
}
|
|
403
|
+
function sortOas3Keys(document) {
|
|
404
|
+
const orderedKeys = [
|
|
405
|
+
'openapi',
|
|
406
|
+
'info',
|
|
407
|
+
'jsonSchemaDialect',
|
|
408
|
+
'servers',
|
|
409
|
+
'security',
|
|
410
|
+
'tags',
|
|
411
|
+
'externalDocs',
|
|
412
|
+
'paths',
|
|
413
|
+
'webhooks',
|
|
414
|
+
'x-webhooks',
|
|
415
|
+
'components',
|
|
416
|
+
];
|
|
417
|
+
const result = {};
|
|
418
|
+
for (const key of orderedKeys) {
|
|
419
|
+
if (document.hasOwnProperty(key)) {
|
|
420
|
+
result[key] = document[key];
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
// merge any other top-level keys (e.g. vendor extensions)
|
|
424
|
+
return Object.assign(result, document);
|
|
425
|
+
}
|
|
426
|
+
function checkIfRulesetExist(rules) {
|
|
427
|
+
const ruleset = {
|
|
428
|
+
...rules.oas2,
|
|
429
|
+
...rules.oas3_0,
|
|
430
|
+
...rules.oas3_1,
|
|
431
|
+
...rules.async2,
|
|
432
|
+
...rules.async3,
|
|
433
|
+
...rules.arazzo1,
|
|
434
|
+
};
|
|
435
|
+
if ((0, utils_1.isEmptyObject)(ruleset)) {
|
|
436
|
+
exitWithError('⚠️ No rules were configured. Learn how to configure rules: https://redocly.com/docs/cli/rules/');
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
function cleanColors(input) {
|
|
440
|
+
// eslint-disable-next-line no-control-regex
|
|
441
|
+
return input.replace(/\x1b\[\d+m/g, '');
|
|
442
|
+
}
|
|
443
|
+
async function sendTelemetry(argv, exit_code, has_config, spec_version, spec_keyword, spec_full_version) {
|
|
444
|
+
try {
|
|
445
|
+
if (!argv) {
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
const { _: [command], $0: _, ...args } = argv;
|
|
449
|
+
const event_time = new Date().toISOString();
|
|
450
|
+
const redoclyClient = new openapi_core_1.RedoclyClient();
|
|
451
|
+
const logged_in = redoclyClient.hasTokens();
|
|
452
|
+
const data = {
|
|
453
|
+
event: 'cli_command',
|
|
454
|
+
event_time,
|
|
455
|
+
logged_in,
|
|
456
|
+
command,
|
|
457
|
+
arguments: cleanArgs(args),
|
|
458
|
+
node_version: process.version,
|
|
459
|
+
npm_version: (0, child_process_1.execSync)('npm -v').toString().replace('\n', ''),
|
|
460
|
+
version: update_version_notifier_1.version,
|
|
461
|
+
exit_code,
|
|
462
|
+
environment: process.env.REDOCLY_ENVIRONMENT,
|
|
463
|
+
environment_ci: process.env.CI,
|
|
464
|
+
raw_input: cleanRawInput(process.argv.slice(2)),
|
|
465
|
+
has_config,
|
|
466
|
+
spec_version,
|
|
467
|
+
spec_keyword,
|
|
468
|
+
spec_full_version,
|
|
469
|
+
};
|
|
470
|
+
await (0, fetch_with_timeout_1.default)(`https://api.redocly.com/registry/telemetry/cli`, {
|
|
471
|
+
timeout: fetch_with_timeout_1.DEFAULT_FETCH_TIMEOUT,
|
|
472
|
+
method: 'POST',
|
|
473
|
+
headers: {
|
|
474
|
+
'content-type': 'application/json',
|
|
475
|
+
},
|
|
476
|
+
body: JSON.stringify(data),
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
catch (err) {
|
|
480
|
+
// Do nothing.
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
function isFile(value) {
|
|
484
|
+
return fs.existsSync(value) && fs.statSync(value).isFile();
|
|
485
|
+
}
|
|
486
|
+
function isDirectory(value) {
|
|
487
|
+
return fs.existsSync(value) && fs.statSync(value).isDirectory();
|
|
488
|
+
}
|
|
489
|
+
function cleanString(value) {
|
|
490
|
+
if (!value) {
|
|
491
|
+
return value;
|
|
492
|
+
}
|
|
493
|
+
if ((0, openapi_core_1.isAbsoluteUrl)(value)) {
|
|
494
|
+
return value.split('://')[0] + '://url';
|
|
495
|
+
}
|
|
496
|
+
if (isFile(value)) {
|
|
497
|
+
return value.replace(/.+\.([^.]+)$/, (_, ext) => 'file-' + ext);
|
|
498
|
+
}
|
|
499
|
+
if (isDirectory(value)) {
|
|
500
|
+
return 'folder';
|
|
501
|
+
}
|
|
502
|
+
if (push_1.DESTINATION_REGEX.test(value)) {
|
|
503
|
+
return value.startsWith('@') ? '@organization/api-name@api-version' : 'api-name@api-version';
|
|
504
|
+
}
|
|
505
|
+
return value;
|
|
506
|
+
}
|
|
507
|
+
function cleanArgs(args) {
|
|
508
|
+
const keysToClean = ['organization', 'o'];
|
|
509
|
+
const result = {};
|
|
510
|
+
for (const [key, value] of Object.entries(args)) {
|
|
511
|
+
if (keysToClean.includes(key)) {
|
|
512
|
+
result[key] = '***';
|
|
513
|
+
}
|
|
514
|
+
else if (typeof value === 'string') {
|
|
515
|
+
result[key] = cleanString(value);
|
|
516
|
+
}
|
|
517
|
+
else if (Array.isArray(value)) {
|
|
518
|
+
result[key] = value.map(cleanString);
|
|
519
|
+
}
|
|
520
|
+
else {
|
|
521
|
+
result[key] = value;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return result;
|
|
525
|
+
}
|
|
526
|
+
function cleanRawInput(argv) {
|
|
527
|
+
return argv.map((entry) => entry.split('=').map(cleanString).join('=')).join(' ');
|
|
528
|
+
}
|
|
529
|
+
function checkForDeprecatedOptions(argv, deprecatedOptions) {
|
|
530
|
+
for (const option of deprecatedOptions) {
|
|
531
|
+
if (argv[option]) {
|
|
532
|
+
process.stderr.write((0, colorette_1.yellow)(`[WARNING] "${String(option)}" option is deprecated and will be removed in a future release. \n\n`));
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
function notifyAboutIncompatibleConfigOptions(themeOpenapiOptions) {
|
|
537
|
+
if ((0, utils_1.isPlainObject)(themeOpenapiOptions)) {
|
|
538
|
+
const propertiesSet = Object.keys(themeOpenapiOptions);
|
|
539
|
+
const deprecatedSet = Object.keys(reference_docs_config_schema_1.deprecatedRefDocsSchema.properties);
|
|
540
|
+
const intersection = propertiesSet.filter((prop) => deprecatedSet.includes(prop));
|
|
541
|
+
if (intersection.length > 0) {
|
|
542
|
+
process.stderr.write((0, colorette_1.yellow)(`\n${(0, utils_1.pluralize)('Property', intersection.length)} ${(0, colorette_1.gray)(intersection.map((prop) => `'${prop}'`).join(', '))} ${(0, utils_1.pluralize)('is', intersection.length)} only used in API Reference Docs and Redoc version 2.x or earlier.\n\n`));
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
function formatPath(path) {
|
|
547
|
+
if ((0, openapi_core_1.isAbsoluteUrl)(path)) {
|
|
548
|
+
return path;
|
|
549
|
+
}
|
|
550
|
+
return (0, path_1.relative)(process.cwd(), path);
|
|
551
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitizes the input path by removing invalid characters.
|
|
3
|
+
*/
|
|
4
|
+
export declare const sanitizePath: (input: string) => string;
|
|
5
|
+
/**
|
|
6
|
+
* Sanitizes the input locale (ex. en-US) by removing invalid characters.
|
|
7
|
+
*/
|
|
8
|
+
export declare const sanitizeLocale: (input: string) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Retrieves platform-specific arguments and utilities.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getPlatformSpawnArgs(): {
|
|
13
|
+
npxExecutableName: string;
|
|
14
|
+
sanitize: (input: string | undefined, sanitizer: (input: string) => string) => string;
|
|
15
|
+
shell: boolean;
|
|
16
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sanitizeLocale = exports.sanitizePath = void 0;
|
|
4
|
+
exports.getPlatformSpawnArgs = getPlatformSpawnArgs;
|
|
5
|
+
/**
|
|
6
|
+
* Sanitizes the input path by removing invalid characters.
|
|
7
|
+
*/
|
|
8
|
+
const sanitizePath = (input) => {
|
|
9
|
+
return input.replace(/[^a-zA-Z0-9 ._\-:\\/@]/g, '');
|
|
10
|
+
};
|
|
11
|
+
exports.sanitizePath = sanitizePath;
|
|
12
|
+
/**
|
|
13
|
+
* Sanitizes the input locale (ex. en-US) by removing invalid characters.
|
|
14
|
+
*/
|
|
15
|
+
const sanitizeLocale = (input) => {
|
|
16
|
+
return input.replace(/[^a-zA-Z0-9@._-]/g, '');
|
|
17
|
+
};
|
|
18
|
+
exports.sanitizeLocale = sanitizeLocale;
|
|
19
|
+
/**
|
|
20
|
+
* Retrieves platform-specific arguments and utilities.
|
|
21
|
+
*/
|
|
22
|
+
function getPlatformSpawnArgs() {
|
|
23
|
+
const isWindowsPlatform = process.platform === 'win32';
|
|
24
|
+
const npxExecutableName = isWindowsPlatform ? 'npx.cmd' : 'npx';
|
|
25
|
+
const sanitizeIfWindows = (input, sanitizer) => {
|
|
26
|
+
if (isWindowsPlatform && input) {
|
|
27
|
+
return sanitizer(input);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
return input || '';
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
return { npxExecutableName, sanitize: sanitizeIfWindows, shell: isWindowsPlatform };
|
|
34
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Spinner = void 0;
|
|
4
|
+
const process = require("process");
|
|
5
|
+
const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
6
|
+
class Spinner {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.frames = SPINNER_FRAMES;
|
|
9
|
+
this.currentFrame = 0;
|
|
10
|
+
this.intervalId = null;
|
|
11
|
+
this.message = '';
|
|
12
|
+
}
|
|
13
|
+
showFrame() {
|
|
14
|
+
process.stdout.write('\r' + this.frames[this.currentFrame] + ' ' + this.message);
|
|
15
|
+
this.currentFrame = (this.currentFrame + 1) % this.frames.length;
|
|
16
|
+
}
|
|
17
|
+
start(message) {
|
|
18
|
+
if (this.message === message) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
this.message = message;
|
|
22
|
+
// If we're not in a TTY, don't display the spinner.
|
|
23
|
+
if (!process.stdout.isTTY) {
|
|
24
|
+
process.stdout.write(`${message}...\n`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (this.intervalId === null) {
|
|
28
|
+
this.intervalId = setInterval(() => {
|
|
29
|
+
this.showFrame();
|
|
30
|
+
}, 100);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
stop() {
|
|
34
|
+
if (this.intervalId !== null) {
|
|
35
|
+
clearInterval(this.intervalId);
|
|
36
|
+
this.intervalId = null;
|
|
37
|
+
process.stdout.write('\r');
|
|
38
|
+
}
|
|
39
|
+
this.message = '';
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.Spinner = Spinner;
|