UNPKG

4.92 kBJavaScriptView Raw
1const debug = require('debug')('upward-js:middleware');
2const jsYaml = require('js-yaml');
3const UpwardServerError = require('./UpwardServerError');
4const IOAdapter = require('./IOAdapter');
5const buildResponse = require('./buildResponse');
6
7class UpwardMiddleware {
8 constructor(upwardPath, env, io) {
9 this.env = env;
10 this.upwardPath = upwardPath;
11 debug(`created for path ${upwardPath}`);
12 this.io = io;
13 }
14 async load() {
15 const { upwardPath } = this;
16 try {
17 this.yamlTxt = await this.io.readFile(upwardPath);
18 } catch (e) {
19 throw new UpwardServerError(e, `unable to read file ${upwardPath}`);
20 }
21 debug(`read upward.yml file successfully`);
22 try {
23 this.definition = await jsYaml.safeLoad(this.yamlTxt);
24 } catch (e) {
25 throw new UpwardServerError(
26 e,
27 `error parsing ${upwardPath} contents: \n\n${this.yamlTxt}`
28 );
29 }
30 debug(`parsed upward.yml file successfully: %o`, this.definition);
31 }
32 async getHandler() {
33 return async (req, res, next) => {
34 const errors = [];
35 let response;
36 try {
37 response = await buildResponse(
38 this.io,
39 this.env,
40 this.definition,
41 req,
42 this.upwardPath
43 );
44 if (typeof response === 'function') {
45 debug('buildResponse returned function');
46 response(req, res, next);
47 return;
48 }
49 if (isNaN(response.status)) {
50 errors.push(
51 `Non-numeric status! Status was '${response.status}'`
52 );
53 }
54 if (typeof response.headers !== 'object') {
55 errors.push(
56 `Resolved with a non-compliant headers object! Headers are: ${
57 response.headers
58 }`
59 );
60 }
61 if (
62 typeof response.body !== 'string' &&
63 typeof response.body.toString !== 'function'
64 ) {
65 errors.push(
66 `Resolved with a non-serializable body! Body was '${Object.prototype.toString.call(
67 response.body
68 )}'`
69 );
70 }
71 } catch (e) {
72 errors.push(e.message);
73 }
74 if (errors.length > 0) {
75 if (this.env.NODE_ENV === 'production') {
76 res.status(500);
77 res.format({
78 json() {
79 res.json({
80 errors: [
81 {
82 status: 500,
83 message: 'Server Error'
84 }
85 ]
86 });
87 },
88 html() {
89 res.send('500 Server Error');
90 }
91 });
92 } else {
93 res.format({
94 json() {
95 res.status(500).json({
96 errors: errors.map(message => ({ message }))
97 });
98 },
99 html() {
100 next(
101 new UpwardServerError(
102 `Request did not evaluate to a valid response, because: \n${errors.join(
103 '\n\n'
104 )}`
105 )
106 );
107 }
108 });
109 }
110 } else {
111 debug('status, headers, and body valid. responding');
112 res.status(response.status)
113 .set(response.headers)
114 .send(
115 typeof response.body === 'string' ||
116 Buffer.isBuffer(response.body)
117 ? response.body
118 : response.body.toString()
119 );
120 }
121 };
122 }
123}
124
125async function upwardJSMiddlewareFactory(
126 upwardPath,
127 env,
128 io = IOAdapter.default(upwardPath)
129) {
130 const middleware = new UpwardMiddleware(upwardPath, env, io);
131 await middleware.load();
132 return middleware.getHandler();
133}
134
135upwardJSMiddlewareFactory.UpwardMiddleware = UpwardMiddleware;
136
137module.exports = upwardJSMiddlewareFactory;