Activation is the plugin manager running a module’s body: once, when the module’s event has fired and every
capability it requires has been contributed.
An activation event is a named moment in the app’s life, such as startup or the first time an article is shown.
A module names the event it waits for in activatesOn, and can combine several: ActivationEvent.oneOf activates on
the first of them, and ActivationEvent.allOf waits for all of them.
Helper to define an eager module body with the same spec-carrying shape as
lazyModule
— for bodies that are plain values (translations, schema) or too small
to justify a chunk, so plugin definitions stay a uniform chain of spec-carrying modules.
@param ― name The module name — used to auto-compute module IDs.
A module’s requires is the second gate. The plugin manager keeps a graph of which module provides each
capability, and activates providers before the modules that require them, whichever event activated the provider.
Registration order plays no part.
1
import*as
import Effect
Effectfrom'effect/Effect';
2
import*as
import Capability
Capabilityfrom'@dxos/app-framework/Capability';
3
4
// No `activatesOn`: this module waits for `Index`, so it activates whenever the
Helper to define an eager module body with the same spec-carrying shape as
lazyModule
— for bodies that are plain values (translations, schema) or too small
to justify a chunk, so plugin definitions stay a uniform chain of spec-carrying modules.
@param ― name The module name — used to auto-compute module IDs.
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.
The app fires ActivationEvents.Startup while it boots and ActivationEvents.Idle once it has painted and the
browser is idle. A module with no activatesOn belongs to the Idle wave, so only what the first screen needs runs
at startup.
The framework fires further events when something first needs a module. ActivationEvents.SurfacesRequested(role)
fires the first time a surface of that role renders; CommandsRequested fires when the command palette or CLI asks
for commands. The module makers in AppCapability choose the event, so the surface module of a plugin loads with
the first article, not at startup.
A module can fire an event itself with Plugin.activate, which is how one plugin loads another’s modules on demand.
An event stays fired. A module added after its event, for example by a plugin a person turns on later, activates
at once.
A lazy module’s code is imported only when it is about to activate. A module whose event never fires is never
loaded, which is what keeps a large app’s boot small.
Plugins come and go while the app runs. Enabling one registers its modules and activates every module whose event
has fired; disabling one deactivates its modules in reverse order, runs their finalizers and removes their
contributions. PluginManager shows the calls.
A module that fails, or does not finish within 30 seconds, is recorded on the manager’s failed list and its
plugin is disabled, so one broken plugin does not stop the app from starting.