control-freak-ide/server/nodejs/lib/build/services/Directory.js
plastic-hub-dev-node-saturn 538369cff7 latest
2021-05-12 18:35:18 +02:00

554 lines
21 KiB
JavaScript

"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
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 Resource_1 = require("../interfaces/Resource");
const base64_1 = require("../io/base64");
const AspectDecorator_1 = require("../lang/AspectDecorator");
const Base_1 = require("../services/Base");
const Local_1 = require("../vfs/Local");
const fs = require("fs");
const mime = require('mime');
const _path = require("path");
const _ = require("lodash");
const Base_2 = require("./Base");
const Path_1 = require("../model/Path");
// import { VFS as GithubVFS, GithubResource } from '../vfs/github/Github';
// import { test as testSFTP } from '../vfs/ssh/sftp';
const sftp_1 = require("../vfs/ssh/sftp");
const copy_1 = require("../fs/copy");
const exists_1 = require("../fs/exists");
// import * as jet from 'fs-jetpack';
const mkdirp = require("mkdirp");
let posix = null;
const _fs = require('node-fs-extra');
try {
posix = require('posix');
}
catch (e) { }
const DEBUG = false;
const posixCache = {};
function FileSizeToString(size) {
const isNumber = typeof size === 'number', l1KB = 1024, l1MB = l1KB * l1KB, l1GB = l1MB * l1KB, l1TB = l1GB * l1KB, l1PB = l1TB * l1KB;
if (isNumber) {
if (size < l1KB) {
size = size + 'b';
}
else if (size < l1MB) {
size = (size / l1KB).toFixed(2) + 'kb';
}
else if (size < l1GB) {
size = (size / l1MB).toFixed(2) + 'mb';
}
else if (size < l1TB) {
size = (size / l1GB).toFixed(2) + 'gb';
}
else if (size < l1PB) {
size = (size / l1TB).toFixed(2) + 'tb';
}
else {
size = (size / l1PB).toFixed(2) + 'pb';
}
}
return size;
}
exports.FileSizeToString = FileSizeToString;
class DirectoryService extends Base_1.BaseService {
constructor(config) {
super(config.configPath, config.relativeVariables, config.absoluteVariables);
// implement Base#method for JSON_RPC2: method = XCOM_Directory_Service.fn
this.method = 'XCOM_Directory_Service';
}
// implement BaseService#init
init() {
}
// implement IVFS#get for non sending mode
_get(path, attachment, send, request) {
const args = arguments;
return new Promise((resolve, reject) => {
const split = path.split('://');
const mount = split[0];
const vfs = this.getVFS(mount, this._getRequest(args));
path = split[1];
if (!vfs) {
reject('Cant find VFS for ' + mount);
}
try {
vfs.get(path).then(resolve, reject);
return;
}
catch (e) {
reject(e);
}
});
}
// implement IVFS#get
// @before((context, args) => validateArgs(args)
// @TODO: remove back-compat for xfile
get(path, attachment, send, dummy = false, reqest = null) {
return __awaiter(this, void 0, void 0, function* () {
if (!attachment && !send) {
return yield this._get(path, attachment, send, reqest);
}
});
}
// implement IVFS#set
set(mount, path, content, reqest = null) {
const args = arguments;
return new Promise((resolve, reject) => {
const vfs = this.getVFS(mount, this._getRequest(args));
if (vfs) {
// IVFS - 2.0
if (typeof vfs['set'] === 'function') {
vfs.set(path, content).then(() => resolve(true));
return;
}
// IVFS 1.0
vfs.writefile(this.resolvePath(mount, path, this._getRequest(args)), content, this.WRITE_MODE);
resolve(true);
}
else {
reject('Cant find VFS for ' + mount);
}
});
}
// implement IVFS#rename
rename(mount, path, newFileName, dummy) {
return __awaiter(this, arguments, void 0, function* () {
const args = arguments;
return new Promise((resolve, reject) => {
const vfs = this.getVFS(mount, this._getRequest(args));
if (vfs) {
vfs.rename(path, { to: newFileName }, (err, meta) => {
err ? reject(err) : resolve(true);
});
}
else {
reject('Cant find VFS for ' + mount);
}
});
});
}
// implement IVFS#mkdir
mkdir(mount, path, reqest = null) {
return __awaiter(this, arguments, void 0, function* () {
const args = arguments;
return new Promise((resolve, reject) => {
const vfs = this.getVFS(mount, this._getRequest(args));
if (vfs) {
const resolved = this.resolvePath(mount, path, this._getRequest(args));
mkdirp.sync(resolved);
resolve(true);
/*
return;
vfs.mkdir(path, {}, (err, data) => {
if (err) {
reject("error reading file : " + err);
} else {
resolve(true);
}
});
resolve(true);
*/
}
else {
reject('Cant find VFS for ' + mount);
}
});
});
}
// implement IVFS#@touch
mkfile(mount, _path, content) {
return __awaiter(this, arguments, void 0, function* () {
const args = arguments;
return new Promise((resolve, reject) => {
const vfs = this.getVFS(mount, this._getRequest(args));
const resolved = this.resolvePath(mount, _path, this._getRequest(args));
if (vfs) {
if (fs.existsSync(resolved)) {
resolve(true);
return;
}
_fs.outputFile(resolved, content || '', function (error) {
if (error) {
reject('Error writing file: ' + error);
}
else {
resolve(true);
}
});
}
else {
reject('Cant find VFS for ' + mount);
}
});
});
}
resolveShort(_path) {
if (_path.startsWith('/')) {
_path = _path.replace('/', '');
}
const mount = _path.split('/')[0];
let parts = _path.split('/');
parts.shift();
return {
mount: mount,
path: parts.join('/')
};
}
getFiles(dir) {
const result = [];
const files = fs.readdirSync(dir);
for (let i in files) {
typeof files[i] === 'string' && result.push(files[i]);
}
return result;
}
// implement IVFS#@cp
copy(selection, dst, options, dummy = true, reqest = null) {
return __awaiter(this, arguments, void 0, function* () {
const args = arguments;
return new Promise((resolve, reject) => {
let destParts = this.resolveShort(dst);
const dstVFS = this.getVFS(destParts.mount, this._getRequest(args));
if (!dstVFS) {
reject('Cant find target VFS for ' + destParts.mount);
}
const targetDirectory = this.resolvePath(destParts.mount, destParts['path'], this._getRequest(args));
let errors = [];
// let success: Array<string> = [];
let others = this.getFiles(targetDirectory);
const newName = (name) => {
let ext = _path.extname(name);
let fileName = _path.basename(name, ext);
let found = false;
let i = 1;
let newName = null;
while (!found) {
newName = fileName + '-' + i + ext;
const colliding = others.indexOf(newName);
if (colliding !== -1) {
i++;
}
else {
found = true;
}
}
return newName;
};
let coptions = {
overwrite: true
};
_.each(selection, (path) => {
let srcParts = this.resolveShort(path);
let srcPath = this.resolvePath(srcParts.mount, srcParts.path, this._getRequest(args));
const srcVFS = this.getVFS(srcParts.mount, reqest);
if (!srcVFS) {
reject('Cant find VFS for ' + srcParts.mount);
}
const _exists = others.indexOf(_path.basename(srcPath)) !== -1;
const newPath = _exists ?
(targetDirectory + _path.sep + newName(_path.basename(srcPath))) :
(targetDirectory + _path.sep + _path.basename(srcPath));
try {
if (exists_1.sync(srcPath)) {
copy_1.sync(srcPath, newPath, coptions);
}
else {
errors.push("cp : doesnt exists " + _path.basename(srcPath));
}
}
catch (e) {
console.error('cp error');
}
});
_.isEmpty(errors) ? resolve(true) : reject(errors.join('\\'));
});
});
}
// implement IVFS#rm
// @TODO: ugly back compat for xphp in here!
delete(selection, options, reqest = null) {
const args = arguments;
return new Promise((resolve, reject) => {
const first = selection[0];
const mount = first.split('/')[0];
const vfs = this.getVFS(mount, this._getRequest(args));
let error = null;
if (!vfs) {
reject('Cant find VFS for ' + mount);
}
// VFS 2.0
if (typeof vfs['remove'] === 'function') {
let paths = selection.map((_path) => {
let parts = _path.split('/');
parts.shift();
return parts.join('/');
});
const ops = [];
paths.forEach((path) => { ops.push(vfs.remove(path)); });
Promise.all(ops).then(() => { resolve(true); }).catch(reject);
return;
}
selection.forEach((_path) => {
let parts = _path.split('/');
parts.shift();
_path = parts.join('/');
try {
vfs.rm(this.resolvePath(mount, _path, this._getRequest(args)), {}, resolve, reject);
}
catch (e) {
reject(e);
}
});
error ? reject(error) : resolve(true);
});
}
createVFSClass(resource) {
// if (resource.vfs === 'github') {
// return new GithubVFS(resource as GithubResource);
// }
if (resource.vfs === 'sftp') {
return new sftp_1.VFS(resource);
}
}
/**
*
* @param {string} mount
* @param {*} [request]
* @returns
*
* @memberOf DirectoryService
*/
getVFS(mount, request) {
const resource = this.getResourceByTypeAndName(Resource_1.EResourceType.FILE_PROXY, mount);
if (resource) {
let root = this._resolveUserMount(mount, request) || this.resolveAbsolute(resource);
try {
const vfsClass = resource.vfs;
// custom VFS class
if (vfsClass) {
return this.createVFSClass(resource);
}
if (fs.lstatSync(root)) {
return Local_1.create({
root: root,
nopty: true
}, resource);
}
else {
console.error('Cant create VFS for mount ' + mount + ': vfs root doesnt exists');
}
}
catch (e) {
console.warn('cant get VFS for ' + mount + ' root : ' + root, e);
console.log('this', this.absoluteVariables);
}
}
return null;
}
resolvePath(mount, path, request) {
const resource = this.getResourceByTypeAndName(Resource_1.EResourceType.FILE_PROXY, mount);
if (resource) {
let abs = this.resolveAbsolute(resource);
if (request) {
abs = this._resolveUserMount(mount, request, abs);
}
if (!abs == null || path == null) {
console.error('error resolving path for mount ' + mount + '|' + path + '|' + abs, new Error().stack);
}
return _path.join(abs, path);
}
else {
console.error('error resolving path, cant find resource for ' + mount + '/' + path);
}
return null;
}
getOwner(uid) {
if (posix) {
if (posixCache[uid]) {
return posixCache[uid];
}
const entry = { name: posix.getpwnam(uid)['name'] };
return posixCache[uid] = entry;
}
else {
return { name: 'unknown' };
}
}
mapNode(node, mount, root) {
const fsNodeStat = fs.statSync(node.path);
const isDirectory = fsNodeStat.isDirectory();
const nodePath = Path_1.Path.normalize(node.path.replace(root, ''));
const parent2 = new Path_1.Path(nodePath, false, false).getParentPath();
const result = {
path: Path_1.Path.normalize('.' + new Path_1.Path(nodePath, false, false).segments.join('/')),
sizeBytes: fsNodeStat.size,
size: isDirectory ? 'Folder' : FileSizeToString(fsNodeStat.size),
owner: {
user: this.getOwner(fsNodeStat.uid),
group: this.getOwner(fsNodeStat.gid)
},
mode: fsNodeStat.mode,
isDir: isDirectory,
directory: isDirectory,
mime: isDirectory ? 'directory' : mime.getType(node.path),
name: _path.win32.basename(node.path),
fileType: isDirectory ? 'folder' : 'file',
modified: fsNodeStat.mtime.getTime() / 1000,
mount: mount,
parent: Path_1.Path.normalize('./' + parent2.segments.join('/'))
};
isDirectory && (result['_EX'] = false);
return result;
}
_ls(path, mount, options, recursive = false) {
const self = this, args = arguments;
return new Promise((resolve, reject) => {
const vfs = this.getVFS(mount, this._getRequest(args));
if (!vfs) {
reject(`cant get VFS for mount '${mount}'`);
}
// try v2 VFS
if (typeof vfs.ls === 'function') {
try {
vfs.ls(path, mount, options).then((nodes) => { resolve(nodes); });
return;
}
catch (e) {
reject(e);
}
}
// v1 VFS
try {
const root = this.resolvePath(mount, '', this._getRequest(args));
// back compat : support filenames
const abs = this.resolvePath(mount, path, this._getRequest(args));
try {
const stat = fs.lstatSync(abs);
if (stat.isFile()) {
path = _path.dirname(path);
}
}
catch (e) { }
vfs.readdir(path, {}, (err, meta) => {
if (err) {
console.error('error reading directory ' + path);
reject(err);
}
if (!meta) {
reject('something wrong');
}
const nodes = [];
try {
meta.stream.on('data', (data) => nodes.push(self.mapNode(data, mount, root)));
meta.stream.on('end', () => {
resolve(nodes);
});
}
catch (e) {
reject(e);
}
});
}
catch (e) {
reject(e);
}
});
}
// implement IVFS#ls
ls(path, mount, options, recursive = false, req) {
return __awaiter(this, arguments, void 0, function* () {
const nodes = yield this._ls.apply(this, arguments);
const root = {
items: [{
_EX: true,
children: nodes,
mount: mount,
name: path,
path: path,
directory: true,
size: 0
}]
};
DEBUG && console.log('nodes', nodes);
return root;
});
}
//
// ─── DECORATOR OVERHEAD ─────────────────────────────────────────────────────────
//
getRpcMethods() {
throw new Error('Should be implemented by decorator');
}
methods() {
const methods = this.getRpcMethods();
return this.toMethods(methods);
}
}
__decorate([
Base_2.RpcMethod,
AspectDecorator_1.before((context, args) => Base_1.decodeArgs(args, '$[\'0\']', base64_1.to)),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Boolean, Boolean, Boolean, Object]),
__metadata("design:returntype", Promise)
], DirectoryService.prototype, "get", null);
__decorate([
Base_2.RpcMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, String, String, Object]),
__metadata("design:returntype", Promise)
], DirectoryService.prototype, "set", null);
__decorate([
Base_2.RpcMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, String, String, Boolean]),
__metadata("design:returntype", Promise)
], DirectoryService.prototype, "rename", null);
__decorate([
Base_2.RpcMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, String, Object]),
__metadata("design:returntype", Promise)
], DirectoryService.prototype, "mkdir", null);
__decorate([
Base_2.RpcMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, String, String]),
__metadata("design:returntype", Promise)
], DirectoryService.prototype, "mkfile", null);
__decorate([
Base_2.RpcMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [Array, String, Object, Boolean, Object]),
__metadata("design:returntype", Promise)
], DirectoryService.prototype, "copy", null);
__decorate([
Base_2.RpcMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [Array, Object, Object]),
__metadata("design:returntype", Promise)
], DirectoryService.prototype, "delete", null);
__decorate([
Base_2.RpcMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, String, Object, Boolean, Object]),
__metadata("design:returntype", Promise)
], DirectoryService.prototype, "ls", null);
exports.DirectoryService = DirectoryService;
//# sourceMappingURL=Directory.js.map