UNPKG

4.57 kBJavaScriptView Raw
1/*
2 * pub server.js
3 *
4 * launches (express) server after resolving opts
5 * invoke directly via node command line, or via require()
6 * see: https://nodejs.org/api/modules.html#modules_accessing_the_main_module
7 *
8 * copyright 2015-2020, Jürgen Leschner - github.com/jldec - MIT license
9 */
10
11var debug = require('debug')('pub:server');
12
13var osType = require('os').type();
14var exec = require('child_process').exec;
15var events = require('events');
16var path = require('path');
17var u = require('pub-util');
18
19if (require.main === module) {
20 pubServer().run();
21}
22else {
23 module.exports = pubServer;
24}
25
26u.inherits(pubServer, events.EventEmitter);
27
28//--//--//--//--//--//--//--//--//--//--//--//--//
29
30function pubServer(opts) {
31
32 if (!(this instanceof pubServer)) return new pubServer(opts);
33 events.EventEmitter.call(this);
34
35 var server = this;
36
37 // pass platform-specific ./node_modules path to resolve-opts for builtin packages
38 server.opts = opts = require('pub-resolve-opts')(opts, path.join(__dirname, 'node_modules'));
39
40 opts.production = opts.production || (process.env.NODE_ENV === 'production');
41 opts.port = opts.port || process.env.PORT || '3001';
42 opts.appUrl = opts.appUrl || process.env.APP || ('http://localhost:' + opts.port);
43
44 server.run = run;
45
46 var generator = server.generator = require('pub-generator')(opts);
47
48 u.each(opts.serverPlugins.reverse(), function(plugin) {
49 debug('server plugin:', plugin.inspect());
50 require(plugin.path)(server);
51 });
52
53 u.each(opts.generatorPlugins.reverse(), function(plugin) {
54 debug('generator plugin:', plugin.path, plugin.inspect());
55 require(plugin.path)(generator);
56 });
57
58 var log = opts.log;
59
60 //--//--//--//--//--//--//--//--//--//--//--//
61
62 function run() {
63 generator.load(function(err) {
64 if (err) return log(err);
65
66 if (opts.outputOnly) {
67 generator.outputPages(function(err, result) {
68 if (err) { log(err); }
69 log('output %s generated pages', u.flatten(result).length);
70 });
71
72 var statics = require('./server/serve-statics')(opts, function(){
73 statics.outputAll();
74 });
75 require('./server/serve-scripts')(opts).outputAll(generator);
76 generator.unload();
77 return;
78 }
79
80 if (opts.logPages) {
81 generator.logPages();
82 generator.unload();
83 return;
84 }
85
86 require('./server/watch-sources')(generator);
87 generator.listen(true);
88
89 if (!opts['no-server']) { expressApp(); }
90 });
91 }
92
93 function expressApp() {
94
95 server.app = require('express')();
96 server.http = require('http').Server(server.app);
97 require('./server/serve-sockets')(server);
98
99 server.app.disable('x-powered-by');
100
101 // see https://expressjs.com/en/guide/behind-proxies.html
102 server.app.set('trust proxy', opts['trust proxy'] || false);
103
104 // log(err) shouldn't throw anymore
105 log.logger.noErrors = true;
106
107 // sessions come with optional redis logger
108 server.sessions = require('pub-serve-sessions')(server);
109 log('starting up', opts.appUrl, (opts.production ? 'production' : 'non-production'));
110
111 // other default middleware
112 var bodyParser = require('body-parser');
113 server.app.use(bodyParser.json());
114 server.app.use(bodyParser.urlencoded({ extended: false }));
115 server.app.use(require('compression')());
116
117 server.emit('init-app-first');
118 server.sessions.authorizeRoutes();
119
120 if (!opts.staticOnly) {
121 require('./server/serve-pages')(server);
122 server.scripts = require('./server/serve-scripts')(opts).serveRoutes(server);
123 }
124 server.statics = require('./server/serve-statics')(opts).serveRoutes(server);
125
126 server.emit('init-app-last');
127
128 var limit = 10;
129 var tried = 1;
130 server.http.on('error', function(err) {
131 if (err.code === 'EADDRINUSE' && tried < limit) {
132 server.http.close();
133 opts.port = (parseInt(opts.port) || 3001) + 1;
134 log('port in use, trying', opts.port);
135 server.http.listen(opts.port);
136 tried ++;
137 }
138 });
139
140 require('./server/handle-errors')(server);
141
142 server.http.listen(opts.port);
143 log('port', opts.port);
144
145 process.on('SIGTERM', function() {
146 log('shutting down');
147 server.http.close(function() {
148 generator.unload();
149 server.emit('shutdown');
150 process.exit();
151 });
152 });
153
154 setTimeout(function() {
155 if (opts.cli && opts.openBrowser && osType.match(/Darwin/)) {
156 exec('open "http://localhost:"' + opts.port);
157 }
158 }, 100);
159 }
160
161}