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.
- package/CHANGELOG.md +2 -0
- package/LICENSE +674 -0
- package/README.md +53 -0
- package/dist/App.js +69 -0
- package/dist/Connection.js +193 -0
- package/dist/FileSystem.js +13 -0
- package/dist/FileWatcher.js +44 -0
- package/dist/Local.js +86 -0
- package/dist/LocalWatcher.js +48 -0
- package/dist/Password.js +51 -0
- package/dist/Queue.js +236 -0
- package/dist/RemoteWatcher.js +44 -0
- package/dist/Session.js +21 -0
- package/dist/commands/clear.js +22 -0
- package/dist/commands/connect.js +87 -0
- package/dist/commands/copy.js +65 -0
- package/dist/commands/disconnect.js +12 -0
- package/dist/commands/duplicate.js +44 -0
- package/dist/commands/getConnection.js +17 -0
- package/dist/commands/index.js +42 -0
- package/dist/commands/mkdir.js +42 -0
- package/dist/commands/read.js +13 -0
- package/dist/commands/remove.js +56 -0
- package/dist/commands/rename.js +21 -0
- package/dist/commands/resolve.js +14 -0
- package/dist/commands/saveConnection.js +50 -0
- package/dist/commands/saveSettings.js +21 -0
- package/dist/commands/settings.js +33 -0
- package/dist/commands/unwatch.js +14 -0
- package/dist/commands/watch.js +25 -0
- package/dist/commands/write.js +17 -0
- package/dist/fs/Ftp.js +188 -0
- package/dist/fs/Local.js +68 -0
- package/dist/fs/SFtp.js +268 -0
- package/dist/index.js +69 -0
- package/dist/keybindings.json +58 -0
- package/dist/log.js +147 -0
- package/dist/options.js +5 -0
- package/dist/public/76e5e3fe6b35d5e6a980.woff2 +0 -0
- package/dist/public/assets/android-chrome-144x144.png +0 -0
- package/dist/public/assets/android-chrome-192x192.png +0 -0
- package/dist/public/assets/android-chrome-256x256.png +0 -0
- package/dist/public/assets/android-chrome-36x36.png +0 -0
- package/dist/public/assets/android-chrome-384x384.png +0 -0
- package/dist/public/assets/android-chrome-48x48.png +0 -0
- package/dist/public/assets/android-chrome-512x512.png +0 -0
- package/dist/public/assets/android-chrome-72x72.png +0 -0
- package/dist/public/assets/android-chrome-96x96.png +0 -0
- package/dist/public/assets/apple-touch-icon-1024x1024.png +0 -0
- package/dist/public/assets/apple-touch-icon-114x114.png +0 -0
- package/dist/public/assets/apple-touch-icon-120x120.png +0 -0
- package/dist/public/assets/apple-touch-icon-144x144.png +0 -0
- package/dist/public/assets/apple-touch-icon-152x152.png +0 -0
- package/dist/public/assets/apple-touch-icon-167x167.png +0 -0
- package/dist/public/assets/apple-touch-icon-180x180.png +0 -0
- package/dist/public/assets/apple-touch-icon-57x57.png +0 -0
- package/dist/public/assets/apple-touch-icon-60x60.png +0 -0
- package/dist/public/assets/apple-touch-icon-72x72.png +0 -0
- package/dist/public/assets/apple-touch-icon-76x76.png +0 -0
- package/dist/public/assets/apple-touch-icon-precomposed.png +0 -0
- package/dist/public/assets/apple-touch-icon.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1125x2436.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1136x640.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1170x2532.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1179x2556.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1242x2208.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1242x2688.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1284x2778.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1290x2796.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1334x750.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1488x2266.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1536x2048.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1620x2160.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1640x2160.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1668x2224.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1668x2388.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-1792x828.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-2048x1536.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-2048x2732.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-2160x1620.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-2160x1640.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-2208x1242.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-2224x1668.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-2266x1488.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-2388x1668.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-2436x1125.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-2532x1170.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-2556x1179.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-2688x1242.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-2732x2048.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-2778x1284.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-2796x1290.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-640x1136.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-750x1334.png +0 -0
- package/dist/public/assets/apple-touch-startup-image-828x1792.png +0 -0
- package/dist/public/assets/browserconfig.xml +12 -0
- package/dist/public/assets/favicon-16x16.png +0 -0
- package/dist/public/assets/favicon-32x32.png +0 -0
- package/dist/public/assets/favicon-48x48.png +0 -0
- package/dist/public/assets/favicon.ico +0 -0
- package/dist/public/assets/manifest.webmanifest +68 -0
- package/dist/public/assets/mstile-144x144.png +0 -0
- package/dist/public/assets/mstile-150x150.png +0 -0
- package/dist/public/assets/mstile-310x150.png +0 -0
- package/dist/public/assets/mstile-310x310.png +0 -0
- package/dist/public/assets/mstile-70x70.png +0 -0
- package/dist/public/assets/yandex-browser-50x50.png +0 -0
- package/dist/public/assets/yandex-browser-manifest.json +9 -0
- package/dist/public/ceb05254cedfa895b512.ttf +0 -0
- package/dist/public/f72efa639bb45d29e62f.ttf +0 -0
- package/dist/public/index.html +1 -0
- package/dist/public/index.js +2 -0
- package/dist/public/index.js.LICENSE.txt +43 -0
- package/dist/queues/Copy.js +69 -0
- package/dist/queues/Download.js +30 -0
- package/dist/queues/Duplicate.js +27 -0
- package/dist/queues/Queue.js +214 -0
- package/dist/queues/Remove.js +82 -0
- package/dist/queues/Upload.js +57 -0
- package/dist/transform.js +24 -0
- package/dist/types.js +46 -0
- package/dist/utils/ReferenceCountMap.js +61 -0
- package/dist/utils/URI.js +44 -0
- package/dist/utils/filter.js +24 -0
- package/dist/utils/path.js +12 -0
- package/dist/utils/uniqid.js +6 -0
- package/package.json +68 -0
package/dist/Queue.js
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.queues = void 0;
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
const types_1 = require("./types");
|
|
9
|
+
const Local_1 = require("./Local");
|
|
10
|
+
const URI_1 = require("./utils/URI");
|
|
11
|
+
const ramda_1 = require("ramda");
|
|
12
|
+
const rxjs_1 = require("rxjs");
|
|
13
|
+
const Connection_1 = __importDefault(require("./Connection"));
|
|
14
|
+
const log_1 = __importDefault(require("./log"));
|
|
15
|
+
class Queue {
|
|
16
|
+
constructor(type, connId, src, dest, watcher, onState, onConflict, onError, onComplete) {
|
|
17
|
+
this.type = type;
|
|
18
|
+
this.connId = connId;
|
|
19
|
+
this.watcher = watcher;
|
|
20
|
+
this.onState = onState;
|
|
21
|
+
this.onConflict = onConflict;
|
|
22
|
+
this.onError = onError;
|
|
23
|
+
this.onComplete = onComplete;
|
|
24
|
+
this.queue = [];
|
|
25
|
+
this.queue$ = new rxjs_1.Subject();
|
|
26
|
+
this.totalCnt = 0;
|
|
27
|
+
this.doneCnt = 0;
|
|
28
|
+
this.totalSize = 0;
|
|
29
|
+
this.doneSize = 0;
|
|
30
|
+
this.pending = [];
|
|
31
|
+
this.touched = new Set();
|
|
32
|
+
if (type == types_1.QueueType.Download) {
|
|
33
|
+
this.download(src, (0, URI_1.parseURI)(dest)['path']);
|
|
34
|
+
}
|
|
35
|
+
else if (type == types_1.QueueType.Upload) {
|
|
36
|
+
this.upload(src.map(uri => (0, URI_1.parseURI)(uri)['path']), dest);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
this.remove(src.map(uri => (0, URI_1.parseURI)(uri)['path']));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
resolve(action, forAll = false) {
|
|
43
|
+
forAll && (this.action = action);
|
|
44
|
+
const drained = !this.queue.length;
|
|
45
|
+
this.queue.push(...this.pending.splice(0, forAll ? this.pending.length : 1).map(f => ({ from: f.src, to: f.dest.path, action })));
|
|
46
|
+
drained && this.queue$.next(this.queue.shift());
|
|
47
|
+
if (this.pending.length) {
|
|
48
|
+
const { src, dest } = this.pending[0];
|
|
49
|
+
this.onConflict(src, dest);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
close() {
|
|
53
|
+
if (this.processing?.closed === false) {
|
|
54
|
+
this.processing?.unsubscribe();
|
|
55
|
+
this.onComplete();
|
|
56
|
+
if (this.type == types_1.QueueType.Upload || this.type == types_1.QueueType.Remove) {
|
|
57
|
+
this.touched.forEach(path => this.watcher.refresh(this.connId + path));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async download(src, dest) {
|
|
62
|
+
await this.enqueue(src.map((0, ramda_1.pipe)(URI_1.parseURI, (0, ramda_1.prop)('path'))), dest, (0, ramda_1.memoizeWith)(ramda_1.identity, (path) => Connection_1.default.list(this.connId, path)));
|
|
63
|
+
const transmit = async (fs, from, to) => {
|
|
64
|
+
await (0, Local_1.touch)(to);
|
|
65
|
+
log_1.default.log(`start downloading ${from.path} -> ${to}`);
|
|
66
|
+
try {
|
|
67
|
+
await fs.get(from.path, to);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
this.onError(error);
|
|
71
|
+
}
|
|
72
|
+
log_1.default.log(`end downloading ${from.path}`);
|
|
73
|
+
this.sendState(from.size);
|
|
74
|
+
};
|
|
75
|
+
this.processing = this.queue$.subscribe(async ({ from, to, action }) => {
|
|
76
|
+
let a = action ?? this.action;
|
|
77
|
+
const existing = (0, Local_1.stat)(to);
|
|
78
|
+
if (existing) {
|
|
79
|
+
if (a) {
|
|
80
|
+
if (a.type == types_1.QueueActionType.Skip) {
|
|
81
|
+
this.sendState(from.size);
|
|
82
|
+
return this.next();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
this.putOnHold(from, existing);
|
|
87
|
+
return this.next();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const [fs, close] = await Connection_1.default.transmit(this.connId);
|
|
91
|
+
existing ?
|
|
92
|
+
this.applyAction(a, from, existing, transmit.bind(this, fs)).then(close) :
|
|
93
|
+
transmit(fs, from, to).then(close);
|
|
94
|
+
this.next();
|
|
95
|
+
});
|
|
96
|
+
this.next();
|
|
97
|
+
}
|
|
98
|
+
async upload(src, dest) {
|
|
99
|
+
const conn = Connection_1.default.get(this.connId);
|
|
100
|
+
const to = (0, URI_1.parseURI)(dest)['path'];
|
|
101
|
+
await this.enqueue(src, to, path => Promise.resolve((0, Local_1.list)(path)));
|
|
102
|
+
this.touched.add(to);
|
|
103
|
+
const transmit = async (fs, from, to) => {
|
|
104
|
+
if (!((0, Local_1.stat)(from.path))) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
log_1.default.log(`start uploading ${from.path} -> ${to}`);
|
|
108
|
+
try {
|
|
109
|
+
const dir = (0, node_path_1.dirname)(to);
|
|
110
|
+
if (!this.touched.has(dir)) {
|
|
111
|
+
await fs.mkdir(dir);
|
|
112
|
+
}
|
|
113
|
+
await fs.put(from.path, to);
|
|
114
|
+
this.touched.add(dir);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
this.onError(error);
|
|
118
|
+
}
|
|
119
|
+
log_1.default.log(`end uploading ${from.path}`);
|
|
120
|
+
this.sendState(from.size);
|
|
121
|
+
};
|
|
122
|
+
const ls = (0, ramda_1.memoizeWith)(ramda_1.identity, async (path) => {
|
|
123
|
+
try {
|
|
124
|
+
return await conn.ls(path);
|
|
125
|
+
}
|
|
126
|
+
catch (e) { }
|
|
127
|
+
return [];
|
|
128
|
+
});
|
|
129
|
+
const exists = async (path) => (await ls((0, node_path_1.dirname)(path))).find((0, ramda_1.whereEq)({ path }));
|
|
130
|
+
this.processing = this.queue$.subscribe(async ({ from, to, action }) => {
|
|
131
|
+
let a = action ?? this.action;
|
|
132
|
+
const existing = await exists(to);
|
|
133
|
+
if (existing) {
|
|
134
|
+
if (a) {
|
|
135
|
+
if (a.type == types_1.QueueActionType.Skip) {
|
|
136
|
+
this.sendState(from.size);
|
|
137
|
+
return this.next();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
this.putOnHold(from, existing);
|
|
142
|
+
return this.next();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const [fs, close] = await Connection_1.default.transmit(this.connId);
|
|
146
|
+
existing ?
|
|
147
|
+
this.applyAction(a, from, existing, transmit.bind(this, fs)).then(close) :
|
|
148
|
+
transmit(fs, from, to).then(close);
|
|
149
|
+
this.next();
|
|
150
|
+
});
|
|
151
|
+
this.next();
|
|
152
|
+
}
|
|
153
|
+
async remove(paths) {
|
|
154
|
+
this.totalCnt = paths.length;
|
|
155
|
+
const touched = new Map();
|
|
156
|
+
paths.forEach(async (path) => {
|
|
157
|
+
const dir = (0, node_path_1.dirname)(path);
|
|
158
|
+
const [conn, close] = await Connection_1.default.transmit(this.connId);
|
|
159
|
+
if (!touched.has(dir)) {
|
|
160
|
+
try {
|
|
161
|
+
touched.set(dir, await conn.ls(dir));
|
|
162
|
+
}
|
|
163
|
+
catch (e) {
|
|
164
|
+
touched.set(dir, null);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const name = (0, node_path_1.basename)(path);
|
|
168
|
+
const file = touched.get(dir)?.find(f => f.name == name);
|
|
169
|
+
if (file) {
|
|
170
|
+
try {
|
|
171
|
+
await conn.rm(path, file.dir);
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
this.onError({
|
|
175
|
+
type: types_1.FailureType.RemoteError,
|
|
176
|
+
id: this.connId,
|
|
177
|
+
error
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
close();
|
|
182
|
+
this.sendState(0);
|
|
183
|
+
if (this.doneCnt == this.totalCnt) {
|
|
184
|
+
this.onComplete();
|
|
185
|
+
touched.forEach((files, dir) => {
|
|
186
|
+
this.watcher.refresh((0, URI_1.createURI)(this.connId, dir));
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
next() {
|
|
192
|
+
if (this.queue.length) {
|
|
193
|
+
this.queue$.next(this.queue.shift());
|
|
194
|
+
}
|
|
195
|
+
else if (!this.pending.length) {
|
|
196
|
+
this.close();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
async enqueue(paths, dest, ls) {
|
|
200
|
+
const add = async (path, to) => {
|
|
201
|
+
const from = (await ls((0, node_path_1.dirname)(path))).find((0, ramda_1.whereEq)({ path }));
|
|
202
|
+
from && (from.dir ?
|
|
203
|
+
(await ls(path)).forEach(async (f) => await add(f.path, (0, node_path_1.join)(to, (0, node_path_1.basename)(path)))) :
|
|
204
|
+
this.queue.push({ from, to: (0, node_path_1.join)(to, (0, node_path_1.basename)(path)) }));
|
|
205
|
+
};
|
|
206
|
+
for (const path of paths) {
|
|
207
|
+
await add(path, dest);
|
|
208
|
+
}
|
|
209
|
+
this.queue.forEach(({ from: { size } }) => { this.totalCnt++; this.totalSize += size; });
|
|
210
|
+
}
|
|
211
|
+
applyAction(action, from, to, transmit) {
|
|
212
|
+
switch (action.type) {
|
|
213
|
+
case types_1.QueueActionType.Replace:
|
|
214
|
+
return transmit(from, to.path);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
putOnHold(src, dest) {
|
|
218
|
+
this.pending.push({ src, dest });
|
|
219
|
+
if (this.pending.length == 1) {
|
|
220
|
+
this.onConflict(src, dest);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
sendState(size) {
|
|
224
|
+
this.doneCnt++;
|
|
225
|
+
this.doneSize += size;
|
|
226
|
+
this.onState({
|
|
227
|
+
totalCnt: this.totalCnt,
|
|
228
|
+
doneCnt: this.doneCnt,
|
|
229
|
+
totalSize: this.totalSize,
|
|
230
|
+
doneSize: this.doneSize,
|
|
231
|
+
pending: this.pending.length
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
exports.default = Queue;
|
|
236
|
+
exports.queues = new Map();
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
7
|
+
const ReferenceCountMap_1 = __importDefault(require("./utils/ReferenceCountMap"));
|
|
8
|
+
const Connection_1 = __importDefault(require("./Connection"));
|
|
9
|
+
const URI_1 = require("./utils/URI");
|
|
10
|
+
class RemoteWatcher {
|
|
11
|
+
constructor(listener, onMissing, transform = (files) => files) {
|
|
12
|
+
this.listener = listener;
|
|
13
|
+
this.onMissing = onMissing;
|
|
14
|
+
this.transform = transform;
|
|
15
|
+
this.watched = new ReferenceCountMap_1.default;
|
|
16
|
+
}
|
|
17
|
+
watch(uri) {
|
|
18
|
+
this.watched.inc(uri) || this.watched.set(uri, false);
|
|
19
|
+
this.refresh(uri);
|
|
20
|
+
}
|
|
21
|
+
unwatch(uri) {
|
|
22
|
+
this.watched.dec(uri);
|
|
23
|
+
}
|
|
24
|
+
refresh(uri) {
|
|
25
|
+
if (this.watched.has(uri)) {
|
|
26
|
+
this.list(uri);
|
|
27
|
+
Array.from(this.watched.keys()).forEach(dir => {
|
|
28
|
+
if (dir.startsWith(uri + node_path_1.sep)) {
|
|
29
|
+
this.list(dir);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
list(uri) {
|
|
35
|
+
const { id, path } = (0, URI_1.parseURI)(uri);
|
|
36
|
+
Connection_1.default.list(id, path)
|
|
37
|
+
.then(files => this.listener(uri, this.transform(files)))
|
|
38
|
+
.catch(e => {
|
|
39
|
+
this.watched.del(uri);
|
|
40
|
+
this.onMissing(uri);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.default = RemoteWatcher;
|
package/dist/Session.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class Session {
|
|
4
|
+
static create() {
|
|
5
|
+
const sid = crypto.randomUUID();
|
|
6
|
+
this.sessions.set(sid, {});
|
|
7
|
+
return sid;
|
|
8
|
+
}
|
|
9
|
+
static remove(sid) {
|
|
10
|
+
this.sessions.delete(sid);
|
|
11
|
+
}
|
|
12
|
+
static get(sid) {
|
|
13
|
+
return this.sessions.get(sid);
|
|
14
|
+
}
|
|
15
|
+
static set(sid, settings) {
|
|
16
|
+
const s = this.sessions.get(sid);
|
|
17
|
+
s && this.sessions.set(sid, Object.assign(s, settings));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
Session.sessions = new Map();
|
|
21
|
+
exports.default = Session;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = default_1;
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
const types_1 = require("../types");
|
|
9
|
+
const URI_1 = require("../utils/URI");
|
|
10
|
+
const Connection_1 = __importDefault(require("../Connection"));
|
|
11
|
+
const App_1 = __importDefault(require("../App"));
|
|
12
|
+
async function default_1(file, force) {
|
|
13
|
+
if (!force) {
|
|
14
|
+
App_1.default.onError({ type: types_1.FailureType.ConfirmClear, file });
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const { id, path } = (0, URI_1.parseURI)(file);
|
|
18
|
+
await Connection_1.default.get(id).write(path, '');
|
|
19
|
+
if (id != types_1.LocalFileSystemID) {
|
|
20
|
+
App_1.default.remoteWatcher.refresh((0, URI_1.createURI)(id, (0, node_path_1.dirname)(path)));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.explorerSettings = explorerSettings;
|
|
7
|
+
exports.default = default_1;
|
|
8
|
+
const node_fs_1 = require("node:fs");
|
|
9
|
+
const path_1 = require("path");
|
|
10
|
+
const types_1 = require("../types");
|
|
11
|
+
const Local_1 = require("../fs/Local");
|
|
12
|
+
const URI_1 = require("../utils/URI");
|
|
13
|
+
const Connection_1 = __importDefault(require("../Connection"));
|
|
14
|
+
const Password_1 = __importDefault(require("../Password"));
|
|
15
|
+
const Session_1 = __importDefault(require("../Session"));
|
|
16
|
+
const ramda_1 = require("ramda");
|
|
17
|
+
function explorerSettings(attributes, config) {
|
|
18
|
+
return {
|
|
19
|
+
columns: config ? [
|
|
20
|
+
...config.columns
|
|
21
|
+
.map(({ name, width }) => {
|
|
22
|
+
const attribute = attributes.find((0, ramda_1.whereEq)({ name }));
|
|
23
|
+
return attribute ? { ...attribute, visible: true, width } : null;
|
|
24
|
+
})
|
|
25
|
+
.filter(ramda_1.isNotNil),
|
|
26
|
+
...attributes
|
|
27
|
+
.filter(({ name }) => !config.columns.find(c => name == c.name))
|
|
28
|
+
.map(a => ({ ...a, visible: false, width: 300 }))
|
|
29
|
+
] : attributes.map(a => ({ ...a, visible: true, width: 300 })),
|
|
30
|
+
...({
|
|
31
|
+
sort: config?.sort ?? ['name', types_1.SortOrder.Asc],
|
|
32
|
+
history: config?.history ?? [],
|
|
33
|
+
filter: config?.filter ?? null
|
|
34
|
+
})
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
async function default_1(file, onError) {
|
|
38
|
+
const stat = (0, node_fs_1.statSync)(file);
|
|
39
|
+
if (!stat.isFile() && !stat.isSymbolicLink()) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
let config;
|
|
43
|
+
try {
|
|
44
|
+
config = JSON.parse((0, node_fs_1.readFileSync)(file).toString());
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
throw new Error(`Invalid connection file ${file}`);
|
|
48
|
+
}
|
|
49
|
+
if (!(0, ramda_1.where)({
|
|
50
|
+
scheme: ramda_1.isNotEmpty,
|
|
51
|
+
user: ramda_1.isNotEmpty,
|
|
52
|
+
host: ramda_1.isNotEmpty,
|
|
53
|
+
port: ramda_1.isNotEmpty
|
|
54
|
+
}, config)) {
|
|
55
|
+
throw new Error(`Invalid connection file ${file}`);
|
|
56
|
+
}
|
|
57
|
+
const id = (0, URI_1.connectionID)(config.scheme, config.user, config.host, config.port);
|
|
58
|
+
try {
|
|
59
|
+
await Password_1.default.get(id);
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
const attributes = await Connection_1.default.open(config.scheme, config.user, config.host, config.port);
|
|
66
|
+
const pwd = await Connection_1.default.get(id).pwd();
|
|
67
|
+
const settings = {
|
|
68
|
+
name: (0, path_1.parse)(file).name,
|
|
69
|
+
attributes,
|
|
70
|
+
pwd,
|
|
71
|
+
theme: config.theme ?? 'black',
|
|
72
|
+
local: explorerSettings(Local_1.ATTRIBUTES, config.local),
|
|
73
|
+
remote: explorerSettings(attributes, config.remote),
|
|
74
|
+
path: {
|
|
75
|
+
local: config.path?.local,
|
|
76
|
+
remote: config.path?.remote ?? pwd
|
|
77
|
+
},
|
|
78
|
+
sync: config.sync ?? null
|
|
79
|
+
};
|
|
80
|
+
return { id, sid: Session_1.default.create(), settings };
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
Password_1.default.delete(id, false);
|
|
84
|
+
onError(id, e);
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = default_1;
|
|
7
|
+
const URI_1 = require("../utils/URI");
|
|
8
|
+
const types_1 = require("../types");
|
|
9
|
+
const Queue_1 = require("../queues/Queue");
|
|
10
|
+
const Session_1 = __importDefault(require("../Session"));
|
|
11
|
+
const Copy_1 = __importDefault(require("../queues/Copy"));
|
|
12
|
+
const Download_1 = __importDefault(require("../queues/Download"));
|
|
13
|
+
const Upload_1 = __importDefault(require("../queues/Upload"));
|
|
14
|
+
const uniqid_1 = __importDefault(require("../utils/uniqid"));
|
|
15
|
+
const App_1 = __importDefault(require("../App"));
|
|
16
|
+
const ramda_1 = require("ramda");
|
|
17
|
+
function default_1(src, dest, move, filter, sid, onComplete = () => { }) {
|
|
18
|
+
if (!src.length) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const { id: fromId } = (0, URI_1.parseURI)(src[0]);
|
|
22
|
+
const { id: toId, path: toPath } = (0, URI_1.parseURI)(dest);
|
|
23
|
+
const from = src.map((0, ramda_1.pipe)(URI_1.parseURI, (0, ramda_1.prop)('path')));
|
|
24
|
+
const id = (0, uniqid_1.default)();
|
|
25
|
+
let queueType;
|
|
26
|
+
let connection;
|
|
27
|
+
let queue;
|
|
28
|
+
const onConflict = (from, to) => {
|
|
29
|
+
if (sid) {
|
|
30
|
+
const action = Session_1.default.get(sid)?.action;
|
|
31
|
+
if (action) {
|
|
32
|
+
Queue_1.queues.get(id)?.resolve(action, true);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Ask, queueType, from, to, sid });
|
|
37
|
+
};
|
|
38
|
+
const onFinish = () => {
|
|
39
|
+
Queue_1.queues.delete(id);
|
|
40
|
+
App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Complete });
|
|
41
|
+
onComplete();
|
|
42
|
+
};
|
|
43
|
+
if (fromId == toId) {
|
|
44
|
+
queueType = move ? types_1.QueueType.Move : types_1.QueueType.Copy;
|
|
45
|
+
connection = fromId;
|
|
46
|
+
queue = new Copy_1.default(connection, from, toPath, filter, state => App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Update, state }), onConflict.bind(queue), error => {
|
|
47
|
+
App_1.default.onError({
|
|
48
|
+
type: types_1.FailureType.RemoteError,
|
|
49
|
+
id: fromId,
|
|
50
|
+
message: error.message ?? String(error)
|
|
51
|
+
});
|
|
52
|
+
}, onFinish, App_1.default.remoteWatcher, move);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
queueType = (0, URI_1.isLocal)(dest) ? types_1.QueueType.Download : types_1.QueueType.Upload;
|
|
56
|
+
connection = queueType == types_1.QueueType.Download ? fromId : toId;
|
|
57
|
+
queue = queueType == types_1.QueueType.Download ?
|
|
58
|
+
new Download_1.default(connection, from, toPath, filter, state => App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Update, state }), onConflict.bind(queue), error => App_1.default.onError(error), onFinish) :
|
|
59
|
+
new Upload_1.default(connection, from, toPath, filter, state => App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Update, state }), onConflict.bind(queue), error => App_1.default.onError(error), onFinish, App_1.default.remoteWatcher);
|
|
60
|
+
}
|
|
61
|
+
Queue_1.queues.set(id, queue);
|
|
62
|
+
App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Create, queueType, connection });
|
|
63
|
+
queue.create();
|
|
64
|
+
return id;
|
|
65
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = default_1;
|
|
7
|
+
const Session_1 = __importDefault(require("../Session"));
|
|
8
|
+
const Connection_1 = __importDefault(require("../Connection"));
|
|
9
|
+
function default_1(id, sid) {
|
|
10
|
+
Session_1.default.remove(sid);
|
|
11
|
+
Connection_1.default.close(id);
|
|
12
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = default_1;
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
const URI_1 = require("../utils/URI");
|
|
9
|
+
const types_1 = require("../types");
|
|
10
|
+
const Queue_1 = require("../queues/Queue");
|
|
11
|
+
const Duplicate_1 = __importDefault(require("../queues/Duplicate"));
|
|
12
|
+
const uniqid_1 = __importDefault(require("../utils/uniqid"));
|
|
13
|
+
const App_1 = __importDefault(require("../App"));
|
|
14
|
+
function default_1(src, filter) {
|
|
15
|
+
if (!src.length) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const { id: connection } = (0, URI_1.parseURI)(src[0]);
|
|
19
|
+
const targets = new Map();
|
|
20
|
+
src.forEach(uri => {
|
|
21
|
+
const { path } = (0, URI_1.parseURI)(uri);
|
|
22
|
+
const parent = (0, node_path_1.dirname)(path);
|
|
23
|
+
if (!targets.has(parent)) {
|
|
24
|
+
targets.set(parent, []);
|
|
25
|
+
}
|
|
26
|
+
targets.get(parent).push(path);
|
|
27
|
+
});
|
|
28
|
+
for (const [to, from] of targets) {
|
|
29
|
+
const id = (0, uniqid_1.default)();
|
|
30
|
+
const queue = new Duplicate_1.default(connection, from, to, filter, state => App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Update, state }), (from, to) => App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Ask, queueType: types_1.QueueType.Copy, from, to }), error => {
|
|
31
|
+
App_1.default.onError({
|
|
32
|
+
type: types_1.FailureType.RemoteError,
|
|
33
|
+
id: connection,
|
|
34
|
+
message: error.message ?? String(error)
|
|
35
|
+
});
|
|
36
|
+
}, () => {
|
|
37
|
+
Queue_1.queues.delete(id);
|
|
38
|
+
App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Complete });
|
|
39
|
+
}, App_1.default.remoteWatcher);
|
|
40
|
+
Queue_1.queues.set(id, queue);
|
|
41
|
+
App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Create, queueType: types_1.QueueType.Copy, connection });
|
|
42
|
+
queue.create();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = default_1;
|
|
7
|
+
const Local_1 = require("../Local");
|
|
8
|
+
const Password_1 = __importDefault(require("../Password"));
|
|
9
|
+
const URI_1 = require("../utils/URI");
|
|
10
|
+
async function default_1(path) {
|
|
11
|
+
if (!(0, Local_1.stat)(path)) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
const config = JSON.parse(await (0, Local_1.read)(path));
|
|
15
|
+
config.password = await Password_1.default.get((0, URI_1.connectionID)(config.scheme, config.user, config.host, config.port), true);
|
|
16
|
+
return config;
|
|
17
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.commands = void 0;
|
|
7
|
+
const connect_1 = __importDefault(require("./connect"));
|
|
8
|
+
const disconnect_1 = __importDefault(require("./disconnect"));
|
|
9
|
+
const watch_1 = __importDefault(require("./watch"));
|
|
10
|
+
const unwatch_1 = __importDefault(require("./unwatch"));
|
|
11
|
+
const copy_1 = __importDefault(require("./copy"));
|
|
12
|
+
const remove_1 = __importDefault(require("./remove"));
|
|
13
|
+
const clear_1 = __importDefault(require("./clear"));
|
|
14
|
+
const mkdir_1 = __importDefault(require("./mkdir"));
|
|
15
|
+
const read_1 = __importDefault(require("./read"));
|
|
16
|
+
const write_1 = __importDefault(require("./write"));
|
|
17
|
+
const settings_1 = __importDefault(require("./settings"));
|
|
18
|
+
const rename_1 = __importDefault(require("./rename"));
|
|
19
|
+
const getConnection_1 = __importDefault(require("./getConnection"));
|
|
20
|
+
const saveConnection_1 = __importDefault(require("./saveConnection"));
|
|
21
|
+
const saveSettings_1 = __importDefault(require("./saveSettings"));
|
|
22
|
+
const duplicate_1 = __importDefault(require("./duplicate"));
|
|
23
|
+
const resolve_1 = __importDefault(require("./resolve"));
|
|
24
|
+
exports.commands = {
|
|
25
|
+
connect: connect_1.default,
|
|
26
|
+
disconnect: disconnect_1.default,
|
|
27
|
+
getSettings: settings_1.default,
|
|
28
|
+
watch: watch_1.default,
|
|
29
|
+
unwatch: unwatch_1.default,
|
|
30
|
+
copy: copy_1.default,
|
|
31
|
+
duplicate: duplicate_1.default,
|
|
32
|
+
remove: remove_1.default,
|
|
33
|
+
clear: clear_1.default,
|
|
34
|
+
mkdir: mkdir_1.default,
|
|
35
|
+
read: read_1.default,
|
|
36
|
+
write: write_1.default,
|
|
37
|
+
rename: rename_1.default,
|
|
38
|
+
getConnection: getConnection_1.default,
|
|
39
|
+
saveConnection: saveConnection_1.default,
|
|
40
|
+
saveSettings: saveSettings_1.default,
|
|
41
|
+
resolve: resolve_1.default
|
|
42
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = default_1;
|
|
7
|
+
const types_1 = require("../types");
|
|
8
|
+
const promises_1 = require("node:fs/promises");
|
|
9
|
+
const Connection_1 = __importDefault(require("../Connection"));
|
|
10
|
+
const URI_1 = require("../utils/URI");
|
|
11
|
+
const node_path_1 = require("node:path");
|
|
12
|
+
const path_1 = require("../utils/path");
|
|
13
|
+
const App_1 = __importDefault(require("../App"));
|
|
14
|
+
async function default_1(name, parent) {
|
|
15
|
+
let { id, path } = (0, URI_1.parseURI)(parent);
|
|
16
|
+
try {
|
|
17
|
+
if (id == types_1.LocalFileSystemID) {
|
|
18
|
+
await (0, promises_1.mkdir)((0, node_path_1.join)(path, name), { recursive: true });
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
const parts = (0, path_1.split)(name);
|
|
22
|
+
const conn = Connection_1.default.get(id);
|
|
23
|
+
for (let i = 0; i < parts.length; i++) {
|
|
24
|
+
path = (0, node_path_1.join)(path, parts[i]);
|
|
25
|
+
try {
|
|
26
|
+
await conn.mkdir(path);
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
if (i == parts.length - 1) {
|
|
30
|
+
throw e;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
App_1.default.onError({ type: types_1.FailureType.RemoteError, id, message: 'message' in error ? error.message : String(error) });
|
|
38
|
+
}
|
|
39
|
+
if (!(0, URI_1.isLocal)(parent)) {
|
|
40
|
+
App_1.default.remoteWatcher.refresh(parent);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = default_1;
|
|
4
|
+
const Local_1 = require("../Local");
|
|
5
|
+
const URI_1 = require("../utils/URI");
|
|
6
|
+
async function default_1(file) {
|
|
7
|
+
const { id, path } = (0, URI_1.parseURI)(file);
|
|
8
|
+
if ((0, URI_1.isLocal)(file)) {
|
|
9
|
+
return (0, Local_1.read)(path);
|
|
10
|
+
}
|
|
11
|
+
// TODO
|
|
12
|
+
return '';
|
|
13
|
+
}
|