# Hooks、插件与 timeline 参考

扩展生命周期、使用 grants 安装插件并控制时间投影，区分各自权限。

Hook 修改生命周期流程；插件组织 setup、权限和 cleanup；timeline 保留投影 journal。每种机制都有所属者和结束活动的方式。

<span id="interceptar-una-fase"></span>

<span class="section-anchor" id="section-1"></span>

## 拦截阶段

```js
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();
```

可用阶段是 Init、Load、Mount、Update、Unmount 和 Destroy 的 before/after。优先级越高越先执行。省略 `next()` 取消链；`failOpen: true` 允许中间件失败后继续。界面 guard 不能替代 core 角色控制或 grants。

<span id="conceder-autoridad-a-un-plugin"></span>

<span class="section-anchor" id="section-2"></span>

## 向插件授予权限

插件权限是 `mount`、`events`、`store`、`apps`、`config` 和 `unsafe`。插件申请这些名称，宿主安装时通过 `options.grants` 授予。不要把 `store.read` 或 `rpc.call` 用作插件 grants，它们属于应用契约。

依赖 setup 前，等待 `pluginSystem.use` 或 `pluginSystem.ready`。异步 factory 安装也参与启动过程。插件执行宿主代码；缩减 API 不会消除闭包已捕获的权限。

<span id="grabar-antes-de-escribir"></span>

<span class="section-anchor" id="section-3"></span>

## 先记录，再写入

```js
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();
```

`wu.timeline` facade 保留可链式调用的方法用于同步控制。`timelineReady` 返回的真实对象具有不同返回值；本参考示例使用 facade。Seek 按选项重新生成 store、props 和组合，不回退网络、timer 或基础设施。

<span class="section-anchor" id="section-4"></span>

## wu.hooks.use

安装带优先级和独立清理的生命周期中间件。

`wu.hooks.use(phase, middleware, options?): () => void`

- **参数：** 有效阶段、middleware(context,next)；options：name、priority、failOpen。
- **返回值：** 取消函数；TypeScript 声明为 void。
- **错误：** 未知阶段或无效回调会抛出；省略 next 取消链。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** stop() 只移除此中间件。

```js
const stop = wu.hooks.use('beforeMount', async (context, next) => {
  console.log(context.appName);
  await next();
}, { name: 'mount-log', priority: 10 });
```

参考：`src/core/wu-hooks.js`.

<span class="section-anchor" id="section-5"></span>

## wu.hooks.useMultiple

将同一中间件安装到多个阶段。

`wu.hooks.useMultiple(phases, middleware, options?): () => void`

- **参数：** 阶段数组；使用稳定 name 标识各派生注册。
- **返回值：** 组合 cleanup。
- **错误：** 每个阶段必须存在；后续阶段失败时，注册并非原子操作。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** stop() 移除本次创建的安装。

```js
const stop = wu.hooks.useMultiple(['beforeMount', 'beforeUnmount'], async (ctx, next) => {
  await next();
}, { name: 'trace' });
```

参考：`src/core/wu-hooks.js`.

<span class="section-anchor" id="section-6"></span>

## wu.hooks.remove

按阶段和名称移除中间件。

`wu.hooks.remove(phase, name): void`

- **参数：** phase 和注册 name。
- **返回值：** void；不存在时不抛出。
- **错误：** 重复名称会使移除存在歧义，优先使用独立 cleanup。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 不安装新资源。

```js
wu.hooks.remove('beforeMount', 'mount-log');
```

参考：`src/core/wu-hooks.js`.

<span class="section-anchor" id="section-7"></span>

## wu.hooks.getHooks

查询已安装中间件元数据。

`wu.hooks.getHooks(phase?): object | object[]`

- **参数：** 可选阶段。
- **返回值：** 无阶段时返回元数据映射，有阶段时返回注册数组。
- **错误：** 指定阶段会返回内部记录；不要通过修改它们配置 API。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 不安装新资源。

```js
console.log(wu.hooks.getHooks());
```

参考：`src/core/wu-hooks.js`.

<span class="section-anchor" id="section-8"></span>

## wu.hooks.getStats

查询 hooks 分布和执行记录。

`wu.hooks.getStats(): object`

- **参数：** 无参数。
- **返回值：** 指标对象。
- **错误：** 执行日志容量有限。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 不安装新资源。

```js
console.log(wu.hooks.getStats());
```

参考：`src/core/wu-hooks.js`.

<span class="section-anchor" id="section-9"></span>

## wu.hooks.cleanup

移除一个或全部阶段的中间件。

`wu.hooks.cleanup(phase?): void`

- **参数：** 可选阶段；省略时还清空执行日志。
- **返回值：** void。
- **错误：** 不会自行取消已在执行的回调。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 释放注册；回调创建的资源需要自己的 cleanup。

```js
wu.hooks.cleanup('beforeMount');
```

参考：`src/core/wu-hooks.js`.

<span class="section-anchor" id="section-10"></span>

## createSimpleHook

将回调转换为继续执行链的中间件。

`createSimpleHook(fn): Function`

- **参数：** fn(context) 可以是异步函数。
- **返回值：** async(context,next) 中间件。
- **错误：** 回调错误遵循 factory 和链的策略。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 用 hooks.use 安装，并保存该注册的 cleanup。

```js
import { createSimpleHook } from 'wu-framework';
const middleware = createSimpleHook(ctx => console.log(ctx.appName));
```

等待回调后再调用 next。

参考：`src/core/wu-hooks.js`.

<span class="section-anchor" id="section-11"></span>

## createConditionalHook

条件为真时执行回调，然后继续。

`createConditionalHook(condition, fn): Function`

- **参数：** condition(context) 和 fn(context)。
- **返回值：** async(context,next) 中间件。
- **错误：** 回调错误遵循 factory 和链的策略。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 用 hooks.use 安装，并保存该注册的 cleanup。

```js
import { createConditionalHook } from 'wu-framework';
const middleware = createConditionalHook(ctx => ctx.appName === 'catalog', ctx => console.log(ctx));
```

条件不是取消 guard；条件为假时仍继续执行链。

参考：`src/core/wu-hooks.js`.

<span class="section-anchor" id="section-12"></span>

## createGuardHook

只有 guard 允许时才继续执行链。

`createGuardHook(shouldContinue): Function`

- **参数：** shouldContinue(context)，同步值或 Promise。
- **返回值：** async(context,next) 中间件。
- **错误：** 回调错误遵循 factory 和链的策略。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 用 hooks.use 安装，并保存该注册的 cleanup。

```js
import { createGuardHook } from 'wu-framework';
const middleware = createGuardHook(ctx => ctx.appName !== 'disabled-app');
```

返回 false 时不调用 next；不能替代 grants 或服务器授权。

参考：`src/core/wu-hooks.js`.

<span class="section-anchor" id="section-13"></span>

## createTransformHook

转换传给下一中间件的上下文。

`createTransformHook(transformer): Function`

- **参数：** transformer(context) 返回上下文数据。
- **返回值：** async(context,next) 中间件。
- **错误：** 回调错误遵循 factory 和链的策略。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 用 hooks.use 安装，并保存该注册的 cleanup。

```js
import { createTransformHook } from 'wu-framework';
const middleware = createTransformHook(ctx => ({ ...ctx, traceLabel: 'catalog' }));
```

不等同于配置该生命周期实际读取字段之外的 core。

参考：`src/core/wu-hooks.js`.

<span class="section-anchor" id="section-14"></span>

## createTimedHook

限制中间件等待回调的时间。

`createTimedHook(fn, timeout?: number): Function`

- **参数：** fn(context)；默认超时 5000 ms。
- **返回值：** async(context,next) 中间件。
- **错误：** 回调错误遵循 factory 和链的策略。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 用 hooks.use 安装，并保存该注册的 cleanup。

```js
import { createTimedHook } from 'wu-framework';
const middleware = createTimedHook(async ctx => console.log(ctx.appName), 1000);
```

失败或超时会记录日志并继续链；原始工作不会自动中止。

参考：`src/core/wu-hooks.js`.

<span class="section-anchor" id="section-15"></span>

## createPlugin

创建包含名称、权限申请和回调的插件。

`createPlugin(config): WuPlugin`

- **参数：** 含 name 的 config；install/uninstall 和 hooks 可选。
- **返回值：** 插件对象；创建不等于安装。
- **错误：** 无效名称或配置可能抛出。
- **权限：** 插件申请权限，宿主调用 use 时授予。
- **清理：** 用 pluginSystem.use 安装，用 uninstall 移除。

```js
import { createPlugin } from 'wu-framework';
const plugin = createPlugin({ name: 'catalog-observer', permissions: ['events'], install(api) { console.log(api.version); } });
```

参考：`src/core/wu-plugin.js`.

<span class="section-anchor" id="section-16"></span>

## wu.pluginSystem.use

安装插件并等待 setup 完成后才将其视为可用。

`wu.pluginSystem.use(pluginOrFactory, options?): Promise<boolean>`

- **参数：** 插件或 async factory；options.grants 和 compatibility 配置权限。
- **返回值：** 安装完成返回 true；验证/setup 失败时拒绝。
- **错误：** 所需权限未获 grants、重复注册或 install 错误可能导致拒绝。
- **权限：** 插件权限为 mount、events、store、apps、config、unsafe，与应用 capabilities 不同。
- **清理：** await uninstall(name) 撤销 API 并执行 cleanup。

```js
await wu.pluginSystem.use({
  name: 'catalog-observer', permissions: ['events'],
  install(api) { console.log(api.version); },
}, { grants: ['events'] });
```

参考：`src/core/wu-plugin.js`.

<span class="section-anchor" id="section-17"></span>

## wu.pluginSystem.ready

等待待完成安装，并向启动过程报告失败。

`wu.pluginSystem.ready(): Promise<boolean>`

- **参数：** 无参数。
- **返回值：** 成功完成时为 true。
- **错误：** 以首个待报告错误拒绝，并包含 pendingPluginErrors。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 不卸载成功的插件。

```js
await wu.pluginSystem.ready();
```

参考：`src/core/wu-plugin.js`.

<span class="section-anchor" id="section-18"></span>

## wu.pluginSystem.uninstall

移除插件及其关联权限。

`wu.pluginSystem.uninstall(name): Promise<boolean>`

- **参数：** 精确插件名称。
- **返回值：** 表示卸载结果的布尔值。
- **错误：** Uninstall 可能失败；请查看错误与诊断。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 调用 uninstall hook，并释放插件所属 hooks/listeners。

```js
await wu.pluginSystem.uninstall('catalog-observer');
```

参考：`src/core/wu-plugin.js`.

<span class="section-anchor" id="section-19"></span>

## wu.pluginSystem.getPlugin

查询已安装插件的定义。

`wu.pluginSystem.getPlugin(name): WuPlugin | undefined`

- **参数：** 精确名称。
- **返回值：** 插件或 undefined。
- **错误：** 安装完成前不存在。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 不安装新资源。

```js
console.log(wu.pluginSystem.getPlugin('catalog-observer')?.name);
```

参考：`src/core/wu-plugin.js`.

<span class="section-anchor" id="section-20"></span>

## wu.pluginSystem.getStats

列出插件、已授予权限和活动 hooks。

`wu.pluginSystem.getStats(): object`

- **参数：** 无参数。
- **返回值：** 包含 totalPlugins、plugins 和 hooks 的对象。
- **错误：** 不验证插件外部副作用。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 不安装新资源。

```js
console.log(wu.pluginSystem.getStats());
```

参考：`src/core/wu-plugin.js`.

<span class="section-anchor" id="section-21"></span>

## wu.pluginSystem.cleanup

卸载系统全部插件。

`wu.pluginSystem.cleanup(): Promise<void>`

- **参数：** 无参数。
- **返回值：** 卸载遍历完成后的 Promise。
- **错误：** 失败遵循 uninstall 约定。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 影响所有插件，属于宿主 teardown。

```js
await wu.pluginSystem.cleanup();
```

参考：`src/core/wu-plugin.js`.

<span class="section-anchor" id="section-22"></span>

## wu.timelineReady

在需要捕获的首次写入前加载 recorder。

`wu.timelineReady(): Promise<unknown>`

- **参数：** 无参数。
- **返回值：** recorder 真实实例，不是可链式调用的 facade。
- **错误：** chunk 下载或导入错误会拒绝。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** wu.timeline.stop() 移除观察者；clear 重置 journal。

```js
await wu.timelineReady();
wu.timeline.record();
```

参考：`src/index.js`.

<span class="section-anchor" id="section-23"></span>

## wu.timeline.record

从当前状态和应用开始 journal。

`wu.timeline.record(options?: { snapshotEvery?: number; maxEntries?: number }): WuTimelineFacade`

- **参数：** 可选快照频率和条目上限。
- **返回值：** WuTimelineFacade
- **错误：** 异步方法可能因 chunk、格式或重建错误而拒绝。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** stop() 移除 taps。

```js
await wu.timelineReady();
wu.timeline.record({ snapshotEvery: 25, maxEntries: 500 });
```

facade 返回自身，真实 recorder 返回 status。未调用 timelineReady 时，延迟加载可能丢失初始写入。

参考：`src/core/wu-timeline.js`.

<span class="section-anchor" id="section-24"></span>

## wu.timeline.stop

停止捕获，保留 journal 供检查。

`wu.timeline.stop(): WuTimelineFacade`

- **参数：** 无参数。
- **返回值：** WuTimelineFacade
- **错误：** 异步方法可能因 chunk、格式或重建错误而拒绝。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 移除 store 和总线的 taps。

```js
wu.timeline.stop();
```

不停止应用创建的 timers、requests 或进程。

参考：`src/core/wu-timeline.js`.

<span class="section-anchor" id="section-25"></span>

## wu.timeline.clear

清空 journal，将当前情况作为新 baseline。

`wu.timeline.clear(): WuTimelineFacade`

- **参数：** 无参数。
- **返回值：** WuTimelineFacade
- **错误：** 异步方法可能因 chunk、格式或重建错误而拒绝。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 想停止记录时，不能用它替代 stop。

```js
wu.timeline.clear();
```

不删除业务状态，也不撤销外部副作用。

参考：`src/core/wu-timeline.js`.

<span class="section-anchor" id="section-26"></span>

## wu.timeline.seek

将 journal 某个位置重建为对应投影。

`wu.timeline.seek(position: number, options?: { store?: boolean; apps?: boolean; props?: boolean }): Promise<WuTimelineStatus>`

- **参数：** 索引 0..length；选择 store/apps/props。
- **返回值：** Promise<WuTimelineStatus>
- **错误：** 异步方法可能因 chunk、格式或重建错误而拒绝。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 返回 live 以恢复最终位置。

```js
const status = await wu.timeline.seek(0, { store: true, apps: false, props: false });
```

不回退 HTTP、timers 或基础设施。在过去位置写入不会创建新分支。

参考：`src/core/wu-timeline.js`.

<span class="section-anchor" id="section-27"></span>

## wu.timeline.live

重建 journal 末尾状态。

`wu.timeline.live(): Promise<WuTimelineStatus>`

- **参数：** 无参数。
- **返回值：** Promise<WuTimelineStatus>
- **错误：** 异步方法可能因 chunk、格式或重建错误而拒绝。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** recorder 保留至 stop。

```js
await wu.timeline.live();
```

返回 live 会丢弃历史位置期间未记录的变更。

参考：`src/core/wu-timeline.js`.

<span class="section-anchor" id="section-28"></span>

## wu.timeline.stepBack

在 journal 中后退一个位置。

`wu.timeline.stepBack(): Promise<WuTimelineStatus>`

- **参数：** 无参数。
- **返回值：** Promise<WuTimelineStatus>
- **错误：** 异步方法可能因 chunk、格式或重建错误而拒绝。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 会话结束时，stop 释放捕获。

```js
await wu.timeline.stepBack();
```

仅限 recorder 可重现的投影。

参考：`src/core/wu-timeline.js`.

<span class="section-anchor" id="section-29"></span>

## wu.timeline.stepForward

在 journal 中前进一个位置。

`wu.timeline.stepForward(): Promise<WuTimelineStatus>`

- **参数：** 无参数。
- **返回值：** Promise<WuTimelineStatus>
- **错误：** 异步方法可能因 chunk、格式或重建错误而拒绝。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 会话结束时，stop 释放捕获。

```js
await wu.timeline.stepForward();
```

不重放 action 的外部副作用。

参考：`src/core/wu-timeline.js`.

<span class="section-anchor" id="section-30"></span>

## wu.timeline.export

序列化条目、快照和应用 baseline。

`wu.timeline.export(): Promise<WuTimelineExport>`

- **参数：** 无参数。
- **返回值：** Promise<WuTimelineExport>
- **错误：** 异步方法可能因 chunk、格式或重建错误而拒绝。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 宿主决定对象的保存或导出位置。

```js
const journal = await wu.timeline.export();
```

可能包含应用状态，不是自动持久审计。

参考：`src/core/wu-timeline.js`.

<span class="section-anchor" id="section-31"></span>

## wu.timeline.import

加载序列化 journal 供检查。

`wu.timeline.import(journal: WuTimelineExport): Promise<WuTimelineStatus>`

- **参数：** 兼容的 export 对象。
- **返回值：** Promise<WuTimelineStatus>
- **错误：** 异步方法可能因 chunk、格式或重建错误而拒绝。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 影响 recorder；后续投影需显式选择。

```js
await wu.timeline.import(journal);
```

验证状态来源；导入不会运行远程沙箱。

参考：`src/core/wu-timeline.js`.

<span class="section-anchor" id="section-32"></span>

## wu.timeline.ingest

依据 journal 顺序合并条目，使用共同的空 baseline。

`wu.timeline.ingest(entries: WuTimelineEntry[]): Promise<WuTimelineStatus>`

- **参数：** 带 Lamport 时钟和站点身份的条目。
- **返回值：** Promise<WuTimelineStatus>
- **错误：** 异步方法可能因 chunk、格式或重建错误而拒绝。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 不打开或认证传输通道。

```js
await wu.timeline.ingest(remoteEntries);
```

合并本身不会把全部状态呈现在 UI 中；需要共同基础和投影规则。

参考：`src/core/wu-timeline.js`.

<span class="section-anchor" id="section-33"></span>

## wu.timeline.entries

读取 recorder 保留的条目。

`wu.timeline.entries(): WuTimelineEntry[]`

- **参数：** 无参数。
- **返回值：** WuTimelineEntry[]
- **错误：** 异步方法可能因 chunk、格式或重建错误而拒绝。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 不安装资源。

```js
console.table(wu.timeline.entries());
```

数组为浅复制，不要通过它修改 recorder。

参考：`src/core/wu-timeline.js`.

<span class="section-anchor" id="section-34"></span>

## wu.timeline.status

查询捕获状态、位置、时钟和已用容量。

`wu.timeline.status(): WuTimelineStatus`

- **参数：** 无参数。
- **返回值：** WuTimelineStatus
- **错误：** 异步方法可能因 chunk、格式或重建错误而拒绝。
- **权限：** 宿主；scoped facade 不暴露全局管理。
- **清理：** 不安装资源。

```js
console.log(wu.timeline.status());
```

loaded 表示 chunk 是否可用，不保证正在记录。

参考：`src/core/wu-timeline.js`.