report failing plugin for onDirEntry
Massimo Melina committed
May 9, 2026 at 17:30 UTC
ee281752da1858eaec4d9b241666cf028a716cb6
1 file changed
+11
-10
src/api.get_file_list.ts
+11
-10
@@ -1,12 +1,12 @@
1
// This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
3
import {
4
- applyParentToChild, getNodeName, hasDefaultFile, hasPermission, masksCouldGivePermission, nodeIsFolder,
4
+ applyParentToChild, getNodeName, hasDefaultFile, hasPermission, masksCouldGivePermission, nodeIsFolder, nodeStats,
5
statusCodeForMissingPerm, urlToNode, VfsNode, walkNode
6
} from './vfs'
7
import { ApiError, ApiHandler } from './apiMiddleware'
8
import { mapPlugins } from './plugins'
9
-import { apiAssertTypes, asyncGeneratorToArray, pattern2filter, statWithTimeout, WHO_NO_ONE } from './misc'
9
+import { apiAssertTypes, asyncGeneratorToArray, pattern2filter, WHO_NO_ONE } from './misc'
10
import { HTTP_METHOD_NOT_ALLOWED, HTTP_NOT_FOUND } from './const'
11
import Koa from 'koa'
12
import { getCommentFor, areCommentsEnabled } from './comments'
@@ -46,7 +46,7 @@ export const get_file_list: ApiHandler = async ({ uri='/', offset, limit, c, onl
46
limit = Number(limit)
47
const { filterName, filterComment, fileMask, depth } = paramsToFilter(rest)
48
const walker = walkNode(node, { ctx: admin ? undefined : ctx, onlyFolders, onlyFiles, depth })
49
- const onDirEntryHandlers = mapPlugins(plug => plug.onDirEntry)
49
+ const onDirEntryHandlers = mapPlugins((plug, id) => plug.onDirEntry && { id, cb: plug.onDirEntry })
50
const can_upload = admin || hasPermission(node, 'can_upload', ctx)
51
const can_delete = admin || hasPermission(node, 'can_delete', ctx)
52
const fakeChild = await applyParentToChild({ source: 'dummy-file', original: undefined }, node) // used to check permission; simple but can produce false results; 'original' to simulate a non-vfs node
@@ -87,15 +87,16 @@ export const get_file_list: ApiHandler = async ({ uri='/', offset, limit, c, onl
87
continue
88
const cbParams = { entry, ctx, listUri: uri, node: sub }
89
try {
90
- const res = await Promise.all(onDirEntryHandlers.map(cb => cb(cbParams)))
90
+ const res = await Promise.all(onDirEntryHandlers.map(({ id, cb }) =>
91
+ Promise.resolve().then(() => cb(cbParams)).catch(error => { throw { id, error } })))
92
if (res.some(x => x === false))
93
continue
93
- if ((await events.emitAsync('dirEntry', cbParams))?.isDefaultPrevented())
94
- continue
94
}
96
- catch(e) {
97
- console.warn("A plugin is causing problems on dirEntry:", e)
95
+ catch(e: any) {
96
+ console.warn(`Plugin ${e?.id || '?'} is causing problems on onDirEntry:`, e?.error ?? e)
97
}
98
+ if ((await events.emitAsync('dirEntry', cbParams))?.isDefaultPrevented())
99
+ continue
100
if (offset) {
101
--offset
102
continue
@@ -120,10 +121,10 @@ export const get_file_list: ApiHandler = async ({ uri='/', offset, limit, c, onl
121
const [web, comment, st] = await Promise.all([
122
hasDefaultFile(node, ctx).then(x => x ? true : undefined),
123
node.comment ?? getCommentFor(source),
123
- source ? (node.stats || statWithTimeout(source).catch(e => {
124
+ nodeStats(node).catch(e => {
125
if (!isFolder || !node.children?.length) // folders with virtual children, keep them
126
throw e
126
- })) : undefined
127
+ })
128
])
129
// permissions of entries are sent as a difference with permissions of parent
130
const pl = node.can_list === WHO_NO_ONE ? 'l'