I’ve finally figure out the way to fully publish API type definitions of plugins, including custom events hooked into Vault/ metadataCache.
Solutions
So currently, I’ve worked out two methods to provide API that works:
- Method 1: export API to global namespace directly (thanks @pjeby for the enlightenment)
- Method 2: access from
plugin.app.plugins.plugins["your-plugin-id"]?.api
For details, here is the example of a minimal project, with some tricks in typescirpt to keep types of on args and trigger args for events in sync:
Example for inter-plugin API declaration in obisidian (github.com)
Real-world demo
In folder-note-core, I’ve exposed getApi, isPluginEnabled and, registerApi in index.ts, which use method 1 and method 2 underneath, and declare API in api.ts
Limitations & Proposal
However, method 1 is definitely polluting the global namespace, despite the convenience to detect and access API. It is risky if other plugins accidentally use the package that relies on a member exported to global, whose name coincides with the API name. And accessing API via method 2 is truly lengthy.
So here I propose two potential solutions for obsidian to improve:
- declare a member
pluginApiin the global namespace, similar toapp, so that plugin devs can add their API towindow.pluginApi.API_NAMEv3to avoid pollution - add
loadApi(api: any)andunloadApi(api: any)method toPluginclass and have an additional member in Plugin class:apisto access other apis. The type ofapp.apiscan be an id-api map like:
(theMap<string, { version: string; [key: string]: any }>versioncan be used to check compatibility of API in case of breaking changes)