@scalar/cli 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +70 -7
- package/dist/index.js +337 -262
- package/dist/package.json +23 -22
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/vite.config.d.ts +2 -0
- package/dist/vite.config.js +12 -0
- package/package.json +22 -21
package/dist/index.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
|
-
import fs from 'node:fs';
|
|
4
3
|
import kleur from 'kleur';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import { openapi } from '@scalar/openapi-parser';
|
|
6
|
+
import watcher from '@parcel/watcher';
|
|
7
|
+
import path from 'node:path';
|
|
5
8
|
import { format } from 'prettier';
|
|
6
|
-
import { Validator } from '@seriousme/openapi-schema-validator';
|
|
7
|
-
import toml from 'toml-js';
|
|
8
9
|
import prompts from 'prompts';
|
|
9
10
|
import { serve } from '@hono/node-server';
|
|
10
|
-
import {
|
|
11
|
+
import { createMockServer } from '@scalar/mock-server';
|
|
11
12
|
import { Hono } from 'hono';
|
|
12
13
|
import { stream } from 'hono/streaming';
|
|
13
14
|
import prettyjson from 'prettyjson';
|
|
14
15
|
|
|
15
|
-
var version = "0.1
|
|
16
|
+
var version = "0.2.1";
|
|
16
17
|
|
|
17
18
|
/******************************************************************************
|
|
18
19
|
Copyright (c) Microsoft Corporation.
|
|
@@ -93,49 +94,19 @@ function getMethodColor(method) {
|
|
|
93
94
|
return (_a = colors[method.toLowerCase()]) !== null && _a !== void 0 ? _a : 'grey';
|
|
94
95
|
}
|
|
95
96
|
|
|
96
|
-
function getOperationByMethodAndPath(schema, method, path) {
|
|
97
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
98
|
-
// Compare just the strings
|
|
99
|
-
if ((_b = (_a = schema.paths) === null || _a === void 0 ? void 0 : _a[path]) === null || _b === void 0 ? void 0 : _b[method.toLowerCase()]) {
|
|
100
|
-
return (_d = (_c = schema.paths) === null || _c === void 0 ? void 0 : _c[path]) === null || _d === void 0 ? void 0 : _d[method.toLowerCase()];
|
|
101
|
-
}
|
|
102
|
-
// Loop through all pathRegex and find the one where the regex matches the path
|
|
103
|
-
// Create a Regex for all paths with variables
|
|
104
|
-
var pathRegex = Object.keys((_e = schema.paths) !== null && _e !== void 0 ? _e : {})
|
|
105
|
-
.filter(function (path) {
|
|
106
|
-
return path.includes('{');
|
|
107
|
-
})
|
|
108
|
-
.map(function (operationPath) {
|
|
109
|
-
return {
|
|
110
|
-
path: operationPath,
|
|
111
|
-
regex: new RegExp(operationPath.replace(/{([^}]+)}/g, function (_, name) { return "(?<".concat(name, ">[^/]+)"); })),
|
|
112
|
-
};
|
|
113
|
-
});
|
|
114
|
-
// Find a Regex that matches the given path
|
|
115
|
-
var matchedPath = pathRegex.find(function (_a) {
|
|
116
|
-
var regex = _a.regex;
|
|
117
|
-
return regex.test(path);
|
|
118
|
-
});
|
|
119
|
-
// Return the operation
|
|
120
|
-
if (matchedPath === null || matchedPath === void 0 ? void 0 : matchedPath.path) {
|
|
121
|
-
return (_g = (_f = schema.paths) === null || _f === void 0 ? void 0 : _f[matchedPath === null || matchedPath === void 0 ? void 0 : matchedPath.path]) === null || _g === void 0 ? void 0 : _g[method.toLowerCase()];
|
|
122
|
-
}
|
|
123
|
-
return null;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
97
|
function loadOpenApiFile(file) {
|
|
127
98
|
return __awaiter(this, void 0, void 0, function () {
|
|
128
|
-
var
|
|
99
|
+
var specification, result, valid, version, schema, pathsCount, operationsCount, path, method;
|
|
129
100
|
return __generator(this, function (_a) {
|
|
130
101
|
switch (_a.label) {
|
|
131
102
|
case 0:
|
|
132
|
-
|
|
133
|
-
return [4 /*yield*/,
|
|
103
|
+
specification = fs.readFileSync(file, 'utf8');
|
|
104
|
+
return [4 /*yield*/, openapi().load(specification).resolve()];
|
|
134
105
|
case 1:
|
|
135
106
|
result = _a.sent();
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
console.log(kleur.bold().white('[INFO]'), kleur.bold().white(schema.info.title), kleur.grey("(OpenAPI v".concat(
|
|
107
|
+
valid = result.valid, version = result.version, schema = result.schema;
|
|
108
|
+
if (valid) {
|
|
109
|
+
console.log(kleur.bold().white('[INFO]'), kleur.bold().white(schema.info.title), kleur.grey("(OpenAPI v".concat(version, ")")));
|
|
139
110
|
pathsCount = Object.keys(schema.paths).length;
|
|
140
111
|
operationsCount = 0;
|
|
141
112
|
for (path in schema.paths) {
|
|
@@ -150,7 +121,7 @@ function loadOpenApiFile(file) {
|
|
|
150
121
|
console.warn(kleur.bold().yellow('[WARN]'), kleur.yellow('File doesn’t match the OpenAPI specification.'));
|
|
151
122
|
console.log();
|
|
152
123
|
}
|
|
153
|
-
return [2 /*return*/,
|
|
124
|
+
return [2 /*return*/, result];
|
|
154
125
|
}
|
|
155
126
|
});
|
|
156
127
|
});
|
|
@@ -158,6 +129,9 @@ function loadOpenApiFile(file) {
|
|
|
158
129
|
|
|
159
130
|
function readFile(file) {
|
|
160
131
|
try {
|
|
132
|
+
if (fs.existsSync(file) === false) {
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
161
135
|
return fs.readFileSync(file, 'utf8');
|
|
162
136
|
}
|
|
163
137
|
catch (err) {
|
|
@@ -165,6 +139,7 @@ function readFile(file) {
|
|
|
165
139
|
}
|
|
166
140
|
}
|
|
167
141
|
|
|
142
|
+
var CONFIG_FILE = 'scalar.config.json';
|
|
168
143
|
function useGivenFileOrConfiguration(file) {
|
|
169
144
|
var _a;
|
|
170
145
|
// If a specific file is given, use it.
|
|
@@ -173,7 +148,9 @@ function useGivenFileOrConfiguration(file) {
|
|
|
173
148
|
}
|
|
174
149
|
// Try to load the configuration
|
|
175
150
|
try {
|
|
176
|
-
|
|
151
|
+
// check if file exists
|
|
152
|
+
var content = readFile(CONFIG_FILE);
|
|
153
|
+
var configuration = JSON.parse(content);
|
|
177
154
|
if ((_a = configuration === null || configuration === void 0 ? void 0 : configuration.reference) === null || _a === void 0 ? void 0 : _a.file) {
|
|
178
155
|
return configuration.reference.file;
|
|
179
156
|
}
|
|
@@ -186,6 +163,86 @@ function useGivenFileOrConfiguration(file) {
|
|
|
186
163
|
process.exit(1);
|
|
187
164
|
}
|
|
188
165
|
|
|
166
|
+
/**
|
|
167
|
+
* Watch a foobar for changes and call a callback when it does.
|
|
168
|
+
*/
|
|
169
|
+
function watchFile(file, callback, options) {
|
|
170
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
171
|
+
var absoluteFilePath;
|
|
172
|
+
return __generator(this, function (_a) {
|
|
173
|
+
switch (_a.label) {
|
|
174
|
+
case 0:
|
|
175
|
+
absoluteFilePath = path.join(process.cwd(), file);
|
|
176
|
+
// Check if file exists
|
|
177
|
+
if (!fs.existsSync(absoluteFilePath)) {
|
|
178
|
+
throw new Error("File ".concat(absoluteFilePath, " does not exist"));
|
|
179
|
+
}
|
|
180
|
+
// Watch the file for changes
|
|
181
|
+
console.log("[INFO] Watch ".concat(file));
|
|
182
|
+
// Start the watcher
|
|
183
|
+
return [4 /*yield*/, watcher.subscribe(process.cwd(), function (err, events) {
|
|
184
|
+
// Match the file path
|
|
185
|
+
if (events.some(function (event) { return event.path === absoluteFilePath; })) {
|
|
186
|
+
callback();
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
// Call the callback immediately
|
|
190
|
+
];
|
|
191
|
+
case 1:
|
|
192
|
+
// Start the watcher
|
|
193
|
+
_a.sent();
|
|
194
|
+
// Call the callback immediately
|
|
195
|
+
if (options === null || options === void 0 ? void 0 : options.immediate) {
|
|
196
|
+
callback();
|
|
197
|
+
}
|
|
198
|
+
return [2 /*return*/];
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function BundleCommand() {
|
|
205
|
+
var _this = this;
|
|
206
|
+
var cmd = new Command('bundle');
|
|
207
|
+
cmd.description('Resolve all references in an OpenAPI file');
|
|
208
|
+
cmd.argument('[file]', 'file to bundle');
|
|
209
|
+
cmd.option('-o, --output <file>', 'output file');
|
|
210
|
+
cmd.action(function (fileArgument) { return __awaiter(_this, void 0, void 0, function () {
|
|
211
|
+
var output, startTime, file, newContent, cache, json, endTime;
|
|
212
|
+
return __generator(this, function (_a) {
|
|
213
|
+
switch (_a.label) {
|
|
214
|
+
case 0:
|
|
215
|
+
output = cmd.opts().output;
|
|
216
|
+
startTime = performance.now();
|
|
217
|
+
file = useGivenFileOrConfiguration(fileArgument);
|
|
218
|
+
return [4 /*yield*/, loadOpenApiFile(file)
|
|
219
|
+
// Replace file content with newContent
|
|
220
|
+
];
|
|
221
|
+
case 1:
|
|
222
|
+
newContent = (_a.sent()).specification;
|
|
223
|
+
cache = [];
|
|
224
|
+
json = JSON.stringify(newContent, function (key, value) {
|
|
225
|
+
if (typeof value === 'object' && value !== null) {
|
|
226
|
+
if (cache.indexOf(value) !== -1) {
|
|
227
|
+
// Circular reference found, discard key
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
// Store value in our collection
|
|
231
|
+
cache.push(value);
|
|
232
|
+
}
|
|
233
|
+
return value;
|
|
234
|
+
}, 2);
|
|
235
|
+
fs.writeFileSync(output !== null && output !== void 0 ? output : file, json, 'utf8');
|
|
236
|
+
endTime = performance.now();
|
|
237
|
+
console.log(kleur.green('OpenAPI Schema bundled'), kleur.grey("in ".concat(kleur.white("".concat(kleur.bold("".concat(Math.round(endTime - startTime))), " ms")))));
|
|
238
|
+
console.log();
|
|
239
|
+
return [2 /*return*/];
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}); });
|
|
243
|
+
return cmd;
|
|
244
|
+
}
|
|
245
|
+
|
|
189
246
|
function FormatCommand() {
|
|
190
247
|
var _this = this;
|
|
191
248
|
var cmd = new Command('format');
|
|
@@ -226,79 +283,81 @@ function FormatCommand() {
|
|
|
226
283
|
function InitCommand() {
|
|
227
284
|
var _this = this;
|
|
228
285
|
var cmd = new Command('init');
|
|
229
|
-
cmd.description('Create a new `scalar.
|
|
286
|
+
cmd.description('Create a new `scalar.config.json` file to configure where your OpenAPI file is placed.');
|
|
230
287
|
cmd.option('-f, --file [file]', 'your OpenAPI file');
|
|
231
|
-
cmd.action(function (_a) {
|
|
232
|
-
var
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
})];
|
|
249
|
-
case 1:
|
|
250
|
-
overwrite = (_c.sent()).overwrite;
|
|
251
|
-
if (overwrite === false) {
|
|
252
|
-
console.log();
|
|
253
|
-
process.exit(1);
|
|
254
|
-
}
|
|
255
|
-
_c.label = 2;
|
|
256
|
-
case 2:
|
|
257
|
-
configuration = {
|
|
258
|
-
reference: { file: '' },
|
|
259
|
-
};
|
|
260
|
-
if (!file) return [3 /*break*/, 3];
|
|
261
|
-
_b = {
|
|
262
|
-
input: file,
|
|
263
|
-
};
|
|
264
|
-
return [3 /*break*/, 5];
|
|
265
|
-
case 3: return [4 /*yield*/, prompts({
|
|
266
|
-
type: 'text',
|
|
267
|
-
name: 'input',
|
|
268
|
-
message: 'Where is your OpenAPI file?',
|
|
269
|
-
initial: './openapi.json',
|
|
270
|
-
validate: function (input) {
|
|
271
|
-
return fs.existsSync(input) ? true : 'File doesn’t exist.';
|
|
272
|
-
},
|
|
288
|
+
cmd.action(function (_a) { return __awaiter(_this, [_a], void 0, function (_b) {
|
|
289
|
+
var configFile, overwrite, configuration, input, _c, content;
|
|
290
|
+
var file = _b.file;
|
|
291
|
+
return __generator(this, function (_d) {
|
|
292
|
+
switch (_d.label) {
|
|
293
|
+
case 0:
|
|
294
|
+
configFile = path.resolve(CONFIG_FILE);
|
|
295
|
+
if (!fs.existsSync(configFile)) return [3 /*break*/, 2];
|
|
296
|
+
console.warn(kleur.yellow("A ".concat(CONFIG_FILE, " file already exists.")));
|
|
297
|
+
console.log();
|
|
298
|
+
return [4 /*yield*/, prompts({
|
|
299
|
+
type: 'toggle',
|
|
300
|
+
name: 'overwrite',
|
|
301
|
+
message: 'Do you want to override the file?',
|
|
302
|
+
initial: false,
|
|
303
|
+
active: 'yes',
|
|
304
|
+
inactive: 'no',
|
|
273
305
|
})];
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
case 5:
|
|
278
|
-
input = (_b).input;
|
|
279
|
-
configuration.reference.file = input;
|
|
280
|
-
content = toml.dump(configuration);
|
|
281
|
-
console.log();
|
|
282
|
-
console.log(kleur.bold().white(' scalar.toml'));
|
|
283
|
-
console.log();
|
|
284
|
-
console.log(content
|
|
285
|
-
.trim()
|
|
286
|
-
.split('\n')
|
|
287
|
-
.map(function (line) { return kleur.grey(" ".concat(line)); })
|
|
288
|
-
.join('\n'));
|
|
289
|
-
console.log();
|
|
290
|
-
// Create `scalar.toml` file
|
|
291
|
-
fs.writeFileSync('scalar.toml', content);
|
|
292
|
-
console.log(kleur.green('Created a new project configuration.'));
|
|
293
|
-
console.log(kleur.white("Run ".concat(kleur
|
|
294
|
-
.grey()
|
|
295
|
-
.bold('scalar --help'), " to see all available commands.")));
|
|
306
|
+
case 1:
|
|
307
|
+
overwrite = (_d.sent()).overwrite;
|
|
308
|
+
if (overwrite === false) {
|
|
296
309
|
console.log();
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
310
|
+
process.exit(1);
|
|
311
|
+
}
|
|
312
|
+
_d.label = 2;
|
|
313
|
+
case 2:
|
|
314
|
+
configuration = {
|
|
315
|
+
references: [],
|
|
316
|
+
};
|
|
317
|
+
if (!file) return [3 /*break*/, 3];
|
|
318
|
+
_c = {
|
|
319
|
+
input: file,
|
|
320
|
+
};
|
|
321
|
+
return [3 /*break*/, 5];
|
|
322
|
+
case 3: return [4 /*yield*/, prompts({
|
|
323
|
+
type: 'text',
|
|
324
|
+
name: 'input',
|
|
325
|
+
message: 'Where is your OpenAPI file?',
|
|
326
|
+
initial: './openapi.json',
|
|
327
|
+
validate: function (input) {
|
|
328
|
+
return fs.existsSync(input) ? true : 'File doesn’t exist.';
|
|
329
|
+
},
|
|
330
|
+
})];
|
|
331
|
+
case 4:
|
|
332
|
+
_c = _d.sent();
|
|
333
|
+
_d.label = 5;
|
|
334
|
+
case 5:
|
|
335
|
+
input = (_c).input;
|
|
336
|
+
configuration.references.push({
|
|
337
|
+
name: 'API Reference',
|
|
338
|
+
path: input,
|
|
339
|
+
});
|
|
340
|
+
content = JSON.stringify(configuration, null, 2);
|
|
341
|
+
console.log();
|
|
342
|
+
console.log(kleur.bold().white(" ".concat(CONFIG_FILE)));
|
|
343
|
+
console.log();
|
|
344
|
+
console.log(content
|
|
345
|
+
.trim()
|
|
346
|
+
.split('\n')
|
|
347
|
+
.map(function (line) { return kleur.grey(" ".concat(line)); })
|
|
348
|
+
.join('\n'));
|
|
349
|
+
console.log();
|
|
350
|
+
// Create `scalar.config.json` file
|
|
351
|
+
fs.writeFileSync(configFile, content);
|
|
352
|
+
console.log(kleur.green('Created a new project configuration.'));
|
|
353
|
+
console.log(kleur.white("Run ".concat(kleur
|
|
354
|
+
.grey()
|
|
355
|
+
.bold('scalar --help'), " to see all available commands.")));
|
|
356
|
+
console.log();
|
|
357
|
+
return [2 /*return*/];
|
|
358
|
+
}
|
|
300
359
|
});
|
|
301
|
-
});
|
|
360
|
+
}); });
|
|
302
361
|
return cmd;
|
|
303
362
|
}
|
|
304
363
|
|
|
@@ -309,87 +368,107 @@ function MockCommand() {
|
|
|
309
368
|
cmd.argument('[file]', 'OpenAPI file to mock the server for');
|
|
310
369
|
cmd.option('-w, --watch', 'watch the file for changes');
|
|
311
370
|
cmd.option('-p, --port <port>', 'set the HTTP port for the mock server');
|
|
312
|
-
cmd.action(function (
|
|
313
|
-
var
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
return c.json(response);
|
|
379
|
-
});
|
|
380
|
-
serve({
|
|
371
|
+
cmd.action(function (fileArgument_1, _a) { return __awaiter(_this, [fileArgument_1, _a], void 0, function (fileArgument, _b) {
|
|
372
|
+
var server, file, specification;
|
|
373
|
+
var _this = this;
|
|
374
|
+
var watch = _b.watch, port = _b.port;
|
|
375
|
+
return __generator(this, function (_c) {
|
|
376
|
+
switch (_c.label) {
|
|
377
|
+
case 0:
|
|
378
|
+
server = null;
|
|
379
|
+
file = useGivenFileOrConfiguration(fileArgument);
|
|
380
|
+
return [4 /*yield*/, loadOpenApiFile(file)
|
|
381
|
+
// Watch OpenAPI file for changes
|
|
382
|
+
];
|
|
383
|
+
case 1:
|
|
384
|
+
specification = (_c.sent()).specification;
|
|
385
|
+
if (!watch) return [3 /*break*/, 3];
|
|
386
|
+
return [4 /*yield*/, watchFile(file, function () { return __awaiter(_this, void 0, void 0, function () {
|
|
387
|
+
return __generator(this, function (_a) {
|
|
388
|
+
switch (_a.label) {
|
|
389
|
+
case 0:
|
|
390
|
+
console.log(kleur.bold().white('[INFO]'), kleur.grey('Mock Server was updated.'));
|
|
391
|
+
return [4 /*yield*/, loadOpenApiFile(file)];
|
|
392
|
+
case 1:
|
|
393
|
+
specification = (_a.sent()).specification;
|
|
394
|
+
server.close();
|
|
395
|
+
return [4 /*yield*/, bootServer({
|
|
396
|
+
specification: specification,
|
|
397
|
+
port: port,
|
|
398
|
+
})];
|
|
399
|
+
case 2:
|
|
400
|
+
server = _a.sent();
|
|
401
|
+
return [2 /*return*/];
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
}); })];
|
|
405
|
+
case 2:
|
|
406
|
+
_c.sent();
|
|
407
|
+
_c.label = 3;
|
|
408
|
+
case 3:
|
|
409
|
+
// Show all paths from the specification
|
|
410
|
+
printAvailablePaths(specification);
|
|
411
|
+
return [4 /*yield*/, bootServer({
|
|
412
|
+
specification: specification,
|
|
413
|
+
port: port,
|
|
414
|
+
})];
|
|
415
|
+
case 4:
|
|
416
|
+
// Listen for requests
|
|
417
|
+
server = _c.sent();
|
|
418
|
+
return [2 /*return*/];
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
}); });
|
|
422
|
+
return cmd;
|
|
423
|
+
}
|
|
424
|
+
function bootServer(_a) {
|
|
425
|
+
return __awaiter(this, arguments, void 0, function (_b) {
|
|
426
|
+
var app;
|
|
427
|
+
var specification = _b.specification, port = _b.port;
|
|
428
|
+
return __generator(this, function (_c) {
|
|
429
|
+
switch (_c.label) {
|
|
430
|
+
case 0: return [4 /*yield*/, createMockServer({
|
|
431
|
+
specification: specification,
|
|
432
|
+
onRequest: onRequest,
|
|
433
|
+
})];
|
|
434
|
+
case 1:
|
|
435
|
+
app = _c.sent();
|
|
436
|
+
return [2 /*return*/, serve({
|
|
381
437
|
fetch: app.fetch,
|
|
382
438
|
port: port !== null && port !== void 0 ? port : 3000,
|
|
383
439
|
}, function (info) {
|
|
384
440
|
console.log("".concat(kleur.bold().green('➜ Mock Server'), " ").concat(kleur.white('listening on'), " ").concat(kleur.cyan("http://localhost:".concat(info.port))));
|
|
385
441
|
console.log();
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
}
|
|
389
|
-
});
|
|
442
|
+
})];
|
|
443
|
+
}
|
|
390
444
|
});
|
|
391
445
|
});
|
|
392
|
-
|
|
446
|
+
}
|
|
447
|
+
function printAvailablePaths(specification) {
|
|
448
|
+
var _a, _b;
|
|
449
|
+
console.log(kleur.bold().white('Available Paths'));
|
|
450
|
+
console.log();
|
|
451
|
+
if ((specification === null || specification === void 0 ? void 0 : specification.paths) === undefined ||
|
|
452
|
+
Object.keys(specification === null || specification === void 0 ? void 0 : specification.paths).length === 0) {
|
|
453
|
+
console.log(kleur.bold().yellow('[WARN]'), kleur.grey('Couldn’t find any paths in the OpenAPI file.'));
|
|
454
|
+
}
|
|
455
|
+
// loop through all paths
|
|
456
|
+
for (var path in (_a = specification === null || specification === void 0 ? void 0 : specification.paths) !== null && _a !== void 0 ? _a : []) {
|
|
457
|
+
// loop through all methods
|
|
458
|
+
for (var method in (_b = specification.paths) === null || _b === void 0 ? void 0 : _b[path]) {
|
|
459
|
+
console.log("".concat(kleur
|
|
460
|
+
.bold()[getMethodColor(method)](method.toUpperCase().padEnd(6)), " ").concat(kleur.grey("".concat(path))));
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
console.log();
|
|
464
|
+
}
|
|
465
|
+
function onRequest(_a) {
|
|
466
|
+
var context = _a.context, operation = _a.operation;
|
|
467
|
+
var method = context.req.method;
|
|
468
|
+
console.log("".concat(kleur
|
|
469
|
+
.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)
|
|
470
|
+
? kleur.white(operation.operationId)
|
|
471
|
+
: kleur.red('[ERROR] 404 Not Found')));
|
|
393
472
|
}
|
|
394
473
|
|
|
395
474
|
function ReferenceCommand() {
|
|
@@ -399,88 +478,83 @@ function ReferenceCommand() {
|
|
|
399
478
|
cmd.argument('[file]', 'OpenAPI file to show the reference for');
|
|
400
479
|
cmd.option('-w, --watch', 'watch the file for changes');
|
|
401
480
|
cmd.option('-p, --port <port>', 'set the HTTP port for the API reference server');
|
|
402
|
-
cmd.action(function (
|
|
403
|
-
var
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
481
|
+
cmd.action(function (fileArgument_1, _a) { return __awaiter(_this, [fileArgument_1, _a], void 0, function (fileArgument, _b) {
|
|
482
|
+
var file, specification, app;
|
|
483
|
+
var _this = this;
|
|
484
|
+
var watch = _b.watch, port = _b.port;
|
|
485
|
+
return __generator(this, function (_c) {
|
|
486
|
+
switch (_c.label) {
|
|
487
|
+
case 0:
|
|
488
|
+
file = useGivenFileOrConfiguration(fileArgument);
|
|
489
|
+
return [4 /*yield*/, loadOpenApiFile(file)];
|
|
490
|
+
case 1:
|
|
491
|
+
specification = (_c.sent()).specification;
|
|
492
|
+
if ((specification === null || specification === void 0 ? void 0 : specification.paths) === undefined ||
|
|
493
|
+
Object.keys(specification === null || specification === void 0 ? void 0 : specification.paths).length === 0) {
|
|
494
|
+
console.log(kleur.bold().yellow('[WARN]'), kleur.grey('Couldn’t find any paths in the OpenAPI file.'));
|
|
495
|
+
}
|
|
496
|
+
app = new Hono();
|
|
497
|
+
app.get('/', function (c) {
|
|
498
|
+
return c.html(getHtmlDocument(specification, watch));
|
|
499
|
+
});
|
|
500
|
+
app.use('/__watcher', function (c, next) { return __awaiter(_this, void 0, void 0, function () {
|
|
501
|
+
return __generator(this, function (_a) {
|
|
502
|
+
switch (_a.label) {
|
|
503
|
+
case 0:
|
|
504
|
+
c.header('Content-Type', 'text/event-stream');
|
|
505
|
+
c.header('Cache-Control', 'no-cache');
|
|
506
|
+
c.header('Connection', 'keep-alive');
|
|
507
|
+
return [4 /*yield*/, next()];
|
|
508
|
+
case 1:
|
|
509
|
+
_a.sent();
|
|
510
|
+
return [2 /*return*/];
|
|
511
|
+
}
|
|
422
512
|
});
|
|
423
|
-
|
|
513
|
+
}); });
|
|
514
|
+
app.get('/__watcher', function (c) {
|
|
515
|
+
return stream(c, function (stream) { return __awaiter(_this, void 0, void 0, function () {
|
|
516
|
+
var _this = this;
|
|
424
517
|
return __generator(this, function (_a) {
|
|
425
518
|
switch (_a.label) {
|
|
426
519
|
case 0:
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
520
|
+
// watch file for changes
|
|
521
|
+
if (watch) {
|
|
522
|
+
watchFile(file, function () { return __awaiter(_this, void 0, void 0, function () {
|
|
523
|
+
return __generator(this, function (_a) {
|
|
524
|
+
switch (_a.label) {
|
|
525
|
+
case 0:
|
|
526
|
+
console.log(kleur.bold().white('[INFO]'), kleur.grey('OpenAPI file modified'));
|
|
527
|
+
return [4 /*yield*/, loadOpenApiFile(file)];
|
|
528
|
+
case 1:
|
|
529
|
+
specification = (_a.sent()).specification;
|
|
530
|
+
stream.write('data: file modified\n\n');
|
|
531
|
+
return [2 /*return*/];
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
}); });
|
|
535
|
+
}
|
|
536
|
+
_a.label = 1;
|
|
431
537
|
case 1:
|
|
538
|
+
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 100); })];
|
|
539
|
+
case 2:
|
|
432
540
|
_a.sent();
|
|
433
|
-
return [
|
|
541
|
+
return [3 /*break*/, 1];
|
|
542
|
+
case 3: return [2 /*return*/];
|
|
434
543
|
}
|
|
435
544
|
});
|
|
436
545
|
}); });
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
return __generator(this, function (_a) {
|
|
448
|
-
switch (_a.label) {
|
|
449
|
-
case 0:
|
|
450
|
-
console.log(kleur.bold().white('[INFO]'), kleur.grey('OpenAPI file modified'));
|
|
451
|
-
return [4 /*yield*/, loadOpenApiFile(file)];
|
|
452
|
-
case 1:
|
|
453
|
-
specification = (_a.sent())
|
|
454
|
-
.specification;
|
|
455
|
-
stream.write('data: file modified\n\n');
|
|
456
|
-
return [2 /*return*/];
|
|
457
|
-
}
|
|
458
|
-
});
|
|
459
|
-
}); });
|
|
460
|
-
}
|
|
461
|
-
_a.label = 1;
|
|
462
|
-
case 1:
|
|
463
|
-
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 100); })];
|
|
464
|
-
case 2:
|
|
465
|
-
_a.sent();
|
|
466
|
-
return [3 /*break*/, 1];
|
|
467
|
-
case 3: return [2 /*return*/];
|
|
468
|
-
}
|
|
469
|
-
});
|
|
470
|
-
}); });
|
|
471
|
-
});
|
|
472
|
-
serve({
|
|
473
|
-
fetch: app.fetch,
|
|
474
|
-
port: port !== null && port !== void 0 ? port : 3000,
|
|
475
|
-
}, function (info) {
|
|
476
|
-
console.log("".concat(kleur.bold().green('➜ API Reference Server'), " ").concat(kleur.white('listening on'), " ").concat(kleur.cyan("http://localhost:".concat(info.port))));
|
|
477
|
-
console.log();
|
|
478
|
-
});
|
|
479
|
-
return [2 /*return*/];
|
|
480
|
-
}
|
|
481
|
-
});
|
|
546
|
+
});
|
|
547
|
+
serve({
|
|
548
|
+
fetch: app.fetch,
|
|
549
|
+
port: port !== null && port !== void 0 ? port : 3000,
|
|
550
|
+
}, function (info) {
|
|
551
|
+
console.log("".concat(kleur.bold().green('➜ API Reference Server'), " ").concat(kleur.white('listening on'), " ").concat(kleur.cyan("http://localhost:".concat(info.port))));
|
|
552
|
+
console.log();
|
|
553
|
+
});
|
|
554
|
+
return [2 /*return*/];
|
|
555
|
+
}
|
|
482
556
|
});
|
|
483
|
-
});
|
|
557
|
+
}); });
|
|
484
558
|
return cmd;
|
|
485
559
|
}
|
|
486
560
|
|
|
@@ -541,19 +615,19 @@ function ValidateCommand() {
|
|
|
541
615
|
cmd.description('Validate an OpenAPI file');
|
|
542
616
|
cmd.argument('[file]', 'file to validate');
|
|
543
617
|
cmd.action(function (fileArgument) { return __awaiter(_this, void 0, void 0, function () {
|
|
544
|
-
var startTime, file,
|
|
618
|
+
var startTime, file, specification, result, endTime;
|
|
545
619
|
var _a;
|
|
546
620
|
return __generator(this, function (_b) {
|
|
547
621
|
switch (_b.label) {
|
|
548
622
|
case 0:
|
|
549
623
|
startTime = performance.now();
|
|
550
624
|
file = useGivenFileOrConfiguration(fileArgument);
|
|
551
|
-
|
|
552
|
-
return [4 /*yield*/,
|
|
625
|
+
specification = fs.readFileSync(file, 'utf8');
|
|
626
|
+
return [4 /*yield*/, openapi().load(specification).validate()];
|
|
553
627
|
case 1:
|
|
554
628
|
result = _b.sent();
|
|
555
629
|
if (result.valid) {
|
|
556
|
-
console.log(kleur.green("Matches the OpenAPI specification".concat(kleur.white(" (OpenAPI ".concat(kleur.bold(
|
|
630
|
+
console.log(kleur.green("Matches the OpenAPI specification".concat(kleur.white(" (OpenAPI ".concat(kleur.bold(result.version), ")")))));
|
|
557
631
|
endTime = performance.now();
|
|
558
632
|
console.log();
|
|
559
633
|
console.log(kleur.green('File validated'), kleur.grey("in ".concat(kleur.white("".concat(kleur.bold("".concat(Math.round(endTime - startTime))), " ms")))));
|
|
@@ -585,6 +659,7 @@ program.addCommand(InitCommand(), {
|
|
|
585
659
|
});
|
|
586
660
|
program.addCommand(FormatCommand());
|
|
587
661
|
program.addCommand(ValidateCommand());
|
|
662
|
+
program.addCommand(BundleCommand());
|
|
588
663
|
program.addCommand(ReferenceCommand());
|
|
589
664
|
program.addCommand(MockCommand());
|
|
590
665
|
program.addCommand(ShareCommand());
|