forked from QuorumDMS/ftp-srv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
fs.js
116 lines (102 loc) · 3.14 KB
/
fs.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
const _ = require('lodash');
const nodePath = require('path');
const uuid = require('uuid');
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
const errors = require('./errors');
class FileSystem {
constructor(connection, {root, cwd} = {}) {
this.connection = connection;
this.cwd = cwd || nodePath.sep;
this.root = root || process.cwd();
}
_resolvePath(path = '') {
const isFromRoot = _.startsWith(path, '/') || _.startsWith(path, nodePath.sep);
const cwd = isFromRoot ? nodePath.sep : this.cwd || nodePath.sep;
const serverPath = nodePath.join(nodePath.sep, cwd, path);
const fsPath = nodePath.join(this.root, serverPath);
return {
serverPath,
fsPath
};
}
currentDirectory() {
return this.cwd;
}
get(fileName) {
const {fsPath} = this._resolvePath(fileName);
return fs.statAsync(fsPath)
.then(stat => _.set(stat, 'name', fileName));
}
list(path = '.') {
const {fsPath} = this._resolvePath(path);
return fs.readdirAsync(fsPath)
.then(fileNames => {
return Promise.map(fileNames, fileName => {
const filePath = nodePath.join(fsPath, fileName);
return fs.accessAsync(filePath, fs.constants.F_OK)
.then(() => {
return fs.statAsync(filePath)
.then(stat => _.set(stat, 'name', fileName));
})
.catch(() => null);
});
})
.then(_.compact);
}
chdir(path = '.') {
const {fsPath, serverPath} = this._resolvePath(path);
return fs.statAsync(fsPath)
.tap(stat => {
if (!stat.isDirectory()) throw new errors.FileSystemError('Not a valid directory');
})
.then(() => {
this.cwd = serverPath;
return this.currentDirectory();
});
}
write(fileName, {append = false, start = undefined} = {}) {
const {fsPath} = this._resolvePath(fileName);
const stream = fs.createWriteStream(fsPath, {flags: !append ? 'w+' : 'a+', start});
stream.once('error', () => fs.unlinkAsync(fsPath));
stream.once('close', () => stream.end());
return stream;
}
read(fileName, {start = undefined} = {}) {
const {fsPath} = this._resolvePath(fileName);
return fs.statAsync(fsPath)
.tap(stat => {
if (stat.isDirectory()) throw new errors.FileSystemError('Cannot read a directory');
})
.then(() => {
const stream = fs.createReadStream(fsPath, {flags: 'r', start});
return stream;
});
}
delete(path) {
const {fsPath} = this._resolvePath(path);
return fs.statAsync(fsPath)
.then(stat => {
if (stat.isDirectory()) return fs.rmdirAsync(fsPath);
else return fs.unlinkAsync(fsPath);
});
}
mkdir(path) {
const {fsPath} = this._resolvePath(path);
return fs.mkdirAsync(fsPath)
.then(() => fsPath);
}
rename(from, to) {
const {fsPath: fromPath} = this._resolvePath(from);
const {fsPath: toPath} = this._resolvePath(to);
return fs.renameAsync(fromPath, toPath);
}
chmod(path, mode) {
const {fsPath} = this._resolvePath(path);
return fs.chmodAsync(fsPath, mode);
}
getUniqueName() {
return uuid.v4().replace(/\W/g, '');
}
}
module.exports = FileSystem;