Modules
Overview
The @antelopejs/interface-core/modules module provides lifecycle events and management functions for AntelopeJS modules. Modules transition through a defined lifecycle, and each transition emits an event that other modules can observe.
Inspect the running modules
Call these functions from a running AntelopeJS module, where the core has attached their implementations. This example reads status without changing the project.
import { ListModules, GetModuleInfo } from "@antelopejs/interface-core/modules";
for (const id of await ListModules()) {
const info = await GetModuleInfo(id);
console.log(id, info.status);
}
Use management functions to change what is running now. Use declaration functions to edit what the project loads on its next start. Neither action automatically performs the other.
Import
import {
Events,
ListModules,
GetModuleInfo,
LoadModule,
StartModule,
StopModule,
DestroyModule,
ReloadModule,
} from "@antelopejs/interface-core/modules";
Module lifecycle
A module moves through these states:
loaded -> constructed -> active -> constructed -> loaded
(stopped) (destroyed)
| State | Description |
|---|---|
loaded | Module code is loaded but no instance exists |
constructed | Module instance is created but not started |
active | Module is fully started and providing services |
unknown | Module status cannot be determined |
Module execution context
This is a loader concern. Application modules normally receive their context from the runtime and do not invent their own owner IDs.
RunWithModuleContext propagates module ownership through synchronous and asynchronous work:
import { RunWithModuleContext } from "@antelopejs/interface-core/modules";
await RunWithModuleContext(
{
module: "search-provider",
owner: "search-provider#42",
},
() => constructModule(),
);
module remains the stable public module ID. owner identifies one lifecycle generation and should be unique when old and replacement instances can overlap. Providers capture this full context when attaching callbacks. GetModuleContext returns the active context, or undefined when there is none, and throws ModuleContextInvalidatedError after its owner is destroyed.
Lifecycle events
The Events namespace exposes four EventProxy instances that fire during module lifecycle transitions.
Events.ModuleConstructed
Fires after a module instance is created, before the module is started.
import { Events } from "@antelopejs/interface-core/modules";
Events.ModuleConstructed.register((moduleId: string) => {
console.log(`Module constructed: ${moduleId}`);
});
Events.ModuleStarted
Fires after a module has been started and is fully operational.
Events.ModuleStarted.register((moduleId: string) => {
console.log(`Module started: ${moduleId}`);
});
Events.ModuleStopped
Fires after a module has been stopped. The module instance still exists but is no longer active.
Events.ModuleStopped.register((moduleId: string) => {
console.log(`Module stopped: ${moduleId}`);
});
Events.ModuleDestroyed
Fires after a module instance has been destroyed and all its resources have been released. The system uses this event internally to clean up proxy attachments and event handlers associated with the destroyed module.
Events.ModuleDestroyed.register((moduleId: string) => {
console.log(`Module destroyed: ${moduleId}`);
});
The event signature remains the module ID. When emitted inside RunWithModuleContext, cleanup targets that context's owner; without an explicit owner it retains the module-level behavior used by earlier releases.
Management functions
These functions are declared as InterfaceFunction proxies. They are available once the core runtime provides their implementation.
ListModules
Returns the identifiers of all loaded modules.
const modules = await ListModules();
// ["auth-module", "database-module", "api-module"]
GetModuleInfo
Returns detailed information about a specific module, including its configuration, status, and file system path.
import type { ModuleInfo } from "@antelopejs/interface-core/modules";
const info: ModuleInfo = await GetModuleInfo("auth-module");
// info.status -> "active"
// info.localPath -> "/path/to/auth-module"
// info.source -> { type: "package", ... }
LoadModule
Loads a new module with the given configuration. Set autostart to true to automatically start the module after loading.
import type { ModuleDefinition } from "@antelopejs/interface-core/modules";
const definition: ModuleDefinition = {
source: { type: "package", package: "@my/module", version: "1.0.0" },
config: { key: "value" },
};
await LoadModule("my-module", definition, true);
StartModule
Starts a loaded but inactive module.
await StartModule("my-module");
StopModule
Stops an active module. The module instance remains but stops providing services.
await StopModule("my-module");
DestroyModule
Destroys a stopped module instance. The module code remains loaded.
await DestroyModule("my-module");
ReloadModule
Stops, destroys, unloads, and reloads a module from its source. This is useful for applying updates without restarting the application.
await ReloadModule("my-module");
Declaration functions
These functions read and edit the modules of the project's antelope.config.ts, for a module that installs or removes other modules and wants the change to survive a restart.
ListModuleDeclarations
Returns the modules the configuration file declares at its top level, by key, shorthand entries expanded and disabled ones included.
const declarations = await ListModuleDeclarations();
SaveModuleDeclaration
Writes the given fields of a module's entry, adding the entry when the file has none. Only those fields are rewritten: every other line of the file, comments and expressions included, stays as it was. A field set to undefined or null is removed. The running project does not restart for this write; the caller loads, stops or reloads the module itself.
await LoadModule("@acme/reports", { source }, true);
await SaveModuleDeclaration("@acme/reports", { source, optional: true });
It throws when the file has no modules object it can edit, such as a configuration built by a function.
RemoveModuleDeclaration
Removes a module's entry, leaving the rest of the file as it was and the project running.
await RemoveModuleDeclaration("@acme/reports");
ModuleDefinition
The configuration object for defining a module.
| Property | Type | Description |
|---|---|---|
source | { type: string } & Record<...> | Source location and loading mechanism |
config | unknown | Optional configuration data for the module |
importOverrides | Record<string, string[]> | Optional runtime import override map with array values |
disabledExports | string[] | Optional list of exports to hide from this module |
ModuleDefinition is the runtime management contract used by LoadModule and GetModuleInfo. It is not the project-file AntelopeModuleConfig: that type uses ImportOverride[] | Record<string, string> for declarative provider bindings and named connections. The different importOverrides shapes are intentional; do not copy one into the other or cast between them. SaveModuleDeclaration uses the project-file shape. See project configuration for that contract.
ModuleInfo
Extends ModuleDefinition with runtime information.
| Property | Type | Description |
|---|---|---|
status | string | Current lifecycle state of the module |
localPath | string | File system path where the module exists |
Next steps
- Logging - Structured logging with channels and levels
- Configuration - Project configuration types