filefive 2.0.1 → 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 +12 -4
  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
@@ -7,7 +7,7 @@ const Copy_1 = __importDefault(require("./Copy"));
7
7
  const types_1 = require("../types");
8
8
  class DuplicateQueue extends Copy_1.default {
9
9
  constructor(connId, src, dest, filter, onState, onConflict, onError, onComplete, watcher) {
10
- super(connId, src, dest, filter, null, onState, onConflict, onError, onComplete, watcher, false);
10
+ super(connId, src, dest, filter, undefined, onState, onConflict, onError, onComplete, watcher, false);
11
11
  this.newNames = new Map();
12
12
  this.resolve({ type: types_1.QueueActionType.Rename }, true);
13
13
  }
@@ -23,7 +23,7 @@ const lsRemote = (connId) => {
23
23
  const [conn, close] = await Connection_1.default.transmit(connId);
24
24
  conn.ls(path)
25
25
  .then(resove)
26
- .catch(() => resove(null))
26
+ .catch(() => resove([]))
27
27
  .finally(() => close());
28
28
  });
29
29
  cache.set(path, list);
@@ -90,10 +90,10 @@ class TransmitQueue {
90
90
  }
91
91
  async enqueue(paths, dest) {
92
92
  const ls = this.ls(this.from);
93
- let matchFilter = (file) => true;
93
+ let matchesFilter = (file) => true;
94
94
  if (this.filter) {
95
- const re = (0, filter_1.filterRegExp)(this.filter);
96
- matchFilter = (file) => {
95
+ const nameMatchesFilter = (0, filter_1.buildFilterPredicate)(this.filter);
96
+ matchesFilter = (file) => {
97
97
  if (this.filter.ignored === true && 'git_i' in file.attributes) {
98
98
  return false;
99
99
  }
@@ -104,11 +104,7 @@ class TransmitQueue {
104
104
  'git_c' in file.attributes)) {
105
105
  return false;
106
106
  }
107
- if (!re) {
108
- return true;
109
- }
110
- const found = re.exec(file.name);
111
- return this.filter?.invert ?? false ? found === null : found !== null;
107
+ return nameMatchesFilter(file.name);
112
108
  };
113
109
  }
114
110
  paths = paths.map(posix_1.normalize).filter(path => !paths.find(ancestor => path.startsWith(ancestor + posix_1.sep)));
@@ -120,10 +116,10 @@ class TransmitQueue {
120
116
  const from = (await ls(parent))?.find((0, ramda_1.whereEq)({ path }));
121
117
  if (from) {
122
118
  if (from.dir) {
123
- return Promise.all((await ls(from.path))?.map(child => add(child.path, to, [...dirs, (0, posix_1.basename)(path)])));
119
+ return Promise.all((await ls(from.path))?.map(child => add(child.path, to, [...dirs, (0, posix_1.basename)(path)])) ?? []);
124
120
  }
125
121
  else {
126
- if (matchFilter(from)) {
122
+ if (matchesFilter(from)) {
127
123
  this.queue.push({ from, to, dirs });
128
124
  this.totalCnt++;
129
125
  this.totalSize += from.size;
@@ -131,7 +127,9 @@ class TransmitQueue {
131
127
  }
132
128
  }
133
129
  };
134
- await Promise.all(paths.map(path => add(path, dest, this.fromRoot ? (0, posix_1.dirname)(path).substring(this.fromRoot.length + 1).split('/') : [])));
130
+ await Promise.all(paths.map(path => add(path, dest, this.fromRoot
131
+ ? (0, posix_1.dirname)(path).substring(this.fromRoot.length + 1).split('/')
132
+ : [])));
135
133
  }
136
134
  stop() {
137
135
  if (!this.stopped) {
@@ -197,7 +195,7 @@ class TransmitQueue {
197
195
  putOnHold(src, dirs, to, dest) {
198
196
  this.pending.push({ src, dirs, to, dest });
199
197
  if (this.pending.length == 1) {
200
- this.onConflict(src, dest);
198
+ setTimeout(() => this.onConflict(src, dest));
201
199
  }
202
200
  }
203
201
  ls(connId) {
@@ -214,7 +212,7 @@ class TransmitQueue {
214
212
  return (path) => Promise.resolve((0, Local_1.stat)(path));
215
213
  }
216
214
  const ls = this.ls(connId);
217
- return async (path) => (await ls((0, posix_1.dirname)(path)))?.find((0, ramda_1.whereEq)({ path }));
215
+ return async (path) => (await ls((0, posix_1.dirname)(path)))?.find((0, ramda_1.whereEq)({ path })) ?? null;
218
216
  }
219
217
  async rename(name, dir) {
220
218
  let { name: oldName, ext } = (0, posix_1.parse)(name);
@@ -19,7 +19,9 @@ class RemoveQueue {
19
19
  this.stopped = false;
20
20
  }
21
21
  async create() {
22
- const paths = this.paths.map(posix_1.normalize).filter(path => !this.paths.find(ancestor => path.startsWith(ancestor + posix_1.sep)));
22
+ const paths = this.paths
23
+ .map(posix_1.normalize)
24
+ .filter(path => !this.paths.find(ancestor => path.startsWith(ancestor + posix_1.sep)));
23
25
  let totalCnt = 0;
24
26
  let doneCnt = 0;
25
27
  const ls = (0, Queue_1.lsRemote)(this.connId);
@@ -1,27 +1,36 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = default_1;
4
+ exports.getRoot = getRoot;
5
+ exports.getStatuses = getStatuses;
6
+ exports.getIgnoredList = getIgnoredList;
4
7
  const node_util_1 = require("node:util");
5
8
  const node_child_process_1 = require("node:child_process");
6
9
  const posix_1 = require("node:path/posix");
7
10
  const types_1 = require("../types");
8
11
  const Local_1 = require("../Local");
9
12
  const ramda_1 = require("ramda");
13
+ const run = (0, node_util_1.promisify)(node_child_process_1.execFile);
10
14
  async function default_1(path, files) {
11
- const run = (0, node_util_1.promisify)(node_child_process_1.execFile);
12
15
  try {
13
- let { stdout: repoRoot } = await run('git', ['rev-parse', '--show-toplevel'], { cwd: (0, Local_1.osify)(path) });
14
- repoRoot = (0, Local_1.unosify)(repoRoot.trim());
15
- const { stdout: statuses } = await run('git', ['status', '-z', '.'], { cwd: (0, Local_1.osify)(path) });
16
- const [inRoot, inSubfolders] = (0, ramda_1.partition)(([p]) => (0, posix_1.dirname)(p) == path, (0, Local_1.unosify)(statuses)
17
- .replace(/\0$/, '')
18
- .split('\0')
19
- .map(s => [(0, posix_1.join)(repoRoot, s.substring(3)), s.substring(0, 2)])
20
- .map(([path, status]) => [path.replace(/\/$/, ''), status]));
16
+ const repoRoot = await getRoot(path);
17
+ const ignored = await getIgnoredList(path);
18
+ if (ignored === null) {
19
+ files.forEach(f => f[types_1.FileAttrsAttr][GitStatus.Ignored] = statusNames[GitStatus.Ignored]);
20
+ }
21
+ else {
22
+ ignored.forEach(path => {
23
+ const f = files.find(f => f.path == path);
24
+ f && (f[types_1.FileAttrsAttr][GitStatus.Ignored] = statusNames[GitStatus.Ignored]);
25
+ });
26
+ }
27
+ const [inRoot, inSubfolders] = (0, ramda_1.partition)(([p]) => (0, posix_1.dirname)(p) == path, await getStatuses(path, repoRoot));
21
28
  if (inSubfolders.length == 1 && inSubfolders[0][0] == path && inSubfolders[0][1].includes('?')) {
22
29
  files.forEach(f => {
23
- const status = f.dir ? GitStatus.Contains : GitStatus.Untracked;
24
- f[types_1.FileAttrsAttr][status] = statusNames[status];
30
+ if (!(GitStatus.Ignored in f[types_1.FileAttrsAttr])) {
31
+ const status = f.dir ? GitStatus.Contains : GitStatus.Untracked;
32
+ f[types_1.FileAttrsAttr][status] = statusNames[status];
33
+ }
25
34
  });
26
35
  }
27
36
  else {
@@ -33,33 +42,50 @@ async function default_1(path, files) {
33
42
  ].forEach(([path, status]) => {
34
43
  const f = files.find(f => f.path == path);
35
44
  if (f) {
36
- if (f.dir) {
37
- status = GitStatus.Contains;
45
+ if (!(GitStatus.Ignored in f[types_1.FileAttrsAttr])) {
46
+ if (f.dir) {
47
+ status = GitStatus.Contains;
48
+ }
49
+ f[types_1.FileAttrsAttr][status] = status ? (statusNames[status] ?? '') : '';
38
50
  }
39
- f[types_1.FileAttrsAttr][status] = status ? (statusNames[status] ?? '') : '';
40
51
  }
41
52
  });
42
53
  }
43
- const { stdout: ignored } = await run('git', ['ls-files', '--others', '--ignored', '--exclude-standard', '--directory', '-z'], { cwd: (0, Local_1.osify)(path) });
44
- if (ignored == './\0') {
45
- files.forEach(f => f[types_1.FileAttrsAttr][GitStatus.Ignored] = statusNames[GitStatus.Ignored]);
46
- }
47
- else {
48
- (0, Local_1.unosify)(ignored)
49
- .replace(/\0$/, '')
50
- .split('\0')
51
- .map(s => (0, posix_1.join)(path, s.replace(/\/$/, '')))
52
- .forEach(path => {
53
- const f = files.find(f => f.path == path);
54
- f && (f[types_1.FileAttrsAttr][GitStatus.Ignored] = statusNames[GitStatus.Ignored]);
55
- });
56
- }
57
54
  }
58
55
  catch {
59
56
  // either path is not in git repo or no git installed
60
57
  }
61
58
  return files;
62
59
  }
60
+ async function getRoot(path) {
61
+ const { stdout: repoRoot } = await run('git', ['rev-parse', '--show-toplevel'], { cwd: (0, Local_1.osify)(path) });
62
+ return (0, Local_1.unosify)(repoRoot.trim());
63
+ }
64
+ async function getStatuses(path, repoRoot) {
65
+ const { stdout: statuses } = await run('git', ['status', '-z', '.'], { cwd: (0, Local_1.osify)(path) });
66
+ return statuses.length
67
+ ? statuses
68
+ .replace(/\0$/, '')
69
+ .split('\0')
70
+ .map(s => [(0, posix_1.join)(repoRoot, s.substring(3)), s.substring(0, 2)])
71
+ .map(([path, status]) => [path.replace(/\/$/, ''), status])
72
+ : [];
73
+ }
74
+ async function getIgnoredList(path) {
75
+ try {
76
+ const { stdout: ignored } = await run('git', ['ls-files', '--others', '--ignored', '--exclude-standard', '--directory', '-z'], { cwd: (0, Local_1.osify)(path) });
77
+ if (ignored == './\0') {
78
+ return null;
79
+ }
80
+ return ignored
81
+ .replace(/\0$/, '')
82
+ .split('\0')
83
+ .map(s => (0, posix_1.join)(path, s.replace(/\/$/, '')));
84
+ }
85
+ catch (e) {
86
+ return null; // deep in ignored subfolders
87
+ }
88
+ }
63
89
  var GitStatus;
64
90
  (function (GitStatus) {
65
91
  GitStatus["Untracked"] = "git_u";
package/dist/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FailureType = exports.QueueActionType = exports.QueueEventType = exports.QueueType = exports.SortOrder = exports.FileAttrsAttr = exports.FileState = exports.FileStateAttr = exports.LocalFileSystemID = void 0;
3
+ exports.MirrorEventType = exports.FailureType = exports.QueueActionType = exports.QueueEventType = exports.QueueType = exports.SortOrder = exports.FileAttrsAttr = exports.FileState = exports.FileStateAttr = exports.LocalFileSystemID = void 0;
4
4
  exports.LocalFileSystemID = 'file://';
5
5
  exports.FileStateAttr = Symbol.for('state');
6
6
  var FileState;
@@ -45,4 +45,12 @@ var FailureType;
45
45
  FailureType["RemoteError"] = "remote-error";
46
46
  FailureType["APIError"] = "api-error";
47
47
  FailureType["Warning"] = "warning";
48
+ FailureType["Info"] = "info";
49
+ FailureType["UpdateAvailable"] = "update-available";
48
50
  })(FailureType || (exports.FailureType = FailureType = {}));
51
+ var MirrorEventType;
52
+ (function (MirrorEventType) {
53
+ MirrorEventType["Create"] = "create";
54
+ MirrorEventType["Syncing"] = "syncing";
55
+ MirrorEventType["Complete"] = "complete";
56
+ })(MirrorEventType || (exports.MirrorEventType = MirrorEventType = {}));
@@ -52,9 +52,9 @@ class default_1 {
52
52
  if (!this.entries.has(from)) {
53
53
  return;
54
54
  }
55
- this.entries.has(to) ?
56
- this.entries.get(to).count += this.entries.get(from).count :
57
- this.entries.set(to, this.entries.get(from));
55
+ this.entries.has(to)
56
+ ? this.entries.get(to).count += this.entries.get(from).count
57
+ : this.entries.set(to, this.entries.get(from));
58
58
  this.entries.delete(from);
59
59
  }
60
60
  }
package/dist/utils/URI.js CHANGED
@@ -24,7 +24,7 @@ function connectionID(scheme, user, host, port) {
24
24
  // https://jsdom.github.io/whatwg-url/#url=bmF0czovL2xvY2FsaG9zdDo0MjAwLw==&base=ZmlsZTovLy8=
25
25
  function parseURI(uri) {
26
26
  const { protocol, pathname, username, hostname, port: p } = new whatwg_url_1.URL(uri);
27
- const port = p ? parseInt(p) : defaultPort(protocol.slice(0, -1));
27
+ const port = p ? parseInt(p) : defaultPort(protocol.slice(0, -1)) ?? 0;
28
28
  return {
29
29
  id: connectionID(protocol.slice(0, -1), username, hostname, port),
30
30
  scheme: protocol.slice(0, -1),
@@ -36,6 +36,9 @@ function parseURI(uri) {
36
36
  }
37
37
  function createURI(id, path) {
38
38
  const u = (0, whatwg_url_1.parseURL)(id);
39
+ if (!u) {
40
+ throw new Error(`Invalid URL: ${id}`);
41
+ }
39
42
  u.path = path;
40
43
  if (!u.port) {
41
44
  u.port = defaultPort(u.scheme);
@@ -50,6 +53,5 @@ function defaultPort(protocol) {
50
53
  case 'http': return 80;
51
54
  case 'https': return 443;
52
55
  }
53
- console.error(`Default port for ${protocol} is not defined`);
54
- return null;
56
+ throw new Error(`Defaul port for protocol ${protocol} is not defined`);
55
57
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.filterRegExp = filterRegExp;
4
+ exports.buildFilterPredicate = buildFilterPredicate;
4
5
  function escapeRegExp(s) {
5
6
  let re = s.replace(/[/\-\\^$+.()|[\]{}]/g, '\\$&');
6
7
  re = re.replaceAll('*', '.*');
@@ -22,3 +23,33 @@ function filterRegExp(settings) {
22
23
  return null;
23
24
  }
24
25
  }
26
+ const tmpRe = new RegExp('^(?:' +
27
+ String.raw `.*~|` +
28
+ String.raw `.*\.(?:tmp|temp|bak|old|orig|save|swp|swo|swn|part|crdownload|download|dmp|core)|` +
29
+ String.raw `[._].*\.sw[a-z]|` +
30
+ String.raw `.*\.un~|` +
31
+ String.raw `\.#.*|` +
32
+ String.raw `#.*#|` +
33
+ String.raw `\.~.*#|` +
34
+ String.raw `\.goutputstream-.*|` +
35
+ String.raw `\._.*|\.DS_Store|\.Trashes|\.Spotlight-V100|\.fseventsd|\.TemporaryItems|\.DocumentRevisions-V100|Thumbs\.db|ehthumbs\.db|` +
36
+ String.raw `core(?:\..*)?` +
37
+ ')$');
38
+ function buildFilterPredicate(settings) {
39
+ const nameRe = filterRegExp(settings);
40
+ return (name) => {
41
+ if (settings.hidden
42
+ && name.startsWith('.')) {
43
+ return false;
44
+ }
45
+ if (settings.temporary
46
+ && tmpRe.test(name)) {
47
+ return false;
48
+ }
49
+ if (!nameRe) {
50
+ return true;
51
+ }
52
+ const matched = nameRe.test(name);
53
+ return settings.invert ? !matched : matched;
54
+ };
55
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "filefive",
3
3
  "description": "SFTP/FTP/Amazon S3 client and dual-panel file manager for macOS and Linux",
4
- "version": "2.0.1",
4
+ "version": "3.0.0",
5
5
  "license": "GPL-3.0",
6
6
  "author": "Max Miroshnikov",
7
7
  "bin": {
@@ -28,47 +28,50 @@
28
28
  "bin/"
29
29
  ],
30
30
  "scripts": {
31
- "dev": "NODE_ENV=development nodemon src/index.ts",
31
+ "dev": "NODE_ENV=development nodemon --exec tsx src/index.ts",
32
32
  "build": "./scripts/build.sh",
33
33
  "start": "node dist/index.js",
34
34
  "test": "jest tests",
35
35
  "lint": "eslint",
36
- "publish": "tsc -p . && npm publish"
36
+ "publish": "tsc -p . && npm publish",
37
+ "checkupdates": "npx npm-check-updates",
38
+ "up": "npx npm-check-updates -u && yarn install"
37
39
  },
38
40
  "dependencies": {
39
- "@aws-sdk/client-s3": "^3.1002.0",
40
- "chalk": "^5.6.2",
41
- "commander": "^14.0.3",
41
+ "@aws-sdk/client-s3": "^3.1100.0",
42
+ "chalk": "^6.0.0",
43
+ "commander": "^15.0.0",
42
44
  "express": "^5.2.1",
43
45
  "ftp": "^0.3.10",
44
- "multer": "^2.1.1",
46
+ "multer": "^2.2.0",
45
47
  "open": "^11.0.0",
48
+ "p-limit": "^7.3.2",
46
49
  "ramda": "^0.32.0",
47
50
  "rxjs": "^7.8.2",
48
51
  "ssh2": "^1.17.0",
49
52
  "trash": "^10.1.1",
50
- "whatwg-url": "^16.0.1",
51
- "ws": "^8.19.0"
53
+ "whatwg-url": "^17.1.0",
54
+ "ws": "^8.21.1"
52
55
  },
53
56
  "devDependencies": {
54
57
  "@eslint/js": "^10.0.1",
55
58
  "@types/express": "^5.0.6",
56
59
  "@types/ftp": "^0.3.36",
57
60
  "@types/jest": "^30.0.0",
58
- "@types/multer": "^2.0.0",
59
- "@types/node": "^25.3.3",
60
- "@types/ramda": "^0.31.1",
61
+ "@types/multer": "^2.2.0",
62
+ "@types/node": "^26.1.2",
63
+ "@types/ramda": "^0.32.0",
61
64
  "@types/ssh2": "^1.15.5",
62
65
  "@types/whatwg-url": "^13.0.0",
63
66
  "@types/ws": "^8.18.1",
64
- "dotenv": "^17.3.1",
65
- "eslint": "^10.0.2",
66
- "jest": "^30.2.0",
67
+ "dotenv": "^17.4.2",
68
+ "eslint": "^10.8.0",
69
+ "jest": "^30.4.2",
67
70
  "nodemon": "^3.1.14",
68
- "ts-jest": "^29.4.6",
69
- "ts-node": "^10.9.2",
70
- "typescript": "^5.9.3",
71
- "typescript-eslint": "^8.56.1"
71
+ "ts-jest": "^29.4.12",
72
+ "tsx": "^4.23.1",
73
+ "typescript": "^7.0.2",
74
+ "typescript-eslint": "^8.65.0"
72
75
  },
73
76
  "nodemonConfig": {
74
77
  "ignore": [