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。
