@zappinginc/zm2 6.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +8 -0
- package/.gitattributes +4 -0
- package/.mocharc.js +14 -0
- package/CHANGELOG.md +2416 -0
- package/CLAUDE.md +84 -0
- package/CONTRIBUTING.md +124 -0
- package/GNU-AGPL-3.0.txt +665 -0
- package/LICENSE +1 -0
- package/README.md +248 -0
- package/bin/zm2 +3 -0
- package/bin/zm2-dev +3 -0
- package/bin/zm2-docker +3 -0
- package/bin/zm2-runtime +3 -0
- package/bin/zm2-windows +3 -0
- package/bin/zm2.ps1 +3 -0
- package/bun.lock +421 -0
- package/constants.js +114 -0
- package/index.js +13 -0
- package/lib/API/Configuration.js +212 -0
- package/lib/API/Containerizer.js +335 -0
- package/lib/API/Dashboard.js +459 -0
- package/lib/API/Deploy.js +117 -0
- package/lib/API/Extra.js +775 -0
- package/lib/API/ExtraMgmt/Docker.js +30 -0
- package/lib/API/Log.js +315 -0
- package/lib/API/LogManagement.js +371 -0
- package/lib/API/Modules/LOCAL.js +122 -0
- package/lib/API/Modules/Modularizer.js +148 -0
- package/lib/API/Modules/NPM.js +445 -0
- package/lib/API/Modules/TAR.js +362 -0
- package/lib/API/Modules/flagExt.js +46 -0
- package/lib/API/Modules/index.js +120 -0
- package/lib/API/Monit.js +247 -0
- package/lib/API/Serve.js +343 -0
- package/lib/API/Startup.js +629 -0
- package/lib/API/UX/helpers.js +213 -0
- package/lib/API/UX/index.js +9 -0
- package/lib/API/UX/pm2-describe.js +193 -0
- package/lib/API/UX/pm2-ls-minimal.js +31 -0
- package/lib/API/UX/pm2-ls.js +483 -0
- package/lib/API/Version.js +382 -0
- package/lib/API/interpreter.json +12 -0
- package/lib/API/pm2-plus/PM2IO.js +372 -0
- package/lib/API/pm2-plus/auth-strategies/CliAuth.js +288 -0
- package/lib/API/pm2-plus/auth-strategies/WebAuth.js +187 -0
- package/lib/API/pm2-plus/helpers.js +97 -0
- package/lib/API/pm2-plus/link.js +126 -0
- package/lib/API/pm2-plus/pres/motd +16 -0
- package/lib/API/pm2-plus/pres/motd.update +26 -0
- package/lib/API/pm2-plus/pres/welcome +28 -0
- package/lib/API/pm2-plus/process-selector.js +52 -0
- package/lib/API/schema.json +379 -0
- package/lib/API.js +1931 -0
- package/lib/Client.js +776 -0
- package/lib/Common.js +911 -0
- package/lib/Configuration.js +304 -0
- package/lib/Daemon.js +456 -0
- package/lib/Event.js +37 -0
- package/lib/God/ActionMethods.js +909 -0
- package/lib/God/ClusterMode.js +97 -0
- package/lib/God/ForkMode.js +297 -0
- package/lib/God/Methods.js +265 -0
- package/lib/God/Reload.js +240 -0
- package/lib/God.js +632 -0
- package/lib/HttpInterface.js +76 -0
- package/lib/ProcessContainer.js +305 -0
- package/lib/ProcessContainerBun.js +360 -0
- package/lib/ProcessContainerFork.js +42 -0
- package/lib/ProcessContainerForkBun.js +33 -0
- package/lib/ProcessUtils.js +55 -0
- package/lib/TreeKill.js +118 -0
- package/lib/Utility.js +430 -0
- package/lib/VersionCheck.js +46 -0
- package/lib/Watcher.js +117 -0
- package/lib/Worker.js +169 -0
- package/lib/binaries/CLI.js +1041 -0
- package/lib/binaries/DevCLI.js +183 -0
- package/lib/binaries/Runtime.js +101 -0
- package/lib/binaries/Runtime4Docker.js +192 -0
- package/lib/completion.js +229 -0
- package/lib/completion.sh +40 -0
- package/lib/motd +36 -0
- package/lib/templates/Dockerfiles/Dockerfile-java.tpl +7 -0
- package/lib/templates/Dockerfiles/Dockerfile-nodejs.tpl +8 -0
- package/lib/templates/Dockerfiles/Dockerfile-ruby.tpl +7 -0
- package/lib/templates/ecosystem-es.tpl +24 -0
- package/lib/templates/ecosystem-simple-es.tpl +8 -0
- package/lib/templates/ecosystem-simple.tpl +6 -0
- package/lib/templates/ecosystem.tpl +22 -0
- package/lib/templates/init-scripts/launchd.tpl +35 -0
- package/lib/templates/init-scripts/openrc.tpl +52 -0
- package/lib/templates/init-scripts/pm2-init-amazon.sh +86 -0
- package/lib/templates/init-scripts/rcd-openbsd.tpl +41 -0
- package/lib/templates/init-scripts/rcd.tpl +44 -0
- package/lib/templates/init-scripts/smf.tpl +43 -0
- package/lib/templates/init-scripts/systemd-online.tpl +22 -0
- package/lib/templates/init-scripts/systemd.tpl +22 -0
- package/lib/templates/init-scripts/upstart.tpl +103 -0
- package/lib/templates/logrotate.d/pm2 +10 -0
- package/lib/templates/sample-apps/http-server/README.md +14 -0
- package/lib/templates/sample-apps/http-server/api.js +9 -0
- package/lib/templates/sample-apps/http-server/ecosystem.config.js +14 -0
- package/lib/templates/sample-apps/http-server/package.json +11 -0
- package/lib/templates/sample-apps/pm2-plus-metrics-actions/README.md +45 -0
- package/lib/templates/sample-apps/pm2-plus-metrics-actions/custom-metrics.js +66 -0
- package/lib/templates/sample-apps/pm2-plus-metrics-actions/ecosystem.config.js +12 -0
- package/lib/templates/sample-apps/pm2-plus-metrics-actions/package.json +11 -0
- package/lib/templates/sample-apps/python-app/README.md +4 -0
- package/lib/templates/sample-apps/python-app/echo.py +7 -0
- package/lib/templates/sample-apps/python-app/ecosystem.config.js +12 -0
- package/lib/templates/sample-apps/python-app/package.json +11 -0
- package/lib/tools/Config.js +248 -0
- package/lib/tools/IsAbsolute.js +20 -0
- package/lib/tools/copydirSync.js +101 -0
- package/lib/tools/deleteFolderRecursive.js +19 -0
- package/lib/tools/find-package-json.js +74 -0
- package/lib/tools/fmt.js +72 -0
- package/lib/tools/isbinaryfile.js +94 -0
- package/lib/tools/json5.js +752 -0
- package/lib/tools/open.js +63 -0
- package/lib/tools/passwd.js +58 -0
- package/lib/tools/promise.min.js +1 -0
- package/lib/tools/sexec.js +55 -0
- package/lib/tools/treeify.js +113 -0
- package/lib/tools/which.js +120 -0
- package/lib/tools/xdg-open +861 -0
- package/package.json +219 -0
- package/paths.js +93 -0
- package/pm2 +11 -0
- package/preinstall.js +24 -0
- package/run.sh +9 -0
- package/types/index.d.ts +722 -0
- package/types/tsconfig.json +14 -0
package/lib/API/Monit.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
|
|
3
|
+
* Use of this source code is governed by a license that
|
|
4
|
+
* can be found in the LICENSE file.
|
|
5
|
+
*/
|
|
6
|
+
// pm2-htop
|
|
7
|
+
// Library who interacts with PM2 to display processes resources in htop way
|
|
8
|
+
// by Strzelewicz Alexandre
|
|
9
|
+
|
|
10
|
+
var multimeter = require('pm2-multimeter');
|
|
11
|
+
var os = require('os');
|
|
12
|
+
var p = require('path');
|
|
13
|
+
var chalk = require('ansis');
|
|
14
|
+
|
|
15
|
+
var UX = require('./UX');
|
|
16
|
+
|
|
17
|
+
var debug = require('debug')('zm2:monit');
|
|
18
|
+
|
|
19
|
+
// Cst for light programs
|
|
20
|
+
const RATIO_T1 = Math.floor(os.totalmem() / 500);
|
|
21
|
+
// Cst for medium programs
|
|
22
|
+
const RATIO_T2 = Math.floor(os.totalmem() / 50);
|
|
23
|
+
// Cst for heavy programs
|
|
24
|
+
const RATIO_T3 = Math.floor(os.totalmem() / 5);
|
|
25
|
+
// Cst for heavy programs
|
|
26
|
+
const RATIO_T4 = Math.floor(os.totalmem());
|
|
27
|
+
|
|
28
|
+
var Monit = {};
|
|
29
|
+
|
|
30
|
+
//helper to get bars.length (num bars printed)
|
|
31
|
+
Object.size = function(obj) {
|
|
32
|
+
var size = 0, key;
|
|
33
|
+
for (key in obj) {
|
|
34
|
+
if (obj.hasOwnProperty(key)) size++;
|
|
35
|
+
}
|
|
36
|
+
return size;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Reset the monitor through charm, basically \033c
|
|
41
|
+
* @param String msg optional message to show
|
|
42
|
+
* @return Monit
|
|
43
|
+
*/
|
|
44
|
+
Monit.reset = function(msg) {
|
|
45
|
+
|
|
46
|
+
this.multi.charm.reset();
|
|
47
|
+
|
|
48
|
+
this.multi.write('\x1B[32m⌬ PM2 \x1B[39mmonitoring\x1B[96m (To go further check out https://app.pm2.io) \x1B[39m\n\n');
|
|
49
|
+
|
|
50
|
+
if(msg) {
|
|
51
|
+
this.multi.write(msg);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
this.bars = {};
|
|
55
|
+
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Synchronous Monitor init method
|
|
61
|
+
* @method init
|
|
62
|
+
* @return Monit
|
|
63
|
+
*/
|
|
64
|
+
Monit.init = function() {
|
|
65
|
+
|
|
66
|
+
this.multi = multimeter(process);
|
|
67
|
+
|
|
68
|
+
this.multi.on('^C', this.stop);
|
|
69
|
+
|
|
70
|
+
this.reset();
|
|
71
|
+
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Stops monitor
|
|
77
|
+
* @method stop
|
|
78
|
+
*/
|
|
79
|
+
Monit.stop = function() {
|
|
80
|
+
this.multi.charm.destroy();
|
|
81
|
+
process.exit(0);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Refresh monitor
|
|
87
|
+
* @method refresh
|
|
88
|
+
* @param {} processes
|
|
89
|
+
* @return this
|
|
90
|
+
*/
|
|
91
|
+
Monit.refresh = function(processes) {
|
|
92
|
+
debug('Monit refresh');
|
|
93
|
+
|
|
94
|
+
if(!processes) {
|
|
95
|
+
processes = [];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
var num = processes.length;
|
|
99
|
+
this.num_bars = Object.size(this.bars);
|
|
100
|
+
|
|
101
|
+
if(num !== this.num_bars) {
|
|
102
|
+
debug('Monit addProcesses - actual: %s, new: %s', this.num_bars, num);
|
|
103
|
+
return this.addProcesses(processes);
|
|
104
|
+
} else {
|
|
105
|
+
|
|
106
|
+
if(num === 0) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
debug('Monit refresh');
|
|
111
|
+
var proc;
|
|
112
|
+
|
|
113
|
+
for(var i = 0; i < num; i++) {
|
|
114
|
+
proc = processes[i];
|
|
115
|
+
|
|
116
|
+
//this is to avoid a print issue when the process is restarted for example
|
|
117
|
+
//we might also check for the pid but restarted|restarting will be rendered bad
|
|
118
|
+
if(this.bars[proc.pm_id] && proc.pm2_env.status !== this.bars[proc.pm_id].status) {
|
|
119
|
+
debug('bars for %s does not exist', proc.pm_id);
|
|
120
|
+
this.addProcesses(processes);
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
this.updateBars(proc);
|
|
125
|
+
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
Monit.addProcess = function(proc, i) {
|
|
133
|
+
if(proc.pm_id in this.bars) {
|
|
134
|
+
return ;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (proc.monit.error)
|
|
138
|
+
throw new Error(JSON.stringify(proc.monit.error));
|
|
139
|
+
|
|
140
|
+
var process_name = proc.pm2_env.name || p.basename(proc.pm2_env.pm_exec_path);
|
|
141
|
+
var status = proc.pm2_env.status == 'online' ? chalk.green.bold('●') : chalk.red.bold('●');
|
|
142
|
+
|
|
143
|
+
this.multi.write(' ' + status + ' ' + chalk.green.bold(process_name));
|
|
144
|
+
this.multi.write('\n');
|
|
145
|
+
this.multi.write('[' + proc.pm2_env.pm_id + '] [' + proc.pm2_env.exec_mode + ']\n');
|
|
146
|
+
|
|
147
|
+
var bar_cpu = this.multi(40, (i * 2) + 3 + i, {
|
|
148
|
+
width: 30,
|
|
149
|
+
solid: {
|
|
150
|
+
text: '|',
|
|
151
|
+
foreground: 'white',
|
|
152
|
+
background: 'blue'
|
|
153
|
+
},
|
|
154
|
+
empty: {
|
|
155
|
+
text: ' '
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
var bar_memory = this.multi(40, (i * 2) + 4 + i, {
|
|
160
|
+
width: 30,
|
|
161
|
+
solid: {
|
|
162
|
+
text: '|',
|
|
163
|
+
foreground: 'white',
|
|
164
|
+
background: 'red'
|
|
165
|
+
},
|
|
166
|
+
empty: {
|
|
167
|
+
text: ' '
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
this.bars[proc.pm_id] = {
|
|
172
|
+
memory: bar_memory,
|
|
173
|
+
cpu: bar_cpu,
|
|
174
|
+
status: proc.pm2_env.status
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
this.updateBars(proc);
|
|
178
|
+
|
|
179
|
+
this.multi.write('\n');
|
|
180
|
+
|
|
181
|
+
return this;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
Monit.addProcesses = function(processes) {
|
|
185
|
+
|
|
186
|
+
if(!processes) {
|
|
187
|
+
processes = [];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
this.reset();
|
|
191
|
+
|
|
192
|
+
var num = processes.length;
|
|
193
|
+
|
|
194
|
+
if(num > 0) {
|
|
195
|
+
for(var i = 0; i < num; i++) {
|
|
196
|
+
this.addProcess(processes[i], i);
|
|
197
|
+
}
|
|
198
|
+
} else {
|
|
199
|
+
this.reset('No processes to monit');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Draw memory bars
|
|
205
|
+
/**
|
|
206
|
+
* Description
|
|
207
|
+
* @method drawRatio
|
|
208
|
+
* @param {} bar_memory
|
|
209
|
+
* @param {} memory
|
|
210
|
+
* @return
|
|
211
|
+
*/
|
|
212
|
+
Monit.drawRatio = function(bar_memory, memory) {
|
|
213
|
+
var scale = 0;
|
|
214
|
+
|
|
215
|
+
if (memory < RATIO_T1) scale = RATIO_T1;
|
|
216
|
+
else if (memory < RATIO_T2) scale = RATIO_T2;
|
|
217
|
+
else if (memory < RATIO_T3) scale = RATIO_T3;
|
|
218
|
+
else scale = RATIO_T4;
|
|
219
|
+
|
|
220
|
+
bar_memory.ratio(memory,
|
|
221
|
+
scale,
|
|
222
|
+
UX.helpers.bytesToSize(memory, 3));
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Updates bars informations
|
|
227
|
+
* @param {} proc proc object
|
|
228
|
+
* @return this
|
|
229
|
+
*/
|
|
230
|
+
Monit.updateBars = function(proc) {
|
|
231
|
+
if (this.bars[proc.pm_id]) {
|
|
232
|
+
if (proc.pm2_env.status !== 'online' || proc.pm2_env.status !== this.bars[proc.pm_id].status) {
|
|
233
|
+
this.bars[proc.pm_id].cpu.percent(0, chalk.red(proc.pm2_env.status));
|
|
234
|
+
this.drawRatio(this.bars[proc.pm_id].memory, 0, chalk.red(proc.pm2_env.status));
|
|
235
|
+
} else if (!proc.monit) {
|
|
236
|
+
this.bars[proc.pm_id].cpu.percent(0, chalk.red('No data'));
|
|
237
|
+
this.drawRatio(this.bars[proc.pm_id].memory, 0, chalk.red('No data'));
|
|
238
|
+
} else {
|
|
239
|
+
this.bars[proc.pm_id].cpu.percent(proc.monit.cpu);
|
|
240
|
+
this.drawRatio(this.bars[proc.pm_id].memory, proc.monit.memory);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return this;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
module.exports = Monit;
|
package/lib/API/Serve.js
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
|
|
3
|
+
* Use of this source code is governed by a license that
|
|
4
|
+
* can be found in the LICENSE file.
|
|
5
|
+
*/
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
var fs = require('fs');
|
|
9
|
+
var http = require('http');
|
|
10
|
+
var url = require('url');
|
|
11
|
+
var path = require('path');
|
|
12
|
+
var debug = require('debug')('zm2:serve');
|
|
13
|
+
|
|
14
|
+
// var probe = require('@pm2/io');
|
|
15
|
+
// var errorMeter = probe.meter({
|
|
16
|
+
// name : '404/sec',
|
|
17
|
+
// samples : 1,
|
|
18
|
+
// timeframe : 60
|
|
19
|
+
// })
|
|
20
|
+
/**
|
|
21
|
+
* list of supported content types.
|
|
22
|
+
*/
|
|
23
|
+
var contentTypes = {
|
|
24
|
+
'3gp': 'video/3gpp',
|
|
25
|
+
'a': 'application/octet-stream',
|
|
26
|
+
'ai': 'application/postscript',
|
|
27
|
+
'aif': 'audio/x-aiff',
|
|
28
|
+
'aiff': 'audio/x-aiff',
|
|
29
|
+
'asc': 'application/pgp-signature',
|
|
30
|
+
'asf': 'video/x-ms-asf',
|
|
31
|
+
'asm': 'text/x-asm',
|
|
32
|
+
'asx': 'video/x-ms-asf',
|
|
33
|
+
'atom': 'application/atom+xml',
|
|
34
|
+
'au': 'audio/basic',
|
|
35
|
+
'avi': 'video/x-msvideo',
|
|
36
|
+
'bat': 'application/x-msdownload',
|
|
37
|
+
'bin': 'application/octet-stream',
|
|
38
|
+
'bmp': 'image/bmp',
|
|
39
|
+
'bz2': 'application/x-bzip2',
|
|
40
|
+
'c': 'text/x-c',
|
|
41
|
+
'cab': 'application/vnd.ms-cab-compressed',
|
|
42
|
+
'cc': 'text/x-c',
|
|
43
|
+
'chm': 'application/vnd.ms-htmlhelp',
|
|
44
|
+
'class': 'application/octet-stream',
|
|
45
|
+
'com': 'application/x-msdownload',
|
|
46
|
+
'conf': 'text/plain',
|
|
47
|
+
'cpp': 'text/x-c',
|
|
48
|
+
'crt': 'application/x-x509-ca-cert',
|
|
49
|
+
'css': 'text/css',
|
|
50
|
+
'csv': 'text/csv',
|
|
51
|
+
'cxx': 'text/x-c',
|
|
52
|
+
'deb': 'application/x-debian-package',
|
|
53
|
+
'der': 'application/x-x509-ca-cert',
|
|
54
|
+
'diff': 'text/x-diff',
|
|
55
|
+
'djv': 'image/vnd.djvu',
|
|
56
|
+
'djvu': 'image/vnd.djvu',
|
|
57
|
+
'dll': 'application/x-msdownload',
|
|
58
|
+
'dmg': 'application/octet-stream',
|
|
59
|
+
'doc': 'application/msword',
|
|
60
|
+
'dot': 'application/msword',
|
|
61
|
+
'dtd': 'application/xml-dtd',
|
|
62
|
+
'dvi': 'application/x-dvi',
|
|
63
|
+
'ear': 'application/java-archive',
|
|
64
|
+
'eml': 'message/rfc822',
|
|
65
|
+
'eps': 'application/postscript',
|
|
66
|
+
'exe': 'application/x-msdownload',
|
|
67
|
+
'f': 'text/x-fortran',
|
|
68
|
+
'f77': 'text/x-fortran',
|
|
69
|
+
'f90': 'text/x-fortran',
|
|
70
|
+
'flv': 'video/x-flv',
|
|
71
|
+
'for': 'text/x-fortran',
|
|
72
|
+
'gem': 'application/octet-stream',
|
|
73
|
+
'gemspec': 'text/x-script.ruby',
|
|
74
|
+
'gif': 'image/gif',
|
|
75
|
+
'gz': 'application/x-gzip',
|
|
76
|
+
'h': 'text/x-c',
|
|
77
|
+
'hh': 'text/x-c',
|
|
78
|
+
'htm': 'text/html',
|
|
79
|
+
'html': 'text/html',
|
|
80
|
+
'ico': 'image/vnd.microsoft.icon',
|
|
81
|
+
'ics': 'text/calendar',
|
|
82
|
+
'ifb': 'text/calendar',
|
|
83
|
+
'iso': 'application/octet-stream',
|
|
84
|
+
'jar': 'application/java-archive',
|
|
85
|
+
'java': 'text/x-java-source',
|
|
86
|
+
'jnlp': 'application/x-java-jnlp-file',
|
|
87
|
+
'jpeg': 'image/jpeg',
|
|
88
|
+
'jpg': 'image/jpeg',
|
|
89
|
+
'js': 'application/javascript',
|
|
90
|
+
'json': 'application/json',
|
|
91
|
+
'log': 'text/plain',
|
|
92
|
+
'm3u': 'audio/x-mpegurl',
|
|
93
|
+
'm4v': 'video/mp4',
|
|
94
|
+
'man': 'text/troff',
|
|
95
|
+
'mathml': 'application/mathml+xml',
|
|
96
|
+
'mbox': 'application/mbox',
|
|
97
|
+
'mdoc': 'text/troff',
|
|
98
|
+
'me': 'text/troff',
|
|
99
|
+
'mid': 'audio/midi',
|
|
100
|
+
'midi': 'audio/midi',
|
|
101
|
+
'mime': 'message/rfc822',
|
|
102
|
+
'mml': 'application/mathml+xml',
|
|
103
|
+
'mng': 'video/x-mng',
|
|
104
|
+
'mov': 'video/quicktime',
|
|
105
|
+
'mp3': 'audio/mpeg',
|
|
106
|
+
'mp4': 'video/mp4',
|
|
107
|
+
'mp4v': 'video/mp4',
|
|
108
|
+
'mpeg': 'video/mpeg',
|
|
109
|
+
'mpg': 'video/mpeg',
|
|
110
|
+
'ms': 'text/troff',
|
|
111
|
+
'msi': 'application/x-msdownload',
|
|
112
|
+
'odp': 'application/vnd.oasis.opendocument.presentation',
|
|
113
|
+
'ods': 'application/vnd.oasis.opendocument.spreadsheet',
|
|
114
|
+
'odt': 'application/vnd.oasis.opendocument.text',
|
|
115
|
+
'ogg': 'application/ogg',
|
|
116
|
+
'p': 'text/x-pascal',
|
|
117
|
+
'pas': 'text/x-pascal',
|
|
118
|
+
'pbm': 'image/x-portable-bitmap',
|
|
119
|
+
'pdf': 'application/pdf',
|
|
120
|
+
'pem': 'application/x-x509-ca-cert',
|
|
121
|
+
'pgm': 'image/x-portable-graymap',
|
|
122
|
+
'pgp': 'application/pgp-encrypted',
|
|
123
|
+
'pkg': 'application/octet-stream',
|
|
124
|
+
'pl': 'text/x-script.perl',
|
|
125
|
+
'pm': 'text/x-script.perl-module',
|
|
126
|
+
'png': 'image/png',
|
|
127
|
+
'pnm': 'image/x-portable-anymap',
|
|
128
|
+
'ppm': 'image/x-portable-pixmap',
|
|
129
|
+
'pps': 'application/vnd.ms-powerpoint',
|
|
130
|
+
'ppt': 'application/vnd.ms-powerpoint',
|
|
131
|
+
'ps': 'application/postscript',
|
|
132
|
+
'psd': 'image/vnd.adobe.photoshop',
|
|
133
|
+
'py': 'text/x-script.python',
|
|
134
|
+
'qt': 'video/quicktime',
|
|
135
|
+
'ra': 'audio/x-pn-realaudio',
|
|
136
|
+
'rake': 'text/x-script.ruby',
|
|
137
|
+
'ram': 'audio/x-pn-realaudio',
|
|
138
|
+
'rar': 'application/x-rar-compressed',
|
|
139
|
+
'rb': 'text/x-script.ruby',
|
|
140
|
+
'rdf': 'application/rdf+xml',
|
|
141
|
+
'roff': 'text/troff',
|
|
142
|
+
'rpm': 'application/x-redhat-package-manager',
|
|
143
|
+
'rss': 'application/rss+xml',
|
|
144
|
+
'rtf': 'application/rtf',
|
|
145
|
+
'ru': 'text/x-script.ruby',
|
|
146
|
+
's': 'text/x-asm',
|
|
147
|
+
'sgm': 'text/sgml',
|
|
148
|
+
'sgml': 'text/sgml',
|
|
149
|
+
'sh': 'application/x-sh',
|
|
150
|
+
'sig': 'application/pgp-signature',
|
|
151
|
+
'snd': 'audio/basic',
|
|
152
|
+
'so': 'application/octet-stream',
|
|
153
|
+
'svg': 'image/svg+xml',
|
|
154
|
+
'svgz': 'image/svg+xml',
|
|
155
|
+
'swf': 'application/x-shockwave-flash',
|
|
156
|
+
't': 'text/troff',
|
|
157
|
+
'tar': 'application/x-tar',
|
|
158
|
+
'tbz': 'application/x-bzip-compressed-tar',
|
|
159
|
+
'tcl': 'application/x-tcl',
|
|
160
|
+
'tex': 'application/x-tex',
|
|
161
|
+
'texi': 'application/x-texinfo',
|
|
162
|
+
'texinfo': 'application/x-texinfo',
|
|
163
|
+
'text': 'text/plain',
|
|
164
|
+
'tif': 'image/tiff',
|
|
165
|
+
'tiff': 'image/tiff',
|
|
166
|
+
'torrent': 'application/x-bittorrent',
|
|
167
|
+
'tr': 'text/troff',
|
|
168
|
+
'txt': 'text/plain',
|
|
169
|
+
'vcf': 'text/x-vcard',
|
|
170
|
+
'vcs': 'text/x-vcalendar',
|
|
171
|
+
'vrml': 'model/vrml',
|
|
172
|
+
'war': 'application/java-archive',
|
|
173
|
+
'wav': 'audio/x-wav',
|
|
174
|
+
'webp': 'image/webp',
|
|
175
|
+
'wma': 'audio/x-ms-wma',
|
|
176
|
+
'wmv': 'video/x-ms-wmv',
|
|
177
|
+
'wmx': 'video/x-ms-wmx',
|
|
178
|
+
'wrl': 'model/vrml',
|
|
179
|
+
'wsdl': 'application/wsdl+xml',
|
|
180
|
+
'xbm': 'image/x-xbitmap',
|
|
181
|
+
'xhtml': 'application/xhtml+xml',
|
|
182
|
+
'xls': 'application/vnd.ms-excel',
|
|
183
|
+
'xml': 'application/xml',
|
|
184
|
+
'xpm': 'image/x-xpixmap',
|
|
185
|
+
'xsl': 'application/xml',
|
|
186
|
+
'xslt': 'application/xslt+xml',
|
|
187
|
+
'yaml': 'text/yaml',
|
|
188
|
+
'yml': 'text/yaml',
|
|
189
|
+
'zip': 'application/zip',
|
|
190
|
+
'woff': 'application/font-woff',
|
|
191
|
+
'woff2': 'application/font-woff',
|
|
192
|
+
'otf': 'application/font-sfnt',
|
|
193
|
+
'otc': 'application/font-sfnt',
|
|
194
|
+
'ttf': 'application/font-sfnt'
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
var options = {
|
|
198
|
+
port: process.env.PM2_SERVE_PORT || process.argv[3] || 8080,
|
|
199
|
+
host: process.env.PM2_SERVE_HOST || process.argv[4] || '0.0.0.0',
|
|
200
|
+
path: path.resolve(process.env.PM2_SERVE_PATH || process.argv[2] || '.'),
|
|
201
|
+
spa: process.env.PM2_SERVE_SPA === 'true',
|
|
202
|
+
homepage: process.env.PM2_SERVE_HOMEPAGE || '/index.html',
|
|
203
|
+
basic_auth: process.env.PM2_SERVE_BASIC_AUTH === 'true' ? {
|
|
204
|
+
username: process.env.PM2_SERVE_BASIC_AUTH_USERNAME,
|
|
205
|
+
password: process.env.PM2_SERVE_BASIC_AUTH_PASSWORD
|
|
206
|
+
} : null,
|
|
207
|
+
monitor: process.env.PM2_SERVE_MONITOR
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
if (typeof options.port === 'string') {
|
|
211
|
+
options.port = parseInt(options.port) || 8080
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (typeof options.monitor === 'string' && options.monitor !== '') {
|
|
215
|
+
try {
|
|
216
|
+
let fileContent = fs.readFileSync(path.join(process.env.PM2_HOME, 'agent.json5')).toString()
|
|
217
|
+
// Handle old configuration with json5
|
|
218
|
+
fileContent = fileContent.replace(/\s(\w+):/g, '"$1":')
|
|
219
|
+
// parse
|
|
220
|
+
let conf = JSON.parse(fileContent)
|
|
221
|
+
options.monitorBucket = conf.public_key
|
|
222
|
+
} catch (e) {
|
|
223
|
+
console.log('Interaction file does not exist')
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// start an HTTP server
|
|
228
|
+
http.createServer(function (request, response) {
|
|
229
|
+
if (options.basic_auth) {
|
|
230
|
+
if (!request.headers.authorization || request.headers.authorization.indexOf('Basic ') === -1) {
|
|
231
|
+
return sendBasicAuthResponse(response)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
var user = parseBasicAuth(request.headers.authorization)
|
|
235
|
+
if (user.username !== options.basic_auth.username || user.password !== options.basic_auth.password) {
|
|
236
|
+
return sendBasicAuthResponse(response)
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
serveFile(request.url, request, response);
|
|
241
|
+
|
|
242
|
+
}).listen(options.port, options.host, function (err) {
|
|
243
|
+
if (err) {
|
|
244
|
+
console.error(err);
|
|
245
|
+
process.exit(1);
|
|
246
|
+
}
|
|
247
|
+
console.log('Exposing %s directory on %s:%d', options.path, options.host, options.port);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
function serveFile(uri, request, response) {
|
|
251
|
+
var file = decodeURIComponent(url.parse(uri || request.url).pathname);
|
|
252
|
+
|
|
253
|
+
if (file === '/' || file === '') {
|
|
254
|
+
file = options.homepage;
|
|
255
|
+
request.wantHomepage = true;
|
|
256
|
+
}
|
|
257
|
+
var filePath = path.resolve(options.path + file);
|
|
258
|
+
|
|
259
|
+
// since we call filesystem directly so we need to verify that the
|
|
260
|
+
// url doesn't go outside the serve path
|
|
261
|
+
if (filePath.indexOf(options.path) !== 0) {
|
|
262
|
+
response.writeHead(403, { 'Content-Type': 'text/html' });
|
|
263
|
+
return response.end('403 Forbidden');
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
var contentType = contentTypes[filePath.split('.').pop().toLowerCase()] || 'text/plain';
|
|
267
|
+
|
|
268
|
+
fs.readFile(filePath, function (error, content) {
|
|
269
|
+
if (error) {
|
|
270
|
+
if ((!options.spa || file === options.homepage)) {
|
|
271
|
+
console.error('[%s] Error while serving %s with content-type %s : %s',
|
|
272
|
+
new Date(), filePath, contentType, error.message || error);
|
|
273
|
+
}
|
|
274
|
+
//errorMeter.mark();
|
|
275
|
+
if (error.code === 'ENOENT') {
|
|
276
|
+
if (options.spa && !request.wantHomepage) {
|
|
277
|
+
request.wantHomepage = true;
|
|
278
|
+
return serveFile(`/${path.basename(file)}`, request, response);
|
|
279
|
+
} else if (options.spa && file !== options.homepage) {
|
|
280
|
+
return serveFile(options.homepage, request, response);
|
|
281
|
+
}
|
|
282
|
+
fs.readFile(options.path + '/404.html', function (err, content) {
|
|
283
|
+
content = err ? '404 Not Found' : content;
|
|
284
|
+
response.writeHead(404, { 'Content-Type': 'text/html' });
|
|
285
|
+
return response.end(content, 'utf-8');
|
|
286
|
+
});
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
response.writeHead(500);
|
|
290
|
+
return response.end('Sorry, check with the site admin for error: ' + error.code + ' ..\n');
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Add CORS headers to allow browsers to fetch data directly
|
|
294
|
+
response.writeHead(200, {
|
|
295
|
+
'Content-Type': contentType,
|
|
296
|
+
'Access-Control-Allow-Origin': '*',
|
|
297
|
+
'Access-Control-Allow-Methods': 'GET'
|
|
298
|
+
});
|
|
299
|
+
if (options.monitorBucket && contentType === 'text/html') {
|
|
300
|
+
content = content.toString().replace('</body>', `
|
|
301
|
+
<script>
|
|
302
|
+
;(function (b,e,n,o,i,t) {
|
|
303
|
+
b[o]=b[o]||function(f){(b[o].c=b[o].c||[]).push(f)};
|
|
304
|
+
t=e.createElement(i);e=e.getElementsByTagName(i)[0];
|
|
305
|
+
t.async=1;t.src=n;e.parentNode.insertBefore(t,e);
|
|
306
|
+
}(window,document,'https://apm.pm2.io/pm2-io-apm-browser.v1.js','pm2Ready','script'))
|
|
307
|
+
|
|
308
|
+
pm2Ready(function(apm) {
|
|
309
|
+
apm.setBucket('${options.monitorBucket}')
|
|
310
|
+
apm.setApplication('${options.monitor}')
|
|
311
|
+
apm.reportTimings()
|
|
312
|
+
apm.reportIssues()
|
|
313
|
+
})
|
|
314
|
+
</script>
|
|
315
|
+
</body>
|
|
316
|
+
`);
|
|
317
|
+
}
|
|
318
|
+
response.end(content, 'utf-8');
|
|
319
|
+
debug('[%s] Serving %s with content-type %s', Date.now(), filePath, contentType);
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function parseBasicAuth(auth) {
|
|
324
|
+
// auth is like `Basic Y2hhcmxlczoxMjM0NQ==`
|
|
325
|
+
var tmp = auth.split(' ');
|
|
326
|
+
|
|
327
|
+
var buf = Buffer.from(tmp[1], 'base64');
|
|
328
|
+
var plain = buf.toString();
|
|
329
|
+
|
|
330
|
+
var creds = plain.split(':');
|
|
331
|
+
return {
|
|
332
|
+
username: creds[0],
|
|
333
|
+
password: creds[1]
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function sendBasicAuthResponse(response) {
|
|
338
|
+
response.writeHead(401, {
|
|
339
|
+
'Content-Type': 'text/html',
|
|
340
|
+
'WWW-Authenticate': 'Basic realm="Authentication service"'
|
|
341
|
+
});
|
|
342
|
+
return response.end('401 Unauthorized');
|
|
343
|
+
}
|