UNPKG

14.7 kBJavaScriptView Raw
1"use strict";
2var __assign = (this && this.__assign) || function () {
3 __assign = Object.assign || function(t) {
4 for (var s, i = 1, n = arguments.length; i < n; i++) {
5 s = arguments[i];
6 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7 t[p] = s[p];
8 }
9 return t;
10 };
11 return __assign.apply(this, arguments);
12};
13Object.defineProperty(exports, "__esModule", { value: true });
14var ChildProcess = require("child_process");
15var events_1 = require("events");
16var Fs = require("fs-extra");
17var path_1 = require("path");
18/**
19 Contains general utilities.
20 */
21var cwdReturnValue;
22var git;
23var npm;
24var node;
25function init() {
26 // Defaults to process's current working dir
27 cwdReturnValue = process.env.TORTILLA_CWD || process.cwd();
28 try {
29 cwdReturnValue = ChildProcess.execFileSync('git', [
30 'rev-parse', '--show-toplevel',
31 ], {
32 cwd: cwdReturnValue,
33 stdio: ['pipe', 'pipe', 'ignore'],
34 }).toString()
35 .trim();
36 }
37 catch (err) {
38 // If no git-exists nor git-failed use default value instead
39 }
40 // Setting all relative utils
41 exec.print = spawn;
42 git = exec.bind(null, 'git');
43 git.print = spawn.bind(null, 'git');
44 npm = exec.bind(null, 'npm');
45 npm.print = spawn.bind(null, 'npm');
46 node = exec.bind(null, 'node');
47 node.print = spawn.bind(null, 'node');
48}
49init();
50function cwd() {
51 return cwdReturnValue;
52}
53// Checks if one of the parent processes launched by the provided file and has
54// the provided arguments
55function isChildProcessOf(file, argv, offset) {
56 // There might be nested processes of the same file so we wanna go through all of them,
57 // This variable represents how much skips will be done anytime the file is found.
58 var trial = offset = offset || 0;
59 // The current process would be the node's
60 var currProcess = {
61 file: process.title,
62 pid: process.pid,
63 argv: process.argv,
64 };
65 // Will abort once the file is found and there are no more skips left to be done
66 while (currProcess.file !== file || trial--) {
67 // Get the parent process id
68 currProcess.pid = Number(getProcessData(currProcess.pid, 'ppid'));
69 // The root process'es id is 0 which means we've reached the limit
70 if (!currProcess.pid) {
71 return false;
72 }
73 currProcess.argv = getProcessData(currProcess.pid, 'command')
74 .split(' ')
75 .filter(Boolean);
76 // The first word in the command would be the file name
77 currProcess.file = currProcess.argv[0];
78 // The rest would be the arguments vector
79 currProcess.argv = currProcess.argv.slice(1);
80 }
81 // Make sure it has the provided arguments
82 var result = argv.every(function (arg) { return currProcess.argv.indexOf(arg) !== -1; });
83 // If this is not the file we're looking for keep going up in the processes tree
84 return result || isChildProcessOf(file, argv, ++offset);
85}
86// Gets process data using 'ps' formatting
87function getProcessData(pid, format) {
88 if (arguments.length === 1) {
89 format = pid;
90 pid = process.pid;
91 }
92 var result = exec('ps', ['-p', pid, '-o', format]).split('\n');
93 result.shift();
94 return result.join('\n');
95}
96// Spawn new process and print result to the terminal
97function spawn(file, argv, options) {
98 argv = argv || [];
99 options = extend({
100 cwd: process.env.TORTILLA_CWD || cwd(),
101 stdio: process.env.TORTILLA_STDIO || 'inherit',
102 env: {},
103 }, options);
104 var envRedundantKeys = Object.keys(options.env).filter(function (key) {
105 return options.env[key] == null;
106 });
107 options.env = extend({
108 TORTILLA_CHILD_PROCESS: true,
109 }, process.env, options.env);
110 envRedundantKeys.forEach(function (key) {
111 delete options.env[key];
112 });
113 return ChildProcess.spawnSync(file, argv, options);
114}
115// Execute file
116function exec(file, argv, options) {
117 argv = argv || [];
118 options = extend({
119 cwd: process.env.TORTILLA_CWD || cwd(),
120 stdio: 'pipe',
121 env: {},
122 }, options);
123 var envRedundantKeys = Object.keys(options.env).filter(function (key) {
124 return options.env[key] == null;
125 });
126 options.env = __assign({ TORTILLA_CHILD_PROCESS: true }, process.env, options.env);
127 envRedundantKeys.forEach(function (key) {
128 delete options.env[key];
129 });
130 debug("Executing (execFileSync) command \"" + file + " " + argv.join(' ') + "\" (" + options.cwd + ")");
131 var out = ChildProcess.execFileSync(file, argv, options);
132 // In case of stdio inherit
133 if (!out) {
134 return '';
135 }
136 return out.toString().trim();
137}
138function inspect(str, argv) {
139 if (argv === void 0) { argv = []; }
140 return spawn('less', argv, {
141 input: str,
142 stdio: ['pipe', 'inherit', 'inherit']
143 });
144}
145// Tells if entity exists or not by an optional document type
146function exists(path, type) {
147 try {
148 var stats = Fs.lstatSync(path);
149 switch (type) {
150 case 'dir':
151 return stats.isDirectory();
152 case 'file':
153 return stats.isFile();
154 case 'symlink':
155 return stats.isSymbolicLink();
156 default:
157 return true;
158 }
159 }
160 catch (err) {
161 return false;
162 }
163}
164// Create a temporary scope which will define provided variables on the environment
165function scopeEnv(fn, env) {
166 var keys = Object.keys(env);
167 var originalEnv = pluck(process.env, keys);
168 var nullKeys = keys.filter(function (key) { return process.env[key] == null; });
169 extend(process.env, env);
170 try {
171 return fn();
172 }
173 finally {
174 extend(process.env, originalEnv);
175 contract(process.env, nullKeys);
176 }
177}
178// Filter all strings matching the provided pattern in an array
179function filterMatches(arr, pattern) {
180 pattern = pattern || '';
181 return arr.filter(function (str) { return str.match(pattern); });
182}
183// Deeply merges destination object with source object
184function merge(destination, source) {
185 if (!(destination instanceof Object) ||
186 !(source instanceof Object)) {
187 return source;
188 }
189 Object.keys(source).forEach(function (k) {
190 destination[k] = merge(destination[k], source[k]);
191 });
192 return destination;
193}
194// Extend destination object with provided sources
195function extend(destination) {
196 var sources = [];
197 for (var _i = 1; _i < arguments.length; _i++) {
198 sources[_i - 1] = arguments[_i];
199 }
200 sources.forEach(function (source) {
201 if (!(source instanceof Object)) {
202 return;
203 }
204 Object.keys(source).forEach(function (k) {
205 destination[k] = source[k];
206 });
207 });
208 return destination;
209}
210// Deletes all keys in the provided object
211function contract(destination, keys) {
212 keys.forEach(function (key) {
213 delete destination[key];
214 });
215 return destination;
216}
217// Plucks all keys from object
218function pluck(obj, keys) {
219 return keys.reduce(function (result, key) {
220 result[key] = obj[key];
221 return result;
222 }, {});
223}
224// Pad the provided string with the provided pad params from the left
225// '1' -> '00001'
226function pad(str, length, char) {
227 str = str.toString();
228 char = char || ' ';
229 var chars = Array(length + 1).join(char);
230 return chars.substr(0, chars.length - str.length) + str;
231}
232// Like pad() only from the right
233// '1' -> '10000'
234function padRight(str, length, char) {
235 str = str.toString();
236 char = char || ' ';
237 var chars = Array(length + 1).join(char);
238 return str + chars.substr(0, chars.length - str.length);
239}
240// foo_barBaz -> foo-bar-baz
241function toKebabCase(str) {
242 return splitWords(str)
243 .map(lowerFirst)
244 .join('-');
245}
246// foo_barBaz -> Foo Bar Baz
247function toStartCase(str) {
248 return splitWords(str)
249 .map(upperFirst)
250 .join(' ');
251}
252// Lower -> lower
253function lowerFirst(str) {
254 return str.substr(0, 1).toLowerCase() + str.substr(1);
255}
256// upper -> Upper
257function upperFirst(str) {
258 return str.substr(0, 1).toUpperCase() + str.substr(1);
259}
260// foo_barBaz -> ['foo', 'bar', 'Baz']
261function splitWords(str) {
262 return str
263 .replace(/[A-Z]/, ' $&')
264 .split(/[^a-zA-Z0-9]+/);
265}
266// Wraps source descriptors and defines them on destination. The modifiers object
267// contains the wrappers for the new descriptors, and has 3 properties:
268// - value - A value wrapper, if function
269// - get - A getter wrapper
270// - set - A setter wrapper
271// All 3 wrappers are called with 3 arguments: handler, propertyName, args
272function delegateProperties(destination, source, modifiers) {
273 Object.getOwnPropertyNames(source).forEach(function (propertyName) {
274 var propertyDescriptor = Object.getOwnPropertyDescriptor(source, propertyName);
275 if (typeof propertyDescriptor.value === 'function' && modifiers.value) {
276 var superValue_1 = propertyDescriptor.value;
277 propertyDescriptor.value = function () {
278 var args = [].slice.call(arguments);
279 return modifiers.value.call(this, superValue_1, propertyName, args);
280 };
281 }
282 else {
283 if (propertyDescriptor.get && modifiers.get) {
284 var superGetter_1 = propertyDescriptor.get;
285 propertyDescriptor.get = function () {
286 return modifiers.get.call(this, superGetter_1, propertyName);
287 };
288 }
289 if (propertyDescriptor.set && modifiers.set) {
290 var superGetter_2 = propertyDescriptor.set;
291 propertyDescriptor.set = function (value) {
292 return modifiers.value.call(this, superGetter_2, propertyName, value);
293 };
294 }
295 }
296 Object.defineProperty(destination, propertyName, propertyDescriptor);
297 });
298 return destination;
299}
300function isEqual(objA, objB) {
301 if (objA === objB) {
302 return true;
303 }
304 if (typeof objA !== typeof objB) {
305 return false;
306 }
307 if (!(objA instanceof Object) || !(objB instanceof Object)) {
308 return false;
309 }
310 if (objA.__proto__ !== objB.__proto__) {
311 return false;
312 }
313 var objAKeys = Object.keys(objA);
314 var objBKeys = Object.keys(objB);
315 if (objAKeys.length !== objBKeys.length) {
316 return;
317 }
318 objAKeys.sort();
319 objBKeys.sort();
320 return objAKeys.every(function (keyA, index) {
321 var keyB = objBKeys[index];
322 if (keyA !== keyB) {
323 return false;
324 }
325 var valueA = objA[keyA];
326 var valueB = objB[keyB];
327 return isEqual(valueA, valueB);
328 });
329}
330function escapeBrackets(str) {
331 return str
332 .replace(/\(/g, '\\(')
333 .replace(/\)/g, '\\)')
334 .replace(/\[/g, '\\[')
335 .replace(/\]/g, '\\]')
336 .replace(/\{/g, '\\{')
337 .replace(/\}/g, '\\}')
338 .replace(/\</g, '\\<')
339 .replace(/\>/g, '\\>');
340}
341// Takes a shell script string and transforms it into a one liner
342function shCmd(cmd) {
343 return cmd
344 .trim()
345 .replace(/\n+/g, ';')
346 .replace(/\s+/g, ' ')
347 .replace(/then\s*;/g, 'then')
348 .replace(/else\s*;/g, 'else')
349 .replace(/;\s*;/g, ';')
350 .trim();
351}
352function naturalSort(as, bs) {
353 var a1;
354 var b1;
355 var i = 0;
356 var n;
357 var rx = /(\.\d+)|(\d+(\.\d+)?)|([^\d.]+)|(\.\D+)|(\.$)/g;
358 if (as === bs) {
359 return 0;
360 }
361 var a = as.toLowerCase().match(rx);
362 var b = bs.toLowerCase().match(rx);
363 var L = a.length;
364 while (i < L) {
365 if (!b[i]) {
366 return 1;
367 }
368 a1 = a[i];
369 b1 = b[i++];
370 if (a1 !== b1) {
371 n = a1 - b1;
372 if (!isNaN(n)) {
373 return n;
374 }
375 return a1 > b1 ? 1 : -1;
376 }
377 }
378 return b[i] ? -1 : 0;
379}
380// Temporarily changes CWD for child_process and then restores it at the end
381// of the execution. Useful for submodules. Will emit a 'cwdChange' event once
382// it happens to do so
383function setTempCwd(callback, tempCwd) {
384 tempCwd = path_1.resolve(cwd(), tempCwd);
385 var result = scopeEnv(function () {
386 init();
387 exports.Utils.emit('cwdChange', tempCwd);
388 return callback();
389 }, {
390 TORTILLA_CWD: tempCwd
391 });
392 init();
393 exports.Utils.emit('cwdChange', cwdReturnValue);
394 return result;
395}
396// Will use the shortest indention as an axis
397exports.freeText = function (text) {
398 if (text instanceof Array) {
399 text = text.join('');
400 }
401 // This will allow inline text generation with external functions, same as ctrl+shift+c
402 // As long as we surround the inline text with ==>text<==
403 text = text.replace(/( *)==>((?:.|\n)*?)<==/g, function (match, baseIndent, content) {
404 return content
405 .split('\n')
406 .map(function (line) { return "" + baseIndent + line; })
407 .join('\n');
408 });
409 var lines = text.split('\n');
410 var minIndent = lines.filter(function (line) { return line.trim(); }).reduce(function (soFar, line) {
411 var currIndent = line.match(/^ */)[0].length;
412 return currIndent < soFar ? currIndent : soFar;
413 }, Infinity);
414 return lines
415 .map(function (line) { return line.slice(minIndent); })
416 .join('\n')
417 .trim()
418 .replace(/\n +\n/g, '\n\n');
419};
420function log() {
421 var args = [];
422 for (var _i = 0; _i < arguments.length; _i++) {
423 args[_i] = arguments[_i];
424 }
425 console.log.apply(console, args);
426}
427function debug() {
428 var args = [];
429 for (var _i = 0; _i < arguments.length; _i++) {
430 args[_i] = arguments[_i];
431 }
432 if (process.env.DEBUG) {
433 console.log.apply(console, args);
434 }
435}
436exports.Utils = Object.assign(new events_1.EventEmitter(), {
437 cwd: cwd,
438 exec: exec,
439 inspect: inspect,
440 git: git,
441 npm: npm,
442 childProcessOf: isChildProcessOf,
443 exists: exists,
444 scopeEnv: scopeEnv,
445 filterMatches: filterMatches,
446 merge: merge,
447 extend: extend,
448 contract: contract,
449 pluck: pluck,
450 pad: pad,
451 padRight: padRight,
452 kebabCase: toKebabCase,
453 startCase: toStartCase,
454 lowerFirst: lowerFirst,
455 upperFirst: upperFirst,
456 words: splitWords,
457 delegateProperties: delegateProperties,
458 isEqual: isEqual,
459 escapeBrackets: escapeBrackets,
460 shCmd: shCmd,
461 naturalSort: naturalSort,
462 tempCwd: setTempCwd,
463 freeText: exports.freeText,
464 log: log,
465 debug: debug,
466});
467//# sourceMappingURL=utils.js.map
\No newline at end of file