@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.
Files changed (133) hide show
  1. package/.claude/settings.local.json +8 -0
  2. package/.gitattributes +4 -0
  3. package/.mocharc.js +14 -0
  4. package/CHANGELOG.md +2416 -0
  5. package/CLAUDE.md +84 -0
  6. package/CONTRIBUTING.md +124 -0
  7. package/GNU-AGPL-3.0.txt +665 -0
  8. package/LICENSE +1 -0
  9. package/README.md +248 -0
  10. package/bin/zm2 +3 -0
  11. package/bin/zm2-dev +3 -0
  12. package/bin/zm2-docker +3 -0
  13. package/bin/zm2-runtime +3 -0
  14. package/bin/zm2-windows +3 -0
  15. package/bin/zm2.ps1 +3 -0
  16. package/bun.lock +421 -0
  17. package/constants.js +114 -0
  18. package/index.js +13 -0
  19. package/lib/API/Configuration.js +212 -0
  20. package/lib/API/Containerizer.js +335 -0
  21. package/lib/API/Dashboard.js +459 -0
  22. package/lib/API/Deploy.js +117 -0
  23. package/lib/API/Extra.js +775 -0
  24. package/lib/API/ExtraMgmt/Docker.js +30 -0
  25. package/lib/API/Log.js +315 -0
  26. package/lib/API/LogManagement.js +371 -0
  27. package/lib/API/Modules/LOCAL.js +122 -0
  28. package/lib/API/Modules/Modularizer.js +148 -0
  29. package/lib/API/Modules/NPM.js +445 -0
  30. package/lib/API/Modules/TAR.js +362 -0
  31. package/lib/API/Modules/flagExt.js +46 -0
  32. package/lib/API/Modules/index.js +120 -0
  33. package/lib/API/Monit.js +247 -0
  34. package/lib/API/Serve.js +343 -0
  35. package/lib/API/Startup.js +629 -0
  36. package/lib/API/UX/helpers.js +213 -0
  37. package/lib/API/UX/index.js +9 -0
  38. package/lib/API/UX/pm2-describe.js +193 -0
  39. package/lib/API/UX/pm2-ls-minimal.js +31 -0
  40. package/lib/API/UX/pm2-ls.js +483 -0
  41. package/lib/API/Version.js +382 -0
  42. package/lib/API/interpreter.json +12 -0
  43. package/lib/API/pm2-plus/PM2IO.js +372 -0
  44. package/lib/API/pm2-plus/auth-strategies/CliAuth.js +288 -0
  45. package/lib/API/pm2-plus/auth-strategies/WebAuth.js +187 -0
  46. package/lib/API/pm2-plus/helpers.js +97 -0
  47. package/lib/API/pm2-plus/link.js +126 -0
  48. package/lib/API/pm2-plus/pres/motd +16 -0
  49. package/lib/API/pm2-plus/pres/motd.update +26 -0
  50. package/lib/API/pm2-plus/pres/welcome +28 -0
  51. package/lib/API/pm2-plus/process-selector.js +52 -0
  52. package/lib/API/schema.json +379 -0
  53. package/lib/API.js +1931 -0
  54. package/lib/Client.js +776 -0
  55. package/lib/Common.js +911 -0
  56. package/lib/Configuration.js +304 -0
  57. package/lib/Daemon.js +456 -0
  58. package/lib/Event.js +37 -0
  59. package/lib/God/ActionMethods.js +909 -0
  60. package/lib/God/ClusterMode.js +97 -0
  61. package/lib/God/ForkMode.js +297 -0
  62. package/lib/God/Methods.js +265 -0
  63. package/lib/God/Reload.js +240 -0
  64. package/lib/God.js +632 -0
  65. package/lib/HttpInterface.js +76 -0
  66. package/lib/ProcessContainer.js +305 -0
  67. package/lib/ProcessContainerBun.js +360 -0
  68. package/lib/ProcessContainerFork.js +42 -0
  69. package/lib/ProcessContainerForkBun.js +33 -0
  70. package/lib/ProcessUtils.js +55 -0
  71. package/lib/TreeKill.js +118 -0
  72. package/lib/Utility.js +430 -0
  73. package/lib/VersionCheck.js +46 -0
  74. package/lib/Watcher.js +117 -0
  75. package/lib/Worker.js +169 -0
  76. package/lib/binaries/CLI.js +1041 -0
  77. package/lib/binaries/DevCLI.js +183 -0
  78. package/lib/binaries/Runtime.js +101 -0
  79. package/lib/binaries/Runtime4Docker.js +192 -0
  80. package/lib/completion.js +229 -0
  81. package/lib/completion.sh +40 -0
  82. package/lib/motd +36 -0
  83. package/lib/templates/Dockerfiles/Dockerfile-java.tpl +7 -0
  84. package/lib/templates/Dockerfiles/Dockerfile-nodejs.tpl +8 -0
  85. package/lib/templates/Dockerfiles/Dockerfile-ruby.tpl +7 -0
  86. package/lib/templates/ecosystem-es.tpl +24 -0
  87. package/lib/templates/ecosystem-simple-es.tpl +8 -0
  88. package/lib/templates/ecosystem-simple.tpl +6 -0
  89. package/lib/templates/ecosystem.tpl +22 -0
  90. package/lib/templates/init-scripts/launchd.tpl +35 -0
  91. package/lib/templates/init-scripts/openrc.tpl +52 -0
  92. package/lib/templates/init-scripts/pm2-init-amazon.sh +86 -0
  93. package/lib/templates/init-scripts/rcd-openbsd.tpl +41 -0
  94. package/lib/templates/init-scripts/rcd.tpl +44 -0
  95. package/lib/templates/init-scripts/smf.tpl +43 -0
  96. package/lib/templates/init-scripts/systemd-online.tpl +22 -0
  97. package/lib/templates/init-scripts/systemd.tpl +22 -0
  98. package/lib/templates/init-scripts/upstart.tpl +103 -0
  99. package/lib/templates/logrotate.d/pm2 +10 -0
  100. package/lib/templates/sample-apps/http-server/README.md +14 -0
  101. package/lib/templates/sample-apps/http-server/api.js +9 -0
  102. package/lib/templates/sample-apps/http-server/ecosystem.config.js +14 -0
  103. package/lib/templates/sample-apps/http-server/package.json +11 -0
  104. package/lib/templates/sample-apps/pm2-plus-metrics-actions/README.md +45 -0
  105. package/lib/templates/sample-apps/pm2-plus-metrics-actions/custom-metrics.js +66 -0
  106. package/lib/templates/sample-apps/pm2-plus-metrics-actions/ecosystem.config.js +12 -0
  107. package/lib/templates/sample-apps/pm2-plus-metrics-actions/package.json +11 -0
  108. package/lib/templates/sample-apps/python-app/README.md +4 -0
  109. package/lib/templates/sample-apps/python-app/echo.py +7 -0
  110. package/lib/templates/sample-apps/python-app/ecosystem.config.js +12 -0
  111. package/lib/templates/sample-apps/python-app/package.json +11 -0
  112. package/lib/tools/Config.js +248 -0
  113. package/lib/tools/IsAbsolute.js +20 -0
  114. package/lib/tools/copydirSync.js +101 -0
  115. package/lib/tools/deleteFolderRecursive.js +19 -0
  116. package/lib/tools/find-package-json.js +74 -0
  117. package/lib/tools/fmt.js +72 -0
  118. package/lib/tools/isbinaryfile.js +94 -0
  119. package/lib/tools/json5.js +752 -0
  120. package/lib/tools/open.js +63 -0
  121. package/lib/tools/passwd.js +58 -0
  122. package/lib/tools/promise.min.js +1 -0
  123. package/lib/tools/sexec.js +55 -0
  124. package/lib/tools/treeify.js +113 -0
  125. package/lib/tools/which.js +120 -0
  126. package/lib/tools/xdg-open +861 -0
  127. package/package.json +219 -0
  128. package/paths.js +93 -0
  129. package/pm2 +11 -0
  130. package/preinstall.js +24 -0
  131. package/run.sh +9 -0
  132. package/types/index.d.ts +722 -0
  133. package/types/tsconfig.json +14 -0
@@ -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;
@@ -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
+ }