Skip to content

Commit 54d4a2d

Browse files
author
Alessandro Romanelli
committed
0.2.14
1 parent 8d41e5e commit 54d4a2d

File tree

9 files changed

+79
-66
lines changed

9 files changed

+79
-66
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "expresso-api",
3-
"version": "0.2.13",
3+
"version": "0.2.14",
44
"main": "dist/lib/index.js",
55
"types": "dist/lib/index.d.ts",
66
"bin": {

src/lib/generator/index.ts

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ import util from 'util';
33
import logger from 'jet-logger';
44
import { replaceExpress } from '../replacer';
55
import { exec as syncExec, ExecOptions } from 'child_process';
6-
import { move, readFile, readJSON, remove, writeFile } from "fs-extra";
6+
import { move, readFile, readJSON, remove, writeFile } from 'fs-extra';
77
import { CLIOptionsGenerate } from '../../cli/types';
88
import YAML from 'json2yaml';
9-
import { Handler, HandlerJSON } from "../proxy/model";
10-
import { writeSpecification } from "../proxy/writer";
11-
import waitOn from "wait-on"
9+
import { Handler, HandlerJSON } from '../proxy/model';
10+
import { writeSpecification } from '../proxy/writer';
11+
import waitOn from 'wait-on';
1212

1313
const exec = util.promisify(syncExec);
1414

@@ -41,7 +41,7 @@ export const generateSpecification = async ({ root, startLine, output, extension
4141
};
4242

4343
// Launch the work copy with the replaced modules
44-
logger.info("Starting work copy...")
44+
logger.info('Starting work copy...');
4545
try {
4646
const { stdout, stderr } = await exec(startLine, execOptions);
4747
logger.info(`Command '${startLine}' executed. Output:`);
@@ -54,28 +54,28 @@ export const generateSpecification = async ({ root, startLine, output, extension
5454

5555
try {
5656
await waitOn({
57-
resources: [ path.resolve(root, 'expresso-models.json') ],
58-
timeout: 10000
59-
})
57+
resources: [path.resolve(root, 'expresso-models.json')],
58+
timeout: 10000,
59+
});
6060
} catch (e) {
61-
logger.err(e)
62-
return cleanUp(root)
61+
logger.err(e);
62+
return cleanUp(root);
6363
}
6464

6565
// Read the models file and perform the analysis
6666
try {
6767
const models = new Set(
68-
(await readJSON(
69-
path.resolve(root, 'expresso-models.json'), 'utf-8') as HandlerJSON[]
70-
).map(x => Handler.fromJSON(x))
71-
)
72-
await remove(path.resolve(root, 'expresso-models.json'))
73-
await writeSpecification(replacedProjectPath, models)
68+
((await readJSON(path.resolve(root, 'expresso-models.json'), 'utf-8')) as HandlerJSON[]).map((x) =>
69+
Handler.fromJSON(x),
70+
),
71+
);
72+
await remove(path.resolve(root, 'expresso-models.json'));
73+
await writeSpecification(replacedProjectPath, models);
7474
} catch (e) {
75-
logger.err("Unable to read the models extracted from the work copy. Aborting...")
76-
logger.err(e)
77-
logger.err(e.stack)
78-
return cleanUp(root)
75+
logger.err('Unable to read the models extracted from the work copy. Aborting...');
76+
logger.err(e);
77+
logger.err(e.stack);
78+
return cleanUp(root);
7979
}
8080

8181
// Convert to YAML if requested

src/lib/proxy/analyzer/index.ts

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { parse, find, walk, traverse, remove } from 'abstract-syntax-tree';
33
import { getReasonPhrase } from 'http-status-codes';
44
import logger from 'jet-logger';
55
import _ from 'lodash';
6-
import { RequestHandler } from "express";
6+
import { RequestHandler } from 'express';
77

88
const EXPRESS_TERMINATORS = [
99
'send',
@@ -115,38 +115,49 @@ const mineStatementForResponse = (statement: any, resName: string): ResponseStat
115115
find(
116116
statement,
117117
`CallExpression:has(Identifier[name='${resName}'])[callee.property.name='status'] > *:last-child, ` +
118-
`AssignmentExpression[left.object.name='${resName}'][left.property.name='statusCode'] > *[property.name!='statusCode']`,
118+
`AssignmentExpression[left.object.name='${resName}'][left.property.name='statusCode'] > *[property.name!='statusCode']`,
119119
),
120120
);
121121
if (response) return mineNodeForResponse(response);
122-
const terminator = _.first(find(statement, `CallExpression:has(Identifier[name='${resName}'])[callee.property.name=/${EXPRESS_TERMINATORS.join('|')}/]`));
122+
const terminator = _.first(
123+
find(
124+
statement,
125+
`CallExpression:has(Identifier[name='${resName}'])[callee.property.name=/${EXPRESS_TERMINATORS.join('|')}/]`,
126+
),
127+
);
123128
if (terminator) return getStatusCodeForTerminator(terminator);
124129
};
125130

126131
const mineBlockForResponses = (block: any, resName: string): ResponseStatus[] => {
127132
remove(block, 'IfStatement BlockStatement,SwitchStatement');
128-
const statements = find(block,
129-
`IfStatement ReturnStatement:has(CallExpression:has(Identifier[name='${resName}'])`+
130-
`[callee.property.name=/${['status', ...EXPRESS_TERMINATORS].join("|")}/])`)
133+
const statements = find(
134+
block,
135+
`IfStatement ReturnStatement:has(CallExpression:has(Identifier[name='${resName}'])` +
136+
`[callee.property.name=/${['status', ...EXPRESS_TERMINATORS].join('|')}/])`,
137+
);
131138
const lastStatement = _.last(
132139
find(
133140
block,
134141
`ExpressionStatement:has(CallExpression:has(Identifier[name='${resName}'])[callee.property.name='status']), ` +
135-
`*:not(IfStatement) > ReturnStatement:has(CallExpression:has(Identifier[name='${resName}'])[callee.property.name='status']), ` +
136-
`AssignmentExpression[left.object.name=${resName}]`,
142+
`*:not(IfStatement) > ReturnStatement:has(CallExpression:has(Identifier[name='${resName}'])[callee.property.name='status']), ` +
143+
`AssignmentExpression[left.object.name=${resName}]`,
137144
),
138145
);
139146
if (lastStatement) {
140-
statements.push(lastStatement)
147+
statements.push(lastStatement);
141148
} else {
142149
const lastStatement = _.last(
143150
find(
144151
block,
145-
`ExpressionStatement:has(CallExpression:has(Identifier[name='${resName}'])[callee.property.name=/${EXPRESS_TERMINATORS.join('|')}/]), ` +
146-
`*:not(IfStatement) > ReturnStatement:has(CallExpression:has(Identifier[name='${resName}'])[callee.property.name=/${EXPRESS_TERMINATORS.join('|')}/])`
152+
`ExpressionStatement:has(CallExpression:has(Identifier[name='${resName}'])[callee.property.name=/${EXPRESS_TERMINATORS.join(
153+
'|',
154+
)}/]), ` +
155+
`*:not(IfStatement) > ReturnStatement:has(CallExpression:has(Identifier[name='${resName}'])[callee.property.name=/${EXPRESS_TERMINATORS.join(
156+
'|',
157+
)}/])`,
147158
),
148159
);
149-
if (lastStatement) statements.push(lastStatement)
160+
if (lastStatement) statements.push(lastStatement);
150161
}
151162

152163
return statements.map((x: any) => mineStatementForResponse(x, resName));
@@ -162,13 +173,11 @@ export const mineExpressResponses = (fnBody: string): OpenAPIV3.ResponsesObject
162173

163174
const responses: ResponseStatus[] = find(
164175
fn,
165-
`BlockStatement:has(CallExpression:has(Identifier[name='${resName}'])`+
166-
`[callee.property.name=/${EXPRESS_TERMINATORS.join('|')}/])`,
176+
`BlockStatement:has(CallExpression:has(Identifier[name='${resName}'])` +
177+
`[callee.property.name=/${EXPRESS_TERMINATORS.join('|')}/])`,
167178
)
168179
.flatMap((x: any) => mineBlockForResponses(x, resName))
169180
.filter((x: any) => x);
170181

171-
return responses
172-
.map((x) => x.toSpecification())
173-
.reduce((prev, curr) => Object.assign(prev, curr), {});
182+
return responses.map((x) => x.toSpecification()).reduce((prev, curr) => Object.assign(prev, curr), {});
174183
};

src/lib/proxy/event.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import EventEmitter from 'events';
22
import { models } from './model';
3-
import { writeModels } from "./writer";
3+
import { writeModels } from './writer';
44

55
class OAPIEmitter extends EventEmitter {}
66

src/lib/proxy/index.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import express from 'express-original';
22
import { Endpoint, ExpressHandler, Handler, HTTP_METHODS, Method, models } from './model';
33
import { emitter } from './event';
4-
import { RequestHandler } from "express";
4+
import { RequestHandler } from 'express';
55

66
const isHTTPMethod = (method: string): method is Method => {
77
return HTTP_METHODS.includes(method as Method);
@@ -12,7 +12,14 @@ const makeProxyHandler = (app: Handler): ProxyHandler<express.Express> => {
1212
const routeHandlerEndpoint = (method: Method): ProxyHandler<RequestHandler> => ({
1313
apply: (target, thisArg, argArray) => {
1414
const [path, ...handlers] = argArray;
15-
app.add(new Endpoint(method, path, handlers.flatMap(x => x).map(x => x.toString()), opIndex++));
15+
app.add(
16+
new Endpoint(
17+
method,
18+
path,
19+
handlers.flatMap((x) => x).map((x) => x.toString()),
20+
opIndex++,
21+
),
22+
);
1623
emitter.emit('api-update');
1724
},
1825
});

src/lib/proxy/model/Endpoint.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ export class Endpoint {
3535
}
3636

3737
analyzeHandler(handler: string): [OpenAPIV3.ResponsesObject, OpenAPIV3.ParameterObject[]] {
38-
console.log(handler, this.getResponses(handler))
38+
console.log(handler, this.getResponses(handler));
3939
return [this.getResponses(handler), this.getParameters(handler)];
4040
}
4141

4242
analyzeHandlers() {
43-
const [responses, params] = this.handlers
43+
const [responses, params] = this.handlers
4444
.map((x) => this.analyzeHandler(x))
4545
.reduce(
4646
([prevResponses, prevParams], [responses, params]) => [
@@ -49,13 +49,13 @@ export class Endpoint {
4949
],
5050
[{}, []],
5151
);
52-
this.responses = responses
53-
this.params = params
52+
this.responses = responses;
53+
this.params = params;
5454
}
5555

5656
static fromJSON(obj: EndpointJSON): Endpoint {
57-
const endpoint = new Endpoint(obj.method, obj.path, obj.handlers, obj.index)
58-
endpoint.analyzeHandlers()
59-
return endpoint
57+
const endpoint = new Endpoint(obj.method, obj.path, obj.handlers, obj.index);
58+
endpoint.analyzeHandlers();
59+
return endpoint;
6060
}
6161
}

src/lib/proxy/model/Handler.ts

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import express from 'express-original';
2-
import { Endpoint, EndpointJSON } from "./Endpoint";
2+
import { Endpoint, EndpointJSON } from './Endpoint';
33
import { Method } from './Method';
44

55
export interface HandlerJSON {
66
_instance: ExpressHandler;
7-
_endpoints: { [k1: string]: { [k2 in Method]: EndpointJSON } }
8-
_routers: { [key: string]: HandlerJSON }
7+
_endpoints: { [k1: string]: { [k2 in Method]: EndpointJSON } };
8+
_routers: { [key: string]: HandlerJSON };
99
}
1010

1111
export type ExpressHandler = express.Express | express.Application | express.Router;
@@ -54,14 +54,11 @@ export class Handler {
5454
}
5555

5656
static fromJSON(obj: HandlerJSON): Handler {
57-
const handler = new Handler(obj._instance)
58-
const endpoints = Object.values(obj._endpoints)
59-
.flatMap(x => Object.values(x)
60-
.map(x => Endpoint.fromJSON(x)))
61-
endpoints.forEach(x => handler.add(x))
62-
const handlers = Object.entries(obj._routers)
63-
.map(([path, x]) => [path, Handler.fromJSON(x)] as [string, Handler])
64-
handlers.forEach(([path, x]) => handler.mount(path, x))
65-
return handler
57+
const handler = new Handler(obj._instance);
58+
const endpoints = Object.values(obj._endpoints).flatMap((x) => Object.values(x).map((x) => Endpoint.fromJSON(x)));
59+
endpoints.forEach((x) => handler.add(x));
60+
const handlers = Object.entries(obj._routers).map(([path, x]) => [path, Handler.fromJSON(x)] as [string, Handler]);
61+
handlers.forEach(([path, x]) => handler.mount(path, x));
62+
return handler;
6663
}
6764
}

src/lib/proxy/writer.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ export const writeSpecification = async (projectRoot = '.', models: Set<Handler>
6666
export const writeModels = async (projectRoot = '.', models: Set<Handler>): Promise<void> => {
6767
const filePath = path.resolve(projectRoot, '..', 'expresso-models.json');
6868
try {
69-
await writeJSON(filePath, Array.from(models))
69+
await writeJSON(filePath, Array.from(models));
7070
} catch (e) {
71-
console.error(e)
71+
console.error(e);
7272
}
73-
}
73+
};

src/lib/replacer/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export const replaceExpress = async (basePath: string): Promise<boolean> => {
5454
await copy(basePath, path.resolve(basePath, '../.expresso-runtime'), {
5555
recursive: true,
5656
filter: (src) => !src.includes('node_modules'),
57-
overwrite: true
57+
overwrite: true,
5858
});
5959
// Move it within the original folder
6060
await move(path.resolve(basePath, '../.expresso-runtime'), path.resolve(basePath, '.expresso-runtime'));
@@ -72,8 +72,8 @@ export const replaceExpress = async (basePath: string): Promise<boolean> => {
7272
path.resolve(basePath, 'node_modules/@types/express/index.d.ts'),
7373
path.resolve(basePath, '.expresso-runtime/node_modules/express/dist/lib/index.d.ts'),
7474
{
75-
overwrite: true
76-
}
75+
overwrite: true,
76+
},
7777
);
7878
// Install the real 'express' within the work copy with a different name to avoid conflicts
7979
await copy(

0 commit comments

Comments
 (0)