mcpField
P
platform-custom-setting-generate

platform-custom-setting-generate

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

关于 platform-custom-setting-generate

该 Salesforce 技能用于创建和校验层级或列表自定义设置,包括元数据 XML 与字段规则。它还区分设置定义和设置值,并指导处理部署限制及触发器绕过开关。

主要功能

  1. 01生成层级或列表自定义设置
  2. 02生成和校验元数据 XML
  3. 03添加或校验支持的字段
  4. 04说明设置值的部署限制
  5. 05排查自定义设置部署错误

适用场景

  1. 01为功能开关创建层级设置
  2. 02为命名查找表创建列表设置
  3. 03校验现有设置的字段定义
  4. 04排查设置部署失败原因

安装

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

$npx skills add https://github.com/forcedotcom/sf-skills --skill platform-custom-setting-generate

安装后在 Claude Code 中输入/platform-custom-setting-generate确认已加载。

详细介绍

Salesforce 自定义设置生成器和验证器

何时使用此技能

在以下情况下使用此技能:

  • 创建层次结构或列表自定义设置
  • 生成自定义设置元数据 XML
  • 为现有自定义设置添加或验证字段
  • 填充自定义设置值(这些是数据,不是元数据——参见第 6 节)
  • 排查自定义设置部署错误

触发器绕过开关 / 紧急关闭开关属于自定义设置——不是 Apex,也不是 __mdt。 当用户想要一个管理员可以切换、以启用或禁用行为的开关时——例如“在数据加载期间禁用我的 Account 触发器”、功能开关或维护模式标志——只生成带有 Checkbox 字段的层次结构自定义设置(例如 Disable_Triggers__c / Bypass__c)。请勿编写读取该字段的 Apex 触发器、处理程序或测试,也不要将其建模为自定义元数据类型:绕过标志所需的按配置文件 / 用户覆盖功能,正是层次结构自定义设置具备而 __mdt 不具备的。检查该标志的 Apex 由开发人员编写——此技能只生成设置。


如需了解此技能之外权威的 Metadata API 类型、字段和枚举详情,请使用 platform-metadata-api-context-get 技能。

1. 概述和用途

本文档规定了生成自定义设置元数据时必须遵守的约束。自定义设置是设置了 <customSettingsType> 的 CustomObject——它不是独立的元数据类型。

文件扩展名: .object-meta.xml 文件路径: force-app/main/default/objects/<Name>__c/<Name>__c.object-meta.xml API 名称后缀: __c(与常规自定义对象相同——该后缀无法区分它们)

值是数据,不是元数据。 你可以将设置的定义生成为 XML,但不能以这种方式部署其值。自定义设置没有与 customMetadata/ 等效的源格式。切勿生成声称包含设置值的文件——应改为参见第 6 节。


2. 语法要点(第 1 级)

<customSettingsType> 为必填项——关键

这是此技能中严重级别最高的一条规则。 省略 <customSettingsType> 不会产生“忘记填写 customSettingsType”错误。该组件会悄然不再是自定义设置,而是按普通自定义对象进行验证。

这种失败很危险,因为它会朝错误方向修复:Agent 省略该元素后,再照着平台报告的每个错误逐一修复,最终会得到部署成功,但组件类型完全错误的结果。

你看到的内容含义
Must specify a non-empty plural label for the CustomObject你并未在构建自定义设置。缺少 customSettingsType。请添加它——不要添加 pluralLabel。
Cannot specify: nameField for CustomSettings你确实在构建自定义设置。请移除指定的元素。

这两条字符串代表互斥的情况。第一条的关键在于短语 for the CustomObject,以及其中完全没有提及自定义设置。

如果部署在用户要求创建自定义设置的内容上报告 Must specify a non-empty plural label for the CustomObject,切勿通过添加 <pluralLabel> 来解决该错误。 添加该元素(以及 nameField、deploymentStatus 和 sharingModel)会使部署成功,但创建的是用户并未要求的普通自定义对象。

必需和允许的元素
元素要求说明
<customSettingsType>必需Hierarchy 或 List — 参见第 3 节
<label>必需单数形式的 UI 名称
<visibility>始终包含Public;仅在开发/沙盒/临时组织中可用 Protected(第 5 节)
<description>始终包含说明此设置控制什么,以及由谁编辑
<enableFeeds>可选接受
<listViews>可选接受 — 尽管禁止使用 recordTypes 和 compactLayouts,此元素仍允许使用
禁止的元素

以下每个元素都会导致 Cannot specify: <element> for CustomSettings:

禁止的元素说明
<pluralLabel>常规自定义对象必需,此处禁止。 正好相反。
<nameField>List 设置中隐式存在 Name 字段
<deploymentStatus>
<sharingModel>自定义设置不是共享记录
<enableActivities> <enableReports> <enableHistory> <enableSearch>
<validationRules>请改用 Apex 强制执行这些规则
<recordTypes>
<compactLayouts>

错误 — 包含常规自定义对象必需的元素:

<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
  <customSettingsType>Hierarchy</customSettingsType>
  <label>Feature Flags</label>
  <pluralLabel>Feature Flags</pluralLabel>        
  <sharingModel>ReadWrite</sharingModel>          
  <deploymentStatus>Deployed</deploymentStatus>   
  <nameField>                                    
    <label>Name</label>
    <type>Text</type>
  </nameField>
  <visibility>Public</visibility>
</CustomObject>

错误信息: Cannot specify: pluralLabel for CustomSettings · Cannot specify: sharingModel for CustomSettings · Cannot specify: deploymentStatus for CustomSettings · Cannot specify: nameField for CustomSettings

正确 — 最简有效的自定义设置:

<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
  <customSettingsType>Hierarchy</customSettingsType>
  <label>Feature Flags</label>
  <description>Per-profile and per-user toggles for beta features in the ordering app. Edited by admins in Setup.</description>
  <visibility>Public</visibility>
</CustomObject>

请注意,没有 <fullName>。根级别的 <fullName> 会被容忍并忽略,但应省略它 — API 名称取自目录和文件名。

部署 <customSettingsType>List</customSettingsType> 时,无需在 Setup 中启用“Manage List Custom Settings Type”开关。某些组织中存在此开关,因此,如果 List 设置在其他组织中因 customSettingsType 问题而被拒绝,请先检查 Schema Settings,再判断 XML 是否有误。


3. List 与 Hierarchy 的选择(第 2 层)

<customSettingsType> 只有两个可选值,而选择会改变行的寻址方式。

HierarchyList
适用场景值可按配置文件或用户变化,并具有组织范围的回退值设置是一个小型键值参考表,对所有人都相同
行键SetupOwnerId(Organization、Profile 或 User)Name
解析方式用户值 → 配置文件值 → 组织默认值按 Name 查找
Apex 读取MySetting__c.getInstance() / getOrgDefaults()MySetting__c.getValues('Key') / getAll()
典型场景功能开关、按配置文件设置的限制、调试开关国家代码、按地区设置的税率、按键值索引的集成端点

当用户描述的是开关、限制或任何“可以覆盖”的值时,默认选择 Hierarchy。如果用户描述的是包含命名行的查找表,则选择 List。

如果用户需要的是一个可在组织之间部署的键值参考表,List 自定义设置通常不是正确选择 — 其中的行属于数据,不会随部署迁移。请改用 platform-custom-metadata-type-generate(第 7 节)。


4. 字段规则

自定义设置中的字段是普通的 CustomField 组件,路径为 objects/<Name>__c/fields/<Field>__c.field-meta.xml。

此技能仅负责自定义设置特有的差异 — 即下文所列的支持类型允许列表和 fieldManageability 禁止规则。对于所有通用规则(<fullName> 的推导、<label>、<description>、<inlineHelpText>、精度/小数位数、<length>、externalId),请遵循 platform-custom-field-generate。

支持的字段类型

Checkbox、Currency、Date、DateTime、Email、Number、Percent、Phone、Text、TextArea、Url

自定义设置字段接受 required、unique、externalId 和 defaultValue。这些属性是否适用于特定类型,属于通用字段规则 — 请参阅 platform-custom-field-generate。

不支持的字段类型

Picklist、MultiselectPicklist、LongTextArea、Html、Lookup、MasterDetail、AutoNumber、 Location、Time、EncryptedText,以及 Formula(任何类型上的 <formula> 元素)。

这些类型都会失败,并返回同一条简短且没有说明的字符串:

Invalid data type.

此错误既没有指出字段,也没有指出类型。 部署多个字段时,请读取 --json 输出中的 componentFailures[].fullName 以找出问题字段——不要猜。

汇总字段在结构上无法实现——Summary 需要一个主从关系子项,而自定义设置本身又不支持 MasterDetail。不要生成汇总字段;错误文本不固定,因此不要根据特定字符串进行匹配。

Picklist 是常见陷阱。 用户经常要求在自定义设置中使用 picklist,但这不受支持。请使用 Text,并在 Apex 中强制执行允许的值;或者将请求转交给 platform-custom-metadata-type-generate——CMDT 确实支持 Picklist。

与 CMDT 几乎相反:Currency 在这里可用,但 CMDT 不支持;Picklist/LongTextArea 在 CMDT 中可用, 但这里不支持。切勿将一种类型的字段假设套用到另一种类型上。

<fieldManageability> 禁止使用

该元素仅属于 CMDT 字段。在自定义设置字段上使用会失败,并返回:

Field manageability cannot be set on this entity.

5. 可见性、机密信息与禁止静默降级规则

Protected 取决于组织类型

<visibility>Protected</visibility> 仅可部署到开发组织、沙盒组织或临时组织。在其他任何组织中:

You can't set the visibility for a Custom Setting to Protected unless you are in a developer, sandbox, or scratch org.
禁止静默降级规则 — 至关重要

如果因组织类型而导致 Protected 失败,绝不要通过切换到 Public 来“修复”。 静默降级会将有意做出的保密选择变成任何人都可读取的组件,且不提供任何提示。请明确说明:该组织不允许使用 Protected,因此可选方案是使用开发组织、沙盒组织或临时组织,或者接受 Public——由用户决定。此规则适用于任何收窄可见性的情况,而不仅是此错误。

机密信息不应存放在自定义设置中

自定义设置不是机密信息存储区。任何能够查询该对象的人都能读取其中的值,而对于同一命名空间中的代码,Protected 也不会改变这一点。

当用户要求将 API 密钥、密码、令牌、客户端密钥或证书存储在自定义设置中时:

  1. 首先明确警告——在生成任何内容之前——自定义设置不适合存放凭据,而且其中的值可被读取。
  2. 推荐合适的组件——用于调用身份验证的 Named Credential 和 External Credential。请明确说明此技能不会生成这些组件。
  3. 如果用户仍然坚持,就照办——生成自定义设置,但在回复中保留警告。不要默默拒绝,也不要不作说明地照办。

绝不要将机密信息转为 Protected 可见性来折中:如果 Protected 不可用(见上文),则必须严格遵守禁止静默降级规则,因为降级会公开机密信息。


6. 设置值是数据,而非元数据

自定义设置的行无法以 XML 部署。 它们没有类似 customMetadata/ 的文件夹。 只有对象定义及其字段属于元数据。

当用户要求创建带值的设置时——例如“添加一个供管理员启用 Beta 的功能标记设置”——请完成以下所有事项:

  1. 像往常一样生成对象和字段 XML。
  2. 用一行说明限制: 设置值属于数据,而非元数据,因此不会随部署发布。
  3. 在聊天回复中直接提供可立即运行的命令,完整替换为实际的对象和字段 API 名称及实际值——不是占位符模板,也不要写入文件。

以下三种形式均已验证可正常运行。

层级 — 组织范围的默认行

省略 SetupOwnerId。 它默认采用 Organization Id,正好对应组织默认行。无需查询 Id。

sf data create record --sobject Feature_Flags__c \
  --values "Enable_Beta__c=true Max_Retries__c=3" \
  --target-org <alias>
层级 — 配置文件或用户覆盖

这一步需要 Id,因此分为两步。用户级覆盖使用相同的结构,但用 User Id 代替 Profile Id(根据配置文件的情况推断,尚未单独验证)。

sf data query --query "SELECT Id FROM Profile WHERE Name='System Administrator'" --target-org <alias>

sf data create record --sobject Feature_Flags__c \
  --values "SetupOwnerId=00eXXXXXXXXXXXXXXX Enable_Beta__c=false" \
  --target-org <alias>

覆盖行与组织默认行共存,不会取代它。

列表 — 每个键对应一行

Name 是行键,且为必填项。

sf data create record --sobject Country_Codes__c \
  --values "Name='US' Iso_Code__c='USA' Dial_Prefix__c='+1'" \
  --target-org <alias>
引号

将整个 --values 参数用双引号括起来;包含空格或 shell 特殊字符的值要用单引号括起来 (Environment_Label__c='org default')。普通数字、布尔值和 Id 无需加内层引号。

在 Apex 中使用设置

通过生成的类型化类读取值——值会被缓存,因此读取不消耗 SOQL,在循环和触发器中使用也安全。对于层级设置:

Feature_Flags__c cfg = Feature_Flags__c.getInstance();        // running user: user → profile → org default
Feature_Flags__c org = Feature_Flags__c.getOrgDefaults();     // org-default row only, no hierarchy
Feature_Flags__c forProfile = Feature_Flags__c.getInstance(profileId);  // a User Id works too
Boolean beta = cfg.Enable_Beta__c;

getInstance() 和 getOrgDefaults() 永远不会返回 null(API ≥ 22)——记录缺失时会返回空行,因此如果需要确认记录是否实际存在,请检查 org.Id != null。对于列表设置,使用 getValues('Key') 获取一行,或使用 getAll() 获取包含所有行的 Map<String, Feature_Flags__c>。

事务内 DML 规则

填充或更改值属于运行时 DML(Apex insert/update/upsert,或上述 sf 命令)——没有元数据路径。这正是“值属于数据”在操作层面的体现,并有两个值得向用户说明的后果:

  • 写入会计入 DML 管理限制;读取不会。 对包含 200 条记录的触发器,切勿每条记录都 upsert 一次设置——将写入移出循环,只执行一次。
  • 跨事务传播存在延迟。 写入后,在组织缓存传播期间,其他事务可能会短暂读取到旧值;在同一事务内,新值会立即可见。

7. 选择合适的组件

开始生成前,请确认自定义设置确实符合用户需求。如果不符合,请说明原因并指出合适的技能,而不是构建错误的组件。

如果配置是……使用原因
可由管理员按配置文件/用户编辑,或仅在一个组织中使用的小型键值表自定义设置(此技能)值属于数据;部署时不会随之迁移
必须连同记录一起部署到不同组织的参考数据platform-custom-metadata-type-generateCMDT 记录属于元数据,可以部署
用户在运行时创建和编辑的业务记录platform-custom-object-generate自定义设置用于配置,不是事务数据
可翻译的 UI 文本Custom Label — 此技能不会生成它标签是受支持的翻译方式
凭据、API 密钥、令牌、带身份验证的端点Named Credential / External Credential — 此技能不会生成它们参见第 5 节
Apex 或流程中的权限检查Custom Permission — 此技能不会生成它布尔访问检查应由权限模型处理

最重要的区别:CMDT 记录可以部署,自定义设置值不能。 如果用户说“而且它应该随这些值一起发布”或“在每个组织中都相同”,这就是 CMDT 需求。


8. 常见部署错误

错误消息原因修复方法
Must specify a non-empty plural label for the CustomObject缺少 <customSettingsType>,因此系统会将其作为普通自定义对象进行验证添加 <customSettingsType>。不要添加 <pluralLabel>(第 2 节)
Cannot specify: pluralLabel for CustomSettings存在 <pluralLabel>删除它——自定义对象必须包含此项,但此处禁止使用
Cannot specify: <element> for CustomSettings(<element> = nameField、sharingModel、deploymentStatus、validationRules、recordTypes 或 compactLayouts)存在仅适用于自定义对象的元素删除它(改为在 Apex 中实施验证逻辑)
Invalid data type.不支持此字段类型(第 4 节)查看 componentFailures[].fullName 找出字段;改用受支持的类型
Field manageability cannot be set on this entity.设置字段上存在 <fieldManageability>删除它——仅适用于 CMDT
You can't set the visibility for a Custom Setting to Protected unless you are in a developer, sandbox, or scratch org.在类似生产环境的组织中使用了 Protected告知用户;绝不能静默改为 Public(第 5 节)

Cannot specify: 后面的后缀是 for CustomSettings(一个单词),而 CMDT 的后缀是 for Custom Metadata Type;可见性错误使用的是 for a Custom Setting(带空格,单数)。匹配这些字符串时,不要假设它们共用同一个模板。


9. 验证清单

生成自定义设置 XML 之前,请验证以下各项:

组件身份检查(关键)
  • 是否存在 <customSettingsType>,且其值为 Hierarchy 或 List?
  • 是否根据请求说明了选择 Hierarchy 还是 List(可覆盖的设置还是键控表)?
  • 如果部署报告了 Must specify a non-empty plural label for the CustomObject,是否通过添加 <customSettingsType> 修复,而非添加 <pluralLabel>?
  • 成功部署新的设置后,是否确认它确实是自定义设置?检查 XML 无法发现此问题,因为错误组件仍会显示绿色部署成功。运行 sf sobject describe --sobject <Name>__c --target-org <alias>,并确认 customSetting 为 true。
语法检查
  • 是否存在 <label> 和 <visibility>?
  • 是否存在 <description>,并具体说明该设置控制什么?
  • 是否不存在 <pluralLabel>?
  • 是否不存在 <nameField>、<sharingModel> 和 <deploymentStatus>?
  • 是否不存在 <enableActivities>、<enableReports>、<enableHistory> 和 <enableSearch>?
  • 是否不存在 <validationRules>、<recordTypes> 和 <compactLayouts>?
  • 文件名是否与预期的 API 名称一致,并以 __c 结尾?
字段检查
  • 每个字段类型是否都在受支持的列表中(第 4 节)?
  • 是否不存在 Picklist?(不受支持——请使用 Text,或改用 CMDT)
  • 是否不存在任何 <formula> 元素?(不支持公式)
  • 每个字段上是否都不存在 <fieldManageability>?
  • 通用字段属性是否遵循 platform-custom-field-generate?
值检查
  • 如果用户要求提供值,是否明确说明了数据不属于元数据的限制?
  • 是否在回复中直接给出 sf 命令,并将其完整替换为真实 API 名称和真实值——而不是写入文件或保留为模板?
  • 对于 Hierarchy 组织默认值,是否省略 SetupOwnerId,而不是猜测其值?
  • 对于 List 行,是否提供了 Name?
使用检查
  • 如果用户询问如何读取设置,是否提供了使用生成的访问器的 Apex 代码片段(Hierarchy 使用 getInstance / getOrgDefaults,List 使用 getValues / getAll)?
  • 是否说明了事务内 DML 规则——写入属于会计入限制的 DML(应批量处理,并移出循环),读取不受限制,而跨事务的缓存传播会有延迟?
安全检查(关键)
  • 如果请求涉及机密、密钥、令牌或密码,是否在生成之前发出了警告,并建议使用 Named Credential?
  • 如果因组织类型错误,是否保留了 Protected,而不是悄悄降级为 Public?
组件选择检查
  • 如果这些值必须在组织之间部署,是否改为推荐 platform-custom-metadata-type-generate?
  • 如果请求实际涉及业务记录,是否改为推荐 platform-custom-object-generate?

评论

支持 Markdown