plugin.onDirEntry will let you mess with listing
Massimo Melina committed
Jan 12, 2022 at 16:10 UTC
5d9553835aae276974482afff346a35c183db589
2 files changed
+28
-4
src/api.file_list.ts
+11
-1
@@ -4,6 +4,7 @@ import createSSE from './sse'
4
import { basename } from 'path'
5
import { ApiError, ApiHandler } from './apis'
6
import { stat } from 'fs/promises'
7
+import { mapPlugins } from './plugins'
8
9
export const file_list:ApiHandler = async ({ path, offset, limit, search, omit, sse }, ctx) => {
10
let node = await vfs.urlToNode(path || '/', ctx)
@@ -19,6 +20,7 @@ export const file_list:ApiHandler = async ({ path, offset, limit, search, omit,
20
const match = (s?:string) => !s || !search || re.test(s)
21
const walker = walkNode(node, ctx, search ? Infinity : 0)
22
const sseSrv = sse ? createSSE(ctx) : null
23
+ const onDirEntryHandlers = mapPlugins(plug => plug.onDirEntry)
24
const res = produceEntries()
25
return !sseSrv && { list: await res }
26
@@ -32,6 +34,14 @@ export const file_list:ApiHandler = async ({ path, offset, limit, search, omit,
34
const entry = await nodeToDirEntry(sub)
35
if (!entry)
36
continue
37
+ const cbParams = { entry, ctx, listPath:path, node:sub }
38
+ try {
39
+ if (onDirEntryHandlers.some(cb => cb(cbParams) === false))
40
+ continue
41
+ }
42
+ catch(e) {
43
+ console.log('a plugin with onDirEntry is causing problems:', e)
44
+ }
45
if (offset) {
46
--offset
47
continue
@@ -55,7 +65,7 @@ export const file_list:ApiHandler = async ({ path, offset, limit, search, omit,
65
}
66
}
67
58
-interface DirEntry { n:string, s?:number, m?:Date, c?:Date }
68
+export interface DirEntry { n:string, s?:number, m?:Date, c?:Date }
69
70
async function nodeToDirEntry(node: VfsNode): Promise<DirEntry | null> {
71
try {
src/plugins.ts
+17
-3
@@ -8,13 +8,20 @@ import mime from 'mime-types'
8
import Koa from 'koa'
9
import { getOrSet, onProcessExit, wantArray } from './misc'
10
import { getConfig, subscribeConfig } from './config'
11
+import { DirEntry } from './api.file_list'
12
+import { VfsNode } from './vfs'
13
14
const PATH = 'plugins'
15
16
const plugins: Record<string, Plugin> = {}
17
16
-export function mapPlugins<T>(cb:(plugin:Readonly<Plugin>, pluginKey:string)=> T) {
17
- return _.map(plugins, cb)
18
+export function mapPlugins<T>(cb:(plugin:Readonly<Plugin>, pluginName:string)=> T) {
19
+ return _.map(plugins, (pl,plName) => {
20
+ try { return cb(pl,plName) }
21
+ catch(e) {
22
+ console.log('plugin error', plName, String(e))
23
+ }
24
+ }).filter(x => x !== undefined) as Exclude<T,undefined>[]
25
}
26
27
export function pluginsMiddleware(): Koa.Middleware {
@@ -62,6 +69,10 @@ subscribeConfig({ k:'disable_plugins', defaultValue:[] }, () => {
69
}
70
})
71
72
+// return false to ask to exclude this entry from results
73
+interface OnDirEntryParams { entry:DirEntry, ctx:Koa.Context, node:VfsNode }
74
+type OnDirEntry = (params:OnDirEntryParams) => void | false
75
+
76
class Plugin {
77
js: any
78
constructor(readonly k:string, private data:any, private unwatch:()=>void){
@@ -93,6 +104,9 @@ class Plugin {
104
get frontend_js(): undefined | string[] {
105
return this.data?.frontend_js
106
}
107
+ get onDirEntry(): undefined | OnDirEntry {
108
+ return this.data?.onDirEntry
109
+ }
110
111
unload() {
112
console.log('unloading plugin', this.k)
@@ -122,7 +136,7 @@ async function rescan() {
136
f = resolve(f) // without this, import won't work
137
const unwatch = watchLoad(f, async () => {
138
try {
125
- console.log('loading plugin', k)
139
+ console.log(plugins[k] ? 'reloading plugin' : 'loading plugin', k)
140
const data = await import(f)
141
deleteModule(require.resolve(f)) // avoid caching
142
new Plugin(k, data, unwatch)