@equinor/fusion-framework-vite-plugin-api-service

中文文档
3.0.1发布于 2026/11/12ISCTypeScriptES Module近 30 天下载 8533

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

中文使用文档
文档目录22 节
  1. 安装
  2. 快速启动
  3. 如何运作
  4. 服务发现流程
  5. 普通 API 请求流程
  6. 移动路线流
  7. 配置
  8. 插件选项
  9. 服务发现 createProxyHandler
  10. 添加服务器拥有的路由
  11. 合并代理路由和自定义路由
  12. 路线匹配 createRouteMatcher
  13. 路径参数
  14. 通关卡
  15. 多种图案
  16. 自定义匹配函数
  17. 迁移:路径到regexp v9
  18. 拦截器 createResponseInterceptor
  19. 类型安全转换
  20. API 参考
  21. 出口
  22. 类型

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

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

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

需要时使用此插件 :

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

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

安装

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

快速启动

// 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,
          };
        },
      ),
    }),
  ],
});

如何运作

服务发现流程

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. 修改后的服务列表被退回客户端.

代理响应 (上游):

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

插件响应 (致客户端):

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

普通 API 请求流程

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. 结果归客户端.

移动路线流

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. 如果没有中间软件路由匹配,则请求会通过代理路由或下一个中间软件.

配置

插件选项

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

服务发现 createProxyHandler

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

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 路线。 见 模拟服务指南。当 端点不是一个可以发现的服务模拟.

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。自定义路径在代理之前进行评估 服务:

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 路径并提取路径参数。 建造在 路径到备忘。 。 。 .

路径参数

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

通关卡

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

多种图案

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

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

自定义匹配函数

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

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

见 路径到记录的文档 用于完整的模式语法.

迁移:路径到regexp v9

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

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。 优先分开 当每个抓取有明确的含义时, 将路径及其调用者一起更新 :

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 无法更改, 请提供 自定义匹配函数 执行 您想要的解析和解码规则; v9 不恢复 v8 模糊的捕捉行为 自动。 参数分出部分的普通图案,例如 /users/:id进行 没有这种模糊性.

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

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

拦截器 createResponseInterceptor

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

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

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

类型安全转换

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 用于插件日志.
JsonDataJSON-可序列价值类型联盟.

版本与发布记录

@equinor/fusion-framework-vite-plugin-api-service 共发布 35 个版本,首次发布于 2025/05/27;过去 12 个月发布了 22 个版本。

版本发布日期距今
3.0.1latest2026/11/121 天前
3.0.1-next.0next2026/11/112 天前
3.0.02026/11/112 天前
2.1.22026/10/1727 天前
2.1.2-trusted-publishing-20261015-9dfe7602cd2a49a8a9df00d62c26e7304a82a85atrusted-publishing-202610152026/10/1629 天前
2.1.12026/10/1629 天前

其他发布通道:cli-search-index → 1.2.5-cli-search-index.0,msal-v5 → 1.2.5-msal-v5.0,trusted-publishing-20261015 → 2.1.2-trusted-publishing-20261015-9dfe7602cd2a49a8a9df00d62c26e7304a82a85a,next → 3.0.1-next.0。

关于 @equinor/fusion-framework-vite-plugin-api-service 的常见问题

@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 和提交记录判断。