UNPKG

@xmobitea/gn-server

Version:

GearN Server by XmobiTea (Pro)

249 lines (192 loc) 10.3 kB
# CLOUDSCRIPT USAGE ## 1. Mục đích Đây là file tổng quan cho AI Agent. Đọc file này trước để hiểu: - CloudScript của GearN chạy theo flow nào. - Những rule nào bắt buộc. - Nên chọn `database`, `http`, `socket`, `mail`, `pushNotification`, hay `admin`. - Cần mở file chi tiết nào tiếp theo. Nếu bạn cần chi tiết theo từng helper, đọc các file trong `docs/` thay vì nhồi mọi thứ vào đây. ## 2. Flow runtime Từ [AddFunctionRequestHandler.ts](./src/GN-app-api/handler/controller/handler/cloudScript/AddFunctionRequestHandler.ts), flow thực tế là: 1. Client gọi `addFunction`. 2. Server nhận `script`, `canExecute`, `isLive`. 3. Script bị từ chối ngay nếu chứa chuỗi `GNNetwork`. 4. Script được nhúng vào [templateCloudScript.ts](./src/GN-startup/cloudScript/templateCloudScript.ts). 5. Server compile TypeScript. 6. Nếu compile pass, server lưu thành version mới. 7. Khi execute, server gọi `handlers[functionName]`. Kết luận: script hợp lệ không phải file TypeScript hoàn chỉnh. Nó chỉ là phần code được chèn vào template, và bắt buộc phải tự đăng ký function vào `handlers`. ## 3. Rule bắt buộc - Luôn đăng ký function theo dạng `handlers["functionName"] = async (args, context, log) => { ... }`. - Không dùng trực tiếp chuỗi `GNNetwork` trong submitted script. - `functionName` nên nằm trong giới hạn `3..30` ký tự. - Khi pin version để execute, `version` phải đúng 7 ký tự. - Nếu không truyền `version`, runtime hiện tại sẽ dùng version đang `isLive`. - `args``functionParameters` từ request execute. - `context``userId``customTags`. - `log` là tham số thứ 3 của handler, không phải global logger và không phải `console.log`. - Không bắt buộc gọi `log` trong mỗi function. Chỉ dùng khi cần debug số liệu, trace luồng đi, hoặc kiểm tra payload tạm thời. - Gọi `log(value)` chỉ để append debug log cho lần execute hiện tại. Runtime sẽ lưu `JSON.stringify(value)` vào `logs` và trả về client qua `functionLogs`. - Nếu `value` không stringify được, ví dụ object vòng tham chiếu, function sẽ lỗi. Chỉ log dữ liệu JSON-safe. - `return` chỉ nên là dữ liệu serialize an toàn: `null`, `boolean`, `number`, `string`, JSON object, JSON array, `GNHashtable`, `GNArray`. - Nếu cần fail rõ ràng, dùng `throw new Error("message")`. Về `context.customTags`: - Đây là metadata đi kèm request execute từ phía caller. - Dùng cho trace, correlation id, source, feature flag, campaign, hoặc thông tin phụ trợ khác. - Không dùng `customTags` cho authorization, permission, hoặc secret. - Hãy coi `customTags` là input phụ trợ, có thể không tồn tại. Khuyến nghị deploy: 1. Add version mới với `canExecute = true`, `isLive = false`. 2. Test bằng đúng `version` vừa tạo. 3. Chỉ promote live sau khi test pass. 4. Chỉ omit `version` khi bạn thực sự muốn execute vào version đang `isLive`. ## 4. Runtime object có sẵn Template inject sẵn các symbol này: - `gameId` - `handlers` - `database` - `http` - `socket` - `mail` - `pushNotification` - `admin` - `mongodb` - `axios` - `OperationEvent` - `GNHashtable` - `GNArray` - `GNHashtableBuilder` - `GNArrayBuilder` - các enum/constants từ `@xmobitea/gn-typescript-client` Source cần đọc khi cần verify: - [templateCloudScript.ts](./src/GN-startup/cloudScript/templateCloudScript.ts) - [CloudScriptDatabase.ts](./src/GN-startup/cloudScript/CloudScriptDatabase.ts) - [CloudScriptHttp.ts](./src/GN-startup/cloudScript/CloudScriptHttp.ts) - [CloudScriptSocket.ts](./src/GN-startup/cloudScript/CloudScriptSocket.ts) - [CloudScriptMail.ts](./src/GN-startup/cloudScript/CloudScriptMail.ts) - [CloudScriptPushNotification.ts](./src/GN-startup/cloudScript/CloudScriptPushNotification.ts) - [CloudScriptAdmin.ts](./src/GN-startup/cloudScript/CloudScriptAdmin.ts) ## 5. Chọn helper nào - `database`: dùng khi cần đọc hoặc ghi MongoDB nội bộ của GearN, hoặc cần helper domain của `xDatabase`. Docs: [docs/CLOUDSCRIPT_database.md](./docs/CLOUDSCRIPT_database.md) - `http`: dùng khi cần gọi REST API hoặc webhook bên ngoài. Docs: [docs/CLOUDSCRIPT_http.md](./docs/CLOUDSCRIPT_http.md) - `socket`: dùng khi cần realtime event cho user online hoặc room. Docs: [docs/CLOUDSCRIPT_socket.md](./docs/CLOUDSCRIPT_socket.md) - `mail`: dùng khi cần gửi email qua mail service của server. Docs: [docs/CLOUDSCRIPT_mail.md](./docs/CLOUDSCRIPT_mail.md) - `pushNotification`: dùng khi cần gửi push tới token hoặc topic. Docs: [docs/CLOUDSCRIPT_pushNotification.md](./docs/CLOUDSCRIPT_pushNotification.md) - `admin`: dùng khi behavior đã tồn tại trong official GearN admin API. Ưu tiên `admin` trước `database` nếu business rule đã có sẵn. Docs: [docs/CLOUDSCRIPT_admin.md](./docs/CLOUDSCRIPT_admin.md) Rule chọn nhanh: - Có official API rồi thì ưu tiên `admin`. - Chỉ đụng raw DB khi official API không cover hoặc bạn cố ý thao tác trực tiếp collection. - Side effect ra ngoài hệ thống thì chọn `http`, `mail`, `socket`, `pushNotification` đúng theo mục tiêu delivery. ## 6. Script tối thiểu hợp lệ ```ts handlers["pingCloudScript"] = async (args: any, context, log) => { const message = typeof args?.message === "string" && args.message.length > 0 ? args.message : "pong"; return { gameId: gameId, userId: context.userId, message: message }; }; ``` Nếu cần debug luồng đi hoặc số liệu runtime, có thể gọi `log(value)`: ```ts handlers["pingCloudScriptDebug"] = async (args: any, context, log) => { const message = typeof args?.message === "string" && args.message.length > 0 ? args.message : "pong"; // Use this only for temporary debug data or execution tracing. log("pingCloudScriptDebug", { userId: context.userId, message: message }); return { message: message }; }; ``` Khi có gọi `log`, `functionLogs` nhận về sẽ là mảng string, ví dụ: ```ts [ "{\"action\":\"pingCloudScriptDebug\",\"userId\":\"0123456789\",\"message\":\"hello\"}" ] ``` Nếu bạn cần ví dụ thật theo từng helper, xem file chi tiết trong `docs/`. ## 7. Add và execute nhanh Ví dụ add script: ```ts import { GNNetwork } from "@xmobitea/gn-typescript-client"; const secretKey = process.env.GN_SECRET_KEY ?? ""; const script = `handlers["pingCloudScript"] = async (args, context, log) => ({ ok: true, userId: context.userId });`; const addResponse = await GNNetwork.cloudScript.admin.addFunctionAsync( { script: script, canExecute: true, isLive: false }, undefined, secretKey ); if (addResponse.hasReturnCodeError()) { throw new Error(addResponse.toString()); } const version = addResponse.responseData.version; ``` Ví dụ execute đúng version vừa add: ```ts import { GNNetwork } from "@xmobitea/gn-typescript-client"; const secretKey = process.env.GN_SECRET_KEY ?? ""; const executeResponse = await GNNetwork.cloudScript.admin.executeFunctionAsync( { userId: "0123456789", functionName: "pingCloudScript", version: version, functionParameters: { message: "hello" } }, undefined, secretKey ); if (executeResponse.hasReturnCodeError()) { throw new Error(executeResponse.toString()); } ``` Ví dụ execute không truyền `version`: ```ts import { GNNetwork } from "@xmobitea/gn-typescript-client"; const secretKey = process.env.GN_SECRET_KEY ?? ""; const executeResponse = await GNNetwork.cloudScript.admin.executeFunctionAsync( { userId: "0123456789", functionName: "pingCloudScript", functionParameters: { message: "hello" } }, undefined, secretKey ); if (executeResponse.hasReturnCodeError()) { throw new Error(executeResponse.toString()); } ``` Case này sẽ chạy vào version đang `isLive`, không phải version mới nhất vừa add nếu version đó chưa được promote live. ## 8. Những lỗi hay dính - Quên đăng ký function vào `handlers`. - Viết code như một file TypeScript hoàn chỉnh thay vì chỉ viết phần body được inject. - Để literal `GNNetwork` trong script. - Hard-code `secretKey` vào script. - Tưởng rằng bỏ `version` sẽ chạy vào version mới add gần nhất. Runtime hiện tại chạy vào version đang `isLive`. - Dùng class instance phức tạp làm `return`, dẫn đến serialize lỗi hoặc mất field. - Tưởng function nào cũng phải gọi `log`. Không cần. Chỉ dùng `log` cho debug số liệu hoặc trace luồng. - Tưởng `console.log` hoặc global `log` sẽ đi vào `functionLogs`. Runtime chỉ capture tham số `log` được truyền vào handler. - Truyền object vòng tham chiếu vào `log(value)`, làm `JSON.stringify(value)` lỗi. - Dùng `database` để làm việc mà `admin` đã có official API sẵn. - Tưởng `socket`, `mail`, `pushNotification` sẽ trả ACK delivery chi tiết. Không có. ## 9. Thứ tự đọc khuyến nghị 1. [CLOUDSCRIPT_USAGE.md](./CLOUDSCRIPT_USAGE.md) 2. [docs/CLOUDSCRIPT_database.md](./docs/CLOUDSCRIPT_database.md) nếu đụng dữ liệu nội bộ 3. [docs/CLOUDSCRIPT_http.md](./docs/CLOUDSCRIPT_http.md) nếu gọi API ngoài 4. [docs/CLOUDSCRIPT_socket.md](./docs/CLOUDSCRIPT_socket.md) nếu cần realtime 5. [docs/CLOUDSCRIPT_mail.md](./docs/CLOUDSCRIPT_mail.md) nếu gửi email 6. [docs/CLOUDSCRIPT_pushNotification.md](./docs/CLOUDSCRIPT_pushNotification.md) nếu gửi push 7. [docs/CLOUDSCRIPT_admin.md](./docs/CLOUDSCRIPT_admin.md) nếu cần official admin API