mcpField
O
omnistudio-callable-apex-generate

omnistudio-callable-apex-generate

github.com/forcedotcom开发1.1k4.8k 次安装1 天前更新
代码仓库

关于 omnistudio-callable-apex-generate

用于创建和审查 Salesforce Industries Common Core callable Apex 实现的技能,面向开发者,支持 System.Callable 动作分派、安全输入输出契约,以及从旧版 Vlocity Open Interface 扩展迁移。

主要功能

  1. 01生成 System.Callable 类
  2. 02定义并验证动作契约
  3. 03执行共享与 CRUD/FLS 检查
  4. 04迁移旧版 Open Interface 实现
  5. 05评分并测试 callable 代码

适用场景

  1. 01添加可由 OmniStudio 调用的动作
  2. 02审查 callable 的安全性与批量处理
  3. 03将 VlocityOpenInterface2 迁移至 System.Callable
  4. 04测试支持和不支持的动作

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/forcedotcom/sf-skills --skill omnistudio-callable-apex-generate

安装后在 Claude Code 中输入/omnistudio-callable-apex-generate确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

README.md
assets/
pattern_callable_openinterface.cls
pattern_callable_vanilla.cls
pattern_migration.cls
pattern_openinterface.cls
pattern_test_class.cls
examples/Test_QuoteByProductCallable/
Industries_QuoteByProductCallable.cls
Industries_QuoteByProductCallableTest.cls
IndustriesCallableException.cls
TRANSCRIPT.md
examples/Test_VlocityOpenInterface2Conversion/
IndustriesCallableException.cls
MyCustomCallable.cls
MyCustomCallableTest.cls
MyCustomRemoteClass.cls
TRANSCRIPT.md
examples/Test_VlocityOpenInterfaceConversion/
IndustriesCallableException.cls
MyCustomCallable.cls
MyCustomCallableTest.cls
MyCustomClass.cls
TRANSCRIPT.md

详细介绍

omnistudio-callable-apex-generate:Salesforce Industries Common Core 的 Callable Apex

专注于 Salesforce Industries Common Core 的 Callable Apex 实现。生成安全、确定且可配置的 Apex,并与 OmniStudio 和 Industries 扩展点无缝集成。

范围

  • 范围内:为 Industries 扩展点创建 System.Callable 类;审查 Callable 实现的正确性和风险;将 VlocityOpenInterface / VlocityOpenInterface2 迁移到 System.Callable;进行 120 分评分和验证
  • 范围外:不带 Callable 接口的通用 Apex 类(使用 platform-apex-generate);构建 Integration Procedure(使用 omnistudio-integration-procedure-generate);编写 OmniScript(使用 omnistudio-omniscript-generate);部署 Apex 类(使用 platform-metadata-deploy)

核心职责

  1. 生成 Callable:构建具有安全操作分派机制的 System.Callable 类
  2. 审查 Callable:审计现有 Callable 实现的正确性和风险
  3. 验证与评分:根据 120 分评分标准进行评估
  4. 适配 Industries:确保与 OmniStudio/Industries 扩展点兼容

工作流(4 阶段模式)

阶段 1:收集需求

询问:

  • 入口点(OmniScript、Integration Procedure、DataRaptor 或其他 Industries 扩展钩子)
  • 操作名称(传入 call 的字符串)
  • 输入/输出约定(必需键、类型和响应结构)
  • 数据访问需求(对象/字段、CRUD/FLS(创建/读取/更新/删除和字段级安全)规则)
  • 副作用(DML、调用外部服务、异步要求)

然后:

  1. 扫描现有 Callable 类:Glob: **/*Callable*.cls
  2. 确定用于 Industries 扩展的共享实用工具或基类
  3. 创建任务列表

阶段 2:设计与约定定义

定义 Callable 约定:

  • 操作列表(明确且带版本的字符串)
  • 输入架构(必需键 + 类型)
  • 输出架构(一致的响应封装)

推荐的响应封装:

{
  "success": true|false,
  "data": {...},
  "errors": [ { "code": "...", "message": "..." } ]
}

操作分派规则:

  • 使用 switch on action
  • 默认分支抛出有类型的异常
  • 不使用动态方法调用或反射

VlocityOpenInterface / VlocityOpenInterface2 约定映射:

为旧版 Open Interface 扩展(或 Callable + Open Interface 双重支持)进行设计时,请映射以下签名:

invokeMethod(String methodName, Map<String, Object> inputMap, Map<String, Object> outputMap, Map<String, Object> options)
参数作用Callable 对应项
methodName操作选择器(与 action 语义相同)call(action, args) 中的 action
inputMap主要输入数据(必需键、类型)args.get('inputMap')
outputMap写入结果的可变映射(按引用输出)返回值;Callable 返回封装结果
options其他上下文(父级 DataRaptor/OmniScript 上下文、调用元数据)args.get('options')

Open Interface 约定的设计规则:

  • 将 inputMap 和 options 视为合并后的输入架构
  • 定义每个操作必须写入 outputMap 的键(成功和错误情况)
  • 保留 methodName 字符串,使其与 Callable 的 action 字符串保持一致
  • 记录每个操作中的 options 是必需、可选还是未使用

阶段 3:实现模式

原生 System.Callable(扁平参数,不耦合 Open Interface):

生成前请先阅读 assets/pattern_callable_vanilla.cls——当调用方传入扁平参数且不需要集成 VlocityOpenInterface 时使用。

Callable 骨架(输入与 VlocityOpenInterface 相同):

生成前请先阅读 assets/pattern_callable_openinterface.cls——与 Open Interface 集成时,或调用方传入该结构时,在 args 中使用 inputMap 和 options 键。

输入格式:调用方将 args 作为 { 'inputMap' => Map<String, Object>, 'options' => Map<String, Object> } 传入。为保持向后兼容,如果 args 中没有 'inputMap',则将 args 本身视为 inputMap,并将 options 设为空 Map。

实现规则:

  1. 保持 call() 精简;委托给私有方法或服务类
  2. 尽早验证并转换输入类型(安全处理 null)
  3. 强制执行 CRUD/FLS(创建/读取/更新/删除和字段级安全)及共享规则(with sharing、Security.stripInaccessible())
  4. 当 args 包含记录集合时进行批量化处理
  5. 适当时在 SOQL 中使用 WITH USER_MODE
  6. 命名空间处理:System.Callable 是标准接口(无需命名空间前缀);omnistudio.VlocityOpenInterface2 使用托管包命名空间 omnistudio——务必始终使用限定名称。如果 Callable 类将部署到带命名空间的托管包中,请向用户确认命名空间前缀,并将其应用于自定义类名(例如,myns__Industries_XxxCallable)

VlocityOpenInterface / VlocityOpenInterface2 实现:

实现 omnistudio.VlocityOpenInterface 或 omnistudio.VlocityOpenInterface2 时,使用以下签名:

global Boolean invokeMethod(String methodName, Map<String, Object> inputMap,
                           Map<String, Object> outputMap, Map<String, Object> options)

生成前请先阅读 assets/pattern_openinterface.cls——其中包含完整的 VlocityOpenInterface2 骨架,以及使用 switch on 进行分发和 outputMap 契约的示例。

Open Interface 实现规则:

  • 使用 putAll() 或单独调用 put() 将结果写入 outputMap;不要从 invokeMethod 返回封套
  • 成功时返回 true,不支持或失败的操作返回 false
  • 使用与 Callable 相同的内部私有方法(参数相同,均为 inputMap 和 options);只有入口点不同
  • 使用相同的封套结构(success、data、errors)填充 outputMap,确保一致性

Callable 和 Open Interface 接受相同的输入(inputMap、options),并委托给签名相同的私有方法来共享逻辑。


阶段 4:测试与验证

最低测试要求:

  • 正向:支持的操作成功执行
  • 负向:不支持的操作抛出预期异常
  • 契约:缺失或无效的输入返回错误封套
  • 批量:处理列表输入时不触发限制

生成测试前,请先阅读 assets/pattern_test_class.cls——其中包含完整的测试类骨架,涵盖正向、负向、契约、批量和 null 参数用例。


迁移:从 VlocityOpenInterface 迁移到 System.Callable

现代化 Industries 扩展时,将 VlocityOpenInterface 或 VlocityOpenInterface2 实现迁移到 System.Callable,并保持 操作契约稳定。

指南:

  • 将操作名称(methodName)保留为 call() 中的 action 字符串
  • 将 inputMap 和 options 作为 args 中的键传递:{ 'inputMap' => inputMap, 'options' => options }
  • 返回一致的响应封套,而不是修改 outMap
  • 保持 call() 精简;委托给签名为 (inputMap, options) 的相同内部方法
  • 为每项操作和不支持的操作添加测试

开始迁移前,请先阅读 assets/pattern_migration.cls——其中包含标注过的迁移前后示例(从 VlocityOpenInterface2 迁移到 System.Callable)。

最佳实践(120 分评分)

类别分值关键规则
契约与分发20明确的操作列表;switch on;带版本的操作字符串
输入验证20验证必需键;安全地转换类型;空值保护
安全性20with sharing;CRUD/FLS 检查;Security.stripInaccessible()
错误处理15类型化异常;一致的错误封装;不使用空 catch
批量化与限制20循环中不执行 SOQL/DML;支持列表输入
测试15正向/负向/契约/批量测试
文档10为类和操作方法编写 ApexDoc(/** ... */ 块注释 — Salesforce Apex 文档标准)

门槛:[PASS] 90+(就绪)| [REVIEW] 70-89(审核)| [BLOCK] <70(阻止)


防护措施(强制)

如果要引入以下任一做法,请停下来并询问用户:

  • 基于用户输入动态执行方法(不使用反射)
  • 在循环中执行 SOQL/DML
  • 在可调用类上使用 without sharing
  • 静默失败(空 catch、吞掉异常)
  • 不同操作的响应结构不一致

易错点

问题解决方案
调用方传入扁平参数,但代码期望 inputMap 键做好防御性处理:如果 args 缺少 'inputMap' 键,就将 args 本身视为输入映射
call() 收到的 args 为 null访问键之前始终先检查 args 是否为 null;如果为 null,则初始化为空映射
测试类使用 (Map<String, Object>) svc.call(...),但 call 返回了错误类型确保每个操作都返回相同的封装类型(Map<String, Object>)——混合返回类型会导致调用方出错
迁移到 VlocityOpenInterface2 后,读取 outputMap 引用的调用方出错迁移到 Callable 后,调用方必须读取返回值,而非读取 outputMap — 更新所有调用方
项目中缺少 IndustriesCallableException 类此自定义异常必须与可调用类一起部署 — 将其包含在每个部署包中
组织中旧版 Open Interface 和新版 Callable 都绑定到同一操作同一时间只能启用一个入口点;确认 callable 正常工作后,停用旧接口

常见反模式

  • call() 包含业务逻辑,而不是委派处理
  • 操作名称没有版本号或未记录文档
  • 假定输入映射包含所需键,却未进行检查
  • 返回类型混杂(有时为 Map,有时为 String)
  • 未针对不支持的操作编写测试

跨技能集成

技能使用时机示例
platform-apex-generate可调用实现之外的一般 Apex 工作"Create trigger for Account"
platform-custom-object-generate / platform-custom-field-generate编写代码前确认对象/字段是否可用"Describe Product2 fields"
platform-metadata-deploy验证/部署可调用类"Deploy to sandbox"

参考技能

请遵循以下文档中的核心 Apex 标准、测试模式和防护措施:


附带示例

输出预期

此技能生成的交付物:

  • <ClassName>.cls — 实现 System.Callable 并使用 switch on action 分发的 Callable 类
  • <ClassName>Test.cls — 包含正向、负向、契约和批量测试方法的测试类
  • IndustriesCallableException.cls — 自定义异常类(如果项目中尚不存在)

备注

  • 优先采用确定性强、明确处理副作用的可调用操作
  • 保持操作契约稳定;对于不兼容的更改,应引入新操作
  • 避免在同步可调用方法中执行耗时工作;需要时使用异步方式

参考文件索引

文件何时阅读
assets/pattern_callable_vanilla.cls阶段 3 — 纯 System.Callable 骨架(扁平参数,不耦合 Open Interface)
assets/pattern_callable_openinterface.cls阶段 3 — 带有 inputMap/options 参数的 System.Callable 骨架(兼容 Open Interface)
assets/pattern_openinterface.cls阶段 3 — 带有 switch on 分派和 outputMap 契约的 VlocityOpenInterface2 骨架
assets/pattern_test_class.cls阶段 4 — 测试类骨架(涵盖正向、负向、契约、批量和空参数场景)
assets/pattern_migration.cls迁移 — 带注释的迁移前后模式(VlocityOpenInterface2 → System.Callable)
examples/Test_QuoteByProductCallable/Industries_QuoteByProductCallable.cls阶段 3 — 完整的可调用实现,包含 WITH USER_MODE SOQL 和错误封装
examples/Test_QuoteByProductCallable/Industries_QuoteByProductCallableTest.cls阶段 4 — 完整测试类,涵盖正向、契约和不支持的操作场景
examples/Test_QuoteByProductCallable/IndustriesCallableException.cls阶段 3 — 用于不支持操作的自定义异常模式
examples/Test_QuoteByProductCallable/TRANSCRIPT.md参考 — Quote-by-Product 可调用示例的推理记录
examples/Test_VlocityOpenInterfaceConversion/MyCustomCallable.cls阶段 3 — 从旧版 VlocityOpenInterface 迁移的模式
examples/Test_VlocityOpenInterfaceConversion/MyCustomCallableTest.cls阶段 4 — VlocityOpenInterface 迁移示例的测试类
examples/Test_VlocityOpenInterfaceConversion/IndustriesCallableException.cls阶段 3 — 与 VlocityOpenInterface 转换一同部署的自定义异常类
examples/Test_VlocityOpenInterfaceConversion/MyCustomClass.cls阶段 3 — 迁移前原始的旧版 VlocityOpenInterface 类
examples/Test_VlocityOpenInterfaceConversion/TRANSCRIPT.md参考 — VlocityOpenInterface 转换的推理记录
examples/Test_VlocityOpenInterface2Conversion/MyCustomCallable.cls阶段 3 — 从 VlocityOpenInterface2 迁移的模式
examples/Test_VlocityOpenInterface2Conversion/MyCustomCallableTest.cls阶段 4 — VlocityOpenInterface2 迁移示例的测试类
examples/Test_VlocityOpenInterface2Conversion/IndustriesCallableException.cls阶段 3 — 与 VlocityOpenInterface2 转换一同部署的自定义异常类
examples/Test_VlocityOpenInterface2Conversion/MyCustomRemoteClass.cls阶段 3 — VlocityOpenInterface2 迁移示例使用的远程类
examples/Test_VlocityOpenInterface2Conversion/TRANSCRIPT.md参考 — VlocityOpenInterface2 转换的推理记录

交付前检查清单

  • call() 在访问键之前会对 args 进行空值检查
  • 部署包中包含 IndustriesCallableException 类
  • 为 omnistudio.VlocityOpenInterface2 添加命名空间限定(如适用)
  • 按操作记录 outputMap 的键(成功和错误场景)
  • 迁移后的调用方读取返回值,而非通过引用读取 outputMap

评论

支持 Markdown