Node.js 示例运行指南
完整源码见 GitLab sdk/server/node,仓库访问需要相应权限。
这里提供接口调用和回调框架示例,不包含聊天 Web UI;浏览器聊天应使用客户端 SDK,Go/Python 的业务服务端聊天 Demo 是另一类示例。 当前源码包版本 1.0.0,尚未公开发布 npm;不能直接把 pnpm add @deeprespond/im-server-sdk 作为可用安装步骤。 要求 Node.js 22.17 以上、pnpm;支持 ESM / CommonJS,示例使用 TypeScript ESM。
构建本地安装包
完整仓库根目录执行:
cd sdk/server/node
pnpm install --frozen-lockfile
pnpm build
pnpm pack --pack-destination /tmp得到 /tmp/deeprespond-im-server-sdk-1.0.0.tgz。它只包含 dist 与 SDK README,不包含 examples;更新源码后需重新构建、打包并安装。 Windows 使用自己的可写输出目录;不要把 /tmp 视为各平台统一路径。pnpm build 不执行完整发布检查,发布前检查仍需完整仓库。
独立业务工程运行
新建 ESM 工程,将当前目录中的 client.ts、import-users.ts 复制到该工程 src(下文路径以此布局为准):
mkdir im-node-example
cd im-node-example
npm init -y
npm pkg set type=module
npm install /tmp/deeprespond-im-server-sdk-1.0.0.tgz
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 运行时不会把它自动改成 client.ts。 PowerShell 将多行命令合为一行,环境变量使用 $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。
检查与排查
完整仓库根目录可执行 make sdk-server-node-test 与 make sdk-server-node-integration,后者需要独立 harness。 现有实现记录见 docs/server-node/3.实现与测试.md;SDK 测试、示例编译和真实回调联调分别验收。
| 现象 | 检查 |
|---|---|
| npm 404 | 当前未公开发布,先构建 tgz 再安装本地文件 |
| 找不到 client.js | 用 NodeNext 编译 TS 后执行 dist,不直接运行示例 TS |
| 401 / 凭据无效 | 组织、应用、Client ID/Secret 及 API 地址是否属于同一环境 |
| 图片发送到一半失败 | 当前工作目录 banner.png、用户存在性、媒体大小与应用策略 |
| 回调验证失败 | 接收端已启动、ID/密钥匹配、原始请求体、反代路径及 IM 网络可达 |
| Redis ECONNREFUSED | REDIS_URL、实际端口、认证和数据库,或先用单实例 Fastify 示例 |
| 重复事件或多实例不一致 | 业务幂等、共享 nonce/dedup,不能只依赖各进程内存 |
完整文档见Node.js SDK。
