mcpField
P
platform-custom-metadata-type-generate

platform-custom-metadata-type-generate

github.com/forcedotcom開発1.1k1.4k 回インストール1 日前に更新
リポジトリ

platform-custom-metadata-type-generate について

Salesforce の Custom Metadata Type、フィールド、レコードを生成・検証するスキルです。組織間でデプロイする設定を扱う開発者向けで、メタデータリレーションや `.md-meta.xml` レコードにも対応します。

主な機能

  1. 01CMDT の型定義とフィールド生成
  2. 02対応フィールド型とリレーションの検証
  3. 03デプロイ可能な CMDT レコードファイル作成
  4. 04フィールド型に応じたレコード値の形式化
  5. 05デプロイ制約とエラーの診断

活用シーン

  1. 01パッケージに含める設定の作成
  2. 02CSV や一覧からの CMDT レコード生成
  3. 03メタデータリレーションやデプロイ問題の調査

インストール

コマンドをコピーしてターミナルで実行します。

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

インストール後、Claude Code で/platform-custom-metadata-type-generateを入力して読み込まれたか確認します。

同梱ファイルreferences/cmdt-records.mdscripts/sanitize-developer-name.sh

詳細

Salesforce カスタムメタデータ型の生成と検証

このスキルを使う場面

次の作業が必要な場合に、このスキルを使います。

  • カスタムメタデータ型(__mdt)を作成する
  • MetadataRelationship フィールドを含む CMDT フィールドを生成または検証する
  • デプロイ可能な .md-meta.xml ファイルとして CMDT レコードを生成する
  • CMDT のデプロイエラーをトラブルシューティングする

このスキルの範囲を超える Metadata API の型、フィールド、列挙値については、正確な情報を得るために platform-metadata-api-context-get スキルを使ってください。

1. 概要と目的

カスタムメタデータ型は2種類のアーティファクト群を生成するため、ほとんどのリクエストでは両方が必要です。

アーティファクトパスメタデータ型
型定義objects/<Name>__mdt/<Name>__mdt.object-meta.xmlCustomObject
フィールドobjects/<Name>__mdt/fields/<Field>__c.field-meta.xmlCustomField
レコードcustomMetadata/<Name>.<Record>.md-meta.xmlCustomMetadata

API 名の接尾辞: 型には __mdt、フィールドには引き続き __c を付けます。

カスタム設定に対する決定的な利点:CMDT レコードはメタデータであるため、組織間でデプロイできます。 ユーザーが、設定を「パッケージに含める」または「すべての組織で同じにする」必要があると言った場合、適切な選択肢は CMDT です。

ルート要素は <CustomObject> ですが、カスタムオブジェクトのルールはほとんど適用されません。 通常のカスタムオブジェクトでは必須または一般的な sharingModel、nameField、deploymentStatus は、ここでは重大なエラーになります。platform-custom-object-generate の前提をそのまま持ち込まないでください。


2. 構文の基本 — 型定義(ティア 1)

必須および使用可能な要素
要素要件備考
<label>必須UI に表示する単数形の名前
<pluralLabel>必須省略すると Must specify a non-empty plural label for the CustomObject が返されます
<visibility>常に含めるPublic、または開発/サンドボックス/スクラッチ環境のみで Protected/PackageProtected(セクション 6)
<description>常に含めるこの型が設定する内容と、その所有者

<pluralLabel> はここでは必須ですが、カスタム設定では使用できません。この違いは、2つの系列で最もよく混同されるルールです。どちらのエラーも、もう一方の系列のルールには触れません。

使用禁止の要素

以下の各要素を指定すると Cannot specify: <element> for Custom Metadata Type が発生します。通常のカスタムオブジェクトのひな形を再利用し、sharingModel、deploymentStatus、nameField ブロック、または enableSearch を含めることが、よくある原因です。

sharingModel、nameField、deploymentStatus、enableActivities、enableReports、enableHistory、enableSearch

正しい例 — 最小限の有効な __mdt 型:

<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
  <label>Partner Tier</label>
  <pluralLabel>Partner Tiers</pluralLabel>
  <description>Discount and threshold configuration per partner tier. Ships with the package; edited by the revenue ops team.</description>
  <visibility>Public</visibility>
</CustomObject>

3. フィールドのルール

このスキルが扱うのは CMDT 固有の差分のみです。以下の型の許可リスト、fieldManageability、MetadataRelationship が対象です。一般的なフィールドの仕組み(<fullName> の導出、<label>、<description>、<inlineHelpText>、精度/小数点以下の桁数、<length>、visibleLines)については、platform-custom-field-generate に従ってください。

サポートされているフィールド型

Checkbox、Date、DateTime、Email、Number、Percent、Phone、Picklist、Text、TextArea、LongTextArea、Url、および MetadataRelationship

サポートされていないフィールド型

Currency、AutoNumber、MasterDetail、Summary、Location、Time、EncryptedText、Html、MultiselectPicklist。いずれも、正確で形式の整ったエラーを返します。

Type {TypeName} of CustomMetadataField {Object}__mdt.{Field}__c is not supported for the Entity {Object}__mdt

(末尾にピリオドはありません。)例:Type Currency of CustomMetadataField Partner_Tier__mdt.Discount__c is not supported for the Entity Partner_Tier__mdt

よくある落とし穴は Currency です。 カスタム設定では使用できますが、ここでは使えません。<precision>/<scale> を指定した Number を使用し、通貨はラベルまたはヘルプテキストに記載してください。

数式フィールドはサポートされていませんが、上記のパターンとは異なるエラーになります。それ以外は有効な型に <formula> 要素を指定すると、次のエラーのみが返されます。

Invalid data type.
Lookup はサイレントに強制変換されます — 重大

__mdt の <type>Lookup</type> は、referenceTo が実在する sObject に解決されてもエラーになりません。デプロイは成功し、プラットフォームがフィールドをサイレントに MetadataRelationship に書き換えます。その後に取得すると、ユーザーが一度も記述していないフィールドが表示されます。

<type>MetadataRelationship</type>   

必ず MetadataRelationship を明示的に記述してください。 Lookup を出力すると、デプロイは成功する一方、ソースと組織の不一致が生じ、誰かが初めて取得したときに Git の差分が増え続けます。(稼働中のデプロイで再現済み:解決可能な Lookup は MetadataRelationship として返され、解決できない referenceTo は問題なく拒否されます。)

MetadataRelationship

有効なターゲットは 3 種類です。どれを使うかは referenceTo で指定します。

<referenceTo>用途追加要件
別の __mdt 型2 つのカスタムメタデータ型をリンクします異なる型である必要があります
EntityDefinitionsObject を参照しますなし
FieldDefinitionフィールドを参照します<metadataRelationshipControllingField> が必要です
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
  <fullName>Target_Field__c</fullName>
  <label>Target Field</label>
  <type>MetadataRelationship</type>
  <referenceTo>FieldDefinition</referenceTo>
  <metadataRelationshipControllingField>Partner_Tier__mdt.Target_Object__c</metadataRelationshipControllingField>
  <relationshipLabel>Target Field</relationshipLabel>
  <relationshipName>Target_Field</relationshipName>
</CustomField>

制御フィールドは、同じ型に属する EntityDefinition リレーションシップである必要があり、Type__mdt.Field__c の形式で参照します。これを省略すると、Metadata relationships to Field Definition require a controlling field. が表示されます。

自己参照はできません。 MetadataRelationship の参照先を自分自身の親型にすると、Cannot add a self-lookup relationship child with cascade or restrict options to the object itself というエラーが発生します(稼働中の __mdt デプロイからの原文)。2 つ目の型を使用してください。

<fieldManageability>

省略可能です。デフォルトは DeveloperControlled です。ユーザーが別の値を希望しない限り、追加しないでください。有効な値は DeveloperControlled、SubscriberControlled、Locked です。

これは __mdt フィールドでのみ有効です。通常のカスタムオブジェクトフィールドまたはカスタム設定フィールドでは、次のようになります。

Field manageability cannot be set on this entity.

4. CMDT レコード(.md-meta.xml)

ファイル名の規則

customMetadata/<TypeNameWithout__mdt>.<RecordDeveloperName>.md-meta.xml として記述してください。

customMetadata/Partner_Tier.Bronze_AMER.md-meta.xml

ファイル名に __mdt のサフィックスを付けてもデプロイされ、実際のレコードが作成されるため許容されます。ただし、Salesforce の取得処理ではサフィックスなしの形式に正規化されるため、Git の差分が増えるのを避けるには、必ず __mdt を付けずに記述してください(詳細は references/cmdt-records.md を参照)。

必須の名前空間

ルート要素では 3 つすべてが必須です。値に xsi:type を指定しても、これらがなければ解決されません。

<CustomMetadata xmlns="http://soap.sforce.com/2006/04/metadata"
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
xsi:type の対応表 — すべての値に指定が必要です
フィールド型正しい xsi:type値の例
チェックボックスxsd:booleantrue
日付xsd:date2024-01-15
日時xsd:dateTime2024-01-15T10:30:00.000Z
数値、パーセントxsd:double42.0
テキスト、テキストエリア、長文テキストエリアxsd:stringsome text
メール、電話、URLxsd:string[email protected]
選択リストxsd:stringBeta
MetadataRelationship → EntityDefinitionxsd:stringAccount
MetadataRelationship → FieldDefinitionxsd:stringAccount.Name
任意の型、nullxsi:type なし — <value xsi:nil="true"/> と記述

MetadataRelationship を介して別の __mdt 型を参照する値は検証されていません。ターゲットの DeveloperName を xsd:string で指定すると想定されますが、確認してください。

xsd:picklist を出力してはいけません — 重大

Salesforce の公式ドキュメントでは、選択リストフィールドに xsd:picklist を使うよう指示されていますが、これは誤りです。有効な XML Schema 型ではありません。プラットフォームは明確な検証エラーを返す代わりに、サーバー側でデプロイ全体を失敗させ、コンポーネント単位の診断情報も表示しません。その結果、ほかのすべてのコンポーネントも巻き添えになります。選択リストフィールドの値には必ず xsd:string を出力し、xsd:picklist は決して使用しないでください。 references/cmdt-records.md §2 を参照してください。

レコード本体のルール
  • <label> は必須です。省略すると Required fields are missing: [MasterLabel] が返されます。報告されるのは label ではなく、sObject のフィールド名 MasterLabel です。
  • <protected> は省略可能で、デフォルトは false です。
  • <values> ブロック内に <fullName> を入れないでください。パースエラーになります。
  • <value xsi:nil="true"/> は省略可能なフィールドでは機能します。必須フィールドでは、フィールドが存在しない場合と同様に拒否されます。nil でない値で xsi:type を省略すると、テキストフィールドを含め、必ず致命的なエラーになります。

正しい例 — 完全なレコード:

<?xml version="1.0" encoding="UTF-8"?>
<CustomMetadata xmlns="http://soap.sforce.com/2006/04/metadata"
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <label>Bronze AMER</label>
  <protected>false</protected>
  <values>
    <field>Discount_Percent__c</field>
    <value xsi:type="xsd:double">5.0</value>
  </values>
  <values>
    <field>Region__c</field>
    <value xsi:type="xsd:string">AMER</value>
  </values>
  <values>
    <field>Effective_Date__c</field>
    <value xsi:type="xsd:date">2024-01-15</value>
  </values>
  <values>
    <field>Notes__c</field>
    <value xsi:nil="true"/>
  </values>
</CustomMetadata>
レコードの DeveloperName ルール

名前はファイル名の2番目のセグメントです。英字で始まり、英数字とアンダースコアのみを含み、アンダースコアで終わらず、連続するアンダースコアを含まず、最大40文字である必要があります。違反すると、次のエラーが返されます。

Custom Metadata Record Name: The <Type>__mdt API Name can only contain underscores and alphanumeric characters. It must be unique, begin with a letter, not include spaces, not end with an underscore, and not contain two consecutive underscores.

40文字を超えると Value too long for field: fullName maximum length is:40 が返されます(コロンの後にスペースはありません)。

デプロイ順序

順序の制約はありません — 型と参照されるすべてのフィールドは、解決できればよいだけです(組織にすでに存在するか、同じデプロイに含まれていること)。不足しているものは、次の2種類のエラーで確認できます。 Custom metadata type <Type>__mdt is not available in this organization.(型が存在しない場合)および <Type>__mdt: could not find fields: <Field>__c(型は存在するが、フィールドが存在しない場合)。

→ レコード値のエラー一覧と xsi:type の型強制における非対称性:references/cmdt-records.md。

ユーザー入力からのレコード生成

レコードデータは3つの方法で渡されます。いずれの場合も、各行につき <Type>.<Record>.md-meta.xml を1つ出力し、列を適切な xsi:type を持つ <field>/<value> の組に対応付けます。

  • インラインのリスト/テーブル — 列をそのままフィールドに対応付けます。
  • CSV — ヘッダーにはフィールドの API 名を指定します(またはラベルを API 名に対応付けます)。各行が1つのレコードで、キー列から DeveloperName を取得します。
  • 文章 — 行を推測し(「Bronze は5%、Gold は15%」など)、生成前にフィールドの対応付けを確認します。

キー列またはラベルから、各 DeveloperName を決定論的に導出してください。手作業で作成してはいけません。各行について、レコードファイルを書き込む前に scripts/sanitize-developer-name.sh "<LABEL>" <ROW> を実行します(同じ入力からは同じ有効な名前が得られます。空のラベル、記号のみのラベル、非ラテン文字のラベルには Record_<ROW> が割り当てられます)。

変換は多対一です。United States と United-States はどちらも United_States になり、各レコードは <Type>.<DeveloperName>.md-meta.xml であるため、衝突すると行が警告なく上書きされます。バッチ全体の名前を導出した後、書き込む前に重複を確認してください。衝突があれば処理を停止し、衝突した元のラベルを報告します(ユーザーが自動解決を求めた場合に限り、決定論的な _2/_3 のサフィックスを追加します)。 順序付きのアルゴリズム、ASCII のみという制限、一意性チェック、具体例:references/cmdt-records.md §7。

Apex でのレコードの使用

レコードは生成された型付きクラスを介して読み取られます。SOQL は不要で、クエリ行も消費しないため、ループやトリガー内でも安全です。

Map<String, Partner_Tier__mdt> all = Partner_Tier__mdt.getAll();
Partner_Tier__mdt bronze = Partner_Tier__mdt.getInstance('Bronze_AMER');  // by DeveloperName

アクセサーによる切り詰め — LongTextArea では重要です。 getAll()/getInstance() は、あらゆるフィールドの先頭255文字のみを返します。これらの呼び出しでは、255文字を超える LongTextArea の値が警告なく切り詰められるため、SOQL(SELECT ... FROM Partner_Tier__mdt)で読み取る必要があります。CMDT に LongTextArea を指定する場合は、必ずこの点を伝えてください。


5. 適切なコンポーネントの選択

生成する前に、ユーザーが必要としているものが CMDT であることを確認してください。

設定が…使用するもの理由
レコードとともに組織間でデプロイする必要がある参照データCMDT(このスキル)レコードはメタデータです
管理者が保守するマッピング/参照/対応表(項目↔項目、コード↔コード、「A を B に対応付ける」)CMDT(このスキル)編集可能な参照データで、ペアごとに 1 レコードです
プロファイル/ユーザーごとに編集可能、または組織ローカルである値platform-custom-setting-generate値はデータであり、1 つの組織内にとどまります
ユーザーが実行時に作成・編集する業務レコードplatform-custom-object-generateCMDT レコードはトランザクションデータではありません
翻訳可能な UI テキストカスタム表示ラベル — ここでは生成しません表示ラベルが翻訳対象です
認証情報、API キー、トークン名前付き認証情報/外部認証情報 — ここでは生成しませんセクション 6 を参照してください
Apex またはフローでの権限チェックカスタム権限 — ここでは生成しませんブール値のアクセス権は権限モデルで管理します

最も重要な違いは、CMDT レコードはデプロイされますが、カスタム設定の値はデプロイされないことです。ユーザーが実行時に管理者によるプロファイルごとの値の編集を必要としている場合、それは CMDT ではなくカスタム設定です。

項目マッピングテーブルや参照テーブルは、代表的な CMDT の用途です。 ユーザーが「A から B に項目をマッピングする」、コード間の参照を管理する、または管理者が編集できる対応表を保持すると依頼した場合は、CMDT としてモデル化してください。ペアごとに 1 レコードにします(例:Lead_Field__c/Target_Field__c、または MetadataRelationship 項目と FieldDefinition の組み合わせ)。ハードコードした Apex の Map、定数、またはフローの判断ロジックにしてはいけません。「変換用」や「連携用」という表現でも、コードになるわけではありません。管理者がデプロイなしでペアを保守するのであれば、それは CMDT の参照データです。


6. 可視性、シークレット、そしてサイレントなダウングレードの禁止

Protected と PackageProtected は組織の種類に依存します

どちらも開発者組織、Sandbox、またはスクラッチ組織にのみデプロイできます。それ以外では次のようになります。

You can't set the visibility for a Custom Metadata Type to Protected unless you are in a developer, sandbox, or scratch org.

PackageProtected でも、Protected が PackageProtected に置き換わった同じメッセージが表示されます。このエラーは本番環境に近い組織で確認されています。これらの値が開発者組織、Sandbox、またはスクラッチ組織で成功するという情報は、別途テストした結果ではなく、メッセージ本文に基づいています。

サイレントなダウングレードの禁止 — 重大

組織の種類が原因で Protected に失敗した場合、Public に切り替えて「修正」してはいけません。 処理を停止し、ユーザーに伝えてください。サイレントなダウングレードでは、意図的な機密性の選択が、警告もなく正常にデプロイされた全世界から閲覧可能なコンポーネントに変わってしまいます。何も変わったことを知らせるものがないため、これは最悪の結果です。

代わりに状況を報告してください。組織では Protected が許可されないため、開発者組織/Sandbox/スクラッチ組織にデプロイするか、Public を受け入れるかが選択肢です。選ぶのはユーザーです。

このルールは、このエラーに限らず、可視性を狭めるあらゆるケースに適用されます。

シークレットを CMDT に保存してはいけません

CMDT はシークレットストアではありません。Protected は名前空間の外部からのアクセスを制限しますが、暗号化ではなく、名前空間内のコードや管理者から値を保護するものでもありません。

ユーザーが CMDT に API キー、パスワード、トークン、クライアントシークレット、または証明書を保存しようとした場合:

  1. 最初に、はっきりと警告してください。何かを生成する前に、CMDT は認証情報を保存する場所として適切ではなく、Protected も暗号化ではないことを伝えてください。
  2. 適切なコンポーネントを推奨してください。名前付き認証情報と外部認証情報を使用してください。このスキルではそれらを生成しないことも明確に伝えてください。
  3. ユーザーがそれでも希望する場合は、依頼に従ってください。組織で許可される場合は Protected の可視性で CMDT を生成し、回答にも警告を残してください。黙って拒否したり、黙って従ったりしてはいけません。

2 つのルールは組み合わせて適用され、順序が重要です。 ユーザーがシークレットを CMDT に保存することを強く希望し、かつ組織が Protected を拒否した場合、サイレントなダウングレードの禁止ルールによって、キーが Public コンポーネントに保存されるのを防ぎます。処理を停止して報告してください。シークレットを含む型を Public にダウングレードしてはいけません。


7. デプロイエラーのリファレンス

型レベルおよびフィールドレベルのエラー文字列は、該当するエラーの原因となる誤りの横に、セクション 2~4 でインラインに記載されています(Cannot specify: <element> for Custom Metadata Type、未対応の型を示す文字列、数式に対する Invalid data type.、Field manageability cannot be set on this entity.、MetadataRelationship の制御フィールドおよび自己参照エラー、ならびに Must specify a non-empty plural label のケース)。

レコード値の完全な逐語カタログ(xsi:type の誤りによるすべての拒否、Required fields are missing: [MasterLabel]、必須項目の nil、DeveloperName のルール、正確な文字列に関する注意点(API 名ではなく Label で指定されたフィールド名、xsi:type なしのエラーに含まれる二重スペースと i.g. の誤記、スペースなしの maximum length is:40))は、references/cmdt-records.md にあります。

一致させる際の注意点が 1 つあります。ここでの接尾辞は for Custom Metadata Type(スペースあり、タイトルケース)です。カスタム設定では for CustomSettings を使います。これらの文字列が共通のテンプレートに従うと想定しないでください。


8. 検証チェックリスト

型定義のチェック
  • <label>、<pluralLabel>、<visibility> がすべて含まれていますか?
  • <description> が含まれており、具体的な内容になっていますか?
  • <sharingModel>、<nameField>、<deploymentStatus> は含まれていませんか?
  • <enableActivities>、<enableReports>、<enableHistory>、<enableSearch> は含まれていませんか?
  • ディレクトリ名とファイル名の末尾が __mdt になっていますか?
フィールドのチェック
  • すべてのフィールド型がサポート対象の一覧(セクション 3)に含まれていますか?
  • Currency は含まれていませんか?(ここでは未対応です。代わりに Number を使用してください)
  • すべての <formula> 要素が含まれていませんか?
  • <type>Lookup</type> は含まれておらず、代わりに MetadataRelationship と記述されていますか? 重大 — Lookup はエラーなしでデプロイされ、書き換えられます
  • FieldDefinition のリレーションシップに <metadataRelationshipControllingField> が含まれていますか?
  • MetadataRelationship が自身の親型を参照していませんか?
  • デフォルト以外の値が要求されていない限り、<fieldManageability> は省略されていますか?
レコードのチェック 重大
  • ファイル名は __mdt を付けずに <Type>.<Record>.md-meta.xml となっていますか?
  • ルート要素に 3 つすべての名前空間(xmlns、xmlns:xsd、xmlns:xsi)がありますか?
  • nil 以外の <value> にはすべて xsi:type が指定されていますか?
  • xsi:type="xsd:picklist" はどこにも含まれていませんか?(デプロイ全体がクラッシュします。代わりに xsd:string を使用してください)
  • 各 xsi:type は、セクション 4 の表に従ってフィールド型と一致していますか?
  • すべてのレコードに <label> が含まれていますか?
  • すべての <values> ブロックから <fullName> が除かれていますか?
  • 必須フィールドにはすべて、xsi:nil="true" ではなく実際の値が指定されていますか?
  • すべてのレコードの DeveloperName は 40 文字以下で、英字で始まり、スペースやハイフンを含んでいませんか?
  • レコードがバッチ、リスト、CSV から作成された場合、派生した DeveloperName がすべて重複していないことを(sort | uniq -d で)確認し、行を黙って上書きせず、重複があれば報告していますか? 重大 — 重複があると、デプロイエラーなしでレコードが失われます
  • 各 <field> には、その型に存在するフィールド、または今回のデプロイに含まれるフィールドが指定されていますか?
  • レコードがリスト、CSV、または文章による説明から作成された場合、各行につきファイルが 1 つだけあり、列が正しいフィールドに対応付けられていますか?
利用時のチェック
  • ユーザーがレコードの読み取り方法を尋ねた場合、getAll() / getInstance(developerName) を使用する Apex スニペットを提示しましたか?
  • いずれかのレコードが LongTextArea に値を設定している場合、アクセサーは 255 文字で切り詰めるため、値全体を取得するには SOQL が必要であることをユーザーに伝えましたか?
セキュリティのチェック 重大
  • リクエストにシークレット、キー、トークン、またはパスワードが含まれる場合、生成前に警告し、Named Credential を推奨しましたか?
  • 組織タイプの不一致があっても、Protected をそのまま維持し、黙って Public に変更していませんか?
コンポーネント選択の確認項目
  • 実行時に管理者がプロファイルやユーザーごとに値を編集する必要がある場合、代わりに platform-custom-setting-generate が推奨されていますか?
  • データが実際にはトランザクション型のビジネスレコードである場合、代わりに platform-custom-object-generate が推奨されていますか?

リファレンスファイル一覧

ファイル読むタイミング
references/cmdt-records.mdCMDT レコードのデプロイに関するデバッグ — レコード値のエラーを網羅した完全なカタログ、型強制の非対称性(プラットフォームが暗黙的に受け入れる xsi:type の不一致)、レコードの具体例

コメント