-
Notifications
You must be signed in to change notification settings - Fork 63
/
Copy pathfunctionRunner.ts
95 lines (87 loc) · 3.01 KB
/
functionRunner.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
import { ServerlessCallback } from '@twilio-labs/serverless-runtime-types/types';
import { serializeError } from 'serialize-error';
import { getRouteMap } from '../internal/route-cache';
import { constructContext, constructGlobalScope, isTwiml } from '../route';
import { Response } from './response';
const sendDebugMessage = (debugMessage: string, ...debugArgs: any) => {
process.send && process.send({ debugMessage, debugArgs });
};
export type Reply = {
body?: string | number | boolean | object;
headers?: { [key: string]: number | string };
statusCode: number;
};
const handleError = (err: Error | string | object) => {
if (err) {
process.send && process.send({ err: serializeError(err) });
}
};
const handleSuccess = (responseObject?: string | number | boolean | object) => {
let reply: Reply = { statusCode: 200 };
if (typeof responseObject === 'string') {
sendDebugMessage('Sending basic string response');
reply.headers = { 'Content-Type': 'text/plain' };
reply.body = responseObject;
} else if (
responseObject &&
typeof responseObject === 'object' &&
isTwiml(responseObject)
) {
sendDebugMessage('Sending TwiML response as XML string');
reply.headers = { 'Content-Type': 'text/xml' };
reply.body = responseObject.toString();
} else if (responseObject && responseObject instanceof Response) {
sendDebugMessage('Sending custom response');
reply = responseObject.serialize();
} else {
sendDebugMessage('Sending JSON response');
reply.body = responseObject;
reply.headers = { 'Content-Type': 'application/json' };
}
if (process.send) {
process.send({ reply });
}
};
process.on('message', async ({ functionPath, event, config, path }) => {
try {
await getRouteMap(config);
constructGlobalScope(config);
const context = constructContext(config, path);
sendDebugMessage('Context for %s: %p', path, context);
sendDebugMessage('Event for %s: %o', path, event);
let run_timings: { start: [number, number]; end: [number, number] } = {
start: [0, 0],
end: [0, 0],
};
const callback: ServerlessCallback = (err, responseObject) => {
run_timings.end = process.hrtime();
sendDebugMessage('Function execution %s finished', path);
sendDebugMessage(
`(Estimated) Total Execution Time: ${
(run_timings.end[0] * 1e9 +
run_timings.end[1] -
(run_timings.start[0] * 1e9 + run_timings.start[1])) /
1e6
}ms`
);
if (err) {
handleError(err);
} else {
handleSuccess(responseObject);
}
};
sendDebugMessage('Calling function for %s', path);
run_timings.start = process.hrtime();
const { handler } = require(functionPath);
if (typeof handler !== 'function') {
throw new Error(
`Could not find a "handler" function in file ${functionPath}`
);
}
handler(context, event, callback);
} catch (err) {
if (process.send) {
process.send({ err: serializeError(err) });
}
}
});