@vbarbarosh/node-helpers 3.6.0 → 3.7.0
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.
- package/package.json +3 -2
- package/src/progress.js +18 -4
- package/src/sftp_get_file_info.js +44 -0
- package/src/sftp_get_stream_range.js +47 -0
- package/src/waitcb.js +18 -0
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"author": "Vladimir Barbarosh <vladimir.barbarosh@gmail.com>",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"name": "@vbarbarosh/node-helpers",
|
|
5
|
-
"version": "3.
|
|
5
|
+
"version": "3.7.0",
|
|
6
6
|
"description": "A set of helpers for JavaScript/Node.js",
|
|
7
7
|
"files": [
|
|
8
8
|
"src"
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"form-data": "^4.0.0",
|
|
29
29
|
"json-stable-stringify": "^1.0.2",
|
|
30
30
|
"sanitize-filename": "^1.6.3",
|
|
31
|
-
"split": "^1.0.1"
|
|
31
|
+
"split": "^1.0.1",
|
|
32
|
+
"ssh2": "^1.15.0"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|
|
34
35
|
"mocha": "^10.2.0",
|
package/src/progress.js
CHANGED
|
@@ -8,27 +8,41 @@
|
|
|
8
8
|
// https://bramcohen.livejournal.com/24122.html
|
|
9
9
|
function progress(total)
|
|
10
10
|
{
|
|
11
|
-
|
|
11
|
+
const history = [];
|
|
12
12
|
const time0 = Date.now();
|
|
13
13
|
const out = {
|
|
14
14
|
done: 0,
|
|
15
15
|
total,
|
|
16
16
|
eta: null,
|
|
17
|
+
// `rate` instead of `bps` (bytes per speed) because this function could count any values (e.g.
|
|
18
|
+
// copied bytes over time, or handled jobs over time, or created object over time, etc.)
|
|
17
19
|
rate: null,
|
|
18
20
|
duration: 0,
|
|
19
21
|
progress: null,
|
|
20
22
|
percentage: null,
|
|
21
23
|
add: function (delta = 0) {
|
|
24
|
+
const now_minus_5_seconds = Date.now() - 5000;
|
|
25
|
+
history.push({time: Date.now(), delta});
|
|
26
|
+
// Keep last 5 seconds
|
|
27
|
+
history.splice(0, history.findLastIndex(v => v.time < now_minus_5_seconds));
|
|
22
28
|
out.done += delta;
|
|
23
29
|
out.refresh();
|
|
24
30
|
},
|
|
25
31
|
update: function (done) {
|
|
26
|
-
out.done
|
|
27
|
-
out.refresh();
|
|
32
|
+
out.add(done - out.done);
|
|
28
33
|
},
|
|
29
34
|
refresh: function () {
|
|
35
|
+
const now_minus_5_seconds = Date.now() - 5000;
|
|
36
|
+
const tmp = history.filter(v => v.time >= now_minus_5_seconds);
|
|
37
|
+
if (tmp.length > 1) {
|
|
38
|
+
const items = tmp.reduce((a,v) => a + v.delta, 0);
|
|
39
|
+
const time_sec = (tmp.pop().time - tmp[0].time)/1000;
|
|
40
|
+
out.rate = items/time_sec;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
out.rate = out.done/out.duration;
|
|
44
|
+
}
|
|
30
45
|
out.duration = (Date.now() - time0)/1000;
|
|
31
|
-
out.rate = out.done/out.duration;
|
|
32
46
|
out.percentage = !out.total ? null : out.done/out.total;
|
|
33
47
|
out.eta = !out.total ? null : (out.total - out.done)/out.rate;
|
|
34
48
|
},
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const Promise = require('bluebird');
|
|
2
|
+
const ignore = require('./ignore');
|
|
3
|
+
const ssh2 = require('ssh2');
|
|
4
|
+
const waitcb = require('./waitcb');
|
|
5
|
+
|
|
6
|
+
async function sftp_get_file_info(url, {log = ignore})
|
|
7
|
+
{
|
|
8
|
+
const u = new URL(url);
|
|
9
|
+
const host = u.host;
|
|
10
|
+
const port = +u.port || 22;
|
|
11
|
+
const username = decodeURIComponent(u.username);
|
|
12
|
+
const password = decodeURIComponent(u.password);
|
|
13
|
+
const pathname = u.pathname;
|
|
14
|
+
|
|
15
|
+
log('Establishing connection...');
|
|
16
|
+
const conn = new ssh2.Client();
|
|
17
|
+
try {
|
|
18
|
+
await new Promise(function (resolve, reject) {
|
|
19
|
+
conn.once('ready', resolve);
|
|
20
|
+
conn.once('error', reject);
|
|
21
|
+
conn.connect({host, port, username, password});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
log('Asking for an sftp service...');
|
|
25
|
+
const sftp = await waitcb(cb => conn.sftp(cb));
|
|
26
|
+
|
|
27
|
+
log('Requesting file info...');
|
|
28
|
+
const [stat, lstat, readdir] = await Promise.all([
|
|
29
|
+
waitcb(cb => sftp.stat(pathname, cb)),
|
|
30
|
+
waitcb(cb => sftp.lstat(pathname, cb)),
|
|
31
|
+
waitcb(cb => sftp.readdir(pathname, cb)),
|
|
32
|
+
]);
|
|
33
|
+
return {
|
|
34
|
+
stat,
|
|
35
|
+
lstat,
|
|
36
|
+
readdir,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
conn.end();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = sftp_get_file_info;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const ignore = require('./ignore');
|
|
2
|
+
const ssh2 = require('ssh2');
|
|
3
|
+
const waitcb = require('./waitcb');
|
|
4
|
+
|
|
5
|
+
const ___stat = Symbol('sftp_get_stream_range.stat');
|
|
6
|
+
|
|
7
|
+
async function sftp_get_stream_range(url, first, last, {log = ignore} = {})
|
|
8
|
+
{
|
|
9
|
+
const u = new URL(url);
|
|
10
|
+
const host = u.host;
|
|
11
|
+
const port = +u.port || 22;
|
|
12
|
+
const username = decodeURIComponent(u.username);
|
|
13
|
+
const password = decodeURIComponent(u.password);
|
|
14
|
+
const pathname = u.pathname;
|
|
15
|
+
|
|
16
|
+
log('Establishing connection...');
|
|
17
|
+
const conn = new ssh2.Client();
|
|
18
|
+
await new Promise(function (resolve, reject) {
|
|
19
|
+
conn.on('ready', resolve);
|
|
20
|
+
conn.on('error', reject);
|
|
21
|
+
conn.connect({host, port, username, password});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
log('Asking for an sftp service...');
|
|
25
|
+
const sftp = await waitcb(cb => conn.sftp(cb));
|
|
26
|
+
|
|
27
|
+
log('Requesting file info...');
|
|
28
|
+
const stat = url[___stat] || (url[___stat] = await waitcb(cb => sftp.stat(pathname, cb)));
|
|
29
|
+
|
|
30
|
+
if (first < 0 || last >= stat.size) {
|
|
31
|
+
throw new Error(`Invalid range: [first=${first}][last=${last}]`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const out = sftp.createReadStream(pathname, {start: first, end: last})
|
|
35
|
+
out.content_range = {
|
|
36
|
+
type: 'bytes',
|
|
37
|
+
first,
|
|
38
|
+
last,
|
|
39
|
+
total: stat.size,
|
|
40
|
+
};
|
|
41
|
+
out.once('end', function () {
|
|
42
|
+
conn.end();
|
|
43
|
+
});
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = sftp_get_stream_range;
|
package/src/waitcb.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const Promise = require('bluebird');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wait for a Node-like function to finish (which will call `callback`
|
|
5
|
+
* with 2 arguments: `error` and `value`).
|
|
6
|
+
*
|
|
7
|
+
* await waitcb(cb => fs.promises.writeFile('a', 'hello\n', cb));
|
|
8
|
+
*/
|
|
9
|
+
function waitcb(fn)
|
|
10
|
+
{
|
|
11
|
+
return new Promise(function (resolve, reject) {
|
|
12
|
+
fn(function (error, out) {
|
|
13
|
+
error ? reject(error) : resolve(out);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = waitcb;
|