A library module is a module which itself does not offer any functionality for a user, rather provides an API which other modules can leverage.
Follow semver and avoid breaking the API if possible.
library
Leverage the manifest JSON field library
to inform Foundry Core that this module should be loaded first.
The convention among Foundry VTT Development community (and the official recommendation from Atropos himself) is to expose module-specific APIs on the module's moduleData located at game.modules.get('my-module-name')?.api
. Additionally, any module can call an arbitrary hook to inform other modules about events.
Together these two methods provide a bulletproof way for a module to expose an API to other modules.
¶ Package Load Order
It is a best practice to leverage a custom hook because packages fire hooks like
ready
andinit
in a specific order which you cannot control. A module might load before yours does, and if it relies on your module's api at ready, it will not have a good way to do so.Using the
library
field in your manifest will mitigate the risk of a different package loading before yours, if applicable.
Cool module needs to set up some settings before it can reliably provide an API.
class MyCoolClass {
// ...
static myStaticMethod(argument) {
// does stuff you want other modules to have access to
}
}
Hooks.on('init', () => {
// my module needs to do something to set itself up (e.g. register settings)
// ...
// once set up, we create our API object
game.modules.get('cool-module').api = {
coolStaticMethod: MyCoolClass.myStaticMethod
};
// now that we've created our API, inform other modules we are ready
// provide a reference to the module api as the hook arguments for good measure
Hooks.callAll('coolModuleReady', game.modules.get('cool-module').api);
});
A different module can now reliably use this api like so.
// if I need to do something as soon as the cool-module is ready
Hooks.on('coolModuleReady', (api) => {
// do what I need with their api
});
// alternatively if I know that the API should be populated when I need it,
// I can defensively use the api on game.modules
game.modules.get('cool-module')?.api?.coolStaticMethod(someInput)
Rather than including these js libs in your own module's files, you can make use of these commonly re-used packages.
More than simply wrapping an existing js lib, these are made specifically with foundry's use cases in mind.