-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
mock.ts
117 lines (103 loc) · 3.38 KB
/
mock.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { Command, flags } from '@oclif/command';
import * as Koa from 'koa';
import * as bodyparser from 'koa-bodyparser';
import * as cors from '@koa/cors';
import * as mount from 'koa-mount';
import OpenAPIBackend, { Document } from 'openapi-backend';
import * as commonFlags from '../common/flags';
import { startServer, createServer } from '../common/koa';
import { serveSwaggerUI } from '../common/swagger-ui';
import { resolveDefinition, printInfo, printOperations } from '../common/definition';
export default class Mock extends Command {
public static description = 'start a local mock API server';
public static examples = [
'$ openapi mock ./openapi.yml',
'$ openapi mock https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v3.0/petstore.yaml',
];
public static flags = {
...commonFlags.help(),
...commonFlags.serverOpts(),
...commonFlags.overrideServers(),
'swagger-ui': flags.string({ char: 'U', description: 'Swagger UI endpoint', helpValue: 'docs' }),
};
public static args = [
{
name: 'definition',
description: 'input definition file',
},
];
public async run() {
const { args, flags } = this.parse(Mock);
const { port, logger, 'swagger-ui': swaggerui, serveroverride } = flags;
let portRunning = port;
const definition = resolveDefinition(args.definition);
if (!definition) {
this.error('Please load a definition file', { exit: 1 });
}
const api = new OpenAPIBackend({ definition });
api.register({
validationFail: (c, ctx) => {
ctx.status = 400;
ctx.body = { err: c.validation.errors };
},
notFound: (c, ctx) => {
ctx.status = 404;
ctx.body = { err: 'not found' };
},
notImplemented: (c, ctx) => {
const { status, mock } = c.api.mockResponseForOperation(c.operation.operationId);
ctx.status = status;
ctx.body = mock;
},
});
await api.init();
const app = createServer({ logger });
app.use(bodyparser());
app.use(cors({ credentials: true }));
// serve openapi.json
const openApiFile = 'openapi.json';
const documentPath = `/${openApiFile}`;
app.use(
mount(documentPath, async (ctx, next) => {
await next();
const doc = api.document;
doc.servers = serveroverride
? serveroverride.map((url) => ({ url }))
: [
{
url: `http://localhost:${portRunning}`,
},
];
ctx.body = api.document;
ctx.status = 200;
}),
);
// serve swagger ui
if (swaggerui) {
app.use(mount(`/${swaggerui}`, serveSwaggerUI({ url: documentPath })));
}
// serve openapi-backend
app.use((ctx) =>
api.handleRequest(
{
method: ctx.request.method,
path: ctx.request.path,
body: ctx.request.body,
query: ctx.request.query,
headers: ctx.request.headers,
},
ctx,
),
);
// start server
const server = await startServer({ app, port });
portRunning = server.port;
this.log();
this.log(`Mock server running at http://localhost:${portRunning}`);
if (swaggerui) {
this.log(`Swagger UI running at http://localhost:${portRunning}/${swaggerui}`);
}
this.log(`OpenAPI definition at http://localhost:${portRunning}${documentPath}`);
this.log();
}
}