@scalar/cli 0.2.141 → 0.2.143
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/dist/commands/bundle/BundleCommand.js +38 -0
- package/dist/commands/format/FormatCommand.js +44 -0
- package/dist/commands/init/InitCommand.js +145 -0
- package/dist/commands/mock/MockCommand.js +124 -0
- package/dist/commands/serve/ServeCommand.js +89 -0
- package/dist/commands/share/ShareCommand.js +58 -0
- package/dist/commands/validate/ValidateCommand.js +47 -0
- package/dist/commands/void/VoidCommand.js +38 -0
- package/dist/index.js +11 -962
- package/dist/package.json.js +3 -0
- package/dist/src/commands/bundle/BundleCommand.d.ts +3 -0
- package/dist/src/commands/bundle/BundleCommand.d.ts.map +1 -0
- package/dist/src/commands/format/FormatCommand.d.ts +3 -0
- package/dist/src/commands/format/FormatCommand.d.ts.map +1 -0
- package/dist/src/commands/format/format.test.d.ts +2 -0
- package/dist/src/commands/format/format.test.d.ts.map +1 -0
- package/dist/src/commands/index.d.ts +9 -0
- package/dist/src/commands/index.d.ts.map +1 -0
- package/dist/src/commands/init/InitCommand.d.ts +33 -0
- package/dist/src/commands/init/InitCommand.d.ts.map +1 -0
- package/dist/src/commands/init/init.test.d.ts +2 -0
- package/dist/src/commands/init/init.test.d.ts.map +1 -0
- package/dist/src/commands/mock/MockCommand.d.ts +3 -0
- package/dist/src/commands/mock/MockCommand.d.ts.map +1 -0
- package/dist/src/commands/mock/mock.test.d.ts +2 -0
- package/dist/src/commands/mock/mock.test.d.ts.map +1 -0
- package/dist/src/commands/serve/ServeCommand.d.ts +3 -0
- package/dist/src/commands/serve/ServeCommand.d.ts.map +1 -0
- package/dist/src/commands/share/ShareCommand.d.ts +3 -0
- package/dist/src/commands/share/ShareCommand.d.ts.map +1 -0
- package/dist/src/commands/validate/ValidateCommand.d.ts +6 -0
- package/dist/src/commands/validate/ValidateCommand.d.ts.map +1 -0
- package/dist/src/commands/validate/validate.test.d.ts +2 -0
- package/dist/src/commands/validate/validate.test.d.ts.map +1 -0
- package/dist/src/commands/void/VoidCommand.d.ts +3 -0
- package/dist/src/commands/void/VoidCommand.d.ts.map +1 -0
- package/dist/src/commands/void/void.test.d.ts +2 -0
- package/dist/src/commands/void/void.test.d.ts.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/options/version/version.test.d.ts +2 -0
- package/dist/src/options/version/version.test.d.ts.map +1 -0
- package/dist/src/utils/getFileOrUrl.d.ts +5 -0
- package/dist/src/utils/getFileOrUrl.d.ts.map +1 -0
- package/dist/src/utils/getHtmlDocument.d.ts +3 -0
- package/dist/src/utils/getHtmlDocument.d.ts.map +1 -0
- package/dist/src/utils/getMethodColor.d.ts +3 -0
- package/dist/src/utils/getMethodColor.d.ts.map +1 -0
- package/dist/src/utils/getOperationByMethodAndPath.d.ts +3 -0
- package/dist/src/utils/getOperationByMethodAndPath.d.ts.map +1 -0
- package/dist/src/utils/getOperationByMethodAndPath.test.d.ts +2 -0
- package/dist/src/utils/getOperationByMethodAndPath.test.d.ts.map +1 -0
- package/dist/src/utils/index.d.ts +9 -0
- package/dist/src/utils/index.d.ts.map +1 -0
- package/dist/src/utils/isUrl.d.ts +5 -0
- package/dist/src/utils/isUrl.d.ts.map +1 -0
- package/dist/src/utils/isYamlFileName.d.ts +5 -0
- package/dist/src/utils/isYamlFileName.d.ts.map +1 -0
- package/dist/src/utils/loadOpenApiFile.d.ts +11 -0
- package/dist/src/utils/loadOpenApiFile.d.ts.map +1 -0
- package/dist/src/utils/printSpecificationBanner.d.ts +6 -0
- package/dist/src/utils/printSpecificationBanner.d.ts.map +1 -0
- package/dist/src/utils/readFile.d.ts +2 -0
- package/dist/src/utils/readFile.d.ts.map +1 -0
- package/dist/src/utils/useGivenFileOrConfiguration.d.ts +3 -0
- package/dist/src/utils/useGivenFileOrConfiguration.d.ts.map +1 -0
- package/dist/src/utils/watchFile.d.ts +7 -0
- package/dist/src/utils/watchFile.d.ts.map +1 -0
- package/dist/tests/invoke-cli.d.ts +12 -0
- package/dist/tests/invoke-cli.d.ts.map +1 -0
- package/dist/tests/matcher.d.ts +10 -0
- package/dist/tests/matcher.d.ts.map +1 -0
- package/dist/utils/getFileOrUrl.js +23 -0
- package/dist/utils/getHtmlDocument.js +37 -0
- package/dist/utils/getMethodColor.js +12 -0
- package/dist/utils/isUrl.js +9 -0
- package/dist/utils/isYamlFileName.js +13 -0
- package/dist/utils/loadOpenApiFile.js +41 -0
- package/dist/utils/printSpecificationBanner.js +19 -0
- package/dist/utils/readFile.js +16 -0
- package/dist/utils/useGivenFileOrConfiguration.js +31 -0
- package/dist/utils/watchFile.js +33 -0
- package/package.json +18 -9
- package/dist/package.json +0 -64
- package/dist/tsconfig.tsbuildinfo +0 -1
package/dist/index.js
CHANGED
|
@@ -1,967 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
import prettyjson from 'prettyjson';
|
|
15
|
-
import { createVoidServer } from '@scalar/void-server';
|
|
16
|
-
|
|
17
|
-
var version = "0.2.141";
|
|
18
|
-
|
|
19
|
-
/******************************************************************************
|
|
20
|
-
Copyright (c) Microsoft Corporation.
|
|
21
|
-
|
|
22
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
23
|
-
purpose with or without fee is hereby granted.
|
|
24
|
-
|
|
25
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
26
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
27
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
28
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
29
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
30
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
31
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
32
|
-
***************************************************************************** */
|
|
33
|
-
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
37
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
38
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
39
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
40
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
41
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
42
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function __generator(thisArg, body) {
|
|
47
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
48
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
49
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
50
|
-
function step(op) {
|
|
51
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
52
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
53
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
54
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
55
|
-
switch (op[0]) {
|
|
56
|
-
case 0: case 1: t = op; break;
|
|
57
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
58
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
59
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
60
|
-
default:
|
|
61
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
62
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
63
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
64
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
65
|
-
if (t[2]) _.ops.pop();
|
|
66
|
-
_.trys.pop(); continue;
|
|
67
|
-
}
|
|
68
|
-
op = body.call(thisArg, _);
|
|
69
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
70
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
75
|
-
var e = new Error(message);
|
|
76
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Check if the input is a URL.
|
|
81
|
-
*/
|
|
82
|
-
function isUrl(text) {
|
|
83
|
-
return (typeof text === 'string' &&
|
|
84
|
-
(text.startsWith('http://') || text.startsWith('https://')));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Pass a file path or URL and get the content of the file.
|
|
89
|
-
*/
|
|
90
|
-
function getFileOrUrl(input) {
|
|
91
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
92
|
-
var response;
|
|
93
|
-
return __generator(this, function (_a) {
|
|
94
|
-
switch (_a.label) {
|
|
95
|
-
case 0:
|
|
96
|
-
if (!isUrl(input)) return [3 /*break*/, 3];
|
|
97
|
-
return [4 /*yield*/, fetch(input)];
|
|
98
|
-
case 1:
|
|
99
|
-
response = _a.sent();
|
|
100
|
-
if (!response.ok) {
|
|
101
|
-
console.error(kleur.bold().red('[ERROR]'), kleur.bold().red('Failed to fetch OpenAPI specification from URL.'));
|
|
102
|
-
return [2 /*return*/, ''];
|
|
103
|
-
}
|
|
104
|
-
return [4 /*yield*/, response.text()];
|
|
105
|
-
case 2: return [2 /*return*/, _a.sent()];
|
|
106
|
-
case 3:
|
|
107
|
-
if (!fs.existsSync(input)) {
|
|
108
|
-
throw new Error('File not found');
|
|
109
|
-
}
|
|
110
|
-
return [2 /*return*/, fs.readFileSync(input, 'utf-8')];
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function getHtmlDocument(specification, watch) {
|
|
117
|
-
if (watch === void 0) { watch = false; }
|
|
118
|
-
return "<!doctype html>\n <html>\n <head>\n <title>Scalar API Reference</title>\n <meta charset=\"utf-8\" />\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1\" />\n <style>\n body {\n margin: 0;\n }\n </style>\n ".concat(watch
|
|
119
|
-
? "\n <script>\n const evtSource = new EventSource('__watcher');\n evtSource.onmessage = (event) => {\n console.log(`message: ${event.data}`);\n window.location.reload();\n };\n </script>\n "
|
|
120
|
-
: '', "\n </head>\n <body>\n <script\n id=\"api-reference\"\n type=\"application/json\"\n data-proxy-url=\"https://proxy.scalar.com\">").concat(JSON.stringify(specification), "</script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n </html>");
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function getMethodColor(method) {
|
|
124
|
-
var _a;
|
|
125
|
-
var colors = {
|
|
126
|
-
get: 'green',
|
|
127
|
-
post: 'cyan',
|
|
128
|
-
put: 'yellow',
|
|
129
|
-
delete: 'red',
|
|
130
|
-
patch: 'magenta',
|
|
131
|
-
};
|
|
132
|
-
return (_a = colors[method.toLowerCase()]) !== null && _a !== void 0 ? _a : 'grey';
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function loadOpenApiFile(input) {
|
|
136
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
137
|
-
var specification, filesystem, result, error_1;
|
|
138
|
-
var _a;
|
|
139
|
-
return __generator(this, function (_b) {
|
|
140
|
-
switch (_b.label) {
|
|
141
|
-
case 0: return [4 /*yield*/, getFileOrUrl(input)];
|
|
142
|
-
case 1:
|
|
143
|
-
specification = _b.sent();
|
|
144
|
-
_b.label = 2;
|
|
145
|
-
case 2:
|
|
146
|
-
_b.trys.push([2, 5, , 6]);
|
|
147
|
-
return [4 /*yield*/, load(specification)];
|
|
148
|
-
case 3:
|
|
149
|
-
filesystem = (_b.sent()).filesystem;
|
|
150
|
-
return [4 /*yield*/, validate(filesystem)
|
|
151
|
-
// Invalid specification
|
|
152
|
-
];
|
|
153
|
-
case 4:
|
|
154
|
-
result = _b.sent();
|
|
155
|
-
// Invalid specification
|
|
156
|
-
if (!result.valid) {
|
|
157
|
-
console.warn(kleur.bold().yellow('[WARN]'), kleur.bold().yellow('File doesn’t match the OpenAPI specification.'));
|
|
158
|
-
console.log();
|
|
159
|
-
// Output errors
|
|
160
|
-
(_a = result.errors) === null || _a === void 0 ? void 0 : _a.forEach(function (error) {
|
|
161
|
-
console.warn(kleur.bold().yellow('[WARN]'), kleur.yellow(error.error), kleur.yellow("(".concat(error.path, ")")));
|
|
162
|
-
});
|
|
163
|
-
console.log();
|
|
164
|
-
return [2 /*return*/, result];
|
|
165
|
-
}
|
|
166
|
-
return [2 /*return*/, result];
|
|
167
|
-
case 5:
|
|
168
|
-
error_1 = _b.sent();
|
|
169
|
-
console.warn(kleur.bold().red('[ERROR]'), kleur.red(error_1));
|
|
170
|
-
console.log();
|
|
171
|
-
return [2 /*return*/, {
|
|
172
|
-
valid: false,
|
|
173
|
-
version: undefined,
|
|
174
|
-
specification: undefined,
|
|
175
|
-
schema: undefined,
|
|
176
|
-
errors: [
|
|
177
|
-
{
|
|
178
|
-
error: error_1.message,
|
|
179
|
-
path: '',
|
|
180
|
-
},
|
|
181
|
-
],
|
|
182
|
-
}];
|
|
183
|
-
case 6: return [2 /*return*/];
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
function readFile(file) {
|
|
190
|
-
try {
|
|
191
|
-
if (fs.existsSync(file) === false) {
|
|
192
|
-
return undefined;
|
|
193
|
-
}
|
|
194
|
-
return fs.readFileSync(file, 'utf8');
|
|
195
|
-
}
|
|
196
|
-
catch (err) {
|
|
197
|
-
console.error(err);
|
|
198
|
-
return undefined;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
var CONFIG_FILE = 'scalar.config.json';
|
|
203
|
-
function useGivenFileOrConfiguration(file) {
|
|
204
|
-
var _a;
|
|
205
|
-
// If a specific file is given, use it.
|
|
206
|
-
if (file) {
|
|
207
|
-
return file;
|
|
208
|
-
}
|
|
209
|
-
// Try to load the configuration
|
|
210
|
-
try {
|
|
211
|
-
// check if file exists
|
|
212
|
-
var content = readFile(CONFIG_FILE);
|
|
213
|
-
var configuration = JSON.parse(content);
|
|
214
|
-
if ((_a = configuration === null || configuration === void 0 ? void 0 : configuration.reference) === null || _a === void 0 ? void 0 : _a.file) {
|
|
215
|
-
return configuration.reference.file;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
catch (_b) {
|
|
219
|
-
// Do nothing
|
|
220
|
-
}
|
|
221
|
-
console.error(kleur.red('No file provided.'));
|
|
222
|
-
console.log();
|
|
223
|
-
console.log(kleur.white('Try `scalar init` or add the file as an argument. Read `scalar --help` for more information.'));
|
|
224
|
-
console.log();
|
|
225
|
-
return process.exit(1);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Watch a foobar for changes and call a callback when it does.
|
|
230
|
-
*/
|
|
231
|
-
function watchFile(file, callback, options) {
|
|
232
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
233
|
-
var absoluteFilePath, directory;
|
|
234
|
-
return __generator(this, function (_a) {
|
|
235
|
-
switch (_a.label) {
|
|
236
|
-
case 0:
|
|
237
|
-
// Poll URLs
|
|
238
|
-
if (isUrl(file)) {
|
|
239
|
-
setInterval(callback, 5000);
|
|
240
|
-
return [2 /*return*/];
|
|
241
|
-
}
|
|
242
|
-
absoluteFilePath = path.join(process.cwd(), file);
|
|
243
|
-
// Check if file exists
|
|
244
|
-
if (!fs.existsSync(absoluteFilePath)) {
|
|
245
|
-
throw new Error("File ".concat(absoluteFilePath, " does not exist"));
|
|
246
|
-
}
|
|
247
|
-
// Watch the file for changes
|
|
248
|
-
console.log("[INFO] Watch ".concat(file));
|
|
249
|
-
directory = path.dirname(absoluteFilePath);
|
|
250
|
-
// Start the watcher
|
|
251
|
-
return [4 /*yield*/, watcher.subscribe(directory, function (err, events) {
|
|
252
|
-
// Match the file path
|
|
253
|
-
if (events.some(function (event) { return event.path === absoluteFilePath; })) {
|
|
254
|
-
callback();
|
|
255
|
-
}
|
|
256
|
-
})
|
|
257
|
-
// Call the callback immediately
|
|
258
|
-
];
|
|
259
|
-
case 1:
|
|
260
|
-
// Start the watcher
|
|
261
|
-
_a.sent();
|
|
262
|
-
return [2 /*return*/];
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
function BundleCommand() {
|
|
269
|
-
var _this = this;
|
|
270
|
-
var cmd = new Command('bundle');
|
|
271
|
-
cmd.description('Resolve all references in an OpenAPI file');
|
|
272
|
-
cmd.argument('[file]', 'file to bundle');
|
|
273
|
-
cmd.option('-o, --output <file>', 'output file');
|
|
274
|
-
cmd.action(function (fileArgument) { return __awaiter(_this, void 0, void 0, function () {
|
|
275
|
-
var output, startTime, file, newContent, cache, json, endTime;
|
|
276
|
-
return __generator(this, function (_a) {
|
|
277
|
-
switch (_a.label) {
|
|
278
|
-
case 0:
|
|
279
|
-
output = cmd.opts().output;
|
|
280
|
-
startTime = performance.now();
|
|
281
|
-
file = useGivenFileOrConfiguration(fileArgument);
|
|
282
|
-
return [4 /*yield*/, loadOpenApiFile(file)
|
|
283
|
-
// Replace file content with newContent
|
|
284
|
-
];
|
|
285
|
-
case 1:
|
|
286
|
-
newContent = (_a.sent()).specification;
|
|
287
|
-
cache = [];
|
|
288
|
-
json = JSON.stringify(newContent, function (key, value) {
|
|
289
|
-
if (typeof value === 'object' && value !== null) {
|
|
290
|
-
if (cache.indexOf(value) !== -1) {
|
|
291
|
-
// Circular reference found, discard key
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
// Store value in our collection
|
|
295
|
-
cache.push(value);
|
|
296
|
-
}
|
|
297
|
-
return value;
|
|
298
|
-
}, 2);
|
|
299
|
-
fs.writeFileSync(output !== null && output !== void 0 ? output : file, json, 'utf8');
|
|
300
|
-
endTime = performance.now();
|
|
301
|
-
console.log(kleur.green('OpenAPI Schema bundled'), kleur.grey("in ".concat(kleur.white("".concat(kleur.bold("".concat(Math.round(endTime - startTime))), " ms")))));
|
|
302
|
-
console.log();
|
|
303
|
-
return [2 /*return*/];
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
}); });
|
|
307
|
-
return cmd;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* True for all files ending with .yml or .yaml (case-insensitive).
|
|
312
|
-
*/
|
|
313
|
-
function isYamlFileName(fileName) {
|
|
314
|
-
if (isUrl(fileName)) {
|
|
315
|
-
return false;
|
|
316
|
-
}
|
|
317
|
-
return /\.ya?ml$/i.test(fileName);
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
function FormatCommand() {
|
|
321
|
-
var _this = this;
|
|
322
|
-
var cmd = new Command('format');
|
|
323
|
-
cmd.description('Format an OpenAPI file');
|
|
324
|
-
cmd.argument('[file|url]', 'File or URL to format');
|
|
325
|
-
cmd.option('-o, --output <file>', 'Output file');
|
|
326
|
-
cmd.action(function (inputArgument_1, _a) { return __awaiter(_this, [inputArgument_1, _a], void 0, function (inputArgument, _b) {
|
|
327
|
-
var startTime, input, specification, newContent, _c, endTime;
|
|
328
|
-
var output = _b.output;
|
|
329
|
-
return __generator(this, function (_d) {
|
|
330
|
-
switch (_d.label) {
|
|
331
|
-
case 0:
|
|
332
|
-
startTime = performance.now();
|
|
333
|
-
input = useGivenFileOrConfiguration(inputArgument);
|
|
334
|
-
return [4 /*yield*/, getFileOrUrl(input)];
|
|
335
|
-
case 1:
|
|
336
|
-
specification = _d.sent();
|
|
337
|
-
if (!specification) {
|
|
338
|
-
console.error(kleur.bold().red('[ERROR]'), kleur.red('Couldn’t read file.'));
|
|
339
|
-
process.exit(1);
|
|
340
|
-
}
|
|
341
|
-
if (!isYamlFileName(output || input)) return [3 /*break*/, 3];
|
|
342
|
-
return [4 /*yield*/, openapi().load(specification).toYaml()];
|
|
343
|
-
case 2:
|
|
344
|
-
_c = _d.sent();
|
|
345
|
-
return [3 /*break*/, 5];
|
|
346
|
-
case 3: return [4 /*yield*/, openapi().load(specification).toJson()
|
|
347
|
-
// Replace file content with newContent
|
|
348
|
-
];
|
|
349
|
-
case 4:
|
|
350
|
-
_c = _d.sent();
|
|
351
|
-
_d.label = 5;
|
|
352
|
-
case 5:
|
|
353
|
-
newContent = _c;
|
|
354
|
-
// Replace file content with newContent
|
|
355
|
-
if (output) {
|
|
356
|
-
fs.writeFileSync(output, newContent, 'utf8');
|
|
357
|
-
}
|
|
358
|
-
else if (!isUrl(input)) {
|
|
359
|
-
fs.writeFileSync(input, newContent, 'utf8');
|
|
360
|
-
}
|
|
361
|
-
else {
|
|
362
|
-
console.error(kleur.bold().red('[ERROR]'), kleur.red('Output file is required for URLs. Try passing --output file flag.'));
|
|
363
|
-
process.exit(1);
|
|
364
|
-
}
|
|
365
|
-
endTime = performance.now();
|
|
366
|
-
console.log(kleur.green('File formatted'), kleur.grey("in ".concat(kleur.white("".concat(kleur.bold("".concat(Math.round(endTime - startTime))), " ms")))));
|
|
367
|
-
console.log();
|
|
368
|
-
return [2 /*return*/];
|
|
369
|
-
}
|
|
370
|
-
});
|
|
371
|
-
}); });
|
|
372
|
-
return cmd;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
function InitCommand() {
|
|
376
|
-
var _this = this;
|
|
377
|
-
var cmd = new Command('init');
|
|
378
|
-
cmd.description('Create a new `scalar.config.json` file to configure where your OpenAPI file is placed.');
|
|
379
|
-
cmd.option('-f, --file [file]', 'your OpenAPI file');
|
|
380
|
-
cmd.option('-s, --subdomain [url]', 'subdomain to publish on');
|
|
381
|
-
cmd.option('--force', 'override existing configuration');
|
|
382
|
-
cmd.action(function (_a) { return __awaiter(_this, [_a], void 0, function (_b) {
|
|
383
|
-
// Function to validate file extension
|
|
384
|
-
function isValidFile(filePath) {
|
|
385
|
-
var validExtensions = ['.json', '.yaml', '.yml'];
|
|
386
|
-
var extension = path.extname(filePath).toLowerCase();
|
|
387
|
-
return validExtensions.includes(extension);
|
|
388
|
-
}
|
|
389
|
-
var configFile, validInput, input, nextSteps, handleCancel, shouldOverwriteExisting, _c, configuration, response, slugger, slug, validExtensions, extension, response, content;
|
|
390
|
-
var file = _b.file, subdomain = _b.subdomain, force = _b.force;
|
|
391
|
-
return __generator(this, function (_d) {
|
|
392
|
-
switch (_d.label) {
|
|
393
|
-
case 0:
|
|
394
|
-
configFile = path.resolve(CONFIG_FILE);
|
|
395
|
-
input = file;
|
|
396
|
-
nextSteps = function () {
|
|
397
|
-
console.log('What to do next:');
|
|
398
|
-
console.log(" ".concat(kleur.cyan('scalar format'), " ").concat(kleur.gray('[options] [file|url]'), " to format your OpenAPI file"));
|
|
399
|
-
console.log(" ".concat(kleur.cyan('scalar validate'), " ").concat(kleur.gray('[file|url]'), " to validate your OpenAPI file"));
|
|
400
|
-
console.log(" ".concat(kleur.cyan('scalar bundle'), " ").concat(kleur.gray('[options] [file]'), " to bundle your OpenAPI file"));
|
|
401
|
-
console.log(" ".concat(kleur.cyan('scalar serve'), " ").concat(kleur.gray('[options] [file|url]'), " to serve your OpenAPI file"));
|
|
402
|
-
console.log();
|
|
403
|
-
console.log(kleur.white("Run ".concat(kleur.magenta('scalar --help'), " to see all available commands.")));
|
|
404
|
-
};
|
|
405
|
-
handleCancel = function () {
|
|
406
|
-
cancel('Operation cancelled.');
|
|
407
|
-
nextSteps();
|
|
408
|
-
process.exit(0);
|
|
409
|
-
};
|
|
410
|
-
if (!fs.existsSync(configFile)) return [3 /*break*/, 4];
|
|
411
|
-
console.log("".concat(kleur.green('⚠'), " Found existing configuration: ").concat(kleur.reset().green("".concat(CONFIG_FILE))));
|
|
412
|
-
if (force) {
|
|
413
|
-
console.log("".concat(kleur.green('✔'), " Overwriting existing file\u2026"));
|
|
414
|
-
}
|
|
415
|
-
if (!(force !== null && force !== void 0)) return [3 /*break*/, 1];
|
|
416
|
-
_c = force;
|
|
417
|
-
return [3 /*break*/, 3];
|
|
418
|
-
case 1: return [4 /*yield*/, confirm({
|
|
419
|
-
message: 'Do you want to override the file?',
|
|
420
|
-
initialValue: false,
|
|
421
|
-
})];
|
|
422
|
-
case 2:
|
|
423
|
-
_c = (_d.sent());
|
|
424
|
-
_d.label = 3;
|
|
425
|
-
case 3:
|
|
426
|
-
shouldOverwriteExisting = _c;
|
|
427
|
-
if (isCancel(shouldOverwriteExisting)) {
|
|
428
|
-
handleCancel();
|
|
429
|
-
}
|
|
430
|
-
if (!shouldOverwriteExisting) {
|
|
431
|
-
handleCancel();
|
|
432
|
-
}
|
|
433
|
-
_d.label = 4;
|
|
434
|
-
case 4:
|
|
435
|
-
configuration = {
|
|
436
|
-
subdomain: '',
|
|
437
|
-
references: [],
|
|
438
|
-
guides: [],
|
|
439
|
-
};
|
|
440
|
-
// Subdomain
|
|
441
|
-
validInput = !!subdomain;
|
|
442
|
-
_d.label = 5;
|
|
443
|
-
case 5:
|
|
444
|
-
if (!!validInput) return [3 /*break*/, 7];
|
|
445
|
-
return [4 /*yield*/, text({
|
|
446
|
-
message: "What\u2019s the name of your project? We\u2019ll use that to create a custom subdomain for you.",
|
|
447
|
-
validate: function (value) {
|
|
448
|
-
if (value.trim().length === 0) {
|
|
449
|
-
return "You didn\u2019t provide a project name. Please provide a name!";
|
|
450
|
-
}
|
|
451
|
-
return null;
|
|
452
|
-
},
|
|
453
|
-
})
|
|
454
|
-
// TODO: Check if the subdomain is available
|
|
455
|
-
];
|
|
456
|
-
case 6:
|
|
457
|
-
response = _d.sent();
|
|
458
|
-
// TODO: Check if the subdomain is available
|
|
459
|
-
if (isCancel(response)) {
|
|
460
|
-
handleCancel();
|
|
461
|
-
}
|
|
462
|
-
else {
|
|
463
|
-
validInput = true;
|
|
464
|
-
}
|
|
465
|
-
slugger = new GithubSlugger();
|
|
466
|
-
slug = slugger.slug(response.toString());
|
|
467
|
-
// eslint-disable-next-line no-param-reassign
|
|
468
|
-
subdomain = "".concat(slug, ".apidocumentation.com");
|
|
469
|
-
console.log("".concat(kleur.green('✔'), " Subdomain: ").concat(kleur.green(subdomain)));
|
|
470
|
-
return [3 /*break*/, 5];
|
|
471
|
-
case 7:
|
|
472
|
-
configuration.subdomain = subdomain.trim();
|
|
473
|
-
// Reference
|
|
474
|
-
// Check if the file option is provided and valid
|
|
475
|
-
if (input) {
|
|
476
|
-
validExtensions = ['.json', '.yaml', '.yml'];
|
|
477
|
-
extension = path.extname(input).toLowerCase();
|
|
478
|
-
if (!validExtensions.includes(extension)) {
|
|
479
|
-
console.log(kleur.red('✖'), "Please enter a valid file path ".concat(validExtensions.join(', '), "."));
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
// Ask for the file path
|
|
483
|
-
validInput = input && isValidFile(input);
|
|
484
|
-
_d.label = 8;
|
|
485
|
-
case 8:
|
|
486
|
-
if (!!validInput) return [3 /*break*/, 10];
|
|
487
|
-
return [4 /*yield*/, text({
|
|
488
|
-
message: "Where is your OpenAPI file? ".concat(kleur.reset().grey('(Add a path to the file)')),
|
|
489
|
-
validate: function (value) {
|
|
490
|
-
if (value.length === 0)
|
|
491
|
-
return "Value is required!";
|
|
492
|
-
return null;
|
|
493
|
-
},
|
|
494
|
-
})];
|
|
495
|
-
case 9:
|
|
496
|
-
response = _d.sent();
|
|
497
|
-
input = response;
|
|
498
|
-
if (isCancel(response)) {
|
|
499
|
-
handleCancel();
|
|
500
|
-
}
|
|
501
|
-
if (isValidFile(input)) {
|
|
502
|
-
validInput = true;
|
|
503
|
-
}
|
|
504
|
-
else {
|
|
505
|
-
console.log(kleur.red('✖'), "Invalid file extension. Expected: ".concat(['.json', '.yaml', '.yml'].join(', '), "."));
|
|
506
|
-
}
|
|
507
|
-
return [3 /*break*/, 8];
|
|
508
|
-
case 10:
|
|
509
|
-
configuration.references.push({
|
|
510
|
-
name: 'API Reference',
|
|
511
|
-
path: input,
|
|
512
|
-
});
|
|
513
|
-
content = JSON.stringify(configuration, null, 2);
|
|
514
|
-
// Create `scalar.config.json` file
|
|
515
|
-
fs.writeFileSync(configFile, content);
|
|
516
|
-
console.log("".concat(kleur.green('✔'), " Configuration stored."));
|
|
517
|
-
console.log();
|
|
518
|
-
console.log("".concat(kleur.bold().green("".concat(CONFIG_FILE))));
|
|
519
|
-
console.log();
|
|
520
|
-
console.log("".concat(kleur.grey(content
|
|
521
|
-
.split('\n')
|
|
522
|
-
.map(function (line) { return " ".concat(line); })
|
|
523
|
-
.join('\n'))));
|
|
524
|
-
console.log();
|
|
525
|
-
nextSteps();
|
|
526
|
-
console.log();
|
|
527
|
-
return [2 /*return*/];
|
|
528
|
-
}
|
|
529
|
-
});
|
|
530
|
-
}); });
|
|
531
|
-
return cmd;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
function printSpecificationBanner(result) {
|
|
535
|
-
var version = result.version, schema = result.schema;
|
|
536
|
-
// Version
|
|
537
|
-
console.log(kleur.bold().white('[INFO]'), kleur.bold().white(schema.info.title), kleur.grey("(OpenAPI v".concat(version, ")")));
|
|
538
|
-
// Count number of paths
|
|
539
|
-
var pathsCount = Object.keys(schema.paths).length;
|
|
540
|
-
// Count number of operations
|
|
541
|
-
var operationsCount = Object.values(schema.paths).reduce(function (acc, path) { return acc + Object.keys(path).length; }, 0);
|
|
542
|
-
// Statistics
|
|
543
|
-
console.log(kleur.bold().white('[INFO]'), kleur.grey("".concat(pathsCount, " paths, ").concat(operationsCount, " operations")));
|
|
544
|
-
console.log();
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
function MockCommand() {
|
|
548
|
-
var _this = this;
|
|
549
|
-
var cmd = new Command('mock');
|
|
550
|
-
cmd.description('Mock an API from an OpenAPI file');
|
|
551
|
-
cmd.argument('[file|url]', 'OpenAPI file or URL to mock the server for');
|
|
552
|
-
cmd.option('-w, --watch', 'watch the file for changes');
|
|
553
|
-
cmd.option('-o, --once', 'run the server only once and exit after that');
|
|
554
|
-
cmd.option('-p, --port <port>', 'set the HTTP port for the mock server');
|
|
555
|
-
cmd.action(function (fileArgument_1, _a) { return __awaiter(_this, [fileArgument_1, _a], void 0, function (fileArgument, _b) {
|
|
556
|
-
var server, input, result, specification;
|
|
557
|
-
var _this = this;
|
|
558
|
-
var watch = _b.watch, once = _b.once, port = _b.port;
|
|
559
|
-
return __generator(this, function (_c) {
|
|
560
|
-
switch (_c.label) {
|
|
561
|
-
case 0:
|
|
562
|
-
server = null;
|
|
563
|
-
input = useGivenFileOrConfiguration(fileArgument);
|
|
564
|
-
return [4 /*yield*/, loadOpenApiFile(input)];
|
|
565
|
-
case 1:
|
|
566
|
-
result = _c.sent();
|
|
567
|
-
if (!result.valid) {
|
|
568
|
-
console.warn(kleur.bold().red('[ERROR]'), kleur.red('Invalid OpenAPI specification'));
|
|
569
|
-
return [2 /*return*/];
|
|
570
|
-
}
|
|
571
|
-
printSpecificationBanner({
|
|
572
|
-
version: result.version,
|
|
573
|
-
schema: result.schema,
|
|
574
|
-
});
|
|
575
|
-
specification = result.specification;
|
|
576
|
-
if (!watch) return [3 /*break*/, 3];
|
|
577
|
-
return [4 /*yield*/, watchFile(input, function () { return __awaiter(_this, void 0, void 0, function () {
|
|
578
|
-
var newResult, specificationHasChanged;
|
|
579
|
-
return __generator(this, function (_a) {
|
|
580
|
-
switch (_a.label) {
|
|
581
|
-
case 0: return [4 /*yield*/, loadOpenApiFile(input)];
|
|
582
|
-
case 1:
|
|
583
|
-
newResult = _a.sent();
|
|
584
|
-
specificationHasChanged = (newResult === null || newResult === void 0 ? void 0 : newResult.specification) &&
|
|
585
|
-
JSON.stringify(specification) !==
|
|
586
|
-
JSON.stringify(newResult.specification);
|
|
587
|
-
if (!specificationHasChanged) return [3 /*break*/, 3];
|
|
588
|
-
console.log(kleur.bold().white('[INFO]'), kleur.grey('OpenAPI file modified'));
|
|
589
|
-
printSpecificationBanner({
|
|
590
|
-
version: newResult.version,
|
|
591
|
-
schema: newResult.schema,
|
|
592
|
-
});
|
|
593
|
-
specification = newResult.specification;
|
|
594
|
-
// Update mock server
|
|
595
|
-
server.close();
|
|
596
|
-
return [4 /*yield*/, bootServer$1({
|
|
597
|
-
specification: specification,
|
|
598
|
-
port: port,
|
|
599
|
-
})];
|
|
600
|
-
case 2:
|
|
601
|
-
server = _a.sent();
|
|
602
|
-
_a.label = 3;
|
|
603
|
-
case 3: return [2 /*return*/];
|
|
604
|
-
}
|
|
605
|
-
});
|
|
606
|
-
}); })];
|
|
607
|
-
case 2:
|
|
608
|
-
_c.sent();
|
|
609
|
-
_c.label = 3;
|
|
610
|
-
case 3:
|
|
611
|
-
// Show all paths from the specification
|
|
612
|
-
printAvailablePaths(specification);
|
|
613
|
-
return [4 /*yield*/, bootServer$1({
|
|
614
|
-
specification: specification,
|
|
615
|
-
port: port,
|
|
616
|
-
})
|
|
617
|
-
// Exit after the first run
|
|
618
|
-
];
|
|
619
|
-
case 4:
|
|
620
|
-
// Listen for requests
|
|
621
|
-
server = _c.sent();
|
|
622
|
-
// Exit after the first run
|
|
623
|
-
if (once) {
|
|
624
|
-
setTimeout(function () {
|
|
625
|
-
server.close();
|
|
626
|
-
}, 2000);
|
|
627
|
-
}
|
|
628
|
-
return [2 /*return*/];
|
|
629
|
-
}
|
|
630
|
-
});
|
|
631
|
-
}); });
|
|
632
|
-
return cmd;
|
|
633
|
-
}
|
|
634
|
-
function bootServer$1(_a) {
|
|
635
|
-
return __awaiter(this, arguments, void 0, function (_b) {
|
|
636
|
-
var app;
|
|
637
|
-
var specification = _b.specification, port = _b.port;
|
|
638
|
-
return __generator(this, function (_c) {
|
|
639
|
-
switch (_c.label) {
|
|
640
|
-
case 0: return [4 /*yield*/, createMockServer({
|
|
641
|
-
specification: specification,
|
|
642
|
-
onRequest: onRequest,
|
|
643
|
-
})];
|
|
644
|
-
case 1:
|
|
645
|
-
app = _c.sent();
|
|
646
|
-
return [2 /*return*/, serve({
|
|
647
|
-
fetch: app.fetch,
|
|
648
|
-
port: port !== null && port !== void 0 ? port : 3000,
|
|
649
|
-
}, function (info) {
|
|
650
|
-
console.log("".concat(kleur.bold().green('➜ Mock Server'), " ").concat(kleur.white('listening on'), " ").concat(kleur.cyan("http://localhost:".concat(info.port))));
|
|
651
|
-
console.log();
|
|
652
|
-
})];
|
|
653
|
-
}
|
|
654
|
-
});
|
|
655
|
-
});
|
|
656
|
-
}
|
|
657
|
-
function printAvailablePaths(specification) {
|
|
658
|
-
var _a, _b;
|
|
659
|
-
console.log(kleur.bold().white('Available Paths'));
|
|
660
|
-
console.log();
|
|
661
|
-
if ((specification === null || specification === void 0 ? void 0 : specification.paths) === undefined ||
|
|
662
|
-
Object.keys(specification === null || specification === void 0 ? void 0 : specification.paths).length === 0) {
|
|
663
|
-
console.log(kleur.bold().yellow('[WARN]'), kleur.grey('Couldn’t find any paths in the OpenAPI file.'));
|
|
664
|
-
}
|
|
665
|
-
// loop through all paths
|
|
666
|
-
for (var path in (_a = specification === null || specification === void 0 ? void 0 : specification.paths) !== null && _a !== void 0 ? _a : []) {
|
|
667
|
-
// loop through all methods
|
|
668
|
-
for (var method in (_b = specification.paths) === null || _b === void 0 ? void 0 : _b[path]) {
|
|
669
|
-
console.log("".concat(kleur
|
|
670
|
-
.bold()[getMethodColor(method)](method.toUpperCase().padEnd(6)), " ").concat(kleur.grey("".concat(path))));
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
console.log();
|
|
674
|
-
}
|
|
675
|
-
function onRequest(_a) {
|
|
676
|
-
var context = _a.context, operation = _a.operation;
|
|
677
|
-
var method = context.req.method;
|
|
678
|
-
console.log("".concat(kleur
|
|
679
|
-
.bold()[getMethodColor(method)](method.toUpperCase().padEnd(6)), " ").concat(kleur.grey("".concat(context.req.path))), "".concat(kleur.grey('→'), " ").concat((operation === null || operation === void 0 ? void 0 : operation.operationId)
|
|
680
|
-
? kleur.white(operation.operationId)
|
|
681
|
-
: kleur.red('[ERROR] 404 Not Found')));
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
function ServeCommand() {
|
|
685
|
-
var _this = this;
|
|
686
|
-
var cmd = new Command('serve');
|
|
687
|
-
// Old name for the command
|
|
688
|
-
cmd.alias('reference');
|
|
689
|
-
cmd.description('Serve an API Reference from an OpenAPI file');
|
|
690
|
-
cmd.argument('[file|url]', 'OpenAPI file or URL to show the reference for');
|
|
691
|
-
cmd.option('-w, --watch', 'watch the file for changes');
|
|
692
|
-
cmd.option('-o, --once', 'run the server only once and exit after that');
|
|
693
|
-
cmd.option('-p, --port <port>', 'set the HTTP port for the API reference server');
|
|
694
|
-
cmd.action(function (inputArgument_1, _a) { return __awaiter(_this, [inputArgument_1, _a], void 0, function (inputArgument, _b) {
|
|
695
|
-
var input, result, specification, app, server;
|
|
696
|
-
var _this = this;
|
|
697
|
-
var watch = _b.watch, once = _b.once, port = _b.port;
|
|
698
|
-
return __generator(this, function (_c) {
|
|
699
|
-
switch (_c.label) {
|
|
700
|
-
case 0:
|
|
701
|
-
input = useGivenFileOrConfiguration(inputArgument);
|
|
702
|
-
return [4 /*yield*/, loadOpenApiFile(input)];
|
|
703
|
-
case 1:
|
|
704
|
-
result = _c.sent();
|
|
705
|
-
if (!result.valid) {
|
|
706
|
-
return [2 /*return*/];
|
|
707
|
-
}
|
|
708
|
-
specification = result.specification;
|
|
709
|
-
printSpecificationBanner({
|
|
710
|
-
version: result.version,
|
|
711
|
-
schema: result.schema,
|
|
712
|
-
});
|
|
713
|
-
if ((specification === null || specification === void 0 ? void 0 : specification.paths) === undefined ||
|
|
714
|
-
Object.keys(specification === null || specification === void 0 ? void 0 : specification.paths).length === 0) {
|
|
715
|
-
console.log(kleur.bold().yellow('[WARN]'), kleur.grey('Couldn’t find any paths in the OpenAPI file.'));
|
|
716
|
-
}
|
|
717
|
-
app = new Hono();
|
|
718
|
-
app.get('/', function (c) {
|
|
719
|
-
return c.html(getHtmlDocument(specification, watch));
|
|
720
|
-
});
|
|
721
|
-
app.use('/__watcher', function (c, next) { return __awaiter(_this, void 0, void 0, function () {
|
|
722
|
-
return __generator(this, function (_a) {
|
|
723
|
-
switch (_a.label) {
|
|
724
|
-
case 0:
|
|
725
|
-
c.header('Content-Type', 'text/event-stream');
|
|
726
|
-
c.header('Cache-Control', 'no-cache');
|
|
727
|
-
c.header('Connection', 'keep-alive');
|
|
728
|
-
return [4 /*yield*/, next()];
|
|
729
|
-
case 1:
|
|
730
|
-
_a.sent();
|
|
731
|
-
return [2 /*return*/];
|
|
732
|
-
}
|
|
733
|
-
});
|
|
734
|
-
}); });
|
|
735
|
-
app.get('/__watcher', function (c) {
|
|
736
|
-
return stream(c, function (s) { return __awaiter(_this, void 0, void 0, function () {
|
|
737
|
-
var _this = this;
|
|
738
|
-
return __generator(this, function (_a) {
|
|
739
|
-
switch (_a.label) {
|
|
740
|
-
case 0:
|
|
741
|
-
// watch file for changes
|
|
742
|
-
if (watch) {
|
|
743
|
-
watchFile(input, function () { return __awaiter(_this, void 0, void 0, function () {
|
|
744
|
-
var newResult, specificationHasChanged;
|
|
745
|
-
return __generator(this, function (_a) {
|
|
746
|
-
switch (_a.label) {
|
|
747
|
-
case 0: return [4 /*yield*/, loadOpenApiFile(input)];
|
|
748
|
-
case 1:
|
|
749
|
-
newResult = _a.sent();
|
|
750
|
-
specificationHasChanged = (newResult === null || newResult === void 0 ? void 0 : newResult.specification) &&
|
|
751
|
-
JSON.stringify(specification) !==
|
|
752
|
-
JSON.stringify(newResult.specification);
|
|
753
|
-
if (specificationHasChanged) {
|
|
754
|
-
console.log(kleur.bold().white('[INFO]'), kleur.grey('OpenAPI file modified'));
|
|
755
|
-
printSpecificationBanner({
|
|
756
|
-
version: newResult.version,
|
|
757
|
-
schema: newResult.schema,
|
|
758
|
-
});
|
|
759
|
-
specification = newResult.specification;
|
|
760
|
-
s.write('data: file modified\n\n');
|
|
761
|
-
}
|
|
762
|
-
return [2 /*return*/];
|
|
763
|
-
}
|
|
764
|
-
});
|
|
765
|
-
}); });
|
|
766
|
-
}
|
|
767
|
-
_a.label = 1;
|
|
768
|
-
case 1:
|
|
769
|
-
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 100); })];
|
|
770
|
-
case 2:
|
|
771
|
-
_a.sent();
|
|
772
|
-
return [3 /*break*/, 1];
|
|
773
|
-
case 3: return [2 /*return*/];
|
|
774
|
-
}
|
|
775
|
-
});
|
|
776
|
-
}); });
|
|
777
|
-
});
|
|
778
|
-
server = serve({
|
|
779
|
-
fetch: app.fetch,
|
|
780
|
-
port: port !== null && port !== void 0 ? port : 3000,
|
|
781
|
-
}, function (info) {
|
|
782
|
-
console.log("".concat(kleur.bold().green('➜ API Reference Server'), " ").concat(kleur.white('listening on'), " ").concat(kleur.cyan("http://localhost:".concat(info.port))));
|
|
783
|
-
console.log();
|
|
784
|
-
});
|
|
785
|
-
// Exit after the first run
|
|
786
|
-
if (once) {
|
|
787
|
-
setTimeout(function () {
|
|
788
|
-
server.close();
|
|
789
|
-
}, 2000);
|
|
790
|
-
}
|
|
791
|
-
return [2 /*return*/];
|
|
792
|
-
}
|
|
793
|
-
});
|
|
794
|
-
}); });
|
|
795
|
-
return cmd;
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
function ShareCommand() {
|
|
799
|
-
var _this = this;
|
|
800
|
-
var cmd = new Command('share');
|
|
801
|
-
cmd.description('Share an OpenAPI file');
|
|
802
|
-
cmd.argument('[file]', 'file to share');
|
|
803
|
-
cmd.option('-t, --token <token>', 'pass a token to update an existing sandbox');
|
|
804
|
-
cmd.action(function (fileArgument_1, _a) { return __awaiter(_this, [fileArgument_1, _a], void 0, function (fileArgument, _b) {
|
|
805
|
-
var file, url, _c, _d, _e, _f;
|
|
806
|
-
var _g, _h;
|
|
807
|
-
var token = _b.token;
|
|
808
|
-
return __generator(this, function (_j) {
|
|
809
|
-
switch (_j.label) {
|
|
810
|
-
case 0:
|
|
811
|
-
file = useGivenFileOrConfiguration(fileArgument);
|
|
812
|
-
url = 'https://sandbox.scalar.com/api/share' + (token ? "?token=".concat(token) : '');
|
|
813
|
-
_c = fetch;
|
|
814
|
-
_d = [url];
|
|
815
|
-
_g = {
|
|
816
|
-
method: 'POST',
|
|
817
|
-
headers: {
|
|
818
|
-
'Content-Type': 'application/json',
|
|
819
|
-
}
|
|
820
|
-
};
|
|
821
|
-
_f = (_e = JSON).stringify;
|
|
822
|
-
_h = {};
|
|
823
|
-
return [4 /*yield*/, getFileOrUrl(file)];
|
|
824
|
-
case 1:
|
|
825
|
-
_c.apply(void 0, _d.concat([(_g.body = _f.apply(_e, [(_h.content = _j.sent(),
|
|
826
|
-
_h)]),
|
|
827
|
-
_g)]))
|
|
828
|
-
.then(function (response) { return response.json(); })
|
|
829
|
-
.then(function (data) {
|
|
830
|
-
var id = data.id, newToken = data.token;
|
|
831
|
-
console.log(kleur.bold().green('Your OpenAPI file is public.'));
|
|
832
|
-
console.log();
|
|
833
|
-
console.log("".concat(kleur.green('➜'), " ").concat(kleur
|
|
834
|
-
.bold()
|
|
835
|
-
.white('API Reference:'.padEnd(14)), " ").concat(kleur.cyan("https://sandbox.scalar.com/p/".concat(id))));
|
|
836
|
-
console.log("".concat(kleur.grey('➜'), " ").concat(kleur
|
|
837
|
-
.bold()
|
|
838
|
-
.grey('Editor:'.padEnd(14)), " ").concat(kleur.cyan("https://sandbox.scalar.com/e/".concat(id))));
|
|
839
|
-
console.log();
|
|
840
|
-
console.log("".concat(kleur.grey('➜'), " ").concat(kleur
|
|
841
|
-
.bold()
|
|
842
|
-
.grey('OpenAPI JSON:'.padEnd(14)), " ").concat(kleur.cyan("https://sandbox.scalar.com/files/".concat(id, "/openapi.json"))));
|
|
843
|
-
console.log("".concat(kleur.grey('➜'), " ").concat(kleur
|
|
844
|
-
.bold()
|
|
845
|
-
.grey('OpenAPI YAML:'.padEnd(14)), " ").concat(kleur.cyan("https://sandbox.scalar.com/files/".concat(id, "/openapi.yaml"))));
|
|
846
|
-
console.log();
|
|
847
|
-
console.log(kleur.white('Use the token to update the existing sandbox:'));
|
|
848
|
-
console.log();
|
|
849
|
-
console.log("".concat(kleur.grey('$'), " ").concat(kleur.bold().white("scalar share --token=")).concat(kleur.bold().cyan("".concat(newToken)), " "));
|
|
850
|
-
console.log();
|
|
851
|
-
})
|
|
852
|
-
.catch(function (error) {
|
|
853
|
-
console.error('Failed to share the file.');
|
|
854
|
-
console.log();
|
|
855
|
-
console.error('Error:', error);
|
|
856
|
-
console.log();
|
|
857
|
-
process.exit(1);
|
|
858
|
-
});
|
|
859
|
-
return [2 /*return*/];
|
|
860
|
-
}
|
|
861
|
-
});
|
|
862
|
-
}); });
|
|
863
|
-
return cmd;
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
function ValidateCommand() {
|
|
867
|
-
var _this = this;
|
|
868
|
-
var cmd = new Command('validate');
|
|
869
|
-
cmd.description('Validate an OpenAPI file');
|
|
870
|
-
cmd.argument('[file|url]', 'File or URL to validate');
|
|
871
|
-
cmd.action(function (inputArgument) { return __awaiter(_this, void 0, void 0, function () {
|
|
872
|
-
var startTime, input, specification, result, endTime;
|
|
873
|
-
var _a;
|
|
874
|
-
return __generator(this, function (_b) {
|
|
875
|
-
switch (_b.label) {
|
|
876
|
-
case 0:
|
|
877
|
-
startTime = performance.now();
|
|
878
|
-
input = useGivenFileOrConfiguration(inputArgument);
|
|
879
|
-
return [4 /*yield*/, getFileOrUrl(input)
|
|
880
|
-
// Validate
|
|
881
|
-
];
|
|
882
|
-
case 1:
|
|
883
|
-
specification = _b.sent();
|
|
884
|
-
return [4 /*yield*/, openapi().load(specification).validate().get()];
|
|
885
|
-
case 2:
|
|
886
|
-
result = _b.sent();
|
|
887
|
-
if (result.valid) {
|
|
888
|
-
console.log(kleur.green("Matches the OpenAPI specification".concat(kleur.white(" (OpenAPI ".concat(kleur.bold(result.version), ")")))));
|
|
889
|
-
endTime = performance.now();
|
|
890
|
-
console.log();
|
|
891
|
-
console.log(kleur.green('File validated'), kleur.grey("in ".concat(kleur.white("".concat(kleur.bold("".concat(Math.round(endTime - startTime))), " ms")))));
|
|
892
|
-
console.log();
|
|
893
|
-
}
|
|
894
|
-
else {
|
|
895
|
-
console.log(prettyjson.render(result.errors));
|
|
896
|
-
console.log();
|
|
897
|
-
console.error(kleur.red('File doesn’t match the OpenAPI specification.'));
|
|
898
|
-
console.log();
|
|
899
|
-
console.error(kleur.red("".concat(kleur.bold("".concat((_a = result.errors) === null || _a === void 0 ? void 0 : _a.length, " error").concat(result.errors && result.errors.length > 1 ? 's' : '')), " found.")));
|
|
900
|
-
console.log();
|
|
901
|
-
process.exit(1);
|
|
902
|
-
}
|
|
903
|
-
return [2 /*return*/];
|
|
904
|
-
}
|
|
905
|
-
});
|
|
906
|
-
}); });
|
|
907
|
-
return cmd;
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
function VoidCommand() {
|
|
911
|
-
var _this = this;
|
|
912
|
-
var cmd = new Command('void');
|
|
913
|
-
cmd.description('Boot a server to mirror HTTP requests');
|
|
914
|
-
cmd.option('-o, --once', 'run the server only once and exit after that');
|
|
915
|
-
cmd.option('-p, --port <port>', 'set the HTTP port for the mock server');
|
|
916
|
-
cmd.action(function (_a) { return __awaiter(_this, [_a], void 0, function (_b) {
|
|
917
|
-
var server;
|
|
918
|
-
var once = _b.once, port = _b.port;
|
|
919
|
-
return __generator(this, function (_c) {
|
|
920
|
-
switch (_c.label) {
|
|
921
|
-
case 0:
|
|
922
|
-
server = null;
|
|
923
|
-
return [4 /*yield*/, bootServer({
|
|
924
|
-
port: port,
|
|
925
|
-
})
|
|
926
|
-
// Exit after the first run
|
|
927
|
-
];
|
|
928
|
-
case 1:
|
|
929
|
-
// Listen for requests
|
|
930
|
-
server = _c.sent();
|
|
931
|
-
// Exit after the first run
|
|
932
|
-
if (once) {
|
|
933
|
-
setTimeout(function () {
|
|
934
|
-
server.close();
|
|
935
|
-
}, 2000);
|
|
936
|
-
}
|
|
937
|
-
return [2 /*return*/];
|
|
938
|
-
}
|
|
939
|
-
});
|
|
940
|
-
}); });
|
|
941
|
-
return cmd;
|
|
942
|
-
}
|
|
943
|
-
function bootServer(_a) {
|
|
944
|
-
return __awaiter(this, arguments, void 0, function (_b) {
|
|
945
|
-
var app;
|
|
946
|
-
var port = _b.port;
|
|
947
|
-
return __generator(this, function (_c) {
|
|
948
|
-
switch (_c.label) {
|
|
949
|
-
case 0: return [4 /*yield*/, createVoidServer()];
|
|
950
|
-
case 1:
|
|
951
|
-
app = _c.sent();
|
|
952
|
-
return [2 /*return*/, serve({
|
|
953
|
-
fetch: app.fetch,
|
|
954
|
-
port: port !== null && port !== void 0 ? port : 3000,
|
|
955
|
-
}, function (info) {
|
|
956
|
-
console.log("".concat(kleur.bold().green('➜ Void Server'), " ").concat(kleur.white('listening on'), " ").concat(kleur.cyan("http://localhost:".concat(info.port))));
|
|
957
|
-
console.log();
|
|
958
|
-
})];
|
|
959
|
-
}
|
|
960
|
-
});
|
|
961
|
-
});
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
var program = new Command();
|
|
3
|
+
import { version } from './package.json.js';
|
|
4
|
+
import { InitCommand } from './commands/init/InitCommand.js';
|
|
5
|
+
import { FormatCommand } from './commands/format/FormatCommand.js';
|
|
6
|
+
import { ValidateCommand } from './commands/validate/ValidateCommand.js';
|
|
7
|
+
import { BundleCommand } from './commands/bundle/BundleCommand.js';
|
|
8
|
+
import { ServeCommand } from './commands/serve/ServeCommand.js';
|
|
9
|
+
import { MockCommand } from './commands/mock/MockCommand.js';
|
|
10
|
+
import { VoidCommand } from './commands/void/VoidCommand.js';
|
|
11
|
+
import { ShareCommand } from './commands/share/ShareCommand.js';
|
|
12
|
+
|
|
13
|
+
const program = new Command();
|
|
965
14
|
program
|
|
966
15
|
.name('@scalar/cli')
|
|
967
16
|
.description('CLI to work with your OpenAPI files')
|