plugins: api.setError

Massimo Melina committed Jan 6, 2025 at 17:16 UTC 6a51aa1b69e4a020a3f09f222881a8649efa6147
3 files changed +23 -14
dev-plugins.md
+5 -1
@@ -244,6 +244,8 @@ The `api` object you get as parameter of the `init` contains the following:
244
245 - `ctxBelongsTo(ctx: Context, accounts: strings[]): boolean` check if the current username, or any group it belongs to, matches the provided accounts list.
246
247 +- `setError(error: string)` set an error message that will be displayed in the admin-panel. Use an empty string to clear it.
248 +
249 - `misc` many functions and constants available in [misc.ts](https://github.com/rejetto/hfs/blob/main/src/misc.ts).
250 These are not documented, probably never will, and are subject to change without notifications,
251 but you can study the sources if you are interested in using them. It's just a shorter version of `api.require('./misc')`
@@ -700,7 +702,9 @@ If you want to override a text regardless of the language, use the special langu
702
703 ## API version history
704
703 - - 10.3 (v0.55.0)
705 +- 11 (v0.56.0)
706 + - api.setError
707 +- 10.3 (v0.55.0)
708 - HFS.copyTextToClipboard
709 - HFS.urlParams
710 - exports.beforePlugin + afterPlugin
src/const.ts
+1 -1
@@ -9,7 +9,7 @@ import { formatTimestamp } from './cross'
9 import { argv } from './argv'
10 export * from './cross-const'
11
12 -export const API_VERSION = 10.3
12 +export const API_VERSION = 11
13 export const COMPATIBLE_API_VERSION = 1 // while changes in the api are not breaking, this number stays the same, otherwise it is made equal to API_VERSION
14
15 // you can add arguments with this file, currently used for the update process on mac/linux
src/plugins.ts
+17 -12
@@ -92,8 +92,8 @@ export function setPluginConfig(id: string, changes: Dict | null) {
92 }
93
94 export function getPluginInfo(id: string) {
95 - const running = plugins.get(id)?.getData()
96 - return running && Object.assign(running, {id}) || availablePlugins[id]
95 + const running = plugins.get(id)
96 + return running && { ...running.getData(), ...running } || availablePlugins[id]
97 }
98
99 export function findPluginByRepo<T>(repo: string) {
@@ -111,13 +111,14 @@ export function getPluginConfigFields(id: string) {
111 return plugins.get(id)?.getData().config
112 }
113
114 -async function initPlugin<T>(pl: any, morePassedToInit?: T) {
114 +async function initPlugin(pl: any, morePassedToInit?: { id: string } & Dict<any>) {
115 const res = await pl.init?.({
116 Const,
117 require,
118 getConnections,
119 events,
120 log: console.log,
121 + setError(msg: string) { setError(morePassedToInit?.id || 'server_code', msg) },
122 getHfsConfig: getConfig,
123 customApiCall,
124 notifyClient,
@@ -182,11 +183,11 @@ export const pluginsMiddleware: Koa.Middleware = async (ctx, next) => {
183 for (const [id,f] of Object.entries(after))
184 try { await f() }
185 catch (e) { printError(id, e) }
185 -}
186
187 -function printError(id: string, e: any) {
188 - console.log(`error middleware plugin ${id}: ${e?.message || e}`)
189 - console.debug(e)
187 + function printError(id: string, e: any) {
188 + console.log(`error middleware plugin ${id}: ${e?.message || e}`)
189 + console.debug(e)
190 + }
191 }
192
193 declare module "koa" {
@@ -260,7 +261,7 @@ export class Plugin implements CommonPluginInterface {
261 }
262
263 getData(): any {
263 - return { ...this.data }
264 + return this.data
265 }
266
267 async unload(reloading=false) {
@@ -420,8 +421,7 @@ function watchPlugin(id: string, path: string) {
421
422 async function onUninstalled() {
423 await stop()
423 - const was = getPluginInfo(id)
424 - if (!was) return
424 + if (!getPluginInfo(id)) return // already missing
425 delete availablePlugins[id]
426 events.emit('pluginUninstalled', id)
427 }
@@ -470,6 +470,7 @@ function watchPlugin(id: string, path: string) {
470 await mkdir(storageDir, { recursive: true })
471 const dbs: KvStorage[] = []
472 await initPlugin(pluginData, {
473 + id,
474 srcDir: __dirname,
475 storageDir,
476 async openDb(filename: string, options?: KvStorageOptions){
@@ -528,7 +529,6 @@ function watchPlugin(id: string, path: string) {
529 const parsed = e.stack?.split('\n\n') // this form is used by syntax-errors inside the plugin, which is useful to show
530 const where = parsed?.length > 1 ? `\n${parsed[0]}` : ''
531 e = e.message + where || String(e)
531 - console.log(`plugin error: ${id}:`, e)
532 setError(id, e)
533 }
534 finally {
@@ -547,11 +547,16 @@ function getError(id: string) {
547 return getPluginInfo(id)?.error as undefined | string
548 }
549
550 +// returns true if there's an error, and it has changed
551 function setError(id: string, error: string) {
552 const info = getPluginInfo(id)
553 if (!info) return
554 + if (info.error === error) return
555 info.error = error
554 - events.emit('pluginUpdated', { id, error })
556 + events.emit('pluginUpdated', info)
557 + if (!error) return
558 + console.log(`plugin error: ${id}:`, error)
559 + return true
560 }
561
562 function deleteModule(id: string) {