UNPKG

5.76 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.shell = exports.ShellContext = exports.spawn = exports.exec = exports.execa = void 0;
4const tslib_1 = require("tslib");
5const execa_1 = tslib_1.__importDefault(require("execa"));
6exports.execa = execa_1.default;
7const path_1 = tslib_1.__importDefault(require("path"));
8const logger_1 = require("./logger");
9const utils_1 = require("./utils");
10const fs_1 = require("./fs");
11const shellParser = require('shell-parser');
12function _exec(cmd, options) {
13 let [file, ...args] = shellParser(cmd);
14 return execa_1.default(file, args, options);
15}
16function exec(commands, options) {
17 if (utils_1.Is.str(commands)) {
18 return _exec(commands, options);
19 }
20 const rets = [];
21 let retsP = Promise.resolve(null);
22 for (const cmd of commands) {
23 retsP = retsP.then(() => {
24 return _exec(cmd, options).then((r) => {
25 rets.push(r);
26 return rets;
27 });
28 });
29 }
30 return retsP;
31}
32exports.exec = exec;
33exports.spawn = execa_1.default;
34class ShellContext {
35 constructor() {
36 this._cwdStack = [process.cwd()];
37 this._env = {};
38 this.logCommand = false;
39 this.sleep = utils_1.sleep;
40 this._logger = logger_1.logger;
41 this._process = { current: null };
42 }
43 /**
44 * get current word directory
45 */
46 get cwd() {
47 return this._cwdStack[this._cwdStack.length - 1];
48 }
49 /**
50 * change work directory
51 * @param dir
52 */
53 cd(dir) {
54 this._cwdStack[this._cwdStack.length - 1] = path_1.default.resolve(this._cwdStack[this._cwdStack.length - 1], dir);
55 return this;
56 }
57 /**
58 * like pushd in shell
59 * @param dir
60 */
61 pushd(dir) {
62 this._cwdStack.push(path_1.default.resolve(this._cwdStack[this._cwdStack.length - 1], dir));
63 return this;
64 }
65 /**
66 * like popd in shell
67 */
68 popd() {
69 this._cwdStack.pop();
70 return this;
71 }
72 exec(commands, options) {
73 this._logCmd(commands);
74 let p = exec(commands, Object.assign({ cwd: this.cwd, env: Object.assign(Object.assign({}, process.env), this._env), stdio: 'inherit' }, options));
75 // tslint:disable-next-line:no-floating-promises
76 p.catch((err) => {
77 this._logger.error('Exec failed: ', commands);
78 throw err;
79 });
80 this._process.current = p;
81 p.finally(() => {
82 this._process.current = null;
83 });
84 return p;
85 }
86 /**
87 * spawn file
88 * @param file
89 * @param args
90 * @param options
91 */
92 spawn(file, args = [], options) {
93 const command = file + ' ' + args.map((a) => `"${a.replace(/"/g, '\\"')}"`).join(' ');
94 this._logCmd(command);
95 let p = exports.spawn(file, args, Object.assign({ cwd: this.cwd, env: Object.assign(Object.assign({}, process.env), this._env), stdio: 'inherit' }, options));
96 // tslint:disable-next-line:no-floating-promises
97 p.catch((err) => {
98 this._logger.error('Exec failed: ', command);
99 throw err;
100 });
101 this._process.current = p;
102 p.finally(() => {
103 this._process.current = null;
104 });
105 return p;
106 }
107 env(key, val) {
108 if (arguments.length === 1) {
109 return this._env[key];
110 }
111 if (utils_1.Is.defed(val)) {
112 this._env[key] = val;
113 }
114 else {
115 delete this._env[key];
116 }
117 return this;
118 }
119 /**
120 * restart processes when file changes
121 * @example
122 * ctx.monitor('./src', 'tsc')
123 * ctx.monitor('./src', 'webpack')
124 * ctx.monitor('./src', 'foy watch')
125 * ctx.monitor('./src', ['rm -rf dist', 'foy watch'])
126 * ctx.monitor('./src', async p => {
127 * await fs.rmrf('dist')
128 * p.current = ctx.exec('webpack serve')
129 * })
130 */
131 monitor(dir, run, options = {}) {
132 let p = this._process;
133 fs_1.fs.watchDir(dir, options, (event, file) => tslib_1.__awaiter(this, void 0, void 0, function* () {
134 if (options.ignore && options.ignore(event, file)) {
135 return;
136 }
137 while (p.current && !p.current.killed && p.current.exitCode === null) {
138 p.current.kill();
139 yield utils_1.sleep(1000);
140 }
141 if (typeof run === 'string') {
142 let cmd = run;
143 run = (p) => (p.current = this.exec(cmd));
144 }
145 if (Array.isArray(run)) {
146 let cmds = run;
147 run = (p) => tslib_1.__awaiter(this, void 0, void 0, function* () {
148 for (const cmd of cmds.slice(0, -1)) {
149 yield this.exec(cmd);
150 }
151 p.current = this.exec(cmds.slice(-1)[0]);
152 });
153 }
154 run(p);
155 }));
156 }
157 /**
158 * reset env to default
159 */
160 resetEnv() {
161 this._env = {};
162 return this;
163 }
164 _logCmd(cmd) {
165 if (this.logCommand) {
166 let env = Object.keys(this._env)
167 .map((k) => `${k}=${this._env[k] || ''}`)
168 .join(' ');
169 if (env) {
170 env += ' ';
171 }
172 cmd = Array.isArray(cmd) ? cmd : [cmd];
173 cmd.forEach((cmd) => {
174 this._logger.info(`$ ${env}${cmd}`);
175 });
176 }
177 }
178}
179exports.ShellContext = ShellContext;
180function shell(callback) {
181 return tslib_1.__awaiter(this, void 0, void 0, function* () {
182 return callback(new ShellContext());
183 });
184}
185exports.shell = shell;
186//# sourceMappingURL=exec.js.map
\No newline at end of file