filefive 2.0.2 → 3.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 (103) hide show
  1. package/README.md +8 -0
  2. package/dist/App.js +9 -11
  3. package/dist/Connection.js +13 -12
  4. package/dist/FileWatcher.js +1 -1
  5. package/dist/Local.js +11 -5
  6. package/dist/LocalWatcher.js +5 -2
  7. package/dist/Password.js +2 -2
  8. package/dist/Queue.js +12 -7
  9. package/dist/RemoteFiles.js +7 -2
  10. package/dist/commands/clear.js +5 -1
  11. package/dist/commands/connect.js +16 -6
  12. package/dist/commands/copy.js +3 -3
  13. package/dist/commands/disconnect.js +2 -0
  14. package/dist/commands/duplicate.js +1 -1
  15. package/dist/commands/mkdir.js +10 -3
  16. package/dist/commands/remove.js +1 -1
  17. package/dist/commands/rename.js +1 -1
  18. package/dist/commands/saveConnection.js +3 -0
  19. package/dist/commands/write.js +1 -1
  20. package/dist/events.js +10 -0
  21. package/dist/fs/S3.js +8 -7
  22. package/dist/fs/SFtp.js +5 -3
  23. package/dist/index.js +6 -5
  24. package/dist/log.js +5 -2
  25. package/dist/plugins/mirror/commands.js +185 -0
  26. package/dist/plugins/mirror/sessions.js +26 -0
  27. package/dist/plugins/mirror/watchers.js +4 -0
  28. package/dist/public/assets/android-chrome-144x144.png +0 -0
  29. package/dist/public/assets/android-chrome-192x192.png +0 -0
  30. package/dist/public/assets/android-chrome-256x256.png +0 -0
  31. package/dist/public/assets/android-chrome-36x36.png +0 -0
  32. package/dist/public/assets/android-chrome-384x384.png +0 -0
  33. package/dist/public/assets/android-chrome-48x48.png +0 -0
  34. package/dist/public/assets/android-chrome-512x512.png +0 -0
  35. package/dist/public/assets/android-chrome-72x72.png +0 -0
  36. package/dist/public/assets/android-chrome-96x96.png +0 -0
  37. package/dist/public/assets/apple-touch-icon-1024x1024.png +0 -0
  38. package/dist/public/assets/apple-touch-icon-114x114.png +0 -0
  39. package/dist/public/assets/apple-touch-icon-120x120.png +0 -0
  40. package/dist/public/assets/apple-touch-icon-144x144.png +0 -0
  41. package/dist/public/assets/apple-touch-icon-152x152.png +0 -0
  42. package/dist/public/assets/apple-touch-icon-167x167.png +0 -0
  43. package/dist/public/assets/apple-touch-icon-180x180.png +0 -0
  44. package/dist/public/assets/apple-touch-icon-57x57.png +0 -0
  45. package/dist/public/assets/apple-touch-icon-60x60.png +0 -0
  46. package/dist/public/assets/apple-touch-icon-72x72.png +0 -0
  47. package/dist/public/assets/apple-touch-icon-76x76.png +0 -0
  48. package/dist/public/assets/apple-touch-icon-precomposed.png +0 -0
  49. package/dist/public/assets/apple-touch-icon.png +0 -0
  50. package/dist/public/assets/apple-touch-startup-image-1125x2436.png +0 -0
  51. package/dist/public/assets/apple-touch-startup-image-1136x640.png +0 -0
  52. package/dist/public/assets/apple-touch-startup-image-1170x2532.png +0 -0
  53. package/dist/public/assets/apple-touch-startup-image-1179x2556.png +0 -0
  54. package/dist/public/assets/apple-touch-startup-image-1242x2208.png +0 -0
  55. package/dist/public/assets/apple-touch-startup-image-1242x2688.png +0 -0
  56. package/dist/public/assets/apple-touch-startup-image-1284x2778.png +0 -0
  57. package/dist/public/assets/apple-touch-startup-image-1290x2796.png +0 -0
  58. package/dist/public/assets/apple-touch-startup-image-1334x750.png +0 -0
  59. package/dist/public/assets/apple-touch-startup-image-1488x2266.png +0 -0
  60. package/dist/public/assets/apple-touch-startup-image-1536x2048.png +0 -0
  61. package/dist/public/assets/apple-touch-startup-image-1620x2160.png +0 -0
  62. package/dist/public/assets/apple-touch-startup-image-1640x2160.png +0 -0
  63. package/dist/public/assets/apple-touch-startup-image-1668x2224.png +0 -0
  64. package/dist/public/assets/apple-touch-startup-image-1668x2388.png +0 -0
  65. package/dist/public/assets/apple-touch-startup-image-1792x828.png +0 -0
  66. package/dist/public/assets/apple-touch-startup-image-2048x1536.png +0 -0
  67. package/dist/public/assets/apple-touch-startup-image-2048x2732.png +0 -0
  68. package/dist/public/assets/apple-touch-startup-image-2160x1620.png +0 -0
  69. package/dist/public/assets/apple-touch-startup-image-2160x1640.png +0 -0
  70. package/dist/public/assets/apple-touch-startup-image-2208x1242.png +0 -0
  71. package/dist/public/assets/apple-touch-startup-image-2224x1668.png +0 -0
  72. package/dist/public/assets/apple-touch-startup-image-2266x1488.png +0 -0
  73. package/dist/public/assets/apple-touch-startup-image-2388x1668.png +0 -0
  74. package/dist/public/assets/apple-touch-startup-image-2436x1125.png +0 -0
  75. package/dist/public/assets/apple-touch-startup-image-2532x1170.png +0 -0
  76. package/dist/public/assets/apple-touch-startup-image-2556x1179.png +0 -0
  77. package/dist/public/assets/apple-touch-startup-image-2688x1242.png +0 -0
  78. package/dist/public/assets/apple-touch-startup-image-2732x2048.png +0 -0
  79. package/dist/public/assets/apple-touch-startup-image-2778x1284.png +0 -0
  80. package/dist/public/assets/apple-touch-startup-image-2796x1290.png +0 -0
  81. package/dist/public/assets/apple-touch-startup-image-640x1136.png +0 -0
  82. package/dist/public/assets/apple-touch-startup-image-750x1334.png +0 -0
  83. package/dist/public/assets/apple-touch-startup-image-828x1792.png +0 -0
  84. package/dist/public/assets/favicon-16x16.png +0 -0
  85. package/dist/public/assets/favicon-32x32.png +0 -0
  86. package/dist/public/assets/favicon-48x48.png +0 -0
  87. package/dist/public/assets/mstile-144x144.png +0 -0
  88. package/dist/public/assets/mstile-150x150.png +0 -0
  89. package/dist/public/assets/mstile-310x150.png +0 -0
  90. package/dist/public/assets/mstile-310x310.png +0 -0
  91. package/dist/public/assets/mstile-70x70.png +0 -0
  92. package/dist/public/assets/yandex-browser-50x50.png +0 -0
  93. package/dist/public/index.js +2 -1
  94. package/dist/public/index.js.map +1 -0
  95. package/dist/queues/Duplicate.js +1 -1
  96. package/dist/queues/Queue.js +12 -14
  97. package/dist/queues/Remove.js +3 -1
  98. package/dist/transformers/git.js +54 -28
  99. package/dist/types.js +9 -1
  100. package/dist/utils/ReferenceCountMap.js +3 -3
  101. package/dist/utils/URI.js +5 -3
  102. package/dist/utils/filter.js +31 -0
  103. package/package.json +22 -19
package/dist/log.js CHANGED
@@ -29,7 +29,7 @@ class LogFS extends FileSystem_1.FileSystem {
29
29
  }
30
30
  catch (e) {
31
31
  let msg = `Could not connect to ${this.id}`;
32
- if ('message' in e) {
32
+ if (e && typeof e == 'object' && 'message' in e) {
33
33
  msg += ': ' + e.message;
34
34
  }
35
35
  logger.error(await (0, exports.err)(msg));
@@ -129,7 +129,10 @@ class LogFS extends FileSystem_1.FileSystem {
129
129
  return await this.fs.cp(from, to, recursive);
130
130
  }
131
131
  catch (e) {
132
- logger.error(await (0, exports.err)(e.message));
132
+ const message = String((e && typeof e === 'object' && 'message' in e)
133
+ ? e.message
134
+ : e);
135
+ logger.error(await (0, exports.err)(message));
133
136
  throw e;
134
137
  }
135
138
  }
@@ -0,0 +1,185 @@
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.FileType = void 0;
7
+ exports.mirror = mirror;
8
+ exports.unmirror = unmirror;
9
+ const posix_1 = require("node:path/posix");
10
+ const node_fs_1 = require("node:fs");
11
+ const types_1 = require("../../types");
12
+ const Local_1 = require("../../Local");
13
+ const URI_1 = require("../../utils/URI");
14
+ const watchers_1 = __importDefault(require("./watchers"));
15
+ const Upload_1 = __importDefault(require("../../queues/Upload"));
16
+ const Remove_1 = __importDefault(require("../../queues/Remove"));
17
+ const mkdir_1 = __importDefault(require("../../commands/mkdir"));
18
+ const sessions_1 = __importDefault(require("./sessions"));
19
+ const filter_1 = require("../../utils/filter");
20
+ const git_1 = require("../../transformers/git");
21
+ var FileType;
22
+ (function (FileType) {
23
+ FileType[FileType["File"] = 0] = "File";
24
+ FileType[FileType["Directory"] = 1] = "Directory";
25
+ FileType[FileType["NonExistent"] = 2] = "NonExistent";
26
+ FileType[FileType["Unsupported"] = 3] = "Unsupported";
27
+ })(FileType || (exports.FileType = FileType = {}));
28
+ const operations = new Map();
29
+ const pending = new Set();
30
+ const touched = new Map();
31
+ const repos = new Map();
32
+ let counter = 0;
33
+ function mirror(localRoot, remote, sid, recursive, del, filter, watcher, onChange) {
34
+ const { id: connectionID, path: destPath } = (0, URI_1.parseURI)(remote);
35
+ const id = "" + ++counter;
36
+ touched.set(id, new Set());
37
+ onChange({
38
+ type: types_1.MirrorEventType.Create,
39
+ id,
40
+ sid,
41
+ setting: { local: localRoot, remote, recursive, del, filter }
42
+ });
43
+ const matchesName = filter ? (0, filter_1.buildFilterPredicate)(filter) : () => true;
44
+ watchers_1.default.set(id, (0, Local_1.watch)(localRoot, (event, file) => {
45
+ if (!file) {
46
+ return;
47
+ }
48
+ file = (0, Local_1.unosify)(file);
49
+ if (isInsideGitDir(file)) {
50
+ return;
51
+ }
52
+ const localPath = (0, posix_1.join)(localRoot, file);
53
+ if (filter && !matchesName((0, posix_1.basename)(file))) {
54
+ return;
55
+ }
56
+ const operationId = localPath + ':' + remote;
57
+ if (touch(id, operationId)) {
58
+ onChange({ type: types_1.MirrorEventType.Syncing, id });
59
+ }
60
+ const timeout = operations.get(operationId);
61
+ if (timeout === true) { // operation is in process
62
+ pending.add(operationId);
63
+ }
64
+ else {
65
+ clearTimeout(timeout);
66
+ operations.set(operationId, setTimeout(async () => {
67
+ operations.set(operationId, true);
68
+ do {
69
+ pending.delete(operationId);
70
+ await process(localRoot, localPath, file, connectionID, destPath, recursive, del, filter, watcher);
71
+ } while (pending.has(operationId));
72
+ operations.delete(operationId);
73
+ untouch(operationId, onChange);
74
+ }, 1000));
75
+ }
76
+ }, e => {
77
+ console.log('Sync error', e);
78
+ }, { recursive }));
79
+ sessions_1.default.set(sid, [...sessions_1.default.get(sid) ?? [], id]);
80
+ return id;
81
+ }
82
+ function unmirror(id) {
83
+ watchers_1.default.get(id)?.();
84
+ watchers_1.default.delete(id);
85
+ }
86
+ async function process(root, src, relativePath, connId, dest, recursive, del, filter, watcher) {
87
+ const type = fileType(src);
88
+ if (type == FileType.Unsupported) {
89
+ return;
90
+ }
91
+ if (filter?.ignored === true &&
92
+ await isInRepo(root) &&
93
+ await isIgnored(src)) {
94
+ return;
95
+ }
96
+ if (filter?.uncommited === true &&
97
+ await isInRepo(root) &&
98
+ !await isUncommited(root, src)) {
99
+ return;
100
+ }
101
+ if (type == FileType.File) {
102
+ return new Promise((resolve, reject) => {
103
+ const q = new Upload_1.default(connId, [src], dest, undefined, root, () => { }, () => q.resolve({ type: types_1.QueueActionType.Replace }, true), reject, () => resolve(), watcher);
104
+ q.create();
105
+ });
106
+ }
107
+ else if (type == FileType.Directory) {
108
+ if (recursive) {
109
+ if (!filter || filter?.folders === true) {
110
+ return (0, mkdir_1.default)(relativePath, (0, URI_1.createURI)(connId, dest));
111
+ }
112
+ }
113
+ }
114
+ else if (type == FileType.NonExistent) {
115
+ if (del) {
116
+ return new Promise((resolve, reject) => {
117
+ (new Remove_1.default(connId, [(0, posix_1.join)(dest, relativePath)], () => { }, reject, () => resolve(), watcher)).create();
118
+ });
119
+ }
120
+ }
121
+ }
122
+ function fileType(path) {
123
+ try {
124
+ const stat = (0, node_fs_1.statSync)((0, Local_1.osify)(path));
125
+ if (stat.isFile()) {
126
+ return FileType.File;
127
+ }
128
+ if (stat.isDirectory()) {
129
+ return FileType.Directory;
130
+ }
131
+ }
132
+ catch (err) {
133
+ return FileType.NonExistent;
134
+ }
135
+ return FileType.Unsupported;
136
+ }
137
+ function touch(mirrorId, operationId) {
138
+ const m = touched.get(mirrorId);
139
+ if (m) {
140
+ m.add(operationId);
141
+ return m.size == 1;
142
+ }
143
+ return false;
144
+ }
145
+ function untouch(operationId, onChange) {
146
+ for (const [id, items] of touched.entries()) {
147
+ if (items.delete(operationId) && !items.size) {
148
+ onChange({ type: types_1.MirrorEventType.Complete, id });
149
+ }
150
+ }
151
+ }
152
+ function isInsideGitDir(path) {
153
+ return path
154
+ .split('/')
155
+ .includes('.git');
156
+ }
157
+ async function isInRepo(path) {
158
+ const repoRoot = repos.get(path);
159
+ if (repoRoot !== undefined) {
160
+ return repoRoot != false;
161
+ }
162
+ try {
163
+ const root = await (0, git_1.getRoot)(path);
164
+ repos.set(path, root);
165
+ return true;
166
+ }
167
+ catch (e) { }
168
+ repos.set(path, false);
169
+ return false;
170
+ }
171
+ async function isUncommited(root, file) {
172
+ const repoRoot = repos.get(root);
173
+ if (!repoRoot) {
174
+ return false;
175
+ }
176
+ const statuses = await (0, git_1.getStatuses)((0, posix_1.dirname)(file), repoRoot);
177
+ return statuses.find(([path, status]) => path == file && status.match('[MAD]')) != undefined;
178
+ }
179
+ async function isIgnored(path) {
180
+ const ignored = await (0, git_1.getIgnoredList)((0, posix_1.dirname)(path));
181
+ if (!ignored) {
182
+ return true;
183
+ }
184
+ return ignored.includes(path);
185
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const events_1 = require("../../events");
4
+ const commands_1 = require("./commands");
5
+ const index_1 = require("../../index");
6
+ const sessions = new Map();
7
+ exports.default = sessions;
8
+ events_1.event$.subscribe(e => {
9
+ if (e.type == events_1.SystemEventType.Disconnect) {
10
+ (sessions.get(e.sid) ?? []).forEach(id => (0, commands_1.unmirror)(id));
11
+ sessions.delete(e.sid);
12
+ }
13
+ else if (e.type == events_1.SystemEventType.Connect) {
14
+ if (e.settings && Array.isArray(e.settings.mirrors)) {
15
+ setTimeout(() => {
16
+ e.settings.mirrors.forEach(mirror => {
17
+ fetch(`http://localhost:${index_1.inputOptions.port}/api/mirror`, {
18
+ method: 'POST',
19
+ headers: { "Content-Type": "application/json" },
20
+ body: JSON.stringify({ ...mirror, sid: e.sid })
21
+ });
22
+ });
23
+ }, 1000);
24
+ }
25
+ }
26
+ });
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const watchers = new Map();
4
+ exports.default = watchers;
Binary file