@wolfstar/kit
| Install | |
|---|---|
npm install @wolfstar/kit |
|
| Latest Version: | 0.3.1 |
| License: | Apache-2.0 |
| Last Updated: | Oct 22, 2026 |
| Links: | GitHub · npm |
@wolfstar/kit
defineModule and the module runtime for installable Stars modules — the @nuxt/kit counterpart. A module is a
package that says it is one; the project lists it in modules in stars.config:
// stars.config.ts
import { defineConfig } from '@wolfstar/http-framework/config';
export default defineConfig({
modules: ['@wolfstar/plugin-cache', ['@wolfstar/plugin-gateway', { shards: 2 }]]
});
// the module's package: its default export
import { defineModule } from '@wolfstar/kit';
export default defineModule<{ ttl: number }>({
meta: {
name: '@wolfstar/plugin-cache',
compatibility: { framework: '>=6.1.0' }
},
defaults: { ttl: 60_000 },
hooks: {
'build:done': (outcome) => {}
},
setup(options, ctx) {
ctx.addPlugin({ from: new URL('./plugin.js', import.meta.url), options });
ctx.addImports('@wolfstar/plugin-cache');
}
});
// plugin.js — runs in the bot
import { definePlugin } from '@wolfstar/http-framework';
export default definePlugin((options) => ({
name: '@wolfstar/plugin-cache',
preLoad(client) {}
}));
@wolfstar/kit depends on @wolfstar/schema only, so a module depends on it (as a peer) without pulling in the
framework or the CLI.
What setup can do
setup(options, ctx) runs once, in the CLI process, while the project loads. options is the module's defaults
merged under the ones written in stars.config (plain objects merge deeply, arrays are replaced). They come from two
places, the inline ones winning: the [name, options] tuple in modules, and, when the module declares
meta.configKey, a top-level key of that name.
// the module
export default defineModule<ScheduledTasksOptions>({
meta: { name: '@wolfstar/plugin-scheduled-tasks', configKey: 'scheduledTasks' },
defaults: { concurrency: 1 },
setup(options, ctx) {}
});
declare module '@wolfstar/schema' {
interface StarsConfig {
scheduledTasks?: ScheduledTasksOptions;
}
}
// stars.config.ts
export default defineConfig({
modules: ['@wolfstar/plugin-scheduled-tasks'],
scheduledTasks: { bull: { connection: { host: 'localhost', port: 6379 } } }
});
A key that no installed module claims is reported by the CLI as an unknown option, so a misspelled one is still an
error. The declare module augmentation only applies once the module's types are loaded: import the package in
stars.config.ts (stars prepare does not reference installed modules yet).
A configKey must be a non-empty string, not a built-in key of stars.config and not claimed by another installed
module; the value under it must be a plain object. A module installed through dependencies or ctx.installModule
reads its key as well, with the options passed to installModule taking the inline place.
ctx.addPlugin(source)registers a runtime plugin. The plugin lives in the bot's process andsetupin the CLI's, so a plugin is given by source —{ from, export?, options? }— rather than by value.fromis a package specifier, an absolute path or afile:URL (a relative path is rejected: it would resolve differently in each build tool); theexport(default'default') is the plugin or, when it is a function, a factory called withoptions, which must be JSON-serialisable. A legacyPluginclass is registered as it is, never called.ctx.addLocales(directory)registers a directory of locales laid out as<language>/<namespace>.json(nested folders make namespaces such ascommands/shared). Give an absolute path or afile:URL to a directory that exists when the module is set up, because its namespaces are read then. A generated runtime plugin merges it into the client'si18noption before@wolfstar/plugin-i18nextbuilds its handler, and keeps the project's own languages directory. It needs a framework that exportsgetRootData. LikeaddPiecesDir, the absolute path is written into the generated source and read at runtime, so a build that bundles everything (Vite, Nitro) or one moved to another machine will not find the directory.ctx.addClientHook(name, source)(orhooks: { 'client:preLoad': source }) runs a function in the bot at a point of the client's lifecycle:client:preGenericsInitialization,client:preInitialization,client:postInitialization,client:preLoadorclient:postListen. Like a plugin it is given by source (a specifier, an absolute path or afile:URL, or{ from, export? }); the export is called with(client, clientOptions), and may be async only forpreLoadandpostListen. A module's hooks share one runtime plugin named after it, so a failure is reported with the module's name. One hook per name and module.ctx.addPiecesDir(directory)registers a directory of pieces (a folder per store:commands,listeners, …) that is loaded next to the bot's own. Give an absolute path or afile:URL, e.g.new URL('./pieces', import.meta.url); a relative path is rejected. The pieces are read from files at runtime, so it does not work in a build that bundles everything (Vite, Nitro). Only the stores that exist when the modules source runs are covered (the framework's four, and any registered by an earlier import); a folder for a store registered later is ignored.ctx.addImports(preset)adds a package to the auto imports presets.ctx.hook(name, callback)/ctx.callHook(name, …)use the CLI's hooks (StarsHooks), the same registry ashooksinstars.config. A module'shooksare registered beforesetupruns; an unknown hook name or a value that is not a function fails the install.ctx.installModule(module, options?)installs another module, anddependenciesinstalls modules first. A module is installed once, bymeta.name: the first installation wins.
meta.compatibility (framework, stars) is a semver range checked against the project's installed
@wolfstar/http-framework and the running @wolfstar/cli; a mismatch fails early instead of leaving a plugin that
silently never runs.
Production with tsc or none
tsdown, vite and Nitro builds register the runtime plugins through the entry. tsc and none builds cannot be
transformed: stars dev preloads the plugins with node --import, and for production stars prepare (and
stars build) writes .stars/modules.mjs, to be preloaded the same way: node --import ./.stars/modules.mjs dist/main.js.
stars build, stars prepare and stars info report a warning (MODULES_PRELOAD_REQUIRED) when such a project has modules with runtime plugins; stars dev does not print it, since it preloads them itself. With env enabled, modules.mjs imports .stars/env.mjs first, so the environment is loaded before any plugin is evaluated.
Programmatic usage
setupModules({ config, hooks, load, versions }) is what the CLI calls: load imports a specifier from the project,
hooks is a hookable-shaped registry, and the result (ModulesRuntime) lists the installed modules, the runtime
plugins, the import presets and the configKeys they contributed. Failures are ModuleErrors with a code (MODULE_LOAD_FAILED,
MODULE_INVALID, MODULE_INCOMPATIBLE, MODULE_SETUP_FAILED, MODULE_PLUGIN_INVALID) and the moduleName.
Related Packages
The VuePress API Playground is a Vue.js component for showcasing and testing API...
Version History
| Version | Released | License |
|---|---|---|
| 0.3.1 | Apache-2.0 | |
| 0.3.0 | Apache-2.0 | |
| 0.2.1 | Apache-2.0 | |
| 0.2.0 | Apache-2.0 | |
| 0.1.3 | Apache-2.0 | |
| 0.1.1 | Apache-2.0 | |
| 0.1.0 | Apache-2.0 |
Pre-releases (8)
| Version | Released | License |
|---|---|---|
| 0.2.1-next-20261009120452 | Apache-2.0 | |
| 0.2.1-next-20261009115919 | Apache-2.0 | |
| 0.2.0-next-20261007154227 | Apache-2.0 | |
| 0.2.0-next-20261007152629 | Apache-2.0 | |
| 0.2.0-next-20261007120201 | Apache-2.0 | |
| 0.1.2-next-20261006112342 | Apache-2.0 | |
| 0.1.1-next-20261004142621 | Apache-2.0 | |
| 0.1.1-next-20261004131917 | Apache-2.0 |