@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,371 @@
1
+ var chalk = require('ansis');
2
+ var util = require('util');
3
+ var fs = require('fs');
4
+ var exec = require('child_process').exec;
5
+ var path = require('path');
6
+
7
+ var Log = require('./Log');
8
+ var cst = require('../../constants.js');
9
+ var Common = require('../Common.js');
10
+
11
+ module.exports = function(CLI) {
12
+
13
+ /**
14
+ * Description
15
+ * @method flush
16
+ * @return
17
+ */
18
+ CLI.prototype.flush = function(api, cb) {
19
+ var that = this;
20
+
21
+ if (!api) {
22
+ Common.printOut(cst.PREFIX_MSG + 'Flushing ' + cst.PM2_LOG_FILE_PATH);
23
+ fs.closeSync(fs.openSync(cst.PM2_LOG_FILE_PATH, 'w'));
24
+ }
25
+
26
+ that.Client.executeRemote('getMonitorData', {}, function(err, list) {
27
+ if (err) {
28
+ Common.printError(err);
29
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
30
+ }
31
+ list.forEach(function(l) {
32
+ if (typeof api == 'undefined') {
33
+ Common.printOut(cst.PREFIX_MSG + 'Flushing:');
34
+ Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_out_log_path);
35
+ Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_err_log_path);
36
+
37
+ if (l.pm2_env.pm_log_path) {
38
+ Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_log_path);
39
+ fs.closeSync(fs.openSync(l.pm2_env.pm_log_path, 'w'));
40
+ }
41
+ fs.closeSync(fs.openSync(l.pm2_env.pm_out_log_path, 'w'));
42
+ fs.closeSync(fs.openSync(l.pm2_env.pm_err_log_path, 'w'));
43
+ }
44
+ else if (l.pm2_env.pm_id == api || l.pm2_env.name === api) {
45
+ Common.printOut(cst.PREFIX_MSG + 'Flushing:');
46
+
47
+ if (l.pm2_env.pm_log_path && fs.existsSync(l.pm2_env.pm_log_path)) {
48
+ Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_log_path);
49
+ fs.closeSync(fs.openSync(l.pm2_env.pm_log_path, 'w'));
50
+ }
51
+
52
+ if (l.pm2_env.pm_out_log_path && fs.existsSync(l.pm2_env.pm_out_log_path)) {
53
+ Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_out_log_path);
54
+ fs.closeSync(fs.openSync(l.pm2_env.pm_out_log_path, 'w'));
55
+ }
56
+
57
+ if (l.pm2_env.pm_err_log_path && fs.existsSync(l.pm2_env.pm_err_log_path)) {
58
+ Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_err_log_path);
59
+ fs.closeSync(fs.openSync(l.pm2_env.pm_err_log_path, 'w'));
60
+ }
61
+ }
62
+ });
63
+
64
+ Common.printOut(cst.PREFIX_MSG + 'Logs flushed');
65
+ return cb ? cb(null, list) : that.exitCli(cst.SUCCESS_EXIT);
66
+ });
67
+ };
68
+
69
+ CLI.prototype.logrotate = function(opts, cb) {
70
+ var that = this;
71
+
72
+ if (process.getuid() != 0) {
73
+ return exec('whoami', function(err, stdout, stderr) {
74
+ Common.printError(cst.PREFIX_MSG + 'You have to run this command as root. Execute the following command:');
75
+ Common.printError(cst.PREFIX_MSG + chalk.gray(' sudo env PATH=$PATH:' + path.dirname(process.execPath) + ' pm2 logrotate -u ' + stdout.trim()));
76
+
77
+ cb ? cb(Common.retErr('You have to run this with elevated rights')) : that.exitCli(cst.ERROR_EXIT);
78
+ });
79
+ }
80
+
81
+ if (!fs.existsSync('/etc/logrotate.d')) {
82
+ Common.printError(cst.PREFIX_MSG + '/etc/logrotate.d does not exist we can not copy the default configuration.');
83
+ return cb ? cb(Common.retErr('/etc/logrotate.d does not exist')) : that.exitCli(cst.ERROR_EXIT);
84
+ }
85
+
86
+ var templatePath = path.join(cst.TEMPLATE_FOLDER, cst.LOGROTATE_SCRIPT);
87
+ Common.printOut(cst.PREFIX_MSG + 'Getting logrorate template ' + templatePath);
88
+ var script = fs.readFileSync(templatePath, {encoding: 'utf8'});
89
+
90
+ var user = opts.user || 'root';
91
+
92
+ script = script.replace(/%HOME_PATH%/g, cst.PM2_ROOT_PATH)
93
+ .replace(/%USER%/g, user);
94
+
95
+ try {
96
+ fs.writeFileSync('/etc/logrotate.d/pm2-'+user, script);
97
+ } catch (e) {
98
+ console.error(e.stack || e);
99
+ }
100
+
101
+ Common.printOut(cst.PREFIX_MSG + 'Logrotate configuration added to /etc/logrotate.d/pm2');
102
+ return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
103
+ };
104
+
105
+ /**
106
+ * Description
107
+ * @method reloadLogs
108
+ * @return
109
+ */
110
+ CLI.prototype.reloadLogs = function(cb) {
111
+ var that = this;
112
+
113
+ Common.printOut('Reloading all logs...');
114
+ that.Client.executeRemote('reloadLogs', {}, function(err, logs) {
115
+ if (err) {
116
+ Common.printError(err);
117
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
118
+ }
119
+ Common.printOut('All logs reloaded');
120
+ return cb ? cb(null, logs) : that.exitCli(cst.SUCCESS_EXIT);
121
+ });
122
+ };
123
+
124
+ /**
125
+ * Description
126
+ * @method streamLogs
127
+ * @param {String} id
128
+ * @param {Number} lines
129
+ * @param {Boolean} raw
130
+ * @return
131
+ */
132
+ CLI.prototype.streamLogs = function(id, lines, raw, timestamp, exclusive, highlight) {
133
+ var that = this;
134
+ var files_list = [];
135
+
136
+ // If no argument is given, we stream logs for all running apps
137
+ id = id || 'all';
138
+ lines = lines !== undefined ? lines : 20;
139
+ lines = lines < 0 ? -(lines) : lines;
140
+
141
+ // Avoid duplicates and check if path is different from '/dev/null'
142
+ var pushIfUnique = function(entry) {
143
+ var exists = false;
144
+
145
+ if (entry.path.toLowerCase
146
+ && entry.path.toLowerCase() !== '/dev/null') {
147
+
148
+ files_list.some(function(file) {
149
+ if (file.path === entry.path)
150
+ exists = true;
151
+ return exists;
152
+ });
153
+
154
+ if (exists)
155
+ return;
156
+
157
+ files_list.push(entry);
158
+ }
159
+ }
160
+
161
+ // Get the list of all running apps
162
+ that.Client.executeRemote('getMonitorData', {}, function(err, list) {
163
+ var regexList = [];
164
+ var namespaceList = [];
165
+
166
+ if (err) {
167
+ Common.printError(err);
168
+ that.exitCli(cst.ERROR_EXIT);
169
+ }
170
+
171
+ if (lines === 0)
172
+ return Log.stream(that.Client, id, raw, timestamp, exclusive, highlight);
173
+
174
+ Common.printOut(chalk.bold.gray(util.format.call(this, '[TAILING] Tailing last %d lines for [%s] process%s (change the value with --lines option)', lines, id, id === 'all' ? 'es' : '')));
175
+
176
+ // Populate the array `files_list` with the paths of all files we need to tail
177
+ list.forEach(function(proc) {
178
+ if (proc.pm2_env && (id === 'all' ||
179
+ proc.pm2_env.name == id ||
180
+ proc.pm2_env.pm_id == id)) {
181
+ if (proc.pm2_env.pm_out_log_path && exclusive !== 'err')
182
+ pushIfUnique({
183
+ path : proc.pm2_env.pm_out_log_path,
184
+ app_name :proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
185
+ type : 'out'});
186
+ if (proc.pm2_env.pm_err_log_path && exclusive !== 'out')
187
+ pushIfUnique({
188
+ path : proc.pm2_env.pm_err_log_path,
189
+ app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
190
+ type : 'err'
191
+ });
192
+ } else if(proc.pm2_env && proc.pm2_env.namespace == id) {
193
+ if(namespaceList.indexOf(proc.pm2_env.name) === -1) {
194
+ namespaceList.push(proc.pm2_env.name)
195
+ }
196
+ if (proc.pm2_env.pm_out_log_path && exclusive !== 'err')
197
+ pushIfUnique({
198
+ path : proc.pm2_env.pm_out_log_path,
199
+ app_name :proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
200
+ type : 'out'});
201
+ if (proc.pm2_env.pm_err_log_path && exclusive !== 'out')
202
+ pushIfUnique({
203
+ path : proc.pm2_env.pm_err_log_path,
204
+ app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
205
+ type : 'err'
206
+ });
207
+ }
208
+ // Populate the array `files_list` with the paths of all files we need to tail, when log in put is a regex
209
+ else if(proc.pm2_env && (isNaN(id) && id[0] === '/' && id[id.length - 1] === '/')) {
210
+ var regex = new RegExp(id.replace(/\//g, ''));
211
+ if(regex.test(proc.pm2_env.name)) {
212
+ if(regexList.indexOf(proc.pm2_env.name) === -1) {
213
+ regexList.push(proc.pm2_env.name);
214
+ }
215
+ if (proc.pm2_env.pm_out_log_path && exclusive !== 'err')
216
+ pushIfUnique({
217
+ path : proc.pm2_env.pm_out_log_path,
218
+ app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
219
+ type : 'out'});
220
+ if (proc.pm2_env.pm_err_log_path && exclusive !== 'out')
221
+ pushIfUnique({
222
+ path : proc.pm2_env.pm_err_log_path,
223
+ app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
224
+ type : 'err'
225
+ });
226
+ }
227
+ }
228
+ });
229
+
230
+ //for fixing issue https://github.com/Unitech/pm2/issues/3506
231
+ /* if (files_list && files_list.length == 0) {
232
+ Common.printError(cst.PREFIX_MSG_ERR + 'No file to stream for app [%s], exiting.', id);
233
+ return process.exit(cst.ERROR_EXIT);
234
+ }*/
235
+
236
+ if (!raw && (id === 'all' || id === 'PM2') && exclusive === false) {
237
+ Log.tail([{
238
+ path : cst.PM2_LOG_FILE_PATH,
239
+ app_name : 'PM2',
240
+ type : 'PM2'
241
+ }], lines, raw, function() {
242
+ Log.tail(files_list, lines, raw, function() {
243
+ Log.stream(that.Client, id, raw, timestamp, exclusive, highlight);
244
+ });
245
+ });
246
+ }
247
+ else {
248
+ Log.tail(files_list, lines, raw, function() {
249
+ if(regexList.length > 0) {
250
+ regexList.forEach(function(id) {
251
+ Log.stream(that.Client, id, raw, timestamp, exclusive, highlight);
252
+ })
253
+ }
254
+ else if(namespaceList.length > 0) {
255
+ namespaceList.forEach(function(id) {
256
+ Log.stream(that.Client, id, raw, timestamp, exclusive, highlight);
257
+ })
258
+ }
259
+ else {
260
+ Log.stream(that.Client, id, raw, timestamp, exclusive, highlight);
261
+ }
262
+ });
263
+ }
264
+ });
265
+ };
266
+
267
+ /**
268
+ * Description
269
+ * @method printLogs
270
+ * @param {String} id
271
+ * @param {Number} lines
272
+ * @param {Boolean} raw
273
+ * @return
274
+ */
275
+ CLI.prototype.printLogs = function(id, lines, raw, timestamp, exclusive) {
276
+ var that = this;
277
+ var files_list = [];
278
+
279
+ // If no argument is given, we stream logs for all running apps
280
+ id = id || 'all';
281
+ lines = lines !== undefined ? lines : 20;
282
+ lines = lines < 0 ? -(lines) : lines;
283
+
284
+ // Avoid duplicates and check if path is different from '/dev/null'
285
+ var pushIfUnique = function(entry) {
286
+ var exists = false;
287
+
288
+ if (entry.path.toLowerCase
289
+ && entry.path.toLowerCase() !== '/dev/null') {
290
+
291
+ files_list.some(function(file) {
292
+ if (file.path === entry.path)
293
+ exists = true;
294
+ return exists;
295
+ });
296
+
297
+ if (exists)
298
+ return;
299
+
300
+ files_list.push(entry);
301
+ }
302
+ }
303
+
304
+ // Get the list of all running apps
305
+ that.Client.executeRemote('getMonitorData', {}, function(err, list) {
306
+ if (err) {
307
+ Common.printError(err);
308
+ that.exitCli(cst.ERROR_EXIT);
309
+ }
310
+
311
+ if (lines <= 0) {
312
+ return that.exitCli(cst.SUCCESS_EXIT)
313
+ }
314
+
315
+ Common.printOut(chalk.bold.gray(util.format.call(this, '[TAILING] Tailing last %d lines for [%s] process%s (change the value with --lines option)', lines, id, id === 'all' ? 'es' : '')));
316
+
317
+ // Populate the array `files_list` with the paths of all files we need to tail
318
+ list.forEach(function(proc) {
319
+ if (proc.pm2_env && (id === 'all' ||
320
+ proc.pm2_env.name == id ||
321
+ proc.pm2_env.pm_id == id)) {
322
+ if (proc.pm2_env.pm_out_log_path && exclusive !== 'err')
323
+ pushIfUnique({
324
+ path : proc.pm2_env.pm_out_log_path,
325
+ app_name :proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
326
+ type : 'out'});
327
+ if (proc.pm2_env.pm_err_log_path && exclusive !== 'out')
328
+ pushIfUnique({
329
+ path : proc.pm2_env.pm_err_log_path,
330
+ app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
331
+ type : 'err'
332
+ });
333
+ }
334
+ // Populate the array `files_list` with the paths of all files we need to tail, when log in put is a regex
335
+ else if(proc.pm2_env && (isNaN(id) && id[0] === '/' && id[id.length - 1] === '/')) {
336
+ var regex = new RegExp(id.replace(/\//g, ''));
337
+ if(regex.test(proc.pm2_env.name)) {
338
+ if (proc.pm2_env.pm_out_log_path && exclusive !== 'err')
339
+ pushIfUnique({
340
+ path : proc.pm2_env.pm_out_log_path,
341
+ app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
342
+ type : 'out'});
343
+ if (proc.pm2_env.pm_err_log_path && exclusive !== 'out')
344
+ pushIfUnique({
345
+ path : proc.pm2_env.pm_err_log_path,
346
+ app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
347
+ type : 'err'
348
+ });
349
+ }
350
+ }
351
+ });
352
+
353
+ if (!raw && (id === 'all' || id === 'PM2') && exclusive === false) {
354
+ Log.tail([{
355
+ path : cst.PM2_LOG_FILE_PATH,
356
+ app_name : 'PM2',
357
+ type : 'PM2'
358
+ }], lines, raw, function() {
359
+ Log.tail(files_list, lines, raw, function() {
360
+ that.exitCli(cst.SUCCESS_EXIT);
361
+ });
362
+ });
363
+ }
364
+ else {
365
+ Log.tail(files_list, lines, raw, function() {
366
+ that.exitCli(cst.SUCCESS_EXIT);
367
+ });
368
+ }
369
+ });
370
+ };
371
+ };
@@ -0,0 +1,122 @@
1
+
2
+ var path = require('path');
3
+ var fs = require('fs');
4
+ var os = require('os');
5
+ var spawn = require('child_process').spawn;
6
+ var chalk = require('ansis');
7
+ var parallel = require('async/parallel');
8
+
9
+ var Configuration = require('../../Configuration.js');
10
+ var cst = require('../../../constants.js');
11
+ var Common = require('../../Common');
12
+ var Utility = require('../../Utility.js');
13
+ var readline = require('readline')
14
+
15
+ var INTERNAL_MODULES = {
16
+ 'deep-monitoring': {
17
+ dependencies: [{name: 'v8-profiler-node8'}, {name: 'gc-stats'}, {name: 'event-loop-inspector'}]
18
+ },
19
+ 'gc-stats': {name: 'gc-stats'},
20
+ 'event-loop-inspector': {name: 'event-loop-inspector'},
21
+ 'v8-profiler': {name: 'v8-profiler-node8'},
22
+ 'profiler': {name: 'v8-profiler-node8'},
23
+ 'typescript': {dependencies: [{name: 'typescript'}, {name: 'ts-node@latest'}]},
24
+ 'livescript': {name: 'livescript'},
25
+ 'coffee-script': {name: 'coffee-script', message: 'Coffeescript v1 support'},
26
+ 'coffeescript': {name: 'coffeescript', message: 'Coffeescript v2 support'}
27
+ };
28
+
29
+ module.exports = {
30
+ install,
31
+ INTERNAL_MODULES,
32
+ installMultipleModules
33
+ }
34
+
35
+
36
+ function install(module, cb, verbose) {
37
+ if (!module || !module.name || module.name.length === 0) {
38
+ return cb(new Error('No module name !'));
39
+ }
40
+
41
+ if (typeof verbose === 'undefined') {
42
+ verbose = true;
43
+ }
44
+
45
+ installLangModule(module.name, function (err) {
46
+ var display = module.message || module.name;
47
+ if (err) {
48
+ if (verbose) { Common.printError(cst.PREFIX_MSG_MOD_ERR + chalk.bold.green(display + ' installation has FAILED (checkout previous logs)')); }
49
+ return cb(err);
50
+ }
51
+
52
+ if (verbose) { Common.printOut(cst.PREFIX_MSG + chalk.bold.green(display + ' ENABLED')); }
53
+ return cb();
54
+ });
55
+ }
56
+
57
+ function installMultipleModules(modules, cb, post_install) {
58
+ var functionList = [];
59
+ for (var i = 0; i < modules.length; i++) {
60
+ functionList.push((function (index) {
61
+ return function (callback) {
62
+ var module = modules[index];
63
+ if (typeof modules[index] === 'string') {
64
+ module = {name: modules[index]};
65
+ }
66
+ install(module, function ($post_install, err, $index, $modules) {
67
+ try {
68
+ var install_instance = spawn(post_install[modules[index]], {
69
+ stdio : 'inherit',
70
+ windowsHide: true,
71
+ env: process.env,
72
+ shell : true,
73
+ cwd : process.cwd()
74
+ });
75
+ Common.printOut(cst.PREFIX_MSG_MOD + 'Running configuraton script.');
76
+ }
77
+ catch(e)
78
+ {
79
+ Common.printOut(cst.PREFIX_MSG_MOD + 'No configuraton script found.');
80
+ }
81
+ callback(null, { module: module, err: err });
82
+ }, false);
83
+ };
84
+ })(i));
85
+ }
86
+
87
+ parallel(functionList, function (err, results) {
88
+ for (var i = 0; i < results.length; i++) {
89
+ var display = results[i].module.message || results[i].module.name;
90
+ if (results[i].err) {
91
+ err = results[i].err;
92
+ Common.printError(cst.PREFIX_MSG_MOD_ERR + chalk.bold.green(display + ' installation has FAILED (checkout previous logs)'));
93
+ } else {
94
+ Common.printOut(cst.PREFIX_MSG + chalk.bold.green(display + ' ENABLED'));
95
+ }
96
+ }
97
+
98
+ if(cb) cb(err);
99
+ });
100
+ };
101
+
102
+ function installLangModule(module_name, cb) {
103
+ var node_module_path = path.resolve(path.join(__dirname, '../../../'));
104
+ Common.printOut(cst.PREFIX_MSG_MOD + 'Calling ' + chalk.bold.red('[NPM]') + ' to install ' + module_name + ' ...');
105
+
106
+ var install_instance = spawn(cst.IS_WINDOWS ? 'npm.cmd' : 'npm', ['install', module_name, '--loglevel=error'], {
107
+ stdio : 'inherit',
108
+ env: process.env,
109
+ shell : true,
110
+ cwd : node_module_path
111
+ });
112
+
113
+ install_instance.on('close', function(code) {
114
+ if (code > 0)
115
+ return cb(new Error('Module install failed'));
116
+ return cb(null);
117
+ });
118
+
119
+ install_instance.on('error', function (err) {
120
+ console.error(err.stack || err);
121
+ });
122
+ };
@@ -0,0 +1,148 @@
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
+ var path = require('path');
7
+ var eachLimit = require('async/eachLimit');
8
+ var forEachLimit = require('async/forEachLimit');
9
+
10
+ var Configuration = require('../../Configuration.js');
11
+ var cst = require('../../../constants.js');
12
+ var Common = require('../../Common');
13
+ var NPM = require('./NPM.js')
14
+ var TAR = require('./TAR.js')
15
+ var LOCAL = require('./LOCAL.js')
16
+
17
+ var Modularizer = module.exports = {};
18
+
19
+ /**
20
+ * PM2 Module System.
21
+ */
22
+ Modularizer.install = function (CLI, module_name, opts, cb) {
23
+ module_name = module_name.replace(/[;`|]/g, "");
24
+ if (typeof(opts) == 'function') {
25
+ cb = opts;
26
+ opts = {};
27
+ }
28
+
29
+ if (LOCAL.INTERNAL_MODULES.hasOwnProperty(module_name)) {
30
+ Common.logMod(`Adding dependency ${module_name} to PM2 Runtime`);
31
+ var currentModule = LOCAL.INTERNAL_MODULES[module_name];
32
+ if (currentModule && currentModule.hasOwnProperty('dependencies')) {
33
+ LOCAL.installMultipleModules(currentModule.dependencies, cb);
34
+ } else {
35
+ LOCAL.install(currentModule, cb);
36
+ }
37
+ }
38
+ else if (module_name == '.') {
39
+ Common.logMod(`Installing local NPM module`);
40
+ return NPM.localStart(CLI, opts, cb)
41
+ }
42
+ else if (opts.tarball || /\.tar\.gz$/i.test(module_name)) {
43
+ Common.logMod(`Installing TAR module`);
44
+ TAR.install(CLI, module_name, opts, cb)
45
+ }
46
+ else {
47
+ Common.logMod(`Installing NPM ${module_name} module`);
48
+ NPM.install(CLI, module_name, opts, cb)
49
+ }
50
+ };
51
+
52
+ /**
53
+ * Launch All Modules
54
+ * Used PM2 at startup
55
+ */
56
+ Modularizer.launchModules = function(CLI, cb) {
57
+ var modules = Modularizer.listModules();
58
+
59
+ if (!modules) return cb();
60
+
61
+ // 1#
62
+ function launchNPMModules(cb) {
63
+ if (!modules.npm_modules) return launchTARModules(cb)
64
+
65
+ eachLimit(Object.keys(modules.npm_modules), 1, function(module_name, next) {
66
+ NPM.start(CLI, modules, module_name, next)
67
+ }, function() {
68
+ launchTARModules(cb)
69
+ });
70
+ }
71
+
72
+ // 2#
73
+ function launchTARModules(cb) {
74
+ if (!modules.tar_modules) return cb()
75
+
76
+ eachLimit(Object.keys(modules.tar_modules), 1, function(module_name, next) {
77
+ TAR.start(CLI, module_name, next)
78
+ }, function() {
79
+ return cb ? cb(null) : false;
80
+ });
81
+ }
82
+
83
+ launchNPMModules(cb)
84
+ }
85
+
86
+ Modularizer.package = function(CLI, module_path, cb) {
87
+ var fullpath = process.cwd()
88
+ if (module_path)
89
+ fullpath = require('path').resolve(module_path)
90
+ TAR.packager(fullpath, process.cwd(), cb)
91
+ }
92
+
93
+ /**
94
+ * Uninstall module
95
+ */
96
+ Modularizer.uninstall = function(CLI, module_name, cb) {
97
+ Common.printOut(cst.PREFIX_MSG_MOD + 'Uninstalling module ' + module_name);
98
+ var modules_list = Modularizer.listModules();
99
+
100
+ if (module_name == 'all') {
101
+ if (!modules_list) return cb();
102
+
103
+ return forEachLimit(Object.keys(modules_list.npm_modules), 1, function(module_name, next) {
104
+ NPM.uninstall(CLI, module_name, next)
105
+ }, () => {
106
+ forEachLimit(Object.keys(modules_list.tar_modules), 1, function(module_name, next) {
107
+ TAR.uninstall(CLI, module_name, next)
108
+ }, cb)
109
+ });
110
+ }
111
+
112
+ if (modules_list.npm_modules[module_name]) {
113
+ NPM.uninstall(CLI, module_name, cb)
114
+ } else if (modules_list.tar_modules[module_name]) {
115
+ TAR.uninstall(CLI, module_name, cb)
116
+ }
117
+ else {
118
+ Common.errMod('Unknown module')
119
+ CLI.exitCli(1)
120
+ }
121
+ };
122
+
123
+ /**
124
+ * List modules based on modules present in ~/.pm2/modules/ folder
125
+ */
126
+ Modularizer.listModules = function() {
127
+ return {
128
+ npm_modules: Configuration.getSync(cst.MODULE_CONF_PREFIX) || {},
129
+ tar_modules: Configuration.getSync(cst.MODULE_CONF_PREFIX_TAR) || {}
130
+ }
131
+ };
132
+
133
+ Modularizer.getAdditionalConf = function(app_name) {
134
+ return NPM.getModuleConf(app_name)
135
+ };
136
+
137
+ Modularizer.publish = function(PM2, folder, opts, cb) {
138
+ if (opts.npm == true) {
139
+ NPM.publish(opts, cb)
140
+ }
141
+ else {
142
+ TAR.publish(PM2, folder, cb)
143
+ }
144
+ };
145
+
146
+ Modularizer.generateSample = function(app_name, cb) {
147
+ NPM.generateSample(app_name, cb)
148
+ };