模块定义开发
定义模块属性、方法、事件、用户域和权限。
模块版本来自项目 Git 快照。运行时可调用方法来自 methods/*.json,不能只修改数据库记录、Manager 页面或已经安装的运行态服务。
模块源码项目不是发布单元,可以先独立创建:
baijimu module project create \
--workspace-id <workspaceId> \
--name <projectName>模块定义必须在 Bundle 内创建。<bundle> 可以是 bundleId 或精确名称;CLI 会先解析
并校验唯一 Bundle,再把稳定 bundleId 写入模块定义:
baijimu bundle module create <workspace> <bundle> \
--project-id <projectId> \
--name <moduleName> \
--description <description>不要使用隐藏的旧版顶层 module create 作为新流程入口,也不要创建没有 Bundle 归属的
模块记录。
主要文件
| 文件 | 内容 |
|---|---|
module.json | 名称、描述、属性、事件、用户域、接口和兼容配置 |
methods/*.json | 方法名称、参数、返回值、错误类型和方法实现 |
不同历史项目中的 JSON 字段可能使用数组或 JSON 字符串。修改时保留现有字段形状,除非当前版本迁移明确要求规范化。
属性
属性需要声明类型、必填、默认值、敏感性和管理方。常见分类:
- 连接凭据:
appId、appSecret、token - 路由配置:
serviceBaseUrl - 运行开关:
autoStart、syncEnabled - 运行态回填:外部实例 ID、状态、最后同步时间
敏感属性不能出现在页面文案、日志、Bundle Manifest 或普通返回值中。
模块需要引用另一个模块时,使用 Interface 属性和 ServiceReference 逻辑值;需要保证目标
Bundle 一同安装时,在 Bundle Manifest 中声明精确 dependencies。不要使用历史模块依赖字段
代替这两层契约。安装时可用属性默认值绑定目标,安装后可用 baijimu runtime app properties update
手动绑定;Runtime
管理引用访问关系,插件通过新协议按需领取当前凭据。完整方式见
ServiceReference 声明、绑定与运行时交付。
需要通过稳定业务键绑定多个同接口目标时,属性类型使用 InterfaceMap,属性值使用
ServiceReferenceMap。两者的 JSON 结构、安装后配置、整组替换和按需引用访问解析规则见
InterfaceMap 与 ServiceReferenceMap。
方法
每个方法应明确:
- 稳定业务名称
- 参数类型、必填和默认值
- 返回类型和错误模型
- 需要的属性与用户域
- 超时、幂等和重试语义
不要把内部 Controller 名、第三方原始路径或临时实现细节作为公共方法名。
paramDefinitions 是模块方法面对所有调用方的公共 JSON 输入契约。平台应用页面发送的
JSON 顶层字段与参数名称一一对应;模块内部 HTTP 请求的 methodBody 不属于页面协议。
通过 CLI 创建 HTTP 方法时使用 --type HttpMethod;这里的 HttpMethod 是平台方法实现类型,
不是 GET 或 POST。HTTP 动词写入 methodBody.http_method,查询参数映射写入
methodBody.query,不能把 GET、POST 或 QUERY 传给 --type。
methodBody 的可编辑源必须使用 snake_case,具体字段、示例和历史兼容边界见
HTTP methodBody 源契约。
浏览器侧的完整调用方式见
平台应用调用模块方法。
事件
后端模块事件是 module.json 顶层 events 数组中的版本化声明,不使用独立的
events/*.json 文件。事件的创建、修改和删除都通过修改这个数组完成,不要求独立的事件
CRUD 命令。
{
"events": [
{
"name": "orderStatusChanged",
"description": "订单状态发生变化后触发。",
"paramDefinitions": [
{
"name": "orderId",
"type": {
"@type": "DataType",
"type": "string",
"nullable": false
},
"description": "订单 ID。",
"required": true
},
{
"name": "status",
"type": {
"@type": "DataType",
"type": "string",
"nullable": false
},
"description": "变更后的订单状态。",
"required": true
},
{
"name": "occurredAt",
"type": {
"@type": "DataType",
"type": "integer",
"nullable": false
},
"description": "事件发生时间,Unix epoch 毫秒。",
"required": true
}
]
}
]
}新定义必须把 events 写成实际 JSON 数组,不要写成包含 JSON 文本的字符串。事件和参数名称
是调用方、订阅方和触发规则共同依赖的稳定契约;已经发布后若重命名或改变参数类型,应创建
明确的后继事件,而不是静默改变原事件语义。
paramDefinitions 描述事件载荷的顶层参数,类型结构与模块方法参数相同:
required表示该顶层参数是否必须出现。nullable表示参数出现时其值能否为null。- 对象和数组可以继续使用
properties、items、required、additionalProperties等DataType字段描述内部结构。 - 平台控制的时间字段统一使用 Unix epoch 毫秒整数,完整规则见 时间类型。
模块事件声明不同于本地 Connector 的 payload_schema,不要在两种能力之间复制字段名。
声明事件只会把事件加入模块版本和安装后的服务定义,不会自动发送事件,也不会自动创建
订阅或动作。事件生产方必须通过目标 Runtime 提供的事件发布能力发送与声明一致的载荷;
需要把事件绑定到模块方法或其他动作时,应把 Event Trigger 作为独立的 Bundle 资源管理。
工作流和独立模块后端的发布方式、地址来源、回调属性及安全边界见
模块事件与发布机制。
提交时检查并只提交预期源码,再使用该提交创建模块版本:
baijimu project checkout <projectId> --workspace-id <workspaceId> --directory <directory>
cd <directory>
git diff -- module.json
git add -- module.json
git commit -m '<message>'
git push
commitId="$(git rev-parse HEAD)"
baijimu bundle module version create <workspace> <bundle> <projectId> \
--module-id <moduleId> \
--version <semanticVersion> \
--commit-id <commitId>冻结后应从版本定义或安装后的 Runtime 服务中回读事件名称和 paramDefinitions,确认它们来自
预期 Git 提交。只有整个 Bundle 的版本发布、审核和安装完成后,新事件才会进入目标 Runtime;
仅修改工作区文件或创建模块版本都不会升级已经安装的 Bundle。
用户身份
模块方法从运行时调用上下文获取当前 Runtime、已验证调用方、工作区和访问用户。不要依赖浏览器把 userId 作为普通业务参数传入。
需要映射第三方账号时,服务端保存百积木用户与外部账号的映射,并在调用前同时校验平台权限和外部系统权限。
当前可用字段、不同入口下的出现条件以及 HTTP 方法映射方式见 模块调用上下文。
与插件开发的边界
模块声明属性、方法、事件和接口引用,不拥有 Bundle 的安装状态机。需要独立后端协调外部状态或 按需领取 Runtime 引用凭据时,统一使用生命周期插件开发。 插件注册、请求协议、阶段处理和安装验证均在该入口维护;模块文档仅负责资源声明和服务调用。
创建模块版本遇到插件退役或安装时协议不匹配,请按 旧插件迁移与发布错误处理 定位精确源码与失败资源,完成后继版本迁移;不能只升级 CLI 或替换插件名称。