Hooks, plugins, and timeline reference
Extend lifecycle, install plugins with grants, and control time projections while distinguishing their authorities.
A hook changes the lifecycle flow; a plugin groups setup, permissions, and cleanup; timeline keeps a projection journal. Each mechanism has an owner and a way to end its activity.
Intercepting a phase
import { wu, createGuardHook } from 'wu-framework';
const removeGuard = wu.hooks.use('beforeMount', createGuardHook(context => {
return context.appName !== 'disabled-app';
}), { name: 'availability' });
// Al retirar esta extensión:
removeGuard();
Available phases are before/after Init, Load, Mount, Update, Unmount, and Destroy. Higher priority runs first. Omitting next() cancels the chain; failOpen: true allows continuation after middleware failure. A UI guard does not replace role controls or core grants.
Granting authority to a plugin
Plugin permissions are mount, events, store, apps, config, and unsafe. A plugin requests these names, and the host grants options.grants during installation. Do not reuse store.read or rpc.call as plugin grants: those belong to application contracts.
Await pluginSystem.use or pluginSystem.ready before depending on setup. Installation from an asynchronous factory also participates in this startup. A plugin executes host code; its reduced API does not remove privileges captured in closures.
Recording before writing
await wu.timelineReady();
wu.timeline.record({ maxEntries: 500 });
wu.store.set('demo.count', 1);
wu.store.set('demo.count', 2);
await wu.timeline.seek(0, { apps: false, props: false });
await wu.timeline.live();
wu.timeline.stop();
The wu.timeline facade retains chainable methods for synchronous controls. The real object returned by timelineReady has different return values; use the facade in this reference’s examples. Seek rematerializes store, props, and composition according to options; it does not rewind networks, timers, or infrastructure.
wu.hooks.use
Installs lifecycle middleware with priority and individual cleanup.
wu.hooks.use(phase, middleware, options?): () => void
- Parameters: Valid phase, middleware(context,next); options: name, priority, failOpen.
- Returns: Unsubscribe function; the TypeScript declaration says void.
- Errors: Unknown phase or invalid callback throws; omitting next cancels the chain.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: stop() removes only that middleware.
const stop = wu.hooks.use('beforeMount', async (context, next) => {
console.log(context.appName);
await next();
}, { name: 'mount-log', priority: 10 });
Reference: src/core/wu-hooks.js.
wu.hooks.useMultiple
Installs the same middleware in several phases.
wu.hooks.useMultiple(phases, middleware, options?): () => void
- Parameters: Phase array; use a stable name to identify each derived registration.
- Returns: Combined cleanup.
- Errors: Every phase must exist; registration is not atomic if a later phase fails.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: stop() removes the created installations.
const stop = wu.hooks.useMultiple(['beforeMount', 'beforeUnmount'], async (ctx, next) => {
await next();
}, { name: 'trace' });
Reference: src/core/wu-hooks.js.
wu.hooks.remove
Removes middleware identified by phase and name.
wu.hooks.remove(phase, name): void
- Parameters: phase and registration name.
- Returns: void; absence does not throw.
- Errors: Duplicate names make removal ambiguous; prefer individual cleanup.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Installs no new resources.
wu.hooks.remove('beforeMount', 'mount-log');
Reference: src/core/wu-hooks.js.
wu.hooks.getHooks
Queries installed middleware metadata.
wu.hooks.getHooks(phase?): object | object[]
- Parameters: Optional phase.
- Returns: Without a phase: metadata map; with a phase: registration array.
- Errors: With a phase, returns internal registrations; do not mutate them as a configuration API.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Installs no new resources.
console.log(wu.hooks.getHooks());
Reference: src/core/wu-hooks.js.
wu.hooks.getStats
Queries hook distribution and execution records.
wu.hooks.getStats(): object
- Parameters: No arguments.
- Returns: Metrics object.
- Errors: The execution log has limited capacity.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Installs no new resources.
console.log(wu.hooks.getStats());
Reference: src/core/wu-hooks.js.
wu.hooks.cleanup
Removes middleware from one or every phase.
wu.hooks.cleanup(phase?): void
- Parameters: Optional phase; omitting it also empties the execution log.
- Returns: void.
- Errors: Does not itself cancel a callback already running.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Releases registrations; resources created by callbacks need their own cleanup.
wu.hooks.cleanup('beforeMount');
Reference: src/core/wu-hooks.js.
createSimpleHook
Converts a callback into middleware that continues the chain.
createSimpleHook(fn): Function
- Parameters: fn(context) may be asynchronous.
- Returns: async(context,next) middleware.
- Errors: Callback errors follow the factory and chain policy.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Install with hooks.use and retain that registration’s cleanup.
import { createSimpleHook } from 'wu-framework';
const middleware = createSimpleHook(ctx => console.log(ctx.appName));
Awaits the callback, then invokes next.
Reference: src/core/wu-hooks.js.
createConditionalHook
Executes a callback if the condition is true, then continues.
createConditionalHook(condition, fn): Function
- Parameters: condition(context) and fn(context).
- Returns: async(context,next) middleware.
- Errors: Callback errors follow the factory and chain policy.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Install with hooks.use and retain that registration’s cleanup.
import { createConditionalHook } from 'wu-framework';
const middleware = createConditionalHook(ctx => ctx.appName === 'catalog', ctx => console.log(ctx));
The condition is not a cancellation guard: a false condition continues the chain.
Reference: src/core/wu-hooks.js.
createGuardHook
Continues the chain only when the guard allows it.
createGuardHook(shouldContinue): Function
- Parameters: shouldContinue(context), synchronous or promise.
- Returns: async(context,next) middleware.
- Errors: Callback errors follow the factory and chain policy.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Install with hooks.use and retain that registration’s cleanup.
import { createGuardHook } from 'wu-framework';
const middleware = createGuardHook(ctx => ctx.appName !== 'disabled-app');
If it returns false, it does not call next; it does not replace grants or server authorization.
Reference: src/core/wu-hooks.js.
createTransformHook
Transforms the context received by the next middleware.
createTransformHook(transformer): Function
- Parameters: transformer(context) returns context data.
- Returns: async(context,next) middleware.
- Errors: Callback errors follow the factory and chain policy.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Install with hooks.use and retain that registration’s cleanup.
import { createTransformHook } from 'wu-framework';
const middleware = createTransformHook(ctx => ({ ...ctx, traceLabel: 'catalog' }));
This does not configure the core beyond fields consumed by that lifecycle.
Reference: src/core/wu-hooks.js.
createTimedHook
Limits how long middleware waits for a callback.
createTimedHook(fn, timeout?: number): Function
- Parameters: fn(context); default timeout 5000 ms.
- Returns: async(context,next) middleware.
- Errors: Callback errors follow the factory and chain policy.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Install with hooks.use and retain that registration’s cleanup.
import { createTimedHook } from 'wu-framework';
const middleware = createTimedHook(async ctx => console.log(ctx.appName), 1000);
A failure or timeout is logged and the chain continues; original work is not automatically aborted.
Reference: src/core/wu-hooks.js.
createPlugin
Builds a plugin with a name, requested permissions, and callbacks.
createPlugin(config): WuPlugin
- Parameters: config with name; optional install/uninstall and hooks.
- Returns: Plugin object; creating does not install.
- Errors: Invalid name/config may throw.
- Permissions: The plugin requests permissions; the host grants them when calling use.
- Cleanup: Install with pluginSystem.use and remove with uninstall.
import { createPlugin } from 'wu-framework';
const plugin = createPlugin({ name: 'catalog-observer', permissions: ['events'], install(api) { console.log(api.version); } });
Reference: src/core/wu-plugin.js.
wu.pluginSystem.use
Installs a plugin and awaits setup before considering it available.
wu.pluginSystem.use(pluginOrFactory, options?): Promise<boolean>
- Parameters: Plugin or async factory; options.grants and compatibility configure authority.
- Returns: true when installed; rejects validation/setup failures.
- Errors: Required permissions without grants, duplicates, and install errors may reject.
- Permissions: Plugin permissions: mount, events, store, apps, config, unsafe; distinct from app capabilities.
- Cleanup: await uninstall(name) revokes its API and runs cleanup.
await wu.pluginSystem.use({
name: 'catalog-observer', permissions: ['events'],
install(api) { console.log(api.version); },
}, { grants: ['events'] });
Reference: src/core/wu-plugin.js.
wu.pluginSystem.ready
Awaits pending installations and exposes their failures to bootstrap.
wu.pluginSystem.ready(): Promise<boolean>
- Parameters: No arguments.
- Returns: true on successful completion.
- Errors: Rejects the first pending error and includes pendingPluginErrors.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Does not uninstall successful plugins.
await wu.pluginSystem.ready();
Reference: src/core/wu-plugin.js.
wu.pluginSystem.uninstall
Removes a plugin and its associated authority.
wu.pluginSystem.uninstall(name): Promise<boolean>
- Parameters: Exact plugin name.
- Returns: Uninstallation boolean.
- Errors: Uninstall may fail; inspect the error and diagnostics.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Invokes the uninstall hook and releases plugin-owned hooks/listeners.
await wu.pluginSystem.uninstall('catalog-observer');
Reference: src/core/wu-plugin.js.
wu.pluginSystem.getPlugin
Queries an installed plugin’s definition.
wu.pluginSystem.getPlugin(name): WuPlugin | undefined
- Parameters: Exact name.
- Returns: Plugin or undefined.
- Errors: Does not exist until installation completes.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Installs no new resources.
console.log(wu.pluginSystem.getPlugin('catalog-observer')?.name);
Reference: src/core/wu-plugin.js.
wu.pluginSystem.getStats
Lists plugins, granted permissions, and active hooks.
wu.pluginSystem.getStats(): object
- Parameters: No arguments.
- Returns: Object with totalPlugins, plugins, and hooks.
- Errors: Does not verify plugin external effects.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Installs no new resources.
console.log(wu.pluginSystem.getStats());
Reference: src/core/wu-plugin.js.
wu.pluginSystem.cleanup
Uninstalls every plugin in the system.
wu.pluginSystem.cleanup(): Promise<void>
- Parameters: No arguments.
- Returns: Promise resolving when uninstallation traversal finishes.
- Errors: Failures follow the uninstall contract.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Affects all plugins; belongs to host teardown.
await wu.pluginSystem.cleanup();
Reference: src/core/wu-plugin.js.
wu.timelineReady
Loads the recorder before the first writes you want to capture.
wu.timelineReady(): Promise<unknown>
- Parameters: No arguments.
- Returns: Actual recorder instance; not the chainable facade.
- Errors: Rejects chunk download/import errors.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: wu.timeline.stop() removes observers; clear resets the journal.
await wu.timelineReady();
wu.timeline.record();
Reference: src/index.js.
wu.timeline.record
Starts the journal from current state and apps.
wu.timeline.record(options?: { snapshotEvery?: number; maxEntries?: number }): WuTimelineFacade
- Parameters: Optional snapshot frequency and entry limit.
- Returns: WuTimelineFacade
- Errors: The asynchronous family may reject chunk, format, or materialization errors.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: stop() removes taps.
await wu.timelineReady();
wu.timeline.record({ snapshotEvery: 25, maxEntries: 500 });
The facade returns itself; the actual recorder returns status. Without timelineReady, deferred loading may miss initial writes.
Reference: src/core/wu-timeline.js.
wu.timeline.stop
Stops capture while retaining the journal for inspection.
wu.timeline.stop(): WuTimelineFacade
- Parameters: No arguments.
- Returns: WuTimelineFacade
- Errors: The asynchronous family may reject chunk, format, or materialization errors.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Removes store and bus taps.
wu.timeline.stop();
Does not stop timers, requests, or processes created by applications.
Reference: src/core/wu-timeline.js.
wu.timeline.clear
Empties the journal and takes the current situation as the new baseline.
wu.timeline.clear(): WuTimelineFacade
- Parameters: No arguments.
- Returns: WuTimelineFacade
- Errors: The asynchronous family may reject chunk, format, or materialization errors.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Does not replace stop if you want to stop recording.
wu.timeline.clear();
Does not delete business state or reverse external effects.
Reference: src/core/wu-timeline.js.
wu.timeline.seek
Materializes a journal position in its projections.
wu.timeline.seek(position: number, options?: { store?: boolean; apps?: boolean; props?: boolean }): Promise<WuTimelineStatus>
- Parameters: Index 0..length; selects store/apps/props.
- Returns: Promise
- Errors: The asynchronous family may reject chunk, format, or materialization errors.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Return to live to recover the final position.
const status = await wu.timeline.seek(0, { store: true, apps: false, props: false });
Does not reverse HTTP, timers, or infrastructure. Writes made in the past do not create a new branch.
Reference: src/core/wu-timeline.js.
wu.timeline.live
Materializes the end of the journal.
wu.timeline.live(): Promise<WuTimelineStatus>
- Parameters: No arguments.
- Returns: Promise
- Errors: The asynchronous family may reject chunk, format, or materialization errors.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Retains the recorder until stop.
await wu.timeline.live();
Returning to live discards unrecorded changes made at the historical position.
Reference: src/core/wu-timeline.js.
wu.timeline.stepBack
Moves back one journal position.
wu.timeline.stepBack(): Promise<WuTimelineStatus>
- Parameters: No arguments.
- Returns: Promise
- Errors: The asynchronous family may reject chunk, format, or materialization errors.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: stop releases capture when the session ends.
await wu.timeline.stepBack();
Limited to the recorder’s reproducible projections.
Reference: src/core/wu-timeline.js.
wu.timeline.stepForward
Moves forward one journal position.
wu.timeline.stepForward(): Promise<WuTimelineStatus>
- Parameters: No arguments.
- Returns: Promise
- Errors: The asynchronous family may reject chunk, format, or materialization errors.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: stop releases capture when the session ends.
await wu.timeline.stepForward();
Does not replay an action’s external effects.
Reference: src/core/wu-timeline.js.
wu.timeline.export
Serializes entries, snapshots, and the app baseline.
wu.timeline.export(): Promise<WuTimelineExport>
- Parameters: No arguments.
- Returns: Promise
- Errors: The asynchronous family may reject chunk, format, or materialization errors.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: The host decides where to save/export the object.
const journal = await wu.timeline.export();
May contain application state; not an automatic durable audit.
Reference: src/core/wu-timeline.js.
wu.timeline.import
Loads a serialized journal for inspection.
wu.timeline.import(journal: WuTimelineExport): Promise<WuTimelineStatus>
- Parameters: Compatible export object.
- Returns: Promise
- Errors: The asynchronous family may reject chunk, format, or materialization errors.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Affects the recorder; explicitly choose the subsequent projection.
await wu.timeline.import(journal);
Validate state provenance; importing does not execute a remote sandbox.
Reference: src/core/wu-timeline.js.
wu.timeline.ingest
Merges entries using journal order and a shared empty baseline.
wu.timeline.ingest(entries: WuTimelineEntry[]): Promise<WuTimelineStatus>
- Parameters: Entries with Lamport clock and site identity.
- Returns: Promise
- Errors: The asynchronous family may reject chunk, format, or materialization errors.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Does not open or authenticate transport.
await wu.timeline.ingest(remoteEntries);
Merging does not itself materialize all UI state; it requires a shared baseline and projection rules.
Reference: src/core/wu-timeline.js.
wu.timeline.entries
Reads entries retained by the recorder.
wu.timeline.entries(): WuTimelineEntry[]
- Parameters: No arguments.
- Returns: WuTimelineEntry[]
- Errors: The asynchronous family may reject chunk, format, or materialization errors.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Installs no resources.
console.table(wu.timeline.entries());
The array is shallow-copied; do not use it to mutate the recorder.
Reference: src/core/wu-timeline.js.
wu.timeline.status
Queries capture, position, clocks, and used capacity.
wu.timeline.status(): WuTimelineStatus
- Parameters: No arguments.
- Returns: WuTimelineStatus
- Errors: The asynchronous family may reject chunk, format, or materialization errors.
- Permissions: Host; the scoped facade does not expose global administration.
- Cleanup: Installs no resources.
console.log(wu.timeline.status());
loaded indicates whether the chunk is available; it does not guarantee recording is active.
Reference: src/core/wu-timeline.js.