# @equinor/fusion-framework-vite-plugin-api-service 中文文档

规范地址：https://npmcn.com/package/%40equinor/fusion-framework-vite-plugin-api-service/

版本：3\.0\.1
npm 元数据更新时间：2026-11-12T09:54:00.959Z
中文译文更新时间：2026-11-13T20:28:24.418Z
软件包许可：ISC

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

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

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

- 包体积（解压后）：238 kB，40 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：3 个
- 首次发布：2025-05-27T15:14:47.658Z
- 最新版本发布：2026-11-12T09:54:00.713Z
- 近 30 天下载量：8533（2026-10-14 至 2026-11-12，npm 官方下载统计）
- 已发布版本数：35（近 12 个月 22 个）

## 中文简介

用于代理服务发现和嘲笑的 Vite 插件

## 安装

```sh
npm install @equinor/fusion-framework-vite-plugin-api-service
```

也可以使用：`pnpm add @equinor/fusion-framework-vite-plugin-api-service`、`yarn add @equinor/fusion-framework-vite-plugin-api-service`、`bun add @equinor/fusion-framework-vite-plugin-api-service`

## README

# @equinor/ inform-framework-vite-plugin-api-service (英语)

用于代理服务发现请求的 Vite 插件, 在 Fusion 中添加服务器拥有的路由 框架应用开发.

> \[TIP\] 应用程序服务模拟器属于可执行文件 `mocks/<service>.mock.ts` 模块创建 `defineService`见 [模拟服务指南](https://npmcn.com/package/dev-server/docs/mocking.md)。使用此软件包 路由 API 只有在建设开发基础设施或自定义 Vite 集成时直接使用.

需要时使用此插件 :

-   **与服务发现相结合** ——代理请求一个远程发现端点并重新映射服务URL到dev-server可以管理的本地路线.
-   **添加服务器自主响应** ——定义健康检查,召回或自定义主机行为的中间软件路径.
-   **拦截和改变对策** ——在到达客户端前修改代理响应有效载荷(规范数据,注入元数据等).

该插件是为Fusion Framew Dev Server生态系统而设计的,但在任何Vite项目中工作.

## 安装

```bash
pnpm add -D @equinor/fusion-framework-vite-plugin-api-service
```

## 快速启动

```ts
// vite.config.ts
import { defineConfig } from 'vite';
import apiServicePlugin, { createProxyHandler } from '@equinor/fusion-framework-vite-plugin-api-service';

export default defineConfig({
  plugins: [
    apiServicePlugin({
      proxyHandler: createProxyHandler(
        'https://discovery.example.com/services',
        (services, { route }) => {
          const routes = services.map((svc) => ({
            match: `/${svc.name}/*path`,
            proxy: {
              target: svc.url,
              rewrite: (p: string) => p.replace(`/${svc.name}`, ''),
            },
          }));
          return {
            data: services.map((svc) => ({ ...svc, uri: `${route}/${svc.name}` })),
            routes,
          };
        },
      ),
    }),
  ],
});
```

## 如何运作

### 服务发现流程

```mermaid
flowchart TD
    subgraph "Service Discovery Flow"
        SD1[Client] -->|Request /@fusion-services| SD2[Plugin]
        SD2 -->|Proxy request| SD3[Service Discovery Endpoint]
        SD3 -->|Return service data| SD2
        SD2 -->|Transform & remap services| SD4[Modified Service List]
        SD4 -->|Return to client| SD1
    end
```

1.  客户端请求服务列表(例如. `/@fusion-services`) (中文(简体) ).
2.  插件将请求代理到真实的服务发现端点.
3.  这个 `generateRoutes` 回调将每个服务 URL 映射到本地代理路径并注册路径 .
4.  修改后的服务列表被退回客户端.

**代理响应** (上游):

```json
[{ "id": "abc", "name": "apps", "url": "https://apps.prod.example.com/" }]
```

**插件响应** (致客户端):

```json
[{ "id": "abc", "name": "apps", "url": "/@fusion-api/apps" }]
```

### 普通 API 请求流程

```mermaid
flowchart TD
    subgraph "API Request Flow"
        API1[Client] -->|Request /@fusion-api/apps/all| API2[Plugin]
        API2 -->|Proxy request| API3[Real API Service]
        API3 -->|Response| API2
        API2 -->|Apply interceptors| API4[Processed Response]
        API4 -->|Return to client| API1
    end
```

1.  客户端通过代理URL(如. `/@fusion-api/apps/all`) (中文(简体) ).
2.  插件解决匹配的路由并代理请求到上游 URL.
3.  可选反应拦截器改变有效载荷.
4.  结果归客户端.

### 移动路线流

```mermaid
flowchart TD
    subgraph "Mock Route Flow"
        M1[Client] -->|Request| M2[Plugin]
        M2 -->|Check routes| M3{Mock exists?}
        M3 -->|Yes| M4[Return Mock Response]
        M3 -->|No| M5[Continue to Proxy / Next]
        M4 --> M1
    end
```

1.  客户端会提出匹配中间软件路径的请求.
2.  插件直接执行中间软件处理器,不代理.
3.  如果没有中间软件路由匹配,则请求会通过代理路由或下一个中间软件.

## 配置

### 插件选项

| 选项 | 类型 | 默认 | 说明 |
| --- | --- | --- | --- |
| `route` | `string` | `'/@fusion-api'` | 安装插件中间软件的基础路径 . |
| `process` | `ProcessRouteOptions` | —— 说 | 额外的路由处理选项(例如. `onProxyRes` 师曰. |
| `logger` | `PluginLogger` | —— 说 | 调试/info/warn/error消息的锁定器 。 过 `console` 快速调试. |
| `headers` | `Record<string, string>` | —— 说 | 标题添加到每一个代理的上游请求(服务发现和代理路线)中,例如用于识别dev-server流量. 一条路是自己的 `proxy.headers` 优先发言. |

### 服务发现 `createProxyHandler`

`createProxyHandler` 创建一个 `ApiProxyHandler` 并动态生成来自响应的代理路径.

```ts
import { createProxyHandler } from '@equinor/fusion-framework-vite-plugin-api-service';

const proxyHandler = createProxyHandler(
  // URL of the upstream service discovery endpoint
  'https://api.example.com/service-discovery',

  // Callback that processes the response and returns routes
  (responseData, { route, request }) => {
    const routes = responseData.services.map((service) => ({
      match: `/${service.name}/*path`,
      proxy: {
        target: service.url,
        rewrite: (path: string) => path.replace(`/${service.name}`, ''),
      },
    }));
    return {
      data: responseData,
      routes,
    };
  },

  // Optional configuration
  {
    route: '/@fusion-services',  // where discovery proxy is mounted (default)
    apiRoute: '/@fusion-api',    // base path for generated routes (default)
    proxyOptions: { changeOrigin: true, secure: false },
    logger: console,
  },
);

apiServicePlugin({ proxyHandler });
```

#### 响应缓存

`createProxyHandler` 缓存服务在内存中的发现响应, 因此一个浏览器标签卡被卡入了重载回路( Vite full reload, auth direct, crashing app) 无法淹没上游的发现 API :

-   成功反应被重新用于 **60秒钟**。原始的上游有效载荷被缓存,并在每次请求时通过您的处理器传递,因此依赖请求输出(例如,从源代码中创建的URI) `referer`保持正确的状态.
-   答复失败(状况) `>= 400`) 以相同的状态代码回答 **10 秒钟** 而不呼叫上游.
-   条目由 URL 和 散列 键入 `Authorization` 信头,所以一个新符号从未收到一个缓存到另一个的响应. 仅 `GET` 请求被缓存 .
-   缓存反应 `x-fusion-discovery-cache: hit` 头曰.

#### 锁上护身符

模拟认证问题未签名的令牌( Q)`alg: none`),真实的服务总是拒绝. 插件从不向公共主机转发携带这种标志的请求——无论是通过服务发现代理还是代理路线. 它会回答的 `401` 本地为 `x-fusion-dev-server-blocked: mock-token` 换句话说.

本地目标仍然被允许,因此模拟服务器和当地API继续工作: `localhost`, (中文(简体) ), `*.localhost`,单标签主机,如 Docker 编译服务(`http://api:8080`, (中文(简体) ), `*.local`, (中文(简体) ), `*.internal`范围.

### 添加服务器拥有的路由

定义开发主机拥有的端点的中间软件路径,例如健康检查和 基础设施召回:

> \[大 Fusion 应用程序服务模拟器应该使用可执行文件 `mocks/<service>.mock.ts` 模块 `defineService`,而不是手写 API-plugin 路线。 见 [模拟服务指南](https://npmcn.com/package/dev-server/docs/mocking.md)。当 端点不是一个可以发现的服务模拟.

```ts
apiServicePlugin({
  routes: [
    {
      match: '/health',
      middleware: (_req, res) => {
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ status: 'ok' }));
      },
    },
    {
      match: '/users/:userId',
      middleware: (req, res) => {
        const userId = req.params?.userId;
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ id: userId, name: 'Test User' }));
      },
    },
  ],
});
```

### 合并代理路由和自定义路由

两者都可以供应 `proxyHandler` 财务报告和审定财务报表 `routes`。自定义路径在代理之前进行评估 服务:

```ts
apiServicePlugin({
  proxyHandler,
  routes: [
    {
      match: '/apps/my-local-app',
      middleware: (_req, res) => {
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ appKey: 'my-local-app', version: 'dev' }));
      },
    },
  ],
});
```

## 路线匹配 `createRouteMatcher`

`createRouteMatcher` 创建匹配器函数,以对照模式测试 URL 路径并提取路径参数。 建造在 [路径到备忘](https://www.npmjs.com/package/path-to-regexp)。 。 。 .

### 路径参数

```ts
import { createRouteMatcher } from '@equinor/fusion-framework-vite-plugin-api-service';

const matcher = createRouteMatcher({ match: '/api/users/:userId/profile' });

matcher('/api/users/123/profile', req); // { params: { userId: '123' } }
matcher('/api/posts/123', req);         // false
```

### 通关卡

```ts
const serviceMatcher = createRouteMatcher({ match: '/api/services/:serviceName/*path' });
serviceMatcher('/api/services/auth/v1/token', req);
// { params: { serviceName: 'auth', path: [ 'v1', 'token' ] } }
```

### 多种图案

通过一系列图案来匹配其中的任何一种 :

```ts
const multiMatcher = createRouteMatcher({
  match: ['/api/v1/users/:id', '/api/v2/users/:id'],
  middleware: handler,
});
```

### 自定义匹配函数

对于高级逻辑,提供函数而不是字符串模式:

```ts
const customMatcher = createRouteMatcher({
  match: (path, req) => {
    if (path.startsWith('/api/custom') && req.method === 'GET') {
      return { params: { custom: path.substring(12) } };
    }
    return false;
  },
  middleware: handler,
});
```

见 [路径到记录的文档](https://www.npmjs.com/package/path-to-regexp) 用于完整的模式语法.

### 迁移:路径到regexp v9

此主要发行更改字符串模式匹配 `createRouteMatcher`,包括代理和 中间软件路线。 在同一段和处理器中有两个或两个以上参数的审查路线 在提升之前使用它们捕获的值.

```ts
const matcher = createRouteMatcher({
  match: '/:file.:ext',
  proxy: { target: 'http://localhost:3001' },
});

matcher('/foo.json.html', req);
// Before (v8): params = { file: 'foo.json', ext: 'html' }
// Now (v9):    params = { file: 'foo', ext: 'json.html' }
```

扩展检查, 如 `params.ext === 'html'` 不再识别此 URL。 优先分开 当每个抓取有明确的含义时, 将路径及其调用者一起更新 :

```ts
const matcher = createRouteMatcher({
  match: '/files/:file/extensions/:ext',
  proxy: { target: 'http://localhost:3001' },
});

matcher('/files/foo.json/extensions/html', req);
// params = { file: 'foo.json', ext: 'html' }
```

如果 URL 无法更改, 请提供 [自定义匹配函数](https://npmcn.com/package/%40equinor/fusion-framework-vite-plugin-api-service/#readme-custom-matcher-function) 执行 您想要的解析和解码规则; v9 不恢复 v8 模糊的捕捉行为 自动。 参数分出部分的普通图案,例如 `/users/:id`进行 没有这种模糊性.

明确斜线终止模式,例如 `/files/` 现在匹配 `/files/` 但没有 `/files//`。 。 。 . 将呼叫者规范到一个尾巴上 一种没有明显斜线的图案,例如 `/files`, (中文(简体) ), 还接受 `/files/` 在匹配者的默认选项下.

添加被点值的路由回归,被捕获参数,并跟踪斜线. 检查代理 重写和中间软件的决定以及路由是否匹配. 依赖性仅为无害环境管理 ,需要节点22或更新;此软件包使用其命名的 `match` 输出.

## 拦截器 `createResponseInterceptor`

`createResponseInterceptor` 截取了JSON代理响应,并在他们到达客户端之前进行改造. 非JSON回复和出错回复(status QQ 400)通过未受触动,带有其原始状态代码和头.

```ts
import { createResponseInterceptor } from '@equinor/fusion-framework-vite-plugin-api-service';

const interceptor = createResponseInterceptor(
  (data) => ({
    ...data,
    timestamp: new Date().toISOString(),
  }),
  { logger: console },
);
```

### 类型安全转换

```ts
interface OriginalResponse {
  items: string[];
  totalCount: number;
}

interface TransformedResponse {
  data: string[];
  metadata: { count: number; timestamp: string };
}

const typedInterceptor = createResponseInterceptor<OriginalResponse, TransformedResponse>(
  (response) => ({
    data: response.items,
    metadata: {
      count: response.totalCount,
      timestamp: new Date().toISOString(),
    },
  }),
);
```

> **说明:** 拦截器要求 `selfHandleResponse: true` 在代理配置上。 使用时自动设置 `createProxyHandler`。 。 。 .

## API 参考

### 出口

| 导出 | 说明 |
| --- | --- |
| `plugin` (默认) | Vite 插件厂- 通过 `PluginArguments` 和可选 `PluginOptions`。 。 。 . |
| `createProxyHandler` | 创建一个 `ApiProxyHandler` 服务发现代理. |
| `createRouteMatcher` | 从路由定义创建路径匹配器. |
| `createResponseInterceptor` | 为 JSON 转换创建代理响应截取器. |
| `DEFAULT_VALUES` | 带有默认路由路径的 Enum (`API_PATH`, (中文(简体) ), `SERVICES_PATH`) (中文(简体) ). |

### 类型

| 类型 | 说明 |
| --- | --- |
| `PluginArguments` | 插件厂的参数( R)`routes`, (中文(简体) ), `proxyHandler`) (中文(简体) ). |
| `PluginOptions` | 可选插件配置( N)`route`, (中文(简体) ), `process`, (中文(简体) ), `logger`) (中文(简体) ). |
| `ApiProxyHandler` | 代理处理器接口返回 `createProxyHandler`; 可选 `middleware` 成员在Vite 代理服务器之前应答请求 . |
| `ApiDataProcessor` | 回调类型,用于处理服务发现回复. |
| `ApiRoute` | 联盟 `MiddlewareRoute` 财务报告和审定财务报表 `ProxyRoute`。 。 。 . |
| `MiddlewareRoute` | 带有自定义中件处理器的路由定义 . |
| `ProxyRoute` | 路由定义可以代表远程目标. |
| `ApiRouteProxyOptions` | 代理配置选项 `ProxyRoute`。 。 。 . |
| `Matcher` | 路由匹配的函数类型 . |
| `MatchResult` | 返回类型 a `Matcher` —— 说 `boolean` 或者说 `{ params }`。 。 。 . |
| `PluginLogger` | 子集数 `Console` 用于插件日志. |
| `JsonData` | JSON-可序列价值类型联盟. |

## 常见问题

### @equinor/fusion-framework-vite-plugin-api-service 是什么？

用于代理服务发现和嘲笑的 Vite 插件

### 如何安装 @equinor/fusion-framework-vite-plugin-api-service？

在项目目录运行 npm install @equinor/fusion-framework-vite-plugin-api-service，或使用 pnpm add / yarn add / bun add。

### @equinor/fusion-framework-vite-plugin-api-service 支持 TypeScript 吗？

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

### @equinor/fusion-framework-vite-plugin-api-service 支持 ESM 还是 CommonJS？

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

### @equinor/fusion-framework-vite-plugin-api-service 可以商用吗？

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

### @equinor/fusion-framework-vite-plugin-api-service 的下载量有多少？

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

### @equinor/fusion-framework-vite-plugin-api-service 还在维护吗？

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

