@arrirpc/server

中文文档
0.85.0发布于 2026/10/03MITTypeScriptESM + CJS近 30 天下载 4493

字型执行 阿里·RPC它建在顶部 H3级 和用途 兴建 为捆绑.

中文使用文档
文档目录19 节
  1. 目录
  2. 快速启动
  3. 手动设置
  4. 安装依赖关系
  5. 脚手架您的工程
  6. 使用量
  7. 创建程序
  8. 添加非 RPC 路由
  9. 正在添加中间软件
  10. 背景工人和生命周期钩
  11. 添加客户端生成器
  12. 关键概念
  13. Arri 定义文件
  14. 如何将程序映射到终点
  15. H3 支助
  16. 阿里·CLI
  17. 发展
  18. 大楼
  19. 运行单元测试

Arri RPC - 字迹服务器

字型执行 阿里·RPC它建在顶部 H3级 和用途 兴建 为捆绑.

参数和反应的定义使用 @ arrirpc/ schema (韩语) 对投入和产出进行自动验证和序列化,并为客户发电机生成Arri类型定义.

目录

快速启动

# npm
npx arri init [project-name]
cd [project-name]
npm install
npm run dev

# pnpm
pnpm dlx arri init [project-name]
cd [project-name]
pnpm install
pnpm run dev

手动设置

安装依赖关系

# npm
npm install -D arri
npm install @arrirpc/server @arrirpc/schema

# pnpm
pnpm install -D arri
pnpm install @arrirpc/server @arrirpc/schema

脚手架您的工程

一个基本的Arri应用目录看起来是这样的:

|-- project-dir
    |-- .arri // temp files go here
    |-- .output // final bundle goes here
    |-- src
        |-- procedures // .rpc.ts files go here
        |-- app.ts
    |-- arri.config.ts
    |-- package.json
    |-- tsconfig.json
|

两者 .arri 财务报告和审定财务报表 .output 应添加到您的 .gitignore 文件

.arri
.output
node_modules

配置文件

创建一个 arri.config.ts 在项目目录中

// arri.config.ts
import { defineConfig, servers, generators } from 'arri';

export default defineConfig({
    server: servers.tsServer(),
    generators: [
        generators.typescriptClient({
            // options
        }),
        generators.dartClient({
            // options
        }),
    ],
});
App 条目

在您的 src 目录中创建应用程序条目文件 。 文件名称必须匹配您所显示的 entry 在你身边 arri.config.ts。 。 。 .

// ./src/app.ts
import { ArriApp } from 'arri';

const app = new ArriApp();

export default app;
软件包.json

设置 npm 脚本 :

{
    "name": "my-arri-app",
    "type": "module",
    "scripts": {
        "dev": "arri dev",
        "build": "arri build"
    },
    "dependencies": {
        ...
    },
    "devDependencies": {
        ...
    }
}

使用量

创建程序

基于文件的运行

ARRI RPC 带有一个基于文件的可选路由器,该路由器将在 ./procedures 以 .rpc.ts 文件扩展名.

|-- src
   |-- procedures
      |-- sayHello.rpc.ts // becomes sayHello()
      |-- users
          |-- getUser.rpc.ts // becomes users.getUser()
          |-- updateUser.rpc.ts // becomes users.updateUser()

示例 .rpc.ts 文件

// ./src/users/getUser.rpc.ts
import { defineRpc } from '@arrirpc/server';
import { a } from '@arrirpc/schema';

export default defineRpc({
    params: a.object({
        userId: a.string(),
    }),
    response: a.object({
        id: a.string(),
        name: a.string(),
        createdAt: a.timestamp(),
    }),
    handler({ params }) {
        // function body
    },
});
自定义基于文件的路由器
export default defineConfig({
    servers: servers.tsServer({
        procedureDir: 'procedures', // change which directory to look for procedures (This is relative to the srcDir)
        procedureGlobPatterns: ['**/*.rpc.ts'], // change the file name glob pattern for finding rpcs
    }),
    // rest of config
});

手动运行

对于那些想要选择退出基于文件的路由系统的人,您可以手动注册这样的程序.

// using the app instance
const app = new ArriApp()
app.rpc('sayHello',
    defineRpc({...})
);

// defining a service
const app = new ArriApp();
const usersService = defineService("users");
usersService.rpc("getUser", defineRpc({...}));
usersService.rpc("createUser", defineRpc({...}));

// register the service on the app instance
app.use(usersService);

还有一个简写,用于初始化 服务与程序

// this is equivalent to what we showed above
const usersService = defineService("users", {
    getUser: defineRpc({..}),
    createUser: defineRpc({..}),
});

创建事件流程序

活动流程程序利用 服务器已发送事件 将事件流到客户端.

Arri事件流发送了以下事件类型:

  • message - 以JSON为序列的响应数据的标准信息
  • start - 启动溪流的起始信息
  • done - 告诉客户 不会再发生任何事件
  • heartbeat - 服务器定期发送信息,以保持连接.
/// message event ///
id: string | undefined;
event: 'message';
data: Response; // whatever you have specified as the response serialized to json

/// done event ///
event: 'done';
data: 'this stream has ended';

/// heartbeat event ///
event: 'heartbeat';
data: '';
示例使用法:
// procedures/users/watchUser.rpc.ts
export default defineEventStreamRpc({
    params: a.object({
        userId: a.string(),
    }),
    response: a.object({
        id: a.string(),
        name: a.string(),
        createdAt: a.timestamp(),
        updatedAt: a.timestamp(),
    }),
    handler({ params, stream }) {
        // initialize the stream and send it to the client
        stream.send();

        // send a message every second
        const interval = setInterval(async () => {
            await stream.push({
                id: '1',
                name: 'John Doe',
                createdAt: new Date(),
                updatedAt: new Date(),
            });
        }, 1000);

        // cleanup when the client disconnects
        stream.on('close', () => {
            clearInterval(interval);
        });
    },
});

事件串联方法

// send the stream to the client. Must be called before pushing any messages
stream.send()
// push a new message to the client
stream.push(data: Data, eventId?: string)
// close the stream and tell the client that there will be no more messages
stream.close()
// register a callback that will fire after the stream has been close by the server or the connection has been dropped
stream.onClosed(cb: () => any)

添加非 RPC 路由

对于基于信件的 RPC 端点不符合的情况,也可以添加通用端点.

// using the app instance
const app = new ArriApp();
app.route({
    method: "get",
    path: "/hello-world",
    handler(event) {
        return "hello world";
    },
});

// using a sub-router
const app = new ArriApp();
const router = new ArriRouter();
router.route({
    method: "get",
    path: "/hello-world",
    handler(event) {
        return "hello world",
    }
})
app.use(router)

// sup-routers can also specify a route prefix
const router = new ArriRouter("/v1")
router.route({
    method: "get",
    path: "/hello-world", // this will become /v1/hello-world
    handler(event) {
        return "hello world"
    }
});

正在添加中间软件

const app = new ArriApp();

const requestLoggerMiddleware = defineMiddleware((event) => {
    console.log(`new request at ${event.path}`);
});

app.use(requestLoggerMiddleware);

添加到 RPC 背景

添加到任何数值 event.context 将在 rpc 实例中可用

const authMiddleware = defineMiddleware(async (event) => {
    // assume you did something to get the user from the request
    event.context.user = {
        id: 1,
        name: 'John Doe',
        email: '[email protected]',
    };
});

app.rpc('sayHello', {
    params: undefined,
    response: a.object({
        message: a.string(),
    }),
    // user is available here
    handler({ user }) {
        return {
            message: `Hello ${user.name}`,
        };
    },
});

要为这些新属性获得类型安全性 .d.ts 文档和增强 ArriEventContext 国家 @arrirpc/server

import '@arrirpc/server';

declare module '@arrirpc/server' {
    interface ArriEventContext {
        user?: {
            id: number;
            name: string;
            email: string;
        };
    }
}

背景工人和生命周期钩

您可以注册背景工人 和生命周期钩 ArriApp当应用程序在编码时导入时,工人和生命周期钩不运行(arri build);它们只在网页服务器开始收听时开始.

import { ArriApp, defineWorker } from '@arrirpc/server';

const app = new ArriApp({
    onStart() {
        console.log('Server is starting up');
    },
    onStop() {
        console.log('Server is shutting down');
    },
    onWorkerError(err, worker) {
        logger.error({ err, worker: worker.name }, 'Worker error');
    },
});

// Registering a worker with a continuous loop and AbortSignal
app.registerWorker(
    defineWorker({
        name: 'queue-consumer',
        async start(signal) {
            while (!signal.aborted) {
                const job = await queue.pop({ signal });
                if (job) await processJob(job);
            }
        },
        async stop() {
            // Optional: cleanup or drain
        },
    }),
);

// Registering a third-party worker (e.g. BullMQ)
app.registerWorker(
    defineWorker({
        name: 'bullmq-emails',
        async start() {
            worker = new Worker('emails', async (job) => {
                await sendEmail(job.data);
            });
        },
        async stop() {
            await worker.close();
        },
    }),
);

// Function shorthand
app.registerWorker(async (signal) => {
    while (!signal.aborted) {
        await heartbeat();
        await delay(5000, signal);
    }
});

服务处还可对工人进行登记:

const authService = new ArriService('auth');
authService.registerWorker(tokenCleanupWorker);

app.use(authService); // Workers will be registered on the app

添加客户端生成器

// arri.config.ts
import { defineConfig, servers, generators } from "arri";

export default defineConfig({
    server: servers.tsServer(),
    generators: [
        generators.typescriptClient({...}),
        generators.dartClient({...}),
        generators.kotlinClient({...})
        generators.someGenerator({...})
    ]
});

有关现有发电机的信息见 这里

要了解如何创建自己的生成器,请查看 @ arrirpc/ codegen- utils

关键概念

Arri 定义文件

服务器生成一个 __definition.json 用于设计 API 中的所有程序和模型。 默认情况下, 此方案可以从 /__definition 当服务器运行时,但可以修改. 终点也与 rpcRoutePrefix 选项.

看起来是这样的:

{
    "procedures": {
        "sayHello": {
            "transport": "http",
            "path": "/say-hello",
            "method": "post",
            "params": "SayHelloParams",
            "response": "SayHelloResponse"
        }
        // rest of procedures
    },
    "definitions": {
        "SayHelloParams": {
            "properties": {
                "name": {
                    "type": "string"
                }
            }
        },
        "SayHelloResponse": {
            "properties": {
                "message": {
                    "type": "string"
                }
            }
        }
        // rest of models
    }
}

Arri能够使用这个schema文件自动生成多种语言的客户端. 这样它的工作方式类似于一个开放的API schema,但得到了更好的代码生成支持. 在设计这个计划时,我做了许多刻意的选择,使代码生成更容易,语言之间更加一致. 例如,Arri schemas使用一个超级集,即: JSON 类型定义 他们的模型而不是JSON Schema.

如何将程序映射到终点

每个程序都根据它的名字 绘制到一个不同的url 例如,以下文件结构:

|--src
   |--procedures
      |--getStatus.rpc.ts
      |--users
         |--getUser.rpc.ts
         |--updateUser.rpc.ts

我们将获得以下终点:

POST /get-status
POST /users/get-user
POST /users/update-user

(Note: these will always be relative to the `rpcRoutePrefix` option)

默认情况下,所有程序都会成为员额请求,但在创建程序时可以更改:

// procedures/users/getUser.rpc.ts
export default defineRpc({
    method: 'get',
    // rest of config
});

支持的HTTP方法如下:

  • 员额
  • 起来
  • 删除
  • 补丁
  • 设置

当使用获取方法时, RPC 参数将被映射为查询参数,该参数将使用 a.coerce 方法从 arri-validate。获取方法支持所有基本的 scalar 类型,无论阵列和嵌入对象不支持.

H3 支助

阿里建在顶部 H3级 因此适用于H3的许多概念也适用于Arri.

上网公用事业

Arri重新运送所有H3公用事业.

import { getRequestIP, setResponseHeader } from '@arrirpc/server';

访问 H3 事件

您可以通过内部程序处理器访问 H3 事件 .

defineRpc({
    params: undefined,
    response: undefined,
    handler(_, event) {
        getRequestIP(event);
    },
});

defineEventStreamRpc({
    params: undefined,
    response: undefined,
    handler(_, event) {
        getRequestIP(event);
    },
});

手动启动 Arri 服务器

Arri服务器只是引擎盖下的一个H3应用程序,这样你就可以以同样的方式启动H3应用程序. 尽管您应该注意的是,目前基于备案的路由器只在使用Arri CLI时才有效.

import { createServer } from 'node:http';
import { ArriApp, toNodeListener } from '@arrirpc/server';

const app = new ArriApp();

createServer(toNodeListener(app.h3App)).listen(process.env.PORT || 3000);

阿里·CLI

# start the dev server
arri dev [flags]

# create a production build
arri build [flags]

# create a new project
arri init [dir]

# run codegen
arri codegen [path-to-definition-file]

发展

大楼

运行 nx build arri-rpc 来建造图书馆.

运行单元测试

运行 nx test arri-rpc 通过Vitest执行单元测试.

版本与发布记录

@arrirpc/server 共发布 89 个版本,首次发布于 2024/05/14;过去 12 个月发布了 11 个版本。

版本发布日期距今
0.85.0latest2026/10/031 个月前
0.84.12026/08/043 个月前
0.84.02026/08/043 个月前
0.83.12026/07/143 个月前
0.83.02026/07/143 个月前
0.82.02026/05/225 个月前

其他发布通道:beta → 0.76.3-beta.0。

关于 @arrirpc/server 的常见问题

@arrirpc/server 是什么?

字型执行 阿里·RPC它建在顶部 H3级 和用途 兴建 为捆绑.

如何安装 @arrirpc/server?

在项目目录运行 npm install @arrirpc/server,或使用 pnpm add / yarn add / bun add。

@arrirpc/server 支持 TypeScript 吗?

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

@arrirpc/server 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@arrirpc/server 可以商用吗?

@arrirpc/server 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@arrirpc/server 的下载量有多少?

根据 npm 官方下载统计,@arrirpc/server 在 2026/10/07 – 2026/11/05 这 30 天内被下载 4,493 次,日均约 150 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@arrirpc/server 还在维护吗?

最新版本 0.85.0 发布于 2026/10/03(1 个月前);至今共发布 89 个版本,其中过去 12 个月发布了 11 个;首次发布于 2024/05/14。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。