filefive 1.0.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.
Files changed (127) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/LICENSE +674 -0
  3. package/README.md +53 -0
  4. package/dist/App.js +69 -0
  5. package/dist/Connection.js +193 -0
  6. package/dist/FileSystem.js +13 -0
  7. package/dist/FileWatcher.js +44 -0
  8. package/dist/Local.js +86 -0
  9. package/dist/LocalWatcher.js +48 -0
  10. package/dist/Password.js +51 -0
  11. package/dist/Queue.js +236 -0
  12. package/dist/RemoteWatcher.js +44 -0
  13. package/dist/Session.js +21 -0
  14. package/dist/commands/clear.js +22 -0
  15. package/dist/commands/connect.js +87 -0
  16. package/dist/commands/copy.js +65 -0
  17. package/dist/commands/disconnect.js +12 -0
  18. package/dist/commands/duplicate.js +44 -0
  19. package/dist/commands/getConnection.js +17 -0
  20. package/dist/commands/index.js +42 -0
  21. package/dist/commands/mkdir.js +42 -0
  22. package/dist/commands/read.js +13 -0
  23. package/dist/commands/remove.js +56 -0
  24. package/dist/commands/rename.js +21 -0
  25. package/dist/commands/resolve.js +14 -0
  26. package/dist/commands/saveConnection.js +50 -0
  27. package/dist/commands/saveSettings.js +21 -0
  28. package/dist/commands/settings.js +33 -0
  29. package/dist/commands/unwatch.js +14 -0
  30. package/dist/commands/watch.js +25 -0
  31. package/dist/commands/write.js +17 -0
  32. package/dist/fs/Ftp.js +188 -0
  33. package/dist/fs/Local.js +68 -0
  34. package/dist/fs/SFtp.js +268 -0
  35. package/dist/index.js +69 -0
  36. package/dist/keybindings.json +58 -0
  37. package/dist/log.js +147 -0
  38. package/dist/options.js +5 -0
  39. package/dist/public/76e5e3fe6b35d5e6a980.woff2 +0 -0
  40. package/dist/public/assets/android-chrome-144x144.png +0 -0
  41. package/dist/public/assets/android-chrome-192x192.png +0 -0
  42. package/dist/public/assets/android-chrome-256x256.png +0 -0
  43. package/dist/public/assets/android-chrome-36x36.png +0 -0
  44. package/dist/public/assets/android-chrome-384x384.png +0 -0
  45. package/dist/public/assets/android-chrome-48x48.png +0 -0
  46. package/dist/public/assets/android-chrome-512x512.png +0 -0
  47. package/dist/public/assets/android-chrome-72x72.png +0 -0
  48. package/dist/public/assets/android-chrome-96x96.png +0 -0
  49. package/dist/public/assets/apple-touch-icon-1024x1024.png +0 -0
  50. package/dist/public/assets/apple-touch-icon-114x114.png +0 -0
  51. package/dist/public/assets/apple-touch-icon-120x120.png +0 -0
  52. package/dist/public/assets/apple-touch-icon-144x144.png +0 -0
  53. package/dist/public/assets/apple-touch-icon-152x152.png +0 -0
  54. package/dist/public/assets/apple-touch-icon-167x167.png +0 -0
  55. package/dist/public/assets/apple-touch-icon-180x180.png +0 -0
  56. package/dist/public/assets/apple-touch-icon-57x57.png +0 -0
  57. package/dist/public/assets/apple-touch-icon-60x60.png +0 -0
  58. package/dist/public/assets/apple-touch-icon-72x72.png +0 -0
  59. package/dist/public/assets/apple-touch-icon-76x76.png +0 -0
  60. package/dist/public/assets/apple-touch-icon-precomposed.png +0 -0
  61. package/dist/public/assets/apple-touch-icon.png +0 -0
  62. package/dist/public/assets/apple-touch-startup-image-1125x2436.png +0 -0
  63. package/dist/public/assets/apple-touch-startup-image-1136x640.png +0 -0
  64. package/dist/public/assets/apple-touch-startup-image-1170x2532.png +0 -0
  65. package/dist/public/assets/apple-touch-startup-image-1179x2556.png +0 -0
  66. package/dist/public/assets/apple-touch-startup-image-1242x2208.png +0 -0
  67. package/dist/public/assets/apple-touch-startup-image-1242x2688.png +0 -0
  68. package/dist/public/assets/apple-touch-startup-image-1284x2778.png +0 -0
  69. package/dist/public/assets/apple-touch-startup-image-1290x2796.png +0 -0
  70. package/dist/public/assets/apple-touch-startup-image-1334x750.png +0 -0
  71. package/dist/public/assets/apple-touch-startup-image-1488x2266.png +0 -0
  72. package/dist/public/assets/apple-touch-startup-image-1536x2048.png +0 -0
  73. package/dist/public/assets/apple-touch-startup-image-1620x2160.png +0 -0
  74. package/dist/public/assets/apple-touch-startup-image-1640x2160.png +0 -0
  75. package/dist/public/assets/apple-touch-startup-image-1668x2224.png +0 -0
  76. package/dist/public/assets/apple-touch-startup-image-1668x2388.png +0 -0
  77. package/dist/public/assets/apple-touch-startup-image-1792x828.png +0 -0
  78. package/dist/public/assets/apple-touch-startup-image-2048x1536.png +0 -0
  79. package/dist/public/assets/apple-touch-startup-image-2048x2732.png +0 -0
  80. package/dist/public/assets/apple-touch-startup-image-2160x1620.png +0 -0
  81. package/dist/public/assets/apple-touch-startup-image-2160x1640.png +0 -0
  82. package/dist/public/assets/apple-touch-startup-image-2208x1242.png +0 -0
  83. package/dist/public/assets/apple-touch-startup-image-2224x1668.png +0 -0
  84. package/dist/public/assets/apple-touch-startup-image-2266x1488.png +0 -0
  85. package/dist/public/assets/apple-touch-startup-image-2388x1668.png +0 -0
  86. package/dist/public/assets/apple-touch-startup-image-2436x1125.png +0 -0
  87. package/dist/public/assets/apple-touch-startup-image-2532x1170.png +0 -0
  88. package/dist/public/assets/apple-touch-startup-image-2556x1179.png +0 -0
  89. package/dist/public/assets/apple-touch-startup-image-2688x1242.png +0 -0
  90. package/dist/public/assets/apple-touch-startup-image-2732x2048.png +0 -0
  91. package/dist/public/assets/apple-touch-startup-image-2778x1284.png +0 -0
  92. package/dist/public/assets/apple-touch-startup-image-2796x1290.png +0 -0
  93. package/dist/public/assets/apple-touch-startup-image-640x1136.png +0 -0
  94. package/dist/public/assets/apple-touch-startup-image-750x1334.png +0 -0
  95. package/dist/public/assets/apple-touch-startup-image-828x1792.png +0 -0
  96. package/dist/public/assets/browserconfig.xml +12 -0
  97. package/dist/public/assets/favicon-16x16.png +0 -0
  98. package/dist/public/assets/favicon-32x32.png +0 -0
  99. package/dist/public/assets/favicon-48x48.png +0 -0
  100. package/dist/public/assets/favicon.ico +0 -0
  101. package/dist/public/assets/manifest.webmanifest +68 -0
  102. package/dist/public/assets/mstile-144x144.png +0 -0
  103. package/dist/public/assets/mstile-150x150.png +0 -0
  104. package/dist/public/assets/mstile-310x150.png +0 -0
  105. package/dist/public/assets/mstile-310x310.png +0 -0
  106. package/dist/public/assets/mstile-70x70.png +0 -0
  107. package/dist/public/assets/yandex-browser-50x50.png +0 -0
  108. package/dist/public/assets/yandex-browser-manifest.json +9 -0
  109. package/dist/public/ceb05254cedfa895b512.ttf +0 -0
  110. package/dist/public/f72efa639bb45d29e62f.ttf +0 -0
  111. package/dist/public/index.html +1 -0
  112. package/dist/public/index.js +2 -0
  113. package/dist/public/index.js.LICENSE.txt +43 -0
  114. package/dist/queues/Copy.js +69 -0
  115. package/dist/queues/Download.js +30 -0
  116. package/dist/queues/Duplicate.js +27 -0
  117. package/dist/queues/Queue.js +214 -0
  118. package/dist/queues/Remove.js +82 -0
  119. package/dist/queues/Upload.js +57 -0
  120. package/dist/transform.js +24 -0
  121. package/dist/types.js +46 -0
  122. package/dist/utils/ReferenceCountMap.js +61 -0
  123. package/dist/utils/URI.js +44 -0
  124. package/dist/utils/filter.js +24 -0
  125. package/dist/utils/path.js +12 -0
  126. package/dist/utils/uniqid.js +6 -0
  127. package/package.json +68 -0
@@ -0,0 +1,268 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ATTRIBUTES = void 0;
4
+ const node_path_1 = require("node:path");
5
+ const ssh2_1 = require("ssh2");
6
+ const FileSystem_1 = require("../FileSystem");
7
+ // https://github.com/mscdex/ssh2/blob/master/SFTP.md
8
+ // https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-4.3
9
+ // see also https://github.com/theophilusx/ssh2-sftp-client
10
+ exports.ATTRIBUTES = [
11
+ {
12
+ name: "name",
13
+ type: FileSystem_1.FileAttributeType.String,
14
+ title: "Name"
15
+ },
16
+ {
17
+ name: "size",
18
+ type: FileSystem_1.FileAttributeType.Number,
19
+ title: "Size"
20
+ },
21
+ {
22
+ name: "modified",
23
+ type: FileSystem_1.FileAttributeType.Date,
24
+ title: "Last Modified"
25
+ },
26
+ {
27
+ name: "rights",
28
+ type: FileSystem_1.FileAttributeType.String,
29
+ title: "Rights"
30
+ }
31
+ ];
32
+ class SFtp extends FileSystem_1.FileSystem {
33
+ constructor(host, user, password, port = 22, onError, onClose = () => { }) {
34
+ super();
35
+ this.host = host;
36
+ this.user = user;
37
+ this.password = password;
38
+ this.port = port;
39
+ this.onError = onError;
40
+ this.onClose = onClose;
41
+ this.connection = new ssh2_1.Client();
42
+ }
43
+ async open() {
44
+ if (this.connected === undefined) {
45
+ let connecting = true;
46
+ this.connected = new Promise((resolve, reject) => {
47
+ this.connection
48
+ .on('close', () => {
49
+ if (this.connected) {
50
+ if (connecting) {
51
+ reject(new Error('Remote side unexpectedly closed network connection'));
52
+ }
53
+ else {
54
+ this.onClose();
55
+ }
56
+ }
57
+ this.connected = undefined;
58
+ connecting = false;
59
+ })
60
+ .on('ready', () => {
61
+ connecting = false;
62
+ this.connection.sftp((e, sftp) => {
63
+ if (e) {
64
+ reject(new Error(this.decodeError(e)));
65
+ return;
66
+ }
67
+ this.connection.on('error', this.onError);
68
+ this.extensions = sftp._extensions;
69
+ resolve(sftp);
70
+ });
71
+ })
72
+ .on('error', err => reject(err));
73
+ });
74
+ this.connection.connect({
75
+ host: this.host,
76
+ username: this.user,
77
+ password: this.password,
78
+ port: this.port,
79
+ // debug: s => console.log('DEBUG', s)
80
+ });
81
+ }
82
+ return this.connected;
83
+ }
84
+ close() {
85
+ this.connection.end();
86
+ }
87
+ opened() {
88
+ return this.connected != undefined;
89
+ }
90
+ async pwd() {
91
+ const sftp = await this.open();
92
+ return new Promise((resolve, reject) => sftp.realpath('.', (e, current) => e ?
93
+ reject(new Error(this.decodeError(e))) :
94
+ resolve(current)));
95
+ }
96
+ async ls(dir) {
97
+ const sftp = await this.open();
98
+ return new Promise((resolve, reject) => {
99
+ sftp.readdir(dir, async (e, list) => {
100
+ if (e) {
101
+ reject(new Error(`LS: Can't get contents of ${dir} ` + this.decodeError(e)));
102
+ return;
103
+ }
104
+ const files = [];
105
+ for (let f of list) {
106
+ if (f.attrs.isSymbolicLink()) {
107
+ let target = await this.readlink((0, node_path_1.join)(dir, f.filename));
108
+ if (!(0, node_path_1.isAbsolute)(target)) {
109
+ target = (0, node_path_1.normalize)((0, node_path_1.join)(dir, target));
110
+ }
111
+ const targetStat = await this.stat(target);
112
+ files.push({
113
+ path: (0, node_path_1.join)(dir, f.filename),
114
+ name: f.filename,
115
+ dir: f.attrs.isDirectory(),
116
+ size: targetStat.size,
117
+ modified: new Date(targetStat.mtime * 1000),
118
+ owner: targetStat.uid,
119
+ group: targetStat.gid,
120
+ rights: targetStat.mode,
121
+ target
122
+ });
123
+ }
124
+ else {
125
+ files.push({
126
+ path: (0, node_path_1.join)(dir, f.filename),
127
+ name: f.filename,
128
+ dir: f.attrs.isDirectory(),
129
+ size: f.attrs.size,
130
+ modified: new Date(f.attrs.mtime * 1000),
131
+ owner: f.attrs.uid,
132
+ group: f.attrs.gid,
133
+ rights: f.attrs.mode
134
+ });
135
+ }
136
+ }
137
+ resolve(files);
138
+ });
139
+ });
140
+ }
141
+ async readlink(path) {
142
+ const sftp = await this.open();
143
+ return new Promise((resolve, reject) => {
144
+ sftp.readlink(path, (e, target) => e ? reject(new Error(this.decodeError(e))) : resolve(target));
145
+ });
146
+ }
147
+ async stat(path) {
148
+ const sftp = await this.open();
149
+ return new Promise((resolve, reject) => {
150
+ sftp.stat(path, (e, stats) => e ? reject(new Error(this.decodeError(e))) : resolve(stats));
151
+ });
152
+ }
153
+ async get(fromRemote, toLocal) {
154
+ const sftp = await this.open();
155
+ return new Promise((resolve, reject) => {
156
+ sftp.fastGet(fromRemote, toLocal, (e) => e ? reject(new Error(this.decodeError(e))) : resolve());
157
+ });
158
+ }
159
+ async put(fromLocal, toRemote) {
160
+ const sftp = await this.open();
161
+ return new Promise((resolve, reject) => {
162
+ sftp.fastPut(fromLocal, toRemote, e => e ? reject(new Error(this.decodeError(e) + ` ${toRemote}`)) : resolve());
163
+ });
164
+ }
165
+ async rm(path, recursive) {
166
+ const sftp = await this.open();
167
+ return new Promise((resolve, reject) => {
168
+ if (recursive) {
169
+ sftp.rmdir(path, e => e ? reject(new Error(this.decodeError(e))) : resolve());
170
+ }
171
+ else {
172
+ sftp.unlink(path, e => e ? reject(new Error(this.decodeError(e))) : resolve());
173
+ }
174
+ });
175
+ }
176
+ async mkdir(path) {
177
+ const sftp = await this.open();
178
+ return new Promise((resolve, reject) => sftp.mkdir(path, e => e ?
179
+ reject(new Error(`MKDIR: Can't create directory ${path} ` + this.decodeError(e))) :
180
+ resolve()));
181
+ }
182
+ async rename(from, to) {
183
+ const sftp = await this.open();
184
+ return new Promise((resolve, reject) => {
185
+ sftp.rename(from, to, e => {
186
+ if (e) {
187
+ reject(new Error(this.decodeError(e)));
188
+ return;
189
+ }
190
+ resolve();
191
+ });
192
+ });
193
+ }
194
+ async mv(from, to) {
195
+ await this.exec(`rm -Rf '${to}'`);
196
+ await this.exec(`mkdir -p '${(0, node_path_1.dirname)(to)}'`);
197
+ return this.exec(`mv -f '${from}' '${to}'`);
198
+ }
199
+ async cp(from, to, recursive) {
200
+ await this.exec(`rm -Rf '${to}'`);
201
+ if (recursive) {
202
+ return this.exec(`cp -fR '${from}' '${to}'`);
203
+ }
204
+ await this.exec(`mkdir -p '${(0, node_path_1.dirname)(to)}'`);
205
+ return this.exec(`cp -f '${from}' '${to}'`);
206
+ }
207
+ async write(path, s) {
208
+ const sftp = await this.open();
209
+ return new Promise((resolve, reject) => {
210
+ sftp.open(path, 'w', (e, h) => {
211
+ if (e) {
212
+ reject(e);
213
+ return;
214
+ }
215
+ const data = Buffer.from(s);
216
+ sftp.write(h, data, 0, data.length, 0, (e) => e ? reject(new Error(this.decodeError(e))) : resolve());
217
+ });
218
+ });
219
+ }
220
+ async exec(cmd) {
221
+ await this.open();
222
+ return new Promise((resolve, reject) => this.connection.exec(cmd, (e, stream) => {
223
+ if (e) {
224
+ reject(new Error(cmd + ': ' + this.decodeError(e)));
225
+ return;
226
+ }
227
+ stream.on('exit', (code) => {
228
+ if (code) {
229
+ reject(new Error(`${cmd}: the process's return code is ${code}`));
230
+ }
231
+ resolve();
232
+ }).on('data', (data) => {
233
+ console.log(`${cmd}: ${data}`);
234
+ }).stderr.on('data', data => {
235
+ reject(new Error(`${cmd}: ${data}`));
236
+ });
237
+ }));
238
+ }
239
+ decodeError(e) {
240
+ const STATUS_CODE = {
241
+ OK: 0,
242
+ EOF: 1,
243
+ NO_SUCH_FILE: 2,
244
+ PERMISSION_DENIED: 3,
245
+ FAILURE: 4,
246
+ BAD_MESSAGE: 5,
247
+ NO_CONNECTION: 6,
248
+ CONNECTION_LOST: 7,
249
+ OP_UNSUPPORTED: 8
250
+ };
251
+ const STATUS_CODE_STR = {
252
+ [STATUS_CODE.OK]: 'No error',
253
+ [STATUS_CODE.EOF]: 'End of file',
254
+ [STATUS_CODE.NO_SUCH_FILE]: 'No such file or directory',
255
+ [STATUS_CODE.PERMISSION_DENIED]: 'Permission denied',
256
+ [STATUS_CODE.FAILURE]: 'Failure',
257
+ [STATUS_CODE.BAD_MESSAGE]: 'Bad message',
258
+ [STATUS_CODE.NO_CONNECTION]: 'No connection',
259
+ [STATUS_CODE.CONNECTION_LOST]: 'Connection lost',
260
+ [STATUS_CODE.OP_UNSUPPORTED]: 'Operation unsupported',
261
+ };
262
+ let msg = e.message || (('code' in e) ?
263
+ (e['code'] in STATUS_CODE_STR ? STATUS_CODE_STR[e['code']] : `Code: ${e['code']}`) :
264
+ 'Unknown error');
265
+ return msg;
266
+ }
267
+ }
268
+ exports.default = SFtp;
package/dist/index.js ADDED
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const express_1 = __importDefault(require("express"));
8
+ const multer_1 = __importDefault(require("multer"));
9
+ const path_1 = require("path");
10
+ const node_os_1 = require("node:os");
11
+ const promises_1 = require("node:fs/promises");
12
+ const App_1 = __importDefault(require("./App"));
13
+ const ws_1 = require("ws");
14
+ const open = import("open");
15
+ const URI_1 = require("./utils/URI");
16
+ const types_1 = require("./types");
17
+ const commands_1 = require("./commands");
18
+ const commander_1 = require("commander");
19
+ const package_json_1 = __importDefault(require("../package.json"));
20
+ const options_1 = __importDefault(require("./options"));
21
+ commander_1.program
22
+ .name('F5')
23
+ .description('SFTP/FTP client, dual-panel file manager in the browser')
24
+ .version(package_json_1.default.version)
25
+ .option('-p, --port <number>', 'port number', '3113')
26
+ .option('--log', 'prints the log information');
27
+ commander_1.program.parse();
28
+ const inputOptions = commander_1.program.opts();
29
+ const port = inputOptions.port ?? 3113;
30
+ options_1.default.log = inputOptions.log ?? process.env.NODE_ENV == 'development';
31
+ const app = (0, express_1.default)();
32
+ app.use(express_1.default.json());
33
+ app.use(express_1.default.static((0, path_1.resolve)(__dirname, 'public')));
34
+ app.use(express_1.default.static((0, path_1.resolve)(__dirname, '../dist/public')));
35
+ const server = app.listen(port, async () => {
36
+ console.log(`Listening on http://localhost:${port}`);
37
+ if (process.env.NODE_ENV !== 'development') {
38
+ (await open).default(`http://localhost:${port}`);
39
+ }
40
+ });
41
+ const handle = async (name, handler) => {
42
+ app.post(`/api/${name}`, async (req, res) => {
43
+ try {
44
+ const result = await handler(req.body);
45
+ res.json(result ?? null);
46
+ }
47
+ catch (e) {
48
+ res.status(400);
49
+ process.env.NODE_ENV == 'development' && console.error(e);
50
+ res.json({ message: (typeof e == 'object' && 'message' in e) ? e.message : String(e) });
51
+ }
52
+ });
53
+ };
54
+ const upload = (0, multer_1.default)({ dest: (0, node_os_1.tmpdir)() });
55
+ app.post('/api/upload', upload.array('files'), async function (req, res) {
56
+ if (Array.isArray(req.files)) {
57
+ const src = [];
58
+ for (const { path, originalname } of req.files) {
59
+ const fnm = (0, path_1.join)((0, path_1.dirname)(path), originalname);
60
+ await (0, promises_1.rename)(path, fnm);
61
+ src.push(fnm);
62
+ }
63
+ commands_1.commands.copy(src.map(path => (0, URI_1.createURI)(types_1.LocalFileSystemID, path)), req.body['to'], true, null, null, () => src.forEach(path => (0, promises_1.rm)(path, { force: true })));
64
+ }
65
+ res.json(true);
66
+ });
67
+ const wss = new ws_1.WebSocketServer({ server, path: `/events` });
68
+ const emitter = channel => event => wss.clients.forEach(ws => ws.send(JSON.stringify({ channel, ...event })));
69
+ App_1.default.bootstrap(handle, emitter, async (file) => { (await open).default(file); });
@@ -0,0 +1,58 @@
1
+ [
2
+ {
3
+ "key": "meta+comma",
4
+ "command": "settings"
5
+ },
6
+ {
7
+ "key": "meta+o",
8
+ "command": "connections"
9
+ },
10
+ {
11
+ "key": "meta+s",
12
+ "command": "connections"
13
+ },
14
+ {
15
+ "key": "delete",
16
+ "command": "delete"
17
+ },
18
+ {
19
+ "key": "meta+a",
20
+ "command": "select-all"
21
+ },
22
+ {
23
+ "key": "ctrl+r",
24
+ "command": "refresh"
25
+ },
26
+ {
27
+ "key": "alt+meta+c",
28
+ "command": "copy-path"
29
+ },
30
+ {
31
+ "key": "alt+meta+shift+c",
32
+ "command": "copy-relative-path"
33
+ },
34
+ {
35
+ "key": "ctrl+meta+c",
36
+ "command": "copy-name"
37
+ },
38
+ {
39
+ "key": "f5",
40
+ "command": "transfer"
41
+ },
42
+ {
43
+ "key": "ctrl+f",
44
+ "command": "show-filter"
45
+ },
46
+ {
47
+ "key": "ctrl+bracketleft",
48
+ "command": "go-back"
49
+ },
50
+ {
51
+ "key": "ctrl+bracketright",
52
+ "command": "go-forward"
53
+ },
54
+ {
55
+ "key": "meta+y",
56
+ "command": "sync-browsing"
57
+ }
58
+ ]
package/dist/log.js ADDED
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LogFS = exports.err = exports.id = void 0;
4
+ const FileSystem_1 = require("./FileSystem");
5
+ const chalk = import('chalk');
6
+ // const logger = new Console({
7
+ // stdout: createWriteStream(join(homedir(), '.f5', 'app.log')),
8
+ // stderr: createWriteStream(join(homedir(), '.f5', 'error.log')),
9
+ // })
10
+ const logger = console;
11
+ exports.default = logger;
12
+ const cmd = async (cmd) => (await chalk).default.bold.bgGreen(cmd);
13
+ const id = async (id) => (await chalk).default.yellow(id);
14
+ exports.id = id;
15
+ const err = async (error) => (await chalk).default.red('⚠ ' + error);
16
+ exports.err = err;
17
+ class LogFS extends FileSystem_1.FileSystem {
18
+ constructor(id, fs) {
19
+ super();
20
+ this.id = id;
21
+ this.fs = fs;
22
+ }
23
+ async open() {
24
+ logger.log(await cmd('CONNECT'), await (0, exports.id)(this.id), '...');
25
+ try {
26
+ const res = await this.fs.open();
27
+ logger.log(await cmd('CONNECTED'), await (0, exports.id)(this.id));
28
+ return res;
29
+ }
30
+ catch (e) {
31
+ let msg = `Could not connect to ${this.id}`;
32
+ if ('message' in e) {
33
+ msg += ': ' + e.message;
34
+ }
35
+ logger.error(await (0, exports.err)(msg));
36
+ throw new Error(msg);
37
+ }
38
+ }
39
+ async close() {
40
+ logger.log(await cmd('CLOSE'), await (0, exports.id)(this.id));
41
+ this.fs.close();
42
+ }
43
+ opened() {
44
+ return this.fs.opened();
45
+ }
46
+ async pwd() {
47
+ logger.log(await cmd('PWD'), await (0, exports.id)(this.id));
48
+ try {
49
+ return await this.fs.pwd();
50
+ }
51
+ catch (e) {
52
+ logger.error(e);
53
+ throw e;
54
+ }
55
+ }
56
+ async ls(dir) {
57
+ logger.log(await cmd('LS'), await (0, exports.id)(this.id) + dir);
58
+ try {
59
+ return await this.fs.ls(dir);
60
+ }
61
+ catch (e) {
62
+ logger.error(e);
63
+ throw e;
64
+ }
65
+ }
66
+ async get(remote, local) {
67
+ logger.log(await cmd('GET'), `${local} ← ` + await (0, exports.id)(this.id) + remote);
68
+ try {
69
+ return await this.fs.get(remote, local);
70
+ }
71
+ catch (e) {
72
+ logger.error(e);
73
+ throw e;
74
+ }
75
+ }
76
+ async put(local, remote) {
77
+ logger.log(await cmd('PUT'), `${local} → ` + await (0, exports.id)(this.id) + remote);
78
+ try {
79
+ return await this.fs.put(local, remote);
80
+ }
81
+ catch (e) {
82
+ logger.error(e);
83
+ throw e;
84
+ }
85
+ }
86
+ async rm(path, recursive) {
87
+ logger.log(await cmd(recursive ? 'RMDIR' : 'RM'), await (0, exports.id)(this.id) + path);
88
+ try {
89
+ return await this.fs.rm(path, recursive);
90
+ }
91
+ catch (e) {
92
+ logger.error(e);
93
+ throw e;
94
+ }
95
+ }
96
+ async mkdir(path) {
97
+ logger.log(await cmd('MKDIR'), await (0, exports.id)(this.id) + path);
98
+ try {
99
+ return await this.fs.mkdir(path);
100
+ }
101
+ catch (e) {
102
+ logger.error(e);
103
+ throw e;
104
+ }
105
+ }
106
+ async rename(from, to) {
107
+ logger.log(await cmd('RENAME'), await (0, exports.id)(this.id) + from, ' → ', await (0, exports.id)(this.id) + to);
108
+ try {
109
+ return await this.fs.rename(from, to);
110
+ }
111
+ catch (e) {
112
+ logger.error(e);
113
+ throw e;
114
+ }
115
+ }
116
+ async mv(from, to) {
117
+ logger.log(await cmd('MV'), await (0, exports.id)(this.id) + from, ' → ', await (0, exports.id)(this.id) + to);
118
+ try {
119
+ return await this.fs.mv(from, to);
120
+ }
121
+ catch (e) {
122
+ logger.error(await (0, exports.err)(e.message));
123
+ throw e;
124
+ }
125
+ }
126
+ async cp(from, to, recursive) {
127
+ logger.log(await cmd(recursive ? 'CP -R' : 'CP'), await (0, exports.id)(this.id) + from, ' → ', await (0, exports.id)(this.id) + to);
128
+ try {
129
+ return await this.fs.cp(from, to, recursive);
130
+ }
131
+ catch (e) {
132
+ logger.error(await (0, exports.err)(e.message));
133
+ throw e;
134
+ }
135
+ }
136
+ async write(path, data) {
137
+ logger.log(await cmd('WRITE'), await (0, exports.id)(this.id) + path);
138
+ try {
139
+ return await this.fs.write(path, data);
140
+ }
141
+ catch (e) {
142
+ logger.error(e);
143
+ throw e;
144
+ }
145
+ }
146
+ }
147
+ exports.LogFS = LogFS;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = {
4
+ log: false
5
+ };