Lifecycle
init, start, stop. Order, async model, failures.
Three phases
| Phase | Method | Direction | When | Context |
|---|---|---|---|---|
| init | onInit | forward | inside createApp(), synchronous | full ctx |
| start | onStart | forward | await app.start() | full ctx |
| stop | onStop | reverse | await app.stop() | own global, config, state |
Before the lifecycle, each plugin's factories run in this order:
createStatehooksapionInitonStartonStop
Async model
One plugin at a time, fully awaited. There is no parallelism inside or across phases: plugin A
resolves before plugin B begins. createApp() is synchronous; start() and stop() return
promises.
import { createApp, createPlugin } from "@moku-labs/web";
const timerPlugin = createPlugin("timer", {
createState: (): { handle?: ReturnType<typeof setInterval> } => ({}),
onStart: ctx => {
ctx.state.handle = setInterval(() => ctx.log.info("timer:tick"), 1000);
},
onStop: ctx => {
clearInterval(ctx.state.handle);
}
});
const app = createApp({
plugins: [timerPlugin],
pluginConfigs: { site: { name: "Demo", url: "https://example.com" } }
});
await app.start(); // onStart, forward, one plugin at a time
await app.stop(); // onStop, reverse: infrastructure outlives the plugins that use it- Open a resource when the app starts.
- onStop gets its own state back, nothing else.
onStart and onStop are optional. Add them only when a plugin opens something it must close: a
socket, a listener, a timer.
Failures
Lifecycle is not transactional. Errors propagate to the caller. The kernel does not roll back, retry or compensate. After a failure, discard the app and create a new one.
start() throws when called twice, and stop() throws when start() never ran. The exact
messages are on What the kernel checks.
Core plugins
Core plugins have their own timeline: they init and start before regular plugins, and stop after
them. ctx.log therefore works in every onStop of a regular plugin's teardown chain, and the
logger is the last thing to go.
In @moku-labs/web
Most web plugins only use onInit: router compiles its table, site and i18n validate their
config. spa is the one default with onStart and onStop, because it owns browser listeners.