UNPKG

7.6 kBJavaScriptView Raw
1
2const path = require('path');
3const glob = require('glob');
4const favicon = require('serve-favicon');
5const _ = require("lodash");
6const debug = require('debug')('motif:process');
7
8const Macro = require('node-macro');
9
10const http = require( 'http' );
11const express = require('express');
12
13const session = require('express-session');
14const cookieParser = require('cookie-parser');
15const bodyParser = require('body-parser');
16const helmet = require('helmet');
17const cors = require('cors');
18const formidable = require('formidable');
19
20const Context = require('./Context');
21const Swagger = require('./Swagger');
22
23class Process {
24
25 get app() {
26 return this._app;
27 }
28
29 get context() {
30 return this._context;
31 }
32
33 _loadService( file ) {
34 debug("_loadService", file);
35 delete require.cache[require.resolve(path.resolve(this._context.appPath, file))];
36 return require(path.resolve(this._context.appPath, file));
37 }
38
39 _loadServices() {
40
41 debug("_loadServices");
42
43 const macro = new Macro();
44
45 let serviceFiles = [];
46
47 macro.add("CREATE-APP", (action) => {
48
49 let app = express();
50 app.use(helmet());
51 app.use(bodyParser.urlencoded({ extended: false }));
52 app.use(bodyParser.json());
53 app.use(cors());
54
55 if (this._context.useCookie === true) {
56 app.use(cookieParser());
57 }
58
59 if (this._context.useFavicon === true) {
60 app.use(favicon(path.join(this._context.appPath, 'public', 'favicon.ico')));
61 }
62
63 if (this._context.useProxy === true) {
64 app.set('trust proxy', true);
65 }
66
67 app.on('uncaughtException', this.onException);
68
69 // file uploader
70 app.use(function (req, res, next) {
71 if (req.headers['content-type'] && req.headers['content-type'].indexOf('multipart/form-data') > -1) {
72 // 멀티파트 데이터
73 const form = new formidable.IncomingForm({
74 encoding: 'utf-8',
75 multiples: true,
76 type: 'multipart', // or urlencoded
77 maxFieldsSize: 20 * 1024 * 1024,
78 maxFileSize: 200 * 1024 * 1024,
79 maxFields: 1000,
80 hash: true,
81 keepExtensions: false
82 });
83 form.parse(req, function (err, fields) {
84 _.merge(req.body, fields);
85 req.openedFiles = [];
86 });
87 form.on('file', function (name, file) {
88 if (!req.files) {
89 req.files = {};
90 }
91 req.files[name] = file;
92 req.body[name] = file;
93 });
94 form.on('end', function () {
95 req.openedFiles = this.openedFiles;
96 next();
97 });
98 } else {
99 next();
100 }
101 });
102
103 this._app = app;
104 action.complete();
105 });
106
107 macro.add("LOAD-SERVICE-FILES", (action) => {
108 glob("services/*/*Service.js", { cwd: this._context.appPath }, (err, files) => {
109 if (err) {
110 action.error(err);
111 return;
112 }
113
114 serviceFiles = files;
115 action.complete();
116 });
117 });
118
119 macro.add("LOAD-SERVICES", (action) => {
120 _.each(serviceFiles, (file) => {
121 this._services.push(
122 this._loadService( file )
123 );
124 });
125
126 action.complete();
127 });
128
129 if (this._context.createDoc === true) {
130
131 macro.add("CRAETE-SWAGGER-DOCS", async (action) => {
132
133 try {
134 let app = this._app;
135 let swagger = new Swagger( this._context );
136
137 let json = swagger.buildJSON( this._routerPaths, false );
138 let swaggerPath = path.join(this._context.appPath, "public/swagger");
139
140 await swagger.jsonWriteAsync( path.join(swaggerPath, "/data/swag.json"), json );
141
142 app.use(express.static(path.join(this._context.appPath, 'public', 'swagger')));
143
144 app.get('/doc/data', (req, res) => {
145 res.sendFile('data/swag.json', {root: swaggerPath });
146 });
147
148 app.get('/doc', (req, res) => {
149 res.sendFile('index.html', {root: swaggerPath });
150 });
151 }
152 catch(e) {
153 console.log( e );
154 }
155
156 action.complete();
157 });
158
159 macro.add("CRAETE-SWAGGER-ADMIN-DOCS", async (action) => {
160
161 try {
162 let app = this._app;
163 let swagger = new Swagger( this._context );
164
165 let json = swagger.buildJSON( this._routerPaths, true );
166 let swaggerPath = path.join(this._context.appPath, "public/swagger");
167
168 await swagger.jsonWriteAsync( path.join(swaggerPath, "/data/swag.admin.json"), json );
169
170 app.use(express.static(path.join(this._context.appPath, 'public', 'swagger')));
171
172 app.get('/doc/data-admin', (req, res) => {
173 res.sendFile('data/swag.admin.json', {root: swaggerPath });
174 });
175
176 app.get('/doc-admin', (req, res) => {
177 res.sendFile('index.admin.html', {root: swaggerPath });
178 });
179 }
180 catch(e) {
181 console.log( e );
182 }
183
184 action.complete();
185 });
186 }
187
188 macro.add("RUN-SERVER", (action) => {
189
190 let server = http.createServer( this._app );
191 server.listen( this.context.port, () => {
192 debug( `Server is running on port ${this.context.port}` );
193 });
194 server.on('error', this.onError);
195 server.on('listening', this.onListening);
196
197 this._server = server;
198
199 action.complete();
200 });
201
202 macro.start((error) => {
203 if (error) {
204 debug(error);
205 }
206 });
207 }
208
209 _attachExceptionHandlers() {
210 process.on('uncaughtException', async function (err) {
211 console.error(err.stack);
212 process.exit(1);
213 });
214
215 process.on('unhandledRejection', async function (err) {
216 console.error(err.stack);
217 process.exit(1);
218 });
219 }
220
221 constructor( options ) {
222
223 this._context = new Context({
224 appPath: path.resolve(process.env.PWD, '.'),
225 ...options
226 });
227
228 this._app = null;
229 this._server = null;
230 this._services = [];
231 this._views = [];
232 this._routerPaths = [];
233
234 process.motif = this;
235 }
236
237 run( ) {
238
239 this._attachExceptionHandlers();
240
241 this._loadServices();
242 }
243
244 onListening() {
245 debug( "onListening" );
246 }
247
248 onException(req, res, route, err) {
249 debug( "onException", err );
250 }
251
252 onError(error) {
253 debug( "onError", error );
254 }
255
256};
257
258module.exports = Process;