Node.js 示例运行指南
完整源码见 GitLab sdk/server/node,访问仓库需要相应权限。
这里的示例演示调用接口和在各框架中接收回调,不包含聊天的网页界面:浏览器中的聊天请使用客户端 SDK;Go 和 Python 服务端 SDK 的聊天 Demo 是另一类示例。 当前版本为 1.0.7,已发布到 npm,业务项目用 npm 安装 @deeprespond/im-server-sdk@1.0.7 即可,也可以使用从源码构建的本地 tgz。 需要 Node.js 22.17 以上;业务工程用 npm 即可,从源码构建才需要 pnpm。SDK 同时支持 ESM 和 CommonJS,下面的示例源码是 TypeScript ESM。
只想先调通接口的,使用快速开始中完整的 JavaScript 示例即可,不需要仓库权限。本页说明怎样把仓库中的脚本和框架示例放进自己的工程运行;npm 包中不含这些示例。
可选:构建本地安装包
在完整仓库的根目录执行:
cd sdk/server/node
pnpm install --frozen-lockfile
pnpm build
pnpm pack --pack-destination /tmp得到 /tmp/deeprespond-im-server-sdk-1.0.7.tgz,其中只有构建产物(dist)和 SDK 的 README,没有示例;源码更新后要重新构建、打包和安装。 Windows 上请换成自己可写的输出目录,/tmp 不是各平台通用的路径。pnpm build 不做完整的发布检查,发布前的检查需要在完整仓库中执行。
独立业务工程运行
新建一个 ESM 工程,把仓库 sdk/server/node/examples/ 中的 client.ts、import-users.ts 复制到工程的 src 目录(下文的路径都按这个结构):
mkdir im-node-example
cd im-node-example
npm init -y
npm pkg set type=module
npm install @deeprespond/im-server-sdk@1.0.7
npm install --save-dev typescript @types/node@22
mkdir src复制后编译。源码中的 .js 导入按 NodeNext 的规则对应到 TypeScript 源文件:
npm exec -- tsc --module NodeNext --moduleResolution NodeNext --target ES2022 \
--strict --esModuleInterop --skipLibCheck --outDir dist src/client.ts src/import-users.ts不要直接运行 node examples/*.ts:这些源码导入的是 ./client.js,Node.js 运行时不会把它自动换成 client.ts。 在 PowerShell 中,把多行命令合成一行,环境变量用 $env:名称='值' 设置。
也可以把下文的应用配置写进 .env,用 node --env-file=.env dist/import-users.js users.jsonl 启动;.env 不要提交到版本库。环境变量要在创建客户端之前加载。
应用配置
client.ts 只读取下面这些环境变量,填写同一个应用的服务端凭据:
export IM_BASE_URL='https://im.example.com'
export IM_ORG_NAME='组织名'
export IM_APP_NAME='应用名'
export IM_CLIENT_ID='替换为 Client ID'
export IM_CLIENT_SECRET='替换为 Client Secret'IM_BASE_URL 默认为 https://api.example.com,其他变量默认为空,都只是占位;AppKey 中 # 前后分别是组织名和应用名。 凭据只保存在后端,不要写进代码、浏览器、日志或版本库。SDK 以应用管理员的身份调用接口,你的业务接口还要检查当前用户和他的权限。 管理员撤回不等于用户撤回,管理视角的历史也不等于用户能看到的历史;下载附件只取回文件内容,不替你的 HTTP 响应设置安全的类型和下载头。
示例选择
| 文件 | 做什么,运行条件 |
|---|---|
client.ts | 共用的 DRClient;导入时不发请求,第一次调用接口时换取 App Token |
import-users.ts | 从 JSONL 文件批量创建用户,会修改应用数据,运行前确认目标应用 |
send-message.ts | 先以 system 给 alice 发一条文本,再上传当前目录的 banner.png 发一张图片;需要用户已经存在、目录中有这张图片 |
login-ticket.ts | 导出 imLoginTicket(username),不是独立的命令;在业务登录成功后由后端调用,可以自动创建 IM 用户 |
callback-fastify.ts | Fastify 5,随机数和去重存在内存中,在 3000 端口监听 /im/callback;适合单实例 |
callback-express.ts | Express 4/5 + ioredis,监听 3000 端口;验签的路由必须放在 express.json() 之前 |
callback-nestjs.ts | NestJS 的 Express 平台,rawBody: true;监听 3000 端口,不是完整的业务系统 |
nextjs/ | Next.js nodejs 运行时的路由示例,要按 Next 项目的目录集成,不能单独用 node 运行 |
例如,创建一个自己的测试 JSONL 文件并导入(会真实写入数据,只对测试应用执行):
printf '%s\n' '{"username":"demo_import_alice","nickname":"测试用户"}' > users.jsonl
node dist/import-users.js users.jsonl处理失败的项时按 code 判断;already_exists 不代表整批失败。其他示例复制到 src 后,把上面编译命令中的入口文件换成它即可。 运行 send-message 的目录中必须有 banner.png,否则可能文本已经发出而图片失败;实际业务中要分别处理每一步的结果。 脚本用完调用 im.close();长期运行的后端进程复用一个客户端,退出时统一关闭。
回调本地运行
以 Fastify 作为最小示例,把 callback-fastify.ts 复制到 src:
npm install fastify@5
npm exec -- tsc --module NodeNext --moduleResolution NodeNext --target ES2022 \
--strict --esModuleInterop --skipLibCheck --outDir dist src/callback-fastify.ts
export IM_CALLBACK_ENDPOINT_ID='回调地址ID'
export IM_CALLBACK_SECRET='回调签名密钥'
node dist/callback-fastify.js- 在控制台中创建回调地址,指向 IM 服务能访问到的
/im/callback,保存地址 ID 和密钥。 - 带着这两个环境变量启动接收端,再在控制台中验证地址,开启需要的事件订阅。
- 在业务中操作一次,确认事件进入了处理函数;自己发送的普通 JSON 请求没有签名,不能证明回调可用。
这个示例只注册了 group.members_added;Express 示例另外演示了 message.sent、user.created 和同步回调 message.before_send。 Fastify 默认只监听本机地址;IM 服务在远端时,需要在本机做反向代理或隧道,或者修改监听地址。浏览器能打开这个端口,不代表 IM 服务能访问到它。 Express 示例还要安装 express@5、ioredis@5、@types/express,并配置 REDIS_URL(默认 redis://127.0.0.1:6379);示例不会自动使用其他 Redis 地址。 NestJS 示例还要安装 @nestjs/common、@nestjs/core、@nestjs/platform-express、reflect-metadata、rxjs;多个进程时,随机数和去重改用共享的 Redis。 这些示例都使用 3000 端口,同一时间只启动一个,用 Ctrl+C 停止后再换下一个。
其他框架的配置要点
| 框架 | 依赖和配置 | 完整接入 |
|---|---|---|
| Express | 安装 express@5、ioredis@5、@types/express;回调路由放在 JSON 解析之前;运行前准备好 Redis | Express、共享存储 |
| NestJS | 使用 Express 平台和 rawBody: true;JSON 上限设为 2 MiB;已有的 Nest 工程沿用自己的 TypeScript 和装饰器配置 | NestJS |
| Koa | 安装 koa 和对应的类型;保留原始请求体;按 Koa 2 或 3 选择依赖 | Koa |
| Next.js | 在已有的 App Router 工程中添加 app/im/callback/route.ts 和共用的处理器模块;选择 nodejs 运行时,多个实例共用 Redis | Next.js |
Next.js 示例是路由模块,不能当作普通的 Node.js 脚本启动。测试时启动完整的 Next 应用,从实际的 HTTP 路由发送带签名的请求,而不只是检查 TypeScript 能否编译。
检查与排查
在完整仓库的根目录可以执行 make sdk-server-node-test 和 make sdk-server-node-integration,后者需要先启动仓库中的测试服务。SDK 测试、示例编译和真实的回调联调要分别确认。
npm 1.0.7 发布时验证过的范围见版本说明;安装或联调失败时,先按常见问题与排查核对版本、凭据、网络和原始请求体。
| 现象 | 检查 |
|---|---|
| npm 404 | registry 是否为 https://registry.npmjs.org/,包名和版本是否正确;私有镜像还没同步时用官方 registry 或本地 tgz |
| 找不到 client.js | 用 NodeNext 编译 TypeScript 后运行 dist 中的文件,不要直接运行示例的 TS |
| 401 或凭据无效 | 组织、应用、Client ID/Secret 和 API 地址是否属于同一个环境 |
| 图片发到一半失败 | 当前目录中是否有 banner.png,用户是否存在,文件大小和应用策略 |
| 回调地址验证失败 | 接收端是否已启动,地址 ID 和密钥是否匹配,原始请求体是否被改动,反向代理的路径,IM 服务能否访问到 |
| Redis ECONNREFUSED | REDIS_URL、实际端口、认证和数据库;或者先用单实例的 Fastify 示例 |
| 事件重复或多个实例不一致 | 业务是否幂等,随机数和去重是否用共享存储,不能只靠各进程的内存 |
完整文档见 Node.js SDK。
