UNPKG

4.92 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 if (opts.outputOnly) {
64
65 var output = opts.outputs[0];
66 if (!output) return log('No output configured.');
67
68 if (output.overrideOpts) {
69 log('output only - override opts', output.overrideOpts);
70 u.assign(opts, output.overrideOpts);
71 }
72
73 generator.load(function(err) {
74 if (err) return log(err);
75
76 generator.outputPages(function(err, result) {
77 if (err) { log(err); }
78 log('output %s generated pages', u.flatten(result).length);
79 });
80
81 var statics = require('./server/serve-statics')(opts, function(){
82 statics.outputAll();
83 });
84
85 require('./server/serve-scripts')(opts).outputAll(generator);
86
87 generator.unload();
88 });
89
90 return;
91 }
92
93 generator.load(function(err) {
94 if (err) return log(err);
95
96 if (opts.logPages) {
97 generator.logPages();
98 generator.unload();
99 return;
100 }
101
102 require('./server/watch-sources')(generator);
103 generator.listen(true);
104
105 if (!opts['no-server']) { expressApp(); }
106 });
107 }
108
109 function expressApp() {
110
111 server.app = require('express')();
112 server.http = require('http').Server(server.app);
113 require('./server/serve-sockets')(server);
114
115 server.app.disable('x-powered-by');
116
117 // see https://expressjs.com/en/guide/behind-proxies.html - boolean type sensitive
118 server.app.set('trust proxy', opts['trust proxy'] || false);
119
120 // log(err) shouldn't throw anymore
121 log.logger.noErrors = true;
122
123 // sessions come with optional redis logger
124 server.sessions = require('pub-serve-sessions')(server);
125 log('starting up', opts.appUrl, (opts.production ? 'production' : 'non-production'));
126
127 // other default middleware
128 var bodyParser = require('body-parser');
129 server.app.use(bodyParser.json());
130 server.app.use(bodyParser.urlencoded({ extended: false }));
131 server.app.use(require('compression')());
132
133 server.emit('init-app-first');
134 server.sessions.authorizeRoutes();
135
136 server.statics = require('./server/serve-statics')(opts).serveRoutes(server);
137
138 if (!opts.staticOnly) {
139 server.scripts = require('./server/serve-scripts')(opts).serveRoutes(server);
140 require('./server/serve-pages')(server);
141 }
142
143 server.emit('init-app-last');
144
145 var limit = 10;
146 var tried = 1;
147 server.http.on('error', function(err) {
148 if (err.code === 'EADDRINUSE' && tried < limit) {
149 server.http.close();
150 opts.port = (parseInt(opts.port) || 3001) + 1;
151 log('port in use, trying', opts.port);
152 server.http.listen(opts.port);
153 tried ++;
154 }
155 });
156
157 require('./server/handle-errors')(server);
158
159 server.http.listen(opts.port);
160 log('port', opts.port);
161
162 process.on('SIGTERM', function() {
163 log('shutting down');
164 server.http.close(function() {
165 generator.unload();
166 server.emit('shutdown');
167 process.exit();
168 });
169 });
170
171 setTimeout(function() {
172 if (opts.cli && opts.openBrowser && osType.match(/Darwin/)) {
173 exec('open "http://localhost:"' + opts.port);
174 }
175 }, 100);
176 }
177
178}