The plugin manager holds an app’s plugins, decides which are enabled, and activates their modules as events fire. An
app such as Composer creates one at boot; a plugin reaches it through Capabilities.PluginManager when it needs to
turn other plugins on or off. Activation explains the order it activates modules in.
PluginManager.make takes the plugins the app knows about and the ones enabled at start. Plugins tagged system
are always enabled. The pluginLoader turns an id the manager is later asked to add into a plugin.
Creates a plugin loader that resolves built-in plugins by ID or loads remote plugins from URLs.
Remote URLs must point at a plugin manifest (plugin.json). The loader fetches the manifest,
eagerly persists every declared asset via the configured PluginAssetCache, then dynamic-imports
the entry module.
make([]),
12
});
13
start runs the startup pass: it activates the Startup modules and every module whose requirements they satisfy.
An app fires Idle once it has painted. A React app renders App.Root from @dxos/app-framework/App, which does both.
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to use
Use when you want to write effectful code that looks and behaves like
synchronous code, while still handling asynchronous tasks, errors, and complex
control flow such as loops and conditions.
Generator functions work similarly to async/await but keep errors,
requirements, and interruption in the Effect type. You can yield* values
from effects and return the final result at the end.
Runs startup: the capability-dependency resolution pass for dependency-mode modules,
concurrently with the event-mode activation pass for any module explicitly targeting the
Startup event. The event-level Startup activated message publishes only after both
passes complete. Idempotent — subsequent calls activate whatever registered since.
activate(Startup) delegates here.
Fired once by the host at main-thread idle after the app is interactive.
For REGISTRATION contributions only — graph builders, operation handler sets, settings: the
app-wide indexes a user can reach from anywhere (the navtree, the operation registry, a
settings read) and which therefore no single surface can gate. A feature's own modules ride
its plugin start event, fired when its surface renders; putting a feature body here instead
is what turned the former DeferredStartup into a second startup pass.
This is also what omitting activatesOn normalizes to, so a module that must run at boot has
to say activatesOn: ActivationEvents.Startup explicitly. Defined in core; see
enable turns on a plugin and the plugins it declares in dependsOn, then activates every module whose event has
fired. disable deactivates a plugin’s modules and, by default, the plugins that depend on it. remove disables a
plugin and forgets it.
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to use
Use when you want to write effectful code that looks and behaves like
synchronous code, while still handling asynchronous tasks, errors, and complex
control flow such as loops and conditions.
Generator functions work similarly to async/await but keep errors,
requirements, and interruption in the Effect type. You can yield* values
from effects and return the final result at the end.
Determines whether an array includes a certain element, returning true or false as appropriate.
@param ― searchElement The element to search for.
@param ― fromIndex The position in this array at which to begin searching for searchElement.
includes(
key: string
key)) {
6
// Also disables the plugins that depend on it.
7
yield*
const manager: PluginManager.PluginManager
manager.
PluginManager.disable(id: string, opts?: {
cascade?: boolean;
}): Effect.Effect<boolean, Error>
Disables a plugin.
By default, cascades to currently-enabled dependents (transitively, leaves
first) so disabling a depended-upon plugin never leaves its dependents
stranded. Pass cascade: false to disable only the named plugin and leave
its dependents enabled-but-broken — VS Code-style disable parity for
callers that want the escape hatch (e.g. when swapping in an alternative
implementation that satisfies the dependents' needs in its own way).
Fails with
Plugin.PluginDependencyError
(reason: 'core-dependent')
when cascading would require disabling a core plugin; UI flows should
surface their own confirmation before calling disable with the default.
disable(
key: string
key);
8
} else {
9
yield*
const manager: PluginManager.PluginManager
manager.
PluginManager.enable(id: string, opts?: {
resolveDependencies?: boolean;
}): Effect.Effect<boolean, Error>
Enables a plugin.
Default behavior auto-resolves the plugin's declared dependsOn closure:
missing entries that exist in the plugin registry catalog are installed via
add
, then enabled in dependency-first order. Set resolveDependencies
to false to enable only the named plugin and skip the closure walk
entirely — useful when substituting an alternative plugin that satisfies
the dependent's capability needs in its own way.
add hands an id to the plugin loader and registers the result without enabling it. UrlLoader.make loads a plugin
from its manifest URL, which is how Composer’s Load dev plugin and the docs’ inspector
load a plugin from its dev server. The page needs an import map of the shared packages, so the plugin uses the page’s
copies.
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to use
Use when you want to write effectful code that looks and behaves like
synchronous code, while still handling asynchronous tasks, errors, and complex
control flow such as loops and conditions.
Generator functions work similarly to async/await but keep errors,
requirements, and interruption in the Effect type. You can yield* values
from effects and return the final result at the end.
Loads a plugin via the plugin loader and registers it without enabling it.
Returns the loaded plugin so callers can enable it by its canonical id
(which may differ from the locator used to load it, e.g. URL loaders).
A plugin whose id is already enabled, such as one persisted from an earlier
session, is activated as part of the add.
add('http://localhost:3967/manifest.json');
6
yield*
const manager: PluginManager.PluginManager
manager.
PluginManager.enable(id: string, opts?: {
resolveDependencies?: boolean;
}): Effect.Effect<boolean, Error>
Enables a plugin.
Default behavior auto-resolves the plugin's declared dependsOn closure:
missing entries that exist in the plugin registry catalog are installed via
add
, then enabled in dependency-first order. Set resolveDependencies
to false to enable only the named plugin and skip the closure walk
entirely — useful when substituting an alternative plugin that satisfies
the dependent's capability needs in its own way.
Each piece of state has a getter for a one-off read and an atom for a component that should update. getFailed
lists plugins that failed to load or activate, with the phase and the error.
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@param ― callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
@param ― thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map(({
id: string
id,
phase: PluginManager.PluginFailurePhase
phase,
reason: PluginManager.PluginFailureReason
reason }) => ({
id: string
id,
phase: PluginManager.PluginFailurePhase
phase,
reason: PluginManager.PluginFailureReason
reason })),
7
});
8
9
// The same state as atoms, for a component that should update.