# @equinor/fusion-framework-module-context 中文文档

规范地址：https://npmcn.com/package/%40equinor/fusion-framework-module-context/

版本：9\.1\.0
npm 元数据更新时间：2026-11-12T09:58:07.554Z
中文译文更新时间：2026-11-13T20:11:20.867Z
软件包许可：ISC

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40equinor/fusion-framework-module-context
原文对照：https://npmcn.com/package/%40equinor/fusion-framework-module-context/?lang=original
源码仓库：https://github.com/equinor/fusion-framework

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：705 kB，103 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：2 个
- peer 依赖：rxjs ^7\.0\.0，semver ^7\.0\.0，@types/semver ^7\.0\.0，@faker-js/faker ^10\.1\.0，@equinor/fusion-framework-module ^6\.2\.0，@equinor/fusion-framework-module-telemetry ^8\.0\.0
- 首次发布：2022-10-26T12:18:57.874Z
- 最新版本发布：2026-11-12T09:58:07.059Z
- 近 30 天下载量：14276（2026-10-14 至 2026-11-12，npm 官方下载统计）
- 已发布版本数：195（近 12 个月 17 个）

## 中文简介

暂无中文简介

## 安装

```sh
npm install @equinor/fusion-framework-module-context
```

也可以使用：`pnpm add @equinor/fusion-framework-module-context`、`yarn add @equinor/fusion-framework-module-context`、`bun add @equinor/fusion-framework-module-context`

## README

# @ equinor/ 组合- 框架- 模块- 文本

融合框架的背景模块。 管理基于Fusion的应用程序和门户网站中的活性上下文(项目,设施,合同等),提供查询,验证,解析,以及从框出父子同步.

## 何时使用

当您的应用程序或门户需要时使用此模块:

-   设置、 读取或清除活性上下文( 如选择工程)
-   搜索和过滤 Fusion 上下文 API 中可用的上下文项目
-   验证某一上下文项目是否匹配允许的上下文类型
-   跨越父子提供方边界的解析上下文(门户网站 )
-   通过从 URL 路径取出上下文ID来进行深链接

> **应用程序开发者** 通常使用高级 `@equinor/fusion-framework-react-app/context` 包件, 包到底 模块带有反应钩和提供者.
> 
> **门户开发者** 将使用 `@equinor/fusion-framework-react/context` 在门户一级也是为了同样的目的.

## 如何融为一体

一个上下文模块从不孤立地生活。 这取决于 `@equinor/fusion-framework-module-services` 用于默认 HTTP 客户端的模块,可选 用途 `@equinor/fusion-framework-module-event` 发送和聆听背景变化事件, 并选择通过 `@equinor/fusion-framework-module-navigation` 改为 从路径中解决上下文。 这些不需要人工设置—— `enableContext` 需求 仅限 `services`· ; `event` 财务报告和审定财务报表 `navigation` 当您到场时会自动拾取.

模块也是 **默认的层次意识**: 当一个门户网站和一个App同时启用时 上下文, App 实例自动连接到 Portal 上下文 —— 除了两侧启用模块外,不需要接线。 见 [生命周期](https://npmcn.com/package/%40equinor/fusion-framework-module-context/docs/lifecycle.md#parentchild-propagation) 确切的说,同步是如何工作的 当它可以被推翻或致残.

## 文档

| 专题 | 说明 |
| --- | --- |
| [数据模型](https://npmcn.com/package/%40equinor/fusion-framework-module-context/docs/data-model.md) | 形状 `ContextItem`,上下文类型如何相互联系,以及查询/相关参数 |
| [生命周期](https://npmcn.com/package/%40equinor/fusion-framework-module-context/docs/lifecycle.md) | `setCurrentContext`校验/解析决定流程、启动时自动初始文本解析以及父/子背景传播 |
| [食谱](https://npmcn.com/package/%40equinor/fusion-framework-module-context/docs/recipes.md) | OData 查询参数、 路径重写、 接受上下文类型家族以及自定义搜索错误 |

## 关键概念

| 概念 | 说明 |
| --- | --- |
| **背景项目** | 代表单个上下文实体(项目,设施等)的打出的记录. |
| **提供背景** | 运行时服务曝光查询,设置,验证,解析,以及事件API. |
| **背景模块配置器** | 流利地用于配置上下文类型,过滤器,客户端和钩子. |
| **启用内容** | 在模块配置器上注册模块的助手. |
| **背景决议** | 当上下文类型不符合所配置的类型时,自动查找相关上下文项目. |
| **父连接** | 双向同步介于父端门户上下文和子端应用上下文之间. |

## 快开始

```ts
import { enableContext } from '@equinor/fusion-framework-module-context';

export const configure = (configurator) => {
  enableContext(configurator, (builder) => {
    // only accept ProjectMaster context items
    builder.setContextType(['ProjectMaster']);
  });
};
```

初始化后, 从模块实例中访问提供者 :

```ts
// observe context changes
modules.context.currentContext$.subscribe((ctx) => {
  console.log('context changed', ctx);
});

// search for context items
const items = await modules.context.queryContextAsync('Johan');

// set context by item
await modules.context.setCurrentContextAsync(items[0]);

// set context by ID
await modules.context.setCurrentContextByIdAsync('7fd97952-...');

// clear the active context
modules.context.clearCurrentContext();
```

## 操作遥测

`IContextProvider` 扩展 `TelemetryConnectable`。供应商使用 `telemetry.scope('context')`回到了懒惰的工厂 以古老的习俗 提供商,并关闭处置的共享手柄; 选择/分辨率观察仍保留在上下文模块中.

当主机注册遥测时, 每个队列 `setCurrentContext` 任务报告1 `fusion.context.select.duration` 结果。 每一份决议尝试报告 `fusion.context.resolve.duration`,无论来自选择,一个直接 `resolveContext`编号 :`resolveContextAsync` 调用或配置的解析器( n)`by: 'item'`),或 从后面的搜索 `setCurrentContextById` (单位:千美元)`by: 'id'`:

-   `failure` 有理无据 `validation` 验证失败而解析被禁;
-   `cancelled` 有理无据 `listener` 当 `onSetContextResolve`, (中文(简体) ), `onSetContextResolved` 或者说 `onCurrentContextChange` 听众的电话 `preventDefault()`· ;
-   `cancelled` 当更新的任务取代任务时,调用者不订阅,或者 处理供应商(理由 `disposed`) (中文(简体) ).

未验证的重设当前项目被跳过, 并且没有报告 . 背景标识,标题和值从不导出,背景行为不变. 同步解析器工厂故障记录并同步重投, 不包含 更改错误对象。 最终 `onCurrentContextChange` 否决权记录的取消 即刻,包括现有的去除-误差路径;遥测不改变 这条路的呼叫者行为. 见 [操作遥测](https://npmcn.com/package/%40equinor/telemetry/docs/operational-telemetry.md)。 。 。 .

## 配置

所有配置流经 `enableContext` → `ContextModuleConfigurator`数字 :

```ts
enableContext(configurator, (builder) => {
  // restrict accepted context types
  builder.setContextType(['ProjectMaster', 'Facility']);

  // post-query filter
  builder.setContextFilter((items) => items.filter((i) => i.isActive));

  // custom parameter mapping for the search API
  builder.setContextParameterFn(({ search, type }) => ({
    search,
    filter: { type },
  }));

  // custom validation logic
  builder.setValidateContext(function (item) {
    return item !== null && this.validateContext(item);
  });

  // custom context resolution
  builder.setResolveContext(function (item) {
    return this.relatedContexts({ item, filter: { type: ['ProjectMaster'] } });
  });

  // connect (or disconnect) from parent context
  // when enabled (default), onParentContextChanged fires before mirroring the parent's context locally
  builder.connectParentContext(false);

  // path ↔ context integration
  // the default resolver uses extractContextIdFromPath to pull a GUID from the URL,
  // then fetches the matching context item — see resolveInitialContext in utils
  builder.setContextPathExtractor((path) => path.split('/')[2]);
  builder.setContextPathGenerator((ctx, path) =>
    path.replace(/\/context\/[^/]+/, `/context/${ctx.id}`),
  );

  // provide a fully custom context client
  builder.setContextClient({
    get: (args) => fetch(`/api/context/${args.id}`).then((r) => r.json()),
    query: (args) => fetch(`/api/context?q=${args.search}`).then((r) => r.json()),
  });
});
```

### 配置参考

| 构建方法 | 目的 |
| --- | --- |
| `setContextType(types)` | 用于验证的上下文类型ID |
| `setContextFilter(fn)` | 冲洗后结果过滤器 |
| `setContextParameterFn(fn)` | 地图搜索 + 类型到 API 查询参数 |
| `setValidateContext(fn)` | 自定义验证( O)`this` = 供应商) |
| `setResolveContext(fn)` | 自定义分辨率( O)`this` = 供应商) |
| `connectParentContext(bool)` | 启用/ 残疾父上下文同步( 火) `onParentContextChanged` 页:1 |
| `setContextPathExtractor(fn)` | 从 URL 路径提取上下文 ID |
| `setContextPathGenerator(fn)` | 从上下文项目生成 URL 路径 |
| `setResolveInitialContext(fn)` | 覆盖初始上下文解析度( 默认使用) `extractContextIdFromPath` → `resolveContextFromPath`(中文(简体) ) |
| `setContextClient(client)` | 自定义获取/取用/相关客户端 |

## URL 中的背景运行

门户网站将活动上下文自动与浏览器 URL同步 通过 `@equinor/fusion-framework-plugin-context-navigation` 插件 。 作为应用 开发者,您控制 **怎么样** 上下文通过声明路径在您的 URL 中出现 在您的应用程序列表中的策略 .

### 宣布路线战略

设定 `contextRouting` 在你的清单 `build.options`数字 :

```jsonc
// app.manifest.config.ts
{
  "build": {
    "options": {
      "contextRouting": "query"
    }
  }
}
```

| 数值 | URL 形状 | 何时使用 |
| --- | --- | --- |
| `'path'` (或省略) | `/apps/{appKey}/{contextId}/sub-route` | 默认——没有复杂路径路径的简单应用程序 |
| `'query'` | `/apps/{appKey}/route?$contextId={id}` | 与上下文路径段相冲突的嵌入路线的应用程序 |

有自定义 URL 形状的应用程序可以省略 `contextRouting` 并登记自定义钩(见下文). 明确 `contextRouting: 'query'` 总是选择查询路由,即使注册了自定义钩.

> \[注\] 何时 `contextRouting` 未设定( 或设定为 `null`),门户默认为 **路径适配器** 将上下文编码为应用程序键后的一个路径段. 如果您的应用程序也注册自定义钩( I)`setContextPathExtractor` 编号 : `setContextPathGenerator`),自定义适配器优先于路径 用于路径路由或在没有宣布策略时的适配器。 明确 `contextRouting: 'query'` 选择查询适配器.

### 自定义URL形状

如果您的应用程序对上下文使用非标准的 URL 版式( 如. `/route-a/{contextId}`, (中文(简体) ), 注册自定义钩子而不是(或除此之外)声明 `contextRouting`数字 :

```ts
enableContext(configurator, (builder) => {
  builder.setContextType(['ProjectMaster']);

  // Tell the portal how to find the context id in your URL
  builder.setContextPathExtractor((path) => {
    const segments = path.split('/').filter(Boolean);
    return segments[1]; // e.g. /route-a/{contextId}
  });

  // Tell the portal how to build a URL with context
  builder.setContextPathGenerator((context, path) => {
    const segments = path.split('/').filter(Boolean);
    const route = segments[0] ?? '';
    return `/${route}/${context.id}`;
  });
});
```

这些钩子注册后,门户的自定义适配器会自动使用它们—— 没有 `contextRouting` 名单中需要声明.

### 如何运作(供参考)

门户的上下文导航插件读取 `contextRouting` 从你的应用软件 在运行时显示并选择适当的 URL 适配器。 你不安装 或自行配置插件——门户处理。 您的应用程序只需要 宣布其倾向.

## 活动

上下文模块通过 `@equinor/fusion-framework-module-event` 系统。 所有事件都属于 `ContextProvider` 来源.

| 活动 | 何时 | 可取消 |
| --- | --- | --- |
| `onCurrentContextChange` | 在更新当前上下文之前 | 对 |
| `onCurrentContextChanged` | 在当前环境发生变化后 | 没有 |
| `onParentContextChanged` | 在本地镜像父上下文更改之前 | 对 |
| `onSetContextResolve` | 在上下文解析开始前 | 对 |
| `onSetContextResolved` | 上下文解析完成后 | 对 |
| `onSetContextValidationFailed` | 当验证失败( 没有解析) | 没有 |
| `onSetContextResolveFailed` | 解析失败时出错 | 没有 |

```ts
modules.event.addEventListener('onCurrentContextChanged', (e) => {
  console.log('previous:', e.detail.previous);
  console.log('next:', e.detail.next);
});
```

## 错误

模块导出 `FusionContextSearchError` (从) `@equinor/fusion-framework-module-context/errors.js`与搜索有关的失败:

```ts
import { FusionContextSearchError } from '@equinor/fusion-framework-module-context/errors.js';

try {
  await modules.context.queryContextAsync('...');
} catch (err) {
  if (err instanceof FusionContextSearchError) {
    console.error(err.title, err.description);
  }
}
```

## 测试

`@equinor/fusion-framework-module-context/mock` 提供 `enableContextMock`,一个目的所建的测试双人由一串种子上下文项的内存支撑——没有上下文 API,没有HTTP模拟,不需要服务发现模拟. 真实 `ContextProvider` 行为`validateContext`, (中文(简体) ), `resolveContext`,父文本传播)仍然运行在种子数据上;只有数据源被替换.

### 默认

-   上下文池开始为空, 没有选择当前上下文 .
-   查询空池不返回项目 .
-   查找一个未种子的ID会抛出一个错误,将ID和种子方法命名.
-   关联的context lookup使用种子池,排除源项,并按所请求的类型过滤.
-   `setCurrentContext` 既种子项目,又选择初始应用分辨率; `setContexts` 只有种子项目.

```ts
import { enableContextMock } from '@equinor/fusion-framework-module-context/mock';

enableContextMock(configurator, (mock) => {
  mock.setCurrentContext({ id: 'my-ctx', type: { id: 'ProjectMaster' }, value: {} });
});
```

-   **友好层** —— 说 `setCurrentContext`, (中文(简体) ), `setContexts`, (中文(简体) ), `addContext`, (中文(简体) ), `setRelatedContexts` ——常见案例的上下文域词汇:种子一个已知项目,取回.
-   **逃逸舱门** —— 说 `setResolver` – 自定义的原始解析函数 `resolveContext` 策略或形状 友好层没有覆盖.

使用时 `@equinor/fusion-framework/mock`, (中文(简体) ), `FrameworkMockConfigurator.context` 返回相同的配置符,所以种子直接通过 `configurator.context` 不需要回电.

这是在测试中伪造上下文数据的两种方法之一. 另一个是直接嘲笑上下文 API的 HTTP 响应(与 `configurator.http.addMiddleware(...)`可选配对 `@equinor/fusion-framework-module-http/mock`是因为 `createOpenApiMockMiddleware` 用于直接从上下文的 OpenAPI spec 中获取的假冒数据 ) —— 用于练习真实 `ContextModuleConfigurator`/服务/HTTP管道,而不是取而代之. 到达 `enableContextMock` (d) 当试验需要覆盖管道本身时,HTTP中间器件的伸展范围。 用于实际种子数据的固定发电机(`createContextItemFactory`, (中文(简体) ), `createContextItems`可从下列网址获取: `@equinor/fusion-framework-module-context/mock/fixtures`。 。 。 .

### 生成决定性上下文定着

可选 `/mock/fixtures` 进入点用途 `@faker-js/faker` 产生现实但 可重复标题和可读标识。 仅在导入此切入点时安装 Faker .

```ts
import { enableContextMock } from '@equinor/fusion-framework-module-context/mock';
import { createContextItems } from '@equinor/fusion-framework-module-context/mock/fixtures';

const [project, contract] = createContextItems([
  { type: 'ProjectMaster' },
  { type: 'Contract', parentTypeIds: ['ProjectMaster'] },
]);

enableContextMock(configurator, (mock) => {
  mock.setContexts([project, contract]);
  mock.setCurrentContext(project);
});
```

使用 `createContextItemFactory(prefix?)` 用于一种类型的相继固定装置。 使用 `createContextItems` 用于多个类型和父/子类型元数据。 生成值为 确定/ id; 使用 `setRelatedContexts` 当每个特定项目的关系必须不同时.

## 公用事业

可向下列机构提供其他帮助: `@equinor/fusion-framework-module-context/utils`数字 :

| 导出 | 目的 |
| --- | --- |
| `enableContext` | 在配置器上注册上下文模块 |
| `resolveInitialContext` | 默认初始文本解析器( path ) – 父倒置) |
| `extractContextIdFromPath` | 从 URL 路径中提取一个 GUID 格式上下文 ID |
| `resolveContextFromPath` | 从 URL 路径获取上下文项的解析器函数 |

## 软件包出口

| 指定者 | 说明 |
| --- | --- |
| `@equinor/fusion-framework-module-context` | 主要条目——模块,提供者,配置器,类型 |
| `@equinor/fusion-framework-module-context/errors.js` | `FusionContextSearchError` |
| `@equinor/fusion-framework-module-context/utils` | 路径解析和启用的功能 |
| `@equinor/fusion-framework-module-context/mock` | `enableContextMock`, (中文(简体) ), `ContextMockConfigurator` - 模拟测试双倍 |
| `@equinor/fusion-framework-module-context/mock/fixtures` | 生产上下文种子的固定工厂 |

## 常见问题

### 如何安装 @equinor/fusion-framework-module-context？

在项目目录运行 npm install @equinor/fusion-framework-module-context，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：rxjs（^7\.0\.0）、semver（^7\.0\.0）、@types/semver（^7\.0\.0）、@equinor/fusion-framework-module（^6\.2\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @equinor/fusion-framework-module-context 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @equinor/fusion-framework-module-context 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @equinor/fusion-framework-module-context 可以商用吗？

@equinor/fusion-framework-module-context 使用 ISC 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @equinor/fusion-framework-module-context 的下载量有多少？

根据 npm 官方下载统计，@equinor/fusion-framework-module-context 在 2026/10/14 – 2026/11/12 这 30 天内被下载 14,276 次，日均约 476 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @equinor/fusion-framework-module-context 还在维护吗？

最新版本 9\.1\.0 发布于 2026/11/12（1 天前）；至今共发布 195 个版本，其中过去 12 个月发布了 17 个；首次发布于 2022/10/26。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

