1 | (function() {
|
2 | module.exports = function($) {
|
3 | var SSH, _, formatArgument, kleur, normalizePathToArray, path, wrapList;
|
4 | ({_} = $);
|
5 | ({formatArgument, normalizePathToArray, wrapList} = $.fn);
|
6 |
|
7 | kleur = require('kleur');
|
8 | path = require('path');
|
9 | SSH = class SSH {
|
10 | |
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | async connect_(option) {
|
22 | await new Promise((resolve) => {
|
23 | var Client, conn, infoServer;
|
24 | ({Client} = require('ssh2'));
|
25 | conn = new Client();
|
26 | infoServer = `${option.username}@${option.host}`;
|
27 | conn.on('end', function() {
|
28 | return $.info('ssh', `disconnected from '${infoServer}'`);
|
29 | }).on('error', function(err) {
|
30 | throw err;
|
31 | }).on('ready', function() {
|
32 | $.info('ssh', `connected to '${infoServer}'`);
|
33 | return resolve();
|
34 | }).connect(option);
|
35 | return this.storage = {conn, option};
|
36 | });
|
37 | return this;
|
38 | }
|
39 |
|
40 | async disconnect_() {
|
41 | await new Promise((resolve) => {
|
42 | var conn;
|
43 | ({conn} = this.storage);
|
44 | return conn.on('end', function() {
|
45 | return resolve();
|
46 | }).end();
|
47 | });
|
48 | return this;
|
49 | }
|
50 |
|
51 | async exec_(cmd, option = {}) {
|
52 | await new Promise((resolve) => {
|
53 | var conn;
|
54 | ({conn} = this.storage);
|
55 | cmd = formatArgument(cmd);
|
56 | cmd = cmd.join(' && ');
|
57 | $.info('ssh', kleur.blue(cmd));
|
58 | return conn.exec(cmd, (err, stream) => {
|
59 | if (err) {
|
60 | throw err;
|
61 | }
|
62 | stream.on('end', function() {
|
63 | return resolve();
|
64 | });
|
65 | stream.stderr.on('data', (chunk) => {
|
66 | if (option.ignoreError) {
|
67 | return this.info(chunk);
|
68 | }
|
69 | throw $.parseString(chunk);
|
70 | });
|
71 | return stream.stdout.on('data', (chunk) => {
|
72 | return this.info(chunk);
|
73 | });
|
74 | });
|
75 | });
|
76 | return this;
|
77 | }
|
78 |
|
79 | info(chunk) {
|
80 | var string;
|
81 | string = $.trim($.parseString(chunk));
|
82 | if (!string.length) {
|
83 | return;
|
84 | }
|
85 | string = string.replace(/\r/g, '\n').replace(/\n{2,}/g, '');
|
86 | return $.i(string);
|
87 | }
|
88 |
|
89 | async mkdir_(source) {
|
90 | var cmd, src;
|
91 | source = formatArgument(source);
|
92 | cmd = ((function() {
|
93 | var i, len, results;
|
94 | results = [];
|
95 | for (i = 0, len = source.length; i < len; i++) {
|
96 | src = source[i];
|
97 | results.push(`mkdir -p ${src}`);
|
98 | }
|
99 | return results;
|
100 | })()).join('; ');
|
101 | $.info.pause('$.ssh.mkdir_');
|
102 | await this.exec_(cmd);
|
103 | $.info.resume('$.ssh.mkdir_');
|
104 | $.info('ssh', `created ${wrapList(source)}`);
|
105 | return this;
|
106 | }
|
107 |
|
108 | async remove_(source) {
|
109 | var cmd, src;
|
110 | source = formatArgument(source);
|
111 | cmd = ((function() {
|
112 | var i, len, results;
|
113 | results = [];
|
114 | for (i = 0, len = source.length; i < len; i++) {
|
115 | src = source[i];
|
116 | results.push(`rm -fr ${src}`);
|
117 | }
|
118 | return results;
|
119 | })()).join('; ');
|
120 | $.info.pause('$.ssh.remove_');
|
121 | await this.exec_(cmd);
|
122 | $.info.resume('$.ssh.remove_');
|
123 | $.info('ssh', `removed ${wrapList(source)}`);
|
124 | return this;
|
125 | }
|
126 |
|
127 | async upload_(source, target, option = {}) {
|
128 | await new Promise((resolve) => {
|
129 | var conn;
|
130 | ({conn} = this.storage);
|
131 | source = normalizePathToArray(source);
|
132 | option = (function() {
|
133 | switch ($.type(option)) {
|
134 | case 'object':
|
135 | return _.clone(option);
|
136 | case 'string':
|
137 | return {
|
138 | filename: option
|
139 | };
|
140 | default:
|
141 | throw new Error('invalid type');
|
142 | }
|
143 | })();
|
144 | return conn.sftp(async(err, sftp) => {
|
145 | var filename, i, len, src, stat;
|
146 | if (err) {
|
147 | throw err;
|
148 | }
|
149 | for (i = 0, len = source.length; i < len; i++) {
|
150 | src = source[i];
|
151 | stat = (await $.stat_(src));
|
152 | filename = option.filename || path.basename(src);
|
153 | if (stat.isDirectory()) {
|
154 | await this.uploadDir_(sftp, src, `${target}/${filename}`);
|
155 | } else if (stat.isFile()) {
|
156 | await this.mkdir_(target);
|
157 | await this.uploadFile_(sftp, src, `${target}/${filename}`);
|
158 | }
|
159 | }
|
160 | sftp.end();
|
161 | return resolve();
|
162 | });
|
163 | });
|
164 | return this;
|
165 | }
|
166 |
|
167 | async uploadDir_(sftp, source, target) {
|
168 | await new Promise(async(resolve) => {
|
169 | var i, len, listSource, relativeTarget, src, stat;
|
170 | listSource = [];
|
171 | await $.walk_(source, function(item) {
|
172 | return listSource.push(item.path);
|
173 | });
|
174 | for (i = 0, len = listSource.length; i < len; i++) {
|
175 | src = listSource[i];
|
176 | stat = (await $.stat_(src));
|
177 | relativeTarget = path.normalize(`${target}/${path.relative(source, src)}`);
|
178 | if (stat.isDirectory()) {
|
179 | await this.mkdir_(relativeTarget);
|
180 | } else if (stat.isFile()) {
|
181 | await this.uploadFile_(sftp, src, relativeTarget);
|
182 | }
|
183 | }
|
184 | return resolve();
|
185 | });
|
186 | return this;
|
187 | }
|
188 |
|
189 | async uploadFile_(sftp, source, target) {
|
190 | await new Promise(function(resolve) {
|
191 | return sftp.fastPut(source, target, function(err) {
|
192 | if (err) {
|
193 | throw err;
|
194 | }
|
195 | $.info('ssh', `uploaded '${source}' to '${target}'`);
|
196 | return resolve();
|
197 | });
|
198 | });
|
199 | return this;
|
200 | }
|
201 |
|
202 | };
|
203 |
|
204 |
|
205 | return $.ssh = function() {
|
206 | var i, key, len, listKey, ssh;
|
207 | ssh = new SSH();
|
208 |
|
209 |
|
210 | listKey = ['connect', 'disconnect', 'exec', 'mkdir', 'remove', 'upload', 'uploadDir', 'uploadFile'];
|
211 | for (i = 0, len = listKey.length; i < len; i++) {
|
212 | key = listKey[i];
|
213 | ssh[`${key}Async`] = ssh[`${key}_`];
|
214 | }
|
215 | return ssh;
|
216 | };
|
217 | };
|
218 |
|
219 | }).call(this);
|