# API 文档 ## 元数据 - 需求编号:004-02 - 文档版本:v1.0.0 - 创建时间:2026-02-05 - 创建人:AI Assistant - 状态:已完成 ## API 概述 本文档描述了 Tooling API 元数据操作功能的 REST API 接口,包括元数据的创建、查询、更新、删除操作,以及操作日志的查询功能。 ### 核心功能 - **创建元数据**:支持创建 CustomObject、CustomField、ApexClass、ApexTrigger、Flow - **查询元数据**:支持通用 SOQL 查询,使用 SoqlBuilder 动态构建查询语句 - **更新元数据**:支持通用元数据更新操作 - **删除元数据**:支持通用元数据删除操作 - **操作日志查询**:支持查询元数据操作日志 ### 技术架构 - **Controller**:`ToolingMetadataController` - 处理 HTTP 请求和响应 - **Service**:`ToolingMetadataServiceImpl` - 实现业务逻辑 - **Factory**:`ToolingConnectionFactory` - 管理 Tooling API 连接 - **异步日志**:使用 Spring @Async 异步记录操作日志 ### 基础信息 - **基础路径**:`/salesforce/tooling/metadata` - **认证方式**:Bearer Token(JWT) - **权限控制**:`@PreAuthorize("@ss.hasLogin()")` - **数据格式**:JSON ## 接口列表 ### 1. 创建自定义对象 #### 接口信息 - **接口名称**:创建自定义对象 - **请求方式**:POST - **请求路径**:`/salesforce/tooling/metadata/custom-object` - **功能描述**:通过 Tooling API 创建 Salesforce 自定义对象 #### 请求参数 **请求体(Body)**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | customObject | Object | 是 | 自定义对象定义 | | customObject.fullName | String | 是 | 对象 API 名称(如 MyCustomObject__c) | | customObject.label | String | 是 | 对象标签 | | customObject.pluralLabel | String | 是 | 对象复数标签 | | customObject.description | String | 否 | 对象描述 | | customObject.sharingModel | String | 否 | 共享模式(ReadWrite/Read/Private) | **请求示例**: ```json { "fullName": "MyCustomObject__c", "label": "My Custom Object", "pluralLabel": "My Custom Objects", "description": "Custom object for testing", "sharingModel": "ReadWrite" } ``` #### 响应参数 | 参数名 | 类型 | 说明 | |--------|------|------| | code | Integer | 状态码(200 成功,其他失败) | | msg | String | 提示信息 | | data | Object | 响应数据 | | data.success | Boolean | 是否成功 | | data.id | String | 创建的对象 ID | | data.metadataName | String | 元数据名称 | | data.operationTime | String | 操作时间(yyyy-MM-dd HH:mm:ss) | | data.errorCode | String | 错误码(失败时) | | data.errorMessage | String | 错误消息(失败时) | **成功响应示例**: ```json { "code": 200, "msg": "创建自定义对象成功", "data": { "success": true, "id": "a01xx0000000001AAA", "metadataName": "MyCustomObject__c", "operationTime": "2026-02-05 10:00:00" } } ``` **失败响应示例**: ```json { "code": 500, "msg": "创建自定义对象失败", "data": { "success": false, "metadataName": "MyCustomObject__c", "operationTime": "2026-02-05 10:00:00", "errorCode": "TOOLING_META_003", "errorMessage": "元数据已存在" } } ``` --- ### 2. 创建自定义字段 #### 接口信息 - **接口名称**:创建自定义字段 - **请求方式**:POST - **请求路径**:`/salesforce/tooling/metadata/custom-field` - **功能描述**:在指定对象上创建自定义字段 #### 请求参数 **请求体(Body)**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | customField | Object | 是 | 自定义字段定义 | | customField.fullName | String | 是 | 字段 API 名称(如 MyField__c) | | customField.label | String | 是 | 字段标签 | | customField.type | String | 是 | 字段类型(Text/Number/Date/DateTime/Checkbox 等) | | customField.length | Integer | 否 | 字段长度(Text 类型时必填) | | objectType | String | 是 | 对象类型(如 MyCustomObject__c) | **请求示例**: ```json { "customField": { "fullName": "MyField__c", "label": "My Field", "type": "Text", "length": 255 }, "objectType": "MyCustomObject__c" } ``` #### 响应参数 | 参数名 | 类型 | 说明 | |--------|------|------| | code | Integer | 状态码(200 成功,其他失败) | | msg | String | 提示信息 | | data | Object | 响应数据 | | data.success | Boolean | 是否成功 | | data.id | String | 创建的字段 ID | | data.metadataName | String | 元数据名称 | | data.operationTime | String | 操作时间 | | data.errorCode | String | 错误码(失败时) | | data.errorMessage | String | 错误消息(失败时) | **成功响应示例**: ```json { "code": 200, "msg": "创建自定义字段成功", "data": { "success": true, "id": "a02xx0000000001AAA", "metadataName": "MyCustomObject__c.MyField__c", "operationTime": "2026-02-05 10:00:00" } } ``` --- ### 3. 创建 Apex 类 #### 接口信息 - **接口名称**:创建 Apex 类 - **请求方式**:POST - **请求路径**:`/salesforce/tooling/metadata/apex-class` - **功能描述**:创建新的 Apex 类定义 #### 请求参数 **请求体(Body)**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | apexClass | Object | 是 | Apex 类定义 | | apexClass.name | String | 是 | 类名 | | apexClass.body | String | 是 | 类代码内容 | | apexClass.apiVersion | Double | 否 | API 版本(默认 58.0) | | apexClass.status | String | 否 | 状态(Active/Inactive,默认 Active) | **请求示例**: ```json { "apexClass": { "name": "MyClass", "body": "public class MyClass {\n public void hello() {\n System.debug('Hello World');\n }\n}", "apiVersion": 58.0, "status": "Active" } } ``` #### 响应参数 **成功响应示例**: ```json { "code": 200, "msg": "创建 Apex 类成功", "data": { "success": true, "id": "01pxx0000000001AAA", "metadataName": "MyClass", "operationTime": "2026-02-05 10:00:00" } } ``` --- ### 4. 创建 Apex 触发器 #### 接口信息 - **接口名称**:创建 Apex 触发器 - **请求方式**:POST - **请求路径**:`/salesforce/tooling/metadata/apex-trigger` - **功能描述**:创建新的 Apex 触发器 #### 请求参数 **请求体(Body)**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | apexTrigger | Object | 是 | Apex 触发器定义 | | apexTrigger.name | String | 是 | 触发器名称 | | apexTrigger.body | String | 是 | 触发器代码内容 | | apexTrigger.tableEnumOrId | String | 是 | 关联对象(如 Account) | | apexTrigger.apiVersion | Double | 否 | API 版本(默认 58.0) | **请求示例**: ```json { "apexTrigger": { "name": "MyTrigger", "body": "trigger MyTrigger on Account (before insert) {\n System.debug('Account created');\n}", "tableEnumOrId": "Account", "apiVersion": 58.0 } } ``` #### 响应参数 **成功响应示例**: ```json { "code": 200, "msg": "创建 Apex 触发器成功", "data": { "success": true, "id": "01qxx0000000001AAA", "metadataName": "MyTrigger", "operationTime": "2026-02-05 10:00:00" } } ``` --- ### 5. 创建 Flow #### 接口信息 - **接口名称**:创建 Flow - **请求方式**:POST - **请求路径**:`/salesforce/tooling/metadata/flow` - **功能描述**:创建新的 Flow 定义 #### 请求参数 **请求体(Body)**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | flow | Object | 是 | Flow 定义 | | flow.fullName | String | 是 | Flow API 名称 | | flow.label | String | 是 | Flow 标签 | | flow.description | String | 否 | Flow 描述 | | flow.apiVersion | Double | 否 | API 版本(默认 58.0) | **请求示例**: ```json { "flow": { "fullName": "MyFlow", "label": "My Flow", "description": "Flow for testing", "apiVersion": 58.0 } } ``` #### 响应参数 **成功响应示例**: ```json { "code": 200, "msg": "创建 Flow 成功", "data": { "success": true, "id": "300xx0000000001AAA", "metadataName": "MyFlow", "operationTime": "2026-02-05 10:00:00" } } ``` --- ### 6. 查询元数据 #### 接口信息 - **接口名称**:查询元数据 - **请求方式**:GET - **请求路径**:`/salesforce/tooling/metadata/query` - **功能描述**:使用 SOQL 查询元数据 #### 请求参数 **查询参数(Query)**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | objectType | String | 是 | 对象类型(如 ApexClass、CustomObject 等) | | fields | String | 是 | 查询字段(逗号分隔,如 Id,Name,ApiVersion) | | whereClause | String | 否 | WHERE 条件(如 Name='MyClass') | | limit | Integer | 否 | 查询限制(默认 100,最大 2000) | **请求示例**: ```http GET /salesforce/tooling/metadata/query?objectType=ApexClass&fields=Id,Name,ApiVersion,Status&limit=10 HTTP/1.1 Host: localhost:8080 Authorization: Bearer {token} ``` #### 响应参数 | 参数名 | 类型 | 说明 | |--------|------|------| | code | Integer | 状态码 | | msg | String | 提示信息 | | data | Object | 响应数据 | | data.total | Integer | 总记录数 | | data.records | Array | 记录列表 | | data.queryTime | String | 查询时间 | | data.errorCode | String | 错误码(失败时) | | data.errorMessage | String | 错误消息(失败时) | **成功响应示例**: ```json { "code": 200, "msg": "查询元数据成功", "data": { "total": 100, "records": [ { "id": "01pxx0000000001AAA", "name": "MyClass", "apiVersion": 58.0, "status": "Active" } ], "queryTime": "2026-02-05 10:00:00" } } ``` --- ### 7. 更新元数据 #### 接口信息 - **接口名称**:更新元数据 - **请求方式**:PUT - **请求路径**:`/salesforce/tooling/metadata/update` - **功能描述**:更新指定的元数据记录 #### 请求参数 **请求体(Body)**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | sObject | Object | 是 | 元数据对象 | | sObject.id | String | 是 | 记录 ID | | sObject.attributes | Object | 是 | 对象属性 | | sObject.attributes.type | String | 是 | 对象类型(如 ApexClass) | | ... | ... | ... | 其他字段根据对象类型而定 | **请求示例**: ```json { "sObject": { "id": "01pxx0000000001AAA", "attributes": { "type": "ApexClass" }, "name": "MyClassUpdated", "body": "public class MyClassUpdated {\n public void hello() {\n System.debug('Hello World Updated');\n }\n}", "apiVersion": 58.0, "status": "Active" } } ``` #### 响应参数 **成功响应示例**: ```json { "code": 200, "msg": "更新元数据成功", "data": { "success": true, "id": "01pxx0000000001AAA", "operationTime": "2026-02-05 10:00:00" } } ``` --- ### 8. 删除元数据 #### 接口信息 - **接口名称**:删除元数据 - **请求方式**:DELETE - **请求路径**:`/salesforce/tooling/metadata/delete` - **功能描述**:删除指定的元数据记录 #### 请求参数 **查询参数(Query)**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | String | 是 | 记录 ID | | objectType | String | 是 | 对象类型(如 ApexClass) | **请求示例**: ```http DELETE /salesforce/tooling/metadata/delete?id=01pxx0000000001AAA&objectType=ApexClass HTTP/1.1 Host: localhost:8080 Authorization: Bearer {token} ``` #### 响应参数 **成功响应示例**: ```json { "code": 200, "msg": "删除元数据成功", "data": { "success": true, "id": "01pxx0000000001AAA", "operationTime": "2026-02-05 10:00:00" } } ``` --- ### 9. 获取元数据操作日志 #### 接口信息 - **接口名称**:获取元数据操作日志 - **请求方式**:GET - **请求路径**:`/salesforce/tooling/metadata/logs` - **功能描述**:查询元数据操作日志 #### 请求参数 **查询参数(Query)**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | operationType | String | 否 | 操作类型(create/update/delete/query) | | metadataType | String | 否 | 元数据类型(如 ApexClass) | | status | String | 否 | 操作状态(success/failed) | | startTime | String | 否 | 开始时间(yyyy-MM-dd HH:mm:ss) | | endTime | String | 否 | 结束时间(yyyy-MM-dd HH:mm:ss) | | pageNum | Integer | 否 | 页码(默认 1) | | pageSize | Integer | 否 | 每页大小(默认 10,最大 100) | **请求示例**: ```http GET /salesforce/tooling/metadata/logs?operationType=create&startTime=2026-02-05%2000:00:00&endTime=2026-02-05%2023:59:59&pageNum=1&pageSize=10 HTTP/1.1 Host: localhost:8080 Authorization: Bearer {token} ``` #### 响应参数 | 参数名 | 类型 | 说明 | |--------|------|------| | code | Integer | 状态码 | | msg | String | 提示信息 | | data | Object | 响应数据 | | data.total | Integer | 总记录数 | | data.pageNum | Integer | 当前页码 | | data.pageSize | Integer | 每页大小 | | data.list | Array | 日志列表 | | data.list[].id | Long | 日志 ID | | data.list[].operationType | String | 操作类型 | | data.list[].metadataType | String | 元数据类型 | | data.list[].metadataId | String | 元数据 ID | | data.list[].metadataName | String | 元数据名称 | | data.list[].status | String | 操作状态 | | data.list[].operationTime | String | 操作时间 | | data.list[].userId | String | 用户 ID | **成功响应示例**: ```json { "code": 200, "msg": "查询元数据操作日志成功", "data": { "total": 100, "pageNum": 1, "pageSize": 10, "list": [ { "id": 1, "operationType": "create", "metadataType": "ApexClass", "metadataId": "01pxx0000000001AAA", "metadataName": "MyClass", "status": "success", "operationTime": "2026-02-05 10:00:00", "userId": "user001" } ] } } ``` --- ## 错误码 ### 错误码列表 | 错误码 | 错误消息 | 说明 | |--------|----------|------| | TOOLING_META_001 | Session 无效或已过期 | Session ID 无效或已过期,需要重新登录 | | TOOLING_META_002 | 创建元数据失败 | 创建元数据失败 | | TOOLING_META_003 | 查询元数据失败 | 查询元数据失败 | | TOOLING_META_004 | 更新元数据失败 | 更新元数据失败 | | TOOLING_META_005 | 删除元数据失败 | 删除元数据失败 | | TOOLING_META_006 | 权限不足 | 当前用户没有访问该元数据的权限 | | TOOLING_META_007 | 元数据验证失败 | 元数据验证失败 | | TOOLING_META_008 | 用户未登录 | 用户未登录或 Session 已过期 | | TOOLING_META_009 | 元数据类型不支持 | 不支持的元数据类型 | | TOOLING_META_010 | 元数据已存在 | 元数据已存在 | | TOOLING_META_011 | 元数据不存在 | 元数据不存在 | ### 错误响应格式 ```json { "code": 500, "msg": "操作失败", "data": { "success": false, "errorCode": "TOOLING_META_001", "errorMessage": "Session 无效或已过期" } } ``` --- ## 数据类型说明 ### 元数据类型(MetadataType) | 类型 | 说明 | |------|------| | CustomObject | 自定义对象 | | CustomField | 自定义字段 | | CustomIndex | 自定义索引 | | ApexClass | Apex 类 | | ApexTrigger | Apex 触发器 | | ApexPage | Visualforce 页面 | | ApexComponent | Visualforce 组件 | | Flow | Flow 定义 | | FlowDefinition | Flow 定义(新版) | | FlowVersion | Flow 版本 | | FlowTestCoverage | Flow 测试覆盖率 | ### 操作类型(OperationType) | 类型 | 说明 | |------|------| | create | 创建操作 | | update | 更新操作 | | delete | 删除操作 | | query | 查询操作 | ### 操作状态(Status) | 状态 | 说明 | |------|------| | success | 成功 | | failed | 失败 | --- ## 相关文档 - [需求文档](../requirements/sub/2026-01-28-004-02-元数据操作.md) - [设计文档](../design/2026-02-03-004-02-元数据操作-设计.md) - [决策文档](../decisions/2026-02-03-004-02-ADR-元数据操作技术选型.md) - [SQL 脚本](../sql/2026-02-03-004-02-元数据操作日志.sql) - [提示词文档](../prompts/2026-02-05-004-02-prompt-元数据操作.md) - [变更日志](../changelog/2026-02-05-004-02-changelog.md) - [复盘文档](../retros/2026-02-05-004-02-retro.md) - [会话记录](../sessions/2026-02-03-004-02-session.md)