Node.js SDK
Node.js 服务端 SDK 用应用凭据调用 OpenAPI,管理用户、好友、群组、消息和文件,并接收事件回调与同步回调。它负责 App Token、重试、限流、分页和回调校验。接口通用规则见调用接口,框架接入见接收回调,全部方法见服务与方法。
运行环境与安装
- Node.js 22.17.0 以上,支持 Node.js 24;使用 Node.js 运行时,Next.js 中选择
nodejs,不支持 Edge 运行时。 - 包名为
@deeprespond/im-server-sdk,没有运行时依赖,使用内置fetch和 Node.js 模块。 - 同时提供 ES 模块和 CommonJS,带 TypeScript 类型,只有具名导出。
- Express、Koa、Fastify、Redis 等由应用按需安装,SDK 不会自动引入它们。
当前提供源码和本地打包方式,公共 npm 发布渠道尚未完成。先在源码仓库的 sdk/server/node 中构建安装包:
pnpm install
pnpm build
pnpm pack --pack-destination /tmp然后在你的业务项目中安装生成的 .tgz 文件:
npm install /tmp/deeprespond-im-server-sdk-1.0.0.tgzES 模块和 TypeScript:
import { DRClient, isDRError } from '@deeprespond/im-server-sdk';CommonJS:
const { DRClient, isDRError } = require('@deeprespond/im-server-sdk');| 导入路径 | 内容 |
|---|---|
@deeprespond/im-server-sdk | DRClient、DRError、BatchError、RawJSON、RAW、参数与响应类型 |
@deeprespond/im-server-sdk/callback | 回调处理器、事件类型、同步回调结果、内存存储 |
@deeprespond/im-server-sdk/callback/node、/express、/koa、/fastify、/fetch | 回调的框架适配 |
@deeprespond/im-server-sdk/redis | App Token、随机数、事件去重的 Redis 存储 |
@deeprespond/im-server-sdk/testing | 假 OpenAPI、带签名的回调请求等测试辅助 |
创建客户端
在控制台取得应用的 Client ID 和 Client Secret。orgName、appName 分别是 AppKey 中 # 前后的部分。
import { DRClient } from '@deeprespond/im-server-sdk';
export const im = new DRClient({
baseUrl: 'https://api.example.com',
orgName: process.env.IM_ORG_NAME!,
appName: process.env.IM_APP_NAME!,
clientId: process.env.IM_CLIENT_ID!,
clientSecret: process.env.IM_CLIENT_SECRET!,
});一个客户端对应一个应用,在每个进程或 Worker 中创建并复用。构造时只校验参数,第一次调用才换取 App Token;各方法返回 Promise,可以并发调用。baseUrl 必须是 HTTP 或 HTTPS 的绝对地址,不能带查询参数;HTTP 只允许本机、内网地址和不带点的主机名,公网地址使用 HTTPS。
Client Secret 和 App Token 等同应用管理员的密码,客户端 SDK 请使用 Web SDK 等,不要将服务端 SDK 打包进网页、App 或小程序。
客户端选项
时间选项使用毫秒。错误的 retryAfter 使用秒,见错误处理。
| 选项 | 默认值 | 说明 |
|---|---|---|
baseUrl | 必填 | IM 接入地址,末尾的 / 会去掉 |
orgName、appName | 必填 | 租户标识、应用名称 |
clientId、clientSecret | 必填 | 应用服务端凭据 |
timeoutMs | 30000 | 每次尝试的总时限;完成上传的默认时限为 150000 |
maxRetries | 3 | 网络错误、超时、5xx 的重试次数,不含第一次;只重试可安全重试的接口 |
maxRateLimitedRetries | 3 | rate_limited 后等待重发的次数 |
maxRetryAfterMs | 60000 | 自动等待 Retry-After 的上限;0 表示不等待 |
rateLimit | 关闭 | 本地限速 { perSecond, burst? };burst 默认 max(1, ceil(perSecond)) |
tokenStore | 进程内缓存 | 共享 App Token 的存储,见多进程共用令牌 |
fetch | 内置 fetch | 自己的请求实现,签名为 (url, init) => Promise<Response> |
hooks | 无 | beforeRequest、afterResponse,见日志与排查 |
logger | 不输出 | { level?, sink? };设置 sink 后默认级别为 warn |
userAgentSuffix | 无 | 追加服务名和版本到 User-Agent |
im.withOptions({ timeoutMs: 3000, maxRetries: 0 }) 返回共用令牌、连接和限流状态的视图。可覆盖 timeoutMs、maxRetries、maxRateLimitedRetries、maxRetryAfterMs,原客户端的设置不变。
第一次调用
用户登录你的业务系统后,为他签发登录凭证,再交给客户端 SDK:
const result = await im.users.issueLoginTicket('alice', { auto_create: true });
// 在业务接口的响应中将 result.ticket 交给当前已登录的用户。auto_create 为 true 时自动创建不存在的用户。凭证有效期和使用规则见签发登录凭证。
发送单聊通知时,from 使用应用内已有的 IM 用户:
await im.messages.send({
from: 'notice',
to_user: 'alice',
client_msg_id: 'order-20261008-paid',
type: 'text',
body: { text: '订单已支付' },
});to_user 和 to_group 恰好传一个。使用稳定的业务 ID 作为 client_msg_id,业务层重试也能去重;不传时 SDK 为本次调用生成 ID,自动重试沿用它。详见发送消息。
App Token
SDK 自动换取、缓存和刷新 App Token,同一客户端内并发请求共用一次换取。剩余有效期不足总有效期的 10%(至少提前 5 分钟)时后台刷新,已过期或剩余不足 1 分钟时等待新令牌。令牌失效后自动重新换取,具体鉴权语义见鉴权与 App Token。
轮换应用凭据后,可以调用 im.updateCredentials(newClientId, newClientSecret),后续请求使用新凭据。排查时可用 await im.token() 取得当前有效令牌,尚未换取时会自动获取;不要将返回的令牌写入日志。im.appId 在首次换取前为 null,之后为应用 ID。
多进程共用令牌
import { Redis } from 'ioredis';
import { DRClient } from '@deeprespond/im-server-sdk';
import { ioredisStores } from '@deeprespond/im-server-sdk/redis';
const redis = new Redis(process.env.REDIS_URL!);
const { tokenStore } = ioredisStores(redis, { keyPrefix: 'my-service:im:' });
const im = new DRClient({
baseUrl: 'https://api.example.com',
orgName: process.env.IM_ORG_NAME!,
appName: process.env.IM_APP_NAME!,
clientId: process.env.IM_CLIENT_ID!,
clientSecret: process.env.IM_CLIENT_SECRET!,
tokenStore,
});使用 node-redis 时,先 await redis.connect(),再用 nodeRedisStores(redis)。SDK 不关闭调用方传入的 Redis 客户端。回调随机数和去重也可使用同一组存储,见共享存储。
代理与私有证书
需要代理时可以传入自己的 fetch,例如使用 undici 的 ProxyAgent:
import { ProxyAgent } from 'undici';
import { DRClient } from '@deeprespond/im-server-sdk';
const dispatcher = new ProxyAgent('http://proxy.internal:3128');
const im = new DRClient({
baseUrl: 'https://api.example.com',
orgName: process.env.IM_ORG_NAME!,
appName: process.env.IM_APP_NAME!,
clientId: process.env.IM_CLIENT_ID!,
clientSecret: process.env.IM_CLIENT_SECRET!,
fetch: (url, init) => {
const options: RequestInit = { ...init };
Object.assign(options, { dispatcher });
return globalThis.fetch(url, options);
},
});
// 服务停止时先 await im.close(),再 await dispatcher.close()。内置 fetch 是否使用环境变量代理取决于 Node.js 的版本和启动配置,SDK 不自行读取 HTTPS_PROXY。私有化部署的 CA 证书可在启动 Node.js 前配置 NODE_EXTRA_CA_CERTS。
服务停止时
await im.close();关闭原客户端会处理正在进行的调用并停止令牌刷新,之后不能再调用。视图的 close() 不关闭原客户端。自己的 Redis、代理连接池由应用关闭。
频道版本
独立频道服务及九种强类型回调已写入当前源码,尚未发布本轮新 SDK 制品。安装旧版本时可能没有 Channels / channels 属性,请确认提供的版本包含频道方法,再按调用示例接入。
