305 lines
12 KiB
JavaScript
305 lines
12 KiB
JavaScript
"use strict";
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const ssh2_1 = require("ssh2");
|
|
const fs = require("fs");
|
|
const pathUtil = require("path");
|
|
const Path_1 = require("../../model/Path");
|
|
const Resource_1 = require("../../interfaces/Resource");
|
|
class VFS {
|
|
constructor(resource) {
|
|
this.resource = resource;
|
|
this.options = this.parseOptions(resource.options);
|
|
this.init();
|
|
}
|
|
/**
|
|
* Map internal node rep. to public INode
|
|
*
|
|
* @param {ITreeBlobNode} node
|
|
* @param {string} mount
|
|
* @param {IObjectLiteral} options
|
|
* @returns {INode}
|
|
*
|
|
* @memberOf VFS
|
|
*/
|
|
mapNode(root, node, stats, mount, options) {
|
|
const directory = stats.isDirectory();
|
|
const abs = new Path_1.Path('./' + root + '/' + node.filename).toString().replace(this.options.root, '');
|
|
const parent = new Path_1.Path(abs, false, false).getParentPath();
|
|
return {
|
|
path: Path_1.Path.normalize('./' + abs),
|
|
sizeBytes: node.attrs.size,
|
|
size: node.attrs.size,
|
|
mtime: node.attrs.mtime,
|
|
atime: node.attrs.atime,
|
|
owner: {
|
|
user: null,
|
|
group: null
|
|
},
|
|
isDir: directory,
|
|
directory: directory,
|
|
mime: !directory ? 'file' : 'folder',
|
|
name: pathUtil.win32.basename(node.filename),
|
|
fileType: directory ? 'folder' : 'file',
|
|
mount: mount,
|
|
parent: Path_1.Path.normalize("./" + parent.toString()),
|
|
type: ''
|
|
};
|
|
}
|
|
list(path) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
return new Promise((resolve, reject) => {
|
|
let sftp = this.sftp;
|
|
if (sftp) {
|
|
sftp.readdir(path, (err, list) => {
|
|
if (err) {
|
|
reject(err);
|
|
return false;
|
|
}
|
|
// reset file info
|
|
list.forEach((item, i) => {
|
|
const _item = list[i];
|
|
_item['name'] = item.filename;
|
|
_item['type'] = item.longname.substr(0, 1);
|
|
});
|
|
resolve(list);
|
|
});
|
|
}
|
|
else {
|
|
reject('sftp connect error');
|
|
}
|
|
});
|
|
});
|
|
}
|
|
_delete(path) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
return new Promise((resolve, reject) => {
|
|
let sftp = this.sftp;
|
|
if (sftp) {
|
|
sftp.unlink(path, (err) => {
|
|
if (err) {
|
|
reject(err);
|
|
return false;
|
|
}
|
|
resolve();
|
|
});
|
|
}
|
|
else {
|
|
reject('sftp connect error');
|
|
}
|
|
});
|
|
});
|
|
}
|
|
;
|
|
remove(path, options) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
return new Promise((resolve, reject) => {
|
|
this.init().then(() => {
|
|
path = this.resolve(path);
|
|
this.sftp.stat(path, (err, stats) => {
|
|
if (stats.isDirectory()) {
|
|
/*
|
|
this.sftp.rmdir(path, (err) => {
|
|
err ? reject(err) : resolve(true);
|
|
});
|
|
*/
|
|
let rmdir = (p) => {
|
|
return this.list(p).then((list) => {
|
|
if (list.length > 0) {
|
|
let promises = [];
|
|
list.forEach((item) => {
|
|
let name = item.name;
|
|
let promise;
|
|
let subPath;
|
|
if (name[0] === '/') {
|
|
subPath = name;
|
|
}
|
|
else {
|
|
if (p[p.length - 1] === '/') {
|
|
subPath = p + name;
|
|
}
|
|
else {
|
|
subPath = p + '/' + name;
|
|
}
|
|
}
|
|
if (item.type === 'd') {
|
|
if (name !== '.' || name !== '..') {
|
|
promise = rmdir(subPath);
|
|
}
|
|
}
|
|
else {
|
|
promise = this._delete(subPath);
|
|
}
|
|
promises.push(promise);
|
|
});
|
|
if (promises.length) {
|
|
return Promise.all(promises).then(() => {
|
|
return rmdir(p);
|
|
});
|
|
}
|
|
}
|
|
else {
|
|
return new Promise((resolve, reject) => {
|
|
return this.sftp.rmdir(p, (err) => {
|
|
if (err) {
|
|
reject(err);
|
|
}
|
|
else {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
});
|
|
};
|
|
return rmdir(path).then(() => { resolve(); });
|
|
}
|
|
else {
|
|
this.sftp.unlink(path, (err) => {
|
|
err ? reject(err) : resolve(true);
|
|
});
|
|
}
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
resolve(path) {
|
|
path = new Path_1.Path(path, true, false).toString();
|
|
if (path === '.') {
|
|
path = '';
|
|
}
|
|
if (!path.startsWith('/')) {
|
|
path = '/' + path;
|
|
}
|
|
return Path_1.Path.normalize(this.options.root + '/' + path);
|
|
}
|
|
ls(path = '/', mount) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
path = this.resolve(path);
|
|
return new Promise((resolve, reject) => {
|
|
this.init().then(() => {
|
|
const ret = [];
|
|
let nodes = [];
|
|
const proceed = () => {
|
|
if (!nodes.length) {
|
|
resolve(ret);
|
|
return;
|
|
}
|
|
const next = nodes[0];
|
|
this.sftp.stat(path + '/' + next.filename, (err, stats) => {
|
|
if (err) {
|
|
console.error('err', err);
|
|
nodes.shift();
|
|
proceed();
|
|
return;
|
|
}
|
|
if (!stats) {
|
|
console.error('cant get stats for ' + next.filename + ' with path query ' + path);
|
|
nodes.shift();
|
|
proceed();
|
|
return;
|
|
}
|
|
ret.push(this.mapNode(path, next, stats, mount));
|
|
nodes.shift();
|
|
proceed();
|
|
});
|
|
};
|
|
this.sftp.readdir(path, (err, files) => {
|
|
if (err) {
|
|
reject(err);
|
|
}
|
|
if (files) {
|
|
nodes = files;
|
|
}
|
|
else {
|
|
console.error('have no files at ' + path, err);
|
|
reject(err);
|
|
}
|
|
proceed();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
init() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
this.client = new ssh2_1.Client();
|
|
return new Promise((resolve, reject) => {
|
|
this.client.on('error', reject);
|
|
this.client.on('ready', () => {
|
|
this.client.sftp((err, sftp) => {
|
|
this.sftp = sftp;
|
|
resolve(true);
|
|
});
|
|
}).connect({
|
|
host: this.options.host,
|
|
port: this.options.port,
|
|
username: this.options.user,
|
|
privateKey: this.options.key,
|
|
password: this.options.password
|
|
});
|
|
});
|
|
});
|
|
}
|
|
parseOptions(options) {
|
|
if (typeof options === "undefined") {
|
|
throw new Error('options hash is required!');
|
|
}
|
|
options = options || {};
|
|
options.host = options.host || "localhost";
|
|
options.port = options.port || 22;
|
|
options.user = options.user || "mc007";
|
|
options.password = options.password || null;
|
|
options.root = options.root || '/';
|
|
if (options.key && fs.existsSync(options.key)) {
|
|
options.key = require('fs').readFileSync(options.key);
|
|
}
|
|
return options;
|
|
}
|
|
}
|
|
exports.VFS = VFS;
|
|
function test() {
|
|
const ab = true;
|
|
if (ab) {
|
|
return;
|
|
}
|
|
let o = {
|
|
host: '192.168.1.37',
|
|
user: 'mc007',
|
|
port: 22,
|
|
password: '214,,asd'
|
|
};
|
|
let or = {
|
|
host: 'pearls-media.com',
|
|
user: 'vu2003',
|
|
port: 22,
|
|
key: '/home/mc007/.ssh/id_rsa'
|
|
};
|
|
let r = {
|
|
options: or,
|
|
enabled: true,
|
|
name: 'sftp',
|
|
path: '',
|
|
readOnly: false,
|
|
type: Resource_1.EResourceType.FILE_PROXY,
|
|
label: '',
|
|
vfs: '',
|
|
url: ''
|
|
};
|
|
let vfs = new VFS(r);
|
|
vfs.ls('/var/www/virtual/pearls-media.com').then((nodes) => {
|
|
console.log('node', [nodes[0], nodes[1]]);
|
|
});
|
|
// console.log('vfs', vfs);
|
|
}
|
|
exports.test = test;
|
|
// test();
|
|
//# sourceMappingURL=sftp.js.map
|