@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,11 @@
1
+ {
2
+ "name": "simple-http-server",
3
+ "version": "1.0.0",
4
+ "description": "Simple HTTP server that can be used in cluster mode",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "author": "",
10
+ "license": "ISC"
11
+ }
@@ -0,0 +1,45 @@
1
+
2
+ # pm2 custom metrics boilerplate
3
+
4
+ In this boilerplate you will discover a working example of custom metrics feature.
5
+
6
+ Metrics covered are:
7
+ - io.metric
8
+ - io.counter
9
+ - io.meter
10
+ - io.histogram
11
+
12
+ ## What is Custom Metrics?
13
+
14
+ Custom metrics is a powerfull way to get more visibility from a running application. It will allow you to monitor in realtime the current value of variables, know the number of actions being processed, measure latency and much more.
15
+
16
+ Once you have plugged in some custom metrics you will be able to monitor their value in realtime with
17
+
18
+ `pm2 monit`
19
+
20
+ Or
21
+
22
+ `pm2 describe`
23
+
24
+ Or on the PM2+ Web interface
25
+
26
+ `pm2 open`
27
+
28
+ ## Example
29
+
30
+ ```javascript
31
+ const io = require('@pm2/io')
32
+
33
+ const currentReq = io.counter({
34
+ name: 'CM: Current Processing',
35
+ type: 'counter'
36
+ })
37
+
38
+ setInterval(() => {
39
+ currentReq.inc()
40
+ }, 1000)
41
+ ```
42
+
43
+ ## Documentation
44
+
45
+ https://doc.pm2.io/en/plus/guide/custom-metrics/
@@ -0,0 +1,66 @@
1
+
2
+ const io = require('@pm2/io')
3
+
4
+ // Straight Metric
5
+ var user_count = 10
6
+
7
+ const users = io.metric({
8
+ name: 'CM: Realtime user',
9
+ value: () => {
10
+ return user_count
11
+ }
12
+ })
13
+
14
+ // or users.set(user_count)
15
+
16
+ // Counter (.inc() .dec())
17
+ const currentReq = io.counter({
18
+ name: 'CM: Current Processing',
19
+ type: 'counter'
20
+ })
21
+
22
+ setInterval(() => {
23
+ currentReq.inc()
24
+ }, 1000)
25
+
26
+ // Meter
27
+ const reqsec = io.meter({
28
+ name: 'CM: req/sec'
29
+ })
30
+
31
+ setInterval(() => {
32
+ reqsec.mark()
33
+ }, 100)
34
+
35
+
36
+ // Histogram
37
+ const latency = io.histogram({
38
+ name: 'CM: latency'
39
+ });
40
+
41
+ var latencyValue = 0;
42
+
43
+ setInterval(() => {
44
+ latencyValue = Math.round(Math.random() * 100);
45
+ latency.update(latencyValue);
46
+ }, 100)
47
+
48
+
49
+ ////////////////////
50
+ // Custom Actions //
51
+ ////////////////////
52
+
53
+ io.action('add user', (done) => {
54
+ user_count++
55
+ done({success:true})
56
+ })
57
+
58
+ io.action('remove user', (done) => {
59
+ user_count++
60
+ done({success:true})
61
+ })
62
+
63
+ io.action('with params', (arg, done) => {
64
+ console.log(arg)
65
+ done({success:arg})
66
+ })
@@ -0,0 +1,12 @@
1
+ module.exports = {
2
+ apps : [{
3
+ name: 'Custom Metrics',
4
+ script: 'custom-metrics.js',
5
+ env: {
6
+ NODE_ENV: 'development'
7
+ },
8
+ env_production: {
9
+ NODE_ENV: 'production'
10
+ }
11
+ }]
12
+ };
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "pm2-plus-custom-metrics",
3
+ "version": "1.0.0",
4
+ "description": "Example that shows how to use pm2+ custom metrics",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "author": "",
10
+ "license": "ISC"
11
+ }
@@ -0,0 +1,4 @@
1
+
2
+ # Managing a Python Application
3
+
4
+ On this boilerlate you will see how you can start a Python application with PM2.
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/python
2
+ import time
3
+
4
+ while 1:
5
+ print("Start : %s" % time.ctime())
6
+ print("second line")
7
+ time.sleep(1)
@@ -0,0 +1,12 @@
1
+ module.exports = {
2
+ apps : [{
3
+ name: 'API',
4
+ script: 'echo.py',
5
+ env: {
6
+ NODE_ENV: 'development'
7
+ },
8
+ env_production: {
9
+ NODE_ENV: 'production'
10
+ }
11
+ }]
12
+ };
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "python-app",
3
+ "version": "1.0.0",
4
+ "description": "Example on how to manage a Python application with PM2",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "author": "",
10
+ "license": "ISC"
11
+ }
@@ -0,0 +1,248 @@
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 util = require('util');
7
+
8
+ /**
9
+ * Validator of configured file / commander options.
10
+ */
11
+ var Config = module.exports = {
12
+ _errMsgs: {
13
+ 'require': '"%s" is required',
14
+ 'type' : 'Expect "%s" to be a typeof %s, but now is %s',
15
+ 'regex' : 'Verify "%s" with regex failed, %s',
16
+ 'max' : 'The maximum of "%s" is %s, but now is %s',
17
+ 'min' : 'The minimum of "%s" is %s, but now is %s'
18
+ },
19
+ /**
20
+ * Schema definition.
21
+ * @returns {exports|*}
22
+ */
23
+ get schema(){
24
+ // Cache.
25
+ if (this._schema) {
26
+ return this._schema;
27
+ }
28
+ // Render aliases.
29
+ this._schema = require('../API/schema');
30
+ for (var k in this._schema) {
31
+ if (k.indexOf('\\') > 0) {
32
+ continue;
33
+ }
34
+ var aliases = [
35
+ k.split('_').map(function(n, i){
36
+ if (i != 0 && n && n.length > 1) {
37
+ return n[0].toUpperCase() + n.slice(1);
38
+ }
39
+ return n;
40
+ }).join('')
41
+ ];
42
+
43
+ if (this._schema[k].alias && Array.isArray(this._schema[k].alias)) {
44
+ // If multiple aliases, merge
45
+ this._schema[k].alias.forEach(function(alias) {
46
+ aliases.splice(0, 0, alias);
47
+ });
48
+ }
49
+ else if (this._schema[k].alias)
50
+ aliases.splice(0, 0, this._schema[k].alias);
51
+
52
+ this._schema[k].alias = aliases;
53
+ }
54
+ return this._schema;
55
+ }
56
+ };
57
+
58
+ /**
59
+ * Filter / Alias options
60
+ */
61
+ Config.filterOptions = function(cmd) {
62
+ var conf = {};
63
+ var schema = this.schema;
64
+
65
+ for (var key in schema) {
66
+ var aliases = schema[key].alias;
67
+ aliases && aliases.forEach(function(alias){
68
+ if (typeof(cmd[alias]) !== 'undefined') {
69
+ conf[key] || (conf[key] = cmd[alias]);
70
+ }
71
+ });
72
+ }
73
+
74
+ return conf;
75
+ };
76
+
77
+ /**
78
+ * Verify JSON configurations.
79
+ * @param {Object} json
80
+ * @returns {{errors: Array, config: {}}}
81
+ */
82
+ Config.validateJSON = function(json){
83
+ // clone config
84
+ var conf = Object.assign({}, json),
85
+ res = {};
86
+ this._errors = [];
87
+
88
+ var regexKeys = {}, defines = this.schema;
89
+
90
+ for (var sk in defines) {
91
+ // Pick up RegExp keys.
92
+ if (sk.indexOf('\\') >= 0) {
93
+ regexKeys[sk] = false;
94
+ continue;
95
+ }
96
+
97
+ var aliases = defines[sk].alias;
98
+
99
+ aliases && aliases.forEach(function(alias){
100
+ conf[sk] || (conf[sk] = json[alias]);
101
+ })
102
+
103
+ var val = conf[sk];
104
+ delete conf[sk];
105
+
106
+ // Validate key-value pairs.
107
+ if (val === undefined ||
108
+ val === null ||
109
+ ((val = this._valid(sk, val)) === null)) {
110
+
111
+ // If value is not defined
112
+ // Set default value (via schema.json)
113
+ if (typeof(defines[sk].default) !== 'undefined')
114
+ res[sk] = defines[sk].default;
115
+ continue;
116
+ }
117
+ //console.log(sk, val, val === null, val === undefined);
118
+ res[sk] = val;
119
+ }
120
+
121
+ // Validate RegExp values.
122
+ var hasRegexKey = false;
123
+ for (var k in regexKeys) {
124
+ hasRegexKey = true;
125
+ regexKeys[k] = new RegExp(k);
126
+ }
127
+ if (hasRegexKey) {
128
+ for (var k in conf) {
129
+ for (var rk in regexKeys) {
130
+ if (regexKeys[rk].test(k))
131
+ if (this._valid(k, conf[k], defines[rk])) {
132
+ res[k] = conf[k];
133
+ delete conf[k];
134
+ }
135
+ }
136
+ }
137
+ }
138
+
139
+ return {errors: this._errors, config: res};
140
+ };
141
+
142
+ /**
143
+ * Validate key-value pairs by specific schema
144
+ * @param {String} key
145
+ * @param {Mixed} value
146
+ * @param {Object} sch
147
+ * @returns {*}
148
+ * @private
149
+ */
150
+ Config._valid = function(key, value, sch){
151
+ var sch = sch || this.schema[key],
152
+ scht = typeof sch.type == 'string' ? [sch.type] : sch.type;
153
+
154
+ // Required value.
155
+ var undef = typeof value == 'undefined';
156
+ if(this._error(sch.require && undef, 'require', key)){
157
+ return null;
158
+ }
159
+
160
+ // If undefined, make a break.
161
+ if (undef) {
162
+ return null;
163
+ }
164
+
165
+ // Wrap schema types.
166
+ scht = scht.map(function(t){
167
+ return '[object ' + t[0].toUpperCase() + t.slice(1) + ']'
168
+ });
169
+
170
+ // Typeof value.
171
+ var type = Object.prototype.toString.call(value), nt = '[object Number]';
172
+
173
+ // Auto parse Number
174
+ if (type != '[object Boolean]' && scht.indexOf(nt) >= 0 && !isNaN(value)) {
175
+ value = parseFloat(value);
176
+ type = nt;
177
+ }
178
+
179
+ // Verify types.
180
+ if (this._error(!~scht.indexOf(type), 'type', key, scht.join(' / '), type)) {
181
+ return null;
182
+ }
183
+
184
+ // Verify RegExp if exists.
185
+ if (this._error(type == '[object String]' && sch.regex && !(new RegExp(sch.regex)).test(value),
186
+ 'regex', key, sch.desc || ('should match ' + sch.regex))) {
187
+ return null;
188
+ }
189
+
190
+ // Verify maximum / minimum of Number value.
191
+ if (type == '[object Number]') {
192
+ if (this._error(typeof sch.max != 'undefined' && value > sch.max, 'max', key, sch.max, value)) {
193
+ return null;
194
+ }
195
+ if (this._error(typeof sch.min != 'undefined' && value < sch.min, 'min', key, sch.min, value)) {
196
+ return null;
197
+ }
198
+ }
199
+
200
+ // If first type is Array, but current is String, try to split them.
201
+ if(scht.length > 1 && type != scht[0] && type == '[object String]'){
202
+ if(scht[0] == '[object Array]') {
203
+ value = value.split(/([\w\-]+\="[^"]*")|([\w\-]+\='[^']*')|"([^"]*)"|'([^']*)'|\s/)
204
+ // unfortunately, js does not support lookahead RegExp (/(?<!\\)\s+/) now (until next ver).
205
+ //value = value.split(/((?<![\w\-])([\w\-]+\="[^"]*")|(?<![\w\-])([\w\-]+\='[^']*')|"([^"]*)"|'([^']*)'|\s )/)
206
+ .filter(function(v){
207
+ return v && v.trim();
208
+ });
209
+ }
210
+ }
211
+
212
+ // Custom types: sbyte && stime.
213
+ if(sch.ext_type && type == '[object String]' && value.length >= 2) {
214
+ var seed = {
215
+ 'sbyte': {
216
+ 'G': 1024 * 1024 * 1024,
217
+ 'M': 1024 * 1024,
218
+ 'K': 1024
219
+ },
220
+ 'stime': {
221
+ 'h': 60 * 60 * 1000,
222
+ 'm': 60 * 1000,
223
+ 's': 1000
224
+ }
225
+ }[sch.ext_type];
226
+
227
+ if(seed){
228
+ value = parseFloat(value.slice(0, -1)) * (seed[value.slice(-1)]);
229
+ }
230
+ }
231
+ return value;
232
+ };
233
+
234
+ /**
235
+ * Wrap errors.
236
+ * @param {Boolean} possible A value indicates whether it is an error or not.
237
+ * @param {String} type
238
+ * @returns {*}
239
+ * @private
240
+ */
241
+ Config._error = function(possible, type){
242
+ if (possible) {
243
+ var args = Array.prototype.slice.call(arguments);
244
+ args.splice(0, 2, this._errMsgs[type]);
245
+ this._errors && this._errors.push(util.format.apply(null, args));
246
+ }
247
+ return possible;
248
+ }
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+
3
+ function posix(path) {
4
+ return path.charAt(0) === '/';
5
+ }
6
+
7
+ function win32(path) {
8
+ // https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56
9
+ var splitDeviceRe = /^([a-zA-Z]:|[\\/]{2}[^\\/]+[\\/]+[^\\/]+)?([\\/])?([\s\S]*?)$/;
10
+ var result = splitDeviceRe.exec(path);
11
+ var device = result[1] || '';
12
+ var isUnc = Boolean(device && device.charAt(1) !== ':');
13
+
14
+ // UNC paths are always absolute
15
+ return Boolean(result[2] || isUnc);
16
+ }
17
+
18
+ module.exports = process.platform === 'win32' ? win32 : posix;
19
+ module.exports.posix = posix;
20
+ module.exports.win32 = win32;
@@ -0,0 +1,101 @@
1
+ var fs = require('fs');
2
+ var path = require('path');
3
+ /*
4
+ options: {
5
+ utimes: false, // Boolean | Object, keep utimes if true
6
+ mode: false, // Boolean | Number, keep file mode if true
7
+ cover: true, // Boolean, cover if file exists
8
+ filter: true, // Boolean | Function, file filter
9
+ }
10
+ */
11
+ function copydirSync(from, to, options) {
12
+ if (typeof options === 'function') {
13
+ options = {
14
+ filter: options
15
+ };
16
+ }
17
+ if(typeof options === 'undefined') options = {};
18
+ if(typeof options.cover === 'undefined') {
19
+ options.cover = true;
20
+ }
21
+ options.filter = typeof options.filter === 'function' ? options.filter : function(state, filepath, filename) {
22
+ return options.filter;
23
+ };
24
+ var stats = fs.lstatSync(from);
25
+ var statsname = stats.isDirectory() ? 'directory' :
26
+ stats.isFile() ? 'file' :
27
+ stats.isSymbolicLink() ? 'symbolicLink' :
28
+ '';
29
+ var valid = options.filter(statsname, from, path.dirname(from), path.basename(from));
30
+
31
+ if (statsname === 'directory' || statsname === 'symbolicLink') {
32
+ // Directory or SymbolicLink
33
+ if(valid) {
34
+ try {
35
+ fs.statSync(to);
36
+ } catch(err) {
37
+ if(err.code === 'ENOENT') {
38
+ fs.mkdirSync(to, { recursive: true });
39
+ options.debug && console.log('>> ' + to);
40
+ } else {
41
+ throw err;
42
+ }
43
+ }
44
+ rewriteSync(to, options, stats);
45
+ if (statsname != 'symbolicLink')
46
+ listDirectorySync(from, to, options);
47
+ }
48
+ } else if(stats.isFile()) {
49
+ // File
50
+ if(valid) {
51
+ if(options.cover) {
52
+ writeFileSync(from, to, options, stats);
53
+ } else {
54
+ try {
55
+ fs.statSync(to);
56
+ } catch(err) {
57
+ if(err.code === 'ENOENT') {
58
+ writeFileSync(from, to, options, stats);
59
+ } else {
60
+ throw err;
61
+ }
62
+ }
63
+ }
64
+ }
65
+ } else {
66
+ throw new Error('stats invalid: '+ from);
67
+ }
68
+ };
69
+
70
+ function listDirectorySync(from, to, options) {
71
+ var files = fs.readdirSync(from);
72
+ copyFromArraySync(files, from, to, options);
73
+ }
74
+
75
+ function copyFromArraySync(files, from, to, options) {
76
+ if(files.length === 0) return true;
77
+ var f = files.shift();
78
+ copydirSync(path.join(from, f), path.join(to, f), options);
79
+ copyFromArraySync(files, from, to, options);
80
+ }
81
+
82
+ function writeFileSync(from, to, options, stats) {
83
+ fs.writeFileSync(to, fs.readFileSync(from, 'binary'), 'binary');
84
+ options.debug && console.log('>> ' + to);
85
+ rewriteSync(to, options, stats);
86
+ }
87
+
88
+ function rewriteSync(f, options, stats, callback) {
89
+ if(options.cover) {
90
+ var mode = options.mode === true ? stats.mode : options.mode;
91
+ var utimes = options.utimes === true ? {
92
+ atime: stats.atime,
93
+ mtime: stats.mtime
94
+ } : options.utimes;
95
+ mode && fs.chmodSync(f, mode);
96
+ utimes && fs.utimesSync(f, utimes.atime, utimes.mtime);
97
+ }
98
+ return true;
99
+ }
100
+
101
+ module.exports = copydirSync;
@@ -0,0 +1,19 @@
1
+
2
+ const fs = require('fs');
3
+ const Path = require('path');
4
+
5
+ const deleteFolderRecursive = function(path) {
6
+ if (fs.existsSync(path)) {
7
+ fs.readdirSync(path).forEach((file, index) => {
8
+ const curPath = Path.join(path, file);
9
+ if (fs.lstatSync(curPath).isDirectory()) { // recurse
10
+ deleteFolderRecursive(curPath);
11
+ } else { // delete file
12
+ fs.unlinkSync(curPath);
13
+ }
14
+ });
15
+ fs.rmdirSync(path);
16
+ }
17
+ };
18
+
19
+ module.exports = deleteFolderRecursive
@@ -0,0 +1,74 @@
1
+ 'use strict';
2
+
3
+ var path = require('path')
4
+ , fs = require('fs');
5
+
6
+ /**
7
+ * Attempt to somewhat safely parse the JSON.
8
+ *
9
+ * @param {String} data JSON blob that needs to be parsed.
10
+ * @returns {Object|false} Parsed JSON or false.
11
+ * @api private
12
+ */
13
+ function parse(data) {
14
+ data = data.toString('utf-8');
15
+
16
+ //
17
+ // Remove a possible UTF-8 BOM (byte order marker) as this can lead to parse
18
+ // values when passed in to the JSON.parse.
19
+ //
20
+ if (data.charCodeAt(0) === 0xFEFF) data = data.slice(1);
21
+
22
+ try { return JSON.parse(data); }
23
+ catch (e) { return false; }
24
+ }
25
+
26
+ /**
27
+ * Find package.json files.
28
+ *
29
+ * @param {String|Object} root The root directory we should start searching in.
30
+ * @returns {Object} Iterator interface.
31
+ * @api public
32
+ */
33
+ module.exports = function find(root) {
34
+ root = root || process.cwd();
35
+ if (typeof root !== "string") {
36
+ if (typeof root === "object" && typeof root.filename === 'string') {
37
+ root = root.filename;
38
+ } else {
39
+ throw new Error("Must pass a filename string or a module object to finder");
40
+ }
41
+ }
42
+ return {
43
+ /**
44
+ * Return the parsed package.json that we find in a parent folder.
45
+ *
46
+ * @returns {Object} Value, filename and indication if the iteration is done.
47
+ * @api public
48
+ */
49
+ next: function next() {
50
+ if (root.match(/^(\w:\\|\/)$/)) return {
51
+ value: undefined,
52
+ filename: undefined,
53
+ done: true
54
+ };
55
+
56
+ var file = path.join(root, 'package.json')
57
+ , data;
58
+
59
+ root = path.resolve(root, '..');
60
+
61
+ if (fs.existsSync(file) && (data = parse(fs.readFileSync(file)))) {
62
+ data.__path = file;
63
+
64
+ return {
65
+ value: data,
66
+ filename: file,
67
+ done: false
68
+ };
69
+ }
70
+
71
+ return next();
72
+ }
73
+ };
74
+ };