hfs 0.57.26 → 0.57.27-beta2

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 (71) hide show
  1. package/admin/assets/{index-CHMhmNYS.js → index-DSkhXlWX.js} +103 -103
  2. package/admin/assets/{sha512-Dsv49IAs.js → sha512-CoddZKeD.js} +1 -1
  3. package/admin/index.html +1 -1
  4. package/frontend/assets/{index-legacy-BI8icwFp.js → index-legacy-C4Gclsbz.js} +4 -4
  5. package/frontend/assets/{sha512-legacy-D82alHBq.js → sha512-legacy-C-FMk44u.js} +1 -1
  6. package/frontend/index.html +1 -1
  7. package/package.json +4 -3
  8. package/src/QuickZipStream.js +11 -8
  9. package/src/SendList.js +10 -8
  10. package/src/ThrottledStream.js +8 -6
  11. package/src/acme.js +5 -7
  12. package/src/adminApis.js +6 -7
  13. package/src/api.accounts.js +4 -6
  14. package/src/api.auth.js +7 -11
  15. package/src/api.get_file_list.js +11 -16
  16. package/src/api.lang.js +1 -1
  17. package/src/api.monitor.js +2 -3
  18. package/src/api.net.js +1 -2
  19. package/src/api.plugins.js +8 -10
  20. package/src/api.vfs.js +14 -19
  21. package/src/apiMiddleware.js +4 -4
  22. package/src/auth.js +6 -9
  23. package/src/basicWeb.js +1 -2
  24. package/src/block.js +1 -1
  25. package/src/commands.js +9 -9
  26. package/src/comments.js +4 -5
  27. package/src/config.js +8 -9
  28. package/src/connections.js +11 -6
  29. package/src/consoleLog.js +6 -6
  30. package/src/const.js +4 -4
  31. package/src/cross.js +19 -21
  32. package/src/customHtml.js +3 -4
  33. package/src/ddns.js +4 -4
  34. package/src/debounceAsync.js +3 -3
  35. package/src/errorPages.js +2 -3
  36. package/src/events.js +7 -10
  37. package/src/fileAttr.js +6 -6
  38. package/src/first.js +13 -8
  39. package/src/frontEndApis.js +5 -5
  40. package/src/geo.js +3 -5
  41. package/src/github.js +14 -17
  42. package/src/i18n.js +3 -4
  43. package/src/icons.js +1 -1
  44. package/src/index.js +2 -3
  45. package/src/lang.js +5 -6
  46. package/src/listen.js +25 -28
  47. package/src/log.js +18 -17
  48. package/src/middlewares.js +12 -15
  49. package/src/misc.js +9 -11
  50. package/src/nat.js +14 -16
  51. package/src/outboundProxy.js +7 -7
  52. package/src/perm.js +7 -12
  53. package/src/persistence.js +1 -1
  54. package/src/plugins.js +62 -73
  55. package/src/roots.js +1 -2
  56. package/src/selfCheck.js +5 -4
  57. package/src/serveFile.js +6 -7
  58. package/src/serveGuiAndSharedFiles.js +7 -9
  59. package/src/serveGuiFiles.js +11 -20
  60. package/src/stat.js +40 -0
  61. package/src/statWorker.js +11 -0
  62. package/src/throttler.js +5 -7
  63. package/src/update.js +7 -7
  64. package/src/upload.js +11 -13
  65. package/src/util-files.js +42 -32
  66. package/src/util-http.js +80 -29
  67. package/src/util-os.js +2 -4
  68. package/src/vfs.js +77 -68
  69. package/src/walkDir.js +9 -9
  70. package/src/watchLoad.js +4 -4
  71. package/src/zip.js +5 -6
package/src/vfs.js CHANGED
@@ -56,7 +56,6 @@ function permsFromParent(parent, child) {
56
56
  return lodash_1.default.isEmpty(ret) ? undefined : ret;
57
57
  }
58
58
  function inheritFromParent(child) {
59
- var _a, _b, _c;
60
59
  const { parent } = child;
61
60
  if (!parent)
62
61
  return;
@@ -64,11 +63,11 @@ function inheritFromParent(child) {
64
63
  if (typeof parent.mime === 'object' && typeof child.mime === 'object')
65
64
  lodash_1.default.defaults(child.mime, parent.mime);
66
65
  else if (parent.mime)
67
- (_a = child.mime) !== null && _a !== void 0 ? _a : (child.mime = parent.mime);
66
+ child.mime ??= parent.mime;
68
67
  if (parent.accept)
69
- (_b = child.accept) !== null && _b !== void 0 ? _b : (child.accept = parent.accept);
68
+ child.accept ??= parent.accept;
70
69
  if (parent.default)
71
- (_c = child.default) !== null && _c !== void 0 ? _c : (child.default = parent.default);
70
+ child.default ??= parent.default;
72
71
  return child;
73
72
  }
74
73
  function isSameFilenameAs(name) {
@@ -79,15 +78,14 @@ function normalizeFilename(x) {
79
78
  return (const_1.IS_WINDOWS || const_1.IS_MAC ? x.toLocaleLowerCase() : x).normalize();
80
79
  }
81
80
  async function applyParentToChild(child, parent, name) {
82
- var _a, _b;
83
81
  const ret = {
84
82
  original: child, // this can be overridden by passing an 'original' in `child`
85
83
  ...child,
86
- isFolder: (_a = child === null || child === void 0 ? void 0 : child.isFolder) !== null && _a !== void 0 ? _a : (((_b = child === null || child === void 0 ? void 0 : child.children) === null || _b === void 0 ? void 0 : _b.length) > 0 || undefined), // isFolder is hidden in original node, so we must copy it explicitly
84
+ isFolder: child?.isFolder ?? (child?.children?.length > 0 || undefined), // isFolder is hidden in original node, so we must copy it explicitly
87
85
  isTemp: true,
88
86
  parent,
89
87
  };
90
- name || (name = child ? getNodeName(child) : '');
88
+ name ||= child ? getNodeName(child) : '';
91
89
  inheritMasks(ret, parent, name);
92
90
  await parentMaskApplier(parent)(ret, name);
93
91
  inheritFromParent(ret);
@@ -105,15 +103,12 @@ async function urlToNode(url, ctx, parent = exports.vfs, getRest) {
105
103
  const ret = await getNodeByName(name, parent);
106
104
  if (!ret)
107
105
  return;
108
- if (rest || (ret === null || ret === void 0 ? void 0 : ret.original))
106
+ if (rest || ret?.original)
109
107
  return urlToNode(rest, ctx, ret, getRest);
110
108
  if (ret.source)
111
- try {
112
- if (!showHiddenFiles.get() && await isHiddenFile(ret.source))
113
- throw 'hiddenFile';
114
- ret.isFolder = (await nodeStats(ret)).isDirectory(); // throws if it doesn't exist on disk
115
- }
116
- catch (_a) {
109
+ if (!showHiddenFiles.get() && await isHiddenFile(ret.source))
110
+ throw 'hiddenFile';
111
+ else if (await setIsFolder(ret) === undefined) { // undefined = not found on disk
117
112
  if (!getRest)
118
113
  return;
119
114
  const rest = ret.source.slice(parent.source.length); // parent has source, otherwise !ret.source || ret.original
@@ -122,23 +117,24 @@ async function urlToNode(url, ctx, parent = exports.vfs, getRest) {
122
117
  }
123
118
  return ret;
124
119
  }
125
- async function nodeStats(ret) {
126
- if (ret.stats)
127
- return ret.stats;
128
- const stats = ret.source ? await (0, misc_1.statWithTimeout)(ret.source) : undefined;
129
- (0, misc_1.setHidden)(ret, { stats });
120
+ async function nodeStats(node) {
121
+ if (node.stats || !node.source)
122
+ return node.stats;
123
+ const stats = (0, misc_1.statWithTimeout)(node.source).catch(() => {
124
+ (0, misc_1.setHidden)(node, { stats: null }); // don't cache rejected promises
125
+ });
126
+ (0, misc_1.setHidden)(node, { stats });
130
127
  return stats;
131
128
  }
132
129
  async function isHiddenFile(path) {
133
- return const_1.IS_WINDOWS ? new Promise(res => fswin_1.default.getAttributes(path, x => res(x === null || x === void 0 ? void 0 : x.IS_HIDDEN)))
130
+ return const_1.IS_WINDOWS ? new Promise(res => fswin_1.default.getAttributes(path, x => res(x?.IS_HIDDEN)))
134
131
  : path[path.lastIndexOf('/') + 1] === '.';
135
132
  }
136
133
  async function getNodeByName(name, parent) {
137
- var _a;
138
134
  // does the tree node have a child that goes by this name, otherwise attempt disk
139
- const child = ((_a = parent.children) === null || _a === void 0 ? void 0 : _a.find(isSameFilenameAs(name))) || childFromDisk();
135
+ const child = parent.children?.find(isSameFilenameAs(name)) || await childFromDisk();
140
136
  return child && applyParentToChild(child, parent, name);
141
- function childFromDisk() {
137
+ async function childFromDisk() {
142
138
  if (!parent.source)
143
139
  return;
144
140
  const ret = {};
@@ -155,18 +151,26 @@ async function getNodeByName(name, parent) {
155
151
  return;
156
152
  ret.source = (0, path_1.join)(parent.source, onDisk);
157
153
  ret.original = undefined; // this will overwrite the 'original' set in applyParentToChild, so we know this is not part of the vfs
154
+ await setIsFolder(ret);
158
155
  return ret;
159
156
  }
160
157
  }
158
+ async function setIsFolder(node) {
159
+ if (!node.source)
160
+ return;
161
+ const isFolder = /[\\/]$/.test(node.source) || await nodeStats(node).then(x => x?.isDirectory(), () => undefined);
162
+ (0, misc_1.setHidden)(node, { isFolder });
163
+ return isFolder;
164
+ }
161
165
  exports.vfs = {};
162
- (0, config_1.defineConfig)('vfs', exports.vfs).sub(reviewVfs);
166
+ (0, config_1.defineConfig)('vfs', exports.vfs).sub(async (x) => {
167
+ await reviewVfs(x);
168
+ console.log('VFS ready');
169
+ });
163
170
  async function reviewVfs(data = exports.vfs) {
164
171
  await (async function recur(node) {
165
- var _a, _b;
166
- if (node.source && !((_a = node.children) === null || _a === void 0 ? void 0 : _a.length) && node.isFolder === undefined) {
167
- const isFolder = /[\\/]$/.test(node.source) || ((_b = (await nodeStats(node).catch(() => { }))) === null || _b === void 0 ? void 0 : _b.isDirectory());
168
- (0, misc_1.setHidden)(node, { isFolder });
169
- }
172
+ if (node.source && !node.children?.length && node.isFolder === undefined)
173
+ await setIsFolder(node);
170
174
  if (node.children)
171
175
  await Promise.allSettled(node.children.map(recur));
172
176
  })(data);
@@ -198,9 +202,18 @@ function getNodeName(node) {
198
202
  return source.slice(source.lastIndexOf('\\') + 1);
199
203
  return base;
200
204
  }
205
+ // this is sync
201
206
  function nodeIsFolder(node) {
202
- var _a, _b, _c, _d;
203
- return (_c = (_a = node.isFolder) !== null && _a !== void 0 ? _a : (_b = node.original) === null || _b === void 0 ? void 0 : _b.isFolder) !== null && _c !== void 0 ? _c : (!nodeIsLink(node) && (((_d = node.children) === null || _d === void 0 ? void 0 : _d.length) > 0 || !node.source));
207
+ return node.isFolder ?? node.original?.isFolder
208
+ ?? (nodeIsLink(node) ? false : (node.children?.length > 0 || !node.source || reconsider()));
209
+ function reconsider() {
210
+ // a networked source may be offline at startup, and become online later: recalculate in the background
211
+ nodeStats(node).then(s => {
212
+ if (s)
213
+ (0, misc_1.setHidden)(node.original || node, { isFolder: s.isDirectory() });
214
+ }, () => { });
215
+ return undefined;
216
+ }
204
217
  }
205
218
  async function hasDefaultFile(node, ctx) {
206
219
  return node.default && nodeIsFolder(node) && await urlToNode(node.default, ctx, node) || undefined;
@@ -219,7 +232,6 @@ function statusCodeForMissingPerm(node, perm, ctx, assign = true) {
219
232
  }
220
233
  return ret;
221
234
  function getCode() {
222
- var _a;
223
235
  if ((isRoot(node) || node.original) && perm === 'can_delete' // we currently don't allow deleting of vfs nodes from frontend
224
236
  || !node.source && perm === 'can_upload') // Upload possible only if we know where to store. First check node.source because is supposedly faster.
225
237
  return const_1.HTTP_FORBIDDEN;
@@ -231,11 +243,11 @@ function statusCodeForMissingPerm(node, perm, ctx, assign = true) {
231
243
  who = node[cur];
232
244
  if ((0, misc_1.isWhoObject)(who))
233
245
  who = who.this;
234
- who !== null && who !== void 0 ? who : (who = misc_1.defaultPerms[cur]);
246
+ who ??= misc_1.defaultPerms[cur];
235
247
  if (typeof who !== 'string' || who === misc_1.WHO_ANY_ACCOUNT)
236
248
  break;
237
249
  if (!max--) {
238
- console.error(`endless loop in permission ${perm}=${(_a = node[perm]) !== null && _a !== void 0 ? _a : misc_1.defaultPerms[perm]} for ${node.url || getNodeName(node)}`);
250
+ console.error(`endless loop in permission ${perm}=${node[perm] ?? misc_1.defaultPerms[perm]} for ${node.url || getNodeName(node)}`);
239
251
  return misc_1.HTTP_SERVER_ERROR;
240
252
  }
241
253
  cur = who;
@@ -259,37 +271,35 @@ async function* walkNode(parent, { ctx, depth = Infinity, prefixPath = '', requi
259
271
  const stream = new node_stream_1.Readable({
260
272
  objectMode: true,
261
273
  async read() {
262
- var _a;
263
274
  if (started)
264
275
  return; // for simplicity, we care about starting, and never suspend
265
276
  started = true;
266
- const { children, source } = parent;
277
+ const { source } = parent;
267
278
  const taken = prefixPath ? undefined : new Set();
268
279
  const maskApplier = parentMaskApplier(parent);
269
280
  const visitLater = [];
270
- if (children)
271
- for (const child of children) {
272
- const nodeName = getNodeName(child);
273
- const name = prefixPath + nodeName;
274
- taken === null || taken === void 0 ? void 0 : taken.add(normalizeFilename(name));
275
- const item = { ...child, original: child, name, parent };
276
- if (await cantSee(item))
277
- continue;
278
- if (item.source && !((_a = item.children) === null || _a === void 0 ? void 0 : _a.length)) // real items must be accessible, unless there's more to it
279
- try {
280
- await promises_1.default.access(item.source);
281
- }
282
- catch (_b) {
283
- continue;
284
- }
285
- const isFolder = nodeIsFolder(child);
286
- if (onlyFiles ? !isFolder : (!onlyFolders || isFolder))
287
- stream.push(item);
288
- if (!depth || !isFolder || cantRecur(item))
289
- continue;
290
- inheritMasks(item, parent);
291
- visitLater.push([item, name]); // prioritize siblings
292
- }
281
+ const childrenWorking = parent.children?.length && Promise.all(parent.children.map(async (child) => {
282
+ const nodeName = getNodeName(child);
283
+ const name = prefixPath + nodeName;
284
+ taken?.add(normalizeFilename(name));
285
+ const item = { ...child, original: child, name, parent };
286
+ if (await cantSee(item))
287
+ return;
288
+ if (item.source && !item.children?.length) // real items must be accessible, unless there's more to it
289
+ try {
290
+ await promises_1.default.access(item.source);
291
+ }
292
+ catch {
293
+ return;
294
+ }
295
+ const isFolder = nodeIsFolder(child);
296
+ if (onlyFiles ? !isFolder : (!onlyFolders || isFolder))
297
+ stream.push(item);
298
+ if (!depth || !isFolder || cantRecur(item))
299
+ return;
300
+ inheritMasks(item, parent);
301
+ visitLater.push([item, name]); // prioritize siblings
302
+ }));
293
303
  try {
294
304
  if (!source)
295
305
  return;
@@ -299,23 +309,22 @@ async function* walkNode(parent, { ctx, depth = Infinity, prefixPath = '', requi
299
309
  return;
300
310
  try {
301
311
  await (0, walkDir_1.walkDir)(source, { depth, ctx, hidden: showHiddenFiles.get(), parallelizeRecursion }, async (entry) => {
302
- var _a;
303
- if (ctx === null || ctx === void 0 ? void 0 : ctx.isAborted()) {
312
+ if (ctx?.isAborted()) {
304
313
  stream.push(null);
305
314
  return null;
306
315
  }
307
316
  if ((0, comments_1.usingDescriptIon)() && entry.name === comments_1.DESCRIPT_ION)
308
317
  return;
309
- const { path } = entry;
318
+ const { path } = entry; // this path is not the original deprecated property: we are overwriting/reusing it
310
319
  const isFolder = entry.isDirectory();
311
- let renamed = (_a = parent.rename) === null || _a === void 0 ? void 0 : _a[path];
320
+ let renamed = parent.rename?.[path];
312
321
  if (renamed) {
313
322
  const dir = (0, path_1.dirname)(path); // if `path` isn't just the name, copy its dir in renamed
314
323
  if (dir !== '.')
315
324
  renamed = dir + '/' + renamed;
316
325
  }
317
326
  const name = prefixPath + (renamed || path);
318
- if (taken === null || taken === void 0 ? void 0 : taken.has(normalizeFilename(name))) // taken by vfs node above
327
+ if (taken?.has(normalizeFilename(name))) // taken by vfs node above
319
328
  return false; // false just in case it's a folder
320
329
  const item = { name, isFolder, source: (0, path_1.join)(source, path), parent };
321
330
  if (await cantSee(item)) // can't see: don't produce and don't recur
@@ -331,6 +340,7 @@ async function* walkNode(parent, { ctx, depth = Infinity, prefixPath = '', requi
331
340
  }
332
341
  }
333
342
  finally {
343
+ await childrenWorking;
334
344
  for (const [item, name] of visitLater)
335
345
  for await (const x of walkNode(item, { depth: depth - 1, prefixPath: name + '/', ctx, requiredPerm, onlyFolders, parallelizeRecursion }))
336
346
  stream.push(x);
@@ -379,13 +389,13 @@ function parentMaskApplier(parent) {
379
389
  let isFolder = undefined;
380
390
  for (const { matcher, mods, mustBeFolder } of matchers) {
381
391
  if (mustBeFolder !== undefined) {
382
- isFolder !== null && isFolder !== void 0 ? isFolder : (isFolder = nodeIsFolder(item));
392
+ isFolder ??= nodeIsFolder(item);
383
393
  if (mustBeFolder !== isFolder)
384
394
  continue;
385
395
  }
386
396
  if (!matcher(virtualBasename))
387
397
  continue;
388
- item.masks && (item.masks = lodash_1.default.merge(lodash_1.default.cloneDeep(mods.masks), item.masks)); // item.masks must take precedence
398
+ item.masks &&= lodash_1.default.merge(lodash_1.default.cloneDeep(mods.masks), item.masks); // item.masks must take precedence
389
399
  lodash_1.default.defaults(item, mods);
390
400
  }
391
401
  };
@@ -421,12 +431,11 @@ function renameUnderPath(rename, path) {
421
431
  events_1.default.on('accountRenamed', ({ from, to }) => {
422
432
  ;
423
433
  (function renameInNode(n) {
424
- var _a;
425
434
  for (const k of misc_1.PERM_KEYS)
426
435
  renameInPerm(n[k]);
427
436
  if (n.masks)
428
437
  Object.values(n.masks).forEach(renameInNode);
429
- (_a = n.children) === null || _a === void 0 ? void 0 : _a.forEach(renameInNode);
438
+ n.children?.forEach(renameInNode);
430
439
  })(exports.vfs);
431
440
  (0, exports.saveVfs)();
432
441
  function renameInPerm(a) {
package/src/walkDir.js CHANGED
@@ -25,20 +25,19 @@ function walkDir(path, { depth = 0, hidden = true, parallelizeRecursion = false,
25
25
  return reject(Error('ENOTDIR'));
26
26
  dirQ.add(() => readDir('', depth)
27
27
  .then(res => {
28
- Promise.resolve(res === null || res === void 0 ? void 0 : res.branchDone).then(resolve);
28
+ Promise.resolve(res?.branchDone).then(resolve);
29
29
  }, reject));
30
30
  });
31
31
  async function readDir(relativePath, depth) {
32
- var _a, _b;
33
32
  if (stopped)
34
33
  return;
35
34
  const base = (0, path_1.join)(path, relativePath);
36
35
  const subDirsDone = [];
37
36
  let n = 0;
38
37
  let last;
39
- const res = (_a = (await events_1.default.emitAsync('listDiskFolder', { path: base, ctx }))) === null || _a === void 0 ? void 0 : _a[0]; // consider only first result
38
+ const res = (await events_1.default.emitAsync('listDiskFolder', { path: base, ctx }))?.[0]; // consider only first result
40
39
  const pluginReceiver = lodash_1.default.isFunction(res) && res || null;
41
- const pluginIterator = lodash_1.default.isFunction((res === null || res === void 0 ? void 0 : res[Symbol.asyncIterator]) || (res === null || res === void 0 ? void 0 : res[Symbol.iterator])) && res;
40
+ const pluginIterator = lodash_1.default.isFunction(res?.[Symbol.asyncIterator] || res?.[Symbol.iterator]) && res;
42
41
  if (const_1.IS_WINDOWS && !pluginIterator) { // use native apis to read the 'hidden' attribute
43
42
  const direntMethods = {
44
43
  isDir: false,
@@ -67,7 +66,7 @@ function walkDir(path, { depth = 0, hidden = true, parallelizeRecursion = false,
67
66
  break;
68
67
  if (!hidden && entry.name[0] === '.' && !const_1.IS_WINDOWS)
69
68
  continue;
70
- const stats = ((_b = entry.isSymbolicLink) === null || _b === void 0 ? void 0 : _b.call(entry)) && await (0, util_files_1.statWithTimeout)((0, path_1.join)(base, entry.name)).catch(() => null);
69
+ const stats = entry.isSymbolicLink?.() && await (0, util_files_1.statWithTimeout)((0, path_1.join)(base, entry.name)).catch(() => null);
71
70
  if (stats === null)
72
71
  continue;
73
72
  if (stats)
@@ -77,7 +76,7 @@ function walkDir(path, { depth = 0, hidden = true, parallelizeRecursion = false,
77
76
  expanded.stats = stats;
78
77
  await work(expanded);
79
78
  }
80
- pluginReceiver === null || pluginReceiver === void 0 ? void 0 : pluginReceiver(!stopped);
79
+ pluginReceiver?.(!stopped);
81
80
  const branchDone = Promise.allSettled(subDirsDone);
82
81
  if (last) // using streams, we don't know when the entries are received, so we need to notify on last item
83
82
  last.closingBranch = branchDone.then(() => relativePath);
@@ -87,7 +86,7 @@ function walkDir(path, { depth = 0, hidden = true, parallelizeRecursion = false,
87
86
  return { branchDone, n };
88
87
  async function work(entry) {
89
88
  entry.path = (relativePath && relativePath + '/') + entry.name;
90
- pluginReceiver === null || pluginReceiver === void 0 ? void 0 : pluginReceiver(entry);
89
+ pluginReceiver?.(entry);
91
90
  if (last && closingQ.length) // pending entries
92
91
  last.closingBranch = Promise.resolve(closingQ.shift());
93
92
  last = entry;
@@ -104,9 +103,9 @@ function walkDir(path, { depth = 0, hidden = true, parallelizeRecursion = false,
104
103
  const job = () => readDir(entry.path, depth - 1) // recur
105
104
  .then(x => x, () => { }) // mute errors
106
105
  .then(res => {
107
- if (!(res === null || res === void 0 ? void 0 : res.n))
106
+ if (!res?.n)
108
107
  closingQ.push(entry.path); // no children to tell i'm done
109
- Promise.resolve(res === null || res === void 0 ? void 0 : res.branchDone).then(() => branchDone.resolve());
108
+ Promise.resolve(res?.branchDone).then(() => branchDone.resolve());
110
109
  });
111
110
  if (parallelizeRecursion)
112
111
  dirQ.add(job);
@@ -119,6 +118,7 @@ const kStats = Symbol('stats');
119
118
  // Adapting an internal class in Node.js to mimic the behavior of `Dirent` when creating it manually from `Stats`.
120
119
  // https://github.com/nodejs/node/blob/a4cf6b204f0b160480153dc293ae748bf15225f9/lib/internal/fs/utils.js#L199C1-L213
121
120
  class DirentFromStats extends node_fs_1.Dirent {
121
+ [kStats];
122
122
  constructor(name, stats) {
123
123
  // @ts-expect-error The constructor has parameters, but they are not represented in types.
124
124
  // https://github.com/nodejs/node/blob/a4cf6b204f0b160480153dc293ae748bf15225f9/lib/internal/fs/utils.js#L164
package/src/watchLoad.js CHANGED
@@ -37,13 +37,13 @@ function watchLoad(path, parser, { failedOnFirstAttempt, immediateFirst } = {})
37
37
  void debounced.flush();
38
38
  }
39
39
  catch (e) {
40
- retry = setTimeout(install, 3000); // manual watching until watch is successful
40
+ retry = setTimeout(install, 3_000); // manual watching until watch is successful
41
41
  if (first)
42
- failedOnFirstAttempt === null || failedOnFirstAttempt === void 0 ? void 0 : failedOnFirstAttempt();
42
+ failedOnFirstAttempt?.();
43
43
  }
44
44
  }
45
45
  function unwatch() {
46
- watcher === null || watcher === void 0 ? void 0 : watcher.close();
46
+ watcher?.close();
47
47
  clearTimeout(retry);
48
48
  watcher = undefined;
49
49
  }
@@ -52,7 +52,7 @@ function watchLoad(path, parser, { failedOnFirstAttempt, immediateFirst } = {})
52
52
  return;
53
53
  doing = true;
54
54
  try {
55
- const text = await (0, util_files_1.readFileBusy)(path).catch(e => {
55
+ const text = await (0, util_files_1.readFileWithBusyRetry)(path).catch(e => {
56
56
  if (e.code === 'EPERM')
57
57
  console.error("missing permissions on file", path); // warn user, who could be clueless about this problem
58
58
  return '';
package/src/zip.js CHANGED
@@ -14,14 +14,13 @@ const api_get_file_list_1 = require("./api.get_file_list");
14
14
  const comments_1 = require("./comments");
15
15
  // expects 'node' to have had permissions checked by caller
16
16
  async function zipStreamFromFolder(node, ctx) {
17
- var _a;
18
- const list = (_a = (0, misc_1.wantArray)(ctx.query.list)[0]) === null || _a === void 0 ? void 0 : _a.split('//'); // slash is the only char not allowed in file names both for windows and unix, but still we need to encode whole paths, so the only safe choice to separate the entries is the double slash
17
+ const list = (0, misc_1.wantArray)(ctx.query.list)[0]?.split('//'); // slash is the only char not allowed in file names both for windows and unix, but still we need to encode whole paths, so the only safe choice to separate the entries is the double slash
19
18
  if (!list && (0, vfs_1.statusCodeForMissingPerm)(node, 'can_archive', ctx))
20
19
  return;
21
20
  ctx.status = const_1.HTTP_OK;
22
21
  ctx.mime = 'zip';
23
22
  // ctx.query.list is undefined | string | string[]
24
- const name = (list === null || list === void 0 ? void 0 : list.length) === 1 ? (0, misc_1.safeDecodeURIComponent)((0, path_1.basename)(list[0])) : (0, vfs_1.getNodeName)(node);
23
+ const name = list?.length === 1 ? (0, misc_1.safeDecodeURIComponent)((0, path_1.basename)(list[0])) : (0, vfs_1.getNodeName)(node);
25
24
  (0, serveFile_1.forceDownload)(ctx, ((0, misc_1.isWindowsDrive)(name) ? name[0] : (name || 'archive')) + '.zip');
26
25
  const { filterName, filterComment } = (0, api_get_file_list_1.paramsToFilter)(ctx.query);
27
26
  const walker = !list ? (0, vfs_1.walkNode)(node, { ctx, requiredPerm: 'can_archive' })
@@ -61,7 +60,7 @@ async function zipStreamFromFolder(node, ctx) {
61
60
  return { path: name + '/' };
62
61
  if (!source)
63
62
  return;
64
- const st = el.stats || await (0, misc_1.statWithTimeout)(source);
63
+ const st = await (el.stats || (0, misc_1.statWithTimeout)(source));
65
64
  if (!st || !st.isFile())
66
65
  return;
67
66
  return {
@@ -73,7 +72,7 @@ async function zipStreamFromFolder(node, ctx) {
73
72
  getData: () => (0, fs_1.createReadStream)(source, { start: 0, end: Math.max(0, st.size - 1) })
74
73
  };
75
74
  }
76
- catch (_a) { }
75
+ catch { }
77
76
  });
78
77
  const zip = new QuickZipStream_1.QuickZipStream(mappedWalker);
79
78
  const time = 1000 * zipSeconds.get();
@@ -86,6 +85,6 @@ async function zipStreamFromFolder(node, ctx) {
86
85
  ctx.body = zip;
87
86
  ctx.req.on('close', () => zip.destroy());
88
87
  ctx.state.archive = 'zip';
89
- (0, serveFile_1.monitorAsDownload)(ctx, size, range === null || range === void 0 ? void 0 : range.start);
88
+ (0, serveFile_1.monitorAsDownload)(ctx, size, range?.start);
90
89
  }
91
90
  const zipSeconds = (0, config_1.defineConfig)('zip_calculate_size_for_seconds', 5);